[Решено] Ложные срабатывания кнопки. Помогите новичку разобраться.

Тема в разделе "Arduino & Shields", создана пользователем PND, 23 фев 2017.

  1. PND

    PND Нуб

    Всем привет. Начал разбираться с Ардуино и даже помигать светодиодом не смог... Помогите понять в чём проблема?

    Имеется:
    Ардуино Нано Atmega328P.
    Светодиод с резистором.
    4х позиционный переключатель.

    Задача. Сделать 3 режима мигания светодиода. В каждом режиме должна настраиваться частота мигания часы/минуты/секунды. Физический переключатель переключает режимы ВЫКЛ /1 режим / 2 режим / 3 режим.
    1.JPG

    Переключатель стоит между 12 пином и 3, 4, 5. Выключатель работает нормально, я его прозванивал.

    А проблема вот в чём. Подключаю всё на макетке, переключаю режимы, контролирую по монитору. Режимы отрабатывают нормально, переключатся и пишут забитое время, вроде всё ок. Но иногда, когда оставляешь всё в покое и ничего не трогаешь, начинается рандомная активация режимов. Например всё отключено, что подтверждает сообщение в мониторе порта и вдруг активируется 2ой режим, потом первый и секунд 10-15 остаётся активным. Выключатель из схемы вообще иногда вытаскивал, а ардуина всё равно переключала режимы сама. Потом вроде успокоится и всё опять работает нормально. А иногда вообще переключатель игнорит и сама режимы меняет - закономерность не смог понять и вообще почему это происходит. Хотел уже скетч с 0 переписать заново, но стало интересно, от чего такое происходит?

    Скетч.

    Код (C++):

    #define PINMODE_1 3
    #define PINMODE_2 4
    #define PINMODE_3 5
    #define light 1000
    long previousTimer = 0;

    void setup() {
      pinMode(2, OUTPUT);
      pinMode(PINMODE_1, INPUT);
      pinMode(PINMODE_2, INPUT);
      pinMode(PINMODE_3, INPUT);
      pinMode(6, OUTPUT);
      pinMode(7, OUTPUT);
      pinMode(8, OUTPUT);
      pinMode(12, OUTPUT);
      Serial.begin(9600);
    }

    void loop() {
      digitalWrite(12, HIGH);


    if (digitalRead(PINMODE_1))                                                  // 1 режим работы
    {
      byte hour1 = 0;                                                            //Выставляем интервал режима 1 в часах.
      byte minute1 = 0;                                                          //Выставляем интервал режима 1 в минут.
      byte second1 = 1;                                                          //Выставляем интервал режима 1 в секундах.
      int mode_1 = hour1*(60000*2)+minute1*60000+second1*1000;
     
      unsigned long currentTimer = millis();
      long interval = mode_1;
      if(currentTimer - previousTimer > interval)
      {
        previousTimer = currentTimer;
        digitalWrite(6, HIGH);  
        delay(light);                                                           //Время отработки мигания.
        digitalWrite(6, LOW);
      }
     
      Serial.print("1 mode is chosen ");
      Serial.print(hour1);
      Serial.print(":");
      Serial.print(minute1);
      Serial.print(":");
      Serial.println(second1);
      delay(1000);
    }

    else if (digitalRead(PINMODE_2))                                             // 2 режим работы
    {
      byte hour2 = 0;                                                            //Выставляем интервал режима 2 в часах.
      byte minute2 = 0;                                                          //Выставляем интервал режима 2 в минут.
      byte second2 = 2;                                                          //Выставляем интервал режима 2 в секундах.
      int mode_2 = hour2*(60000*2)+minute2*60000+second2*1000;
     
      unsigned long currentTimer = millis();
      long interval = mode_2;
      if(currentTimer - previousTimer > interval)
      {
        previousTimer = currentTimer;
        digitalWrite(7, HIGH);  
        delay(light);                                                           //Время отработки мигания.
        digitalWrite(7, LOW);
      }
     
      Serial.print("2 mode is chosen ");
      Serial.print(hour2);
      Serial.print(":");
      Serial.print(minute2);
      Serial.print(":");
      Serial.println(second2);
      delay(1000);
    }

    else if (digitalRead(PINMODE_3))                                             // 3 режим работы
    {
      byte hour3 = 0;                                                            //Выставляем интервал режима 3 в часах.
      byte minute3 = 0;                                                          //Выставляем интервал режима 3 в минут.
      byte second3 = 3;                                                          //Выставляем интервал режима 3 в секундах.
      int mode_3 = hour3*(60000*2)+minute3*60000+second3*1000;
     
      unsigned long currentTimer = millis();
      long interval = mode_3;
      if(currentTimer - previousTimer > interval)
      {
        previousTimer = currentTimer;
        digitalWrite(8, HIGH);  
        delay(light);                                                           //Время отработки мигания.
        digitalWrite(8, LOW);
      }
     
      Serial.print("3 mode is chosen ");
      Serial.print(hour3);
      Serial.print(":");
      Serial.print(minute3);
      Serial.print(":");
      Serial.println(second3);
      delay(1000);
    }
    else
    {
      digitalWrite(2,LOW);
      Serial.println("OFF");
      delay(1000);
    }

         
    }
    Прошу отнестись с пониманием если ерунду спрашиваю. С Ардуиной первый раз встречаюсь.
     
  2. mcureenab

    mcureenab Гуру

    Висячие контакты помехи ловят. Их нужно подтянуть к питанию (режим INPUT_PULLUP) или резистором примерно на 40 - 50 кОм к 0.

    В первом случае замыкать на 0 и принимать LOW, во втором случае замыкать на Vcc и принимать HIGH
     
    PND и arkadyf нравится это.
  3. Karabas

    Karabas Гик

    Все очень просто, неподключенные выводы висят в воздухе и как антенны ловят наводки, и Ардуина воспринимает их как сигналы.
    Что делать, ну во первых, освободить 12 пин и заменить его на плюс, а к 1, 2, и 3 подключить резисторы 10-20кОм и на землю. Таким образом, когда ничего не подключенно, на них будет минус (через резистор).
     
    PND и arkadyf нравится это.
  4. ZAZ-965

    ZAZ-965 Гуру

    У вас входы D3-D5 включены без подтяжки, поэтому реагируют на наводки и помехи.
    Код (C++):
      pinMode(PINMODE_1, INPUT_PULLUP); //включаем подтяжку
      pinMode(PINMODE_2, INPUT_PULLUP);
      pinMode(PINMODE_3, INPUT_PULLUP);
    Вместо использования D12 контакт переключателя подключить к земле и считывать нулевой уровень
    Код (C++):
    if (!digitalRead(PINMODE_1))
     
    MESS, PND и arkadyf нравится это.
  5. PND

    PND Нуб

    Спасибо за ответы!
    Кстати в коде я вывод на 3 светодиода делал - это у же в процессе испытаний делал наглядную индикацию - без компа.

    Я пробовал резиторы к 0 прокидывать, но видимо слишком маленькие...

    Попробую
    Код (C++):
    pinMode(PINMODE_1, INPUT_PULLUP); //включаем подтяжку
      pinMode(PINMODE_2, INPUT_PULLUP);
      pinMode(PINMODE_3, INPUT_PULLUP);
    И позже 12й контакт я на + заменил уже =)
     
  6. PND

    PND Нуб

    Потестил! Спасибо! Я в правильную сторону думал, но не до конца!

    Я пробовал INPUT_PULLUP, но подавал + на переключатель, а надо было "-"...
    И пробовал ставить резисторы между выводом и 0, а надо было к "+"...

    Резисторов нужных под рукой нет, сделал, как посоветовал ZAZ-965, вроде работает стабильно! Спасибо!

    Я читал, что подтягивающие резисторы лучше всё таки внешние использовать, позже, как прийдут заменю на внешние. Ещё раз спасибо!
     
  7. mcureenab

    mcureenab Гуру

    С чего бы это? Меньше деталей, надёжнее схема. Только нужно учитывать, что разомкнутая кнопка дает уровень HIGH, и замыкать её надо на 0, и ловить LOW.

    Еще бывает на кнопку фильтр вешают. Но у вас логика скетча не чувствительна к дребезгу. Можно без обвязки обойтись.
     
    PND и arkadyf нравится это.
  8. yden

    yden Гик

    Можно вклиниться.
    Поясните, плиз.
    Я для кнопок использовал библиотеку Bounce.h. Проверяю HIGH уровень.
    Код (C++):
    if ( bouncer1.read() == HIGH)
    Мне нужно изменить схему подключения кнопки и код? Цель - убрать ложные срабатывания.

    Благодарю.