Используем функции 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 в данном случае выглядит так:
Вероятно, вы уже заметили проблему: когда один светодиод включен, вы не можете включить второй! Причина простая: когда первый светодиод включен, ваш скетч останавливает свою работу и, соответственно, не может проверить состояние второй кнопки...
Используем 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 миллисекунд), то это значит, что светодиод выключен.
Оставляйте Ваши комментарии, вопросы и делитесь личным опытом ниже. В дискуссии часто рождаются новые идеи и проекты!