Okazało się, że nie mogę używać biblioteki Timer razem z CayenneMQTTESP8266 ponieważ występuje konflikt klas. Potrzebowałem funkcji, która będzie odmierzała czas po zanotowaniu ustania ruchu przez czujnik mikrofalowy. Oczywiście zatrzymująca pracę procesora funkcja delay() nie wchodzi w rachubę. W czasie gdy procesor jest blokowany inny czujnik może potrzebować uwagi. Znalazłem w necie artykuł i podobną do Timer bibliotekę millisDelay. Świetnie się nadaje do mojego projektu.
keywords.txt
millisDelay KEYWORD1
start KEYWORD2
stop KEYWORD2
repeat KEYWORD2
restart KEYWORD2
finish KEYWORD2
isFinished KEYWORD2
isRunning KEYWORD2
getStartTime KEYWORD2
remaining KEYWORD2
delay KEYWORD2
Najprostszy szkic zastępujący funkcję delay()
#include <millisDelay.h> int led = 13; // Pin 13 has an LED connected on most Arduino boards. millisDelay ledDelay; void setup() { // initialize the digital pin as an output. pinMode(led, OUTPUT); digitalWrite(led, HIGH); // turn led on // start delay ledDelay.start(10000); } void loop() { // check if delay has timed out if (ledDelay.isFinished()) { digitalWrite(led, LOW); // turn led off } }
Zastosowanie metody repeat()
#include <millisDelay.h> int led = 13; // Pin 13 has an LED connected on most Arduino boards. bool ledOn = false; // keep track of the led state millisDelay ledDelay; void setup() { // initialize the digital pin as an output. pinMode(led, OUTPUT); // initialize the digital pin as an output. digitalWrite(led, LOW); // turn led off ledOn = false; // start delay ledDelay.start(1500); } void loop() { // check if delay has timed out if (ledDelay.isFinished()) { ledDelay.repeat(); // start delay again without drift // toggle the led ledOn = !ledOn; if (ledOn) { digitalWrite(led, HIGH); // turn led on } else { digitalWrite(led, LOW); // turn led off } } }
Oprócz objaśnionych przykładami metod start(zwłoka), isFinished() i repeat(), biblioteka millisDelay używa też następujących metod:
- stop(), która pauzuje odliczanie zwłoki (isFinished() nadal przyjmuje wartość false),
- isRunning() dzięki której sprawdzamy czy odliczanie trwa,
- restart() ponawia odliczanie z wcześniej określoną zwłoką,
- finish() wymusza wcześniejsze zakończenie odliczania zwłoki,
- remaining() zwraca ilość milisekund aż odliczanie zwłoki się zakończy
- delay() zwraca wartość zwłoki ustalonej metodą start()
Bardziej skomplikowany program korzystający z biblioteki millisDelay.h
#include <millisDelay.h> /* (c)2018 Forward Computing and Control Pty. Ltd. NSW Australia, www.forward.com.au This code is not warranted to be fit for any purpose. You may only use it at your own risk. This generated code may be freely used for both private and commercial use provided this copyright is maintained. */ #define DEBUG int led = 13; bool ledOn = false; // keep track of led On/Off // Pin 13 has an LED connected on most Arduino boards. // if using Arduino IDE 1.5 or above you can use pre-defined // LED_BUILTIN instead of 'led' // const unsigned long MAIN_TIME = 10000; // in mS const unsigned long FIRST_PART_DELAY = 4000; // in mS const unsigned long FREEZE_TIME = 2000; // in mS millisDelay mainDelay; // the delay object, the overall delay millisDelay firstPartDelay; // the delay object, the delay until we 'freeze' the main delay millisDelay freezeDelay; // the delay object, the delay of the 'freeze' after which we 're-start' the main delay unsigned long mainRemainingTime = 0; unsigned long currentMillis = 0; // the setup routine runs once when you press reset: void setup() { #ifdef DEBUG Serial.begin(9600); // wait a few sec to let user open the monitor for (int i = 10; i > 0; i--) { Serial.print(i); Serial.print(' '); delay(500); } Serial.println(); #endif // initialize the digital pin as an output. pinMode(led, OUTPUT); mainDelay.start(MAIN_TIME); currentMillis = millis(); // capture current time for print firstPartDelay.start(FIRST_PART_DELAY); #ifdef DEBUG // NOTE: prints take time so do them AFTER setting up the delays Serial.print("start mainDelay at:"); Serial.print(currentMillis); Serial.print(" for "); Serial.print(MAIN_TIME); Serial.println("mS"); #endif } void loop() { if (mainDelay.isRunning()) { digitalWrite(led, HIGH); // led on while main delay is running } else { digitalWrite(led, LOW); // led off otherwise } if (mainDelay.justFinished()) { digitalWrite(led, LOW); // turn the led off #ifdef DEBUG Serial.print("mainDelay finished at:"); Serial.print(millis()); Serial.println(); #endif } if (firstPartDelay.justFinished()) { // finished first part of main delay if (mainDelay.isRunning()) { mainRemainingTime = mainDelay.remaining(); // remember how long left to run in the main delay // NOTE: need to call remaining() BEFORE calling stop(). After calling stop() remaining will return 0 (ALWAYS) mainDelay.stop(); // stop mainDelay. NOTE: mainDelay.justFinished() is NEVER true after stop() freezeDelay.start(FREEZE_TIME); // start freeze delay currentMillis = millis(); // capture current time for print // NOTE: need to capture remaining() and start freeze delay BEFORE doing debug prints as the prints take noticeble time to output. digitalWrite(led, LOW); // turn the led off #ifdef DEBUG Serial.print("'Freeze' mainDelay at:"); Serial.print(currentMillis); Serial.print(" for "); Serial.print(FREEZE_TIME); Serial.println("mS"); Serial.print(" mainDelay has "); Serial.print(mainRemainingTime); Serial.print("mS remaining"); Serial.println(); #endif } } if (freezeDelay.justFinished()) { if (mainRemainingTime > 0) { // start mainDelay again currentMillis = millis(); // capture current time for print mainDelay.start(mainRemainingTime); digitalWrite(led, HIGH); // turn the led on #ifdef DEBUG Serial.print("Restart mainDelay after 'freeze' at:"); Serial.print(currentMillis); Serial.println(); #endif } } }