Pomiar czasu to niemalże podstawowa procedura mikrokontrolera w systemach automatyki. Za pomocą Arduino IDE można to zrobić na kilka sposobów
- prosto - pulseIn - funkcja Arduini IDE
- mój ulubiony sposób - pomiar czasu w poolingu
- profesjonalnie - pomiar czasu z wykorzystaniem przerwań
Ad1 Funkcja Arduini IDE - pulseIn()
To podstawowa funkcja Arduino IDE pomiaru czasu wysokiego lub niskiego stanu na określonym pinie mikrokontrolera. Jest banalnie prosta w użyciu
int els_pin = 4;
void elssetup() {
pinMode(els_pin, INPUT);
}
void elsakcja() {
long duration;
duration = pulseIn(els_pin, LOW);
Serial.println(duration);
}
Ponoć działa też na ESP8266. Nie sprawdziłem bo funkcja pulseIn ma jedną zasadniczą wadę. Wstrzymuje pracę programu przez cały czas pomiaru długości impulsu. Dla zakładanych maksymalnie 40 sekund długości impulsu funkcja rozwali totalnie działanie całego systemu. pulseIn() - do kosza
Ad 2 Pomiar czasu w poolingu
Jak już wielokrotnie deklarowałem pooling (cykliczne odpytywanie) to mój ulubiony sposób obsługi różnych procedur. Przede wszystkim dlatego, że używa go podstawowa aplikacja zarządzająca moimi systemami IoT - BLYNK. I ulubiona biblioteka zegarowa timers.h także. To w zasadzie wyczerpuje znamiona uzasadnienia ale jest jeszcze jedno bardzo istotne - pooling jak do tej pory nigdy mnie nie zawiódł nawet w bardzo skomplikowanych, jak na mnie, projektach. Tak naprawdę to bardzo prosta i klarowna procedura dająca się łatwo konfigurować i testować.
Jak w moim programie działa pooling do odczytu długości impulsu? Banalnie prosto
- czytam w kółko port czujnika LED licznika energii
- jeśli stan portu uległ zmianie odejmuję od aktualnego czasu poprzednio zapamiętany i dostaję wynik długości impulsu
- zapamiętuję aktualny czas i wracam do punktu 1
void elsakcja() {
unsigned long duration;
if (stan_els == digitalRead(els_pin)); else {
stan_els = digitalRead(els_pin);
unsigned long temp_time_els = millis(); // zapamiętanie wartości czasu
duration = temp_time_els - time_els;
time_els = temp_time_els;
Serial.println(duration);
}
}
A efekt?
Program w poolingu obsługuje pomiar długości impulsu, BLYNKa i bibliotekę Timers.h. Pomimo tego pomiar daje dokładność na poziomie 0,01%. dla najkrótszych czasów impuslsów (największych mocy) Całkiem nieźle. Pomiary są stabilne i powtarzalne a cały program pracuje bez zacięć i przerw.
Co prawda program nie jest zbyt rozbudowany toteż nie wiadomo jaki wpływ na pomiar długości impulsu będzie miał ostateczny kształt programu ale jak na razie trzeba uznać pomiar w poolingu za absolutnie zadowalający.
To podstawowy i zalecany przez wszystkie podręczniki programowania sposób pomiaru czasu. Zmiana stanu (z 0 > 1 lub odwrotnie) przerywa działanie programu głównego uruchamiając podprogram obsługi przerwania.
W podprogramie rejestrowany jest aktualny czas i porównywany z czasem z poprzedniego przerwania. Różnica obu czasów daje długość mierzonego impulsu. Następnie program powraca do wykonywania pętli głównej kodu.
Gotowy kod do licznika energii i to działający z BLYNKiem już ktoś przygotował i znajduje się tu>>>>>
Najważniejsza część programu to obsługa przerwania uruchamiana poleceniem
attachInterrupt(els_pin, onPulse, FALLING);
Przerwanie ustawione jest na porcie els_port, na zboczu opadającym z 1 > 0 i wywołuje podprogram onPulse
void onPulse() // The interrupt routine
{
lastTime = pulseTime;
pulseTime = micros();
pulseCount++;
power = (3600000000.0 / (pulseTime - lastTime))/ppwh; //Calculate power
elapsedkWh = (1.0*pulseCount/(ppwh*1000)); // convert wh to kwh
Serial.print(power,4); Serial.print(" "); Serial.println(elapsedkWh,3);
}
Wszystko wygląda łatwo i przejrzyście ale ...
Programy z przerwaniami to jeden z najtrudniejszych (jak dla mnie) elementów programowania. Przerwania stosuje się do obsługi przypadkowych zdarzeń. Nie znany jest więc czas wystąpienia ani miejsce w kodzie gdzie program zostanie na chwilę przerwany. Jeśli cokolwiek pójdzie nie tak ( z powodu naszego błędu, błędu kompilacji czy siły wyższej) znalezienie przyczyny bez specjalnych sprzętowych narzędzi typu debugger graniczy z cudem. Np. wystarczy nie dodać słynnego słówka volatile do zmiennej obsługiwanej w przerwaniu i nasz program może " nie zauważyć skutków działania przerwania.
Przerwania to potężne narzędzie programowania mikrokontrolerów i niezbędne np. w systemach wielowątkowych ale należy je używać jak strzelbę - z pełną świadomością ewentualnych skutków.
Akurat program obsługi czujnika LED licznika energii nie powinien sprawić kłopotów ale dla przezorności warto zmienić deklaracje zmiennych w tym programie na
volatile long pulseCount = 0; //Used to measure power.
volatile unsigned long pulseTime,lastTime;
volatile double power, elapsedkWh; //power and energy
Za to skutek działania programu pomiaru czasu impulsu opartego na przerwaniach jest wręcz rewelacyjny
Walka pomiędzy poolingiem a przerwaniem wydaje się nierozstrzygnięta. Obie więc metody będą brane pod uwagę w trakcie dalszych prac nad systemem monitoringu licznika energii.
LEDa licznika energii zasymulowałem LEDem na płytce sterowanym z D1MINI. Żółty suwak zmienia częstotliwość błysków. Długość Świecenia LEDa jest stała - ok 10 ms. Czas przerwy jest zmieniany suwakiem od 1 do 400 x 100ms to znaczy od 100 ms do 40 sek co odpowiada mocy od 32 kW do 100 W (około).
Który ze sposobów pomiaru czasu pozostanie na placu boju czas i ewentualny ciąg dalszy pokaże ...
Poprzednie wpisy z tego tematu
http://100-x-arduino.blogspot.com/2018/06/czujnik-led-licznika-energii.html
Przydatne linki
http://www.instructables.com/id/Esp8266-12-blynk-wireless-electric-power-meter/
https://learn.openenergymonitor.org/electricity-monitoring/pulse-counting/interrupt-based-pulse-counter
LEDa licznika energii zasymulowałem LEDem na płytce sterowanym z D1MINI. Żółty suwak zmienia częstotliwość błysków. Długość Świecenia LEDa jest stała - ok 10 ms. Czas przerwy jest zmieniany suwakiem od 1 do 400 x 100ms to znaczy od 100 ms do 40 sek co odpowiada mocy od 32 kW do 100 W (około).
Który ze sposobów pomiaru czasu pozostanie na placu boju czas i ewentualny ciąg dalszy pokaże ...
Poprzednie wpisy z tego tematu
http://100-x-arduino.blogspot.com/2018/06/czujnik-led-licznika-energii.html
Przydatne linki
http://www.instructables.com/id/Esp8266-12-blynk-wireless-electric-power-meter/
https://learn.openenergymonitor.org/electricity-monitoring/pulse-counting/interrupt-based-pulse-counter
https://edu.pjwstk.edu.pl/wyklady/swb/scb/SWBwyklad10i.pdf
http://www.avdweb.nl/arduino/libraries/frequency-period-counter.html
http://www.avdweb.nl/arduino/libraries/frequency-period-counter.html
143
Niezwykle pouczający jest ten wpis. Bardzo mi się podoba.
OdpowiedzUsuńto reklama ale ciekawa więc zostawiam ci ten komentarz
OdpowiedzUsuń