Arduino Polska Forum

Pełna wersja: Timer kuchenny bez delay!
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Zapragnąłem zbudować Timer kuchenny, który sygnałem świetlnym i dźwiękowym oznajmi mi zakończony czas. Tych Timerow ma być dużo, z góry zaprogramowanych(załóżmy więcej jak 5) i maja pracować bez "delay"  tylko "równolegle". Pierwszy ma się włączać tuz po włączeniu zasilania, pozostałe maja być wyzwalane z przycisku. Sketch z "delay" sobie napisałem ale to mnie nie satysfakcjonuje a z "millis" czy innymi formatami jest jednak za trudne dla mnie jak na początek. Jak mi się uda to wpisze ten sketch tylko proszę się nie śmiać !!! Jak by był ktoś miły i mi go, "po ludzku" przepisał żeby miało to "ręce i nogi", będę bardzo dźwięczny  Blush .
Z tym millis, to nie jest trudne. Jest nawet powiedziałbym proste.
Jedyną rzeczą jaką trzeba zrobić, to zrozumieć jaki mechanizm włącza nasz mózg, gdy na przykład pieczemy ciasto, czy gotujemy jajka.
Wkładasz ciacho do piekarnika na 45 minut, więc tuż po włożeniu sprawdzasz, która jest godzina i od czasu do czasu sprawdzasz czy minęło już 45 minut. Polega to na sprawdzeniu aktualnej godziny i odjęciu od niej godziny sprawdzonej podczas wkładania ciasta do piekarnika. Jeśli nie minęło, to robisz to co robiłeś dalej, a jeśli minęło, to przerywasz robotę i zajmujesz się wyciąganie żarełka z piekarnika.
W kodowaniu będziesz miał podobnie.
Start timera polega na sprawdzeniu która godzina, czyli ile millis upłynęło od włączenia systemu i zapisujesz to do zmiennej.
Program robi sobie cośtam w pętli, ale za każdym zapętleniem sprawdza czy minęło już tyle millisów ile sobie założyłeś.
Polega to na tym, że pobierasz aktualne millisy i odejmujesz od nich te, które zapisałeś do zmiennej.
I to w zasadzie tyle.
@Polak63 skoro zapragnąłeś coś zrobić, to jest to dobry czas na naukę. Trzeba zrozumieć jak się robi "wielozadaniowość" przy użyciu millis. Tak jak pisał Robson Kerman to nie jest trudne, zwłaszcza przy takim projekcie jak Twój.
Jak sam rozkmicisz jak to zrobić, będzie to procentować na przyszłość. Tu możemy podpowiadać, doradzać, ale trzeba też włączyć swoją chęć rozwiązania problemu.

Podpowiem podstawowy wzór, jak mi się wydaje, użycia millis.

if (millis() - zapCzasPoczatku >= ZadanyCzas)
{
zapCzasPoczatku = millis();
//Tu wstawiasz co ma się zrobić co "ZadanyCzas"
}

Trzeba jeszcze zadeklarować zmienne
unsigned long zapCzasPoczatku ;
unsigned long ZadanyCzas = 20000; // tu wpisany czas co jaki ma się wykonać operacja w if

Zadany czas może być zmienną lub wartością wpisaną z palca np 20000UL czyli w tym przypadku 20 sekund. UL na końcu oznacza liczbę unsigned long.

Mam nadzieję, że nie namieszałem, jak tak to proszę ekspertów o korektę.
Robson Kerman

Ślicznie dziękuje za odpowiedz nie sądziłem że  ktokolwiek odpowie. Ze mną jest jeden problem, kiedyś próbowałem naprawić mój stary samochód wiec kupiłem książkę do naprawy jego. Po przeczytaniu od dechy do dechy nawet 3 krotnie, wiedziałem wszytko ale tylko teoretycznie ale jak przyszło do naprawy, to dalej nic nie wiedziałem, wyjaśniał mi dopiero sąsiad, krok po kroku i to na przykładach (był to gaźnik) jak, co i gdzie. Naprawa mi się udała ale zasługa była sąsiada, następnym razem już wiedziałem gdzie przyłożyć klucz, śrubokręt lub młotek. Zauważyłem że jestem bardziej wzrokowcem. Chodziło mi bardziej o przykłady niż teoretyzowanie. Ale i tak i tak serdecznie dziękuje za szybka odpowiedz.
Z poważaniem Irek
Agregacik

Serdecznie dziękuje za przykład, DZIAŁA !!!! przydał się, analizuje go, staram się odwracać funkcje ale nie za bardzo mi wychodzi, obecny sketch po wpisaniu do Arduino po 5 sek. zapala LED i jest jakiś sukces. Jak to zrobić teraz aby po wpisaniu czy podłączeniu zasilania LED zaczęła od razu świecić a po zadanym czasie zgasła a najlepiej zaczęła mrugać przez jakiś zadany czas i trochę informacji dlaczego tak i tak a nie tak i tak. Z góry dziękuję.


int LEDblue = 12;
int LEDred = 11;

unsigned long zapCzasPoczatku ;
unsigned long ZadanyCzas = 5000;

void setup() {
  pinMode(LEDblue, OUTPUT);
  pinMode(LEDred, OUTPUT);
}
void loop() {

  if (millis() - zapCzasPoczatku >= ZadanyCzas)
  {
    zapCzasPoczatku = millis();
    digitalWrite(LEDred, HIGH);

  }
}
Tu masz przykład migania dwoma diodami niezależnie. Nie sprawdzałem ale powinien działać


Kod:
int LEDblue = 12;
int LEDred = 11;

unsigned long zapCzasPoczatkuRED ;
unsigned long zapCzasPoczatkuBLUE ;
unsigned long ZadanyCzasRED = 5000;
unsigned long ZadanyCzasBLUE = 7000;

void setup()
{
  pinMode(LEDblue, OUTPUT);
  pinMode(LEDred, OUTPUT);
  digitalWrite(LEDred, HIGH); // można w setupie "zapalić" wstępnie diodę
  digitalWrite(LEDblue, HIGH);
}

void loop()
{
  if (millis() - zapCzasPoczatkuRED >= ZadanyCzasRED)
  {
    zapCzasPoczatkuRED = millis();
    digitalWrite(LEDred, !digitalRead(LEDred)); // odczytujesz stan na pinie LEDred i go negujesz ! wykrzyknikiem
    //w efekcie dioda powinna zapalać się i gasnąc co 5 sekund
  }
  if (millis() - zapCzasPoczatkuBLUE >= ZadanyCzasBLUE)
  {
    zapCzasPoczatkuBLUE = millis();
    digitalWrite(LEDblue, !digitalRead(LEDblue)); // odczytujesz stan na pinie LEDblue i go negujesz ! wykrzyknikiem
    //w efekcie dioda powinna zapalać się i gasnąc co 7 sekund
  }

}
Nudząc się wymyśliłem coś takiego. Zaznaczam, że jest to jedna z możliwości realizacji Twojego projektu i nie jest to wersja najlepsza. Zapewne można ją zrealizować w bardziej elegancki i bardziej optymalny sposób.
Nie sprawdzałem czy działa.
Dodatkowe opisy w kodzie.

Kod:
int LEDblau = 12;
int LEDred = 11;
int LEDgreen = 10;
int LEDwhite = 9;
int LEDyellow = 8;

int taster1 = 7;
int taster2 = 6;
int taster3 = 5;
int taster4 = 4;
int tasterstatus1 = 0;
int tasterstatus2 = 0;
int tasterstatus3 = 0;
int tasterstatus4 = 0;
unsigned long zapCzasTester1 ;
byte mig1 = 0;

void setup()
{
  pinMode(LEDblau, OUTPUT);
  pinMode(LEDred, OUTPUT);
  pinMode(LEDwhite, OUTPUT);
  pinMode(LEDgreen, OUTPUT);
  pinMode(LEDyellow, OUTPUT);
  pinMode(taster1, INPUT_PULLUP); // podciągamy do + systemowym opornikirm
  pinMode(taster2, INPUT_PULLUP);
  pinMode(taster3, INPUT_PULLUP);
  pinMode(taster4, INPUT_PULLUP);
 
// sekwencja wstępna w setup może być "na delay"

  digitalWrite(LEDyellow, HIGH);
  delay(5000);
  digitalWrite(LEDyellow, LOW);
  delay(100);
  digitalWrite(LEDyellow, HIGH);
  delay(100);
  digitalWrite(LEDyellow, LOW);
  delay(100);
  digitalWrite(LEDyellow, HIGH);
  delay(100);
  digitalWrite(LEDyellow, LOW);
  delay(100);
  digitalWrite(LEDyellow, HIGH);
  delay(100);
  digitalWrite(LEDyellow, LOW);
  delay(100);
  digitalWrite(LEDyellow, HIGH);
  delay(100);
  digitalWrite(LEDyellow, LOW);
  delay(50);
  digitalWrite(LEDyellow, HIGH);
  delay(50);
  digitalWrite(LEDyellow, LOW);
  delay(50);
  digitalWrite(LEDyellow, HIGH);
  delay(50);
  digitalWrite(LEDyellow, LOW);
  delay(50);
  digitalWrite(LEDyellow, HIGH);
  delay(50);
  digitalWrite(LEDyellow, LOW);
  delay(50);
  digitalWrite(LEDyellow, HIGH);
  delay(50);
  digitalWrite(LEDyellow, LOW);


}

void loop()
{
 
// początek 1 sekwencji

  if (tasterstatus1 == 0 && digitalRead(taster1) == LOW) // gdy tasterstatus1 == 0 naciskając przycisk taster1 wyzwalasz sekwencję "1"
  {
    tasterstatus1 = 1; // ustawiasz tasterstatus1 na jeden i jedziemy
  }
  if (tasterstatus1 == 1) // jak tasterstatus1 == 1 to...
  {
    zapCzasTester1 = millis();  // zapamiętujemy czas millis w zmiennej zapCzasTester1
    digitalWrite(LEDred, HIGH); // "zapalamy" diodę red
    tasterstatus1 = 2;          // zmieniamy tasterstatus1 na 2 aby przejść dalej
  }
  if (tasterstatus1 == 2 && millis() - zapCzasTester1 >= 5000UL) // sprawdzamy jaki jest tasterstatus1 i jak jest równy 2
                                                                 // to sprawdzamy czy upłynął czas 5000 ms jak upłynął to:
  {
    zapCzasTester1 = millis();  // zapisujemy do zapCzasTester1 aktualny czas millis
    digitalWrite(LEDred, LOW); // "gasimy diogę
    tasterstatus1 = 3;         // zmieniamy tasterstatus1 na 3 amy przejść do dalszej sekwencji
  }

  if (tasterstatus1 == 3 && millis() - zapCzasTester1 >= 100UL)  // tu podobnie jak wyżej
  {
    zapCzasTester1 = millis();
    digitalWrite(LEDblau, HIGH); // "zapalamy" diodę blau
    tasterstatus1 = 4;
  }
  if (tasterstatus1 == 4 && millis() - zapCzasTester1 >= 100UL) // tu też podobnie jak wyżej
  {
    zapCzasTester1 = millis();
    digitalWrite(LEDblau, LOW);  //"gasimy" diodę blau
    tasterstatus1 = 3;         // ustawiamy tasterstatus1 na 3 aby po wyjściu z "ifa" powtórzyć sekwencję od 3, czyli cofamy się
    mig1 = mig1 + 1;            // tu dodajemy zmienną mig i ją inkrementujemy
    if (mig1 == 10)            // tu sprawdzamy ile razy mignęliśmy diodą i jak 10 razy to:
    {
      tasterstatus1 = 5;      // przechodzimy do tasterstatus1 5 czyli namigaliśmy się co 100ms i teraz pomigamy co 50ms
      mig1 = 0;
    }
  }

  if (tasterstatus1 == 5 && millis() - zapCzasTester1 >= 50UL)
  {
    zapCzasTester1 = millis();
    digitalWrite(LEDblau, HIGH);
    tasterstatus1 = 6;
  }
  if (tasterstatus1 == 6 && millis() - zapCzasTester1 >= 50UL)
  {
    zapCzasTester1 = millis();
    digitalWrite(LEDblau, LOW);
    tasterstatus1 = 5;
    mig1 = mig1 + 1;
    if (mig1 == 10)
    {
      tasterstatus1 = 0;  // tu ustawiamy  tasterstatus1 na 0 kończymy sekwencję, przechodzimy na początek i tam będziemy czekać na jej wyzwolenie
      mig1 = 0;           // tą zmienną też ustawiamu na 0
    }
  }
 
// koniec 1 sekwencji

// tu możesz dodać kolejne sekwencje przez kopiuj wklej zmieniając odpowiednie zmienne i deklarując je przed setup


} // -------------KONIEC PEĘTLI LOOP ------------------------------
//

EDIT Sprawdziłem i działa.
Ślicznie Ci dziękuje za sketch ale w tym momencie nie mogę go sprawdzić ze względu to że mój Arduino Mega zwariował i jego "wariacje" były już od początku jego egzystencji. Kazdy sketch wpisany lub zastartowany, czyli po podłączeniu zasilania, albo się nie wykonywał albo robił to z opóźnieniem 10-15 sekund, nawet po wpisaniu sketchu Blink z biblioteki tak się działo, co mnie zdziwiło. Wiec postanowiłem zakupić nowe Arduino bo myślę że z obecnym jest coś nie tak. Zamówiłem jeszcze raz Mega, ale jak już szaleć to szaleć to dodałem Uno i Nano i Mikro, a co. Przesyłka będzie gdzieś pod koniec Maja. No i najciekawsze teraz, dlaczego taki pomysł z tym Timerem, hym, jestem hobbystą chemikiem :-) Szukam "tego kamienia filozoficznego" i sprawia mi to przyjemność :-). Posiadam laboratorium garażowe :-) Gdzie mam rożne chemikalia i potrzebuje rożne elementy zanurzać w rożnych kąpielach o rożnych czasach. Do tego potrzebne są mi Timery, kupowałem je na allegro albo na eBay z Chin ale ich jakość i warunki w jakich muszą pracować nie dają im szans na długie życie. Mam ich około 70 z czego 8 jeszcze funkcjonuje. To efekt pracy w rękawicach, nie zawsze "czystych". Zimą nie bawię się tym, wiec zacząłem się bawić programowaniem, widać początki, są jako takie :-) Chodzi mi o to żeby mieć pod dostatkiem Timerow, do moich potrzeb no i myślałem że będzie to można zrobić na na jednym Arduino. Myśl była jedna, Teimer który informuje, 5 sek  przed końcem zadanego czasu, że nastąpi "jego koniec" no i po skończeniu zadanego czasu informuje ostrymi mrugnięciami i sygnałem dźwiękowym że proces kąpieli dobiegł końca. Czyli szybko !!! bo się spitoli :-) Pozdrawiam i proszę o wyrozumiałość :-)
Z poważaniem Irek
No to do programu trzeba dodać jeszcze czas właściwy bez 5 sekund.