Skocz do zawartości

Kurs Arduino - #4 - Przetwornik ADC


Pomocna odpowiedź

Cześć Wszystkim !

zabrałem się za zadanie 4.4 i póki co chciałbym żeby program pokazywał mi zmienną "odczytaneDane" jeszcze bez konwersji na wartości napięcia, ale...

Mam problem z pętlą while().

Gdy zasłaniam dłonią fotorezystor dioda się zapala i podaje zmienną "odczytaneDane" ale  gdy odsłaniam fotorezystor, czyli teoretycznie mój warunek dla pętli while(odczytanaWartosc < prog) przestaje być spełniony, program nie chce wyjść z pętli.

zastanawia mnie dlaczego pętla while nie reaguje na niespełnienie warunku? 

proszę o pomoc i wyjaśnienie

poniżej szkic:

int odczytanaWartosc = 0; //Zmienna do przechowywania odczytu ADC
int prog = 0; //Próg włączenia światła - ustawiany potencjometrem
void setup() {
  pinMode(8, OUTPUT); //Konfiguracja wyjść pod diodę LED
  Serial.begin(9600);
}

void loop() {
  odczytanaWartosc = analogRead(A5);//Odczytanie wartości z ADC
  prog = analogRead(A4);//Odczytanie wartości z ADC  
  
  if (odczytanaWartosc < prog) { //Czy jest ciemniej od ustawionego progu?
     digitalWrite(8, HIGH);//Włączenie diody    
     Serial.println(odczytanaWartosc);
     while(odczytanaWartosc < prog){
      delay(50);
     }
    } else {
     digitalWrite(8, LOW);//Wyłączenie diody      
  }
  
  delay(50);
}

 

Link do komentarza
Share on other sites

while(odczytanaWartosc < prog)
	{
  		delay(50); 
	}

Program wchodzi w pętle kiedy warunek jest spełniony, ale sama pętla to tylko delay(50). Tym samym program wykonują ciągle opóźnienie i nic więcej. Musisz w tej pętli odczytać zmienną odczytanaWartosc, aby wyjść z tej pętli.

while(odczytanaWartosc < prog)
	{
  		delay(50);
  		odczytanaWartosc = analogRead(A5);
	}

Ogólnie ten warunek IF jest niepotrzebny w tym wypadku, jeśli robisz to przy użyciu WHILE - bo właściwie to powtarzasz to samo. Wystarczy np.:

while (odczytanaWartosc < prog)
	{
		digitalWrite(8, HIGH);	//Włączenie diody    
		Serial.println(odczytanaWartosc);
		delay(50);
		odczytanaWartosc = analogRead(A5);	//Sprawdzamy czy wychodzimy z pętli WHILE
		prog = analogRead(A4);	//Przy okazji można dodać sprawdzenie czy próg nie został zmieniony
	}
digitalWrite(8, LOW);	//Wyłączenie diody

Same odczyty możesz zrobić w osobnej funkcji np.:

void odczyty()
	{
		odczytanaWartosc = analogRead(A5);	
		prog = analogRead(A4);
	}

void loop()
	{
		odczyty(); // teraz w dowolnym miejscu programu mozesz powolac sie na ta funkcje
	}

 

Edytowano przez Shary
  • Pomogłeś! 1
Link do komentarza
Share on other sites

@Shary wielkie dzięki za pomoc! coś mi się rozjaśniło 🙂

Trochę mnie przyblokowało podpatrzenie komendy z fragmentu lekcji nr3, 

tam był taki szkic:

void setup(){
  Serial.begin(9600); //Uruchamiamy transmisję
  
  pinMode(8, OUTPUT); //Wyjście diody czerwonej
  pinMode(9, OUTPUT); //Wyjście diody zielonej
  pinMode(10, INPUT_PULLUP); //Przycisk
  
  digitalWrite(8, LOW); //Wyłączenie obu diod
  digitalWrite(9, LOW);
}
 
void loop() {
  
  if (digitalRead(10) == LOW) { //Jeśli przycisk jest wciśnięty
    digitalWrite(9, HIGH); //Włączenie diody zielonej
    digitalWrite(8, LOW); //Wyłączenie diody czerwonej
  } else { //Jeśli przycisk nie jest wciśnięty
    digitalWrite(9, LOW); //Wyłączenie diody zielonej
    digitalWrite(8, HIGH); //Włączenie diody czerwonej
    Serial.println("Uwaga! Alarm! Okno nie jest zamkniete!");
    
    while (digitalRead(10) == HIGH) {
      //Zatrzymujemy się w pustej pętli do ponownego zamknięcia okna
      delay(25); //W pętli wprowadzamy małe opóźnienie 25ms, aby niwelować zakłócenia
    }
 
  }
}

Próbowałem zrobić analogie. Myślałem że skoro w powyższej pętli while() program wychodzi z pętli gdy  switch przechodzi na stan LOW, to w moim szkicu do zadania 4.4 będzie podobnie, tzn. Wychodzę z pętli gdy odsłaniam rękę (odczytanaWartosc>prog). 

Rozumiem Twoją propozycję i bardzo dziękuję za nią, ale też pojawia mi się pytanie czemu ten powyższy szkic nie musiał mieć "niczego w środku" pętli while a potrafił przeczytać Warunek do pętli i wyjść z niej gdy switch przeszedł w stan LOW, a ja w swoim zadaniu 4.4 musze wpisać do swojej pętli while linjkę kodu: odczytanaWartosc=analogRead(A5); bo gdy tego nie zrobię zapętlam się w nieskończoność i nie wychodzę z pętli.

Edytowano przez dastawowy
Link do komentarza
Share on other sites

dobre pytanie, zwróć uwagę na konstrukcję obu pętli:

while (digitalRead(10) == HIGH) // robimy odczyt w warunku, czyli pętla się wykonuję póki D10 ma stan HIGH
  
if (odczytanaWartosc < prog) lub while (odczytanaWartosc < prog) //w obu przypadkach sprawdzamy zmienną (czyli co zawiera zmienna)

w pierwszym wariancie dokonujemy bezpośrednio odczytu z D10, w drugim (Twoim dokonujemy odczytu wartości zmiennej (dwóch zmiennych dokładnie). Zmienna, ma to do siebie, że sama nie zmieni wartości. Musisz na niej wykonać operację. Dlatego w Twojej pętli dokonałem odczytu w "środku" pętli, co zmieni wartość samej zmiennej jeśli odczyt ulegnie zmianie.

Oczywiście analogicznie możesz zrobić warunek taki:

while (analogRead(A5) < analogRead(A4))

I to będzie działać. Jednak z punktu widzenia bardziej skomplikowanych programów, łatwiej jest edytować zmienne niż cały kod.

Edytowano przez Shary
  • Pomogłeś! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Cześć 🙂

mam pytanie do zadania 4.5. (gra)

jakiej funkcji należy użyć by arduino odczytał zmienne typu int które chcę wprowadzić za pośrednictwem terminala?

metodą prób i błędów wiem  że:

odebraneDane = Serial.readStringUntil('\n');

powyższy kod nie odbierze String i nie przekonwertuje tego na INT (użyłem go w pierwszej kolejności na podstawie wiedzy wyniesionej z lekcji nr 3, ale teraz już wiem że to tak nie działa 😉 )

Najbliżej było z:

odebraneDane = Serial.parseInt();

jednak tutaj mam problem z tym że gdy wpisze do terminala poprawną liczbę (dioda zapali mi się na zielono) to po chwili i tak zapala mi się na pomarańczowo.

Zanim okażę się że mam jakieś błędy w szkicu, chciałbym w ogóle dowiedzieć się czy dobrze kombinuje z tym zadaniem, jeśli chodzi o odbiór danych za pośrednictwem terminala. szkic jest w powijakach więc póki co nie wklejam..

Pozdrawiam

Link do komentarza
Share on other sites

Sprawdź pętlą IF czy serial jest aktywny, odczytaj STRING do końca lini, a następni STRING zmień na INT, coś w tej deseń:

if(Serial.available() > 0) 
	{ 
       odczyt_z_konsoli = Serial.readStringUntil('\n');  
       liczba = odczyt_z_konsoli.toInt();
	}

https://www.arduino.cc/reference/pl/language/variables/data-types/string/functions/toint/

Powinno działać. Tu masz dokumentację toInt();

Edytowano przez Shary
  • Pomogłeś! 1
Link do komentarza
Share on other sites

@Shary jesteś wielki! 🙂 dzięki serdeczne, mała wskazówka a bardzo pomogła.

To moja propozycja zadania 4.5

String odczyt = ""; // Liczba którą wysyłam za pośrednictwem terminala
int wyslana = 0; // zmienna użyta do konwersji ze String na Int
int odczytana = 0; // Liczba którą odczytuję z ADC
int szansa = 0; // zmiena do liczenia ile pozostało szans

void setup() {
  Serial.begin(9600);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(2, INPUT_PULLUP);

digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
}

void loop() {
  if(digitalRead(2)==LOW)
  {
    Serial.println("podaj liczbę");
    delay(1000);
    szansa=0;
  }
   if(Serial.available() > 0) //czy wpisałem jakas liczbe?
     {
     odczyt = Serial.readStringUntil('\n'); //jesli tak to wpisz do zmiennej
     wyslana = odczyt.toInt();
     odczytana = analogRead(A4);
     if((wyslana >= odczytana - 50) && (wyslana <= odczytana + 50)) // czy moja liczba spelnia oba warunki?
     {
       Serial.println("wygrana");
       digitalWrite(10, HIGH);
       delay(1000);
       digitalWrite(10, LOW);
       delay(1000);
       szansa=0;
     } 
     else if ((wyslana != odczytana) && (szansa <= 2)) //czy moja liczba spełnia warunki?
     {
       digitalWrite(9, HIGH);
       delay(1000);
       digitalWrite(9, LOW);
       delay(1000);
       szansa=szansa+1;
     }
     if (szansa >= 3) 
     {
      Serial.println("przegrana");
      digitalWrite(8, HIGH);
      delay(1000);
      digitalWrite(8, LOW);
      delay(1000);
      Serial.println("zresetuj grę");
      }
     if(szansa==1)
     {
       Serial.println("zostały 2 szanse");
     }
     if(szansa==2)
     {
       Serial.println("została 1 szansa");
     }
    }
}
 

 

  • Lubię! 1
Link do komentarza
Share on other sites

4.5 

#define czerwona 6
#define zolta 7
#define zielona 8
#define przycisk 3

boolean wygrana = false;
int odczyt = 0;
String traf = "";
int traf1 = 0;
int prob = 2;
boolean odnowa = false;

void setup() {
  
Serial.begin (9600);
 
 pinMode(czerwona,OUTPUT);
 pinMode(zolta, OUTPUT);
 pinMode(zielona, OUTPUT);
 pinMode(przycisk, INPUT_PULLUP);

}

void loop() {

    if(odnowa == true){
      digitalWrite(czerwona, LOW);
      digitalWrite(zielona, LOW);
      digitalWrite(zolta, LOW);
      wygrana = false;
      prob = 2;
    }

  
if(digitalRead(przycisk)==LOW){
      odczyt = analogRead(A4);
      Serial.println ("Podaj liczbę:");
      delay(200);
      
      while(Serial.available()==0){};
      
      if(Serial.available() >0){
        traf = Serial.readStringUntil ('\n');
        traf1 = traf.toInt();
         }
 
         if(odczyt - traf1 <= 50 && odczyt - traf1 >= -50){
          digitalWrite(zielona, HIGH);
          odnowa = true;
          delay(2000);
          } else {
             digitalWrite(zolta, HIGH);
             if(wygrana == false){
              
               while(prob > 0){
       
         
              Serial.println ("Masz jeszcze: ");
              Serial.println (prob);
              Serial.println (" prob");
              prob = prob -1;
              delay(200);
              
               while(Serial.available()==0){};
               
                  if(Serial.available() >0){
                    traf = Serial.readStringUntil ('\n');
                     traf1 = traf.toInt();
          
                      if(odczyt - traf1 <= 50 && odczyt - traf1 >= -50){
                       digitalWrite(zielona, HIGH);
                       digitalWrite(zolta, LOW);
                       wygrana = true;
                       odnowa = true;
                      delay(2000);
                 }
               }  
              }
                          if(wygrana ==false){
                             digitalWrite(zolta, LOW);
                             digitalWrite(czerwona, HIGH);
                             odnowa = true;
                             delay(2000);
         }
       }
    }
  }
 }
 

 

4.6

#define Lzielona  2
#define Lczerwona 3
#define zolta 4
#define Pczerwona 5
#define Pzielona 6

int a =0;
int b = 0;

void setup() {
  Serial.begin(9600);

  pinMode(Lzielona, OUTPUT);
  pinMode(Lczerwona, OUTPUT);
  pinMode(zolta, OUTPUT);
  pinMode(Pczerwona, OUTPUT);
  pinMode(Pzielona, OUTPUT);
}

void loop() {
  digitalWrite(Lzielona, LOW);
  digitalWrite(Lczerwona, LOW);
  digitalWrite(zolta, LOW);
  digitalWrite(Pczerwona, LOW);
  digitalWrite(Pzielona, LOW);
  
  a = analogRead(A5);
  b = analogRead(A4);

  a= map(a, 0, 1023, 1, 5);
  b = map(b, 0, 1023, 1,5);

  Serial.println(a);
  Serial.println(b);

   if(a==b)
    {
      digitalWrite(Lzielona, LOW);
      digitalWrite(Lczerwona, LOW);
      digitalWrite(zolta, HIGH);
      digitalWrite(Pczerwona, LOW);
      digitalWrite(Pzielona, LOW);
    }else if (a-b >=3)
    {
      digitalWrite(Lzielona, HIGH);
      digitalWrite(Lczerwona, LOW);
      digitalWrite(zolta, LOW);
      digitalWrite(Pczerwona, LOW);
      digitalWrite(Pzielona, LOW);
    } else if( a-b == 2 || a-b == 1)
    {
      digitalWrite(Lzielona, LOW);
      digitalWrite(Lczerwona, HIGH);
      digitalWrite(zolta, LOW);
      digitalWrite(Pczerwona, LOW);
      digitalWrite(Pzielona, LOW);
    }else if( b-a >=3)
    {
      digitalWrite(Lzielona, LOW);
      digitalWrite(Lczerwona, LOW);
      digitalWrite(zolta, LOW);
      digitalWrite(Pczerwona, LOW);
      digitalWrite(Pzielona, HIGH);
    }else if( b-a ==2 || b-a ==1)
      {
      digitalWrite(Lzielona, LOW);
      digitalWrite(Lczerwona, LOW);
      digitalWrite(zolta, LOW);
      digitalWrite(Pczerwona, HIGH);
      digitalWrite(Pzielona, LOW);
      }

 delay(100);
}

Może niezbyt optymalne rozwiązania, ale działają 🙂

  • Lubię! 2
Link do komentarza
Share on other sites

@StefanekP sprawa jest dość prosta, funkcja toInt(), która zwróci typ long. Funkcja jest doczepiona do klasy String wiec użycie wygląda pewnie tak:

long liczba = napis.toInt();

Funkcja jest wraperem funkcji atol.

// /*********************************************/
// /*  Parsing / Conversion                     */
// /*********************************************/

long String::toInt(void) const {
    if (buffer())
        return atol(buffer());
    return 0;
}

Jej działanie widocznie bazuje na metodzie Hornera:

liczba += znak * 10;

 

  • Pomogłeś! 2
Link do komentarza
Share on other sites

Moje rozwiązania do zadań domowych:

4.5:

#define zolta 8
#define czerwona 9
#define zielona 10
#define przycisk 11
String odebraneDane="";
int napiecePotencjometru=0;
int lProb=3;
boolean zaczetoGre=false;
boolean wyslanoKomunikat=false;
void setup() {
  // put your setup code here, to run once:
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(11,INPUT_PULLUP);
  Serial.begin(9600);
  digitalWrite(zielona,LOW);
  digitalWrite(czerwona,LOW);
  digitalWrite(zolta,LOW);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (zaczetoGre==false){
    if (digitalRead(przycisk)==LOW){
      zaczetoGre=true;
      //if (wyslanoKomunikat=false){
        Serial.println("Podaj liczbę");
        wyslanoKomunikat=true;
      
      }
    }
  

    else{
      napiecePotencjometru=analogRead(A5);
      if (Serial.available()>0){
        odebraneDane=Serial.readStringUntil("\n");
       long odebranaWartosc=odebraneDane.toInt();
        if (odebranaWartosc<napiecePotencjometru+50){
          if (odebranaWartosc>napiecePotencjometru-50){
            digitalWrite(zielona,HIGH);
            digitalWrite(czerwona,LOW);
            digitalWrite(zolta,LOW);
            zaczetoGre=false;
          }
            else{
              digitalWrite(zolta,HIGH);
              digitalWrite(zielona,LOW);
              digitalWrite(czerwona,LOW);
              lprob=lprob-1;
              Serial.println("Spróbuj jeszcze raz.");
            }
  }
  
          else{
            Serial.println("Spróbuj jeszcze raz");
            lprob=lprob-1;
            digitalWrite(zolta,HIGH);
            digitalWrite(zielona,LOW);
            digitalWrite(czerwona,LOW);
          }
     
        if (lprob==0){
          digitalWrite(zolta,LOW);
          digitalWrite(zielona,LOW);
          digitalWrite(czerwona,HIGH);
          zaczetoGre=false;
  }

}
}
}

4.6:

#define srodkowa 9 //dioda środkowa
#define lewaZolta 8 //dioda znajdująca się po lewej, bliżej środka
#define prawaZolta 10 //dioda znajdująca się po prawej, bliżej środka
#define lewaCzerwona 7 //dioda znajdująca się po lewej, dalej od środka
#define prawaCzerwona 11//dioda, znajdująca się po prawej, dalej od środka
int napieceLewegoDzielnika=0;
int napiecePrawegoDzielnika=0;
boolean wyslanoDane=false;
void setup() {
  // put your setup code here, to run once:
  pinMode(9,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(11,OUTPUT);
  digitalWrite(9,LOW);
  digitalWrite(8,LOW);
  digitalWrite(10,LOW);
  digitalWrite(7,LOW);
  digitalWrite(11,LOW);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  napieceLewegoDzielnika=analogRead(A4);
  napiecePrawegoDzielnika=analogRead(A5);
  if (wyslanoDane==false){
    Serial.println(napieceLewegoDzielnika);
    Serial.println(napiecePrawegoDzielnika);
    wyslanoDane=true;
  }
  if (napieceLewegoDzielnika>napiecePrawegoDzielnika){
    if (napieceLewegoDzielnika-napiecePrawegoDzielnika<5){
      digitalWrite(srodkowa,HIGH);
      digitalWrite(lewaZolta,LOW);
      digitalWrite(prawaZolta,LOW);
      digitalWrite(prawaCzerwona,LOW);
      digitalWrite(lewaCzerwona,LOW);
    }
 
      else if (napieceLewegoDzielnika-napiecePrawegoDzielnika<=15){
        digitalWrite(srodkowa,LOW);
        digitalWrite(lewaZolta,HIGH);
        digitalWrite(prawaZolta,LOW);
        digitalWrite(prawaCzerwona,LOW);
        digitalWrite(lewaCzerwona,LOW);
    }
      else if (napieceLewegoDzielnika-napiecePrawegoDzielnika>15){  
        digitalWrite(srodkowa,LOW);
        digitalWrite(lewaZolta,LOW);
        digitalWrite(prawaZolta,LOW);
        digitalWrite(prawaCzerwona,LOW);
        digitalWrite(lewaCzerwona,HIGH);
        
      }
  
  }
    else if (napieceLewegoDzielnika==napiecePrawegoDzielnika){
      digitalWrite(srodkowa,HIGH);
      digitalWrite(lewaZolta,LOW);
      digitalWrite(prawaZolta,LOW);
      digitalWrite(prawaCzerwona,LOW);
      digitalWrite(lewaCzerwona,LOW);
    }
    else if (napiecePrawegoDzielnika>napieceLewegoDzielnika){
      if (napiecePrawegoDzielnika-napieceLewegoDzielnika<5){
        digitalWrite(srodkowa,HIGH);
        digitalWrite(lewaZolta,LOW);
        digitalWrite(prawaZolta,LOW);
        digitalWrite(prawaCzerwona,LOW);
        digitalWrite(lewaCzerwona,LOW);
    }
        else if (napiecePrawegoDzielnika-napieceLewegoDzielnika<=15){
        digitalWrite(srodkowa,LOW);
        digitalWrite(lewaZolta,LOW);
        digitalWrite(prawaZolta,HIGH);
        digitalWrite(prawaCzerwona,LOW);
        digitalWrite(lewaCzerwona,LOW);
        }
        else if (napiecePrawegoDzielnika-napieceLewegoDzielnika>15){
          digitalWrite(srodkowa,LOW);
          digitalWrite(lewaZolta,LOW);
          digitalWrite(prawaZolta,LOW);
          digitalWrite(prawaCzerwona,HIGH);
          digitalWrite(lewaCzerwona,LOW);

}
}
}

 

  • Lubię! 1
Link do komentarza
Share on other sites

@StefanekP super że robisz dodatkowe zadania 🙂 

Kody wyglądają porządnie, zwłaszcza logika w pierwszym dobrze wygląda. Tylko polecam Ci zapoznać się z autoformatem w Arduino IDE, w menu znajdziesz. Zdecydowanie poprawia czytelność.

Wiem, że w kursie nie ma nic o tablicach ale możesz w ramach ciekawostki poczytać ten artykuł i uprościć warunki przy pomocy tablicy i funkcji map 🙂 

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.