Czas, zegar, clock w SuplaDevice

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 11:20 am 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 ;)
Twój kod nie zadziała przy tych odstępach > 25 dni.

Argument w stylu: "jak ktoś zrobi błąd, to nadal będzie działać"; jest nietrafiony :P. Jak jest błąd, to trzeba poprawić.

Zresztą Twój kod i tak nie zadziała poprawnie. Tzn. będzie się wykonywał co 5 s przez ~49 dni, a potem przestanie... :P
Najlepsze suple dla Twojego domu :mrgreen:
User avatar
vajera
Posts: 7285
Joined: Wed Oct 31, 2018 7:58 am
Location: Biedrusko
Has thanked: 288 times
Been thanked: 161 times

Post

klew wrote: Thu Jun 05, 2025 11:33 am
vajera wrote: Thu Jun 05, 2025 11:20 am 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 ;)
Twój kod nie zadziała przy tych odstępach > 25 dni.
Powinien zadziałać, ale może czegoś nie widzę? ;)
Argument w stylu: "jak ktoś zrobi błąd, to nadal będzie działać"; jest nietrafiony :P. Jak jest błąd, to trzeba poprawić.
Pełna zgoda, od grudnia to mój chleb powszedni ;)
Zresztą Twój kod i tak nie zadziała poprawnie. Tzn. będzie się wykonywał co 5 s przez ~49 dni, a potem przestanie... :P
Powinien zadziałać, ale może czegoś nie widzę? ;)
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 12:15 pm Powinien zadziałać, ale może czegoś nie widzę? ;)
Tam masz:

Code: Select all

setup:
timestamp = millis();

loop:
if (millis() >= timestamp) {    // Warunek 1
  if (millis() - timestamp > 5000) {   // Warunek 2
    akcja_co_5s();
    timestamp = millis();
  }
}
No i przez 49 dni to działa ok. Potem timestamp dostaje wartość około UINT32_MAX - 2000, a millis się przekręca i liczy od 0.
Wtedy Warunek 1 będzie niespełniony na pewno przez kolejne 49 dni i akcja_co_5s() przestanie się wykonywać.
Najlepsze suple dla Twojego domu :mrgreen:
User avatar
vajera
Posts: 7285
Joined: Wed Oct 31, 2018 7:58 am
Location: Biedrusko
Has thanked: 288 times
Been thanked: 161 times

Post

klew wrote: Thu Jun 05, 2025 12:51 pm
vajera wrote: Thu Jun 05, 2025 12:15 pm Powinien zadziałać, ale może czegoś nie widzę? ;)
Tam masz:

Code: Select all

setup:
timestamp = millis();

loop:
if (millis() >= timestamp) {    // Warunek 1
  if (millis() - timestamp > 5000) {   // Warunek 2
    akcja_co_5s();
    timestamp = millis();
  }
}
No i przez 49 dni to działa ok. Potem timestamp dostaje wartość około UINT32_MAX - 2000, a millis się przekręca i liczy od 0.
Wtedy Warunek 1 będzie niespełniony na pewno przez kolejne 49 dni i akcja_co_5s() przestanie się wykonywać.
To fakt, ale to dlatego, że obciąłeś fragment mojego kodu ;)

Code: Select all

} 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();
 }
 
To powinno ogarnąć problem zarówno tych 25 jak i 49 dni.
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 12:54 pm
To powinno ogarnąć problem zarówno tych 25 jak i 49 dni.
Ok, nie skorolowałem odpowiednio i nie widziałem :)

Ale problem 25 dni to nie rozwiązuje. Np. jeśli chcesz uruchomić coś raz na 30 dni, to warunek będzie miał przyrównanie do (30*24*60*60*1000).
I zadziała to raz po 30 dniach od startu, a potem przy przekręceniu licznika timestamp ustawi się na "0", więc kolejne wykonanie będzie po około 50 dniach, a nie 30.
Ale nie ważne ;)
Najlepsze suple dla Twojego domu :mrgreen:
User avatar
vajera
Posts: 7285
Joined: Wed Oct 31, 2018 7:58 am
Location: Biedrusko
Has thanked: 288 times
Been thanked: 161 times

Post

klew wrote: Thu Jun 05, 2025 1:08 pm
vajera wrote: Thu Jun 05, 2025 12:54 pm
To powinno ogarnąć problem zarówno tych 25 jak i 49 dni.
Ok, nie skorolowałem odpowiednio i nie widziałem :)

Ale problem 25 dni to nie rozwiązuje. Np. jeśli chcesz uruchomić coś raz na 30 dni, to warunek będzie miał przyrównanie do (30*24*60*60*1000).
I zadziała to raz po 30 dniach od startu, a potem przy przekręceniu licznika timestamp ustawi się na "0", więc kolejne wykonanie będzie po około 50 dniach, a nie 30.
Ale nie ważne ;)
Masz rację - problemu 25 dni to nie rozwiązuje.

Code: Select all


uint64_t timestamp_64b  = 0;
uint64_t millis_64b   = 0;

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

loop {
...
millis_64b += millis ();

if (millis_64b - timestamp_64b > 5000) {
...do_somethibg_every_5_seconds 
timestamp_64b = millis_64b;
}

To powinno rozwiązać problem na 500 mln lat 🤣
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

Raczej timestamp64b nie możesz zwiększać o millis(), bo to będzie bardzo szybko rosło. Należałoby zwiększać o przyrost millis().
Ale są też na to lepsze mechanizmy, szczególnie w nowszych wersjach c++
Najlepsze suple dla Twojego domu :mrgreen:
nebraska
Posts: 204
Joined: Thu Dec 08, 2022 3:00 pm
Been thanked: 1 time

Post

@vajera, @klew po przeczytaniu Waszych postów nie wiem czy dobrze zrozumiałem.
Zrobiłem próbę, ustawiłem mniejszy zakres, żeby spr co się stanie uint16_t 65535. Wykonywał się co 5s i po przepełnieniu czyli ponad 1min wpadł w pętle.
Czy to właśnie jest spowodowane że zastosowałem uint16 zamiast uint32 jak pisał @klew?

Code: Select all

//uint32_t timestamp = 0; 
uint16_t timestamp = 0; //65535

void setup() { //ESP właśnie się uruchomiło 

Serial.begin(115200);

timestamp = millis(); //inicjalizacja zmiennej timestamp aktualną wartością millis() 
}

void 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) {
		Serial.println("Wykonaj cos co 5s");
		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();
     Serial.println("Przepelnienie licz od nowa");
}
}
User avatar
vajera
Posts: 7285
Joined: Wed Oct 31, 2018 7:58 am
Location: Biedrusko
Has thanked: 288 times
Been thanked: 161 times

Post

nebraska wrote: Sat Jun 07, 2025 10:56 am @vajera, @klew po przeczytaniu Waszych postów nie wiem czy dobrze zrozumiałem.
Zrobiłem próbę, ustawiłem mniejszy zakres, żeby spr co się stanie uint16_t 65535. Wykonywał się co 5s i po przepełnieniu czyli ponad 1min wpadł w pętle.
Czy to właśnie jest spowodowane że zastosowałem uint16 zamiast uint32 jak pisał @klew?

Code: Select all

//uint32_t timestamp = 0; 
uint16_t timestamp = 0; //65535

void setup() { //ESP właśnie się uruchomiło 

Serial.begin(115200);

timestamp = millis(); //inicjalizacja zmiennej timestamp aktualną wartością millis() 
}

void 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) {
		Serial.println("Wykonaj cos co 5s");
		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();
     Serial.println("Przepelnienie licz od nowa");
}
}
millis() zwraca wartości o typie uint32_t, już po 66 sekundach millis() zwróci wartość większą od UINT16_MAX (65535) i przypisanie

Code: Select all

 timestamp = millis()
 
ulegnie przepełnieniu na wiele dni przed tym, jak przepełni się sama wartość 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

millis() zwraca wartości o typie uint32_t, już po 66 sekundach millis() zwróci wartość większą od UINT16_MAX (65535) i przypisanie

Code: Select all

 timestamp = millis()
 
ulegnie przepełnieniu na wiele dni przed tym, jak przepełni się sama wartość millis().
[/quote]

Czyli podsumowując kod który podałeś będzie się cyklicznie po 50 dniach, przepełnieniu wykonywał dalej co 5s bez potrzeby resetu płytki?

Code: Select all

uint32_t timestamp = 0; 

void setup() { //ESP właśnie się uruchomiło 

Serial.begin(115200);

timestamp = millis(); //inicjalizacja zmiennej timestamp aktualną wartością millis() 
}

void 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) {
		Serial.println("Wykonaj cos co 5s");
		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();
     Serial.println("Przepelnienie licz od nowa");
}
}

Return to “Arduino IDE”