- Arduino delay millis и micros для организации задержки в скетче
- Функции времени в Ардуино
- Использование функции arduino delay
- Синтаксис
- Пример delay с миганием светодиодом
- Функция delayMicroseconds
- Функция millis вместо delay
- Функция micros вместо delay
- Резюме
- Arduino.ru
- Не работает delay
- Нашел, почему delay тормозит Arduino. Показываю, как с этим бороться.
Arduino delay millis и micros для организации задержки в скетче
Задержки в Ардуино играют очень большую роль. Без них не сможет работать даже самый простой пример Blink, который моргает светодиодом через заданный промежуток времени. Но большинство начинающих программистов мало знают о временных задержках и используют только Arduino delay, не зная побочных эффектов этой команды. В этой статье я подробно расскажу о временных функциях и особенностях их использования в среде разработки Arduino IDE.
Функции времени в Ардуино
В Arduino cуществует несколько различных команд, которые отвечают за работу со временем и паузы:
Они отличаются по точности и имеют свои особенности, которые стоит учитывать при написании кода.
Использование функции arduino delay
Синтаксис
В методе setup прописываем, что пин 13 будет использоваться, как выход. В основной части программы сначала на пин подается высокий сигнал, затем делаем задержку в 10 секунд. На это время программа как бы приостанавливается. Дальше подается низкий сигнал и опять задержка и все начинается сначала. В итоге мы получаем, что на пин поочередно подается, то 5 В, то 0.
Пример delay с миганием светодиодом
Можно построить схему со светодиодом и резистором. Тогда у нас получится стандартный пример – мигание светодиодом. Для этого на пин, который мы обозначили как выходной, необходимо подключить светодиод плюсовым контактом. Свободную ногу светодиода через резистор приблизительно на 220 Ом (можно немного больше) подключаем на землю. Определить полярность можно, если посмотреть на его внутренности. Большая чашечка внутри соединена с минусом, а маленькая ножка с плюсом. Если ваш светодиод новый, то определить полярность можно по длине выводов: длинная ножка – плюс, короткая – минус.
Функция delayMicroseconds
Данная функция является полным аналогом delay за исключением того, что единицы измерения у нее не миллисекунды, а микросекунды (в 1 секунде – 1000000 микросекунд). Максимальное значение будет 16383, что равно 16 миллисекундам. Разрешение равно 4, то есть число будет всегда кратно четырем. Кусочек примера будет выглядеть следующим образом:
Проблема с delayMicroseconds точно такая же, как у delay – эти функции полностью «вешают» программу и она на некоторое время буквально замирает. В это время невозможна работа с портами, считывание информации с датчиков и произведение математических операций. Для мигалок данный вариант подходит, но опытные пользователи не используют её для больших проектов, так как там не нужны такие сбои. Поэтому, гораздо лучше использовать функции, описанные ниже.
Функция millis вместо delay
Функция millis() позволит выполнить задержку без delay на ардуино, тем самым обойти недостатки предыдущих способов. Максимальное значение параметра millis такое же, как и у функции delay (4294967295мс или 50 суток). При переполнении значение просто сбрасывается в 0, не забывайте об этом.
С помощью millis мы не останавливаем выполнение всего скетча, а просто указываем, сколько времени ардуино должна просто “обходить” именно тот блок кода, который мы хотим приостановить. В отличие от delay millis сама по себе ничего не останавливает. Данная команда просто возвращает нам от встроенного таймера микроконтроллера количество миллисекунд, прошедших с момента запуска. При каждом вызове loop Мы сами измеряем время, прошедшее с последнего вызова нашего кода и если разница времени меньше желаемой паузы, то игнорируем код. Как только разница станет больше нужной паузы, мы выполняем код, получаем текущее время с помощью той же millis и запоминаем его – это время будет новой точкой отсчета. В следующем цикле отсчет уже будет от новой точки и мы опять будем игнорировать код, пока новая разница millis и нашего сохраненного прежде значения не достигнет вновь желаемой паузы.
Вот пример, наглядно иллюстрирующий работу команды:
Сначала мы вводим переменную timing, в ней будет храниться количество миллисекунд. По умолчанию значение переменной равно 0. В основной части программы проверяем условие: если количество миллисекунд с запуска микроконтроллера минус число, записанное в переменную timing больше, чем 10000, то выполняется действие по выводу сообщения в монитор порта и в переменную записывается текущее значение времени. В результате работы программы каждые 10 секунд в монитор порта будет выводиться надпись 10 seconds. Данный способ позволяет моргать светодиодом без delay.
Функция micros вместо delay
Данная функция так же может выполнить задержку, не используя команду delay. Она работает точно так же, как и millis, но считает не миллисекунды, а микросекунды с разрешением в 4мкс. Её максимальное значение 4294967295 микросекунд или 70 минут. При переполнении значение просто сбрасывается в 0, не забывайте об этом.
Резюме
Платформа Arduino предоставляет нам несколько способов выполнения задержки в своем проекте. С помощью delay вы можете быстро поставить на паузу выполнение скетча, но при этом заблокируете работу микроконтроллера. Использование команды millis позволяет обойтись в ардуино без delay, но для этого потребуется чуть больше программировать. Выбирайте лучший способ в зависимости от сложности вашего проекта. Как правило, в простых скетчах и при задержке меньше 10 секунд используют delay. Если логика работы сложнее и требуется большая задержка, то вместо delay лучше использовать millis.
Источник
Arduino.ru
Не работает delay
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Здравствуйте! Понадобилось сделать аппарат, перемещающий крышку каждые 24 часа и работающий автономно. Для уменьшения энергопотребления использую библиотеку LowPower, а для пробуждения по таймеру MsTimer2, для отключения реле(потребляет ток даже когда не движется) — транзистор на 6 поо По непонятным причинам, в функции feed не срабатывает задержка, а без нее серво привод просто не успевает переместится до выключения и перехода в сон.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
для отключения серво-привода (потребляет ток даже когда не движется) — транзистор на 6 порту.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Внутри функции обработки прерывания не работает delay(), значения возвращаемые millis() не изменяются. http://arduino.ru/Reference/AttachInterrupt
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Если совсем никак в обработчике прерывания без делай обойтись не можете, замените на delayMicroseconds — этот работает.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Если совсем никак в обработчике прерывания без делай обойтись не можете, замените на delayMicroseconds — этот работает.
или написать свою функцию delay(), которая будет работать в обработчике прерывания.
Например
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Если совсем никак в обработчике прерывания без делай обойтись не можете, замените на delayMicroseconds — этот работает.
Нет, delayMicroseconds тоже не работает. Всё то же самое, что и с обычным delay. Может, это не совсем то прерывание, которое есть в стандартной библиотеке.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Если совсем никак в обработчике прерывания без делай обойтись не можете, замените на delayMicroseconds — этот работает.
или написать свою функцию delay(), которая будет работать в обработчике прерывания.
Например
У меня тоже была мысль тормозить всё бональным выполнением долгой операции. Но, почему то, это тоже не работает. Как будто задержка выполняется в другом месте. Я вызвал функцию на 49 строке, а в ком порте выводится что серва включена, затем задержка и после этого сразу посылается сигнал на серву и она отключается без уже задержки. Вот уж не знаю как так.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Нет, delayMicroseconds тоже не работает.
delayMicroseconds в прерывании работает. Если у Вас что-то не работает, ищите причину в другом. (кстати, надеюсь, Вы не забыли задержки на 1000 умножить?)
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Да работает, но с длительностью void delayMicroseconds(unsigned int us); 65 милисекунд максимум. Если на 1000 множить, то очень быстро кончается разрядность и задержки опять становятся короткими.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Так множить-то с умом надо! Без ума оно всегда так 🙁
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Ну, так вызывайте несколько раз. Я же говорю, с умом надо это делать.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Можно мне не вызывать несколько раз? Я же просто проинформировал.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Вот лично Вам никак низзя! Три штрафных вызова, как минимум!
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Нет, delayMicroseconds тоже не работает.
delayMicroseconds в прерывании работает. Если у Вас что-то не работает, ищите причину в другом. (кстати, надеюсь, Вы не забыли задержки на 1000 умножить?)
Пишу по факту. У меня не работает простой код, который активируется библиотекой MsTimer2. Какие ещё могут быть причины? Там же вывод текста в ком порт до и после задержки, который в реальности выводятся одновременно. На 1000 не забыл умножить и даже 10 нулей ставил — результат тот же.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
А как вы понимаете одновременность? 16мс — это не так много, как вы думаете.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Относительно того, что я ввожу — это одновременно. Между сообщениями явно в сотни раз меньше 2 секунд. И при чём тут 16мс?
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Пишу по факту. У меня не работает простой код,даже 10 нулей ставил — результат тот же.
Вы пишете не по факту, а по своей интерпретации того. что видите, которая (интерпретация) очевидно ошибочная.
У меня не работает простой код
Так покажите его, чем языком-то болтать.
даже 10 нулей ставил
Вот и я о том же. Вам тут уже полфорума пытались объяснить, что так нельзя, а Вы всё ставите.
Не работает не delayMicroseconds, а Ваш «простой код».
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Относительно того, что я ввожу — это одновременно. Между сообщениями явно в сотни раз меньше 2 секунд. И при чём тут 16мс?
Всё смешалось — люди, кони.
Ваш MSTimer запускает приаттаченную функцию из ISR? Если да, то никакой delay() там работать не будет. Работать будет delayMicroseconds(), а он позволяет задержать ход времени не более, чем 16.x мс.
К тому же, если вы ознакомились с библиотекой Servo.h, то знаете, что она сама подвешивается на прерывание таймера. А прерывания не работают, покуда вы находитесь в обработчике другого прерывания. И я буду удивлен, если ваша серва без дополнительных извращений вдруг поедет по команде, поданной изнутри ISR.
Просто управляйте сервой вручную — и тогда вам не будут нужны ни дилеи, ни пр. ни др.
Источник
Нашел, почему delay тормозит Arduino. Показываю, как с этим бороться.
Разберем на практическом примере почему использование оператора delay() в своих программах ну. такое себе удовольствие.
Возьмем любую Arduino-подобную платформу, кнопку и светодиод с токоограничивающим резистором.
Попробуем решить простую параллельную задачу:
- мигаем встроенным светодиодом 1 раз в секунду
- при нажатой кнопке BT1 светодиод L1 светится, при отпущенной гаснет
Для мигания встроенным светодиодом возьмем код из примера, с которого обычно начинается обучение Arduino и добавим строчку которая будет зажигать светодиод L1 при нажатии на кнопку.
Операторы в цикле loop () выполняются последовательно, а поскольку оператор delay() останавливает выполнение программы на заданное в параметре функции количество миллисекунд строка 23 в которой происходит копирование состояния кнопки фактически будет опрашиваться один раз в две секунды. (нажав/отпустив кнопку придется ждать до 2-х секунд прежде чем программа сможет зажечь/погасить светодиод). Даже при сборке простейших часов такой подход будет не приемлем — пока на дисплее мигают точки поуправлять таким с помощью кнопок (например чтобы установить время) будет проблематично.
Классический пример решения данной задачи предлагает ресурс с официальной документацией по Arduino в статье Blink Without Delay и его всегда можно использовать его в качестве шаблона.
Всю статью я сюда транслировать не буду, кому интересно можете ознакомиться с ней самостоятельно — там много англицких букаф, которые можно перевести гугл-переводчиком.
Мне столько кода для решения задачи моргания двоеточием в часах писать лень — попробуем воспользоваться фишками языка С и затолкнуть все в пару строк кода 😉
Код который переключает светодиод 1 раз в секунду получился даже короче чем при использовании оператора delay() и не блокирует программу.
digitalWrite(ledBlinking, (millis() / 1000) % 2);
Как это работает?
Встроенная функция millis() возвращает значение равное количеству миллисекунд, прошедших с момента включения или перезагрузки Arduino.
Это число мы делим на 1000 (получается время в секундах)
Оператор % берёт остаток от деления на 2 этого промежуточного результата.
Четные числа на 2 делятся без остатка — то есть получается 0
Нечетные числа делятся на 2 с остатком 1
Таким образом, итоговое значение будет то 0, то 1, переключаясь каждую секунду. Это значение мы и записываем с помощью функции digitalWrite в цифровой выход 13 на котором находится встроенный светодиод.
Фактически мы пишем каждую итерацию цикла то 0 то 1. Эта метода не совсем подойдет если код необходимо выполнять каждую секунду, но только один раз. Поэтому добавим в нашу программу еще пару строчек:
Источник