Найти в Дзене
Пишем о чём-то

Избавляемся от delay() в Ардуино

Оглавление

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

Delay() «замораживает» выполнение на 1 секунду (1000 миллисекунд)
Delay() «замораживает» выполнение на 1 секунду (1000 миллисекунд)

Проблемы delay()

И всё же, чем delay() так не угодила ардуинщикам? Проблема в том, что когда мы задействуем delay(), система банально простаивает и не может быть использована. В самых простых программах, например, управляющей каким-нибудь светодиодом, простой проблемой не является, но в реальных задачах это просто недопустимо.

В реальных проектах ардуино зачастую требуется управлять сразу несколькими портами, постоянно считывая и отправляя различные сигналы, а потому подобная «заморозка» системы просто недопустима. Так чем же заменить столь неудобную функцию?

Замена delay()

Использование yield()

Первый способ не убирает delay() из кода, но позволяет выполнять отдельный код пока система остановлена. Разработчики Arduino понимали, что delay() — это проблема и потому добавили функцию yield(). Она работает тогда, когда система останавливается из-за вызова delay(). Это хоть и позволяет выполнять код во время delay(), по факту эта функция является «костылём» и крайне неудобна в использовании. Не рекомендую решать ею проблему с delay().

-3

Обработка вручную при помощи millis() или micros()

Функции millis() и micros() возвращают время, прошедшее с момента запуска микроконтроллера, так называемый аптайм(англ. uptime).

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

С помощью этих функций можно реализовать бесконечное множество разных таймеров, по-разному вычисляющих, отмеряющих и контролирующих регулярный запуск кода. Я покажу лишь наиболее простой вариант создания таймера.

-4

Такой таймер позволяет выполнять код с задержкой, при этом не останавливая выполнение других частей программы. К тому же, таким образом мы можем добавлять столько таймеров, сколько захотим, и они смогут обрабатываться каждый со своей задержкой. Это в разы практичнее delay(). Единственным существенным минусом мне кажется то, что используется переменная, занимающая целых 4 байта (uint32_t), а в особо больших программах каждый бит памяти бывает на счету.

Заключение

В данной статье я описал наиболее простые замены delay(). Также существует аппаратное прерывание таймерами, но эта тема довольно сложна и для её разбора потребуется как минимум отбельная статья. Возможно я когда-нибудь расскажу о них.

Подписывайтесь на канал и ставьте лайки!