Skocz do zawartości

Kurs Arduino - #4 - Przetwornik ADC


Pomocna odpowiedź

Niespodziewałem się tak szybkiej odpowiedzi 😉

Po tym fragmencie oczekuje nic nie robienia, dopóki przycisk jest nie wciśniety. Pomysł wzięty z trzeciej części kursu

   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
   }

Link do komentarza
Share on other sites

Artur, przeanalizuj dokładnie działanie programu z poprzedniej części. Tam zatrzymywaliśmy program w innym miejscu.

Podłącz przełącznik, napisz program z prostym if'em i sprawdź kiedy odczytamy z niego stan LOW, a kiedy HIGH. Przeanalizuj wtedy powyższy fragment. To powinno podsunąć Ci pewne wskazówki 🙂

Link do komentarza
Share on other sites

Program zatrzymywany w innym miejscu ale idea ta sama, dopóki nie wcisnę przycisku, nie robić nic.

#define button 3
void setup() {
   Serial.begin(9600);
   pinMode(button, INPUT_PULLUP);
}

void loop() {
 if (digitalRead(button) == LOW) {
   Serial.println(" Warunek if");
}
}

Napis się wyświetla gdy wcisnę przycisk. LOW wciśnięty, HIGH nie wciśnięty.

Nie czuję na co mnie próbujesz naprowadzić.

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

Artur, dobra Arduino podłączone i dopiero teraz zrozumiałem problem, jeszcze raz przepraszam za zamieszanie 🙂

Ogólnie poruszyłeś ciekawą sprawę, bo w Arduino nie ma gotowej funkcji czyszczącej bufor informacji odbieranych przez mikrokontroler. Można oczywiście jednak zrobić to samodzielnie. Na przykład poprzez... odbieranie wszystkiego, co się pojawi i nie robienie z tym niczego. Od strony kodu będzie można to zrealizować tak:

while(Serial.available()) {
 Serial.read();
}

Powyższy fragment można wstawić w miejscu, w którym chciałbyś kasować bufor. Sprawdziłem działa.

Spróbuj dojść samemu, gdzie umieścić ten kod, a w razie problemów pytaj 🙂

Link do komentarza
Share on other sites

Wielki dzięki, o to mi chodziło. Wstawiłem kod zaraz po wciśnięciu przycisku, a przed poleceniem "Podaj liczbę", w tym miejscu działa jak należy.

W innych miejscach było użyte coś takiego

if (Serial.available() > 0 )

W tej pętli while jest bez tego " > 0".

Czy można ogólnie to pominąć ? Czy Serial.available() może być liczbą ujemną ?

Jeszcze raz dzięki za super kurs, biorę się za część 5.

Link do komentarza
Share on other sites

Artur, cokolwiek podane w warunku, co będzie różne od zera zostanie potraktowane jako prawda/logiczne "1", więc zapis: if (Serial.available() > 0) jest tożsamy z if (Serial.available()). Pierwsza wersja jest czytelniejsza, a druga szybsza w pisaniu - co kto woli 🙂

Link do komentarza
Share on other sites

zad.4.4:

int odczytanaWartosc = 0;           //Zmienna do przechowywania odczytu ADC
int prog = 0;                       //Próg włączenia światła - ustawiany potencjometrem
boolean komunikat = true;           // przełącznik decydujący o wyświetlaniu komunikatu
 
void setup()
{
  pinMode(8, OUTPUT);               //Konfiguracja wyjść pod diodę LED
  Serial.begin(9600);               // ustawienie prędkości transmisji
}
 
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);        // jeśli tak to włączenie diody 
     if (komunikat)                // gdy potrzeby jest komunikat
     {
       String napis = "Odczytana wartosc = ";            //
       int volty = odczytanaWartosc * (5.0 / 1023.0);    // układanie napisu 
       napis = napis + volty + " V";                     //
       Serial.println(napis);      // komunikat do komputera                      
       komunikat = false;          // następny komunikat nie jest w tym cyklu potrzebny
     }  
  } 
  else                             // jest jaśniej
  {
     digitalWrite(8, LOW);         //Wyłączenie diody 
     komunikat = true;             // komunikat znów będzie potrzebny   
  }
  delay(50);
}

Jak to wygląda?

zad4.5:

#define zielona 7
#define zolta 8
#define czerwona 9
#define przycisk 2
#define kreciol A4

int odczytanaWartosc = 0;           //Zmienna do przechowywania odczytu ADC
int proba = 0;                      // ilość prób
 
void setup()
{
  pinMode(przycisk, INPUT_PULLUP);  // wejście przełącznika
  pinMode(zielona, OUTPUT);         // konfiguracja wyjść pod diodę LED
  pinMode(zolta, OUTPUT);           // konfiguracja wyjść pod diodę LED
  pinMode(czerwona, OUTPUT);        // konfiguracja wyjść pod diodę LED
  Serial.begin(9600);               // ustawienie prędkości transmisji
  Serial.println("Zagraj! Ustaw potencjometr i nacisnij przycisk"); 
}
 
void loop()
{
  while(digitalRead(przycisk) == HIGH);           // oczekiwanie na przycisk
  digitalWrite(zielona, LOW);                 //
  digitalWrite(czerwona, LOW);                // wygaszanie diod
  digitalWrite(zolta, LOW);                   //
  proba = 1;                                  // liczymy od nowa
  odczytanaWartosc = analogRead(kreciol);       // odczyt wartości z potencjometru
  while(proba < 4)                                // do trzech razy sztuka 
  {                                              // gracz podaje liczbę
    String odebranaLiczba = ("");
    Serial.print("Proba ");
    Serial.println(proba);
    Serial.println("Podaj liczbe (od 0 do 1023)");
    while(Serial.available() == 0);                        // oczekiwanie na liczbę
    odebranaLiczba = Serial.readStringUntil('\n');         // przepisujemy do zmiennej
    Serial.print("Twoja liczba to: ");
    Serial.println(odebranaLiczba);
    int wynik = odebranaLiczba.toInt();                    // zwracamy wynik jako INT
    if ((wynik <= (odczytanaWartosc + 50)) && (wynik >= (odczytanaWartosc - 50)))
    {                                            // liczba mieści się w granicach błędu
      Serial.print("Wygrales w probie nr ");
      Serial.println(proba);
      digitalWrite(zolta, LOW); 
      digitalWrite(zielona, HIGH);
      Serial.println("Zagraj jeszcze raz. Ustaw potencjometr i nacisnij przycisk"); 
      proba = 5;                                // wyjście z while po wygranej
    } 
    else 
    {                                            // liczba nie mieści się w granicach
       Serial.println("Za duzy blad");
       digitalWrite(zolta, HIGH);
       delay(100);
       proba++;
    }
  }
  if(proba == 4)                                  // za dużo prób
  {
     Serial.println("Przegrales!");
     digitalWrite(zolta, LOW); 
     digitalWrite(czerwona, HIGH);
     Serial.println("Zagraj jeszcze raz. Ustaw potencjometr i nacisnij przycisk"); 
  }
}

Nie wstawiałem początkowego opisu bo to tylko dużo pisania a mało nauki!

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

zad.4.6

Największym problemem jest dobranie fotorezystorów i ich dzielników tak, aby wskazania były przynajmniej podobne dla podobnego oświetlenia. Niestety, fotorezystory z zestawu mają bardzo duży rozrzut parametrów. Ale dość narzekania:

#define zielona 2          // przypisanie kolorów diod do pinów,
#define Lzolta 4           // wybór pinów został uależniony
#define Lczerwona 7        // od metody obliczeń,
#define Pzolta 6           // prosta formuła wybiera nam
#define Pczerwona 5        // odpowiednią diodę
#define niebieska 3        // sygnalizacja braku oświetlenia

int leweOko = 0;           // Zmienna do przechowywania odczytu ADC
int praweOko = 0;          // Zmienna do przechowywania odczytu ADC
int czulosc = 100;          // współczynnik przeskalowania wartości z ADC
float prog = 10.0;         // dolny próg oświetlenia jako procent maksymalnej jasności
int kierunek = 0;          // ustalenie kierunku 0 - na wprost, 1 - lewo, 3 - prawo (3 dla uproszczenia obliczeń) 
int wielkosc = 0;          // wielkość kąta odchylenia od osi 0 - brak, 1 - małe (do np.20 stopni), 2 - duże (np. 45 stopni)
 
void setup()
{
  for( int i = 1; i < 7; i++)        // po kolei
  {
    pinMode(i, OUTPUT);              // ustawiamy piny jako wyjścia
    digitalWrite(i, LOW);            // wygaszamy podpięte do nich diody
  }
  Serial.begin(9600);               // ustawienie prędkości transmisji
  prog = (prog * czulosc) / 100.0;  // próg czułości układu fotorezystorów
}
 
void loop()
{
  leweOko = analogRead(A1);          // odczyt z lewego oka
  leweOko = map(leweOko, 0, 1023, 0, czulosc);
  praweOko = analogRead(A2);         // odczyt z prawego oka
  praweOko = map(praweOko, 0, 1023, 0, czulosc);
  if ((leweOko + praweOko) <= prog)  // jeżeli jest bardzo ciemno
  {
    digitalWrite(niebieska, HIGH);   // sygnalizujemy to i program czeka aż będzie jaśniej
  }
  else                              // mamy dość światła do działania
  {  
    Serial.print("lewe = ");
    Serial.println(leweOko);
    Serial.print("prawe = ");
    Serial.println(praweOko);
    int roznica = leweOko - praweOko;  // ustalenie kierunku
    if (roznica == 0)                  // sygnały są równe
    {
      kierunek = 0;                    // kierunek na wprost
      wielkosc = 0;                    // odchylenie zero                    
    }
    else if (roznica < 0 && roznica < (czulosc/3))  // różnica ujemna ale mniejsza niż 30%
    {
      kierunek = 3;                    // kierunek prawo
      wielkosc = 1;                    // odchylenie małe
    }
    else if (roznica < 0 && roznica > -(czulosc/3))  // różnica ujemna ale większa niż 30%
    {
      kierunek = 3;                    // kierunek prawo
      wielkosc = 2;                    // odchylenie duże
    }
    else if (roznica > 0 && roznica < (czulosc/3))  // różnica dodatnia ale mniejsza niż 30%
    {
      kierunek = 1;                    // kierunek lewo
      wielkosc = 1;                    // odchylenie małe
    }
    else if (roznica > 0 && roznica > -(czulosc/3))  // różnica dodatnia ale większa niż 30%
    {
      kierunek = 1;                    // kierunek lewo
      wielkosc = 2;                    // odchylenie duże
    }
    digitalWrite((2 + kierunek + wielkosc), HIGH);  // zapalenie odpowiedniej diody z zależności od kierunku i odchylenia
    delay(500);
    for( int i = 1; i < 7; i++)        // po kolei
    {
      digitalWrite(i, LOW);            // wygaszamy diody
    }
  }
}

I jak to wygląda?

Link do komentarza
Share on other sites

Niestety, fotorezystory z zestawu mają bardzo duży rozrzut parametrów.

Dziwna sprawa, oba fotorezystory są identyczne. Jakie dokładnie miałeś z nimi problemy?

Nie sprawdzałem dokładnie, linia, po linie. Jednak wygląda dobrze, jeśli działa, to wszystko jest poprawnie. Widać nieszablonowe podejście 🙂

Link do komentarza
Share on other sites

Rozrzut parametrów na poziomie 25%.

W tym samym oświetleniu jeden 1010ohm, a drugi 1280ohm.

Dokładając 5% oporniki z zestawu raczej trudno o prawidłowy pomiar, ale w układzie docelowym można wprowadzić regulowany dzielnik do ich korekcji.

Można trochę więcej o tym "nieszablonowym" podejściu.

Link do komentarza
Share on other sites

Rozrzut parametrów na poziomie 25%.

W tym samym oświetleniu jeden 1010ohm, a drugi 1280ohm.

Sam pomiar napięcia (rezystancji) będzie obaczony jeszcze zawsze innymi błędami. Wejścia ADC są bardzo wrażliwe, więc tutaj ważna będzie nawet długość przewodów oraz sposób ich prowadzenia. Nawet zbliżanie ręki do takiego wejścia będzie powodowało już spore zniekształcenia w odczytach. Zawsze można też zastosować różne wartości w funkcji mapującej map() dla każdego z czujników lub sprawdzić jaka jest między nimi różnica i później wprowadzać korektę do pomiarów.

Link do komentarza
Share on other sites

Witam, mam mały problem z zadaniem 4.5 a mianowicie z fragmentem kiedy mam podać liczbę. W poprzedniej części kursu było wyjaśnione jak wprowadzać tekst (String), niestety nie mam pojęcia jak przerobić ten kod aby zamiast tekstu wyświetlał cyfrę (int). Wklejam fragment kodu (zamiast String wpisywałem int lecz wyświetlało błąd). Proszę o pomoc

String odebraneDane ="";

if(Serial.available() > 0) {

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

}

Link do komentarza
Share on other sites

@eksio,też to zauważyłem dlatego proszę o pomoc aby ktoś mi wytłumaczył jak wsadzić ciąg liczb do zmiennej int. W kursie nie mogłem tego znaleźć. Próbowałem zmienić komendę na readIntUntil i różnego rodzaju "eksperymenty" ale bez efektów

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.