Проблема с кодом - неправильно работает сервопривод

derungebundener

✩✩✩✩✩✩✩
18 Июл 2020
117
3
Товарищи, есть небольшая просьба - может ли кто-то опытный глянуть код и подсказать, в чем может быть проблема?

Проблема такова:

Есть аналоговый джойстик, т.е. 2 потенциометра. Эти два потенциометра управляют двумя сервоприводами.
В блоке setup на оба сервопривода подаётся команда servo.writeMicroseconds(1500)
Эта команда нужна для того, чтобы при старте выровнять сервы по центру.

Управление сервоприводами работает так, как и надо - с этим проблем нет.
Однако вот первоначальная установка в центральное положение работать отказывается.

Код такой:

C++:
#include <Servo.h> //Импорт библиотеки

Servo ServoCamX; //Создание объекта оси Х.
Servo ServoCamY; //Создание объекта оси Y.

unsigned long timer; //Таймер для осей.
byte PosPERIOD = 5; //Период для таймера суммирования джойстика.
unsigned long detachTimerX; //Таймер для отключение сервопривода оси Х.
unsigned long detachTimerY; //Таймер для отключение сервопривода оси У.
byte detachPeriod = 64; //Период для отключения сервоприводов

//Объявление переменных для оси Х

byte JoyPosX = A0; //Аналоговый пин оси Х.
int CamPosXAnalog; //Перемнная для замера положения джойстика. Принимает значение 0-1023.
int CamPosX = 1500; //Переменная для позиции оси Х. Выводится на сервопривод оси Х.
int CamJoyMiddleX; //Переменная реального положения джойстика оси Х. Замеряется при старте в setup.
int CamPosXOld; //Переменная прошлого положения оси Х. Используется для отключения сервопривода.


//Объявление переменных для оси У

byte JoyPosY = A1; //Аналоговый пин оси Y.
int CamPosYAnalog; //Перемнная для замера положения джойстика. Принимает значение 0-1023.
int CamPosY = 1500; //Переменная для позиции оси Х. Выводится на сервопривод оси Y.
int CamJoyMiddleY; //Переменная реального положения джойстика оси Х. Замеряется при старте в setup.
int CamPosYOld; //Переменная прошлого положения оси Y. Используется для отключения сервопривода.

byte CamDeadzone =128; //Мертвая зона джойстика.

void setup()

{

  //Serial.begin(9600);

  //Инициализация оси Х.

  ServoCamX.attach(3, 500, 2500); //Активация оси Х с атрибутами Пин-Мин-Макс.
  [B][U]ServoCamX.writeMicroseconds(1500); [/U][/B]//Cтарт к центральной позиции оси Х при старте.
  //ServoCamX.detach();

  //Инициализация оси У.

  ServoCamY.attach(5, 500, 2500); //Активация оси Y с атрибутами Пин-Мин-Макс.
  [B][U]ServoCamY.writeMicroseconds(1500);[/U][/B] //Cтарт к центральной позиции оси Y при старте.
  //ServoCamY.detach();

  CamJoyMiddleX = analogRead(JoyPosX); //Замер реального положения оси Х в центральном положении - джойстик отпущен.
  CamJoyMiddleY = analogRead(JoyPosY); //Замер реального положения оси Х в центральном положении - джойстик отпущен.
}

void loop() {

  if (millis() - timer >= PosPERIOD) // условие таймера
  {
    timer = millis();                   // Сброс таймера // Выполняем блок кода для осей каждые PosPERIOD миллисекунд

    //Выполняем код оси Х.

    CamPosXAnalog = analogRead(JoyPosX);
    if (CamPosXAnalog < (CamJoyMiddleX-CamDeadzone)|| CamPosXAnalog > (CamJoyMiddleX+CamDeadzone)) //Проверка нахождения оси Х вне мёртвой зоны.
   {
    CamPosXAnalog = map(analogRead(JoyPosX), 0, 1023, -10, 10);
    CamPosX = CamPosX + CamPosXAnalog;
    CamPosX = constrain (CamPosX, 500, 2500);
   }

   //Выполняем код оси Y.

    CamPosYAnalog = analogRead(JoyPosY);
    if (CamPosYAnalog < (CamJoyMiddleY-CamDeadzone)|| CamPosYAnalog > (CamJoyMiddleY+CamDeadzone)) //Проверка нахождения оси Y вне мёртвой зоны.
   {
    CamPosYAnalog = map(analogRead(JoyPosY), 0, 1023, 10, -10); // - и + инвертированы по сравнению с осью Х, так как необходимо инверсное движение оси У.
    CamPosY = CamPosY + CamPosYAnalog;
    CamPosY = constrain (CamPosY, 950, 2500); //950 - ограничение на поворот вниз из-за физического ограичения.
   }
  }

//Отключаем ось Х.

if (CamPosX < (CamPosXOld -5) || CamPosX > (CamPosXOld +5) )
{
ServoCamX.attach(3, 500, 2500);
ServoCamX.writeMicroseconds(CamPosX);
detachTimerX = millis();
CamPosXOld = CamPosX;
}
else if (millis() - detachTimerX > detachPeriod)
{
ServoCamX.detach();
}

//Отключаем ось У.

if (CamPosY < (CamPosYOld -5) || CamPosY > (CamPosYOld +5) )
{
ServoCamY.attach(5, 500, 2500);
ServoCamY.writeMicroseconds(CamPosY);
detachTimerY = millis();
CamPosYOld = CamPosY;
}
else if (millis() - detachTimerY > detachPeriod)
{
ServoCamY.detach();
}

  //Serial.print(CamPosXAnalog);
  //Serial.print("  ||  ");
  //Serial.println(CamPosYAnalog);
}
 

bort707

★★★★★★✩
21 Сен 2020
2,894
860
а зачем постоянно делать detach() и attach() ?
Вы выставили позицию сервы - и держите ее. А когда вы постоянно серву отключаете и подключаете - вот у вас начальная установка положения и теряется, как мне кажется
 

derungebundener

✩✩✩✩✩✩✩
18 Июл 2020
117
3
а зачем постоянно делать detach() и attach() ?
Вы выставили позицию сервы - и держите ее. А когда вы постоянно серву отключаете и подключаете - вот у вас начальная установка положения и теряется, как мне кажется
Нет нет, боюсь, вы не поняли сути проблемы - не работает именно начальное выставление в середину в блоке setup. Всё остальное работает как надо.

attach/detach нужен по другой причине - сервоприводы, видимо, не очень качественные и даже когда они достигают своей позиции, то все равно тихонько "шебуршат" и при этом немного греются.

Нагрузок физических как таковых нет и физического сдвига не будет, поэтому если нет новых команд, то сервы детачатся по таймеру.