Skocz do zawartości

Kurs Arduino - #4 - Przetwornik ADC


Pomocna odpowiedź

@Benji_Tomek każdy element reaguje inaczej, rozbieżność w produkcji (tolerancja). Fotorezystor działa z rezystorem w układzie dzielnika który też ma swoją tolerancję (5%). Jedyna możliwość to kalibracja, czyli przy pomocy wzorca dobranie wartości poprawki w programie - zwykła funkcja liniowa załatwi sprawę ale... pojawiają sięczynniki zewnętrze jak np temperatura która ma pływ na rezystancję 😞 więc nie uzyskasz 2 identycznych wyników, ale możesz zmniejszyć błąd.

Link to post
Share on other sites

@Gieneq jak najbardziej sie z Toba zgadzam. Nie chodzi mi o dokładnie ten sam wynik, bo tak sie nie da, i tak jak piszesz, toleracja i inne warunki które wpływają na wartość mierzoną. Zmierzyłem miernikiem ich rezystancje,

1 - 0,6kOhm,

2 - 1,12kOhm (światło dzienne, rozrzut poza tolerancją, dużo więcej nic 5%),

więc wnioskuję, że mam 2 różne fotorezystory, znaczy o 2 zakresach pomiarowych. Jak patrze w ich oczka "tak to nazwę" , to wygladają inaczej. 

image.thumb.png.b0204ac2bccb71ff6b0f65f0c1ac2c13.png

Link to post
Share on other sites

@Benji_Tomek ciekawa sprawa, ale to dalej mały rozrzut. W botlandzie dostępne są 4 warianty fotorezystorów opisanych przez rezystancję jasną - przy oświetleniu 10 luxami

  • 5-10k,
  • 10-20k,
  • 20-30k,
  • 50-100k.

Spróbuj zmierzyć rezystancję każdego z nich wyciągniętego z płytki, w podobnej pozycji tak by załapał się na jeden z minimalnych progów rezystancji i wtedy porównaj. Rezystor powinien mieć rezystancję jasną od 20 do 30 k czyli jeżeli trafisz na egzemplarze które mają rozrzut poniżej 10k to jest OK 🙂 

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

@Benji_Tomek faktycznie różnica jest całkiem spora, ale raczej po prostu trafiłeś na takie same elementy, które faktycznie mają spory rozrzut wartości. Między innymi właśnie dlatego podczas korzystania z czujników analogowych bardzo często trzeba dokonywać kalibracji, aby mieć większą pewność co do ich odczytów.

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

(edytowany)

Hej,

Zrobiłem zadanie 4.6 w następujący sposób:

#define leftR A4
#define rightR A5 //zdefiniowanie czujników

#define greenL 3
#define yellowL 4 
#define red 5
#define yellowR 6
#define greenR 7 // zdefiniowanie diod

int readingL = 0; //odczyty lewego fotorezystora
int readingR = 0; // odczyt z prawego fotorezystora
int diff = 0; // różnica odczytów


void setup() {
  Serial.begin(9600);
  
  pinMode(greenL, OUTPUT);
  pinMode(yellowL, OUTPUT);
  pinMode(red, OUTPUT);
  pinMode(yellowR, OUTPUT);
  pinMode(greenR, OUTPUT); // ustawienie diod
  
  
  digitalWrite(greenL, LOW);
  digitalWrite(yellowL, LOW);
  digitalWrite(red, LOW);
  digitalWrite(yellowR, LOW);
  digitalWrite(greenR, LOW); // ustawienie domyślnego trybu diod

}

void loop() {
  readingL = analogRead(leftR);
  readingR = analogRead(rightR); // przypisanie odczytów
  delay(300); // opóźnienie zwiększające płynność.
  diff = readingL - readingR; // przypisanie różnicy
  Serial.println(diff); //wyświetlenie różnicy

  if (diff > 100 && diff < 300){ // jeżeli różnica jest z zakresu 100 - 300 zaświeca się lewa żółta
    digitalWrite(greenL, LOW);
    digitalWrite(yellowL, HIGH);
    digitalWrite(red, LOW);
    digitalWrite(yellowR, LOW);
    digitalWrite(greenR, LOW);
    delay(50);
  }
  if (diff > 301) { // jeżeli różnica jest ponad 301 zaświeca się lewa zielona
    digitalWrite(greenL, HIGH);
    digitalWrite(yellowL, LOW);
    digitalWrite(red, LOW);
    digitalWrite(yellowR, LOW);
    digitalWrite(greenR, LOW);
    delay(50);
  }
  if (diff < -100 && diff > -500){ // jeżeli różnica jest pomiędzy -100 - -500 zaświeca się dioda prawa żółta
    digitalWrite(greenL, LOW);
    digitalWrite(yellowL, LOW);
    digitalWrite(red, LOW);
    digitalWrite(yellowR, HIGH);
    digitalWrite(greenR, LOW);
    delay(50);
  }
  if (diff < -501){ // jeżeli różnica jest mniejsza od -501 zaświeca się dioda prawa zielona
    digitalWrite(greenL, LOW);
    digitalWrite(yellowL, LOW);
    digitalWrite(red, LOW);
    digitalWrite(yellowR, LOW);
    digitalWrite(greenR, HIGH);
    delay(50);
  }
  else  { // zaświeca się dioda czerwona
    digitalWrite(greenL, LOW);
    digitalWrite(yellowL, LOW);
    digitalWrite(red, HIGH);
    digitalWrite(yellowR, LOW);
    digitalWrite(greenR, LOW);
    delay(50);
  }
  
}

Jednak przy zmianie położenia źródła światła, diody zaczynają mrugać na zmianę z czerwoną (warunek else) nawet wtedy kiedy spełniane są wyłącznie warunki z pozostałych diod.

 

Przy modyfikacji else na if w taki sposób:

  if (diff < 99 && diff > -99) { // jeżli różnica jest pomiędzy 99 a -99 zaświeca się dioda czerwona
    digitalWrite(greenL, LOW);
    digitalWrite(yellowL, LOW);
    digitalWrite(red, HIGH);
    digitalWrite(yellowR, LOW);
    digitalWrite(greenR, LOW);
    delay(50);
  }

Wszystko zdaje się działać poprawnie. Nie rozumiem jednak czemu przy else zachowanie jest tak dziwne, skoro przy wyżej wypisanym IFie wsadziłem pozostałe warunki czyli de facto to samo co powinno się wykonywać przy "else"

Edytowano przez Opinel
literówka
  • Lubię! 1
Link to post
Share on other sites

@Opinel możliwe że nie masz konstrukcji else if i wtedy tylko ostatni if ma wpływ na końcowy else.

Fajnie że kod działa, ale możesz spróbować potraktować zadanie inaczej, bez infów 😉 zadanie z 2 gwiazdkami, ale możesz popróbować 🙂 

  • Pomogłeś! 1
Link to post
Share on other sites

Cześć!

Prośba o konsultację do zadania 4.4.

Rodziło się w bólach, ale widzę, że ktoś już walczył z funkcją while. Wydaje mi się, że mój kod działa i chyba nawet robi co trzeba 😅, ale pewnie można by to zrobić lepiej. Poniżej kod:

int odczytanaWartosc = 0; //zmienna do przechowywania odczytu ADC
int prog = 0; //próg włączenie światła ustawiany potencjometrem
float napiecie=0; //wartość przeliczona na napięcie w V

void setup() {
  pinMode(8, OUTPUT); //konfirguracja wyjść pod diodę LED
  Serial.begin(9600); //uruchomienie komunikacji USART
}

void loop() {
  odczytanaWartosc = analogRead(A5); //odczytanie wartości z ADC
  prog = analogRead(A4);

  if (odczytanaWartosc < prog) {    
    napiecie = odczytanaWartosc * (5.0/1024.0); //przeliczenie wartości na napięcie
    Serial.println(napiecie); // wyświetlenie napięcia z dzielnika
    digitalWrite(8, HIGH); //włączenie diody      
    while (odczytanaWartosc < prog) {
    odczytanaWartosc = analogRead(A5); //odczytanie wartości z ADC
    }

  } else {
    digitalWrite(8, LOW); //wyłączenie diody
  }

  delay(50);
}

Musiałem wstawić "odświeżanie" odczytanej wartości do środka funkcji while inaczej dioda zaczynała świecić po spełnieniu warunku i już nie chciała przestać. Intuicja mi podpowiada, że while to nie jest zbyt finezyjne rozwiązanie (takie zawieszanie programu). A także, że użycie tej funkcji w poważniejszym zastosowaniu raczej byłoby bez sensu. Pytanie czy działa "wystarczająco dobrze" na tym etapie edukacji i czy ewentualnie można coś poprawić.

Być może ktoś już wpadł na podobne rozwiązanie i gdzieś tu jest na forum, ale czytanie cudzych kodów w takiej ilości na razie zawiesza mi system. Więc jak robię powtórkę to przepraszam!

Pozdrawiam i czekam na uwagi!

Link to post
Share on other sites

@crus7pl zauważ że zdarzenie ma się pojawić raz - sterujesz diodą co każdy obrót pętli, a tu musisz wykryć pewne zdarzenie podobne do obśługi przycisku. Sprawdź ten wpis, tylko że zamiast przycisku trzymasz poprzednią wartość zmiennej:

 

Link to post
Share on other sites

@Gieneq  Dzięki za odpowiedź! Postaram się wieczorem przestudiować podlinkowany wpis. Natomiast jeśli dobrze zrozumiałem polecenie z zadania po każdym włączeniu diody arduino ma wysłać tylko raz do komputera napięcie jakie pojawiło się na dzielniku. Wydawało mi się, że ten kod to robi. Chyba, że problem leży w tym, że zatrzymuję całość "programu". Ale to nie było zabronione. 😉  Jeśli dobrze rozumiem to co napisałem, to jeśli warunek jest odpowiedni do włączenia diody to dioda zostaje włączona, napięcie jest wysłane na komputer i zawieszamy się w pętli while. Jej warunek jest tożsamy z warunkiem funkcji if, czyli dopóki warunek świecenia diody jest spełniony to utknęliśmy w while. Jeśli warunek nie jest spełniony wypadamy do else, dioda gaśnie i znowu całość rusza w pętli dopóki warunek do włączenia diody nie zostanie spełniony. Ewentualnie w while mógłbym jeszcze odświeżać próg włączenia diody, inaczej przy zmianie/regulowaniu progu przy włączonej diodzie mogę się z pętli while nie wydostać. Czy jeszcze bardziej nie rozumiem, niż mi się wydaje, że nie rozumiem?

Tak czy inaczej przejrzę podesłany wpis, spróbuję go zrozumieć (bo to dopiero 4 lekcja) i zastosować.

Pozdrawiam

Link to post
Share on other sites
Dnia 15.01.2021 o 07:52, Gieneq napisał:

@Opinel możliwe że nie masz konstrukcji else if i wtedy tylko ostatni if ma wpływ na końcowy else.

Fajnie że kod działa, ale możesz spróbować potraktować zadanie inaczej, bez infów 😉 zadanie z 2 gwiazdkami, ale możesz popróbować 🙂 

Faktycznie. Dałem konstrukcje if -> else if -> else i teraz działa. Zaczynam rozumieć też dlaczego tak się dzieje. Dzięki!

 

Próbowałem jeszcze bez Ifów. Zastąpiłem je while, ale wtedy odczyt z potencjometrów zaczytuje się tylko raz, po czym uruchamia się odpowiedni zakres while i wszystko stoi 😕

Link to post
Share on other sites

@Gieneq  czy o to chodziło? Czy coś namieszałem?

#define czujnik_swiatla A5
#define czujnik_progu A4
#define dioda_led 8

int odczytana_wartosc = 0;
int prog = 0;
float napiecie=0;
boolean ostatni_komunikat = false;
boolean wyslany_komunikat = false;

void setup() {
  // put your setup code here, to run once:
  pinMode (dioda_led, OUTPUT);
  Serial.begin (9600);

}

void loop() {
  // put your main code here, to run repeatedly:
  odczytana_wartosc = analogRead(czujnik_swiatla);
  prog = analogRead(czujnik_progu);
  napiecie = odczytana_wartosc * (5.0/1024.0);

  if (odczytana_wartosc<prog) {
    digitalWrite (dioda_led, HIGH);
    wyslany_komunikat = true;
  }

  else {
    digitalWrite (dioda_led, LOW);
    wyslany_komunikat = false;
   }

  if (wyslany_komunikat == true && ostatni_komunikat == false) {
    Serial.println (napiecie);
    delay(1000);
    }
  ostatni_komunikat = wyslany_komunikat;
}

Pozdrawiam

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

@crus7pl tak, teraz wygląda lepiej 🙂 

Możesz jeszcze w podobny sposób sterować LEDem - ustawić podczas detekcji zmiany stanu. Ciągła próba wpisania wartości LED nic nie psuje ale praktyczniej byłoby wpisywanie wartości tylko gdy coś się zmienia. Dobrze jest, ale możesz jeszcze rozwinąć to zadanie w ramach nauki 😉 

Link to post
Share on other sites

@Gieneq Dzięki! Podejmuję rękawicę, ale muszę dopytać w takim razie. 😂 Czy uważasz, że zmianę stanu diody na HIGH wystarczy przerzucić do funkcji wysyłającej komunikat? Czy lepiej zrobić to oddzielną funkcją, gdybym w przyszłości chciał rozwodu tych dwóch funkcjonalności w tej jakże wypasionej lampce?

Pytanie dodatkowe(zapewne z tych głupich), ale nigdzie nie rzuciła mi się w oczy odpowiedź. W omawianym nawet wcześniej kodzie ustawiłem pin diody jako wyjście i ustawiam sobie na nim stan wedle potrzeby. Pytanie czy to rozsądne/bezpieczne/możliwe napisać funkcję weryfikującą stan wyjścia, np.:

if (dioda_led = HIGH) { }

Czy mogę zapytać o stan wyjścia w ten sposób? Czy to jakaś herezja, wejść wyjściem lub wyjść wejściem?😅

Link to post
Share on other sites
56 minut temu, crus7pl napisał:

Czy uważasz, że zmianę stanu diody na HIGH wystarczy przerzucić do funkcji wysyłającej komunikat?

Tak, możesz tak zrobić.

Dorób drugą funkcję która wykrywa zdarzenie przeciwne go tego co już masz, zmiana stanu w drugą stronę i tam gaś diodę.

Jedynie pozostanie warunek na porównywanie z progiem.

57 minut temu, crus7pl napisał:

Czy mogę zapytać o stan wyjścia w ten sposób? Czy to jakaś herezja, wejść wyjściem lub wyjść wejściem?

Niestety to może nie herezja, ale to nie zadziała. Jak chcesz uzyskać wartość to robisz:

bool wynik = dioda_led == HIGH;

== oznacza przyrównanie, więc powyższe to odpowiedź na pytanie czy dioda_led jest HIGH? Więc jeżeli ma to być w warunku to robisz tak:

if (dioda_led == HIGH) { }

albo prościej:

if (dioda_led) { }

jak będzie HIGH (czyli 1) to warunek będzie spełniony.

  • Pomogłeś! 1
Link to post
Share on other sites

@Gieneq  Dzięki za dotychczasową pomoc! Wprowadziłem zmiany. Wydaje mi się, że zgodnie z sugestiami i że program robi swoje. 😅 Jeśli nie będzie dodatkowych zastrzeżeń do kodu biorę się za kolejną pracę domową...

#define czujnik_swiatla A5
#define czujnik_progu A4
#define dioda_led 8

int odczytana_wartosc = 0;
int prog = 0;
float napiecie=0;
boolean ostatni_komunikat = false;
boolean wyslany_komunikat = false;

void setup() {
  // put your setup code here, to run once:
  pinMode (dioda_led, OUTPUT);
  Serial.begin (9600);

}

void loop() {
  // put your main code here, to run repeatedly:
  odczytana_wartosc = analogRead(czujnik_swiatla);
  prog = analogRead(czujnik_progu);
  napiecie = odczytana_wartosc * (5.0/1024.0);

  if (odczytana_wartosc<prog) {
    wyslany_komunikat = true;
  }

  else {
    wyslany_komunikat = false;
   }

  if (wyslany_komunikat == true && ostatni_komunikat == false) {
    Serial.println (napiecie);
    digitalWrite (dioda_led, HIGH);
    delay(100);
    }

  if (wyslany_komunikat == false && ostatni_komunikat == true) {
    digitalWrite (dioda_led, LOW);
    delay(100);
    }
    
  ostatni_komunikat = wyslany_komunikat;
}

Pozdrawiam!

  • Lubię! 1
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...

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.