Используем функции delay() и millis() в Arduino IDE правильно

Использование DELAY и постановка проблемы

Одна из основных ошибок новичков при написании скетчей для Arduino – чрезмерное использование функции delay().

Эта функция, (как указано в официальной документации) останавливает выполнение программы на указанное количество милисекунд. Давайте рассмотрим пример: вы подключили к Arduino кнопку и светодиод; когда вы нажимаете на кнопку, светодиод должен зажечься на 3 секунды.

Скетч может выглядеть примерно следующим образом (несолько модифицированная версия из оффициального туториала):

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():

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);

}

}

Схема подключения с использованием breadboard'a в данном случае выглядит так:

Arduino - delay и millis на примере светодиодов

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

Используем MILLIS

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

Если вам надо узнать, когда прошло заданное время, вы можете:

сохранить в переменной начальное время, то есть момент времени, когда вы включили светодиод.

Периодически проверять (например, в теле цикла loop), разницу между начальным временем и фактическим на данный момент.

Ниже приведен новый скетч:

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), чтобы оценивать текущий статус светодиодов (вкл. или выкл. (on/off) или в булевом типе — true/false).

Когда кнопка нажата, скетч заставляет светодиод включится, сохраняет текущее время и меняет значение в переменной статуса.

Если светодиод горит (переменная состояния равна true), скетч периодечески проверяет длительность состояния вкл. (30 секунд, то есть 30000 милисекунд): если период превышает допустимый (30 секунд 30000 миллисекунд), то это значит, что светодиод выключен.

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