Управление сервоприводом с помощью двух потенциометров B10K

Тема в разделе "Arduino & Shields", создана пользователем Volf, 4 фев 2015.

  1. Volf

    Volf Нерд

    Друзья, мне необходима ваша помощь. Как можно прописать программу, чтобы сервопривод управлялся с помощью среднего арифметического с двух датчиков? Датчики стоят зеркально друг к другу, вся система напоминает собой что-то вроде связи электронной педали газа с приводом на дроссельной заслонке. Так же необходимо сделать такую штуку: когда данные с датчиков будут отличаться друг от друга более чем на 10%, чтобы загорался светодиод, подскажите, пожалуйста! Очень надеюсь на вашу помощь! На данный момент у меня есть лишь программа, чтобы управлять сервоприводом с помощью одного датчика.

    Код (Text):
    #include <Servo.h>
    #define POT_MAX_ANGLE 540.0
    Servo myservo;
    void setup()
    {
      myservo.attach(9);
    }
    void loop()
    {
      int val = analogRead(A0);
      int angle = int(val / 1024.0 * POT_MAX_ANGLE);
      angle = constrain(angle, 0, 180);
      myservo.write(angle);
    }
     

    Вложения:

    • WQRtCsCp_W0.jpg
      WQRtCsCp_W0.jpg
      Размер файла:
      212,3 КБ
      Просмотров:
      1.134
    Последнее редактирование: 5 фев 2015
  2. Виталий

    Виталий Нерд

    Но в таком варианте как у вас среднее арифметическое всегда будет одинаковым...

    Насчет отличий показаний потенциометров:
    Код (Text):
    if (max(val1, val2) - min(val1, val2) > 1024 * 10%)
    {
      Включить светодиод
    }
    else
    {
      Выключить светодиод
    }
     
    Последнее редактирование: 5 фев 2015
  3. Volf

    Volf Нерд

    Но как прописать это среднее арифметическое?
     
  4. Виталий

    Виталий Нерд

    Вот так очевидно:
    Код (Text):
    void loop()
    {
      int val1 = analogRead(A0);
      int val2 = analogRead(A1);
      int val = (val1 + val2) / 2;

      //int angle = int(val / 1024.0 * POT_MAX_ANGLE);
      //angle = constrain(angle, 0, 180);
      angle = map(val, 0, 1024, 0, 180);
      myservo.write(angle);
    }
    И кроме того, constrain стоит заменить на map я думаю...
     
  5. Volf

    Volf Нерд

    Спасибо) сегодня попробую, отпишусь по результату
     
  6. Виталий

    Виталий Нерд

    Но я еще раз хочу обратить внимание, что в этом варианте серва двигаться не будет.
    Будет загораться только светодиод.

    Ну или я чего-то недопонимаю....
     
  7. Volf

    Volf Нерд

    upload_2015-2-5_13-57-34.png почему-то выдает такую ошибку, не могу разобраться, в чем дело.
     
  8. X-Dron

    X-Dron Гик

    в данной конфигурации это
    int val1 = analogRead(A0);
    int val2 = analogRead(A1);
    int val = (val1 + val2) / 2;
    работать не будет. Сервак всегда будет стоять в середине. Датчики включены зеркально. Если на одном будет 0, то на втором 1024.
    так будет лучше
    Код (Text):
      int val1 = analogRead(A0);
      int val2 = 1024 - analogRead(A1);
      int val = (val1 + val2) / 2;
     
  9. Volf

    Volf Нерд

    Код (Text):
    #include <Servo.h>
    #define POT_MAX_ANGLE 540.0

    int val1 = analogRead(A0);
      int val2 = 1024 - analogRead(A1);
      int val = (val1 + val2) / 2;
     
    Servo myservo;
    void setup()
    {
      myservo.attach(9);
    }
    void loop()
    {
      int val;
      int angle = int(val / 1024.0 * POT_MAX_ANGLE);
      angle = constrain(val, 0, 180);
      angle = map(val, 0, 1024, 0, 180);
      myservo.write(angle);
    }
    При таком коде серво не хочет двигаться
     
  10. X-Dron

    X-Dron Гик

    а, с какой стати он должен двигаться?
    Странно, что вообще компилируется.
    Код (Text):
    #include <Servo.h>

    Servo myservo;
    void setup()
    {
      myservo.attach(9);
    }
    void loop()
    {
      int val1 = analogRead(A0);
      int val2 = 1024 - analogRead(A1);
      int val = (val1 + val2) / 2;
      angle = map(val, 0, 1024, 0, 180);
      myservo.write(angle);
    }
     
  11. Volf

    Volf Нерд

    upload_2015-2-5_15-7-44.png
     
  12. X-Dron

    X-Dron Гик

    А немного подумать?
    Код (Text):
    #include <Servo.h>

    Servo myservo;
    void setup()
    {
      myservo.attach(9);
    }
    void loop()
    {
      int val1 = analogRead(A0);
      int val2 = 1024 - analogRead(A1);
      int val = (val1 + val2) / 2;
      int  angle = map(val, 0, 1024, 0, 180);
      myservo.write(angle);
    }
    можно вообще вот так
    Код (Text):

    #include <Servo.h>
    Servo myservo;
    void setup()
    {
      myservo.attach(9);
    }

    void loop()
    {
      int  angle = map((1024 + analogRead(A0) - analogRead(A1))/2, 0, 1024, 0, 180);
      myservo.write(angle);
    }
     
     
  13. Volf

    Volf Нерд

    Оп, извиняюсь))))
     
  14. Volf

    Volf Нерд

    А вы не подскажете, в чем здесь проблема? Просто мне нужно сделать так, чтобы при разнице данных с двух датчиков более чем на 10% загорался светодиод
    upload_2015-2-5_15-43-42.png
     
  15. X-Dron

    X-Dron Гик

    после
    myservo.write(angle);
    добавить:
    digitalWrite(3, abs(val1-val2)>18);

    в частном случае как у вас map не нужен
    myservo.write(angle);
    можно заменить на
    myservo.write(val);
    а строку с map удалить.
     
  16. Volf

    Volf Нерд

    Спасибо большое) завтра проведу эксперимент со светодиодом и отпишусь)
     
  17. X-Dron

    X-Dron Гик

    надеюсь, понятно, что код должен быть таким:
    Код (Text):
    #include <Servo.h>

    Servo myservo;
    void setup()
    {
      myservo.attach(9);
    }
    void loop()
    {
      int val1 = analogRead(A0);
      int val2 = 1024 - analogRead(A1);
      int val = (val1 + val2) / 2;
     //  int  angle = map(val, 0, 180, 0, 180);
     angle = constrain(val, 0, 180);
     myservo.write(angle);
     digitalWrite(3, abs(val1-val2)>18);
    }
     
  18. Volf

    Volf Нерд

    Да, конечно)
     
  19. Виталий

    Виталий Нерд

    Функция 'constrain' проверяет и если надо задает новое значение, так чтобы оно была в области допустимых значений, заданной параметрами.
    т.е. теоретически 'val' у нас может быть 0 до 1024. А 'constrain' обрежет нам его от 0 до 180. Как результат серва будет работать только в небольшом диапазоне вращения потенциометра (около 17% где-то в середине диапазона вращения потенциометра).
    Зато функция 'map'пропорционально переносит значение (val) из текущего диапазона значений (0 - 1024) в новый диапазон (0 - 180). И в этом случае весь диапазон вращения потенциометра будет управлять сервой.

    И что касается строки 'digitalWrite(3, abs(val1-val2)>18);' val1-val2 получается постоянная и меняться она не будет. соответственно светодиод менять свое состояние не будет никогда.
    Поэтому 'val2' мы оставим только то, что получили с потенциометра, а при расчете 'val' немного изменим формулу.

    Код (Text):
    #include <Servo.h>
    Servo myservo;

    void setup()
    {
      myservo.attach(9);
    }

    void loop()
    {
      int val1 = analogRead(A0);
      int val2 = analogRead(A1);
      int val = (val1 + 1024 - val2) / 2;
      int  angle = map(val, 0, 1024, 0, 180);
      myservo.write(angle);
      digitalWrite(3, abs(val1 - val2) > 102);
    }
     
  20. X-Dron

    X-Dron Гик

    Виталий, следите за постановкой задачи и развитием темы.
    Изначально так и было, но в #14-м после топикстартер изменил на
    int angle = map(val, 0, 180, 0, 180);
    Понятно, почему: Хоть резисторы B10K и могут поворачиваться на 300град, но вот "электронная педаль газа" должна поворачивать, по замыслу стартера на 52.7град. (300/1024*180), при этом привод должен поворачиваться на 180град. Да, полностью согласен, что при этом используется только 17% диапазона и точность никакая.
    Чтобы на серву не выдавалось значение более 180, на больших углах отклонения резисторов, map был заменен на constrain.
    angle = constrain(val, 0, 180);
    myservo.write(angle);
    Будет, когда один из датчиков отвалится от педали. А светодиод это сигнализация аварии, т.к. среднее арифметическое считается не правильно.
    Лучше будет даже так написать, чтобы в режиме ошибки никуда не пытался ездить.
    Код (Text):
    #include <Servo.h>

    Servo myservo;
    void setup()
    {
      myservo.attach(9);
    }
    void loop()
    {
      int val1 = analogRead(A0);
      int val2 = 1024 - analogRead(A1);
      int val = (val1 + val2) / 2;
      boolean alarm = abs(val1-val2)>18;
      if (!alarm) {
      int angle = constrain(val, 0, 180);
        myservo.write(angle);
      }
      digitalWrite(3, alarm);
    }
     
    Последнее редактирование: 6 фев 2015