Millis + Button

Тема в разделе "Arduino & Shields", создана пользователем evgen_bolbes, 17 авг 2017.

  1. evgen_bolbes

    evgen_bolbes Нуб

    Здравствуйте.
    Есть код и как обычно у новичков не выходит то что они задумали.
    Код (C++):
    unsigned long timebutton1; //хранение времени нажатия кнопки
    byte const led1=9; //светодиод
    byte const button1 = A5; //кнопка

    void setup(){
      Serial.begin(9600);
      pinMode(led1,OUTPUT);
      pinMode(button1,INPUT_PULLUP);
    }
    void loop(){
      boolean button1 = !digitalRead(A5);
     
      if (button1 == 1){  //кнопка нажата
        Serial.print("timebutton1: ");Serial.println(button1);
        timebutton1 = millis(); //время нажатия кнопки
        if (millis() - timebutton1 > 5000){    //еслим прошло 5 сек то
         digitalWrite(led1,1); //вкл светодиод
      }
       }
     
      else {
        digitalWrite(led1,0); // если не прошло 5 сек не вкл
        Serial.print("timebutton1: ");Serial.println(button1);
      }
    }

     
    Логика: При нажатие на кнопку через 5 сек вкл светодиод, если кнопка не нажата светодиод не горит.
     
  2. rkit

    rkit Гуру

    A5 никогда не будет равно 1
    Вы забыли считать состояние пина.
     
  3. issaom

    issaom Гуру

    Код (C++):
    byte const button1 = A5; //кнопка
    Код (C++):
    boolean button1 = !digitalRead(A5);
    У Вас button1 это переменная boolean или константа byte? Что-то я ничего не понимаю )))) Вы её зачем константой то объявили если считываете в нее значение пина ?
     
  4. qwone

    qwone Гик

    Код (C++):
    /**/
    unsigned long mill;// переменая под millis
    //----------------------------------------------------------
    //----------------------------------------------------------
    const byte Led1Pin =/*нога светодиода*/9; //светодиод
    bool stat_led = 0;
    const byte Btn1Pin =/*нога кнопки*/ A5; //кнопка
    unsigned long past = 0;
    //----------------------------------------------------
    void setup() {
      pinMode(Led1Pin, OUTPUT);
      digitalWrite(Led1Pin, 0); //вкл светодиод
      pinMode(Btn1Pin, INPUT_PULLUP);
    }
    void loop() {
      mill = millis();
      if (!digitalRead(Btn1Pin)) {
        past = mill;
        stat_led = 1;
      }
      if (stat_led && mill - past >= 5000) { //еслим прошло 5 сек то
        digitalWrite(Led1Pin, 1); //вкл светодиод
        stat_led = 0;
      }
    }
    /*Скетч использует 1050 байт (3%) памяти устройства. Всего доступно 32256 байт.
      Глобальные переменные используют 18 байт (0%) динамической памяти, оставляя 2030 байт для локальных переменных. Максимум: 2048 байт.
    */
     
  5. mcureenab

    mcureenab Гуру

    Это разные переменные.
    Одна глобальная, другая локальная.
     
    issaom нравится это.
  6. mcureenab

    mcureenab Гуру

    Вы логку по русски сформулировали непонятно, поэтому код такой. Пока кнопка нажата находить текущее время и сравнивать его с текущим временем.

    Как найти 5 секунд от текущего состояния?
     
  7. evgen_bolbes

    evgen_bolbes Нуб

    по мне так все просто. кнопка нажата время записалось в timebutton1. Прошло 5 сек светодиод горит не прошло не горит(т.е. кнопку отпустили) Вот реализация хромает это точно
    время в данный момент - время нажатия > 5 сек = светодиод горит.
     
  8. b707

    b707 Гуру

    Вы записываете текущее время в переменную timebutton1 при каждом выполнении loop() - то есть десятки и сотни раз в секунду. И в следующей же строке сравниваете это значение с millis(). У вас разница между timebutton1 и millis() никогда не достигнет 5 секунд - оно вряд ли превысит даже 1 миллисекунду.
    Значение времени надо сохранять в timebutton1 ОДИН РАЗ!
     
    evgen_bolbes нравится это.
  9. evgen_bolbes

    evgen_bolbes Нуб

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

    Код (C++):
    unsigned long timebutton1; //хранение времени нажатия кнопки
    const byte  led1=9; //pin светодиод
    byte  button1 = 5; //pin кнопка
    long interval01 = 5000;


    void setup(){
      Serial.begin(9600);
      pinMode(led1,OUTPUT); //пин как выход
      pinMode(button1,INPUT_PULLUP); // пин как вход
    }
    void loop(){
      boolean button1 = !digitalRead(5); // при нажатие кнопки получаем 1
     
      if (button1 == 1){  //кнопка нажата и удерживается
        Serial.print("timebutton1: ");Serial.println(button1); //смотрим состояние кнопки (1)
      timer01();
      }
     
      else {
          digitalWrite(led1,0); // если не прошло 5 сек или кнопка отпушена не вкл светодиод
          Serial.print("timebutton1: ");Serial.println(button1); //смотрим состояние кнопки (0)
       
      }
    }

    void timer01() {
       
         
          if (millis() - timebutton1 >= interval01){    //еслим прошло 5 сек после нажатия и удержиния то
              timebutton1 = millis();
              digitalWrite(led1,1); //вкл светодиод
          }
    }
     
  10. Tomasina

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

    У тебя в коде две разные переменные с одинаковым именем.
    И компилятор их обрабатывает по своей (более правильной) логике, чем твоя.
    2017-08-18_14-12-59.png
     
  11. evgen_bolbes

    evgen_bolbes Нуб

    с моей точки зрения компилятор обрабатывает локальную переменную boolean button1 с которой он получает 1. Получил 1 запустил оператор if. Что и подтверждает монитор COM порта. 1 появилась спустя 5 сек вкл светодиод пока кнопка не будет отжата. Подскажите тогда как правильно .
     
  12. evgen_bolbes

    evgen_bolbes Нуб

    убрал одну переменную и результат тоже. задержка при нажатии кнопки так и осталась разная: может 5 сек как планировало а может и 3 и 1.

    Код (C++):
    unsigned long timebutton1; //хранение времени нажатия кнопки
    const byte  led1=9; //pin светодиод
    long interval01 = 5000;


    void setup(){
      Serial.begin(9600);
      pinMode(led1,OUTPUT); //пин как выход
      pinMode(5,INPUT_PULLUP); // пин как вход
    }
    void loop(){
      boolean button1 = !digitalRead(5); // при нажатие кнопки получаем 1
      if (button1 == 1){  //кнопка нажата и удерживается
        Serial.print("timebutton1: ");Serial.println(button1); //смотрим состояние кнопки (1)
      timer01();
      }
      else {
          digitalWrite(led1,0); // если не прошло 5 сек или кнопка отпушена не вкл светодиод
          Serial.print("timebutton1: ");Serial.println(button1); //смотрим состояние кнопки (0)
     
      }
    }

    void timer01() {
     
       
          if (millis() - timebutton1 >= interval01){    //еслим прошло 5 сек после нажатия и удержиния то
              timebutton1 = millis();
              digitalWrite(led1,1); //вкл светодиод
              Serial.print("Светодиод горит: ");Serial.println("ON");
          }
    }
     
     
  13. b707

    b707 Гуру

    Правильно - это давать каждой переменной уникальное имя, чтобы не запутаться. В чем смысл двух одинаковых переменных в вашем коде? С вас что. за каждое имя деньги берут. что ли?:)
     
  14. b707

    b707 Гуру

    Ваша ошибка в том, что для этой задачи не достаточно просто знать, нажата кнопка или нет. Нужно знать прежнее состояние кнопки, чтобы понять, нажали ли ее только что или кнопка нажата давно.Поэтому нужна переменная "прежнее состояние кнопки".
    А дальше все просто -
    - проверяем кнопку, есди кнопка нажата, а до этого она нажата не была - запоминаем текущее время в переменной timebutton1, сохраняем новое состояние кнопки
    - если кнопка нажата и была нажата и раньше - сравниваем значение millis с timebutton1 - если прощло больше 5 сек - зажигаем диод
    - если кнопка отжата - тущим светодиод, обновляем переменную "состояние кнопки"
     
    evgen_bolbes нравится это.
  15. evgen_bolbes

    evgen_bolbes Нуб

    нет денег не берут :) это от незнания:(. ок. выходные переживем и попробую реализовать.
     
  16. evgen_bolbes

    evgen_bolbes Нуб

    сделал как вы написали. подскажите что сделал не так. по нажатию кнопки светодиод просто загорается
    Код (C++):
    unsigned long timebutton1; //хранение времени нажатия кнопки
    unsigned long interval1 = 5000; //задержка в сек
    boolean button1_flag = false; //переключатель состояния кнопки 1
    boolean button1;
    byte  led1=9; //pin светодиод 1



    void setup(){
      Serial.begin(9600);
      pinMode(led1,OUTPUT); //пин светодиод 1
      pinMode(5,INPUT_PULLUP); // пин кнопка 1
    }
    void loop(){
      button1 = !digitalRead(5);
      if (button1 == 1 && button1_flag == false ){  //кнопка нажата
         button1_flag = true; //поднять флаг
         timebutton1=millis(); // записать состояние миллис
        }
    //------------------------------------------------
       if (button1 == 1 && button1_flag == true ) { //кнопка нажата и была нажата
        millis()- timebutton1 >= interval1; //тек.время - врем. нажатия >= 5 сек
        digitalWrite(led1,1); //вкл светодиод
       }
    //-----------------------------------------------
      if (button1 == 0 && button1_flag == true) {   //кнопка не нажата
         button1_flag = false; //опустить флаг
         timebutton1=0; // записать состояние миллис 0
         digitalWrite(led1,0); //выкл светодиод
      }
     
    Serial.print("Состояние кнопки: ");Serial.print(button1);Serial.print(" ");
    Serial.print("Время нажатия кнопки: ");Serial.println(timebutton1);
    }
     
  17. b707

    b707 Гуру

    не надо обнулять время (timebutton1=0) при отпускании кнопки, вместо этого записывайте в него millis
     
  18. evgen_bolbes

    evgen_bolbes Нуб

    Код (C++):
    timebutton1=millis(); // записать состояние миллис 0
    результат тот же:(. по нажатию светодиод сразу загорается. как я понимаю смысл тот же что и в моем коде.
     
  19. akl

    akl Гуру

    формула расчета времени тоже должна быть в условии
    например:
    if (button1 == 1 && button1_flag == true && millis()- timebutton1 >= interval1 ) { //кнопка нажата и была нажата //тек.время - врем. нажатия >= 5 сек
    digitalWrite(led1,1); //вкл светодиод
    }
     
    evgen_bolbes и b707 нравится это.
  20. b707

    b707 Гуру

    akl. верно!