Поворот сервопривода в зависимости от нажатия двух кнопок

Тема в разделе "Arduino & Shields", создана пользователем Plusheviy.los, 20 сен 2016.

  1. Plusheviy.los

    Plusheviy.los Нуб

    Всем привет! Собрался делать довольно большой проект на ардуино, но не особо пока в теме. Сервопривод должен переходить из состояния 0 градусов(первое положение) в 45(второе положение), потом в 90(третье положение). То есть у него 3 положения. Сначала он в первом. У меня 2 кнопки: при нажатии первой он должен повернуться во второе, при повторном нажатии в третье, при ещё одном во второе, то есть первая кнопка переключает 2й и 3й режим, а вторая кнопка сбрасывает из любого положения в первое положение. Я хотел использовать счётчик, но почему-то он не работает. Серво кряхтит, но то поворачивается на 90 сразу, то никуда, то в 45, а потом кряхтит... Вот мой код:
    Код (C++):
    #include <Servo.h>

    //объявляем переменную порта
    int portServ = 9;
    int portBut1 = 2;
    int portBut2 =4;
    int portLed = 13;
    int firstPos = 0;//первое положение сервы
    int partblock=45; //второе положение
    int block=90; //третье положение
    int counter=0; //счетчик

    Servo myservo;

    boolean lastButton1=LOW;
    boolean currentButton1 = LOW;
    boolean lastButton2=LOW;
    boolean currentButton2 = LOW;

    boolean ledOn1=false;

    void setup() {
      // put your setup code here, to run once:
      myservo.attach(portServ); //attach our servo to the port 9
      myservo.write(0);
     
      pinMode(portBut1, INPUT);
      pinMode(portBut2, INPUT);
      pinMode(portLed, OUTPUT);
    }

    boolean debounce (boolean last, int button) //функция, где мы устраняем дребезг
    //передаём последнее значение нажата ли кнопка.
    {
      boolean current = digitalRead(button); //считываем текущее значение кнопки
      if (last!=current) //если значение последнего состояния кнопки не совпадает с текущим
      {
        delay(5); //ждём 5 мс, это мало, но хватит, чтобы кнопка узбагоилась
        current = digitalRead(button); //текущему значению присваеваем считываемое состояние кнопки
      }
      return current;//возвращаем текущее значение, вроде как то что мы чётко считали
    }

    void loop() {
      counter=0;
    start:
      currentButton1=debounce(lastButton1,portBut1);
      currentButton2=debounce(lastButton2,portBut2);
     
       counter=counter+1;
      if(currentButton1==HIGH&&counter%2==0)//нечётный счетчик
      {
         {
        ledOn1= !ledOn1;
      }
        digitalWrite(portLed, ledOn1); //собственно взаимодействие с диодом
        myservo.write(partblock);              // tell servo to go to position in variable 'pos'
        delay(15);                       // waits 15ms for the servo to reach the position
     
       lastButton1=currentButton1; //ну и наш настояший превратился в бывшего
      lastButton2=currentButton2; //ну и наш настояший превратился в бывшего
        goto start;
      }
       
        if(currentButton1==HIGH&&counter%2!=0)
      {
         {
        ledOn1= !ledOn1;
      }
        digitalWrite(portLed, ledOn1); //собственно взаимодействие с диодом
         myservo.write(block);               // tell servo to go to position in variable 'pos'
        delay(15);                       // waits 15ms for the servo to reach the position
        lastButton1=currentButton1; //ну и наш настояший превратился в бывшего
      lastButton2=currentButton2; //ну и наш настояший превратился в бывшего
        goto start;
     
        }
       if(currentButton2==HIGH)
      {
        myservo.write(firstPos);
       
        counter=0;
        lastButton1=currentButton1; //ну и наш настояший превратился в бывшего
      lastButton2=currentButton2; //ну и наш настояший превратился в бывшего
        goto start;
      }
     
       else
       {}
       lastButton1=currentButton1; //ну и наш настояший превратился в бывшего
      lastButton2=currentButton2; //ну и наш настояший превратился в бывшего
     
    }
     
  2. vvr

    vvr Инженерище

    видно что знаний маловато, но проект решили делать большой
    не страшно ?
     
  3. Plusheviy.los

    Plusheviy.los Нуб

    Страшно) но пока время и ресурсы есть.. а так по коду есть что-то?:)
     
  4. vvr

    vvr Инженерище

    ну если проект большой и есть время научитесь правильно обрабатывать кнопки дли избежания дребезга контактов и без задержек.
    потом научитесь кнопками изменять состояние вашей системы
    а потом подключайте серву и устраивайте с ней игрища
     
  5. Valera_gug

    Valera_gug Нерд

    Меня смущает, что вы счетчик сразу же плюсуете.
    Это тоже самое, что вы его объявите равной единице.
    У вас логика нарушена в коде.
     
  6. vvr

    vvr Инженерище

    есть куча готовых библиотек для обработки кнопок
    Bounce для кнопок с наружной подтяжкой
    OneButton и ClickButton для кнопок с внутренней подтяжкой
     
  7. ostrov

    ostrov Гуру

    Код не смотрел, но ИМХО он длинноват для такой задачи. По моему все можно упихать гораздо компактнее.
     
  8. ostrov

    ostrov Гуру

    С дребезгом боремся так: опрашиваем кнопку каждые 40-50мс, если предыдущее состояние "отжато" а нынешнее "нажато", то это и есть нажатие. На другие изменения или отсутствия изменений не реагируем.
     
  9. Tomasina

    Tomasina Сушитель лампочек Модератор

    а надо ли тут бороться с дребезгом? Пока серва не отработает, кнопки можно игнорировать.
    Код (C++):
    #include <Servo.h>

    const byte servoPin = 9;
    const byte button1 = 4;    // Кнопки подключаются между пином и GND
    const byte button2 = 5;
    const byte LED = 13;
    enum {READY, ANGLE_0, ANGLE_45, ANGLE_90};  // возможные состояния
    byte currentMode;

    Servo servoprivod;

    void setup()
    {
      pinMode(button1, INPUT_PULLUP);
      pinMode(button2, INPUT_PULLUP);
      pinMode(LED, OUTPUT);
      rotate(ANGLE_0);
      currentMode = READY;
    }


    void loop()
    {
      checkButtons();            //  сканируем кнопки

      if(currentMode != READY)   // если кнопка нажата
      {
        digitalWrite(LED, HIGH);
        rotate(currentMode);
        digitalWrite(LED, LOW);
        currentMode = READY;
      }
    }


    void rotate(byte mode) // входной параметр - угол поворота
    {
      byte angle;
      switch(mode)
      {
        case ANGLE_0:  angle = 0;  break;
        case ANGLE_45: angle = 45; break;
        case ANGLE_90: angle = 90; break;
        default: angle = 0;
      }
      servoprivod.attach(servoPin,600,2400);
      servoprivod.write(angle);
      delay(512);
      servoprivod.detach();
    }



    void checkButtons()
    {
      if(!digitalRead(button1))      // нажата первая кнопка
      {
        currentMode++;
        if(currentMode > ANGLE_90) currentMode = ANGLE_45;
      }
      else if(!digitalRead(button2)) // нажата вторая кнопка
      {
        currentMode = ANGLE_0;
      }
      else currentMode = READY;
    }
     
  10. vvr

    vvr Инженерище

    А ЧТО ОН ПОТОМ БУДЕТ СПРАШИВАТЬ))))
     
  11. Tomasina

    Tomasina Сушитель лампочек Модератор

    тут еще есть где развернуться :)
    Мне ведь тоже надо интеллект развивать, вот и тренируюсь на кроликах :D
     
    Valera_gug и vvr нравится это.
  12. ostrov

    ostrov Гуру

    Так серва же не тормозит остальные процессы, команда на нее пошла и все. Дребезг может иметь место. А так одна кнопка триггер между 2 и 3 полодением, первая сброс на 1.
     
  13. qwone

    qwone Гик

    На вот код. Решен в 2 потока. Их можно убрать. Но для начального тестирования подойдет.
    Код (C++):
    /*
    серва  -> 9 (Serv_pin)
           +5V -> +5V
           GND -> GND
    кнопка 1  -> 2 (btm1_pin) 0 нажата /1 нет
           GND -> GND
    кнопка 2  -> 4 (btm2_pin) 0 нажата /1 нет
           GND -> GND
    */

    //#1 сервопривод
    #include <Servo.h>
    Servo myservo;
    const int  Serv_pin = 9;
    uint8_t position_serv ;
      void setup1(){
          myservo.attach(Serv_pin);
          position_serv =1;
          myservo.write(0);
      }
      void loop1(){
        switch (position_serv) {
        case 1:
          myservo.write(0);
          break;
        case 2:
          myservo.write(45);
          break;
        case 3:
          myservo.write(90);
          break;
        }
      }
    //#2 кнопки
    const int  btm1_pin = 2;
    const int  btm2_pin = 4;
    uint8_t btm1,btm1_old ;
    uint8_t btm2,btm2_old ;
      void setup2(){
          pinMode(btm1_pin, INPUT_PULLUP)  ;
          btm1 = digitalRead( btm1_pin);
          pinMode(btm2_pin, INPUT_PULLUP)  ;
          btm2 = digitalRead( btm2_pin);
      }
      void loop2(){
        btm1_old=btm1;
        btm1 = digitalRead( btm1_pin);
        if  (btm1_old&&!btm1) {
            if (position_serv==2) position_serv==3 ;
            else position_serv==2;
            }
        btm2_old=btm2;
        btm2 = digitalRead( btm2_pin);
        if  (btm2_old&&!btm2) position_serv=1;
      }

    void setup() {
    //#1
      setup1();
    //#2
      setup2();

    }

    void loop() {
      static uint32_t MILLIS ;
      MILLIS = millis() ;

    //#1 200 миллисекунд вычислит. поток 1
      static uint32_t future1 = 0 ;
      if (MILLIS>=future1) {
      future1 = MILLIS + 200 ;
      loop1();
      MILLIS = millis() ;  
      }
    //#2  200 миллисекунд вычислит. поток 2
      static uint32_t future2 = 0 ;
      if (MILLIS>=future2) {
      future2 = MILLIS + 200 ;
      loop2();
      }
    }
     
  14. ostrov

    ostrov Гуру

    Чем решение от Томасины не понравилось? Оно короче раза в три.
     
  15. qwone

    qwone Гик

    Я не собирался мерятся длиной решения. Я просто показал еще 1 подход решения.И это просто промежуточный вариант для новичков. Да и Tomasina для развития интеллекта.
     
    Последнее редактирование: 20 сен 2016
  16. vvr

    vvr Инженерище

    давайте все по варианту напишем и выложим чтобы тс совсем офигел))))

    Код (C++):

    #include <Servo.h>
    #include "OneButton.h"

    Servo servo;

    OneButton button1(3, true);
    OneButton button2(4, true);

    byte Mode = 0;

    void setup()
    {    
      button1.attachClick(Click1);
      button2.attachClick(Click2);
      servo.attach(5);
    }

    void loop()
    {
      button1.tick();
      button2.tick();
      servo.write(Mode*45);
    }

    void Click1()
    {
      Mode++;
      if(Mode > 2) Mode = 1;
    }

    void Click2()
    {
      Mode = 0;
    }
     
     
    Последнее редактирование модератором: 20 сен 2016
    Plusheviy.los, Tomasina, ИгорьК и ещё 1-му нравится это.
  17. Tomasina

    Tomasina Сушитель лампочек Модератор

    вот блин, как же просто и изящно-то... :D
     
  18. Plusheviy.los

    Plusheviy.los Нуб

    Ух, сколько ответов)) спасибо, конечно.. решил так сразу запустить со своими портами (чтоб не уточняли :D), дребезга нет, но кнопка работает через раз( но работает чисто, когда таки удаётся.. может мой серво такой кривой? или кнопки?..
     
  19. Plusheviy.los

    Plusheviy.los Нуб

    Это не робит(( и почему "if(!digitalRead(button1)) // нажата первая кнопка" ? Это же значит "не нажата"..
     
  20. Plusheviy.los

    Plusheviy.los Нуб

    А кто такой тс? :D
    А где тут обработка дребезга? Его нет вообще, но может кнопка тупит поэтому, что там по дефолту большое время ожидания?..