В этом посте вы можете скачать маленькую библиотеку для ARDUINO в которой реализован таймер для создания задержки в ARDUINO без delay() с проверкой millis() на переполнение.
В необходимости реализации задержки без delay сомнений нет, т.к. останавливать работу всего устройства для ожидания чего-либо это не корректно. Можно конечно копипастить в каждый скетч одну и ту же функцию, но реализация задержки с помощью объекта гораздо проще.
Ардуино. Задержка без delay() с помощью millis(). Библиотека Timer.
Описание библиотеки можно посмотреть здесь: Задержка в ARDUINO без delay()
Текущая версия: 0.0.2 / 2019.01.28
Изменения:
1. Тип возвращаемых данных методом getState() стал enum;
2. При вызове метода setTime() метод reset() выполняется сразу внутри него.
Предыдущие версии:
0.0.1 / 2018.10.31 / http://allforproject.ru/sdm_downloads/arduino-lib-timer/
Size: 3 KB
Version: 0.0.2
655 Загрузки
Файлы библиотеки:
Timer.h
#ifndef Timer_h
#define Timer_h
#include "Arduino.h"
class Timer {
public:
Timer(); //конструктор по-умолчанию
Timer(uint32_t delayTime); //конструктор №1, принимает время задержски в мс
enum timerState {
READY,
COUNTDOWN,
DELAY_OVER,
PAUSED
};
void delay(); //выполняет задержку, результат сохраняет в state
void start(); //запускает таймер
void stop (); //останавливает таймер, с сохнанением оставшегося времени задержки
void reset (); //подготавливает таймер к запуску, восстанавливая время задержки
void setTime(uint32_t delayTime); //изменяет время задержки
uint32_t getTime (); //возвращает установленное время задержки
timerState getState ();
protected:
uint32_t _delayTime; //хранит время задержки
private:
timerState state ;
uint32_t _timeStore; //хранит millis()
uint32_t _delayTimeBuffer; //буфер для работы с временем задержки
};
#endif
Timer.cpp
#include "Arduino.h"
#include "Timer.h"
Timer::Timer(){
_delayTime = 0;
state = timerState::DELAY_OVER;
};
Timer::Timer(uint32_t delayTime){
_delayTime = delayTime;
reset();
};
void Timer::delay(){
if(state == timerState::COUNTDOWN){
if (millis() < _timeStore){
if(millis() + 4294967295 - _timeStore > _delayTimeBuffer) {state = timerState::DELAY_OVER;}
}
else{
if(millis () > _timeStore + _delayTimeBuffer) {state = timerState::DELAY_OVER;}
}
}
};
void Timer::start(){
if ((state == timerState::READY) || (state == timerState::PAUSED)){
state = timerState::COUNTDOWN;
_timeStore = millis();
}
};
void Timer::stop(){
state = timerState::PAUSED;
if (millis() < _timeStore){ _delayTimeBuffer = _delayTimeBuffer - (millis() + 4294967295 - _timeStore);}
else{_delayTimeBuffer = _delayTimeBuffer - (millis() - _timeStore);}
};
void Timer::reset(){
state = timerState::READY;
_delayTimeBuffer = _delayTime;
}
void Timer::setTime(uint32_t delayTime){
_delayTime = delayTime;
reset();
};
uint32_t Timer::getTime (){return _delayTime;};
Timer::timerState Timer::getState (){
return state;
};
Комментарий по работе:
После создания объекта с помощью конструктора по-умолчанию необходимо указать время задержки с помощью метода setTime(). Далее необходимо выполнить метод start(), который по сути является триггером для метода delay(), он устанавливает state в состояние COUNTDOWN. Теперь крутим delay() и контролируем состояние свойства state с помощью метода getStatus(). Как только он станет примет значение DELAY_OVER delay() выполняться перестает, что свидетельствует об окончании задержки.
Предусмотрена возножность остановки таймера с помощью метода stop(), с сохранением оставшегося времени задержки и возможности дальнейшего запуска методом start(). После окончания задержки таймер необходимо «взвести» методом reset(), после этого его можно использовать снова.
Скетч для проверки:
#include <Timer.h>
Timer timer(5000); // создаем объект таймер с задержкой 5 сек
//Timer timer ;
void setup() {
Serial.begin(9600);
//timer.setTime(2000);
}
void loop() {
timer.delay(); //крутим в цикле функцию задержки
if (timer.getState() == Timer::timerState::COUNTDOWN) Serial.print (F("."));
if (timer.getState() == Timer::timerState::DELAY_OVER) {
Serial.println();
Serial.println (F("Delay over!"));
timer.reset();
} ;
test();
//delay (500);
}
void test() {
if (Serial.available()) {
byte symbol = Serial.read();
switch (symbol){
case '0' :
Serial.println();
Serial.println(F("0 pressed"));
timer.start(); // старт таймера
break;
case '1' :
Serial.println();
Serial.println(F("1 pressed"));
timer.stop(); // остановка таймера
break;
case '2' :
Serial.println();
Serial.println(F("2 pressed"));
timer.setTime(10000); // установка времени задержки
break;
}
}
}
Добрый день. Много искал библиотеки с таймерами. Ваша понравилась комментариями. Но программа не компилируется для Ардуино Нано. В чём может быть причина?
Плата:»Arduino Nano, ATmega328P»
Ошибка компиляции для платы Arduino Nano.
Радик здравствуйте! Укажите в комментарии лог компилятора. К сожалению ардуино нано нет под рукой и проверить не могу. На меге и уно все компилируется.
Добрый вечер. Ардуино нано уже использовал в другом проекте. Надеюсь на днях придёт ещё посылка с ардуинками, Тогда обязательно ещё раз всё проверю и отпишусь. Спасибо.
Arduino: 1.8.9 (Windows 10), Плата:»MH-ET LIVE Tiny88(16.0MHz)»
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp: In constructor ‘Timer::Timer()’:
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp:13:9: error: ‘timerState’ is not a class or namespace
state = timerState::DELAY_OVER;
^
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp: In member function ‘void Timer::delay()’:
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp:20:17: error: ‘timerState’ is not a class or namespace
if(state == timerState::COUNTDOWN){
^
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp:22:81: error: ‘timerState’ is not a class or namespace
if(millis() + 4294967295 — _timeStore > _delayTimeBuffer) {state = timerState::DELAY_OVER;}
^
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp:25:68: error: ‘timerState’ is not a class or namespace
if(millis () > _timeStore + _delayTimeBuffer) {state = timerState::DELAY_OVER;}
^
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp: In member function ‘void Timer::start()’:
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp:30:19: error: ‘timerState’ is not a class or namespace
if ((state == timerState::READY) || (state == timerState::PAUSED)){
^
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp:30:51: error: ‘timerState’ is not a class or namespace
if ((state == timerState::READY) || (state == timerState::PAUSED)){
^
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp:31:17: error: ‘timerState’ is not a class or namespace
state = timerState::COUNTDOWN;
^
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp: In member function ‘void Timer::stop()’:
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp:36:13: error: ‘timerState’ is not a class or namespace
state = timerState::PAUSED;
^
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp: In member function ‘void Timer::reset()’:
C:\Program Files (x86)\Arduino\libraries\Timer\Timer.cpp:41:13: error: ‘timerState’ is not a class or namespace
state = timerState::READY;
^
exit status 1
Ошибка компиляции для платы MH-ET LIVE Tiny88(16.0MHz).
Этот отчёт будет иметь больше информации с
включенной опцией Файл -> Настройки ->
«Показать подробный вывод во время компиляции»
Евгений, выложите пожалуйста скетч который вы компилируете. Лог ошибок это хорошо, но можно увидеть весь сервиз?
Это компиляция примера который был в комплекте с библиотекой.
Arduino: 1.8.9 (Windows 10), Плата:»MH-ET LIVE Tiny88(16.0MHz)»
Изменены опции сборки, пересобираем все
C:\Program Files (x86)\Arduino\libraries\Timer\example\example.ino: In function ‘void loop()’:
example:11:34: error: ‘Timer::timerState’ is not a class or namespace
if (timer.getState() == Timer::timerState::COUNTDOWN) Serial.print (F(«.»));
^
example:12:34: error: ‘Timer::timerState’ is not a class or namespace
if (timer.getState() == Timer::timerState::DELAY_OVER) {
^
exit status 1
‘Timer::timerState’ is not a class or namespace
Этот отчёт будет иметь больше информации с
включенной опцией Файл -> Настройки ->
«Показать подробный вывод во время компиляции»
Евгений, похоже по какой-то причине компилятор вместо типа данных ENUM распознает в переменной timerState класс или пространство имен, через оператор доступа «::».
Интересно что для другого типа платы все ОК
Евгений, скачайте старую версию. Ссылка есть в описании. Там нет ENUMa.