Автоматическая панорамная головка

BossTon
Offline
Зарегистрирован: 30.03.2013

Друзья здравствуйте!

Давно хотел собрать подвес для фотоаппарата для авто-съемки панорам

Механику всю собрал, там все просто. фотик небольшой 400гр, так что всего

2 сервомашинки постоянного вращения без редукторов вращают фото в 2 плоскостях.

Я сначала хотел делать все на шаговых двигателях, но не нашел нормальных , пришлось заказывать 2 сервы SM-S4315r постоянного вращения. (Меня подкупил высокий момент до 15 кгс)Лишь когда они приехали, я понял что лоханулся, что такие сервы нельзя позиционировать в пространстве.

Пришлось покупать 2 потенциометра и начинать изучать программирование на ардуино.

Пытаюсь делать сам, принципы понимаю но спотыкаюсь на мелочах.

и так проблема №1:

Мне нужно чтобы серва1 крутила подвес и останавливалась каждые 45 градусов(всего 9 раз) после каждой остановки происходил бы спуск затвора, ну это позже и отдельная тема.

Я поковырялся и написал скетч который просто ставил серву в определенный угол, дабы проверить потенциометр.

#include <Servo.h>

Servo servo1;

int servopin1=10;

int potensiometr = A9;

int val;

void setup()

{

servo1.attach(servopin1);

}

void loop(){

  val = analogRead(potensiometr);

int pos = map(val,0,1023,0,200);

if(pos<30)

{

  servo1.write(80); //гоним серву вперед до заданного положения

}

else if(pos>30)

{

  servo1.write(100); //гоним серву назад до заданного положения

}

else{

  servo1.write(90); //иначе останавливаемся, т.е то что нужно.

  delay(1000);

}

}

}

И он даже работает, что вызывает у меня дикую радость, так как это первый мой скетч и он заработал, но дальше я начал спотыкаться. Я понимаю что нужно запускать FOR. но как я не пытался исхитриться у меня ничего не получается. серва начинает дергаться или просто тупо кружиться. Помогите, пожалуйста, если кто может))) Если кому интересно выложу фото подвеса. а если соберу доконца, то опишу в проектах. механика собрана на 80%. Прилагаю последний код на котором я встал. [CODE]

#include <Servo.h> Servo servo1; 
int servopin1=10; 
int potensiometr = A9;
int val; 

void setup() 
{ 
servo1.attach(servopin1); 
} 

void loop()
{ 
val = analogRead(potensiometr); 
int pos = map(val,0,1023,0,200); 
for(int i=1;i<=101;i=i+20) 
{ 
if(pos<i) 
{ servo1.write(80); } 
else if(pos>i) 
{ servo1.write(100); } 
else
{ servo1.write(90); delay(1000); 
} } }

 

BossTon
Offline
Зарегистрирован: 30.03.2013

Криво вставился код, не знаю как исправить(((( дублирую в правильном виде то, что у меня не получилось.

#include <Servo.h>
Servo servo1;
int servopin1=10;
int potensiometr = A9;
int val;
void setup()
{
servo1.attach(servopin1);

}
void loop(){
  val = analogRead(potensiometr);
int pos = map(val,0,1023,0,200);
for(int i=1;i<=101;i=i+20)
{
if(pos<i)
{
  servo1.write(80);
}
else if(pos>i)
{
  servo1.write(100);
}
else{
  servo1.write(90);
  delay(1000);
}
}
}

 

maksim
Offline
Зарегистрирован: 12.02.2012

Так как не известно какая конкретно зависимость направлений вращений потенциометра и сервы ,то попробуйте раскомментировать строку 21, закомментировав строку 22.

#include <Servo.h>

#define servopin1 10
#define pot A9

Servo servo1;

int poss[] = {23, 273, 523, 723, 1023}; // заданные положения

void setup()
{
  servo1.attach(servopin1);
}

void loop()
{
  static byte i;
  int pos = analogRead(pot);
  if(pos < poss[i]-3 || pos > poss[i]+3)
  {
    //pos = map(pos, 0, poss[i], 0, 90);
    pos = map(pos, 0, poss[i], 180, 90);
    pos = consnrain(pos, 0, 180);
    servo1.write(pos);
  }
  else
  {
    delay(2000);
    i++;
    if(i == 5) i = 0;
  }
  delay(10);
}

Выше реалазовано всего лишь пропорциональное регулирование, а значит будет статическая ошибка.

BossTon
Offline
Зарегистрирован: 30.03.2013

maksim пишет:

Так как не известно какая конкретно зависимость направлений вращений потенциометра и сервы ,то попробуйте раскомментировать строку 21, закомментировав строку 22.

#include <Servo.h>

#define servopin1 10
#define pot A9

Servo servo1;

int poss[] = {23, 273, 523, 723, 1023}; // заданные положения

void setup()
{
  servo1.attach(servopin1);
}

void loop()
{
  static byte i;
  int pos = analogRead(pot);
  if(pos < poss[i]-3 || pos > poss[i]+3)
  {
    //pos = map(pos, 0, poss[i], 0, 90);
    pos = map(pos, 0, poss[i], 180, 90);
    pos = consnrain(pos, 0, 180);
    servo1.write(pos);
  }
  else
  {
    delay(2000);
    i++;
    if(i == 5) i = 0;
  }
  delay(10);
}

Выше реалазовано всего лишь пропорциональное регулирование, а значит будет статическая ошибка.

Спасибо, пытаюсь разобраться в написаном.

А что делает эта строка строка, непойму? 

 

 pos = consnrain(pos, 0, 180);

consnrain это команда какая-то или переменная новая. Ардуино ругается именно на эту строку  error: 'consnrain' was not declared in this scope

maksim
Offline
Зарегистрирован: 12.02.2012

там опечатка 

pos = constrain(pos, 0, 180);

а что она делает написано тут Программирование в разделе Математические функции.

BossTon
Offline
Зарегистрирован: 30.03.2013

Попробовал, что-то идет не так. серва начинает либо бешено кружиться, либо если использовать 21 строку вместо 22 ,серва крутится и останавливается в одном положении и далее не двигается.

maksim
Offline
Зарегистрирован: 12.02.2012

Это и есть статическая ошибка - тоесть до нужной позиции не дотягивает, пока просто снизте точность позиционирования

#include <Servo.h>

#define servopin1 10
#define pot A9

Servo servo1;

int poss[] = {23, 273, 523, 723, 1023}; // заданные положения

void setup()
{
  servo1.attach(servopin1);
}

void loop()
{
  static byte i;
  int pos = analogRead(pot);
  if(pos < poss[i]-30 || pos > poss[i]+30)
  {
    pos = map(pos, 0, poss[i], 0, 90);
    //pos = map(pos, 0, poss[i], 180, 90);
    pos = consnrain(pos, 0, 180);
    servo1.write(pos);
  }
  else
  {
    delay(2000);
    i++;
    if(i == 5) i = 0;
  }
  delay(10);
}

если 30 мало, то сделайте побольше... аесли многовато, то поменьше...

alivan
Offline
Зарегистрирован: 18.09.2013

Подскажите, голову удалось запустить т.е скетч дописать,поделиться им можете?

BossTon
Offline
Зарегистрирован: 30.03.2013

Головку запустил, даже сделал несколько панорам в автоматическом режиме.

Осталось просто доработать механику.

Код получился некрасивый, но иначе (по правилам с циклами переменными)ничерта не работал. Пришлось как всегда изобретать велосипед.

Но в итоге работает.

Так как катастрофически не хватает времени, проект забросил. и где код лежит уже не помню. Но он залит в Ардуино. Можно его оттуда какнить выудить?

А, не, наврал. Код нашел. В программировании не разбираюсь но логику понимаю, поэтому не все может быть понятно.

#define ANGLE_LIMIT 63
#define ANGLE_STEP  7
 #include <Servo.h> 
#define STOP_SPEED  90
#define CW_SPEED	(STOP_SPEED -9)
#define CCW_SPEED   (STOP_SPEED + 9)
int pulscount=1;  // Счетчик числа импульсов в пакете ИК
int puls = 4;    // Число пакетов ИК
int wzat = 2000;         // Время нажатия кнопки затвора - 3 с
int wp = 3000;           // Пауза перед спуском затвора - 4 с
 Servo servo;
 Servo servov;
 void setup(){
   TCCR1A = _BV(COM1A1) | _BV(COM1B1) ; // phase and frequency correct mode. NON-inverted mode
  TCCR1B = _BV(WGM13) | _BV(CS10);     // Делитель N = 1 - (_BV(CS10)); 8 - (_BV(CS11))
  OCR1B = 0;              // Скважность 102 - рабочий сигнал, 0 - сигнал отсутствует
  ICR1 = 210;             // Частота 16мГц/2*N*ICR1 = 16000кГц/(2*1*210)=38095Гц
  pinMode(12, OUTPUT);    // К 12 (на mega) ножке подключен ИК светодиод АЛ107 через сопротивление 1 кОм
 servo.attach(10);
 servo.write(90);
  servov.attach(9);
 servov.write(90);
 }

void loop()
{
  for (int targetAngle = 0; targetAngle < ANGLE_LIMIT; targetAngle += ANGLE_STEP) 
       {
 
		servo.write(CW_SPEED); // запускаем движение вперёд
		while (map(analogRead(A10), 0, 1023, 0, 207) < targetAngle)
			; // ждём пока докрутимся до нужного угла
 
		servo.write(STOP_SPEED); // стоп машина!
		delay(50); // ждём полной остановки
 	        IR_Sony();   // Нажимаем спусковую кнопку
	}
 
	servo.write(CCW_SPEED); // запускаем движение назад
	while (map(analogRead(A10), 0, 1023, 0, 207) > 0); // ждём пока докрутимся до старта
        servo.write(STOP_SPEED);
        delay(50);
  step_vert1();
 for (int targetAngle = 0; targetAngle < ANGLE_LIMIT; targetAngle += ANGLE_STEP) 
       {
 
		servo.write(CW_SPEED); // запускаем движение вперёд
		while (map(analogRead(A10), 0, 1023, 0, 207) < targetAngle)
			; // ждём пока докрутимся до нужного угла
 
		servo.write(STOP_SPEED); // стоп машина!
		delay(50); // ждём полной остановки
 	        IR_Sony();   // Нажимаем спусковую кнопку
	}
 
	servo.write(CCW_SPEED); // запускаем движение назад
	while (map(analogRead(A10), 0, 1023, 0, 207) > 0); // ждём пока докрутимся до старта
        servo.write(STOP_SPEED);
        delay(50);
  step_vert2();
       for (int targetAngle = 0; targetAngle < ANGLE_LIMIT; targetAngle += ANGLE_STEP) 
       {
 
		servo.write(CW_SPEED); // запускаем движение вперёд
		while (map(analogRead(A10), 0, 1023, 0, 207) < targetAngle)
			; // ждём пока докрутимся до нужного угла
 
		servo.write(STOP_SPEED); // стоп машина!
		delay(50); // ждём полной остановки
 	        IR_Sony();   // Нажимаем спусковую кнопку
 
	}
 
	servo.write(CCW_SPEED); // запускаем движение назад
	while (map(analogRead(A10), 0, 1023, 0, 207) > 0); // ждём пока докрутимся до старта
        servo.write(STOP_SPEED);
        delay(50);
   step_vert3();
   IR_Sony(); 
   startvert();

}

 void IR_Sony()  { //Подпрограмма подачи ИК сигналя для спуска зотвора камеры NEX5
  digitalWrite(13, HIGH);//Индикация паузы светодиодом на плате
  delay(wp);// Пауза перед спуском затвора 
  digitalWrite(13, LOW);
  pulscount=1;  
   while (pulscount<puls)          // цикл пакета импульсов  
    
    {OCR1B = 102;   // включаем светодиод
    delayMicroseconds(2432);       // светодиод горит микросекунд
    OCR1B = 0;     // выключаем светодиод
    delayMicroseconds(576);       // светодиод выключен  микросекунд
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(1216);       
    OCR1B = 0;     
    delayMicroseconds(576); 
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(640);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(1216);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(1216);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(640);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(1216);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(640);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(640);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(1216);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(640);       
    OCR1B = 0;     
    delayMicroseconds(576);
     OCR1B = 102;   // включаем светодиод
    delayMicroseconds(1216);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(1216);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(1216);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(640);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(640);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(640);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(1216);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(1216);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(1216);       
    OCR1B = 0;     
    delayMicroseconds(576);
    OCR1B = 102;   // включаем светодиод
    delayMicroseconds(1216);       
    OCR1B = 0;     
    delayMicroseconds(11136);
    pulscount++;
    }
    digitalWrite(13, HIGH);
    delay(wzat); // Время нажатия кнопки затвора
    digitalWrite(13, LOW);    
}
 void step_vert1()
  {
  servov.write(100);
while (map(analogRead(A11), 0, 1023, 0, 100) < 9);
servov.write(90);
delay(500);
  }
  void step_vert2()
  {
  servov.write(100);
while (map(analogRead(A11), 0, 1023, 0, 100) < 18);
servov.write(90);
delay(500);
  }
   void step_vert3()
  {
  servov.write(100);
while (map(analogRead(A11), 0, 1023, 0, 100) < 27);
servov.write(90);
delay(500);
  }
  void startvert()
{servov.write(80);
while (map(analogRead(A11), 0, 1023, 0, 100) > 0);
servov.write(90);
delay(500);
}

 

alivan
Offline
Зарегистрирован: 18.09.2013

Благодарю!