Podstawy: Bluetooth + mikroserwa

Podstawy Arduino

Tym razem poznajemy coś konkretnego – moduł Bluetooth XM-15B. Umożliwi on komunikację z naszym smartfonem i sterowanie wieżtyczką (zbudowaną z 2 mikroserw, jak na poprzednich zajęciach).

Komunikacja z Bluetoothem z wykorzystaniem SoftwareSerial-a.

Poznaliśmy obiekt SoftwareSerial pomocny w komunikacji z dwoma urządzeniami działającymi przez UART, a (niestety) Arduino UNO ma tylko jeden Serial… Wykorzystaliśmy darmową apkę z AndroidStore „Bluetooth control 8 lap” która sterowała wieżyczką. Brawo Studenci!

Wieżyczka z 2x mikroserwo sterowana przez Bluetooth.

Ta apka jest dobra na początek, można poszukać czegoś lepszego w sklepie ale… dlaczego nie stworzyć własnej? To naprawdę proste – z odpowiednim środowiskiem, czyli (polecam) MIT App Inventor

MIT App Inventor – tworzenie pod Androida z bloczków/klocku jak w Scrachu!

Maskotka

Prace trwają: BB poprawia łącza i soft, KG wierci i kręci 😛 A co z tego wyszło? Skrzypi, ale jeździ jak wariat 😀

Podstawy: odczytywanie sygnałów (analogowo i cyfrowo)

Podstawy Arduino

Dalej ćwiczymy funckję analogRead() – tym razem z fajnym modułem, mianowicie czujnikiem pola magnetycznego SS49E. Podłączamy zasilanie a sygnał wychodzi z 3-ciej nóżki, jak na rysunku poniżej:

Czujka i opis nóżek (PIN-outy).

Warte podkreślenia jest, że ta czujka odróżnia dwa bieguny magnesów i dlatego jest warta zakupu. Przy tej okazji przekonaliśmy, że Arduino IDE wyposażone jest w automatyczne rysowanie wykresów dzięki Kreślarce – trzeba tylko wysyłać na port szeregowy liczby w postaci napisów (gdy chcemy dwie krzywe na wykresie – liczby muszą być podane w jednej linii, oddzielnone spacjami). Proste, a jakie użyteczne!

Skoro mamy przećwiczone analogRead() to powracamy do mniej widowiskowego digitalRead(): podłączamy moduł przycisku

Moduł przycisku tact-switch.

W kolejnym kroku podłączyliśmy moduł czujnika drgań:

Moduł czujnika drgań.

Ponownie wykorzystaliśmy Kreślarkę by rysować drgania czujnika, razem z wykresem pola magnetycznego – proste, ale cieszy 😉

Maskotka

Prace trwają: BB z PP rozkładają pojazd, programują i… stwierdzają zgon jednego z dwóch Arduino! Przyczyna? no właśnie… dochodzenie trwa…

podstawy: Serial + wyswietlacz 7(8?) segmentowy

Podstawy Arduino

Obiekt Serial i funkcja wypisująca na ekranie napisy, wartości zmiennych. Ale nie tylko – wczytywanie danych z PC do Arduino. To już prawdziwa rozmowa! Nowi Studenci bardzo pracowici – ich programy wyświetlają już wszystkie cyfry!

Maskotka

Prace nad ulepszeniem napędu trwają (BB).

Komunikacja z naszym Arduino – monitor szeregowy oraz funkcje.

Kolejne zajęcia Fibotu za nami!

Tym razem poruszyliśmy tematy, które pozwoliły nam poznać nieco bardziej techniki komunikacji użytkownik – komputer – kontroler.

Po utworzeniu znanego z początkowych zajęć układu równolegle podłączonych i adresowanych LEDów chcieliśmy móc nimi sterować ręcznie, a nie jedynie z pomocą gotowych algorytmów w pętli.

LEDy połączone płytką stykową

By spróbować czegoś zaawansowanego wróciliśmy do podstaw – każdy uczestnik stworzył znany już układ pięciu LEDów z czego każdy był podłączony do innego pinu cyfrowego w płytce Arduino. Ten układ pozwala niezależnie kontrolować każdą diodę.

#define MAX 5
int piny[5]={2,3,4,5,6}; // Tablica z numerami wyjść cyfrowych do których podłączone zostały diody

void setup(){
  for(i=0;i<MAX;i++) // pętla pozwalająca zdefiniować wyjście każdego z pinów cyfrowych
  pinMode(piny[i],OUTPUT);

}

Monitor szeregowy i komunikacja

Wzbogaciliśmy nasz program o funkcje pozwalające na komunikację przez port szeregowy, a następnie dodaliśmy możliwość wysyłania komend, które będą zapalać i gasić nasze diody.

Sterownik również na bieżąco informuje nas o tym, czy wczytał nasz input – wyświetlał wszystkie znaki które wprowadzimy do monitora szeregowego. By mieć możliwość wczytania więcej niż znaku (char – 1 bajt) zastosowaliśmy funkcję parseInt() pozwalającą na wczytanie ciągu znaków, który zostanie zamienony na liczbę całkowitą. Zmienna „ile” była wprowadzana przez użytkownika i definiowała ile razy lampki mają zamrugać.

#define MAX 5 // liczba diod
int piny[MAX]={2,3,4,5,6};
int i,j;
//char znak;
byte znak;

void setup(){
  for(i=0;i<MAX;i++)
     pinMode(piny[i],OUTPUT);
  Serial.begin(9600);
}
void loop(){
  if(Serial.available()>0){
    int ile=Serial.parseInt();
    Serial.print("Wczytalam ");
    Serial.println(ile);
    mig(ile);
  }

Warto zwrócić uwagę na linijkę trzynastą Serial.available() zwraca liczbę bajtów czekających na odczytanie (a aktualnie przechowywanych w buforze portu szeregowego), gdy zostanie wprowadzona przez użytkownika jakaś dana wejściowa. Czytając jeden bajt (np. Serial.read()) zabieramy z tego bufora jeden bajt a tym samym zmniejszamy licznik danych (bajtów) czekających na odczytanie.

Adnotacja: podczas zajęć modyfikowaliśmy nasz program na bieżąco. W kodzie możecie znaleźć 'przestarzałe’ metody które wprowadziliśmy w ramach zapoznania się z ideologią zadania. Najczęściej będą one zakomentowane w pełnym kodzie, który znajdziecie na samym dole tego wpisu. Warto zwrócić uwagę, że przy wczytywaniu zmiennej char będącej jednym znakiem musimy stosować tłumaczenie na tablicę ASCII, gdyż właśnie w tym formacie zapisane są zmienne char.

Funkcje: szkoda życia na robienie w kółko tego samego !

Stworzywszy program pozwalający na dwukierunkową komunikację z naszym sterownikiem utworzyliśmy funkcję o wdzięcznej nazwie „mig()”. Tworzenie takich funkcji jest podstawą programowania strukturalnego – chodzi o „zamykanie” logicznych części programu (tu: włączanie/wyłączanie wszystkich LEDów) w pewną całość, którą następnie będziemy wielokrotnie używać.

Funkcja „mig()” przechodziła kolejne stadia swojego rozwoju, od najprostrzej – bezargumentowej:

void mig(){
  Serial.println("ON");
  for(i=0;i<MAX;i++)
     digitalWrite(piny[i],HIGH);
   delay(400);
   Serial.println("OFF");
   for(i=0;i<MAX;i++)
      digitalWrite(piny[i],LOW);
   delay(400);
}//mig

Zadaniem powyższej jest jednokrotne włączenie/wyłączenie wszystkich LED-ów. Aby zrobić to kilkukrotnie należy wielokrotnie wykonać stworzoną funkcję mig() – lub wykonać ją w pętli n-razy. Dlatego kolejna modyfikacja polegała na dodaniu argumentu do funkcji:

void mig(int ile){
  for (int jj=0;jj<ile;jj++){
    Serial.println("ON");
    for(i=0;i<MAX;i++)
      digitalWrite(piny[i],HIGH);
    delay(400);
    Serial.print("OFF x");
    Serial.println(jj+1);
    for(i=0;i<MAX;i++)
      digitalWrite(piny[i],LOW);
    delay(400);
  }//jj
}//mig

jednoargumentową, która umożliwia nam wielokrotne włączenie/wyłączenie LED-ów (dodatkow pętla po zmiennej jj). Mając takią funkcję możemy kazać migać, np. czterokrotnie przez wywołanie mig(4) – wówczas następuję przekazanie liczby 4 dla parametru ile w definicji funkcji mig(int ile). Kolejna modyfikacja polegała na dodaniu dodatkowego, drugiego parametru czas określającego ile ms mają być włączone/wyłączone LED-y.

void mig(int ile, int czas){
  for (int jj=0;jj<ile;jj++){
    Serial.println("ON");
    for(i=0;i<MAX;i++)
      digitalWrite(piny[i],HIGH);
    delay(czas);
    Serial.print("OFF x");
    Serial.println(jj+1);
    for(i=0;i<MAX;i++)
      digitalWrite(piny[i],LOW);
    delay(czas);
  }//jj
}//mig

Ten dodatkowy parametr umożliwia nam szybkie miganie (np. czterorkotne) przez wywołanie mig(4, 100) lub wolne przez wywołanie mig(4,2000). Podobnie jak poprzednio wywołując naszą funkcję przypisujemy wartości 4 do zmiennej ile, oraz 100 (lub 2000 w drugim przykładzie) do zmiennej czas. Ostatnia modyfikacja to parametry domyślne w języku C++ (nie ma tego w „czystym” C), czyli zamiana prototypu funkcji (=nagłówka) na następujący: 

void mig(int ile, int czas=400){
  for (int jj=0;jj<ile;jj++){
    Serial.println("ON");
    for(i=0;i<MAX;i++)
      digitalWrite(piny[i],HIGH);
    delay(czas);
    Serial.print("OFF x");
    Serial.println(jj+1);
    for(i=0;i<MAX;i++)
      digitalWrite(piny[i],LOW);
    delay(czas);
  }//jj
}//mig

Powyższa zmiana umożliwia wywołanie dwuargumentowej funkcji mig(int, int) nie wtylko w postaci mig(4,100) ale także mig(4) – wówczas parametr czas przyjmie domyślną wartość 400.   

Funkcja ta robi dokładnie to, o czym wspomniałem przy zmiennej „ile”. Wartość ukryta pod tą zmienną była kierowana do funkcji. Pętla zapalająca (zaznaczona linijka 2) zapala i gasi (linijki 5 i 10) lampki za pomocą znanej już nam pętli wewnętrznej (zapalającej każdą diodę jedną po drugiej w odstępie czasu rzędu milisekund – linijka 4).

Funkcja miała też dodatkową, opcjonalną zmienną wejściową „czas” regulującą odstępy między zapaleniem i zgaszeniem diod za pomocą wbudowanej funkcji „delay()”.

Podsumowanie:

Na tych zajęciach zamiast poznać nowe elementy elektroniczne jak np. znana z poprzednich zajęć czujka szczelinowa, poznaliśmy niezwykle kluczowe możliwości sterownika Arduino – komunikację dwukierunkową przez monitor szeregowy. Możliwość bezpośredniego wysyłania sterownikowi danych wejściowych pozwala na ręczne sterowanie i otwiera nas na nowe możliwości.

Stworzyliśmy swoją własną funkcję istniejącą poza pętlą główną, co zwiększa przejrzystość kodu i daje wygodę stosowania gotowych funkcji.

To nie koniec przygód z komunikacją za pomocą monitora szeregowego. Możliwości implementacji tak kluczowej metody są niezwykle szerokie.

Do zobaczenia na następnych zajęciach!
Maciej (c) 2017 & KG

 

 

Pełny kod:

#define MAX 5
int piny[5]={2,3,4,5,6};
int i,j;
//char znak;
byte znak;

void setup(){
  for(i=0;i<MAX;i++)
  pinMode(piny[i],OUTPUT);
  Serial.begin(9600);
}

void mig(int ile, int czas=400){
  for (int jj=0;jj<ile;jj++){
  Serial.println("ON");
  for(i=0;i<MAX;i++)
    digitalWrite(piny[i],HIGH);
    delay(czas);
   Serial.print("OFF x");
   Serial.println(jj+1);
   for(i=0;i<MAX;i++)
    digitalWrite(piny[i],LOW);
    delay(czas);
  }//jj
}//mig

void loop(){
  if(Serial.available()>0){
    int ile=Serial.parseInt();
    //znak=Serial.read(); //przechowuje 1 bajt
    Serial.print("Wczytalam ");
    Serial.println(ile);
 //   mig(znak-48); //0 w tabeli ASCII to 48
   mig(ile);
 //   if (znak=='3')mig(3);
 //  if (znak=='5')mig(5,500);
    }
    
    

 

Przycisk (modeuł) + ekran

Dziś poznalismy trzy rzeczy: wypisywanie komunikatów przez Arduino na ekran PC-ta, funkcję „zegara” millis() oraz obsługę przycisku (a właściwie modułu z przyciskiem, niedługo poznamy różnice).

Komunickacja z PC-tem

Chodzi o komunikację szeregową UART z wykorzystaniem dwóch pinów cyfrowych Rx/Tx (piny numer zero i jeden). Uruchamiamy komunikację poleceniem Serial.begin(szybkość). W tym momencie tracimy dwa wspomniane piny(zero i jeden) – no cóż, coś za coś. Parametr szybkość musi być na obu urządzeniach taki sam, w przeciwnym przypadku urządzenia się „nie dogadają”. W środowisku Arduino IDE wybieramy Monitor szeregowy (lub w angielskiej wersji: Serial Monitor) i nasłuchujemy to, co nadaje do nas Arduino – to jest właśnie drugie urządzenie, do którego Arduino nadaje (prawy, górny róg okienka z kodem programu)

Jak wspomniałem należy sprawdzić, czy w okienku Monitora (portu) szeregowego parametry tramisji (szybkość) jest taka sama, jak w programie Arduino – prawy, dolny róg tego okienka.

W przyszłości opowiem więcej o tych parametrach transmisji oraz jak wysyłać dane do Arduino – ale to później.

Trzeba zapamiętać dwie funkcje wysyłające napisy z Arduino:

  • Serial.print(„napis”) — wysyłamy tekst napis do urządzenia nasłuchującego; tekst musi być w cudzymsłowiu (aka. psie uszy)
  • Serial.println(„napis”) — wysyłamy napis i znak przejścia do nowej linii – dzięki temu kolejny napis pojawi się w nowej linii.

Te dwie funkcje w zupełności wystarczają, aby Arduino coś do nas „mówiło” 😉

millis()

Bardzo przydatna funkcja zwracająca liczbę milisekund od czasu rucuhomienia programu (włączenia/zrestartowania Arduino). Do zapisywania danych zwracanych przez tą funkcję należy użyć typu unsigned long – wystarczy na około 50 dni. Więcej info tutaj.

Dzięki tej funkcji możemy mierzyć czas wykonania jakiejś czynności. Aby to zrobić, musimy zapisać „zegar” (aktualną wartość milisekund, która sama w sobie nie jest istotna) do jednej zmiennej, powiedzmy t1, wykonać czasochłonne czynności, a po nich ponownie zapytać o „zegar” – i zapisać do drugiej zmiennej, np. t2. Różnica t2 i t1 jest właśnie czasem wykonania konkretnej czynności.

Przycisk (moduł).

Dzięki temu, że to jest przycisk z modułem, to jego obsługa jest bardzo prosta – musimy podłączyć zasilanie do modułu (Vcc do Arduino 5V, GND do Arduino GND, a pin sygnałowy S – do dowolnego, wybranego przez nas pinu cyfrowego w Arduino – np. 7).

Następnie pamiętajmy o poleceniu pinMode(7, INPUT), które spowoduje, że będziemy mogli odczytywac stan przycisku za pomocą digitalRead(7). Jeśli przycisk jest wciśnięty, to funkcja ta zwróci wartość 1, w przeciwnym przypadku – wartość 0 (zero).

Koszt takiego modułu to około 3 zł, należy szukać hasła w stylu Moduł przycisku tack switch z LED ARDUINO (np. w serwisie Allegro).

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ń!