Работа кнопок

Тема в разделе "Arduino & Shields", создана пользователем Defender, 14 июл 2015.

  1. Defender

    Defender Нерд

    Здравствуйте. Столкнулся с такой задачей.
    Есть две кнопки: Пуск и Стоп.
    Нажатие на кнопку Пуск приводит к последовательному включению 4 механизмов с задержкой в 5 секунд. Кнопка Стоп выключает эти механизмы, но только после того как они все включатся.
    Вопрос в том как сделать так чтобы прервать процесс включения механизмов кнопкой Стоп?
    Код (Text):
    #define BUTTON_ONE 4    // Пуск
    #define BUTTON_TWO 2    // Стоп
    #define KM_ONE 5
    #define KM_TWO 6
    #define KM_THREE 9
    #define ZVONOK 3

    void setup()
    {
        pinMode(BUTTON_ONE, INPUT_PULLUP);
        pinMode(BUTTON_TWO, INPUT_PULLUP);
        pinMode(KM_ONE, OUTPUT);
        pinMode(KM_TWO, OUTPUT);
        pinMode(KM_THREE, OUTPUT);
        pinMode(ZVONOK, OUTPUT);
    }

    void loop()
    {
    boolean keyPUSK = digitalRead(BUTTON_ONE);
    boolean keySTOP = digitalRead(BUTTON_TWO);

      if (!keyPUSK)
        {
        digitalWrite(ZVONOK, HIGH);
        delay(5000);
        digitalWrite(ZVONOK, LOW);
        digitalWrite(KM_ONE, HIGH);
        delay(5000);
        digitalWrite(KM_TWO, HIGH);
        delay(5000);
        digitalWrite(KM_THREE, HIGH);
        }

        if (!keySTOP)
        {
        digitalWrite(KM_ONE, LOW);
        digitalWrite(KM_TWO, LOW);
        digitalWrite(KM_THREE, LOW);
        }
    }
     
    Последнее редактирование: 21 июл 2015
  2. Megakoteyka

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

    Не используйте delay, делайте задержку при помощи millis. На форуме десятки обсуждений на эту тему, поищите.
     
    Defender нравится это.
  3. Defender

    Defender Нерд

    Спасибо. На форуме искал, но чёткого ответа так и не нашёл. Понял что дело связано с прерываниями. Сделал прерывание. Теперь кнопка Стоп выключает включение механизмов, но они вновь включаются, так как у меня используется delay().
    С millis() в интернете я нашёл такой пример:

    Код (Text):
    /* Мигание LED Версия 2
    * ------------------------* Включает и выключает светодиод (LED) подсоединенный  * к выходу 13, с интервалом в 2 секунды используя функцию millis()**/
    int ledPin = 13;  // LED подсоединен к выводу 13
    unsigned long currentTime;
    unsigned long loopTime;

    void setup()
    {
    pinMode(ledPin, OUTPUT);  // устанавливаем вывод 13 как выходcurrentTime = millis();  // считываем время, прошедшее с момента запуска программы
    loopTime = currentTime;
    }

    void loop()
    {
    currentTime = millis();  // считываем время, прошедшее с момента запуска программы
    if(currentTime >= (loopTime + 1000)){  // сравниваем текущий таймер с переменной loopTime + 1 секунда
    digitalWrite(ledPin, !digitalRead(ledPin));  // включаем/выключаем LED
    loopTime = currentTime;  // в loopTime записываем новое значение
    }
    // Здесь могут быть другие команды
    }
    Всё вроде бы понятно, но здесь один светодиод. А как сделать запуск с помощью millis() поочерёдно нескольких устройств? Через несколько операторов if не получается.
     
    Последнее редактирование: 21 июл 2015
  4. DrProg

    DrProg Вечный нерд

    Почему не получается? Заводите несколько переменных long int, вначале програамы присваеваете им значение миллис. В лупе несколько if сравнивающих миллис с этими переменными и заданными интервалами. Главное в конце процедуры снова присвоить переменной текущее значение миллис для ожидания следующего вызова.
     
    Defender нравится это.
  5. Megakoteyka

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

    По кнопке пуск ставьте флаг. При установленном флаге пускай вызывается код, который будет при помощи millis отмерять интервалы. В конце каждого интервала прибавляете счетчик и включаете устройство в соответствии с номером счетчика. Когда все устройства будут включены, снимаете флаг. При нажатии кнопки стоп выключаете все устройства и снимаете флаг.
     
    Defender нравится это.
  6. Defender

    Defender Нерд

    Последний нубский вопрос, что такое флаг? В этой теме:
    http://forum.amperka.ru/threads/Авто-полив-растений-с-датчиком-влажности.4930/page-2#post-39355
    вы показываете пример с этими флагами, но я никак не пойму как сама помпа в этом примере завязана с pumpWork? Как она у Вас включается без привязки к какому либо пину?
     
  7. DrProg

    DrProg Вечный нерд

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

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

    Флаг может принимать только 2 значения - "флаг поднят" и "флаг опущен". Если значений больше, то называть флагом такую переменную неверно.
     
  9. Megakoteyka

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

    В той теме показан принцип построения алгоритма, не более того. Предполагается, что в функциях startPump и stopPump будет прописан код, включающий и выключающий помпу.
     
  10. DrProg

    DrProg Вечный нерд

    Разноцветный флаг. )
    Я считал, что любая переменная хранящая один из нескольких возможных значений может считаться флагом. Например переключатель. Хотя, возможно, что то частный случай чего то.
     
  11. Megakoteyka

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

    Когда состояний много, лучше использовать перечисление.
    Код (Text):
    enum EState {
      State_1,
      State_2,
      State_3
    };

    EState state = State_1;

    void loop() {
      switch(state)
      {
        case State_1:
          state = State_2;
          break;

        case State_2:
          state = State_3;
          break;

        case State_3:
          state = State_1;
          break;
      }
    }
    Так код становится более читаемым, а программисту легче не допустить ошибку.
     
  12. DrProg

    DrProg Вечный нерд

    Это понятно, но иногда удобно использовать счетчик-переключатель. Сходу примеров не приведу, но случаи были.
     
  13. Megakoteyka

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

    Из любого правила бывают исключения, куда ж без этого.
     
  14. Defender

    Defender Нерд

    Вроде бы с горем пополам разобрался. Программа такова что есть 3 механизма и звонок.
    Нажимаю кнопку Пуск, сразу звенит звонок, через 5 секунд он выключается и поочередно с интервалом в 5 секунд включаются три механизма. Кнопка Стоп отключает все механизмы сразу. И есть ещё кнопка Рабочий стоп, которая отключает сразу один из механизмов, а потом поочередно два оставшихся с интервалом в 5 секунд.
    Всё вроде бы работает, НО если нажать кнопку Пуск первый раз и потом отключить всё по кнопке Рабочий стоп, а потом опять нажать кнопку Пуск второй раз, то первый (KM_THREE) и второй (KM_TWO) механизмы получают неполное питание. Собирал эту схему вначале на одном стенде, там вместо механизмов используются вентиляторы. И первый и второй вентиляторы явно на глаз видно, что медленее вращаются. Потом собрал на другой плате эмулируя всё на светодиодах, потому что грешил на наводки, но светодиоды тоже светят тусклее ... Получается косяк в программе. Подскажите, пожалуйста, что не так?
    Код (Text):
    #define BUTTON_ONE 4    // Пуск
    #define BUTTON_TWO 2    // Стоп
    #define BUTTON_THREE 1  // Рабочий стоп
    #define KM_ONE 5    // Третий механизм
    #define KM_TWO 6    // Второй механизм
    #define KM_THREE 9  // Первый механизм
    #define ZVONOK 3    // Звонок
    long prev_time_1 = 5000; // Таймер задержки 1 на запуск
    long prev_time_2 = 5000; // Таймер задержки 2 на запуск
    long prev_time_3 = 5000; // Таймер задержки 3 на запуск
    long prev_time_4 = 5000; // Таймер задержки 4 на рабочий стоп
    long prev_time_5 = 5000; // Таймер задержки 5 на рабочий стоп
    long startTime;    // время нажатия на кнопку Пуск
    long startTime_1;  // время нажатия на кнопку Рабочий стоп
    long currentTime;  // время работы технологического процесса
    boolean keyPuskUp = false;  // Флаг "нажата ли кнопка Пуск"
    boolean keyWorkStopUp = false;  // Флаг "нажата ли кнопка Рабочий стоп"
    long time_1;  // время включения KM_ONE
    long time_2;  // время включения KM_TWO
    long time_3;  // время включения KM_THREE
    long time_4;  // время выключения KM_THREE
    long time_5;

    void setup()
    {
        pinMode(BUTTON_ONE, INPUT_PULLUP);  // объявляем кнопку Пуск с подтяжкой
        pinMode(BUTTON_TWO, INPUT_PULLUP);  // объявляем кнопку Стоп с подтяжкой
        pinMode(BUTTON_THREE, INPUT_PULLUP);  // объявляем кнопку Рабочий стоп с подтяжкой
        pinMode(KM_ONE, OUTPUT);  // объявляем пин для третьего механизма
        pinMode(KM_TWO, OUTPUT);  // объявляем пин для второго механизма
        pinMode(KM_THREE, OUTPUT); // объявляем пин для третьего механизма
        pinMode(ZVONOK, OUTPUT);  // объявляем пин для звонка
    }

    void loop()
    {
    currentTime = millis();  // записываем время начала выполнения программы
    boolean keyPUSK = digitalRead(BUTTON_ONE);  // читаем состояние кнопки Пуск
    boolean keySTOP = digitalRead(BUTTON_TWO);  // читаем состояние кнопки Стоп
    boolean keyWORKSTOP = digitalRead(BUTTON_THREE);  // читаем состояние кнопки Рабочий стоп

        if(!keyPUSK)  // если кнопка Пуск нажата
        {
          keyPuskUp = true;  // устанавливаем флаг
          startTime = millis();  // записываем время нажатия на кнопку Пуск
          digitalWrite(ZVONOK, HIGH); // включаем Звонок
        }

        if(keyPuskUp)  // если установлен флаг кнопки Пуск
        {
          start();  // выполнить код в функции start()
        }

        if(!keySTOP)  // если кнопка Стоп нажата
        {
          digitalWrite(ZVONOK, LOW);  // выключить звонок
          keyPuskUp = false;  // убрать флаг кнопки Пуск
          fullstop();  // выполнить код в функции fullstop
        }

        if(!keyWORKSTOP)  // если нажата кнопка Рабочий стоп
        {
          digitalWrite(ZVONOK, LOW);
          digitalWrite(KM_THREE, LOW);
          startTime_1 = millis();
          keyPuskUp = false;
          keyWorkStopUp = true;
        }

        if(keyWorkStopUp)
        {
          workstop();
        }
    }

    void start()
    {
      time_1 = startTime +  prev_time_1;
        if(currentTime >= time_1)
        {
          digitalWrite(ZVONOK, LOW);
          digitalWrite(KM_ONE, HIGH);
        }

      time_2 = time_1 +  prev_time_2;
        if(currentTime >= time_2)
        {
          digitalWrite(KM_TWO, HIGH);
        }

      time_3 = time_2 +  prev_time_3;
        if(currentTime >= time_3)
        {
          digitalWrite(KM_THREE, HIGH);
        }
    }

    void fullstop()
    {
      digitalWrite(KM_ONE, LOW);
      digitalWrite(KM_TWO, LOW);
      digitalWrite(KM_THREE, LOW);
    }

    void workstop()
    {
      time_4 = startTime_1 +  prev_time_4;
        if(currentTime >= time_4)
        {
          digitalWrite(KM_TWO, LOW);
        }

      time_5 = time_4 +  prev_time_5;
        if(currentTime >= time_5)
        {
          digitalWrite(KM_ONE, LOW);
        }
    }
     
    Последнее редактирование: 21 июл 2015