Arduino Polska Forum

Pełna wersja: Sprawdzanie zmiennej niezależnie od delay()
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Witam grono,
Ktoś może podsunąć mi rozwiązanie problemu związanego z programem, który ma się następująco.

Przeprowadzam pomiary z kilku czujników, na wyświetlenie każdego z nich na LCD jest przeznaczony odpowiedni delay.
Chcę dodać funkcję ustawień do nastaw.

Dodałem przerwanie, robię zmienną z 0 na 1, część wyświetlającą wyniki mam w while(x == 0) a ustawienia analogicznie w (x == 1) .

Problem polega na tym że pętla musi "przelecieć" swój obieg aby program zareagował na zmianę parametru X.

Co mogę z tym zrobić wystrzegając się jak diabła przepisywania programu z wykorzystaniem millis()?

Dziękuje za sugestie i pozdrawiam forumowiczów.
Chcesz zrobić sensowny program to naucz się używać millis zamiast delay. Można sprawdzać w przerwaniach timera sprzętowego, ale jak nie umiesz prostszych rzeczy to tylko sobie zrobisz bałagan na strychu. Szkoda Ci przepisać program? Trzeba ich napisać setki w różnych wersjach, to każdy kolejny jest łatwiejszy, palce zaczynają same pisać algorytmy.
Uwierz, że prawie wszyscy boją się rzeczy, których nie rozumieją i nie umieją robić. Boją się nawet podjąć próbę zrozumienia. Potem będziesz się z tego śmiał. I dalej bał spróbować zrozumieć innych rzeczy...
A to powyżej to while (x) lub whiel(! x) i masz to samo dla x dopóki 1 i dopóki NIE 1.
Szukam rozwiązania poza millis()...i tyle, nie mam zamiaru oglądać w logach bałaganu po 50kilku dniach funkcjonowania arduino gdy millis() się zapełni więc tak szkoda mi przepisać program bo pogorszę sprawę Wink
Klątwa 50 dni millis() dotyka tylko tych, którzy nie umieją z tej funkcji korzystać.
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++;
   
        }
      }
    }
  }
}
}
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.