Podstawy: dzielnik napięć, PWM, fotorezystor = inteligentne oświetlenie

Podstawy: dzielnik napięć

Obrazki z tablicy… 

Najpierw bawiliśmy się multimetrem i dzielnikiem:

fibot2016-11-22-note-19-36-1

a potem podłączyliśmy fotorezystor i próbowaliśmy go odczytywać z poziomu Arduino.

Pomysł Pana Pawła (PPP) aby najpierw zmierzyć multimetrem prąd płynący w obwodzie, a następnie znając podane napięcie i stosując prawo Ohma otrzymywać wartość rezystancji na fotooporniku – był dobry, ale wymagał ówczesnego użycia amperomierza (z multimetru). Mi bardziej chodziło o wykorzystanie fotorezystora w ten sposób, aby uzyskać informację czy go zasłaniamy czy nie, czy jest dużo światła zastanego (w pomieszczeniu) czy jest ciemno. Dlatego nie koniecznie interesuje mnie sama wartość oporu, a raczej jej zmiany. Dlatego po sprawdzeniu działania PPP i przyznaniu mu racji (a raczej Ohmowi), zaproponowałem zastosowanie dzielnika napięć i mierzenia napięcia w standardowy spodówb

fibot2016-11-22-note-19-36-2

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

void loop(){
  Serial.println(analogRead(A0));  
  delay(100);
}

W zależności od kolejności oporników (stałego R i zmiennego fotorezystora) otrzymywaliśmy liczby rosnące lub malejące zasłaniając fotorezystor ręką. Dodatkowo można było użyć latarki z telefonu komórkowego i symulować mocne oświetlenie.

PWM

Aby zrobić inteligentne oświetlenie potrzebowaliśmy sposobu na kontrolowanie jasności LED-a. Poznaliśmy Pulse Width Modulation i piny cyfrowe Arduino z „falką” (wolę: tyldą).

fibot2016-11-22-note-19-36-3

Inteligentne oświetlenie

To nic innego jak połączenie dwóch poznanych schematów:

  • mierzymy napięcie na fotorezystora przez wejście analogowe, a następnie
  • ustawiamy jasność LED-a sterując wypełnieniem PWM.

Jedyny problem to kwestia zamiany odczytywanych wartości z portu A0 (fotorezystora) na wartości akceptowane przez piny PWM (przypominam: 0..255). W tym celu wróciliśmy do gimnazjum i zastosowaliśmy funkcję liniową.

Dla przykładu: Pani Emanuela zastosowała stały opornik R o takiej wartości, że na porcie A0 odczytywała wartości 130 gdy fotorezystor był zasłonięty palcem, oraz 500 gdy był oświetlany światłem zastanym. Wartości pomiędzy przedziałem 130..500 odpowiadały częściowemu zasłonięciu ręką fotorezystora. Trzeba to teraz zamienić na liczby 0..255 aby sterować LED-em przez PWM (bo PWM akceptuje właśnie takie liczby, a nie 130..500). Dlatego stosujemy liniowe skalowanie (y=ax+b, współczynniki ab na razie nie znane), gdzie wartość 130 ma odpowiadać maksymalnemu świeceniu LED-a, czyli 100% wypełnieniu PWM-a (wartość 255), natomiast gdy odczytujemy 500 (jest jasno) to LED ma się nie świecić (wypełnienie 0). Trzeba skonstruować układ równań i wyznaczyć a oraz b a następnie przeliczać wskazania z portu A0 (traktując je jako x w równaniu prostej, a otrzymany y to właśnie wartość przekazana do PWM-a). Poniższy rysunek wyjaśniał ten opis:

fibot2016-11-22-note-19-36-4

Z kolei Pan Paweł użył innego rezystora (oraz innej kolejności ustawienia oporników) i miał następujący schemat do rozważenia 

fibot2016-11-22-note-19-36-5

W obu przypadkach trzeba było rozwiązać otrzymany układ równań na kartce a następnie wpisać liczby (wyliczone współczynniki a b) to takiego prostego programiku:

#define lampka 9
float a=0.689189, b = 344.595;

void setup(){
  Serial.begin(9600);
  pinMode(lampka, OUTPUT);
}

void loop(){
  int fotorezystor = analogRead(A0);  
  Serial.print("fotorezystor=");
  Serial.print(fotorezystor);  
  Serial.print("-->");  
  int pwm = a*fotorezystor+b:
  Serial.print(" PWM=");  
  Serial.println(pwm);
  analogWrite(lampka, pwm);  
  delay(100);  
}

Wrócimy do tego programu na kolejnym spotkaniu, bo trzeba tu o paru kwestiach wspomnieć. Ale już teraz zachęcam do zabawy z powyższym programikiem na wirtualnym Arduino (jest tam też wirtualny fotorezystor). Proszę też zastanowić się nad następującymi kwestiami:

  • dlaczego Pan Paweł miał prostą o współczynniki kierunkowym a>0, a Pani Ema a<0 ?
  • kto zastosował lepszą wartość opornika stałego – Pani Ema czy Pan Paweł, a może to nieistotne? 

Zapraszam za tydzień!

 

Podstawy – wejście analogowe + potencjometr

Podstawy – komunikacja szeregowa i obiekt Serial.

Z racji sporej liczby nowych ludzi (nie tylko studentów), głodnych wiedzy i żądnych przygód (zdjęć nie publikuję – tak, jak się umawialiśmy) rozpoczęliśmy od przypomnienia podstaw… Na warsztat trafiło pojęcie zmiennej. Aby to pojęcie „namacalnie” zobrazować przygotowałem programik, w którym poziom życia bohatera (np. Wiedźmina) reprezentowane przez zmienną energia ciągle malał (np. bohater ranny = krwawi). Aktualna wartość życia był wypisywany na ekranie monitora (via obiekt Serial i metoda print/println).

byte energia=77;

void setup(){
  Serial.begin(9600);
  energia=17;
}

void loop(){
  Serial.print("Energia= ");  
  Serial.println(energia);  
  delay(1000);
  energia= energia-1;  
}

Powyższy programik posłużył także do omówienia pojęć bit i bajt oraz wielkości informacji, jaką można zapisać wiadomości za pomocą n-bitów. Zapiski z tablicy w trakcie zajęć (pokolorowałem już po zajęciach):
fibot2016-11-15-note-19-03-1

gdzie przypominam, ze RAM na moim super-obrazku przedstawia całą pamięć operacyjną płytki Arduino UNO (dlatego komórki pamięci – bajty – są ponumerowane od 1..2048, bo UNO ma 2kB pamięci), gdzie mikrokontroler przechowuje właśnie zmienne. W szczególności w naszym programie zaznaczyłem miejsce w pamięci, gdzie zadeklarowaliśmy zmienną energia. Na tym rysunku (modyfikowanym w trakcie zajęć – pamiętacie?) zmienna ta zajmuje 2 komórki (bajty) i odpowiada to już sytuacji innej niż z pierwszego listingu programu: mianowicie int energia=77; Zmienna typu int to 16 bitów, czyli 2^16 różnych informacji (kolor zielony na pokolorwanej tablicy, natomiast kolor żółty – to bity). Pierwotnie była to zmienna byte, czyli 8 bitów i 256 dopuszczalnych wartości (kolor niebieski). Ta pierwsza wersja programu była bardzo treściwa, gdyż pokazywała sytuację co się dzieje z wartością zmiennej, gdy przekraczamy jej dopuszczalny zakres: w naszym przypadku zmniejszaliśmy wartość zmiennej energia co 1 sekundę (delay(1000)) no i gdy mieliśmy już „na liczniku” 0 (zero) to wcale nie pojawiło się -1 (minus jeden) tylko… 255! a potem juz 254… 253… itd. Warte to jest zapamiętania (no i oczywiście w drugą stronę – gdybyśmy zwiększali naszą zmiennę z wartości 255 o jedne to… wiesz, co będzie? jeśli nie, proponuję sprawdzić!).

Potencjometr nastawny.

potencjometr-osiowy-liniowy-5kNa spotkaniu poznawaliśmy potencjometr nastawny i jego podłączenie/obsługę przez Arduino. Ale najpierw zabawy z bateryjka i multimetrem – ćwiczenia obowiązkowe. Dodatkowo przypomniałem co to jest dzielnik napięć i jak „to się je”, a tym samym (mam nadzieję) zrozumieliśmy działanie potencjometru nastawnego (w naszym przypaku liniowego 10k).potencometr

Powyższy schemat tłumaczy działanie potencjometru… Warty zapamiętania jest też taki rysunek:

który pokazuje co się dzieje gdy mierzymy napięcie, lub raczej (prawidłowo) różnicę napięć (potencjałów). Podłaczamy do pinu nr 1 (kolor czerwony na rysunku, numeracja odnosi się do schematu potencjometru z poprzedniego obrazka) „minus” z bateryjki, a do pinu 3 „plus” z bateryjki (niech to będzie 4x bateria AAA – czyli właśnie 6V). Gdy ustawiemy potencjometr w takiej pozycji, aby zmierzone napięcie na pinie nr 2 wynosiło 4V to w zależności od tego, jak mierzymy (=jak podłączamy sondy multimetru) możemy otrzymać też wynik 2V. Chodzi oczywiście o poziom odniesienia (sonda czerwona jest cały czas w „środkowej nóżce”, czyli pinie nr 2, natomiast sonda czarna – poziom odniesienia właśnie – może być w pinie 1 lub 3). Jeśli naszym poziomem będzie GND (=0V, pin 1) to faktycznie otrzymamy 4V, ale gdy mierzymy napięcie pomiędzy „szczytem góry” a naszą pozycją (sonda czarna „na szczycie”, czyli pinie 3) to oczywiście otrzymamy 2V. Wszystko jasne?

Po zabawach z multimetrem (i LED-em podłączonym do potencjometru) przyszedł czas na podłączenie do Arduino i wpisanie nowego kodu programu:

#define IN A0

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

void loop(){
  int war = analogRead(IN);  
  Serial.print(war);  
  Serial.print("-->");  
  Serial.print(war*5.0/1024);  
  Serial.println("V");  
  delay(100);  
}

Ten program (dla odróżnienia się od poprzedniego) wprowadza etykiety nazw (za pomocą dyrektywy preprocesora #define) i nie posługuje się zmienną w tym celu. Zmienna pojawia się dopiero w funkcji loop(). Przypominam, że „zysk” ze stosowania etykiet nazw jest taki, że nie zajmują one pamięci RAM komputera… (ale są i minusy).

„Danie główne” dzisiejszego spotkania to piny analogowe Arduino, i aby je zrozumieć posłużyłem się takim rysuneczkiem:

fibot2016-11-15-note-19-03-3

gdzie pokazuję jakiś przebieg napięcia w czasie (krzywa czarna na wykresie V(t), minimalne napięcie 0, zaznaczone jest też poziom 5V), który teraz możemy odczytywać z rozdzielczością 7-miu poziomów (od 0..6). Mamy więc odczyty jako napięcia jako liczby całkowite 0,1,2,..,6 które odpowiadają napięciom 0V, 0.8333V, 1.666V, …, 5V (przedziały napięcia to właśnie dV=5/6V). Przy takiej rozdzielczości nie ma możliwości odróżnić napięć 0.2V, 0.6V czy 0.8V, gdyż te odczyty trafiają do jednego „worka” (tu: zero). Dopiero poziom 0.84V zmienia wartość mojego odczytu (tu: jedynka).

W przpadku Arduino mamy nie 7 dostępnych poziomów, a 1024 (gdyż jest tam przetwornik analogowo cyfrowy 10-cio bitowy, czyli 2^10=1024). Stąd też i dokładność pomiarów dużo lepsza niż na moim rysuneczku. 

Co najciekawsze, wykonaliśmy kalibrację odczytów z analogowego portu Arduino – posłużyliśmy się multimetrem. Okazało się bowiem, że bez tego często pomiary były baaaardzo nietrafione (tj. dużo się różniły wskazania woltomierza od wskazań Arduino). Przyczyną były doś „spracowane” płytki Arduino…

Bardzo ważna była też informacja o dzieleniu liczb: przypominam, że 5/1024 jest zawsze 0 (zero), natomiast 5.0/1024 już nie.

Zapraszam za tydzień!

 

Encoder do silników DC – pracujemy…

Panu Kamilowi udało się zbudować układ, który w podłączeniu z processingiem produkuje takie obrazki:zad4 zad3 zad2 zad1

Widzimy tu dwie krzywe, ale to właśnie ta biała pochodzi z omawianego encodera. Teraz „trzeba tylko” opracować algorytmiczną metodę zliczania pików w danym okresie czasowym, a następnie przełożyć to na faktyczne obroty koła… Prace w toku…

Przy okazji: ta żółta krzywa pochodzi od czujki pola magnetycznego – dzięki niej w późniejszym czasie można będzie przełożyć zliczone piki (białe) na faktycznie wykonane obroty (żółte dwa piki odpowiadają jednemu pełnemu obrotowi).

Plik z przykładowymi danymi – do wstepnej obróbki (gnuplot, arkusz kalkulacyjny Calc…).