28-07-2020, 04:56
Klątwa 50 dni millis() dotyka tylko tych, którzy nie umieją z tej funkcji korzystać.
Zwróć uwagę, na komentarz o klątwie:
To teoretycznie mógłby być problem gdybyś chciał jednorazowo zliczyć okres powyżej 50 dni. Do takich zliczeń timer sprzętowy i tak popełni zbyt duży błąd przez zależność od temperatury, że to nie ma żadnego sensu. Dodatkowo musi być wtedy wspomagany na timerach programowych i liczbach spoza domeny 8 bitowych AVR. Należy wtedy użyć RTC z kompensowanym temperaturowo kwarcem.
Funkcja powyżej używana w ESP8266 też gubi sekundę co kilka minut, widać to w logach przy wysyłaniu na serwer thinkspeak, dla mnie to nie ma znaczenia, ale łatwo to można skorygować zdejmując kilka ms ze zmiennej. Serwer z tym działał mi prawie rok, pierwszy zgon zaliczył gdy padło zasilanie.
Zwróć uwagę, na komentarz o klątwie:
Kod:
#define led 13
uint32_t czasTeraz,czasPoprzedni,tik=100; //tik musi byc mniejszy niz 1000 i dzilic 1000ms na rowne czesci
uint8_t nTik,sekundy,minuty,godziny,dni; //liczniki tikow, sekund, itd.
bool fnTik,fsekundy,fminuty=1,fgodziny,fdni; //flagi zdarzen nowy tik, nowa sekunda,minuta, godzina, dzien
char napis[10];
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(led,OUTPUT);
}
//oczywiscie serialprinty i ledy sa do wyrzucenia
void loop() {
// put your main code here, to run repeatedly:
//gdy nowa sekunda zmien stan led
if (fsekundy)
{
digitalWrite(led, ! digitalRead (led));
}
//gdy nowa sekunda i co dwie sekundy
if (fsekundy && sekundy%2==0)
{
sprintf(napis,"%03d:%02d:%02d",godziny,minuty,sekundy);
Serial.println(napis);
}
if (fminuty && minuty%30==0) //gdy nowa minuta i co 30min
{
Serial.println("Minelo 30 minut");
}
czas();
}
void czas()
{
czasTeraz=millis();
fnTik=fsekundy=fminuty=fgodziny=fdni=0;
if((uint32_t)(czasTeraz-czasPoprzedni)>=tik) //tak napisany warunek jest odporny na "klątwe 50 dni millis()"
{
czasPoprzedni=czasTeraz;
fnTik=1;
nTik++;
if(nTik>=(1000/tik))
{
nTik=0;
sekundy++;
fsekundy=1;
if (sekundy>=60)
{
sekundy=0;
minuty++;
fminuty=1;
if (minuty>=60)
{
minuty=0;
godziny++;
fgodziny=1;
if (godziny>=24)
{
godziny=0;
fdni=1;
dni++;
}
}
}
}
}
}
Funkcja powyżej używana w ESP8266 też gubi sekundę co kilka minut, widać to w logach przy wysyłaniu na serwer thinkspeak, dla mnie to nie ma znaczenia, ale łatwo to można skorygować zdejmując kilka ms ze zmiennej. Serwer z tym działał mi prawie rok, pierwszy zgon zaliczył gdy padło zasilanie.
Miło być decenianym https://buycoffee.to/kaczakat