Czas, zegar, clock w SuplaDevice

User avatar
vajera
Posts: 7286
Joined: Wed Oct 31, 2018 7:58 am
Location: Biedrusko
Has thanked: 289 times
Been thanked: 161 times

Post

nebraska wrote: Wed Jun 04, 2025 4:57 pm co byś proponował do przykładu @vajera?
To zależy jak ważne jest uruchomienie akcji co 8 sekund - jeżeli jest to bardzo istotne a uptime ma precyzję ±1 sekunda i w dodatku może jeszcze przeskakiwać 2 sekundy to zostałbym przy rozwiązaniu opartym o millis() - jest jakiś powód, dla którego nie chcesz go użyć?
Mam jeszcze drugie pytanie. Jak użyć uptime, żeby po zwolnieniu przycisku zaczął odliczać różnice i po czasie wykonał. Przykład ze zwykłym millis działa, ale nie wiem jak zrobić z uptime.

Code: Select all

loop(){

 mojeUptime.iterate(millis());

    if (action == MOJA_AKCJA) {
      Serial.println("Przycisk zwolniony");
      sensor2 = true;
      //lastTime = millis();
      mojeUptime.getUptime();
}
if ((sensor2)) { 
    if (mojeUptime.getUptime() > 5) {
     //if (millis() - lastTime > 5000) {
      Serial.println("<<< Wykonaj po 5s >>>");
      sensor2 = false;
    }
}
To samo, co powyżej?
Bramka Zigbee <=> SUPLA
Więcej informacji tutaj:
https://forum.supla.org/viewforum.php?f=127
FAQ https://forum.supla.org/viewtopic.php?t=17277
nebraska
Posts: 204
Joined: Thu Dec 08, 2022 3:00 pm
Been thanked: 1 time

Post

vajera wrote: Wed Jun 04, 2025 5:24 pm
nebraska wrote: Wed Jun 04, 2025 4:57 pm co byś proponował do przykładu @vajera?
To zależy jak ważne jest uruchomienie akcji co 8 sekund - jeżeli jest to bardzo istotne a uptime ma precyzję ±1 sekunda i w dodatku może jeszcze przeskakiwać 2 sekundy to zostałbym przy rozwiązaniu opartym o millis() - jest jakiś powód, dla którego nie chcesz go użyć?
Mam jeszcze drugie pytanie. Jak użyć uptime, żeby po zwolnieniu przycisku zaczął odliczać różnice i po czasie wykonał. Przykład ze zwykłym millis działa, ale nie wiem jak zrobić z uptime.

Code: Select all

loop(){

 mojeUptime.iterate(millis());

    if (action == MOJA_AKCJA) {
      Serial.println("Przycisk zwolniony");
      sensor2 = true;
      //lastTime = millis();
      mojeUptime.getUptime();
}
if ((sensor2)) { 
    if (mojeUptime.getUptime() > 5) {
     //if (millis() - lastTime > 5000) {
      Serial.println("<<< Wykonaj po 5s >>>");
      sensor2 = false;
    }
}
To samo, co powyżej?
Rozpatrywaniem to pod kątem czy mam się martwić przepełnieniem millisa po 50 dniach że coś tam może się zawiesić w odczytach ? I myślałem nad użyciem uptime pewnie jest to lepiej zrobione.
To takie moje rozkminy. Czy jest sens w ogóle się tym przejmować i po prostu użyć ?
If (millis()- timestamp> 5000){
timestamp= millis();
User avatar
vajera
Posts: 7286
Joined: Wed Oct 31, 2018 7:58 am
Location: Biedrusko
Has thanked: 289 times
Been thanked: 161 times

Post

nebraska wrote: Wed Jun 04, 2025 9:14 pm Rozpatrywaniem to pod kątem czy mam się martwić przepełnieniem millisa po 50 dniach że coś tam może się zawiesić w odczytach ? I myślałem nad użyciem uptime pewnie jest to lepiej zrobione.
To takie moje rozkminy. Czy jest sens w ogóle się tym przejmować i po prostu użyć ?
If (millis()- timestamp> 5000){
timestamp= millis();
To zrób tak:

Code: Select all


setup() {
....
timestamp = millis();
...}

loop() {
...
if (millis() >= timestamp) {
	if (millis() - timestamp > 5000) {
		do_something;
		timestamp = millis();
	}
} else {
     timestamp = millis();
}
Bramka Zigbee <=> SUPLA
Więcej informacji tutaj:
https://forum.supla.org/viewforum.php?f=127
FAQ https://forum.supla.org/viewtopic.php?t=17277
nebraska
Posts: 204
Joined: Thu Dec 08, 2022 3:00 pm
Been thanked: 1 time

Post

Dziękuję za przykład na pewno się do niego zastosuję.
Mógłbym prosić o wyjaśnienie to bym się czegoś nauczył z tego postu na przyszłość.
User avatar
vajera
Posts: 7286
Joined: Wed Oct 31, 2018 7:58 am
Location: Biedrusko
Has thanked: 289 times
Been thanked: 161 times

Post

nebraska wrote: Wed Jun 04, 2025 9:57 pm Dziękuję za przykład na pewno się do niego zastosuję.
Mógłbym prosić o wyjaśnienie to bym się czegoś nauczył z tego postu na przyszłość.

Code: Select all


uint32_t timestamp = 0; 

setup() { //ESP właśnie się uruchomiło 
....
timestamp = millis(); //inicjalizacja zmiennej timestamp aktualną wartością millis() 
...}

loop() { //wykonuje się cały czas, millis () ulega przepełnieniu po około 49 dniach
...
if (millis() >= timestamp) { //sprawdzamy czy millis () >= od timestamp, ponieważ wcześniej ustawiliśmy timestamp na millis () a wartość millis () wzrasta, więc ten warunek powinien być spełniony chyba, że doszło do przepełnienia - wtedy millis() będzie liczyć od zera a timestamp będzie zawierał poprzednią wartość tej funkcji czy bardzo dużą liczbę 
	if (millis() - timestamp > 5000) {
		do_something;
		timestamp = millis();
	}
} else { //tutaj doszło do przepełnienia, więc z powrotem ustawiamy timestamp na millis() i na 49 kolejnych dni mamy spokój 
     timestamp = millis();
}
Bramka Zigbee <=> SUPLA
Więcej informacji tutaj:
https://forum.supla.org/viewforum.php?f=127
FAQ https://forum.supla.org/viewtopic.php?t=17277
nebraska
Posts: 204
Joined: Thu Dec 08, 2022 3:00 pm
Been thanked: 1 time

Post

vajera wrote: Wed Jun 04, 2025 10:19 pm
nebraska wrote: Wed Jun 04, 2025 9:57 pm Dziękuję za przykład na pewno się do niego zastosuję.
Mógłbym prosić o wyjaśnienie to bym się czegoś nauczył z tego postu na przyszłość.

Code: Select all


uint32_t timestamp = 0; 

setup() { //ESP właśnie się uruchomiło 
....
timestamp = millis(); //inicjalizacja zmiennej timestamp aktualną wartością millis() 
...}

loop() { //wykonuje się cały czas, millis () ulega przepełnieniu po około 49 dniach
...
if (millis() >= timestamp) { //sprawdzamy czy millis () >= od timestamp, ponieważ wcześniej ustawiliśmy timestamp na millis () a wartość millis () wzrasta, więc ten warunek powinien być spełniony chyba, że doszło do przepełnienia - wtedy millis() będzie liczyć od zera a timestamp będzie zawierał poprzednią wartość tej funkcji czy bardzo dużą liczbę 
	if (millis() - timestamp > 5000) {
		do_something;
		timestamp = millis();
	}
} else { //tutaj doszło do przepełnienia, więc z powrotem ustawiamy timestamp na millis() i na 49 kolejnych dni mamy spokój 
     timestamp = millis();
}
Bardzo, bardzo dziękuję zawsze miałem z tym problem. Złota informacja dla mnie.
User avatar
klew
Posts: 13905
Joined: Thu Jun 27, 2019 12:16 pm
Location: Wrocław
Has thanked: 134 times
Been thanked: 137 times

Post

Jeśli używasz uint32 to nie ma potrzeby martwić się przepełnieniem, bo obliczanie różnicy czasu działa poprawnie nawet po przekręceniu licznika.
Także zapis: millis() - timestamp jest poprawny i nie generuje błędów o ile nie liczymy długich odstępów czasu około 25 dni.

uptime służy do czegoś innego. Tutaj millis jest najlepszym rozwiązaniem
Najlepsze suple dla Twojego domu :mrgreen:
User avatar
vajera
Posts: 7286
Joined: Wed Oct 31, 2018 7:58 am
Location: Biedrusko
Has thanked: 289 times
Been thanked: 161 times

Post

klew wrote: Thu Jun 05, 2025 6:08 am Jeśli używasz uint32 to nie ma potrzeby martwić się przepełnieniem, bo obliczanie różnicy czasu działa poprawnie nawet po przekręceniu licznika.
Także zapis: millis() - timestamp jest poprawny i nie generuje błędów o ile nie liczymy długich odstępów czasu około 25 dni.

uptime służy do czegoś innego. Tutaj millis jest najlepszym rozwiązaniem
W teorii możliwa jest taka sytuacja:
  1. timestamp = millis() = UINT32_MAX - 3000,
  2. wtedy warunek millis() - timestamp > 5000 nie zdąży się spełnić i millis() zacznie liczyć od zera a timestamp nadal będzie == UINT32_MAX - 3000 i nie zaktualizuje się przez kolejne 49 dni albo I dłużej?
Bramka Zigbee <=> SUPLA
Więcej informacji tutaj:
https://forum.supla.org/viewforum.php?f=127
FAQ https://forum.supla.org/viewtopic.php?t=17277
User avatar
klew
Posts: 13905
Joined: Thu Jun 27, 2019 12:16 pm
Location: Wrocław
Has thanked: 134 times
Been thanked: 137 times

Post

vajera wrote: Thu Jun 05, 2025 10:45 am W teorii możliwa jest taka sytuacja:
  1. timestamp = millis() = UINT32_MAX - 3000,
  2. wtedy warunek millis() - timestamp > 5000 nie zdąży się spełnić i millis() zacznie liczyć od zera a timestamp nadal będzie == UINT32_MAX - 3000 i nie zaktualizuje się przez kolejne 49 dni albo I dłużej?
Rozumiem, że:

Code: Select all

timestamp = UINT32_MAX - 3000;
czyli 3 s przed przepełnieniem uint32

Następnie millis się przekręca i liczy od zera. Po ~2 s zwraca 2051.

W arytmetyce "unsigned":

Code: Select all

(millis() - timestamp == 5051);
czyli:
if (millis() - timestamp > 5000) -> true
Wynika to z tego, że wynik odejmowania też się "przekręca" i pokaże prawidłową wartość.

Na przykładzie uint8_t

Code: Select all

uint8_t a = 250;
uint8_t b = 2;
uint8_t c = b - a;
std::cout << c;
>> 8
[code]
Czyli mamy prawidłową "odległość" między  oboma czasami.
Najlepsze suple dla Twojego domu :mrgreen:
User avatar
vajera
Posts: 7286
Joined: Wed Oct 31, 2018 7:58 am
Location: Biedrusko
Has thanked: 289 times
Been thanked: 161 times

Post

klew wrote: Thu Jun 05, 2025 11:00 am Rozumiem, że:

Code: Select all

timestamp = UINT32_MAX - 3000;
czyli 3 s przed przepełnieniem uint32

Następnie millis się przekręca i liczy od zera. Po ~2 s zwraca 2051.

W arytmetyce "unsigned":

Code: Select all

(millis() - timestamp == 5051);
czyli:
if (millis() - timestamp > 5000) -> true
Wynika to z tego, że wynik odejmowania też się "przekręca" i pokaże prawidłową wartość.

Na przykładzie uint8_t

Code: Select all

uint8_t a = 250;
uint8_t b = 2;
uint8_t c = b - a;
std::cout << c;
>> 8
Czyli mamy prawidłową "odległość" między oboma czasami.
Oczywiście masz rację, tylko wtedy ten warunek

Code: Select all

if (millis() >= timestamp) 
nie będzie spełniony, więc trzeba z niego zrezygnować.

Mój kod ma jedynie taką zaletę, że jest odporny na sytuację, gdy ktoś modyfikując kod zmieni sobie timestamp na np. int32_t lub int64_t lub gdy odstęp faktycznie przekracza 25 dni ;)

Return to “Arduino IDE”