Посчитать время нажатия кнопки

Тема в разделе "Arduino & Shields", создана пользователем alexey.s, 22 мар 2014.

  1. alexey.s

    alexey.s Нуб

    Всем доброго времени суток.
    Перерыл весь интернет, не могу найти нужный алгоритм подсчета времени нажатия на кнопку.
    По простому нажатию кнопки нужно включать 3 светодиода в режиме Р, а если зажать кнопку на 3 и более секунд - перейти в меню выбора этого режима и последовательными нажатиями на ту же кнопку переключать его. Если состояние кнопки в режиме меню LOW втечении 3 сек - выход из меню.
    Собственно мой код, помогите со входом в меню пожалуйста? Как сделать условие, "если кнопка зажата 3 сек?

    #include <Bounce.h>
    #define KEY 2 //дефайним значения пинов с кнопкой и со светодиодом
    #define LED_1 8 //дефайним значения пинов с кнопкой и со светодиодом
    #define LED_2 7 //дефайним значения пинов с кнопкой и со светодиодом
    #define LED_3 6 //дефайним значения пинов с кнопкой и со светодиодом

    Bounce bouncer = Bounce(KEY,10); //создаем объект класса Bounce. Указываем пин, к которому подключена кнопка, и время дребезга в мс.
    int state = LOW; //задаем начальное состояние всех светодиодов "выключен"
    int mode = 1; //задаем начальный режим работы светодиодов

    void setup() {
    pinMode(KEY,INPUT); //определяем режимы работы пинов
    pinMode(LED_1,OUTPUT); //определяем режимы работы пинов
    pinMode(LED_2,OUTPUT); //определяем режимы работы пинов
    pinMode(LED_3,OUTPUT); //определяем режимы работы пинов
    }

    void loop() {
    if ( bouncer.update() ) { //если сменилось состояние кнопки
    if ( bouncer.read() == HIGH) { //если считано значение 1
    if ( state == LOW ) { //если свет был выключен
    state = HIGH; // будем его включать
    }
    else { // если свет был включен
    state = LOW; // будем выключать
    }
    }
    }
    if (state == HIGH) { // если свет включен
    switch (mode){
    case 1: // Если значение mode равно 1
    digitalWrite (LED_1, HIGH); // Включаем светодиод
    digitalWrite (LED_2, HIGH); // Включаем светодиод
    digitalWrite (LED_3, HIGH); // Включаем светодиод
    break; // Выходим из свитч
    case 2: // Если значение mode равно 2
    digitalWrite (LED_1, HIGH); // Включаем светодиод
    digitalWrite (LED_2, HIGH); // Выключаем светодиод
    digitalWrite (LED_3, LOW); // Выключаем светодиод
    break; // Выходим из свитч
    case 3: // Если значение mode равно 3
    digitalWrite (LED_1, HIGH); // Включаем светодиод
    digitalWrite (LED_2, LOW); // Выключаем светодиод
    digitalWrite (LED_3, LOW); // Выключаем светодиод
    break; // Выходим из свитч
    case 4: // Если значение mode равно 4
    digitalWrite (LED_1, LOW); // Выключаем светодиод
    digitalWrite (LED_2, HIGH); // Включаем светодиод
    digitalWrite (LED_3, LOW); // Выключаем светодиод
    break; // Выходим из свитч
    case 5: // Если значение mode равно 5
    digitalWrite (LED_1, LOW); // Выключаем светодиод
    digitalWrite (LED_2, LOW); // Выключаем светодиод
    digitalWrite (LED_3, HIGH); // Включаем светодиод
    break; // Выходим из свитч
    case 6: // Если значение mode равно 6
    digitalWrite (LED_1, LOW); // Выключаем светодиод
    digitalWrite (LED_2, HIGH); // Включаем светодиод
    digitalWrite (LED_3, HIGH); // Включаем светодиод
    break;
    case 7: // Если значение mode равно 7
    digitalWrite (LED_1, HIGH); // Включаем светодиод
    digitalWrite (LED_2, LOW); // Выключаем светодиод
    digitalWrite (LED_3, HIGH); // Включаем светодиод
    break;
    }
    }else { // если свет выключен
    digitalWrite (LED_1, LOW); // Выключаем светодиод
    digitalWrite (LED_2, LOW); // Выключаем светодиод
    digitalWrite (LED_3, LOW); // Выключаем светодиод
    }
    }
     
  2. pulseIn();
    в помощь.
     
  3. alexey.s

    alexey.s Нуб

    Я просил не ссылку на описание операторов, нужна помощь в построении самого алгоритма.
     
  4. Megakoteyka

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

    Запоминайте момент, в который произошло изменение состояния кнопки. Также храните момент предыдущего изменения состояния. Анализируйте разность времен смены состояний и в зависимости от результата переключайте режим либо выполняйте логику конкретного режима.
    В логике второго режима проверяйте разность текущего времени и времени входа в режим. Если больше трех секунд - переключайте режим обратно.
     
    alexey.s нравится это.
  5. alexey.s

    alexey.s Нуб

    Спасибо, примерно так и сделал, теперь проблема, как ни странно, выключить свет по кратковременному нажатию. Программа сбивает счетчик и не может понять долго ли я держу кнопку или просто хочу выключить свет. Куда копать, чтобы избавиться от граблей? Мой обновленный скетч без функции выключения света:


    #include <Bounce.h>
    #define DEBUG
    #ifdef DEBUG
    #define DEBUG_PRINT(x) Serial.print(x)
    #define DEBUG_PRINTLN(x) Serial.println(x)
    #else
    #define DEBUG_PRINT(x)
    #define DEBUG_PRINTLN(x)
    #endif
    #define KEY 9 //дефайним значения пинов с кнопкой и со светодиодом
    #define LED_1 8 //дефайним значения пинов с кнопкой и со светодиодом
    #define LED_2 7 //дефайним значения пинов с кнопкой и со светодиодом
    #define LED_3 6 //дефайним значения пинов с кнопкой и со светодиодом

    Bounce bouncer = Bounce(KEY,40); //создаем объект класса Bounce. Указываем пин, к которому подключена кнопка, и время дребезга в мс.
    boolean state = 0; //задаем начальное состояние всех светодиодов "выключен"
    int mode = 1; // задаем начальный режим работы светодиодов
    int push = 0; // задаем время нажатия на кнопку в мс
    int unpush = 0; // время простоя кнопки
    boolean setupON = 0; // задаем начальное состояние переменной активации режима настройки
    unsigned long push_p = 0; // переменная хранящая промежуточное значение времени нажатия
    unsigned long unpush_p = 0;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////////////////

    void setup() {
    Serial.begin(9600); // включаем сериал порт на скорости 9600
    pinMode(KEY,INPUT); //определяем режимы работы пинов
    pinMode(LED_1,OUTPUT); //определяем режимы работы пинов
    pinMode(LED_2,OUTPUT); //определяем режимы работы пинов
    pinMode(LED_3,OUTPUT); //определяем режимы работы пинов
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////////////////

    void loop() {
    #ifdef DEBUG
    #endif
    DEBUG_PRINTLN(state);
    bouncer.update(); //обновить состояние кнопки
    boolean switchstate = bouncer.read(); //создаем переменную и считываем в нее состояние кнопки
    if (switchstate == 1 && state == 0){ // Если кнопка нажата и свет выключен
    state = 1; // включаем свет
    }
    timepush(switchstate); // считаем нажатие на кнопку и если оно больше 3 секунд - переключаем режим настройки света
    if (setupON = 1) { // если режим настройки света активирован
    SetMode(switchstate); // переходим в режим настройки
    time_unpush(switchstate); // считаем время простоя кнопки и если оно больше 5 сек. выходим из режима настройки
    }
    if (state == 1){ // если свет включен
    LED_ON(); // зажигаем светодиоды в соответствии с режимом
    }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////////////////

    void timepush(boolean switchstate) { // счетчик нажатия кнопки
    if (switchstate == 1 && state ==1){ //если кнопка нажата и свет включен
    if ((millis() - push_p) >= 1000) { // если разница общего времени работы и промежуточным числом больше или равно 1 сек.
    push++; // счетчик времени нажатия увеличиваем на 1 (сек)
    push_p = millis(); // обновляем значение временного числа
    }
    } else {
    push_p = 0;
    push = 0;
    }
    if (push >= 4){ // если счетчик отсчитал 3 секунды
    setupON = 1; // активируем режим настройки
    }
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////////////////

    void time_unpush (boolean switchstate){ // счетчик не нажатой кнопки
    if (switchstate == 0 && state ==1){ //если кнопка не нажата и свет включен
    if ((millis() - unpush_p) >= 1000) { // если разница общего времени работы и промежуточным числом больше или равно 1 сек.
    unpush++; // счетчик времени простоя увеличиваем на 1 (сек)
    unpush_p = millis(); // обновляем значение временного числа
    }
    } else {
    unpush_p = 0;
    unpush = 0;
    }
    if (unpush >= 6){ // если счетчик отсчитал 5 секунд
    setupON = 0; // выходим из режима настройки
    }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////////////////

    void SetMode(boolean switchstate) { // Выбор режима света
    if (switchstate == 1) { // если кнопка нажата
    if (mode <= 6){ // если выбираемый режим меньше или равен 6
    mode++; // режим увеличиваем на 1
    } else { // иначе
    mode = 1; // выбираем первый режим
    }
    }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////

    void LED_ON(){ // функция переключения режимов
    switch (mode){ // Выбираем режим
    case 1: // Если значение mode равно 1
    digitalWrite (LED_1, HIGH); // Включаем светодиод 1
    digitalWrite (LED_2, HIGH); // Включаем светодиод 2
    digitalWrite (LED_3, HIGH); // Включаем светодиод 3
    break; // Выходим из свитч
    case 2: // Если значение mode равно 2
    digitalWrite (LED_1, HIGH); // Включаем светодиод 1
    digitalWrite (LED_2, HIGH); // Выключаем светодиод 2
    digitalWrite (LED_3, LOW); // Выключаем светодиод 3
    break; // Выходим из свитч
    case 3: // Если значение mode равно 3
    digitalWrite (LED_1, HIGH); // Включаем светодиод 1
    digitalWrite (LED_2, LOW); // Выключаем светодиод 2
    digitalWrite (LED_3, LOW); // Выключаем светодиод 3
    break; // Выходим из свитч
    case 4: // Если значение mode равно 4
    digitalWrite (LED_1, LOW); // Выключаем светодиод 1
    digitalWrite (LED_2, HIGH); // Включаем светодиод 2
    digitalWrite (LED_3, LOW); // Выключаем светодиод 3
    break; // Выходим из свитч
    case 5: // Если значение mode равно 5
    digitalWrite (LED_1, LOW); // Выключаем светодиод 1
    digitalWrite (LED_2, LOW); // Выключаем светодиод 2
    digitalWrite (LED_3, HIGH); // Включаем светодиод 3
    break; // Выходим из свитч
    case 6: // Если значение mode равно 6
    digitalWrite (LED_1, LOW); // Выключаем светодиод 1
    digitalWrite (LED_2, HIGH); // Включаем светодиод 2
    digitalWrite (LED_3, HIGH); // Включаем светодиод 3
    break; // Выходим из свитч
    case 7: // Если значение mode равно 7
    digitalWrite (LED_1, HIGH); // Включаем светодиод 1
    digitalWrite (LED_2, LOW); // Выключаем светодиод 2
    digitalWrite (LED_3, HIGH); // Включаем светодиод 3
    break;
    }
    }