Skocz do zawartości

Kurs Arduino - #4 - Przetwornik ADC


Pomocna odpowiedź

@lleymann no dobrze, czyli zakładam, że to jest aktualna wersja Twojego programu (poprawiłem tylko formatowanie):

#define diodac 8 // dioda czerwona
#define diodazo 9 // dioda zolta
#define diodaz 10 // dioda zielona
#define guzik 11 // Przycisk
int losowanie = 0;// zdefiniowanie zmiennej losowanie
String liczba = ""; // Pusty ciag odebranych danych
int intliczba = 0;// konwersja podanej liczby na wartosc liczbowa, zaczerpnalem to z forum
int liczniknac = 0;// licznik nacisniec guzika, zeby zliczac 3 proby

void setup() {
  Serial.begin(9600); // uruchomienie transmisji z UART
  pinMode(diodac, OUTPUT); // konf pinu 8 jako wyjscie
  pinMode(diodazo, OUTPUT); // konf pinu 9 jako wyjscie
  pinMode(diodaz, OUTPUT); // konf pinu 10 jako wyjscie
  pinMode(guzik, INPUT_PULLUP); // konf pinu 11 jako przycisku


  digitalWrite(diodac, LOW); // wylaczenie diod
  digitalWrite(diodazo, LOW);
  digitalWrite(diodaz, LOW);
  liczniknac = 0; // ustawienie licznika nacisniec na 0
}

void loop() {

  losowanie = analogRead(A4); // Odczytujemy losową liczbę na potencjometrze

  while (digitalRead(guzik) == LOW) { // Jesli wcisniemy przycisk
    liczniknac = liczniknac + 1; // zwieksz licznik nac o 1
    delay(1000); // Czekamy 1 sek
    Serial.println("Podaj liczbe"); // Wyswietlamy Podaj Liczbę
  }
  
  if (liczniknac <= 3) { // Jesli licznik nac bedzie równy lub mniejszy 3 wtedy realizujemy ponizsze warunki
    
    if (Serial.available() > 0) { //Czy Arduino odebrało dane
      liczba = Serial.readStringUntil('\n');  //Jeśli tak, to odczytujemy je do znaku końca linii i zapisz w zmiennej liczba
      intliczba = liczba.toInt(); // konwersja slowa na liczbe
      
      if (losowanie > (intliczba - 50) and (losowanie < (intliczba + 50))) { // Jesli wpisana liczba spelnia podany warunek
        Serial.println("Wygrana!!");// Wyswietlany jest napis wygrana
        digitalWrite(diodaz, HIGH);// I zapalana zielona dioda
        digitalWrite(diodac, LOW);
        digitalWrite(diodazo, LOW);
      } else {// Jesli wpisana liczba nie miesci sie w przedziale
        Serial.println("Spróbuj jeszcze raz");// wyswietlany napis sprobuj jeszcze raz
        digitalWrite(diodazo, HIGH);// I zapala się dioda zolta
        digitalWrite(diodac, LOW);
        digitalWrite(diodaz, LOW);
      }
      
    }
    
  } else {// Jesli guzik jest już naciskany 4 raz
    
    Serial.println("Koniec Gry");// wyswtielany ma byc napis Koniec gry
    digitalWrite(diodaz, LOW);
    digitalWrite(diodac, HIGH);// Zapalana jest czerwona dioda
    digitalWrite(diodazo, LOW);
    liczniknac = 0; // licznik naciśnięć jest zerowany
    Serial.println("Nowa gra.");// wyswietlany jest napis nowa gra i mozna grać od nowa
    
  }
}

Cały problem polega więc na tym, że poniższa linijka wykonuje się po każdym wciśnięciu przycisku, zgadza się?

Serial.println("Podaj liczbe"); // Wyswietlamy Podaj Liczbę

A chodzi Ci o to, aby była wykonywana tylko, gdy ktoś naciska przycisk pierwszy, drugi, lub trzeci raz - tak? Czyli napis ten powinien się pokazywać tylko, gdy licznik naciśnięć przycisku wskazuje wartość mniejszą lub równą 3, tak?

Link to post
Share on other sites

Dzień dobry, nie wiem czy nie pytam za późno, ale zastanawiam się czy przed zmianą układu powinnam jakoś zatrzymać powtarzający się zadany proces? np po układzie z 5 diodami przed przygotowaniem układu z fotorezystorem? Albo czy jest narzucona kolejność odłączania przewodów od płytki?

Link to post
Share on other sites

@Treker dokładnie w ten sposób myślałem i w związku z tym próbowałem ta linię wpisać Pod wierszem z warunkiem:

if (liczniknac <= 3) { // Jesli licznik nac bedzie równy lub mniejszy 3 wtedy realizujemy ponizsze warunki

Tylko, że wtedy program powtarza wysyłanie napisu Podaj liczbę, a jak to zrobić, żeby był on wysyłany tylko raz? Jest na to jakaś funkcja typu "printOne"? Nie wiem właśnie jak rozwiązać ten problem.

Link to post
Share on other sites
1 godzinę temu, lleymann napisał:

Jest na to jakaś funkcja typu "printOne"? Nie wiem właśnie jak rozwiązać ten problem.

Ogólnie  funkcja print wypisuje tylko raz (println też), więc po co Ci jakieś "printOne"? Jeśli coś się w programie powtarza, to najprawdopodobniej jest to w pętli. Może trzeba to "coś" wystawić poza pętlę, zrobić jakiś warunek, przerwać pętlę np. funkcją break.... Sposobów jest wiele.

Link to post
Share on other sites
19 godzin temu, Hanna napisał:

Dzień dobry, nie wiem czy nie pytam za późno, ale zastanawiam się czy przed zmianą układu powinnam jakoś zatrzymać powtarzający się zadany proces? np po układzie z 5 diodami przed przygotowaniem układu z fotorezystorem? Albo czy jest narzucona kolejność odłączania przewodów od płytki?

@Hanna witam na forum 🙂 W tego typu prostych układach nie ma tego typu potrzeby. Możesz robić tak jak Ci wygodnie. Zawsze możesz też odłączyć wszystkie elementy, wgrać nowy program, wyłączysz zasilanie, podłączyć nowe komponenty i dopiero wtedy włączyć zasilanie.

12 godzin temu, lleymann napisał:

@Treker dokładnie w ten sposób myślałem i w związku z tym próbowałem ta linię wpisać Pod wierszem z warunkiem:

@lleymann no tak, działało to błędnie, bo tamto miejsce jest wywoływane przy każdym obiegu pętli. W tym wypadku chcemy jednak, aby warunek wykonywał się tylko po odebraniu danych. Możesz więc dodać warunek w tym miejscu:

  while (digitalRead(guzik) == LOW) { // Jesli wcisniemy przycisk
    liczniknac = liczniknac + 1; // zwieksz licznik nac o 1
    delay(1000); // Czekamy 1 sek
    Serial.println("Podaj liczbe"); // Wyswietlamy Podaj Liczbę
  }

I zrobić coś takiego:

  while (digitalRead(guzik) == LOW) { // Jesli wcisniemy przycisk
    liczniknac = liczniknac + 1; // zwieksz licznik nac o 1
    delay(1000); // Czekamy 1 sek
    if (liczniknac <= 3) {
    	Serial.println("Podaj liczbe"); // Wyswietlamy Podaj Liczbę
    }
  }

Zobacz czy to nie rozwiązuje Twojego problemu 🙂

Link to post
Share on other sites

@Treker niestety nie rozwiązało to mojego problemu. Ponieważ podczas czwartego naciśnięcia guzika wyświetlany jest:

17:30:57.565 -> Koniec Gry
17:30:57.565 -> Nowa gra.
17:30:57.565 -> Podaj Liczbę

A chcę, żeby program wyświetlał ten napis (Podaj liczbę) dopiero po kolejnym naciśnięciu guzika, w przeciwnym wypadku gracz będzie miał 4 próby, ponieważ widząc powyższe zamiast klikania na guzik wpisze po prostu liczbę, a w tym momencie liczniknac jest ustawiony na 0 co de facto spełnia warunek, aby wyświetlić napisz Podaj liczbę.

Można by to rozwiązać zmianą, aby za 4tym naciśnieciem guzika, liczninac = 1, ale to takie jest rozwiązanie na piechotę i to ja się dostosowuję do programu, a nie program do mnie 😞 

Mój obecny kod wygląda tak:

#define diodac 8 // dioda czerwona
#define diodazo 9 // dioda zolta
#define diodaz 10 // dioda zielona
#define guzik 11 // Przycisk
int losowanie = 0;// zdefiniowanie zmiennej losowanie
String liczba = ""; // Pusty ciag odebranych danych
int intliczba = 0;// konwersja podanej liczby na wartosc liczbowa, zaczerpnalem to z forum
int liczniknac = 0;// licznik nacisniec guzika, zeby zliczac 3 proby

void setup() {
Serial.begin(9600); // uruchomienie transmisji z UART 
pinMode(diodac, OUTPUT); // konf pinu 8 jako wyjscie
pinMode(diodazo, OUTPUT); // konf pinu 9 jako wyjscie
pinMode(diodaz, OUTPUT); // konf pinu 10 jako wyjscie
pinMode(guzik, INPUT_PULLUP); // konf pinu 11 jako przycisku


digitalWrite(diodac, LOW); // wylaczenie diod
digitalWrite(diodazo, LOW);
digitalWrite(diodaz, LOW);
liczniknac=0; // ustawienie licznika nacisniec na 0
}

void loop() {
 
losowanie=analogRead(A4); // Odczytujemy losową liczbę na potencjometrze

while (digitalRead(guzik) == LOW) { // Jesli wcisniemy przycisk
  liczniknac = liczniknac + 1; // zwieksz licznik nac o 1
  delay(1000); // Czekamy 1 sek
}
if(liczniknac <= 3) {
     Serial.println("Podaj Liczbę");// wyswtielany ma byc napis Podaj liczbe.
}
if(liczniknac <= 3) {  // Jesli licznik nac bedzie równy lub mniejszy 3 wtedy realizujemy ponizsze warunki 
   while (digitalRead(guzik) == HIGH) { // Jesliprzycisk jest zwolniony         
  if(Serial.available() > 0) { //Czy Arduino odebrało dane
       liczba = Serial.readStringUntil('\n');  //Jeśli tak, to odczytujemy je do znaku końca linii i zapisz w zmiennej liczba
       intliczba = liczba.toInt(); // konwersja slowa na liczbe
       if (losowanie > (intliczba - 50) and (losowanie < (intliczba + 50))) { // Jesli wpisana liczba spelnia podany warunek
        Serial.println("Wygrana!!");// Wyswietlany jest napis wygrana
        digitalWrite(diodaz, HIGH);// I zapalana zielona dioda
        digitalWrite(diodac, LOW);
        digitalWrite(diodazo, LOW);
       }  else  {// Jesli wpisana liczba nie miesci sie w przedziale
        Serial.println("Spróbuj jeszcze raz");// wyswietlany napis sprobuj jeszcze raz
        digitalWrite(diodazo, HIGH);// I zapala się dioda zolta
        digitalWrite(diodac, LOW);
        digitalWrite(diodaz, LOW);
       }
}}
} else {// Jesli guzik jest już naciskany 4 raz 
  Serial.println("Koniec Gry");// wyswtielany ma byc napis Koniec gry
        digitalWrite(diodaz, LOW);
        digitalWrite(diodac, HIGH);// Zapalana jest czerwona dioda
        digitalWrite(diodazo, LOW);
        liczniknac=0;// licznik naciśnięć jest zerowany
        Serial.println("Nowa gra.");// wyswietlany jest napis nowa gra i mozna grać od nowa
}
}

Zacząłem też robić zadanie 4.6. Proszę wytłumaczcie mi, różnicę pomiędzy 3ema poniżej wypisanymi warunkami? Dodam że przy ierwszym spsobie program mi nie działał prawidłowo, a przy drugim sposobie działa.

sposób 1:

if()
if()
if()

Sposób 2:

if()
else if()
else if()

 

Link to post
Share on other sites

@lleymann zacznę od małej reprymendy 😉 Zadbaj o porządek w swoich programach. Sformatowałem wcześniej Twój kod, a już sporo namieszałeś. Te wszystkie spacje, tabulatory i wcięcia to ma konkretny cel - ma zwiększyć czytelność kodu. Wiele błędów jest właśnie wynikiem tego, że ktoś pisze programy "brzydko", później coś skopiuje, wklei w złym miejscu i problem gotowy.

Idąc od końca. Zakładam, że chodziło Ci o takie warunki (nawiasy są ważne):

if (warunek1) {
  
}

if (warunek2) {
  
}

if (warunek3) {
  
}

W takiej sytuacji wszystkie warunki są niezależne. Więc, jeśli warunek1 i warunek2 są prawdziwe to najpierw wykona się warunek 1, a później warunek 2. Na przykład, jeśli w praktyce pierwszy warunek będzie sprawdzał, czy liczba jest mniejsza od 10, a drugi będzie sprawdzał, czy liczba jest mniejsza od 20, to jeśli wartość sprawdzanej zmiennej będzie równa 5, to wykona się najpierw warunek1, a później od razu warunek2.

Druga sytuacja powinna wyglądać tak:

if (warunek1) {
  // Blok instrukcji numer 1
} else if (warunek2) {
  // Blok instrukcji numer 2
} else if (warunek3) {
  // Blok instrukcji numer 3
}

Tym razem warunki są połączone. Sprawdzamy warunek1, jeśli jest prawdziwy to robimy blok instrukcji numer 1 i nic więcej, nie sprawdzamy nawet innych warunków. Jeśli warunek 1 nie jest prawdziwy to przechodzimy do sprawdzenia warunku 2. Jeśli on jest prawdziwy to wykonujemy blok instrukcji numer 2 i koniec, nie sprawdzamy warunku 3. W tej sytuacji warunek 3 zostanie sprawdzony tylko, gdy warunek 1 i warunek 2 nie były prawdziwe.

Jeśli weźmiemy poprzedni przykład sprawdzający, czyli liczba równą 5, to w tym przypadku wykonałby się blok instrukcji numer 1, bo 5 jest mniejsze od 10 i tyle. Drugi warunek nie będzie nawet sprawdzany. Aby drugi warunek był prawdziwy to musiałaby zostać podana np. liczba 12. Podczas pierwszego warunku program sprawdziłbym czy 12 jest mniejsze od 10. Nie jest, więc program przeszedłby do drugiego warunku. Czy 12 jest mniejsze od 20? Tak, więc wykonujemy blok instrukcji numer 2.

Czy teraz jest to jaśniejsze? 🙂 

Link to post
Share on other sites

Witam,

W lekcji tej jest błąd w opisie 

Z wykorzystaniem potencjometru możemy zbudować dzielnik napięcia, który będzie zależny od ilości światła w otoczeniu

Raczej chodziło o fotorezystor 🙂 

Generalnie, super kurs, podobają mi się zadania domowe, na razie udało się rozwiązać wszystkie, co daje dużo satysfakcji 🙂 

Pozdrawiam

Link to post
Share on other sites

@jendrekmar miło słyszeć, że kurs jest pomocny 🙂 Dzięki za zgłoszenie błędu, w tej serii niestety może być trochę kwiatków tego typu, bo nie przechodziła ona jeszcze przez dodatkową korektę. Będzie to poprawiać 🙂

Link to post
Share on other sites

Witam serdecznie. Przy okazji wszystkiego najlepszego w nowym roku. Chciałbym aby ktoś sprawdził mój kod do zadania 4.5. Nieźle się nad nim nagłówkowałem ale myślę, że udało mi się spełnić wszystkie wymagania. Wszelkiego rodzaju rady i poprawki mile widziane.  

#define redLed 2
#define yelowLed 8
#define greenLed 7
#define button 3

String wartoscString="";
int wartoscInt=0;
int wartoscPotencjometru=0;
int licznikProb=3;


void setup() {
  
  Serial.begin(9600);
  pinMode(redLed, OUTPUT);
  pinMode(yelowLed, OUTPUT);
  pinMode(greenLed, OUTPUT);
  pinMode(button, INPUT_PULLUP);
  
  digitalWrite(redLed, HIGH);
  digitalWrite(yelowLed, HIGH);
  digitalWrite(greenLed,HIGH);
  delay(500);
  
  digitalWrite(redLed, LOW);
  digitalWrite(yelowLed, LOW);
  digitalWrite(greenLed, LOW);
 
  Serial.println("Ustaw potencjometr i wciśnij przycisk.");

  }

void loop() {
 
  while(digitalRead(button)==LOW){
    
    Serial.println("wpisz wartość z zakresy 0-1023"); //wyswietli sie raz po wcisnieciu przycisku
    delay(1000);
    }
 
  if(Serial.available()>0 ){ //jezeli przeslano dane realizwane warunki w petli
    
    wartoscPotencjometru=analogRead(A5);//zczytanie wartosci potencjometru
    wartoscString=Serial.readStringUntil('\n'); //wpisanie zgadywanej wartosci
    wartoscInt=wartoscString.toInt();//konwersja do typu int
    Serial.println(wartoscInt);

      if(wartoscPotencjometru-50<=wartoscInt && wartoscPotencjometru+50>=wartoscInt){

       Serial.println("Wygrałes!");
       digitalWrite(greenLed, HIGH);
         
      }else{
        
       if(licznikProb>1){
        
         licznikProb--;
              
         digitalWrite(yelowLed, HIGH);
         Serial.println("Źle Spróbuj jeszcze raz");
         Serial.print("Pozostałe próby: ");
         Serial.println(licznikProb);
         delay(1000);
         digitalWrite(yelowLed, LOW);
         
       }else{
        
        Serial.println("Przegrałeś");
        digitalWrite(redLed,HIGH);
       }
      }
  }
}

 

Link to post
Share on other sites

@gryzmol88 witam na forum 🙂 Na pierwszy rzut oka chyba jest dobrze, warto na pewno tylko trochę popracować nad formatowaniem kodu - postaraj się trochę ładniej wszystko ułożyć (spacje, wcięcia) i będzie super.

  • Lubię! 1
Link to post
Share on other sites

Witam

Wszystkiego dobrego w Nowym Roku

Moje zadnie 4.5 wygląda jak niżej:

#define nacisnijPrzycisk 2 //przycisk
#define przegrana 4 //dioda czerowna
#define zlaLiczba 7 //zlota dioda
#define liczbaTrafiona 8 //zielona dioda

byte iloscProb = 1; //ilosc nacisniec przycisku
int odczytanaWartosc = 0; //odczyt wartosci z A5 ADC
String odczytanaLiczba = ""; //odczyt wartosci z panelu
bool dobraLiczba = false;

void setup(){
  Serial.begin(9600); //uruchomienie komunikacji A<>PC
  while (!Serial) {
    ; // ze stony Arduino.cc - nie tlimaczone - wait for serial port to connect. Needed for native USB 
  }
  pinMode(nacisnijPrzycisk, INPUT_PULLUP); //konfiguracja przycisku
  
  pinMode(przegrana, OUTPUT);              //konfiguracja diod
  pinMode(zlaLiczba, OUTPUT);
  pinMode(liczbaTrafiona, OUTPUT);
  
  digitalWrite(przegrana, LOW);          //zerowanie pinow
  digitalWrite(zlaLiczba, LOW);
  digitalWrite(liczbaTrafiona, LOW);

  Serial.println("Witaj w grze");
  Serial.println("");
  delay(100);
  Serial.println("Zasady:");
  Serial.println("dioda zielona - wygrana");
  Serial.println("dioda zolta - zle wpisales liczbe");
  Serial.println("dioda czerwona - przegrana");
  Serial.println("");
  Serial.println("Ustaw wartosc pokretłem na plytce i wciśnij przycisk");
  Serial.println ("");
  delay(100);
}

void loop() {

  while (digitalRead(nacisnijPrzycisk) == HIGH){
    odczytanaWartosc = analogRead(A5); //odczytana wartosc z wejscia analogowego A5 ADC
  }
  
  Serial.println("Wpisz liczbę z zakresu od 0 do 1023: "); //Podaj liczbe do prownania

  while (iloscProb < 4){
    while (Serial.available() == 0) {
    }
    odczytanaLiczba = Serial.readStringUntil('\n'); //wpisana liczba przez użytkownika
    
    //jak liczba trafiona, to wygrana
    if (odczytanaWartosc >= odczytanaLiczba.toInt() - 50 && odczytanaWartosc < odczytanaLiczba.toInt()+50){
      digitalWrite(liczbaTrafiona, HIGH); // 
      Serial.println("Wygrana");
      iloscProb = 4;
      dobraLiczba = true;
    }

    //liczba nie trafiona 2 proby
    if (odczytanaWartosc < odczytanaLiczba.toInt() - 50 or odczytanaWartosc > odczytanaLiczba.toInt()+50){
      if (iloscProb <= 2) {
        digitalWrite(zlaLiczba, HIGH);
        Serial.println("Wpisz jeszcze raz");
        dobraLiczba = false;
      }
      
    }
    //3 proby - liczba nie trafiona - przegrana
    if (iloscProb == 3 && dobraLiczba == false ){
      digitalWrite(przegrana, HIGH);
      Serial.println("Przegrana");    
    }
    
    iloscProb++;  //licznik ilosci prob
    delay(1000);
    digitalWrite(liczbaTrafiona, LOW);
    digitalWrite(zlaLiczba,LOW);
    digitalWrite(przegrana,LOW);
  }
  iloscProb=1; // licznik prob na 1 i gramy jeszcze raz
  Serial.println("Gramy jeszcze raz, to nacisnij przycisk");
  Serial.println("");
}

 

Pozdrawiam

  • Lubię! 1
Link to post
Share on other sites

Witam,

mam mały problem  fotorezystorami w zadaniu 4.6, przy tych samych warunkach mam zupelnie dwa rożne pomiary:

07:50:58.557 -> A1: 857       = pomiar na wejści A1
07:50:58.557 -> A4: 722      = pomiar na wejści A4
07:50:58.591 -> 135             = różnica

Ustawiłem je obok siebie, aby miałe te same warunki oświetlenie i jest podobnie.

W czym może być problem?? 

Według mnie różnica powinna być kilka kilkanaście jednostek, a przeliczeniu na napięcie ta różnica dochodzi od 0,7 - 0,9 V.
 

Link to post
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

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.