Всем привет! Я абсолютный новичок, программировал последний раз в 7 класс на BASIC, а сейчас купил Ардуино, чтобы играть с ребёнком. Хочу написать программу, которая по однократному нажатию кнопки циклично переключалась бы между режима мигания светодиода: 10 Гц - 2 Гц - выключен - 10 Гц и т.п. Мигание хочу реализовать без delay(t) с помощью отдельной функции. Написал программу, но при её заливке на плату ничего не происходит. Диод не мигает, на кнопку не реагирует. Код (C++): int GREEN1 = 3; //контакт 3 для светодиода int BUTTON = 2; //контакт 2 для кнопки boolean lastButton = LOW; //переменная для хранения последнего состояния кнопки boolean currentButton = LOW; //переменная для хранения текущего статуса кнопки int lmode = 0; //переменная для статуса светодиода int GREEN1_INTERVAL1 = 100; //100 мс для моргания 10 Гц int GREEN1_INTERVAL2 = 500; //500 мс для моргания 2 Гц long previousTime = 0; void setup() { pinMode (GREEN1, OUTPUT); //устанавливаем пин3 как выход pinMode (BUTTON, INPUT); //устанавливаем пин2 как вход } boolean debounce(boolean last) //функция сглаживания, выдает значения HIGH или LOW { boolean current = digitalRead(BUTTON); //считываем состояние кнопки if (last != current) //если не такое, как было { delay(10); //то ждём 10 мс current = digitalRead(BUTTON); //опять считываем состояние кнопки return current; //возвращаем состояние } } void setMode (int mode) //функция для выполнения моргания. void т.к. она ничего не вычисляет { if (mode == 0) //если режим равен 0 { Blink (GREEN1, GREEN1_INTERVAL1); //моргаем на выводе GREEN1 с интервалом GREEN1_INTERVAL1 } if (mode == 1); //если режим равен 1 { Blink (GREEN1, GREEN1_INTERVAL2); } if (mode == 2); //если режим равен 2 { digitalWrite (GREEN1, LOW); //выключаем питание } } void Blink (long INTERVAL, int LED_PIN) //функция воспринимает интервал и пин вывода в качетсве входных параметров { long Time = millis(); //записываем время работы контроллера if (Time - previousTime > INTERVAL) //если прошло достаточно времени, то { previousTime = Time; //перезаписываем время boolean LED_STATE; //вводим локальную переменную, хранящую состояние диода if (LED_STATE == LOW) //если диод выключен LED_STATE = HIGH; //то включаем его else //а иначе LED_STATE = LOW; //опять выключаем digitalWrite (LED_PIN, LED_STATE); //тут включаем/выключаем диод. } } void loop() { currentButton = debounce(lastButton); //подаём функции debounce текущее состояние кнопки, по сути считываем состояние с учётом дребезга if (lastButton == LOW && currentButton == HIGH) //если кнопка нажата { lmode++; //увеличиваем состояние счётчика режима на 1 } lastButton = currentButton; //запоминаем последнее состояние кнопки if (lmode = 3) //если счётчик дошёл до значения 3, которое не предусмотрено в теле функции setMode lmode = 0; //то мы его обнуляем setMode (lmode); //и передаём значение функции setMode } Схема рабочая (см. вложение), простейшие программы на ней работают.
По совету бывалых в setup() инициализировал COM-порт с помощью Serial.begin(9600); и добавил Serial.print("current="); Serial.println(current); В тело функции debounce() после строк delay(10); //то ждём 10 мс current = digitalRead(BUTTON); Выдача при нажатии кнопки такая: current=1 current=0 То есть кнопка меняет своё состояние при нажатии дважды.
10 Гц человеческий глаз будет воспринимать просто как включенный светодиод, т.к. сетчатка "помнит" изображение примерно 0,1 сек.
Я имел в виду включить на 100 мс - выключить на 100 мс - включить на 100 мс и т.п. Такое моргание, очевидно, будет видно.
Такое "моргание" это выключение на 0,1 сек. Будет видно не каждому человеку и зависит от индивидуального восприятия. Приведите полный скетч после добавления вывода в порт и скриншот того, что отображается в мониторе порта после пяти нажатий на кнопку. Апдейт. Выключение на 0,1 сек и включение на 0,1 сек. Это таки 5 Гц. Но все равно на границе восприятия.
Ну если я делаю это моргание с помощью delay(100); то глазами прекрасно всё видно. Вот скетч: Код (C++): int GREEN1 = 3; //контакт 3 для светодиода int BUTTON = 2; //контакт 2 для кнопки boolean lastButton = LOW; //переменная для хранения последнего состояния кнопки boolean currentButton = LOW; //переменная для хранения текущего статуса кнопки int lmode = 0; //переменная для статуса светодиода int GREEN1_INTERVAL1 = 100; //100 мс для моргания 10 Гц int GREEN1_INTERVAL2 = 500; //500 мс для моргания 2 Гц long previousTime = 0; void setup() { pinMode (GREEN1, OUTPUT); //устанавливаем пин3 как выход pinMode (BUTTON, INPUT); //устанавливаем пин2 как вход Serial.begin(9600); } boolean debounce(boolean last) //функция сглаживания, выдает значения HIGH или LOW { boolean current = digitalRead(BUTTON); //считываем состояние кнопки if (last != current) //если не такое, как было { delay(10); //то ждём 10 мс current = digitalRead(BUTTON); //опять считываем состояние кнопки Serial.print("current="); Serial.println(current); return current; //возвращаем состояние } } void setMode (int mode) //функция для выполнения моргания. void т.к. она ничего не вычисляет { if (mode == 0) //если режим равен 0 { Blink (GREEN1, GREEN1_INTERVAL1); //моргаем на выводе GREEN1 с интервалом GREEN1_INTERVAL1 } if (mode == 1); //если режим равен 1 { Blink (GREEN1, GREEN1_INTERVAL2); } if (mode == 2); //если режим равен 2 { digitalWrite (GREEN1, LOW); //выключаем питание } } void Blink (long INTERVAL, int LED_PIN) //функция воспринимает интервал и пин вывода в качетсве входных параметров { long Time = millis(); //записываем время работы контроллера if (Time - previousTime > INTERVAL) //если прошло достаточно времени, то { previousTime = Time; //перезаписываем время boolean LED_STATE; //вводим локальную переменную, хранящую состояние диода if (LED_STATE == LOW) //если диод выключен { LED_STATE = HIGH; //то включаем его } else //а иначе { LED_STATE = LOW; //опять выключаем } digitalWrite (LED_PIN, LED_STATE); //тут включаем/выключаем диод. } } void loop() { currentButton = debounce(lastButton); //подаём функции debounce текущее состояние кнопки, по сути считываем состояние с учётом дребезга if (lastButton == HIGH && currentButton == LOW) //если кнопка нажата { lmode++; //увеличиваем состояние счётчика режима на 1 } lastButton = currentButton; //запоминаем последнее состояние кнопки if (lmode = 3) //если счётчик дошёл до значения 3, которое не предусмотрено в теле функции setMode lmode = 0; //то мы его обнуляем setMode (lmode); //и передаём значение функции setMode } Вот скрин после 5 нажатий. Нажатие это нажал-отпустил. Одно нажатие генерирует пару строк current=0 current=1
Смотрите, вы вызываете Блинк так: Код (C++): Blink (GREEN1, GREEN1_INTERVAL2); Т.е. первый параметр - номер выхода, второй - длительность интервала А прототип функции выглядит так: Код (C++): void Blink (long INTERVAL, int LED_PIN) Т.е. первый параметр - длительность интервала, а второй - номер выхода.
Да, точно! Спасибо! Правда, теперь диод едва мерцает в глубине И кнопка по прежнему не действует (что логично)