blink на millis

Все помнят базовый пример blink.ino:

1
2
3
4
5
6
7
8
9
10
11
12
int led = 13;
 
void setup() {                
	pinMode(led, OUTPUT);     
}
 
void loop() {
	digitalWrite(led, HIGH);
	delay(1000);
	digitalWrite(led, LOW);
	delay(1000);
}

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

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

millis() - это функция, которая возвращает количество миллисекунд с начала работы программы.

Тип возвращаемого ей значения - unsigned long. В Arduino слово long означает, что для хранения переменной используется 4 байта. Таким образом, переменная типа long может принимать 2 в 32-ой степени значений почти поравну слева и справа от нуля: от -2,147,483,648 до 2,147,483,647. Слово unsigned означает, что переменная беззнаковая, то есть заведомо не может принимать отрицательные значения. Тода мы можем сохранить в четырех байтах значения от 0 до 4,294,967,295. Выглядит много. Посчитаем примерно на сколько этого хватит:

4294967295 миллисекунд = 4294967 секунд = 71583 минуты = 1193 часа = 49,7 суток. То есть почти 50 дней.

Во время работы нашей программы мы будем заставлять функцию millis() отдавать нам текущее время, сравнивать это время с временем последнего интересного нам события, если обнаруживаем ВРЕМЯ Х, то действуем и передвигаем время последнего интересного события на текущий момент.

Для начала зададимся номером пина для блинка и временем блинка:

1
2
#define LED_PIN 13
#define BLINK_TIME 500

 Теперь объявим переменную для хранения времени последнего интересного события. Она должна иметь такой же тип, который возвращает millis():

1
unsigned long timerPrev = 0;

В сетапе ничего примечательного:

1
2
3
void setup(){
	pinMode(LED_PIN, OUTPUT);
}

В лупе делаем так, как задумали:

1
2
3
4
5
6
void loop(){
	if (millis()-timerPrev > BLINK_TIME){
		//рандомные действия
		timerPrev = millis();
	}
}

Теперь каждый период времени, равный BLINK_TIME мы будем делать действия, которые мы хотим. А хотим мы блинкать. Надо что-то вставить в место, которое обозначено "рандомные действия"

Можно написать что-то типа такого:

1
2
3
4
5
6
7
8
if (ledState == LOW){
	digitalWrite(LED_PIN, HIGH);
	ledState = HIGH;
}
else {
	digitalWrite(LED_PIN,LOW);
	ledState = LOW;
}

 Предварительно объявив перед сетапом глобальную переменную булевого типа:

1
boolean ledState = 0;

 Но это очень скучно и неинтересно. Мы обойдемся одной строчкой:

1
digitalWrite(LED_PIN, !digitalRead(LED_PIN));

Что творим? Читаем значение на пине, инвертируем его с помощью восклитательного знака, пишем полученное значение в обратно пин!

 Полный текст скетча:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#define LED_PIN 13
#define BLINK_TIME 500
 
unsigned long timerPrev = 0;
 
void setup(){
	pinMode(LED_PIN, OUTPUT);
}
 
void loop(){
	if (millis()-timerPrev > BLINK_TIME){
		digitalWrite(LED_PIN, !digitalRead(LED_PIN));
		timerPrev = millis();
	}
}

Блинкайте с удовольствием!

Метки: программирование, Arduino, код, millis