Меню Рубрики

Ардуино работа со временем

Содержание

6. Работа со временем

рассмотрим дополнительные специфичные функции Arduino для работы со временем

unsigned long millis(void);

Описание:
Возвращает число миллисекунд, с момента исполнения Arduino текущей программы.
Учитывая, что значение хранится в unsigned long, что соотвествует 4 байтам и следовательно может хранить значения от 0 до 4294967295. Т.о счетчик переполнится и обнулится приблизительно через 1193 часов или же 50 дней (49.7).

Возвращаемое значение:
возвращает значение типа unsigned long

unsigned long micros(void);

Описание:
Возвращает число микросекунд, с момента исполнения Arduino/Freeduino текущей программы. Переменная переполнится (обнулится), приблизительно через 70 минут.

Примечание:
На 16 MГц плате Arduino/Freeduino (Duemilanove и Nano), данная функция работает с разрешением в 4 микросекунды (возвращаемое значение всегда кратно черырём).
На 8 MГц плате Arduino/Freeduino (LilyPad), данная функция работает с разрешением в 8 микросекунд.

Возвращаемое значение:
возвращает значение типа unsigned long

void delay(unsigned long);

Описание:
Приостанавливает программу на заданное число миллисекунд.

Параметры:
время_мс – время задержки программы в миллисекундах

void delayMicroseconds(unsigned int us);

Описание:
Приостанавливает программу на заданное число микросекунд.

Параметры:
время_мкс – время задержки программы в микросекундах

  • Уроки
  • Базовые уроки Arduino
  • Функции времени

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

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

Задержки

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

    delay(time) – “Приостанавливает” выполнение кода на time миллисекунд. Дальше функции delay выполнение кода не идёт, за исключением прерываний. Использовать рекомендуется только в самых крайних или тех случаях, когда delay не влияет на скорость работы устройства. time принимает тип данных unsigned long и может приостановить выполнение на срок от 1 мс до
Читайте также:  Если георгины проросли раньше времени

50 суток (4 294 967 295 миллисекунд) с разрешением в 1 миллисекунду. Работает на системном таймере Timer 0
delayMicroseconds(time) – Аналог delay(), приостанавливает выполнение кода на time микросекунд. time принимает тип данных unsigned long и может приостановить выполнение на срок от 4 мкс до

70 минут (4 294 967 295 микросекунд) с разрешением 4 микросекунды. Работает на системном таймере Timer 0

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

И вот мы можем делать какое-то действие два раза в секунду. А что делать, если нам нужно выполнять одно действие два раза в секунду, а другое – три? А третье – 10 раз в секунду например. Сразу привыкаем к той мысли, что задержки лучше вообще не использовать в реальном коде. Разве что delayMicroseconds, он бывает нужен для генерации каких-то протоколов связи. Нормальным инструментом для тайм-менеджмента своего кода являются функции, которые считают время со старта МК.

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

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

    millis() – Возвращает количество миллисекунд, прошедших с запуска. Возвращает unsigned int, от 1 до 4 294 967 295 миллисекунд (

50 суток), имеет разрешение 1 миллисекунда, после переполнения сбрасывается в 0. Работает на системном таймере Timer 0
micros() – Возвращает количество микросекунд, прошедших с запуска. Возвращает unsigned int, от 4 до 4 294 967 295 микросекунд (

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

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

  • Выполнили действие
  • Запомнили текущее время со старта МК (в отдельную переменную)
  • Ищем разницу между текущим временем и запомненным
  • Как только разница больше нужного нам времени “Таймера” – выполняем действие и так по кругу

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

Напомню, что uint32_t это второе название типа данных unsigned long, просто оно короче в записи. Почему переменная должна быть именно такого типа? Потому что функция millis() возвращает именно этот тип данных, т.е. если мы сделаем нашу переменную например типа int, то она переполнится через 32.7 секунды. Но миллис тоже ограничен числом 4 294 967 295, и при переполнении тоже сбросится в 0. Сделает он это через 4 294 967 295 / 1000 / 60 / 60 / 24 = 49.7 суток. Значит ли это, что наш таймер “сломается” через 50 суток? Нет, данная конструкция спокойно переживает переход через 0 и работает дальше, не верьте диванным экспертам, проверьте =)

Вернёмся к вопросу многозадачности: хотим выполнять одно действие два раза в секунду, второе – три, и третье – 10. Нам понадобится 3 переменные таймера и 3 конструкции с условием:

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

Конструкция громоздкая, но используется очень часто, у меня в крупном проекте может быть десяток таких таймеров. Поэтому для ускорения написания кода я сделал библиотечку GyverTimer.

Читайте также:  Диодная лента леруа мерлен

Библиотека GyverTimer

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

Помимо метода isReady(), который сигнализирует о срабатывании таймера, в библиотеке есть куча других:

Пользуйтесь на здоровье! Несколько примеров также есть в папке examples в библиотеке.

Видео