двойное нажатие

Тема в разделе "Схемотехника, компоненты, модули", создана пользователем xace, 11 янв 2014.

  1. xace

    xace Нуб

    Добрый день!

    Подскажите, как реализовать такую схему...

    есть диод ардуина и кнопка.

    При однократном нажатии диод загорается , если еще раз нажать то тухнет.
    При двойном нажатии диод загорается и тухнет через 5 минут (как пример)
    Если однократно нажать на кнопку то он погаснет, вне зависимости как его включили.
     
  2. Unixon

    Unixon Оракул Модератор

    Если второе нажатие произошло менее, чем за X миллисекунд после первого, значит это одно двойное нажатие и нужно установить таймаут, в противном случае это команда на выключение. Запоминаете millis() после каждого нажатия и сравниваете.
     
  3. Tomasina

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

    Как вариант, через обработку состояний:
    Код (Text):
    /*При однократном нажатии диод загорается , если еще раз нажать то тухнет.
    При двойном нажатии диод загорается и тухнет через 5 минут
    Если однократно нажать на кнопку то он погаснет, вне зависимости как его включили.
    Бонус: по удержанию кнопки можно что-то ещё зафигачить :)
    */

    #define BUTTON_PIN 7
    #define LED_PIN 13

    int bounceTime = 10;          // задержка для подавления дребезга
    int holdTime = 300;          // время, в течение которого нажатие можно считать удержанием кнопки
    int doubleTime = 500;        // время, в течение которого нажатия можно считать двойным

    boolean lastReading = false;  // флаг предыдущего состояния кнопки
    boolean buttonSingle = false; // флаг состояния "краткое нажатие"
    boolean buttonDouble = false; // флаг состояния "двойное нажатие"
    boolean buttonHold = false;  // флаг состояния "долгое нажатие"
    boolean ledState = false;    // флаг состояния LED

    long onTime = 0;              // переменная обработки временного интервала
    long lastSwitchTime = 0;      // переменная времени предыдущего переключения состояния
    long ledStartTime = 0;        // переменная-флаг времени начала включения LED
    unsigned long ledTimeout = 300000;      // переменная времени отключения LED, 5 минут = 300 000 мс

    void setup()
    {
      Serial.begin(9600);
      pinMode(9, HIGH);          //! подаем +5В на кнопку - эта строка только для моей схемы, вам не нужно!
      pinMode(BUTTON_PIN, INPUT_PULLUP); // подключаем кнопку через внутренний резистор
      pinMode(LED_PIN, OUTPUT);
      digitalWrite(LED_PIN, ledState);  // принудительно гасим LED
      Serial.println("\nReady...");
    }


    void loop()
    {


      // ================ обработчик состояния кнопки ====================
      boolean reading = !digitalRead(BUTTON_PIN);  // читаем состояние пина кнопки (инвертированное, т.к. подключено через внутренний резистор)
      // проверка первичного нажатия
      if (reading && !lastReading)
      {
        onTime = millis();
      }
      // проверка удержания
      if (reading && lastReading)
      {
        if ((millis() - onTime) > holdTime)
        {
          buttonHold = true;
        }
      }
      // проверка отпускания кнопки
      if (!reading && lastReading)
      {
        if (((millis() - onTime) > bounceTime) && !buttonHold)
        {
          if ((millis() - lastSwitchTime) >= doubleTime)
          {
            lastSwitchTime = millis();
            buttonSingle = true;
          }
          else
          {
            lastSwitchTime = millis();
            buttonDouble = true;
            buttonSingle = false;
            Serial.println("Button: double press");
            isButtonDouble();
            buttonDouble = false;  // сброс состояния после выполнения команды
          }
        }
        if (buttonHold)
        {
          buttonDouble = false;
          Serial.println("Button: hold");
          isButtonHold();
          buttonHold = false;  // сброс состояния после выполнения команды
        }
      }
      lastReading = reading;
      if (buttonSingle && (millis() - lastSwitchTime) > doubleTime)
      {
        buttonDouble = false;
        Serial.println("Button: single press");
        isButtonSingle();
        buttonSingle = false;  // сброс состояния после выполнения команды
      }
      // ================ конец обработчика состояния кнопки ==================

      // ================ обработчик отключения LED по таймауту ===============
      if ((ledStartTime !=0) && (millis() - ledStartTime > ledTimeout))  // если LED включен по даблклику и прошло больше 5 сек
      {
        Serial.println("Timeout");
        ledToggle();        // то гасим LED
        ledStartTime = 0;    // и обнуляем переменную-флаг
      }
      // ================ конец обработчика отключения LED ====================


    } // конец loop


    void isButtonSingle() // действия после одиночного нажатия кнопки
    {
      //При однократном нажатии диод загорается , если еще раз нажать то тухнет.
      //Если однократно нажать на кнопку то он погаснет, вне зависимости как его включили.
      ledToggle();
    }


    void isButtonDouble() // действия после двойного нажатия кнопки
    {
      //При двойном нажатии диод загорается и тухнет через 5 минут
      ledState = true;                    // однозначно включаем LED
      digitalWrite(LED_PIN, ledState);
      ledStartTime = millis();            // начинаем отсчет времени
      Serial.println("LED on. Will turn off after 5 min");
    }


    void isButtonHold() // действия после удержания кнопки
    {
      // здесь код для этого действия
      Serial.println("nothing to do...");
    }


    void ledToggle()    // функция переключения (инвертирования) LED
    {
      ledState = !ledState;
      digitalWrite(LED_PIN, ledState);
      ledState ? Serial.println("LED on"): Serial.println("LED off");
    }
    Действия по событиям вынесены в отдельные функции (isButtonDouble()) - так удобнее.
     
    nedimaon и grx1a нравится это.
  4. Midnight

    Midnight Нерд

    Пожалуйста подскажите как добавить обработку тройное нажатие.
    Добавил переменную boolean buttonThree = false;
    не ясно где именно вставлять дополнительное IF...
     
    Последнее редактирование: 15 июл 2018
  5. Mitrandir

    Mitrandir Гуру

    При первом нажатии запомнить текущее время
    При нажатии на кнопку увеличивается счётчик нажатий.

    Как пройдет n миллисекунд после первого нажатия, взять из счётчика количество нажатий
     
  6. Midnight

    Midnight Нерд

    переменная счетчика нажатий? три нажатия не обрабатывается, сичтает как двойное + одно одинарное

    boolean reading = !digitalRead(BUTTON_PIN); // читаем состояние пина кнопки (инвертированное, т.к. подключено через внутренний резистор)
    // проверка первичного нажатия
    if (reading && !lastReading)
    {
    onTime = millis();
    Serial.println(onTime);
    }
    // проверка удержания
    if (reading && lastReading)
    {
    if ((millis() - onTime) > holdTime)
    {
    buttonHold = true;
    }
    }


    добавил печать в serial текущее значение millis - ни как третье нажатие не проходит
     
  7. Midnight

    Midnight Нерд

    Делаю "стоп-сигнал" для велосипеда. Arduino Pro mini + 32шт WS2812B + 1 Button. Стоп + поворот на лево, на право + габаритный стоп для темного времени. По завершении проекта подробное описание и фото выложу сюда)

    Соотвественно:
    одно нажатие (либо любое непонятное) - режим стоп (продолжает светится 5 - 10 сек)
    двойное нажатие - мигает 20 сек поворот на лево
    тройное нажатие - мигает 20 сек поворот на право
    зажатие более 3 сек - включается 10 центральных светодиодов до следующего зажатие на 3 сек.

    П.С. Изначально планировалась "умная фара" на mpu 6050 с автоматическим определением торможения - (отрицательное ускорение) Но точность показаний не позволило создать нормально работующую модель. Было принято поместить на руль кнопку...
     
    Последнее редактирование: 15 июл 2018
  8. revolover

    revolover Гик

    нужно по магниту на каждую спицу! И будет точность.
    А вообще изврат(... недонажалась кнопка и не тот поворотник. Лучше тогда морзянку отстукивать, вдруг сзади какраз моряк едет - поймет.)))
    И наверняка в ширину поворотники не разнесете. А с Рас
    Я поворот рукой показываю - надежнее.
     
  9. Midnight

    Midnight Нерд

    Естественно это не для "неожиданностей" - тормоза никто не отменял. Это скорее для планового поворота и т.п.... Магнит на каждую спицу - это точно изврат, как было описано - хотелось обойтись "современными многофункциональными устройствами" не вышло, но бог с ним на ближайшие лет 5)))

    а разнести в ширину - свободно возможно, по рулю, только заказать соответсвующие 3-D пластмасски (рассеиватели), но я просил подсказать не об этом...
     
  10. a1000

    a1000 Гуру

    Какой-то сложный алгоритм взаимодействия - двойное, тройное нажатие. Всё как-то не очевидно и легко запутаться. Я бы сделал по другому, поставил бы по кнопке на каждую рукоятку. Алгоритм взаимодействия сделал-бы следующий:
    - нажал левую кнопку - левый поворот;
    - нажал правую кнопку - правый поворот;
    - нажал обе - стоп.
    Так очевиднее для пользователя, да и реализация проще.
     
    Mitrandir нравится это.
  11. Midnight

    Midnight Нерд

    одни доброжелатели...
    вместо реальной помощи
     
  12. ostrov

    ostrov Гуру

    За реальной помощью сюда.
     
  13. a1000

    a1000 Гуру

    Вы не обижайтесь, вам реально хотят помочь. Прежде чем писать код надо отчётливо представлять, что хотите получить в финале. Взаимодействие пользователя с конечным продуктом должно быть удобным и понятным. Если сама идея не совсем удачная, то какой "золотой" код не напиши, устройство будет неудачным. Я понимаю, что у вас уже сложилась в голове готовая идея, но прислушайтесь к советам по самой концепции изделия. На мой взгляд они имеют право на жизнь.
     
    Tomasina и Mitrandir нравится это.
  14. Midnight

    Midnight Нерд

    Я согласен что любая идея имеет право на существование и на реализацию, и вопрос состоял совсем не об устройстве, более того - я абсолютно уверен, что "Тройной клик" найдет массу возможностей для реализации не только у меня... Переделывать что либо на мой лад я не просил, обещал для возможного рассмотрения и принятия решения о повторении выложить отдельной темой... с двумя кнопками - все круто (со стороны электрики и программы), НО если на секунду задуматься - как закрепить кнопки на руле, какие взять кнопки. Не испортить вид и не ограничить движения.... Вы должны понимать что таких готовых кнопок НЕТ. В моем случае есть ГОТОВАЯ кнопка от велофары Fenix BC-30 в количестве ОДНА штука.

    Если бы интересовала сама концепция - то должна была заинтересовать фраза "УМНАЯ ФАРА" - вот тут бы любая критика была бы уместна...

    И на последок, если Вы не веломан - просто поинтересуйтесь, что наш великий технический прогресс предлагает на уровне КУПИ - кнопка на корпусе + 5 светодиодов?
     
  15. Midnight

    Midnight Нерд

    К примеру ВСЕ обычное можно сделать с душой:
    Слева (в низу) 10 * 17 WS2812 и справа многообожаемая качественная LED гирлянда на 4 цвета и 200 светодиодов...

     
    Последнее редактирование: 16 июл 2018
  16. a1000

    a1000 Гуру

    Прежде чем приступить к реализации, необходимо выяснить нужно ли это в принципе. По крайней мере я так стараюсь делать. Идея "умной фары" хорошая и нужная, но вот с концепцией управления беда. Велосипедисту нужно постоянно держать в голове все комбинации.нажатий на кнопки. Даже на мой взгляд не веломана это крайне не удобно. Управление двумя кнопками осуществляется на уровне подсознания и не будет отвлекать велосипедиста. В отсутствие готовых кнопок для крепления на руль не очень верится. Существует куча приборов и устройств для велосипедов, скутеров, мопедов элементы управления которыми выносятся на руль. И оно всё ломается и по этому должны быть в продаже запчасти. В крайнем случае пристройте под рукоятки руля тензодатчики и управляйте усилием сжатия. Но это всё моё личное мнение и я не претендую на истину в последней инстанции.
    А на счёт готовых изделий - если-бы то что предлагает . " великий технический прогресс" устраивало всех сразу из коробки, такие форумы как этот вымерли-бы как явление. Их тоже люди делают, и не факт что они умнее нас и хорошо знают проблему.
     
  17. Midnight

    Midnight Нерд

    Вы описали совсем не УМНУЮ фару, а мои изощрения после неудавшейся попытки реализовать таковую. Там планировалось убрать вовсе любое управление человеком. (MPU6050)

    П.С. - НИКТО не парится с одинарным кликом, двойным кликом, зажатием и еще умножаем эти все умения на две - три кнопки (а некоторым и 10 кнопок не мешает) Столько комбинаций и все у КАЖДОГО в голове!!!! мышь компьютерная....
     
    Последнее редактирование: 19 июл 2018
  18. ArcadePUB

    ArcadePUB Нуб

    Добрый день. Наверное, уже не актуально, но добавлю свои 5 копеек. Может кому пригодится по поиску.
    Скетч для мультиклика. Более подробные комментарии написал на сайте. + возможность удержания кнопки и разные функции от времени удержания. arcadepub.ru/кнопка/

    Код (C++):

    #define BUTTON_PIN 2

    int bounceTime = 10;          // задержка для подавления дребезга
    int doubleTime = 500;         // время, в течение которого нажатия можно считать двойным
    int i = 0;

    boolean lastReading = false;  // флаг предыдущего состояния кнопки
    boolean buttonSingle = false; // флаг состояния "краткое нажатие"
    boolean buttonMulti = false; // флаг состояния "двойное нажатие"

    long onTime = 0;              // переменная обработки временного интервала
    long lastSwitchTime = 0;      // переменная времени предыдущего переключения состояния

    void setup(){
      Serial.begin(9600);
    }

    void loop(){
      boolean reading = digitalRead(BUTTON_PIN);

      // проверка первичного нажатия
      if (reading && !lastReading){
        onTime = millis();
      }
     
      if (!reading && lastReading){
        if (((millis() - onTime) > bounceTime)){
          if ((millis() - lastSwitchTime) >= doubleTime){
            lastSwitchTime = millis();
            buttonSingle = true;
            i=1;
          } else {
            i++;
            lastSwitchTime = millis();
            buttonSingle = false;
            buttonMulti = true;
          }
        }
      }
     
      lastReading = reading;
     
      if (buttonSingle && (millis() - lastSwitchTime) > doubleTime){
        isButtonSingle();
      }
      if (buttonMulti && (millis() - lastSwitchTime) > doubleTime){
        isButtonMulti(i);
      }
    }

    void isButtonSingle(){
        buttonMulti = false;
        buttonSingle = false;
        Serial.println(1);
    }
    void isButtonMulti( int count ){
        buttonSingle = false;
        buttonMulti = false;
        Serial.println(count);
    }
     
     
  19. Tomasina

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

    Узнаю свой стиль именования и оформления :D
     
  20. ArcadePUB

    ArcadePUB Нуб

    Добрый день. Да, переписывал ваш код сверху.