Многозадачность в Arduino с помощью функции millis()
Содержание
- Что такое многозадачность
- Почему стоит воздержаться от использования функции delay() в Arduino
- Почему стоит использовать функцию millis()
Реализация многозадачности в свое время произвело настоящую революцию в компьютерной технике и позволило нескольким программам исполняться одновременно, что увеличило эффективность, гибкость и адаптивность программ. Постепенно из компьютерной техники многозадачность перекочевала и в проекты на микроконтроллерах.
В этой статье мы рассмотрим реализацию многозадачности в плате Arduino на основе использования функции millis(). Обычно для реализации какой-нибудь периодически выполняемой задачи (например, мигание светодиода) в Arduino используется функция delay(), однако эта функция останавливает выполнение программы и во время ее действия плата Arduino не может выполнять никакие другие операции. Поэтому в данной статье мы рассмотрим как преодолеть этот недостаток функции delay() при помощи замены ее на функцию millis(). Таким образом, мы сможем превратить плату Arduino в многозадачную платформу.
Что такое многозадачность
Многозадачность означает выполнение более одной задачи/программы в одно и то же время. В настоящее время практически все операционные системы поддерживают многозадачность. К примеру, ваш персональный компьютер может в одно и то же время принимать электронную почту, открывать сайты в веб-браузере, выполнять какие-нибудь расчеты и т.п. Пользователю кажется что все эти процессы выполняются одновременно, однако у операционной системы на этот счет несколько иной взгляд. Давайте рассмотрим более подробно как выглядит многозадачность с точки зрения операционной системы.
Как показано на представленном рисунке, микропроцессор делит общее время на 3 равные части и в каждой части времени выполняет отдельную задачу. Таким образом реализуется концепция многозадачности в большинстве современных компьютерных систем. Аналогичный подход мы применим и в нашем проекте для Arduino, однако распределение времени на разные задачи будет немного отличаться. Поскольку плата Arduino работает на значительно меньшей частоте чем современные персональные компьютеры и объем оперативной памяти у нее значительно меньше, то и время, выделяемое на каждую задачу, будет различным.
Но прежде чем мы перейдем к реализации многозадачности в Arduino давайте рассмотрим почему не стоит использовать функцию delay() абсолютно в каждом проекте на Arduino.
Почему стоит воздержаться от использования функции delay() в Arduino
В документации на Arduino указано, что в этой платформе существует две функции для организации задержек — delay() и delayMicroseconds() . По принципу действия обе эти функции абсолютно идентичны, только в функции delay() значение задержки указывается в миллисекундах, а в функции delayMicroseconds() – в микросекундах.
Обе эти функции останавливают работу платы Arduino на заданное время. К примеру, если мы сделаем задержку на 10 секунд, то плата Arduino не сможет выполнить никакую другую команду до тех пор, пока эти 10 секунд не истекут. Естественно, подобный подход сильно мешает рациональному использованию вычислительных ресурсов микроконтроллера.
Рассмотрим, к примеру, две кнопки. Допустим, нам нужно переключать состояние двух светодиодов с помощью этих двух кнопок. Например, при нажатии первой кнопки первый светодиод должен включаться на 2 секунды, а при нажатии второй кнопки второй светодиод должен включаться на 4 секунды. Если в данном случае мы будем использовать функцию delay(), то при нажатии первой кнопки программа остановится на 2 секунды и даже если в это время нажать вторую кнопку, то программа просто не сможет обработать нажатие этой кнопки.
В официальной документации на Arduino вы можете прочитать замечания и предупреждения по использованию функции delay(). Если вы найдете в себе силы их прочитать, то вы окончательно убедитесь в том, что использование функции delay() – далеко не лучший способ организации задержек в программах для Arduino.
Почему стоит использовать функцию millis()
Для преодоления проблем, описанных в предыдущем пункте данной статьи, вызванных использованием функции delay(), можно использовать функцию millis() . Использование данной функции позволит более гибко использовать вычислительные возможности платы Arduino, не прибегая к полному останову программы как в случае использования функции delay(). millis() – это функция, которая возвращает количество миллисекунд, прошедших с момента начала выполнения платой Arduino текущей программы. Никакого останова программы во время использования этой функции не происходит. Счетчик этой функции будет переполняться (то есть сбрасываться в ноль) примерно через 50 дней функционирования программы.
Также как и в случае с функцией delayMicroseconds(), в Arduino имеется аналогичная функция и для функции millis() – это функция micros() . Она работает так же как и millis(), но счет ведет в микросекундах. Ее счетчик переполняется примерно через 70 минут функционирования программы.
Чтобы использовать функцию millis() для организации временных задержек в программе вам необходимо сохранять в переменной момент времени когда начало выполняться какое либо действие и затем непрерывно проверять сколько времени истекло с этого момента времени. Для решения стоящей перед нами задачи вначале сохраним текущее время в соответствующей переменной:
Источник: