Skocz do zawartości
Komentator

Kurs Arduino - #4 - Przetwornik ADC

Pomocna odpowiedź

Jeden drobiazg: ja bym najpierw mapował różnicę na led_index, i na nim wywoływał constrains. Niby to samo, ale nie do końca 🙂

  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites

 (odpowiedź na edycję poprzedniego posta) Po zmapowaniu oczywiście!

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Przy setupie jak już masz tablicę z pinami to możesz kontynuować jej używanie - domyslam się że jest to pozostałość z poprzedniego podejścia, ale to nie jest teraz istotne.

Constrain najlepiej użyj przed map, wtedy masz pewność jakie argumenty wchodzą do kolejnego etapu. (Edit: no właśnie 🙂 nie zauważyłem kolejnej strony)

A na czym polega nie działanie?

 

Edytowano przez Gieneq

Udostępnij ten post


Link to post
Share on other sites

@Gieneq constrains najlepiej użyć za map, bo wtedy międli ciebie jakie dane wchodzą, a masz pewność że dane które wychodzą są prawidłowe 🙂

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@Gieneq 

Problem tkwi chyba w samym podłączeniu diód do układu mimo, że jest wręcz podręcznikowe tak jak w każdym przerabianym przykładzie w kursie. 

Ponieważ odczytywanie wartości z fotorezystorów czy to czystych, czy to zmapowanych i ograniczonych przebiega jak najbardziej pomyślnie i dobrze. 

Samo odpalanie diód nie działa ponieważ w żadnym z możliwych przypadków nie świeci się ani jedna 😕 

Udostępnij ten post


Link to post
Share on other sites

@Gieneq @ethanak

DOBRA! Trochę się spóźnię do pracy ale musiałem zakończyć temat tego zadania.

Zmieniłem trochę sposób podłączenia diod do układu i DZIAAAAAAAAŁAAAAAAAA! 

Będę teraz pamiętał, że ten sposób sprawdza się lepiej od poprzedniego. 

Dziękuje jeszcze raz bardzo wszystkim za pomoc! 😍

  • Lubię! 2

Udostępnij ten post


Link to post
Share on other sites

Witajcie,

Przedstawiam kod do Zadania 4.5. Wszystko działa aczkolwiek miałem pewien problem, który udało mi się rozwiązać dzięki przeczytaniu 11 stron komentarzy w tym wątku i dopisaniu w odpowiednim miejscu Serial.read(); (oznaczone komentarzem w kodzie). Mianowicie, kiedy nie było Serial.read(); to przy podaniu liczby i jej zatwierdzeniu, pętla wykonywała się dwa razy. Sytuację przedstawiam na dołączonym screenie - na potrzeby "wersji beta" dodałem w programie wyświetlanie w monitorze liczby jaką wprowadza użytkownik oraz liczby odczytanej z potencjometru. Po dodaniu Serial.read(); problem znika. Proszę o wytłumaczenie z czego to wynika i co dokładnie robi funkcja Serial.read();. Proszę też o ewentualne uwagi co do struktury kodu.

PS. Do programu dodałem dodatkowe sygnalizowanie diodami w przypadku startu systemu oraz błędnej odpowiedzi - proszę o niezwracanie na to uwagi.

Pozdrawiam.

#define przycisk 2
#define zielona 8
#define czerwona 9
#define zolta 10

int wartoscOdczytana = 0;
int liczbaPodana = 0;
int licznik = 0;
boolean przegrana = false;

void setup() 
{
  pinMode(przycisk, INPUT_PULLUP);
  pinMode(zielona, OUTPUT);
  pinMode(czerwona, OUTPUT);
  pinMode(zolta, OUTPUT);

  digitalWrite(zielona, HIGH);
  digitalWrite(czerwona, HIGH);
  digitalWrite(zolta, HIGH);
  delay(500);
  digitalWrite(zielona, LOW);
  digitalWrite(czerwona, LOW);
  digitalWrite(zolta, LOW);
}

void loop() 
{
 wartoscOdczytana = analogRead(A5);
 
 if(digitalRead(przycisk) ==  LOW)
    {
      Serial.begin(9600);
      Serial.println("Podaj liczbę:");
      delay(200);
    }

  if(licznik < 3)
    {
          if(Serial.available() > 0)
        {
          liczbaPodana = Serial.parseInt();
    
          Serial.println("Twoja liczba to: ");
          Serial.println(liczbaPodana);
          Serial.println("Wartość odczytana to: ");
          Serial.println(wartoscOdczytana);
    
          if((wartoscOdczytana - 50) < liczbaPodana && liczbaPodana < (wartoscOdczytana + 50))
            {
              digitalWrite(zielona, HIGH);
              delay(1000);
              Serial.println("Wygrałeś!");
              while(1){}
            }
          else
            {
              digitalWrite(zolta, HIGH);
              digitalWrite(czerwona, HIGH);
              delay(100);
              digitalWrite(czerwona, LOW);
              delay(100);
              digitalWrite(czerwona, HIGH);
              delay(100);
              digitalWrite(czerwona, LOW);
              delay(100);
              digitalWrite(czerwona, HIGH);
              delay(100);
              digitalWrite(czerwona, LOW);
              delay(100);
              Serial.println("Błąd! Spróbuj ponownie!");
            }
          licznik++;
          Serial.read();                                          //TUTAJ
        }  
    }
   else if (przegrana == false)
    {
      Serial.println("Przegrałeś ofiaro!");
      digitalWrite(czerwona, HIGH);
      przegrana = true;
    }
}

 

ococho.png

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

@Stark w poprzedniej części kursu był podobny przykład, gdzie pobierało się od użytkownika dane:

String odebraneDane = ""; //Pusty ciąg odebranych danych

void setup() {
  Serial.begin(9600); //Uruchomienie komunikacji
}

void loop() {
  if(Serial.available() > 0) { //Czy Arduino odebrało dane
    odebraneDane = Serial.readStringUntil('\n'); //Jeśli tak, to odczytaj je do znaku końca linii i zapisz w zmiennej odebraneDane
    Serial.println("Witaj " + odebraneDane + "!"); //Wyświetl komunikat
  }
}

Nie próbowałeś tego z tym powiązać i dopiero pobrany Sting zamienić na int (a w zasadzie na long)?

Co do Serial.read() to polecam dokumentację funkcja ta zwraca byte danych z bufora. Dlaczego zaczęło działać? Nie wiem 🙂 Może w jakiś sposób opróżnia coś z bufora, nie jest to jednak zbyt trafione użycie.

Edytowano przez Gieneq

Udostępnij ten post


Link to post
Share on other sites
14 godzin temu, Gieneq napisał:

Nie próbowałeś tego z tym powiązać i dopiero pobrany Sting zamienić na int (a w zasadzie na long)?

Tak, mogłem tak zrobić, ale chciałem zrobić to jak najbardziej optymalnie. Czy ten sposób albo funkcja jakiej użyłem są niepoprawne?

Z jakiegoś powodu w buforze znajduje się cyfra 0 po przesłaniu dowolnej liczby do programu, co powoduje, że pętla wykonuje się jeszcze raz. 

14 godzin temu, Gieneq napisał:

Co do Serial.read() to polecam dokumentację funkcja ta zwraca byte danych z bufora. Dlaczego zaczęło działać? Nie wiem 🙂

Tak, dziękuję. W kolejnej części kursu było wyjaśnione co robi funkcja o której mowa. W moim przypadku po zastosowaniu funkcji dane te zostały pobrane, co wyeliminowało kolejne wykonanie pętli. Moje pytanie - skąd wzięły się tam te dane?

Ponadto zauważyłem, że przed rozpoczęciem gry (wciśnięcie przycisku), kiedy transmisja danych jest już uruchomiona (w kodzie powyżej rozpoczęcie jest już po wciśnięciu przycisku) a prześlemy do programu dowolne liczby to będą one czekać w kolejce, aby po rozpoczęciu gry "same się wpisać" - to już jest dla mnie zrozumiałe. 

Pewnie kiedy bym wiedział, jak to wszystko dokładnie funkcjonuje to bym to rozszyfrował, ale dopiero zaczynam. Dziś minął mój czwarty dzień z Arduino, jestem już po lekcji ze sterowaniem silnikami DC - stworzyłem dziś pojazd, który jeździ, więc myślę, że idzie dość sprawnie.

Korzystając z okazji, ponownie dziękuję za te kursy, które niesamowicie przyspieszają proces nauki.

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Witam,

Szybkie pytanie - czy mogę użyć funkcji map(), żeby z interwału konwertera (0-1023) przeskalować go na interwał z liczbami zmiennoprzecinkowymi? W ten sposób można by ominąć tworzenie dwóch zmiennych w celu stworzenia naszego woltomierza.

Mój zmieniony program:

float voltage = 0; // Zmienna, na której będziemy działać

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

void loop() {
  voltage = analogRead(A5); // Zczytuje wartość z pinu - teraz jest w formie cyfrowej, interwał 0-1023
  voltage =  map(voltage, 0, 1023, 0.0, 5.0); // Przeskalowuje cyfrowy interwał na interwał, który pokazuje napięcie
  // Użyłem zapisu 0.0-5.0 zamiast 0-5, żeby uniknąć oczywistej omyłki
  Serial.println(voltage); // Pokazuje przeskalowane napięcie w Monitorze
  delay(200);
}

Program mimo zapisu z zerem po przecinku skaluje napięcie w taki sposób, że można zczytać je z dokładnością do cyfry jedności. Efekt podobny jak gdyby zastosować zapis 0-5, z tym że za każdą z tych cyfr pojawiają się dwa zera.

Przykładowo:
0.00
1.00
4.00 itd.

Czy używam nie poprawnie funkcji map() i nie powinno się jej używać do skalowania do interwałów z liczbami po przecinku (jak sugeruje google)? Czy może robię coś innego nie tak? Liczę na Waszą pomoc, z góry dziękuję 🙂

Edytowano przez Gieneq
Zachęcam do używania bloku kodu

Udostępnij ten post


Link to post
Share on other sites

@bujo2001 najlepiej napisz własną funkjcę, bo map od Arduino przyjmuje za argumenty longi:

long map(long x, long in_min, long in_max, long out_min, long out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

 

  • Lubię! 1
  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites

@Gieneq Wszystko jasne, dzięki bardzo :))
Nie zauważyłem, że jest taka opcja, teraz na pewno będę z tego korzystać, wszystko staje się o wiele czytelniejsze.

 

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Witam, mam problem z zad. 4.5. Nie mogę dojść dlaczego po wygranej lub wykorzystaniu wszystkich prób program nie chce włączyć się od nowa, tak jakby zatrzymywał się w miejscach gdzie zaznaczyłem w kodzie. Już nie mam pomysłu co może być nie tak. Usunięcie pętli while na wciśnięcie przycisku nic nie daje.

#define czerwona 10
 #define zolta 9
 #define zielona 8
 #define przycisk 2 
 
 int odczytanaWartosc = 0; //Zmienna do przechowywania odczytu ADC
 String zgadywana_liczba= "";
 int zgadywana_liczba_int = 0;
 bool od_nowa =true;
 int proby = 0;

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

 if(od_nowa == true){
   digitalWrite(zielona, LOW);
   proby = 2;
   Serial.println("Przekrec potencjometr i wcisnij przycisk");
   while (digitalRead(przycisk)==HIGH);
   odczytanaWartosc = analogRead(A5);
   Serial.println(odczytanaWartosc);
   Serial.println("Podaj liczbe: ");
 }

 
   while (Serial.available() == 0);
   zgadywana_liczba = Serial.readStringUntil('\n');
   zgadywana_liczba_int = zgadywana_liczba.toInt();

   
   if(odczytanaWartosc - zgadywana_liczba_int <= 50 && odczytanaWartosc - zgadywana_liczba_int >= -50){
    Serial.println("Gratulacje wygrales! wcisnij przycis aby zagrac ponownie");
    digitalWrite(zielona, HIGH);
    digitalWrite(zolta, LOW);
    od_nowa == true;
    while (digitalRead(przycisk)==HIGH) delay(20); /////////////////////////w tym miejscu nie dzie dalej
   }
   else if(proby>0){
     od_nowa=false;
     proby--;
     Serial.println("Pozostalo prob: ");
     Serial.println(proby+1);
     digitalWrite(zolta, HIGH);
     Serial.println("Niestety nie trafiles. Podaj kolejna liczbe: ");
     digitalWrite(czerwona, HIGH); delay(3000); digitalWrite(czerwona, LOW);
    }
    else {
     digitalWrite(czerwona, HIGH); delay(3000); digitalWrite(czerwona, LOW);
     Serial.println("Koniec gry :( wcisnij przycisk i sproboj jeszcze raz!");
     digitalWrite(zolta, LOW);
     od_nowa == true;
     while (digitalRead(przycisk)==HIGH) delay(20); //w tym miejscu też nie dzie dalej (po usunięciu warunku na naciśnięcie przycisku też stoi w miejscu)
     }
    delay(5);
}

 

Udostępnij ten post


Link to post
Share on other sites

@kerifprzemek witam na forum 🙂 Te linijki "od_nowa == true;" to pozostało po jakimś warunku czy po prostu błąd przypisywania? Przypominam, że podwójny znak równości wykorzystujemy wewnątrz warunków do porównań - przypisywanie to pojedynczy znak równości. Daj znać skąd to się wzięło to ruszymy dalej ze sprawdzaniem 🙂

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

@Treker Linijki "od_nowa == true;" wzięły się z głupiego przekopiowania z if'a na początku i nie zmienienia znaku == na =. Wiedziałem, że tak się nie robi a mimo tego nie zauważyłem. Tak to jest jak się człowiek spieszy i kopiuje bezmyślnie. Dziękuję za pomoc. Będzie nauczka na przyszłość. 🙂

Program wymagał jeszcze tylko dodania małego opóźnienia (zmieniłem wartość delay na końcu z 5 na 1000), ponieważ naciśnięcie przycisku powodowało jednoczesne spełnienie warunku z początku programu w wyniku czego po przejściu jednej pętli programu od razu przechodziło z polecenia "Przekrec potencjometr i wcisnij przycisk" do "podaj liczbę".

Edytowano przez kerifprzemek

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...