Ошибка в коде на управление Серво

Тема в разделе "Arduino & Shields", создана пользователем Otto, 25 дек 2016.

  1. Otto

    Otto Нерд

    Такая проблема, слепил 2 кода для плавных поворотов серво, по отдельности работают отлично, но вместе очень глючино... Когда в void setup() комментируешь любую из двух строчек для назначения серво, то один код работает стабильно, то же самое наоборот.

    Не могу совместить оба кода, что бы работали одновременно. Принцип кода: при длительном зажатии кнопов Влево-Вправо серво поворачивается пока не отпустишь, а при коротком нажатии кнопки вверх на пульте включаются автоповороты серво, при нажатии кнопки вниз - автоповороты откл.

    Вот сам код:
    Код (C++):
    #include <VarSpeedServo.h>  // Библиотека для Servo-Мотора с регулировкой скорости
    #include <IRremote.h>       // Библиотека для ИК приёмника

    byte RECV_PIN = 11;        // вход ИК приемника
    IRrecv irrecv(RECV_PIN);   // Объект ИК
    decode_results results;

    VarSpeedServo servoPovorot; //даём имя servo

    // переменные для контроля за процессом поворотов Servo
    bool Right_Pin_1   = false;   //для ручного поворота вправо при зажатии кнопки
    bool Left_Pin_1    = false;   //для ручного поворота влево при зажатии кнопки
    bool Auto_Povorot  = false;   //для Автоповорота при кратковременном нажатии


    class Sweeper
    {
        VarSpeedServo servoAutoPovorot; // сервопривод для автоповорота

        int pos; // текущее положение сервы
        int increment; // увеличиваем перемещение на каждом шаге
        int updateInterval; // промежуток времени между обновлениями
        unsigned long lastUpdate; // последнее обновление положения

      public:
        Sweeper(int interval)
        {
          updateInterval = interval;
          increment = 1;
        }

        void attach(int pin)
        {
          servoAutoPovorot.attach(pin);
        }

        void detach()
        {
          servoAutoPovorot.detach();
        }

        void Update()
        {
          if ((millis() - lastUpdate) > updateInterval) // время обновлять
          {
            lastUpdate = millis();
            pos += increment;
            servoAutoPovorot.write(pos);
            if ((pos >= 130) || (pos <= 0)) // конец вращения
            {
              // обратное направление
              increment = -increment;
            }
          }
        }
    };

    Sweeper servoAutoPovorot(35);  // скорость Авто-вращения серво



    /* Переменная для плавного вращения servo,чтобы не использовать delay.
      промежуточная переменная для хранения (увеличенного диапазона от 0 до 20000)значений (увеличения или уменьшения)PWM,
      с последующей конвертации в переменную(val_1) диапазон градусов поворота доступных для servo.*/

    int L = 0;

    //переменная для конвертации (увеличенного диапазона значений от 0 до 20000) (L),в значения требуемые для поворота servo.
    int val_1;

    //переменная для (увеличения или уменьшения)скорости поворота servo.
    int speed_PWM = 1;

    //переменная eventTime, для паузы, вместо delay,будем использовать функцию millis.
    unsigned long eventTime = 0;


    void setup()
    {
      irrecv.enableIRIn();          // включить ИК приёмник
      servoPovorot.attach(9);       // Servo подключён на цифровой вход (pin 9)
      servoAutoPovorot.attach(9);   // для автоповоротов класса Sweeper
    }


    void loop()
    {

      if (Auto_Povorot == true) {        //Если Auto_Povorot истина...
        servoAutoPovorot.Update();      // ...тогда включаем автоповорот серво
      }

      /* Делаем, что бы система работала в режиме удержания кнопки для Серво.
        После приёма определённого кода кнопки,сразу перехватывать идущий за ним (кодом), (пустой инфракрасный сигнал)
        и считать его - (пустой инфракрасный сигнал), за код кнопки.
        После пропадания (пустого инфракрасного сигнала) - будем считать, что код перестал слаться.*/


      /* 1. После приёма определённого кода кнопки, перехватывать (пустой инфракрасный сигнал).
         2. Конвертировать пульсирующий (-) с (ИК) преемника сигнал в постоянный.
        После появления и пропадания сигнала, состояние сразу не меняется! а ждет  100 миллисекунд.
        Если 100 миллисекунд не прошло, и поступил еще один ИК сигнал с пульта,
        тогда таймер заново запускается на 100 миллисекунд.*/


      if (digitalRead(RECV_PIN) == LOW)
        eventTime = millis();
      if (millis() - eventTime > 100) (Right_Pin_1 = false), (Left_Pin_1 = false);

      /* Если Right_Pin_1) ==, выставляем ограничение для переменной(L) до (&& L<20000) и начинаем увеличивать
        значения переменной(L), на значение переменной speed_PWM,
        и также выставляем ограничение при убывании (&& a>0).*/


      if (Right_Pin_1 ==  true && L < 20000  ) L = L + speed_PWM;
      if (Left_Pin_1  ==  true && L > 0  ) L = L - speed_PWM;


      //читаем значение (L) и конвертируем его в значение val_1, то бишь в значение поворота в градусов доступных для servo.
      val_1 = L;
      val_1 = map(val_1, 0, 20000, 1, 130);     // Задаём диапазон скорости и поворота Серво (углы поворота от 1 до 130 градусов)
      servoPovorot.write(val_1);                // Положение Серво в соответствии с val_1.


      if (irrecv.decode(&results)) {
        // 2 Команды с пульта отвечающие за ручные повороты Серво.
        if (results.value == 0xFFC23D) Right_Pin_1  = true;  // Поворот Вправо
        if (results.value == 0xFF22DD) Left_Pin_1   = true;  // Поворот Влуво
        if (results.value == 0xFF629D) Auto_Povorot = true;   //Автоповорот вкл.
        if (results.value == 0xFFA857) Auto_Povorot = false;  //Автоповорот откл.

        irrecv.resume(); // получаем следующие значения
      }
    }
     
  2. rkit

    rkit Гуру

    Нельзя просто скопировать два конфликтующих куска кода, и надеяться, что всё будет работать. Разберитесь, что каждый из них делает, и напишите самостоятельно.