Delay что это в ардуино

Arduino delay millis и micros для организации задержки в скетче

Задержки в Ардуино играют очень большую роль. Без них не сможет работать даже самый простой пример Blink, который моргает светодиодом через заданный промежуток времени. Но большинство начинающих программистов мало знают о временных задержках и используют только Arduino delay, не зная побочных эффектов этой команды. В этой статье я подробно расскажу о временных функциях и особенностях их использования в среде разработки Arduino IDE.

Функции времени в Ардуино

В Arduino cуществует несколько различных команд, которые отвечают за работу со временем и паузы:

Они отличаются по точности и имеют свои особенности, которые стоит учитывать при написании кода.

Использование функции arduino delay

Синтаксис

Delay что это в ардуино. Смотреть фото Delay что это в ардуино. Смотреть картинку Delay что это в ардуино. Картинка про Delay что это в ардуино. Фото Delay что это в ардуиноАрдуино delay является самой простой командой и её чаще всего используют новички. По сути она является задержкой, которая приостанавливает работу программы, на указанное в скобках число миллисекунд. (В одной секунде 1000 миллисекунд.) Максимальное значение может быть 4294967295 мс, что примерно ровняется 50 суткам. Давайте рассмотрим простой пример, наглядно показывающий работу этой команды.

В методе setup прописываем, что пин 13 будет использоваться, как выход. В основной части программы сначала на пин подается высокий сигнал, затем делаем задержку в 10 секунд. На это время программа как бы приостанавливается. Дальше подается низкий сигнал и опять задержка и все начинается сначала. В итоге мы получаем, что на пин поочередно подается, то 5 В, то 0.

Пример delay с миганием светодиодом

Delay что это в ардуино. Смотреть фото Delay что это в ардуино. Смотреть картинку Delay что это в ардуино. Картинка про Delay что это в ардуино. Фото Delay что это в ардуиноПример схемы для иллюстрации работы функции 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.

Источник

delay()

Описание

Приостанавливает выполнение программы на указанный промежуток времени (в миллисекундах). (В 1 секунде — 1000 миллисекунд.)

Синтаксис

Параметры

ms: количество миллисекунд, на которые необходимо приостановить программу (unsigned long)

Возвращаемые значения

Пример

Предупреждение

С помощью функции delay() заставить мигать светодиод достаточно просто. Помимо этого, во многих программах функция задержки используется для таких задач, как обработка дребезга контактов и пр. Несмотря на это, использование функции delay() в коде программы имеет существенные недостатки. В процессе действия delay() такие операции, как считывание данных с датчиков, математические вычисления или операции с выводами не могут выполняться. Фактически, функция delay() приводит к остановке практически всех операций. Альтернативный способ контролировать время — использование функции millis() (смотрите пример кода, приведенный ниже). Опытные программисты обычно избегают использования delay() для установки временных интервалов больше нескольких десятков миллисекунд (за исключением очень простых программ Arduino).

Тем не менее, некоторые события и участки кода могут работать и в процессе выполнения микроконтроллером функции delay(), т.к. эта функция не влияет на работу прерываний. Так, по прежнему будут срабатывать прерывания, записываться данные, поступающие на вывод RX по последовательному интерфейсу, а также будет поддерживаться ШИМ-сигнал, формируемый функцией analogWrite().

Источник

Функции времени

Delay что это в ардуино. Смотреть фото Delay что это в ардуино. Смотреть картинку Delay что это в ардуино. Картинка про Delay что это в ардуино. Фото Delay что это в ардуино

Откуда берётся время?

Начнём с того, откуда вообще микроконтроллер знает, сколько проходит времени. Ведь у него нет часов! Для работы микроконтроллера жизненно важен так называемый тактовый генератор, или кварцевый генератор, или он же кварц. Он же oscillator, он же clock. Clock по-английски это часы. Да, но не всё так просто =) Кварц расположен рядом с МК на плате (также во многих МК есть встроенный тактовый генератор), на Ардуинах обычно стоит генератор на 16 МГц, также встречаются модели на 8 МГц. Тактовый генератор выполняет очень простую вещь: он “пинает” микроконтроллер со своей тактовой частотой, то есть 16 МГц кварц пинает МК 16 миллионов раз в секунду. Микроконтроллер, в свою очередь зная частоту кварца, может прикинуть время между пинками (16 МГц = 0.0625 микросекунды), и таким образом ориентироваться во времени. Но на деле не всё так просто, потому что принимают пинки таймера так называемые таймеры-счётчики (Timer-counter). Это физически расположенные внутри МК устройства, которые занимаются подсчётом пинков тактового генератора. И вот микроконтроллер уже может обратиться к счётчику и спросить, а сколько там натикало? И счётчик ему скажет. И вот этим мы уже можем пользоваться, для этого у Ардуино есть готовые функции времени. В Arduino на базе ATmega328 имеются три счётчика, и подсчётом времени занимается таймер под номером 0. Этим может заниматься любой другой счётчик, но работая в Arduino IDE вы сразу получаете такую настройку, т.к. создавая скетч в Arduino IDE вы автоматически работаете с библиотекой Arduino.h, где и реализованы все удобные функции.

Задержки

Простейшей с точки зрения использования функцией времени является задержка, их у нас две:

Задержки использовать очень просто:

И вот мы можем делать какое-то действие два раза в секунду. delayMicroseconds() иногда не совсем корректно работает с переменными, нужно стараться использовать константы ( const или просто число). Для создания микросекундных задержек с переменным периодом и корректной работы в циклах лучше использовать следующую конструкцию:

Функция yield()

Разработчики Arduino позаботились о том, чтобы функция delay() не просто блокировала выполнение кода, но и позволяла выполнять другой код во время этой задержки. Данный “костыль” получил название yield() и работает следующим образом: если объявить функцию

то расположенный внутри неё код будет выполняться во время работы любой задержки delay() в программе! Это решение хоть и кажется нелепым, но в то же время позволяет быстро и без описания лишних костылей и таймеров реализовать пару параллельно выполняющихся задач. Что вполне соответствует назначению Ардуино – максимально простая и быстрая разработка прототипа. Рассмотрим например такой простой пример: стандартный мигающий светодиод, но с опросом кнопки

Подробнее о том, как работать с yield() и строить программу на её основе мы рассмотрим в одном из следующих уроков о том, как написать скетч.

Функции счёта времени

Данные функции возвращают время, прошедшее с момента запуска микроконтроллера, так называемый аптайм (англ. uptime). Таких функций у нас две:

70 минут), имеет разрешение в 4 микросекунды, после переполнения сбрасывается в 0. Работает на системном таймере Timer 0

Таймер на millis()

Вы спросите, а как время со старта МК поможет нам организовать действия по времени? Очень просто, схема вот такая:

Тип 1

Реализация классического “таймера на millis()” выглядит вот так:

Тип 2

Второй вариант сброса таймера будет записан вот так:

Эта конструкция жёстко отрабатывает период, то есть не “уходит” со временем, если в коде присутствует малая задержка, потому что время следующего срабатывания всегда кратно периоду. Минусом здесь является то, что если таймер пропустит период – он “сработает” несколько раз при следующей проверке! Но из этой неприятной ситуации есть выход.

Тип 3

Можно посчитать, на сколько периодов нужно “обновить” переменную таймера. Например так:

Переполнение

Почему эта конструкция работает и не ломается? Потому что мы используем беззнаковый тип данных, который при переполнении начинает считать с нуля. Подробнее об этом читайте в уроке про вычисления. Таким образом когда миллис становится равен нулю и растёт, а мы вычитаем из него огромное число – получаем не отрицательное, а вполне корректное значение, которое является временем с предыдущего сброса таймера. Поэтому конструкция не то что продолжает работать через

50 суток, но и проходит момент “переполнения” без потери периода!

И вот так мы можем например 10 раз в секунду опросить датчик, фильтровать значения, и два раза в секунду выводить показания на дисплей. И три раза в секунду мигать лампочкой. Почему нет? Рассмотрим ещё несколько алгоритмов.

Варианты использования millis()

В классическом варианте таймера нам приходится создавать отдельную 32-х битную переменную под каждый таймер. Весьма расточительно! Давайте рассмотрим другие варианты организации периодических действий на базе счётчика аптайма millis() :

Казалось бы, очень крутой и простой алгоритм… но использовать его нельзя по целому ряду причин:

Вывод: ни в коем случае не используйте данную конструкцию.

Либо вот такой вариант, он не уходит в отличие от предыдущего (разбирали разницу в главе “Таймер на millis()”). Разница напомню в способе сброса таймера.

Пользоваться очень просто: добавьте указанный выше макрос в самое начало кода и вызывайте его как функцию

Единственное ограничение: нельзя вызывать макрос больше одного раза в одном и том же блоке кода, это приведёт к ошибке =) То есть вот так нельзя:

Если очень нужна такая конструкция – помещаем каждый вызов в свой блок кода:

Либо используем блоки кода по условиям или как отдельную функцию, которая “оборачивает” макрос:

Источник

Delay что это в ардуино

Pauses the program for the amount of time (in miliseconds) specified as parameter. (There are 1000 milliseconds in a second.)

Syntax

Parameters

ms: the number of milliseconds to pause (unsigned long)

Returns

Example

int ledPin = 13 ; // LED connected to digital pin 13

Caveat

While it is easy to create a blinking LED with the delay() function, and many sketches use short delays for such tasks as switch debouncing, the use of delay() in a sketch has significant drawbacks. No other reading of sensors, mathematical calculations, or pin manipulation can go on during the delay function, so in effect, it brings most other activity to a halt. For alternative approaches to controlling timing see the millis() function and the sketch sited below. More knowledgeable programmers usually avoid the use of delay() for timing of events longer than 10’s of milliseconds unless the Arduino sketch is very simple.

Certain things do go on while the delay() function is controlling the Atmega chip however, because the delay function does not disable interrupts. Serial communication that appears at the RX pin is recorded, PWM (analogWrite) values and pin states are maintained, and interrupts will work as they should.

See also

Corrections, suggestions, and new documentation should be posted to the Forum.

The text of the Arduino reference is licensed under a Creative Commons Attribution-ShareAlike 3.0 License. Code samples in the reference are released into the public domain.

Источник

Работаем с задержками без delay() на arduino.

В прошлом уроке мы поняли принцип считывания значения с матричной клавиатуры и написали простой код, который реализует данное действие. Прежде чем переходить к более сложной задаче – сохранению введённого значения с клавиатуры, попробуем реализовать функцию работы с замком разного типа, и открытию его по кнопке с обратной стороны двери, а также сделаем звуковую и световую индикацию при открытии.

Delay что это в ардуино. Смотреть фото Delay что это в ардуино. Смотреть картинку Delay что это в ардуино. Картинка про Delay что это в ардуино. Фото Delay что это в ардуино

Мы рисовали общую схему нашего устройства, но сейчас посмотрим на элементы, с которыми мы будем работать в данном уроке. Собственно – их 5. – это зуммер, реле с 2 типами контактов, светодиод, показывающий состояние прохода и кнопка мгновенного действия. Подготовим для всех них понятные имена

Также нам понадобится новая переменная – флаг, который будет указывать тип замка. Замок у нас может быть электромагнитный или электромеханический – отличаются по принципу действия. Если на магните нужно снимать напряжение в момент открытия, то на механике, наоборот подавать напряжение на соленойд для открытия.

Теперь зададим режим работы пинов нашей периферии. Как не сложно догадаться на вход у нас будет настроен только контакт кнопки, все остальные устройства являются исполнительными и будут настроены на выход. Чтобы не вешать внешнее сопротивление, настроим внутреннюю резистивную подтяжку на входе кнопки.

Первым делом попытаемся избавиться от задержки delay() в ардуино, чтобы во время ожидания, наш контроллер мог решать другие задачи. Нам это нужно будет, для управлением временем открытия замка, зажиганию диодов, подачи звука, и чтобы в это время мы могли решать другие задачи, такие как, опрос клавиатуры, кнопки выхода и считывателя.

К счастью, в ардуино уже есть для этого инструменты. Попытаюсь дать короткое объяснение, почему delay это плохо. Для этого отвлечёмся и представим абстрактную задачу, где один светодиод у нас моргает каждую 1 секунду, а другой, каждые 0,2 секунды. Возьмём обычный пример мигания через delay

Естественно, в данном примере, они мигают по очереди, потому-что пока выполняется delay, контроллер делает бесполезные операции в цикле. Можно конечно сделать мигание второго диода в прерывании, но опять же, использовать там delay не получится, чтобы выдержать 200мс.

Delay что это в ардуино. Смотреть фото Delay что это в ардуино. Смотреть картинку Delay что это в ардуино. Картинка про Delay что это в ардуино. Фото Delay что это в ардуино

Можно извратиться, и рассчитать задержки свечения светодиода, который мигает чаще, так, чтобы создать второму диоду нужные 1 секунду простоя и свечения.

Delay что это в ардуино. Смотреть фото Delay что это в ардуино. Смотреть картинку Delay что это в ардуино. Картинка про Delay что это в ардуино. Фото Delay что это в ардуино

Всё просто! Мы используем вспомогательную переменную текущего времени currentTime, На старте её значение равно = 0, как и millis() = 0. Но millis() у нас постоянно увеличивается, а currentTime – нет. Поэтому через 1000мс, сработает условие if (millis() – currentTime > 1000), т.е. мы создали задержку в 1с, но код при этом выполнялся циклично в loop, и мы могли успеть обработать много периферии. Потом мы просто обновляем нашу переменную currentTime, и она снова ждёт сравнения с millis(), когда она вырастет на 1000мс. Попробуем сделать вышестоящую задачу, мигание двумя светодиодами с разной задержкой. но при этом вставим в loop какой нибудь код, пусть будет отправка в терминал, и проверим, как это работает. Я сделал для наглядности вторую переменную currentTime2, для второго светодиода.

Для состояний светодиодов, возьмём переменную bool ledState и ledState2. Мы задали её тип как boolean, а это значит что она может принимать два значения – true и false, что в принципе равно 0 и 1. Чтобы не писать по несколько раз HIGH, LOW, мы подставляем туда состояние светодиода ledState. А меняем его каждый раз логическим отрицанием (!) на противоположное значение.

В конце цикла loop, впишем команду инкрементирования переменной a++, и отправки значения в серийный порт, чтобы отследить, будет ли выполняться этот код в момент ожидания задержек.

Смотрим, что получилось

Delay что это в ардуино. Смотреть фото Delay что это в ардуино. Смотреть картинку Delay что это в ардуино. Картинка про Delay что это в ардуино. Фото Delay что это в ардуино

Видно, что теперь у нас и светодиоды моргают с заданными задержками (1000мс и 200мс) и в серийный порт с постоянством отправляется новая переменная. Отлично – теперь мы можем получить какие-то задатки многозадачности, и продолжить писать код для нашего устройства в следующей статье.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *