Здравствуйте. Столкнулся с такой задачей. Есть две кнопки: Пуск и Стоп. Нажатие на кнопку Пуск приводит к последовательному включению 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); } }
Не используйте delay, делайте задержку при помощи millis. На форуме десятки обсуждений на эту тему, поищите.
Спасибо. На форуме искал, но чёткого ответа так и не нашёл. Понял что дело связано с прерываниями. Сделал прерывание. Теперь кнопка Стоп выключает включение механизмов, но они вновь включаются, так как у меня используется 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 не получается.
Почему не получается? Заводите несколько переменных long int, вначале програамы присваеваете им значение миллис. В лупе несколько if сравнивающих миллис с этими переменными и заданными интервалами. Главное в конце процедуры снова присвоить переменной текущее значение миллис для ожидания следующего вызова.
По кнопке пуск ставьте флаг. При установленном флаге пускай вызывается код, который будет при помощи millis отмерять интервалы. В конце каждого интервала прибавляете счетчик и включаете устройство в соответствии с номером счетчика. Когда все устройства будут включены, снимаете флаг. При нажатии кнопки стоп выключаете все устройства и снимаете флаг.
Последний нубский вопрос, что такое флаг? В этой теме: http://forum.amperka.ru/threads/Авто-полив-растений-с-датчиком-влажности.4930/page-2#post-39355 вы показываете пример с этими флагами, но я никак не пойму как сама помпа в этом примере завязана с pumpWork? Как она у Вас включается без привязки к какому либо пину?
Вообще флаг это такая переменная, которая может принимать два или более определенных значений. Используется для определения фиксированных состояний системы.
Флаг может принимать только 2 значения - "флаг поднят" и "флаг опущен". Если значений больше, то называть флагом такую переменную неверно.
В той теме показан принцип построения алгоритма, не более того. Предполагается, что в функциях startPump и stopPump будет прописан код, включающий и выключающий помпу.
Разноцветный флаг. ) Я считал, что любая переменная хранящая один из нескольких возможных значений может считаться флагом. Например переключатель. Хотя, возможно, что то частный случай чего то.
Когда состояний много, лучше использовать перечисление. Код (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; } } Так код становится более читаемым, а программисту легче не допустить ошибку.
Это понятно, но иногда удобно использовать счетчик-переключатель. Сходу примеров не приведу, но случаи были.
Вроде бы с горем пополам разобрался. Программа такова что есть 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); } }