Uruchomienie akcji na jakiś czas bez użycia delay.

Masz problem z Arduino? Tutaj możesz szukać pomocy.
ODPOWIEDZ
Awatar użytkownika
emiks
Młodszy majsterkowicz
Posty: 10
Rejestracja: 21 sty 2018, 01:05

Uruchomienie akcji na jakiś czas bez użycia delay.

Post autor: emiks » 11 maja 2018, 08:59

Cześć mam problem z pompką wody która będzie mi podlewać kwiatki w czasie mojej nieobecności.
Może mi ktoś podpowiedzieć dlaczego ona nie chce się wyłączyć po 10s ??

Kod: Zaznacz cały

int czasDzialaniaPompaWoda =10000;
int licznik =0;
int statusPompaWoda;

Kod: Zaznacz cały

void nawodnienie()
{
  static unsigned long startStoperPompaWody;
  unsigned long czas = millis();
  
  if (licznik == 0) //&& (dt.day == pompaWodaDzien_ON) && (dt.hour == pompaWodaGodzina_ON) && (dt.minute == pompaWodaMinuta_ON))
  {  
    statusPompaWoda = 1;                                                      //Status pompy
    startStoperPompaWody = czas;                                         //start stopera
    digitalWrite(mosfetPompaWoda, HIGH);                            //uruchomienie pompy o wskazanym czasie
    licznik=1;
    Serial.println("pompa dziala");
  }

  if((licznik==1) && (czas - startStoperPompaWody >= czasDzialaniaPompaWoda))
  {
    statusPompaWoda = 0;                                                         //Status pompy
    digitalWrite(mosfetPompaWoda, LOW);                                //wylaczenie pompy po wskazanym czasie
    licznik=0;  
    startStoperPompaWody=0;
    Serial.println(" pompa wylaczona");
  }
}


Na czas testów zakomentowałem

Kod: Zaznacz cały

//&& (dt.day == pompaWodaDzien_ON) && (dt.hour == pompaWodaGodzina_ON) && (dt.minute == pompaWodaMinuta_ON))
Ostatnio zmieniony 11 maja 2018, 09:43 przez emiks, łącznie zmieniany 2 razy.

Co miesiąc do wygrania nagrody o wartości ponad 1600 zł!


Awatar użytkownika
ethanak
Starszy majsterkowicz
Posty: 709
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Uruchomienie akcji na jakiś czas bez użycia delay.

Post autor: ethanak » 11 maja 2018, 09:15

Dzisiejszego posta sponsoruje słowo "static" :)
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
Awatar użytkownika
emiks
Młodszy majsterkowicz
Posty: 10
Rejestracja: 21 sty 2018, 01:05

Re: Uruchomienie akcji na jakiś czas bez użycia delay.

Post autor: emiks » 11 maja 2018, 09:27

Ewentualnie przeniesienie

Kod: Zaznacz cały

unsigned long startStoperPompaWody;
do zmiennych globalnych, problemu nie rozwiązuje.
Awatar użytkownika
ethanak
Starszy majsterkowicz
Posty: 709
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Uruchomienie akcji na jakiś czas bez użycia delay.

Post autor: ethanak » 11 maja 2018, 09:51

Ponieważ wstydzisz się podać pełny kod, uruchamiam szklaną kulę...
(po chwili magicznych dźwięków i konsultacji ze światem duchów) kula mówi:
"pompa się wyłącza po 10 sekundach, ale przy następnym wywołaniu funkcji od razu się włącza, więc nie możesz zauważyć chwili wyłączenia ;)"

BTW nigdy nie porównuj zmiennych signed i unsigned, zmienna czasDzialaniaPompaWoda powinna być typu const unsigned long.
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
Awatar użytkownika
emiks
Młodszy majsterkowicz
Posty: 10
Rejestracja: 21 sty 2018, 01:05

Re: Uruchomienie akcji na jakiś czas bez użycia delay.

Post autor: emiks » 11 maja 2018, 10:11

Nie podaje całego kodu, nie dlatego że się wstydzę. Nie ma on nic wspólnego z nawodnienie(); i nie ma sensu zaśmiecać masą lini kodu.
@ethanak bardzo dziękuję za Twoje odpowiedzi dzięki temu iż nie podajesz odpowiedzi na talerzu nauczyłem się dzisiaj aby nie porównywać signed z unsigned.
Ostatnio zmieniony 11 maja 2018, 19:18 przez emiks, łącznie zmieniany 1 raz.
Awatar użytkownika
ethanak
Starszy majsterkowicz
Posty: 709
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Uruchomienie akcji na jakiś czas bez użycia delay.

Post autor: ethanak » 11 maja 2018, 10:28

Nic wspólnego powiadasz...
To porównaj coś takiego:

Kod: Zaznacz cały

void loop()
{
    nawodnienie();
}
i coś takiego:

Kod: Zaznacz cały

void loop()
{
    if (! licznik) nawodnienie();
}
Które zadziała?
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
Awatar użytkownika
emiks
Młodszy majsterkowicz
Posty: 10
Rejestracja: 21 sty 2018, 01:05

Re: Uruchomienie akcji na jakiś czas bez użycia delay.

Post autor: emiks » 11 maja 2018, 13:55

Właśnie się przekonałem na własnej skórze iż umieszczanie całego kodu na forum ma ogromne uzasadnienie szczególnie dla osób które chcą pomóc w temacie aby szybko i sprawnie skompilować kod u siebie.

Pozostawię dla potomnych.

Kod: Zaznacz cały

#include <DS3231.h>                                      // biblioteka zegara czasu rzeczywistego DS3231
#include <Wire.h>

#define mosfetPompaWoda 2                         // Pin uruchamiajacy pompe wody

DS3231 clock;
RTCDateTime dt;

const unsigned long czasDzialaniaPompaWoda =30000;                         // Czas jaki ma działać pompa w millisekundach
unsigned long startStoperPompaWody=0;                                                // Stoper odliczający czas pracy pompy
byte licznik=0;
byte pompaWodaDzien_ON = 11;                                                                               
byte pompaWodaGodzina_ON= 13;
byte pompaWodaMinuta_ON= 52;
byte pompaWodaSekunda_ON= 00;
byte statusPompaWoda= 0;   
                                             
void setup()
 {                                                        
  Serial.begin(9600);
  clock.begin();
  pinMode(mosfetPompaWoda,OUTPUT);                     // Mosfet Pin 2 Pompa Wody
  digitalWrite(mosfetPompaWoda, LOW);                  // Wylaczenie podczas startu
  
  }
void loop() 
{
  dt = clock.getDateTime();                  // pobierz date i czas z zegara systemowego RTC DS3231///////////
  nawodnienie();                             // uruchomienie i wyłączenie pompy o zadanym czasie 
}

void nawodnienie()
{
  unsigned long czas = millis();
  
  if ((licznik == 0) && (dt.day == pompaWodaDzien_ON) && (dt.hour == pompaWodaGodzina_ON) && (dt.minute == pompaWodaMinuta_ON) && (dt.second == pompaWodaSekunda_ON) )
  {  
    licznik=1;
    statusPompaWoda = 1;                                                             //Status pompy
    startStoperPompaWody = czas;                                                     //start stopera
    digitalWrite(mosfetPompaWoda, HIGH);                                             //uruchomienie pompy o wskazanym czasie
    Serial.println("pompa dziala");
  }

  if((licznik == 1) && (czas - startStoperPompaWody >= czasDzialaniaPompaWoda))
  {
    licznik=0; 
    //startStoperPompaWody =0; 
    statusPompaWoda = 0;                                                            //Status pompy
    digitalWrite(mosfetPompaWoda, LOW);                                             //wylaczenie pompy po wskazanym czasie
    Serial.println(" pompa wylaczona");
  }
}
Awatar użytkownika
Marhef
Złota rączka
Posty: 1001
Rejestracja: 18 lis 2011, 02:18

Re: Uruchomienie akcji na jakiś czas bez użycia delay.

Post autor: Marhef » 11 maja 2018, 14:19

W funkcji nawodnienie() zmień

Kod: Zaznacz cały

unsigned long czas = millis();
na

Kod: Zaznacz cały

static unsigned long czas = millis();
Tak, jak doradzał ethanak.
I doczytaj, co robi static
Awatar użytkownika
ethanak
Starszy majsterkowicz
Posty: 709
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Uruchomienie akcji na jakiś czas bez użycia delay.

Post autor: ethanak » 11 maja 2018, 14:37

To wtedy przestanie działać.
@Marhef - jako pomysłodawcy przysługuje Ci prawo wytłumaczenia dlaczego :)
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
Awatar użytkownika
emiks
Młodszy majsterkowicz
Posty: 10
Rejestracja: 21 sty 2018, 01:05

Re: Uruchomienie akcji na jakiś czas bez użycia delay.

Post autor: emiks » 11 maja 2018, 17:09

Odrobiłem zadanie domowe ze static i już wiem :D
Awatar użytkownika
emiks
Młodszy majsterkowicz
Posty: 10
Rejestracja: 21 sty 2018, 01:05

Re: Uruchomienie akcji na jakiś czas bez użycia delay.

Post autor: emiks » 13 maja 2018, 13:04

Kod powyżej ma wadę, jeśli dodamy go do swojego programu i cały nasz loop wykonuje się więcej niż 1 sekundę może nie wstrzelić się w warunek

Kod: Zaznacz cały

(dt.second == pompaWodaSekunda_ON) 
a jeśli usuniemy ten warunek i czas działania pompy będzie poniżej jednej minuty, pompa będzie działać do momentu aż następny warunek nie zostanie spełniony czyli do końca warunku

Kod: Zaznacz cały

(dt.miniute == pompaWodaMinuta_ON) 
Czyli minimalny czas uruchomienia pompy w tym momencie to jedna minuta.
Awatar użytkownika
ethanak
Starszy majsterkowicz
Posty: 709
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Uruchomienie akcji na jakiś czas bez użycia delay.

Post autor: ethanak » 13 maja 2018, 13:29

Również nie zadziała jeśli np. przez chwilę nie będzie prądu a akurat wypadnie moment uruchomienia.

Twój problem można rozwiązać w sposób dość prosty:
zmienna "licznik" przyjmuje wartość WLACZ_POMPE wtedy, jeśli zgadza się godzina i minuta a wartość "licznik" wynosi CZEKAM
zmienna "licznik" przyjmuje wartość WYLACZYLEM po zakończeniu działania pompy
zmienna "licznik" przyjmuje wartość CZEKAM wtedy, kiedy jej wartość wynosi WYLACZYLEM i nie zgadza się godzina lub minuta.
W takiej sytuacji masz minutę na uruchomienie pompy i od zera do prawie 24h na jej zatrzymanie :)
Początkową wartością licznika musi być w tym przypadku CZEKAM.
Pompa włącza się, jeśli jest wyłączona a wartość "licznik" jest WLACZ_POMPE.
Wada: nieodporne na braki zasilania.

Możesz zrobić również coś takiego:
Za każdym razem w chwili uruchomienia pompy obliczasz moment następnego uruchomienia i zapisujesz w EEPROMie. Pompę uruchamiasz (w najprostszym przypadku) jeśli bieżąca chwila jest późniejsza niz ta zapisana w EEPROMie.
Wada - po jakichś 300 latach EEPROM się skończy :(
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
ODPOWIEDZ

Strony partnerskie: