Разглядывая примеры в Arduino IDE, Вы, возможно, обратили внимание на скетч
BlinkWithoutDelay (Examples – Digital — BlinkWithoutDelay)
Этот скетч интересен тем, что он выполняет задачу включения/выключения светодиода без функции delay(). Это означает, что мы можем «одновременно» с миганием светодиода выполнять ещё какую-нибудь интересную задачу 🙂
Как же это реализовано? Как обычно – всё достаточно просто 🙂
Вместо обычного delay() используется millis(), которая, как мы помним, возвращает нам число миллисекунд, с момента исполнения Arduino/Freeduino текущей программы.
Итак, сам скетч:
/* Blink without Delay – мигаем без задержки :) * * Включение/выключение светодиода, подключённого к * цифровому порту, без использования функции delay(). * Это означает, что «одновременно» можно выполнять другой код, * без прерывания на мигание светодиодом :) * * http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay */ int ledPin = 13; // наш светодиод на 13 порту int value = LOW; // предыдущее состояние светодиода long previousMillis = 0; // здесь будет храниться время последнего изменения состояния светодиода long interval = 1000; // интервал мигания в миллисекундах void setup() { pinMode(ledPin, OUTPUT); // устанавливаем порт, как выход } void loop() { // здесь можно поместить свой код для постоянного выполнения // проверяем – настало ли время изменить состояние светодиода // для этого берём разность между текущим временем и // временем последнего изменения состояния светодиода, // а затем сверяем полученный интервал с нужным интервалом // мигания – если больше – значит пора мигать ;) if (millis() - previousMillis > interval) { previousMillis = millis(); // запоминаем текущее время // если светодиод был выключен – включаем и наоборот :) if (value == LOW) value = HIGH; else value = LOW; digitalWrite(ledPin, value); } }
Вот собственно и всё 🙂
Чуть более усложнённый пример использования millis() для «одновременного» выполнения нескольких задач можно посмотреть на официальном сайте ардуино:
http://www.arduino.cc/playground/Code/Stopwatch
По теме
Программирование Arduino — Работа со временем
Библиотека TimerOne
5 комментариев на «“Программирование Arduino/CraftDuino — Blink без delay”»
Пример хороший, взял на вооружение…
Но.
Что будет, если счетчик дойдет до 4294967295 и обнулится, а значение previousMillis будет равняться к примеру 4294967000?
Или данное выражение:
(millis() — previousMillis > interval)
не является как (1223 — 4294967000 = -4294965777 > 1000)
?
Извините, если глупый вопрос, я тут новичек.
Вопрос не глупый. Так и будет: переворот счетчика через 0 с последующей некорректной работой.
Только произойдет это через ~50 дней. (На самом деле в приведенном выше коде некорректность — необходимо использовать беззнаковые переменные, чтобы достичь этого максимального периода).
Если ваш скетч должен функционировать более продолжительное время, то надо вставить проверку на переворот. Например так:
Думаю быстрее будет так:
Имелось в виду наверное =! (присвоить инвертированное значение), а не != (логическое неравенство).
Собственно всю конструкцию:
можно (и нужно) заменить на:
В результате получаем более краткий скетч, и при компиляции экономим с десяток байт в дуине. Да и очевидно операнд сравнения схавает несколько дополнительных тактов контроллера. В примере не критично, но в большом коде важная вещь.
ЗЫ я не спец, дуину купил день назад, вот знакомлюсь 🙂
И кстати, просвятите, зачем объявлять
, если без таких объявлений код тоже всегда работает? Я правда не вижу подвоха, расскажите для общего развития.
Функция pinMode(ledPin, OUTPUT) равносильна DDRx |= (1 << ledPin).
DDRx (Data Direction Register) — направление работы порта х. Вместо x подставляется название порта (А, B, C…). Если соответствующий пину бит в этом регистре равен 0 (а это значение по умолчанию), то пин работает как ввод, если 1 — как вывод. Когда выставляешь единицу, то к пину подключается драйвер, который позволяет пину отдавать ток до 20 мА.
Да, код работает и без этой функции, но вы можете заметить, что в этом случае светодиод светится крайне тускло, а некоторые отдельные могут вообще не светиться. Да, ток есть, но он очень маленький.