Millis() или delay() : что лучше и правильнее использовать?

08 октября 2017

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


Функция delay() останавливает выполнение программы на заданное временное значение перед следующим действием или циклом. Прописывается она в отдельное в строке и содержит внутри себя значение в миллисекундах (на заметку: 1000 мс, миллисекунд = 1 секунда)

Пример задержки в 5 секунд будет выглядеть так:

delay(5000);

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

Рассмотрим это на следующем примере:

Попробуем включать светодиоды путем нажатия на кнопку/кнопки

В первом коде светодиод, подключенный к контакту 4 будет включаться нажатием кнопки, подключенной к контакту 2.

const int
buttonPin = 2;
const int ledPin = 4;
void setup() 
{
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}
void loop() 
{
  if (digitalRead(buttonPin)== HIGH) 
  {
   digitalWrite(ledPin,HIGH);
   delay(3000);
   digitalWrite(ledPin, LOW);
  }
}

В данном программном коде используется функция delay(). Она позволяет ставить задержку в 3 секунды после включения светодиода, останавливая цикл, после чего он успешно гаснет – и при нажатии на кнопку снова загорается. Казалось бы, все просто: устанавливаешь в циклах задержку там, где это логически необходимо, и все, но если мы попробуем управлять двумя светодиодами с двух разных кнопок (каждой кнопки присваивается управление над определенным светодиодом)

const int
button1Pin = 2;
const int button2Pin = 3;
const int led1Pin = 4;
const int led2Pin = 5;
void setup() 
{
 pinMode(led1Pin, OUTPUT);
 pinMode(led2Pin, OUTPUT);
 pinMode(button1Pin,INPUT);
 pinMode(button2Pin,INPUT);
}                 
void loop()
{
 if
 (digitalRead(button1Pin) == HIGH) 
 {
  digitalWrite(led1Pin,HIGH);
  delay(3000);
  digitalWrite(led1Pin,LOW);
 } 
 if(digitalRead(button2Pin) == HIGH) 
 {
  digitalWrite(led2Pin,HIGH);
  delay(3000);
  digitalWrite(led2Pin,LOW);
 }
}

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

На помощь придет временной интервал millis(). Данная функция возвращает число миллисекунд/секунд после начала запуска программы, а значит когда один из двух светодиодов включен, то врем программы возвращается на первоначальное, и тогда при нажатии на любую из кнопок, загорается соответствующий светодиод.

const int
button1Pin = 2;
const int
button2Pin = 3;
const int
led1Pin = 4;
const int
led2Pin = 5;
unsigned long
led1OnTime;
unsigned long led2OnTime;
bool led1On;
bool led2On;
void setup() 
{
 pinMode(led1Pin,OUTPUT);
 pinMode(led2Pin,OUTPUT);
 pinMode(button1Pin,INPUT);
 pinMode(button2Pin,INPUT);
 led1On = false;
 led2On = false;
}
void loop()
{
 if (digitalRead(button1Pin)== HIGH) 
 {
  digitalWrite(led1Pin,HIGH);
  led1On = true;
  led1OnTime = millis();
 }
 if(digitalRead(button2Pin) == HIGH) 
 {
  digitalWrite(led2Pin,HIGH);
  led2On = true;
  led2OnTime = millis();
 }
 if(led1On)
 if(millis() -led1OnTime > 30000) 
 {
  digitalWrite(led1Pin,LOW); 
  led1On = false;
 }
 if(led2On)
 if(millis() -led2OnTime > 30000)
 {
  digitalWrite(led2Pin,LOW);
  led2On = false;
 }
}

Отличия от предыдущего скетча в том, что появляются новые переменные и строчки в коде. led1OnTime и led2OnTime сохраняют значения времени для работы каждого из светодиодов, а led1On и led2On отслеживают значение на выходе светодиода – горит он или не горит (true/false)

Таким образом, если нажмем на кнопку, то будет зафиксировано включение светодиода, и программа запомнит время включения.

При включении светодиода программа будет проверять каждый 30 секунд длительность включенного состояния, чтобы определять включен или выключен светодиод (в последнем случае длительность состояния должна будет превысить 30 секунд)

Таким образом, мы выяснили, что для циклов, содержащих в себе несколько переменных и несколько условий, желательно использовать millis()

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

Надеемся, что материал был для вас интересен, а главное полезен, и желаем всем удачной компиляции!

Купить плату Arduino Uno

Читать другие статьи по Arduino


Данная статья является собственностью Amperkot.ru. При перепечатке данного материала активная ссылка на первоисточник, не закрытая для индексации поисковыми системами, обязательна.


Поделиться: