Światłolub – programowanie

komunikacja I2C i hd44780

Aby widzieć odczyty z fotorezystorów wykorzystujemy ekran LCD16x2 — nie chcemy jednak tracić cennych portów cyfrowych (chyba trzeba użyć 7-miu do obsługi), więc stosujemy moduł I2C hd44780.

testy, testy, testy…

Czyli najprzyjemniejsza część zabawy – prototyp już mamy, teraz trzeba go mądrze oprogramować. Zaczynamy!

Trzeba odczytać wskazania obu fotorezystorów gdy światło jest przed pojazdem, z jednego boku, z drugiego… Zapisać do notepada.exe by następnie wpisać w ino 🙂

Kiszka. Stoi. Albo kręci się nie w tą stronę, co trzeba. A niby miało działać 😛 więc znowu do kompa i wprowadzamy zmiany w kodzie /w parametrach.

Nawet kłótni nie było 🙂 nikt nie zrzucał winy na drugiego – nie działa dobrze, więc trzeba poprawić! Świetny team-work !

Zawody

Za tydzień kody będą już dopieszczone, więc będzie można przystąpić do sprawdzenia algorytmów w akcji – postawimy dwie przeszkody, będzie trzeba je objeżdźać – kręcąc tzw. ósemki. Zmierzymy czas trzech okążeń i się okaże, który zespół jest lepszy 😉

(c) K.G. 2025

Oczy światłoluba

Ciągle budujemy pojazd sterowany latarką – wykorzystamy fotorezystory jako „oczy”. Dziś wracamy do konstrukcji pojazdu i będą pierwsze próby. Ale nie chcemy mieć płytki prototypowej na pokładzie więc… poznajemy lutownicę 😉

Przygotowujemy sobie wielokrotne wyjścia GND i 5V, a także lutujemy rezystor z fotorezystorem w szereg – z dodatkowym przewodem do pinu analogowego Arduino UNO. Wszystko proste, tylko trzeba trochę się pobawić… na tym to chyba polega, prawda? 😉

No i dobrze, że się ucząc się także się bawimy!

Udało się! Oczy skierowane są na podłogę (trochę za bardzo) więc rozpoczyna się faza testowa oprogramowania – część „hardwareowa” chwilowo zakończona.

(c) K.G. 2025

fotorezystor – oczy światłoluba

Czyli budujemy pojazd sterowany latarką – wykorzystamy fotorezystor jako „oczy”. Czyli muszą być dwa, aby porównywać ilość światła z jednego czujnika i drugiego i na tej podstawie jechać do przodu, zatrzymywać się czy skręcać. Niby proste – choć cała magia tkwi w odpowiednim doborze parametrów decyzyjnych.

analogRead()

Studenci jeszcze nie mieli omawianej tej funkcji na zajęciach z Arduino – więc zaczynamy od podstaw. Uczymy się więc co mierzymy, jakie są ograniczenia Arduino UNO, sprawdzamy odczyty napięcia 3.3V oraz 5V z płytki Arduino, a także baterie AAA.

Przechodzimy dalej do fotorezytora i uczymy się go najlepiej wykorzystać. Skoro Aruino idczytuje napięcie a nie opór – to wykorzystujemy dzielnik napięcia i odczytujemy napięcie. Ale jaka wartość stałego rezystora w dzielniku dla naszego fotorezystora? Testujemy z wykorzystaniem thinkercada!

Dziś bez podłączenia jeżdzącej platformy – to będzie za tydzień!

(c) K.G. 2025

Pierwsze spotkanie w nowym semestrze 2019/2020!

Nowy semestr w roku akademickim 2019/2020

Zapraszam zainteresowanych na zajęcia koła Fi-BOT w poniedziałki, o godz. 14:15 do sali 1064 (Wydział Fizyki, Kampus). Będziemy pracować nad rozpoczętymi projektami. Mile widziani studenci ze znajomością platformy Arduino, ale i tak liczy się zaangażowanie. Zapraszam!

Radiówka i „grzebek”

Pan Przemek zrealizował proste sterowanie „grzybkiem” (zamiast przycisków). Proste, bo wychylenie gałki (odczyt z analogRead() w zakresie 0..1023) powyżej ustalonej wartości (>700) oznacza ruch w jedną stronę z pełną prędkością, natomiast gałka w drugą stronę (<300) w przeciwną. Tak samo z drugą osią. W kolejnym podejściu prace nad uzależnieniem prędkości od wartości wychylenia (PWM silników skalowane analogReadem grzybka).

Jak zawsze coś się musiało rozlutować…

PM2D3D Nowe wózki i akceleracja

Pan Bartek udoskonalił nowe wózki i ciągle pracuje nad akceleracją… Więcej o projekcie PM2D3D na dedykowanej stronie.

(c) K.G.

Precyzyjna Maszyna oraz RPM

Obroty na minutę: RPM (czujka pola magnetycznego SS49E)

Pan Przemek ukończył kod, który zlicza obroty wirującego silniczka – brawo! Należy się pochwała, bo to jego pierwsze zmagania z Arduino.

Układ doświadczalny:

W układzie celowo zamontowano magnesy tak, by czujka SS49E „widziała” raz biegun północny (N) magnesu, a za drugim razem (gdy silniczek obróci sie o 180 stopni) biegun południowy (S). Ustawienie magnesów na końcach patyka nie jest więc przypadkowe 😉 Czujnik SS49E odczytuje zarówno biegun S jak i N (uwaga: nie wszystkie czujki pola magnetycznego, bazującego na efekcie Halla, tak mają – warto to sprawdzić przed zakupejm), dlatego widzimy dwa „piki” podczas obracania silniczka – jeden „do góry” (większe napięcie) oraz „do dołu” (napięcie mniejsze). Z dala od magnesów czujka zwraca napięcie ~2.5V informując, że wartość pola magnetycznego jest (około) zera. Poniżej wykres z Kreślarki

Program zliczający liczbę obrotów na sekundę (zmienna czas – aktualnie 1000ms, ale można zmienić, także przez krotność – zmienna krok). Algorytm polega na znajdowaniu maksimum i minimum napięcia – a zapisywane jest moment ich wystąpienia (do zmiennych t_1oraz t_2, odpowiednio). Różnica tych czasów do pół obrotu.

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

int i,max_=518,min_=518,a=0,b=0,czas,n=0,krok=1;
float v;
long int t_1=0,t_2=0,t_k=0,t_3=0,t_p;

void loop(){
 t_p=millis();
 czas=1000;
 i=analogRead(A0);
 if(i>540){
   if(i>max_){
    max_=i;
    t_1=millis();
   }
   else if(i<max_){
    a=1;
   }
 }
 if(i<490){
   if(i<min_){
    min_=i;
    t_2=millis();  
    }
   else if(i>min_){ 
    b=1; 
  }
 }

 if(t_1>t_2){
  t_3=t_2;
 }
 else{
  t_3=t_1;
 }
 
 if(a==1&&b==1){
    t_k=abs(t_2-t_1);
    a=0;
    b=0;
    max_ = 518;
    min_ = 518;
    if(czas>t_3){
      n++;
    }
    else if(czas<t_3){
    Serial.print("Liczba pol-obrotow: ");
    Serial.println(n);
    n=0;
    krok++;
    czas=czas*krok;
    }
 }
 }

Zmienna n (małe n) zlicza wystąpienia „półobrotów”, a co ustalony czas wypisywany jest komunikat z tą liczbą. W ten sposób mamy właśnie pół-RPS (revolutions per second), z którego łatwo można już otrzymać RPM (revolutions per minute).

Precyzyjna Maszyna

Sprężynka nie wytrzymała – chyba była zbyt twarda 🙁

Nowy model powinien być lepszy – bo wydrukowany z Z-Ultratu:

No i mamy coraz lepszą pracę Maszyny:

Więcej o projekcie Maszyny na stronie projektu.

(c) K.G.

Precyzyjna Maszyna (chwytak!) oraz Wiatromierz

Chwytak do ołówka/mazaka zaprojektowany, wydrukowany w 3D i zamontowany! Działa z serwomechanizmem a kod BBcode obsługuje nowe instrukcje (up, down).

No i kolejny (próbny) precyzyjny rysunek:

Opis całego proejktu Maszyny pod tym adresem

Obroty na minutę (rpm) i czujka pola magnetycznego SS49E

Wakacje w trakcie, ale nie tylko Pan Bartek spędza wolny czas z pracą nad projektem. Pan Przemek, który nie miał czasu na zajęcia Fi-BOTa w roku akademickim, poznaje Arduino i „atakuje” temat liczenia obrotów silniczka, wykorzystując czujkę pola magnetycznego SS49E


A po co nam zliczanie tych obrotów? Zastosowań jest wiele, jednym z nich jest mierzenie prędkości wiatru takim prostym urządzeniem:

w środku którego znajdują się: czujka SS49E, dwa magnesy oraz łożysko kulkowe (typ 682ZZ).

O dalszych losach tego projektu niebawem…

(c) K.G.

Sterowanie serwem za pomocą joysticka

Na zajęciach sterowaliśmy serwomechanizmami za pomocą joysticka. Na początku używaliśmy niewielkiego modułu z joystickiem podłączanego bezpośrednio do Arduino. W drugiej części użyliśmy nakładki (shield) na Arduino z joystickiem oraz czterema przyciskami (podobnie jak na gamepadach).

Moduł z joystickiem

Moduł posiada pięć pinów. GND oraz 5V podłączamy do Arduino. VRx i VRy to piny sterujące odpowiednio osią OX (czyli lewo-prawo) oraz OY (czyli góra-dół). Podłączamy je do pinów analogowych. Ostatni pin odpowiada za przycisk, jednak nie używaliśmy go w tym zadaniu.

Prosty program wyświetlający położenie joystika

void setup(){
  Serial.begin(9600);
}
int x,y;
void loop(){
   x = analogRead(A0);
   y = analogRead(A1);
   Serial.print("x=");
   Serial.print(x);
   Serial.print(", y=");
   Serial.println(y);  
  }

Położenie na osi OX (także OY) to liczby z zakresu 0..1023. Położenie spoczynkowe powinno odpowiadać wartości 511 (liczby 0..510 to wychylenie w lewo, liczby 512..1023 to wychylenie w prawo). Użycie tego programu pozwoliło nam sprawdzić, że tak jednak nie jest – u nas joy w położeniu spoczynkowym miał wartości 514, 517 (oś OX i OY).

Podczas działania tego programu możemy postawić sobie następujące zadanie: ustawić pozycję joy-a w takim położeniu, aby odczyty były x=800 y=200. Okazuje się to jednak bardzo trudne! Widzimy więc, że sterowanie joy-em nie jest łatwe i wymaga sporo wprawy.

Wieżyczka

Używana przez nas wieżyczka (do której można przyczepić, np. kamerkę internetową by nią sterować) składała się z dwóch serw na podstawce. Umożliwia to poruszanie się mechanizmu na boki oraz w górę i dół.

Wszystkie potrzebne elementy połączyliśmy za pomocą płytki prototypowej. Zamiast zasilania z Arduino użyliśmy zewnętrznego koszyka na 4 baterie o łącznym napięciu 5V. Dlaczego tak zrobiliśmy? Chodziło nam o oddzielne zasilanie silników aby nie przeciążyć płytki Arduino – pojedyncze serwo może pobrać nawet 200mA prądu (co sprawdzaliśmy na poprzednich zajęciach), a wydajność prądowa Arduino UNO to około 200-400 mA. Dlatego dwa takie serwa mogą uszkodzić naszą płytkę. My użyliśmy oddzielnego zasilania silników aby temu zapobiec. WAŻNE: w przypadku używania kilku źródeł zasilania (u nas Arduino 5V i 4x baterie AAA) musimy uwspólnilić masy (GDN z Arduino, „minus” z bateryjki).

Użyliśmy płytki prototypowej, gdzie na jednej szynie (koloru niebieskiego) wetknęliśmy „-” z koszyka baterii oraz GND Arduino. Do tej „szyny” podłączone były masy serw (przewody koloru brązowego). Druga szyna (czerwona – z drugiej strony płytki, dla naszej wygody) doprowadzone miała przewód „+” z koszyka baterii i tam podłączone były zasilania silników serw (czerwone przewody serw). UWAGA: nie można łączyć pinu 5V Arduino z zewnętrznym zasilaniem baterii – może to spowodować uszkodzenie płytki! Łączymy (=uwspólniamy) jedynie masy. Przewody sterujące serwami (koloru żółtego) podłączyliśmy do pinów PWM Arduino UNO – u nas #3 i #5.

Program sterujący

Na początku standardowo dołączamy do programu bibliotekę umożliwiającą sterowanie serwami. Następnie dodajemy zmienne do obu serw, jedno odpowiedzialne za ruch góra-dół, a drugie lewo-prawo.

#include <Servo.h>
Servo GoraDol;
Servo LewoPrawo;

void setup (){
  Serial.begin(9600);
  GoraDol.attach(3);
  LewoPrawo.attach(5);
}
int x,y;

W kolejnej części deklarujemy zmienne odpowiadające za położenie obu osi joysticka – dokładnie tak, jak w pierwszym programie odczytującym położenia joy-a. Wyświetlamy wartości x oraz y w monitorze szeregowym. Joystick zwykle nie jest idealnie skalibrowany, jednak nie ma to znaczenia przy niewielkiej precyzji.

Funkcja map pozwala na łatwe proporcjonalne przeliczenie wartości. Używamy jej, ponieważ położenia joysticka są z zakresiu 0-1023, natomiast sterowanie serwem chcemy wyrażamy w stopniach 0-180. Wynik przypisujemy od razu do zmiennych x oraz y (używamy tych samych zmiennych, niszcząc ich poprzednie wartości). W argumentach funkcji wpisujemy zmienną do przeliczenia, następnie jej obecny zakres i na końcu zakres po zamianie. Po przeliczeniu wartości możemy je przekazać do serwomechanizmów.

   x=map(x,0,1023,0,180); //funkcja map
   LewoPrawo.write(x);
   y=map(y,0,1023,0,180);
   GoraDol.write(y);
   delay(10);

Nakładka (shield) na Arduino

Fajnym rozwiązaniem jest wykorzystanie specjalnej nakładki (shield), która poszerza możliwości Arduino. Piny obu komponentów pasują do siebie, więc nie da się pomylić przy wpinaniu nakładki. Joystick oraz przyciski są fabrycznie podłączone do pinów, więc nie musimy tego robić w programie. Na nakładce wszystkie piny są podpisane, więc później będziemy tylko operować odpowiednimi oznaczeniami pinów.

Modyfikacja programu – przycisk „zamrażający” położenie wieżyczki

Program sterujący jest bardzo podobny do poprzedniego. Jedyną różnicą jest brak podłączenia pinów cyfrowych. Dodatkową funkcją, którą wprowadzamy do naszego programu, jest zatrzymywanie serwa w ustawionej pozycji. Chcemy aby wciśnięcie wybranego przycisku (np. koloru czerwonego) zablokowywało dalsze sterowanie wieżyczką. Kolejne wciśnięcie tego przycisku powoduje odblokowanie sterowania. W tym celu do kodu wprowadzamy zmienną typu logicznego bool (nazwaną tryb) i ustawiamy ją na wartość true. Następnie wybieramy przycisk (np. ten czerwony), który ma sterować zatrzymaniem serwa i  sprawdzamy, który numer pinu u odpowiada. W naszym programie jest to pin 5.  Tworzymy instrukcję sterującą if, która wykona się po wciśnięciu przycisku. Do wartości zmiennej tryb, przypisujemy jej odwrotność. Czyli jeśli tryb jest true, zostanie zmieniony na false i odwrotnie. Funkcja delay() wprowadzamy aby zarejestrować tylko jedną zmianę ustawienia przycisku (przyciski lubią „drgać” co powoduje nie jeden „klik” a wiele takich „klików” – opóźnienie je zniweluje). Działa to w taki sposób, że jeśli tryb jest wartością false, czyli zostanie raz zmieniony we wcześniejszym if’ie, sterowanie joyem zostaje zablokowane. Natomiast po kolejnym użyciu przycisku, tryb zmieni się z false na true, a sterowanie zostanie odblokowane.

bool tryb=true;
void loop(){
  x=analogRead(A0);
  y=analogRead(A1); 
   if (digitalRead(5)==HIGH){
      tryb=!tryb;
      delay(50);
   }

   if(tryb==true){ 
   x=map(x,0,1023,0,180); //funkcja map
   LewoPrawo.write(x);
   y=map(y,0,1023,0,180);
   GoraDol.write(y);
  }
}

Podsumowanie

Jak można zauważyć programy umożliwiające sterowanie servami nie są skomplikowane ani długie. Można sprytnie wykorzystać komponenty posiadające więcej niż jedną oś ruchu, dzięki czemu nasze możliwości się poszerzają. Jednak precyzyjne sterowanie takimi joystikami nie jest łatwe…

(c) Ewelina, KG 2017

Sterowanie servem za pomocą potencjometru

Na ostatnich zajęciach łączyliśmy wiedzę nabytą na dwóch poprzednich spotkaniach, czyli działanie potencjometru oraz serva. Chcieliśmy wykorzystać możliwość zmiany nastawy potencjometru, w celu sterowania ramionami serwomechanizmu. Podobnie jak na zajęciach przedświątecznych, wykorzystamy do tego komendy biblioteki sterującej servami.

Sterowanie serva

#include <Servo.h>
Servo silnik;

void setup (){
  Serial.begin(9600);
  silnik.attach(3);
}

Servo podłączamy tak samo jak na przedświątecznych zajęciach, jednak w tym przypadku używamy 3 pinu, a sam mechanizm nazywamy silnikiem (linia #2 i #6).

Wykorzystanie potencjometru

int pot;
void loop(){
   pot=analogRead(A0);//odczytujemy liczby z zakresu od 0 do 1023
   pot=pot*180.0/1023;//zamienimy na liczby od 0 do 180
   Serial.print(pot);
   silnik.write(pot);
}

Na początku deklarujemy zmienną zapisującą stan potencjometru. W ciele funkcji void loop() podłączamy potencjometr do portu analogowego A0. Linia #4 przelicza zakres potencjometru. Jak pamiętamy, wynosi on od 0 do 1023, natomiast stopnie wychylenia serva chcemy wyrażać w zakresie 0-180. 180 konwertujemy na zmienną typu float dopisując do niej część dziesiętną w celu uniknięcia dzielenia całkowitego. W innym wypadku otrzymywalibyśmy nieprawdziwe wyniki, ponieważ wynikiem dzielenia 180/1023 zawsze będzie 0, przez co całe działanie również wyniesie 0. Przy zapisie 180.0/1023 mamy do czynienia z dzieleniem rzeczywistym, którego wynikiem będzie liczba rzeczywista. Następnie przy przemnożeniu przez zmienną całkowitą pot dostaniemy również liczbę rzeczywistą. Ostateczny wynik jest rzutowany na liczbę całkowitą w momencie przypisania operatorem równości.

Ulepszenie – dodatkowy if

W celu ulepszenia naszego kodu, chcieliśmy aby położenie ramion serwa było aktualizowane jedynie wtedy, kiedy zmienimy położenie potencjometru. Tym samym chcemy uniknąć sytuacji wydawania polecenia „ustaw serwo na pozycję XX” jeśli właśnie aktualną pozycją jest XX (nie ma to sensu, mimo tego, że to działa – jak w naszym pierwszym, prostym programie). Użyliśmy do tego instrukcji sterującej if. W linii #1 dopisaliśmy kolejną zmienną nazwaną old, która ma za zadanie zapisywać poprzedni stan położenia potencjometru (odczytanego napięcia). W warunkach if-a sprawdzamy, czy zmienna pot (czyli aktualny stan potencjometru), różni się od zmiennej old (czyli jego poprzedni stan).  Jeśli nie, funkcja Serial.print() nic nie wypisze i nie zmieniamy położenia serwa. W przeciwnym przypadku zostanie wypisane nowe napięcie, a ramiona serwa zmienią położenie. Na końcu przypisujemy zmienną old do pot, aby móc dokonać nowego porównania w kolejnej iteracji pętli. 

int pot, old; //old - zmienna zapisujaca poprzedni odczyt

void loop(){
  pot=analogRead(A0);
  pot=pot*180.0/1023.0; 
  if (pot!=old){ //aby zmieniac polozenie tylko wtedy, kiedy sie zmienilo, a nie wyswietlac polozenie ciagle
   Serial.print(pot);
   silnik.write(pot);
   old=pot; 
  }
}

Podsumowanie

Dzięki naszemu programowi możemy sterować ramionami serwa kręcąc potencjometrem. Przeliczenie wartości napięcia na stopnie umożliwia dość precyzyjne ustawienie serva.

2018, Ewelina (c)

Sygnały analogowe

Konwerter analogowo cyfrowy (DAC)

Sygnały analogowe to takie sygnały elektroniczne, które możemy zapisywac nie tylko jako 0 lub 1 (tak/nie, prawda/fałsz – tylko dwie wartości), ale w wielu „odcieniach” – w końcu pomiędzy zerem a jedynką jest nieskończenie wiele liczb. Oczywiście w informatyce wszystko musi byc skończone, tak więc tych „odcieni” (poziomów pomiędzy zerem a jedynką) jest skończona liczba. Układ zamianiający sygnał elektroniczny na informację cyfrową nazywa się konwerter analogowo cyffrowy (DAC) i mówiąc o nim podajemy jego zakres – liczbę bitów. Dla 8-bitowego DACa mamy wartości sygnału analogowego z przedziału od 0..255 (256 poziomów = 2^8), natomiast w przypadku 10-bitów 0..1023 (1024 poziomy = 2^10).

Potencjometr

Wygląda dość topornie – ale jeśl macie w domu zbyteczną gałkę z kryształów Swarowskiego to proszę śmiało przynieść i uatrakcyjnimy wygląd tego podzespołu elektronicznego 😉 Trzeba pamiętać o sposobie podłączania go do budowanych układów. Widzimy trzy nóżki więc:

  • jedna skrajna nóżka (nie ma różnicy która) powinna być podłączona do masy (nazwijmy ją GND i oznacza napięcie zero V)
  • druga skrajna nóżka musi być podłączona do danego napięcia, nazwijmy je VCC
  • środkowa nóżka będzie „wyprowadzać” napięcie od zera do VCC w zależności od ustawienia pokrętła na potencjometrze. 

Na zajęciach dość szczegółowo omówiłem budowę potencjometru i zasadę jego działania – dzielnik napięć – ale do tego jeszcze obiecuję wrócić. Na razie skupmy się na powyższych informacjach jak potencjometr łączymy w układ. Jako przykład możemy podłączyć „minus” bateryjki AAA do pierwszej nóżki, „plus” do trzeciej „nóżki”, wówczas z pinu numer dwa otrzymamy napięcie od 0..1.5V. Innym przykładem podłączenia jest wykorzystanie Arduino i pinów GND (podłączamy do pinu 1 na potencjometrze) oraz 5V (do pinu 3 na potencjometrze) – wówczas mamy kontrolę potencjometrem nad napięciem 0..5V (pin 2 na potencjometrze). 

Pinem #2 z potencjometru możemy zasilać jakiś układ – sprawdzaliśmy to z LED-em wpiętemym pomiędzy piny #1 (GND) i #2(0..3.3V) potencjometru, lub mozemy podłączyć pin #2 do wejścia A0 w Arduino – wówczas odczytamy wartość napięcia ustawionego potencjometrem jako liczbę z przedziału 0..1023 (Arduino UNO ma DAC 10-bitowy).

Kalibracja

Konieczne jest sprawdzenie poziomu napięcia 5V w Arduino – może się zdarzyć, że nasza płytka jest uszkodzona lub producent nie trzymał standartów i zamiast 5V mamy 5.1V. To spora różnica. W przypadku uszkodzonych płytek – których wcale nie ma co wyrzucać – napięcie zamiast 5V może być nawet 4.5V co jest już ogormną różnicą! Dlatego konieczne jest sprawdzenie multimetrem wartości napięcia produkowanego przez Arduino z pinu 5V. 

Odczytywanie sygnału – analogRead

void setup(){
  Serial.begin(9600);
}
int odczyt;
void loop(){
  odczyt = analogRead(A0);
  Serial.print("Odczytalem ");
  Serial.print(odczyt);
  Serial.print(" ---> ");
  Serial.print(odczyt*4.9/1024);
  Serial.println(" [V] ");   
}

Ten prosty program odczytuje sygnał podłączony do pinu A0 w Arduino (możesz wybrac inne wyjścia: A1,A2…A5) i wypisuje jego wartość jako liczbę z przedziału 0..1023 (gdyż Arduino UNO ma przetwornik DAC 10-cio bitowy, czyli 2^10=1024) a także podaje wartość w woltach. Sprawdziłem, że w moim Arduino napięcie z pinu 5V wcale nie wynosiło 5V a 4.9V i dlatego linia #10 zawiera właśnie takie przeliczenie na wolty. Zwróć też uwagę na sposób komunikowania się z ekranem – budowanie napisu w jednej linii i dopiero na koniec użycie funkcji Serial.println().

Posługują się powyższym programem najpierw sprawdzamy odczytywane napięcie z pinu 3.3V Arduino, potem 5V Arduino –  porównując wartości wypisywane na ekranie z multimetrem. Potem możemy użyć jakiś baterii a w końcu wykorzystać potencjometr i jego środkowy pin.

PWM (cyfrowe piny z „tyldą” ~)

PWM to szybkozmienny sygnał cyfrowy (cyfrowy, a więc tylko dwie wartości: 0V oraz 5V). Szybkozmienny oznacza naprawdę szybkie zmiany, 500x na sekundę – czyli co 2ms! Musimy podać jaki ułamek czasu (z przedziału 2ms) będzie napięciem wysokim (5V) a wówczas pozostały czas będzie napięciem 0V. Ten ułamek czasu musimy wyrazić jako liczbę całkowitą z przedziału 0..255 (gdzie 255 to 100%) gdyż w Arduino UNO piny PWM są 8-bitowe (a 2^8=256). Wartość 0..255 nazywa się to wypełnieniem sygnału.

Sterowanie wypełnieniem – analogWrite

void setup(){
  pinMode(3, INPUT);//pin cyfrowy z tyldą = PWM 
}

void loop(){ 
  analogWrite(3, 0);
  delay(5000);
  analogWrite(3, 100);
  delay(5000);
  analogWrite(3, 200);
  delay(5000);
  analogWrite(3, 255);
  delay(5000);
}

Powyższy program wybiera pin #3 Arduino UNO (zwróć uwagę, że jest on onzaczony „tyldą” na płytce – czylli jest to pin PWM, ale można wybrac inne piny PWM) i steruje jego wypełnieniem. W tym celu używamy funkcji analogWrite(int,int) podając numer pinu którego ma dotyczyć zmiana (koniecznie pin z tyldą!) oraz wartość wypełnienia (koniecznie z przedziału 0..255). Co 5 sekund zmienia jego wartość, którą możemy odczytać na multimetrze – ale uwaga, będzie to tylko wartość średnia! Aby zobaczyć zmiany napięcia w okresach 2ms należało by użyć oscyloskopu. 

Praca domowa

Wykorzystując informacje z dzisiejszych zajęć uruchomić wirtualne Arduino i zbudować program z potencjometrem, który steruje jasnością LED-a. Musimy więc odczytywać wartości z potencjometru a następnie odpowiednio sterować zasilaniem LED-a. Powodzenia!

(c) KG, 2017

 

Zajęcia nr 5 – serwo silniki, map(), bluetooth

 Serwo silnik (a właściwie mikro-serwo)

serwo1Czyli silnik, który obraca się od 0 do 180 stopni (ma blokadę na inne wychylenia). Potem utrzymuje swoją pozycję. Służy do tworzenia obrotowych ramion itd…

Trzy przewody – zasilanie (czerowny +5V, czarny/brązowy GND) oraz jeden sterujący – musi być PWM. Za dużo nie wnikałem o co chodzi w sterowaniu tym silnikiem, tylko wspomniałem o potencjometrze wewnątrz i o wypełnieniu sygnału sterującego… więcej może później? Zobaczymy.

 

Do sterowania tym silnikiem użyliśmy 2 nowych funkcji z nowej biblioteki:

  • #include <Servo.h> – na początku programu informujemy, że chcemy funkcje z tej nowej biblioteki
  • Servo silniczek; tworzymy zmienną typu silnik-serwo, czyli właśnie o to nam chodzi!
  • silniczek.attach(3); powoduje przekazanie informacji do Arduino, że sterujemy silnikiem przez pin numer 3 (przypominam: musi być to pin PWM, czyli jak nie 3, to 5,9…)
  • silniczek.write(133); ustawia nasz silnik w pozycji 133 stopni. Albo na dowolny inny z zakresu 0..180 stopni. Dziecinie proste 😉

Serwo sterowane z klawiatury

Przypomnieliśmy sobie jak odczytywać liczby z klawiatury (funkcja parseInt() dla obiektu Serial) i stworzyliśmy program ustawiający silnik w pozycji wczytanej z klawiatury. Proste a przyjemne. No i zawsze warto powtarzać wiedzę 😉

Serwo sterowane potencjometrem

Połączenie poprzednich zajęć – potencjometr liniowy (dzielnik napięć!) wykorzystany do ustawiania pozycji serwa – ruszam „gałką” w lewo, orczyk w serwie obraca się w lewo. Tak samo w prawo. Fajne!

Serwo sterowane potencjometrem – program PRO

Dbamy o szczegóły – i nie chcemy ustawiać położenia serwa wówczas, gdy potencjometr nie zminił swojej pozycji. Bez złośliwości – my staramy się programować na serio

Prąd „zjadany” przez serwo – mierzymy!

W skrajnych ustawieniach serwa (tj. w okolicy 0 stopni, oraz w okolicach 180 stopni) słyszymy buczenie/piszczenie serwo-silnika. Coś się dzieje. Amperomierz w garść i mierzymy prąd.

serwo1

Przyjrzyj się uważnie obrazkowi i zwróć uwagę, jak podłączony jest amperomierz.

Oczywiście w wirtualnym Arduino (ciągle polecam circuits.io) silniczek serwo jest idealny i nie widzimy tego, co było u nas na zajęciach….

Dodatkowo: w przypadku mierników uniwersalnych ustaw największą wartość prądu, jaką się spodziewasz dostać – nie odwrotnie! W przeciwnym przypadku zwiększając zakres przepalisz bezpiecznik w multimetrze…

Funkcja map()

Czyli skalowanie wartości z jednego zakresu na drugi zakres. Przykład, z którym my się bawiliśmy: serwo silniczek sterowany potencjometrem. Odczytujemy nastawy potencjometru z portu analogowego Arduino jako liczbę (nazwijmy ją x) z zakresu 0..1023, a następnie ustawiamy serwo w położeniu z zakresu 0..180 stopni (nazwijmy te stopnie y). Czyli musimy dokonać zamiany wczytaj liczby x na y. Na zajęciach pokazałem skalowanie funkcją liniową, rozwiązaliśmy ten układ równań, ale Arduino jest także dla tych co tego nie umieją zrobić i przygotowało funkcję map(). W naszym przypadku będzie to:

y=map(x, 0, 1023, 0, 180);

Należy pamiętać, że funkcja map() działa tylko na liczbach całkowitych (int).

Serwo sterowane przez Androida – bluetooth XM-15B

Dlaczego ten? Bo działa w zakresie 3-6V, czyli można go bezpiecznie podłączyć do Arduino. Inne modele – popularne HC-05, HC-06 komunikują się przez 3.3V i wymagają „zbijania” napięcia (np. dzielnikiem napięć). To proste, ale… po co się w to bawić, jak można kupić właśnie moduł pozbawiony tej uciążliwości? Praujemy więc z XM-15B.

 

Pamiętajmy o łączeniu „na krzyż” portów RxD,TxD modułu XM-15B z portami RxD,TxD płytki Arduino (także tymi wirtualnymi).

Komunikacja z 8LAMP

Ze sklepu Play bierzemy prostą apkę i sprawdzamy, co ona wysyła do naszego bluetootha. Kod:

#include <SoftwareSerial.h>

#define RxD 8
#define TxD 9
SoftwareSerial btSerial(RxD,TxD);

void setup() {
  Serial.begin(9600);
  btSerial.begin(9600);
  Serial.println("start!");
}

void loop() {
  if (btSerial.available()){
    Serial.print("Odebrałem znak= ");
    Serial.println(btSerial.read());
  }  
}

Następnie tak modyfikujemy ten program, by wczytany znak sterował naszym serwem – guzik '1′ ustawiał serwo na 90 stopni, guzik '2′ na 10 stopni i guzik '3′ na 170 stopni. Inne modyfikacje mile widziane 😉

Ważne

Na następne zajęcia proszę o zainstalowanie ze sklepu Play aplikacji Arduino Bluetooth Controler bo będziemy sterować pojazdem.