• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Pytanie o pętlę while, kolejność wykonywania kodu
#1
Witam z nudów buduję automatyczne poidełko dla moich klatkowych zwierzątek, zasada działania jest bardzo prosta. Program sprawdza poziom wody raz dziennie (są 3 poziomy ale narazie używam tylko jednego) jeżeli brakuje wody uruchamia pompkę która ponosi poziom w tym czasie program cały czas sprawdza aktualny poziom i kiedy się on zgodzi wyłącza pompkę i znów odlicza czas do kolejnego sprawdzania poziomu wody. Sterowanie pompki zrobiłem na mosfecie, jest jeszcze dodatkowy tranzystor który uruchamia vcc w mierniku wody, to sterowanie dodałem żeby styki za szybko się nie utleniły. Sam miernik oparty jest o macierz tranzystorową ogólnie bardzo prosty projekt.

jednak mam problem z pętlą while, do tej pory myślałem (już wiem, że błędnie) że jeśli warunek pętli while jest spełniony to wykonuje się tylko ta pętla i nic więcej w całym kodzie, natomiast w tym co zrobiłem takie myślenie narobiło mi kłopotów bo zauważyłem że oprócz pętli while wykonuje się tak na prawdę cały kod co skutkowało włączaniem i wyłączaniem się pompki w kółko a w połączeniu z instrukcjami delay (użytych z lenistwa i tylko na testy) zrobił się totalny chaos. Na chwilę obecną sobie poradziłem i program działa tak jak chciałem ale moje pytanie brzmi, czy pomijając użycie switch case można wymusić wykonywanie tylko danego kawałka kodu pomijając resztę ?

wrzucam mój kod, to co jest zakomentowane to część po której zorientowałem się, że kod jednak wykonuje się w całości podczas gdy zmienna timeForFeed ma wartość 1 a myślałem, że ustawienie tej zmiennej wartości 1 spowoduje, że górna część kodu zostanie pominięta. Do głowy przychodzi mi tylko użycie switch case.

Kod:
#include <avr/wdt.h>

#define VCC A2
#define MOTOR A1

void setup()
{
  //  wdt_disable();
  //  delay(2L * 1000L);
  //  wdt_enable(WDTO_2S);

  pinMode(0, INPUT_PULLUP); // low point
  pinMode(1, INPUT_PULLUP); // middle point
  pinMode(2, INPUT_PULLUP); // high point
  pinMode(13, OUTPUT);
  pinMode(MOTOR, OUTPUT);
  pinMode(VCC, OUTPUT);
}

void pumpOn()
{
  digitalWrite(MOTOR, HIGH);
  digitalWrite(13, HIGH);
}

void pumpOff()
{
  digitalWrite(MOTOR, LOW);
  digitalWrite(13, LOW);
}

void vccOn()
{
  digitalWrite(VCC, LOW);
}

void vccOff()
{
  digitalWrite(VCC, HIGH);
}

int timeForFeed = 1;
unsigned long timeOne;
unsigned long timeTwo = 0;
unsigned long timethree;

void loop()
{
  timeOne = millis();
  timethree = timeOne - timeTwo;

  if (timethree >= 5000UL)
  {
    timeForFeed = 1;
    timeTwo = timeOne;
    vccOn();
    delay(100);
  }
  //  else
  //  {
  //    pumpOff();
  //    vccOff();
  //    timeForFeed = 0;
  //  }

  while (timeForFeed == 1)
  {
    while (digitalRead(1) == HIGH)
    {
      pumpOn();
    }
    while (digitalRead(1) == LOW) {
      pumpOff();
      vccOff();
      timeForFeed = 0;
      timeOne = millis();
      timeTwo = timeOne;
    }
  }
}
 
Odpowiedź
#2
A po co blokujesz?? musi być być "while"?

if (timeForFeed == 1)
{
if (digitalRead(1) == HIGH)
{
pumpOn();
}else {
pumpOff();
vccOff();
}
timeForFeed = 0;
timeOne = millis();
timeTwo = timeOne;
}

choć timeForFeed jest bez sensu po co blokować odczyty na 5s??

uint8_t Odczyt=(digitalRead(1) );

if(Odczyt != ostatniOdczyt){
timeOne = millis();
}
ostatniOdczyt=Odczyt;

If(millis()-timeOne >=50) {
if(odczyt != stanOdczyt){
stanOdczyt=odczyt;
if(stanOdczyt=HIGH){
pumpOn();
}else{
pumpOff();
vccOff();
}
}
}
Arduino zostało wymyślone po to, by robić dobrze jedną prostą rzecz – migać diodą. 
 
Odpowiedź
#3
(06-04-2020, 05:57)Jarewa0606 napisał(a): A po co blokujesz?? musi być być "while"?

if (timeForFeed == 1)
  {
    if (digitalRead(1) == HIGH)
    {
      pumpOn();
    }else  {
      pumpOff();
      vccOff();
    }
      timeForFeed = 0;
      timeOne = millis();
      timeTwo = timeOne;
}

choć timeForFeed jest bez sensu po co blokować odczyty na 5s??

uint8_t Odczyt=(digitalRead(1) );

if(Odczyt != ostatniOdczyt){
    timeOne = millis();
}
ostatniOdczyt=Odczyt;

If(millis()-timeOne >=50) { 
if(odczyt != stanOdczyt){
    stanOdczyt=odczyt;
    if(stanOdczyt=HIGH){
          pumpOn();
      }else{
          pumpOff();
          vccOff();
      }
  }
}

Kompletnie nie zrozumiałeś mojego problemu, odczyt teraz dla testów jest na 5s docelowo ma być raz dziennie i użyłbym funkcji sleep z wybudzeniem przez WDT ale robię to na zabytku Atmega8.

A teraz do rzeczy, muszę zablokować z prostego powodu, wlewanie wody trwa jakiś czas, jeśli zakładam że badanie będzie raz dziennie a nie non stop to muszę zablokować wykonywanie części kodu na czas uzupełnienia wody, inaczej pompka włączy się na moment ale czas pójdzie dalej instrukcja else z pierwszego ifa się spełni i wlewanie się zakończy bez względu na to czy stan został uzupełniony czy też nie.

Za chwilę zapytasz czemu nie badać stanu non stop ? od razu odpowiem, taki układ nie jest idealny w praktyce napięcie powierzchniowe wody potrafi zmieniać stan co kilka sekund na ułamki sekund, oczywiście można to obejść opóźniając czas wyłączenia pompki ale ja chce dopisać jeszcze zabezpieczenia i alarm dźwiękowy więc żeby niepotrzebnie nie komplikować sytuacji wolę sprawdzić stan raz dziennie.

Wczoraj aż specjalnie się cofnąłem do prostych tutoriali z użycie while i ku mojemu zdziwieniu pętla while kiedy jej warunek jest spełniony powinna "blokować" program i działać zgodnie z moim założeniem. Dlaczego tak się nie dzieje ?
 
Odpowiedź
#4
AVR nie wybudzisz raz dziennie z użyciem WDT. Takie wybudzenie raz na dzień to tyykmo przez RTC i to w najnowszych AVR i Xmega.
 
Odpowiedź
#5
(06-04-2020, 11:13)kataklysm napisał(a): Wczoraj aż specjalnie się cofnąłem do prostych tutoriali z użycie while i ku mojemu zdziwieniu pętla while kiedy jej warunek jest spełniony powinna "blokować" program i działać zgodnie z moim założeniem. Dlaczego tak się nie dzieje ?
Bo użyłeś digitalread == LOW
 
Odpowiedź
#6
(06-04-2020, 12:47)fast_rabbit napisał(a):
(06-04-2020, 11:13)kataklysm napisał(a): Wczoraj aż specjalnie się cofnąłem do prostych tutoriali z użycie while i ku mojemu zdziwieniu pętla while kiedy jej warunek jest spełniony powinna "blokować" program i działać zgodnie z moim założeniem. Dlaczego tak się nie dzieje ?
Bo użyłeś digitalread == LOW

Możesz rozwinąć? Kiedy stan wody jest za niski odczyt na tym pinie ma stan niski bez żadnych zmian. O czym zapomniałem?
 
Odpowiedź
#7
(06-04-2020, 15:58)kataklysm napisał(a):
(06-04-2020, 12:47)fast_rabbit napisał(a):
(06-04-2020, 11:13)kataklysm napisał(a): Wczoraj aż specjalnie się cofnąłem do prostych tutoriali z użycie while i ku mojemu zdziwieniu pętla while kiedy jej warunek jest spełniony powinna "blokować" program i działać zgodnie z moim założeniem. Dlaczego tak się nie dzieje ?
Bo użyłeś digitalread == LOW

Możesz rozwinąć? Kiedy stan wody jest za niski odczyt na tym pinie ma stan niski bez żadnych zmian. O czym zapomniałem?
O zakłóceniach.
 
Odpowiedź
#8
(06-04-2020, 19:40)fast_rabbit napisał(a):
(06-04-2020, 15:58)kataklysm napisał(a):
(06-04-2020, 12:47)fast_rabbit napisał(a):
(06-04-2020, 11:13)kataklysm napisał(a): Wczoraj aż specjalnie się cofnąłem do prostych tutoriali z użycie while i ku mojemu zdziwieniu pętla while kiedy jej warunek jest spełniony powinna "blokować" program i działać zgodnie z moim założeniem. Dlaczego tak się nie dzieje ?
Bo użyłeś digitalread == LOW

Możesz rozwinąć? Kiedy stan wody jest za niski odczyt na tym pinie ma stan niski bez żadnych zmian. O czym zapomniałem?
O zakłóceniach.
Sprawdzę przebieg oscyloskopem ale robiłem próby na krótkim kodzie, na zasadzie low włącz high wyłącz i działało bez pudla, zostawiałem obok siebie na godzinę i silnik ani drgnął tak samo z poziomem wody jak i nie przestawał pracować kiedy poziom był za niski także wątpię w tą teorie. Ale sprawdzę. W razie czego można wrzucić pullup rezystor
 
Odpowiedź
#9
(06-04-2020, 12:45)fast_rabbit napisał(a): AVR nie wybudzisz raz dziennie z użyciem WDT. Takie wybudzenie raz na dzień to tyykmo przez RTC i to w najnowszych AVR i Xmega.
To nie prawda, można przy użyciu WDT budzić raz dziennie, z początku myślałem o zasilaniu z pakietu lipo i stąd potrzeba deep sleep ale ostatecznie zrezygnowałem
Swoją drogą docelowo i tak miałem budować przy tym układ rtc. Ostateczna wersja dostanie swoje fabryczne pcb
 
Odpowiedź
#10
(07-04-2020, 00:47)kataklysm napisał(a):
(06-04-2020, 12:45)fast_rabbit napisał(a): AVR nie wybudzisz raz dziennie z użyciem WDT. Takie wybudzenie raz na dzień to tyykmo przez RTC i to w najnowszych AVR i Xmega.
To nie prawda, można przy użyciu WDT budzić raz dziennie,
Niby jak jeżeli max czas to 8 sekund?
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości