Skocz do zawartości
Komentator

Kurs Arduino - #4 - Przetwornik ADC

Pomocna odpowiedź

int lives;
int right;
int guess;
String sent;

void setup() {
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, INPUT);
  digitalWrite(10, LOW);
  digitalWrite(9, LOW);
  digitalWrite(8, LOW);
  Serial.begin(9600);
  lives = 3;
  right = analogRead(A5);
}

void loop() {
  if(lives == 0){
    digitalWrite(10, HIGH);
    return;
  }else{
    Serial.println("Podaj liczbę");
    while(Serial.available() == 0){}
    sent = Serial.readStringUntil('\n');
    guess = sent.toInt();
    if((right - 50) < guess < (right + 50)){
      digitalWrite(8, HIGH);
      return;
    }else{
      digitalWrite(9, HIGH);
      lives = lives - 1;
    }
  }
}

Próbowałem zrobić zadanie 4.5. Wydaje mi się, że ten kod powinien działać, ale zielona(8) i żółta(9) dioda nie zapalają się w ogóle, a czerwona(10) włączyła się tylko raz po podaniu 3 błędnych odpowiedzi. Potencjometr jest podłączony do A5, a jako przycisk postanowiłem użyć tego już wbudowanego w płytkę. Co zrobiłem źle?

Udostępnij ten post


Link to post
Share on other sites
2 minuty temu, Itap88 napisał:

Potencjometr jest podłączony do A5, a jako przycisk postanowiłem użyć tego już wbudowanego w płytkę. Co zrobiłem źle?

@Itap88 zacznijmy od najważniejszego... Na Arduino UNO nie ma żadnego przycisku, który można wykorzystać we własnych programach. Jest tam ewentualnie tylko RESET... Co dokładnie wykorzystałeś w roli przycisku? Po drugie w Arduino nie można tworzyć warunków tego typu:

if((right - 50) < guess < (right + 50)){

Jest wiele sposobów na rozwiązanie tego problemu (np. najprostszy to rozbicie tego na dwa warunki), ale na pewno nie można robić tego tak, jak w cytowanym tutaj fragmencie.

  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites

@Treker Rzeczywiście. W roli przycisku restartującego grę użyłem przycisku RESET. Jest to problem?

A poza tym zmieniłem kod i teraz wygląda tak:

int lives;
int right;
int guess;
String sent;
int right_min;
int right_max;

void setup() {
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, INPUT);
  digitalWrite(10, LOW);
  digitalWrite(9, LOW);
  digitalWrite(8, LOW);
  Serial.begin(9600);
  lives = 3;
  right = analogRead(A5);
  right_min = right - 50;
  right_max = right + 50;
}

void loop() {
  if(lives == 0){
    digitalWrite(10, HIGH);
    return;
  }else{
    Serial.println("Podaj liczbę");
    while(Serial.available() == 0){}
    sent = Serial.readStringUntil('\n');
    guess = sent.toInt();
    if(right_min < guess){
      if(guess < right_max){
        digitalWrite(8, HIGH);
      	return;
      }else{
        digitalWrite(9, HIGH);
      	lives = lives - 1;
      }
    }else{
      digitalWrite(9, HIGH);
      lives = lives - 1;
    }
  }
}

i nadal działa tak samo, czyli praktycznie nie działa.

Udostępnij ten post


Link to post
Share on other sites

@Itap88 przyznam, że nie rozumiem niektórych fragmentów Twojego programu. Możesz dodać do niego komentarze? Będzie łatwiej zrozumieć co masz na myśli i szybciej znajdziemy rozwiązanie 🙂

Udostępnij ten post


Link to post
Share on other sites

@Treker Dodałem komentarze. Chyba nawet za dużo.

int lives;//liczba prób
int right;//wartość z potencjometru
int guess;//wartość podana przez gracza
String sent;//wartość wysłana do arduino
int right_min;//zakres podanych wartości dających zwycięstwo
int right_max;

void setup() {//zawsze po wciśnięciu przycisku RESET
  pinMode(8, OUTPUT);//wyjścia na diody: zielona
  pinMode(9, OUTPUT);//żółta
  pinMode(10, OUTPUT);//czerwona
  digitalWrite(10, LOW);//wyłączenie diód
  digitalWrite(9, LOW);
  digitalWrite(8, LOW);
  Serial.begin(9600);//start transmisji
  lives = 3;//trzy próby
  right = analogRead(A5);//odczytanie potencjometru i ustawienie zakresu
  right_min = right - 50;
  right_max = right + 50;
}

void loop() {
  if(lives == 0){//jeśli brak prób
    digitalWrite(10, HIGH);//zapal czerwoną diodę - przegrana
    return;//wyjdź z funkcji - zakończ program
  }else{
    Serial.println("Podaj liczbę");//informacja dla gracza
    while(Serial.available() == 0){}//oczekiwanie na odpowiedź
    sent = Serial.readStringUntil('\n');//odczytanie odpowiedzi
    guess = sent.toInt();//konwersja na liczbę
    if(right_min < guess){//czy odpowiedź mieści się w zakresie (min)
      if(guess < right_max){//czy odpowiedź mieści się w zakresie (max)
        digitalWrite(8, HIGH);//włącz zieloną diodę - zwycięstwo
      	return;//zakończ program
      }else{
        digitalWrite(9, HIGH);//zapal żółtą diodę - ostrzeżenie
      	lives = lives - 1;//utrata próby
      }
    }else{
      digitalWrite(9, HIGH);//zapal żółtą diodę - ostrzeżenie
      lives = lives - 1;//utrata próby
    }
  }
}

i doszedłem do wniosku, że nie wiem czy return; działa tu tak, jak myślę że działa.

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

funkcja void loop() nigdy się nie kończy zobacz:

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\main.cpp

więc po co ten return; ?

Edytowano przez Belferek
  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites

@Belferek Nie wiedziałem, że ten return; nie działa. Teraz już wiem.

Nie wiem dlaczego, ale po odłączeniu i ponownym podłączeniu diód wszystko działa.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Nie wiem co to u Ciebie znaczy "odłączenie i ponowne podłączenie" -  ja staram się nie dokonywać takich modyfikacji przy pracującym urządzeniu. Może system się resetuje? Serial.println("Reset systemu...:); w setup() może pomóc w diagnostyce.

Edytowano przez Belferek
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@Belferek Odłączenie i ponowne podłączenie oznacza po prostu rozłożenie obwodu elektrycznego na elementy składowe i ponowne jego złożenie.

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

No to jeszcze powiedz co Ci pokazał wynik eksperymentu z Serial.println w setup(); Czy aby nie masz sytuacji, że wszystko wraca do normy po resecie uC?

Edytowano przez Belferek

Udostępnij ten post


Link to post
Share on other sites

@Belferek mam wrażenie, że autor zwyczajnie złożył układ od nowa i teraz wszystko działa. Zapewne był jakiś drobny błąd w pierwotnym montażu 🙂

Udostępnij ten post


Link to post
Share on other sites

Witam,

Mam pytanie odnośnie zadania 4.5. Po wpisaniu błędnej lub poprawnej wartości program powinien czekać na wciśnięcie przycisku i podanie nowej wartości, a jest inaczej. Program czeka na przycisk, po wciśnięciu przeskakuje bez oczekiwania na wpisanie liczby. W kolejnej próbie program ponownie oczekuje na wpisanie liczby.  Gdzie popełniam błąd? Będę wdzięczny za podpowiedź, ponieważ sam nie potrafię wymyślić rozwiązania. Moim zdaniem wygląda to tak jak by funkcja Serial.available() zwracała wartość 1 bez ponownego wpisania liczby do monitora.

int wartoscLosowa = 0;
int liczbaGracza = 0;
int proba=2;

void setup(){
  Serial.begin(9600);
  pinMode(3, INPUT_PULLUP);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  
  
}
void loop(){
 
  wartoscLosowa = analogRead(A4); //odczytanie wejścia
  while(digitalRead(3) == HIGH){} //oczekiwanie na wciśnięcie przycisku
  delay(20);
  digitalWrite(8, LOW);           // ustawienie stanu diody
  digitalWrite(9, LOW);           // ustawienie stanu diody
  digitalWrite(10, LOW);          // ustawienie stanu diody
  Serial.println("Podaj liczbę"); 
  while(Serial.available() == 0){} //oczekiwanie na wprowadzenie liczby
  liczbaGracza = Serial.parseInt();
  if(((wartoscLosowa-50)<liczbaGracza)&&((wartoscLosowa+50)>liczbaGracza)){      //sprawdzenie czy wprowadzona liczba spełnia warunek
  digitalWrite(8, HIGH);         //jeśli tak to zapalenie diody zielonej
  Serial.println("Wygrana");                                                     
  }
  else          //jeśli wprowadzona liczba nie mieści się w zakresie
  {
  digitalWrite(9, HIGH);            // zapalenie diody żółtej
  Serial.println("Spróbuj ponownie, pozostało prob: ");                                 
  Serial.println(proba);
  proba = proba -1;         //dekrementacja ilości pozostałych prób
  }
  if(proba == -1){     //jesli wykorzystano wszystkie próby
  digitalWrite(10, HIGH);      // ustawienie stanu diody 
  digitalWrite(9, LOW);        // ustawienie stanu diody
  digitalWrite(8, LOW);        // ustawienie stanu diody
  proba = 2;                   // ustawienie licznika prób
  Serial.println("Game Over");
  }
  delay(20);
  }

 

Udostępnij ten post


Link to post
Share on other sites

@Qbek witam na forum! Jak masz ustawiony monitor portu szeregowego? Sprawdź jak na działanie programu wpływa opcja dodawania (lub nie) znaków końca linii (rozwijane okienko w oknie monitora) 🙂

  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites
Cytat

witam na forum! Jak masz ustawiony monitor portu szeregowego? Sprawdź jak na działanie programu wpływa opcja dodawania (lub nie) znaków końca linii (rozwijane okienko w oknie monitora) 

@TrekerW monitorze miałem ustawienie "Nowa linia", po zmianie na "brak zakończenia linii" problem ustąpił. 

Dziękuję bardzo za szybką odpowiedź. 

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Świetny kurs. Jako ktoś ZUPEŁNIE zielony w temacie jestem w stanie ogarnąć przykłady i tworzyć już pierwsze własne, proste projekty.

Drobna uwaga matematyczna (proszę o korektę jeśli się mylę)  - jeśli tworzymy nasz pierwszy prosty woltomierz to dzielić powiniśmy nie przez ilość stanów a przez wartość maksymalną. Dzieje się tak, ponieważ przetwornik ADC tak naprawdę przetwarza zakres wartości analogowych na wartość cyfrową (nie może przetwarzać każdego stanu bo jest ich nieskończenie wiele, jak to w świecie analogowym). Jeśli mamy 1024 stany to dysponujemy jedynie 1023 zakresami.

Prosty dowód: jeśli dzielimy przez 1024.00 (jak w przykładzie) przy odczycie wartości z potencjometru 1023 (czyli maksymalnym) oraz napięciu 5V otrzymujemy V=5.00*(1023/1024)=4,995 V. Przy dzieleniu przez 1023 wynik wynosi dokładnie 5.00V. Przyznaję, różnica symboliczna ale im słabszy (o mniejszej rozdzielczości) przetwornik tym większe ma to znaczenie.

Pozdrowienia i raz jeszcze dziękuję za kurs!

  • Lubię! 2

Udostępnij ten post


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