Pojazd (Bluetooth) + podstawy (3xLEDy + 3x przycisk)

Rozwija się projekt POJAZDU, a jednocześnie nauczane są podstawy Arduino (i programowania)…

  1. POJAZD
    1. Sterownik Monster vnh2p30 okazał się uszkodzony! Trudno to było wyczuć, bo z jednej strony działał poprawnie kręcąc silniczkiem w jedną stronę, natomiast w stronę przeciwną – albo wcale, albo baaaardzo powoli. Dlatego odsyłamy sterowniki do sklepu i wracamy do L298 i programujemy sterowanie przez Bluetooth. Pamiętamy o tym, aby nie jeździć na maksa bo ten sterownik przeznaczony jest tylko do pracy z prądami <1A. Na kolejnych zajęciach wrócimy do Monstera – bo mamy ich kilka sztuk a nie wszystkie są niesprawne.

  1. Sterowanie Bluetooth przez aplikację  Android RC działa! gratulacje.
  2. Podstawy Arduino/C/C++ pracujemy….

KG, 2018

Pojazd (pierwsze uruchomienie) + podstawy (LEDy + przycisk)

Rozwija się projekt POJAZDU, a jednocześnie nauczane są podstawy Arduino (i programowania)…

  1. POJAZD
    1. praca nad sterowaniem pojazdem: wykorzystujemy sterownik Monster vnh2p30 o bardzo dobrych parametrach (maksymalny prąd nawet 30A! zasilanie 6-18V) i świetnej cenie (~25 zł). Sterowanie podobne jak w przypadku L298 (za pomocą dwóch sygnałów) – konieczne jest podłączenie sygnału PWM (lub innego pinu z Arduino i włączenie go na stałe na HIGH, czyli PWM=100%). Fajna stronka opisująca co i jak podłączyć – polecam.
    2. Można kupić PODWÓJNY sterownik, ale cena (o dziwo) nie jest już aż tak atrakcyjnaZnalezione obrazy dla zapytania monster vnh2p30
  2. PODSTAWY: LEDy + przycisk = REFLEKS. Poznajemy jak odczytać stan przycisku – małe wyzwanie: program REFLEKS: LED zapali się po losowym czasie, naszym zadaniem jest jak najszybsze wciśnięcie przycisku od razu po zaświeceniu LEDa. Mierzymy czas reakcji człowieka.  Ciągle polecam wirtualne Arduino do zabawy w domu!
  3. Poznaliśmy OPTYCZNY czujnik odległości E18-D80NK (5V, zakres 3-80cm, nie dźwiękowy!) – prosty w użyciu, a niedługo do wykorzystania w projekcie Pojazdu.

KG, 2018

Pojazd (mechanika + pierwsze uruchomienie) + podstawy (LEDy)

Rozwija się projekt POJAZDU, a jednocześnie nauczane są podstawy Arduino (i programowania) – jest więc mały chaos…

  1. POJAZD
    1. konstrukcja: podstawa z płyty wiórowej 18mm wymieniona na sklejkę 10mm, czyli cieńszą, aby koła pojazdy miały większy „prześwit”
    2. silniki to Pollolu 37Dx70L z wbudowanym enkoderem – silnik ma przekładnię 70:1 dzięki której na dość małych obrotach (150 obr/min) uzyskuje  moment obrotowy 1,39 Nm (co oznacza 14 kg*cm). Dodatkowo możemy oprogramować enkoder kwadraturowy o rozdzielczości 64 impulsy na obrót (po przełożeniu 4480 impulsów na obrót).
    3. Zasilanie silnika to 6V do 12V – co przekłada się odpowiednio na na obroty: 75 rpm do 150 rpm i na pobór prądu: średniego 250/300mA i maksymalnego 2.5A/5A. Widać, że będziemy potrzebować mocnego sterownika do tych silników (typowy L298 da radę z maksymalnie 1A – tylko!)
    4. Koło do tego silnika to oryginalne Pollolu 12cm
    5. Mocowanie silnika to wydrukowane w 3D na uczelnianej drukarce „chwytaki” (projekt własny):
  2. PODSTAWY: LEDy, czyli poznajemy jak włączać/wyłączać napięcie na pinach Arduino. Polecam wirtualne Arduino do zabawy w domu.

KG, 2018

RGB LED – PWM (podstawy)

Niby podstawy – ale jakie kolorowe 😉 No i bardzo przyszłościowe – niebawem się okaże, jak barwne mogą być nasze elektroniczne gry zręcznościowe!

Sprawa jest prosta – w tej diodzie RGB są właściwie TRZY diody – czerwona, niebieska i zielona. Dzięki mieszaniu trzech kolorów otrzymujemy każdy inny, dowolny kolor – w tym także biały. Właśnie biały to bardzo ważny kolor – potrzbny nam do codziennego życia – dlatego też właśnie w 2014 r. uchonorowano Japończyków nagrodą Nobla za zrobienie niebieskiego lasera.

RGB LEDy występują z dwoma typami obudowy – matową (polecam) oraz przezroczystą. Ta pierwsza daje światło bardziej rozproszone, trudno nawet zobaczyć te trzy oddzielne LEDy.

Wspólna anoda, wspólna katoda.

RGB LED ma cztery „nóżki” (wyprowadzenia): skoro sa tam trzy LEDy (czerwony, zielony i niebieski) to niepotrzebną rozrzutnością było by mocowanie sześciu nóżek – po dwie dla każdej diody. Oczywiście dioda ma mieć możliwość oddzielnego sterowania (włącznaia), dlatego te trzy nóżki muszą być – natomiast resztę (też 3) można ze sobą uwspólnić – czyli połączyć. Tym oto sposobem zredukowaliśmy nadmiar wyprowadzeń i mamy dwie odmiany RGB LEDa: wspólna katoda (czyli wspólny minus), oraz wspólna anoda (czyli wspólny plus). Wiele mówiący rysunek:

Podłączenie – pamiętaj o oporniku dla KAŻDEGO LEDa!

Niby oczywiste, ale warto o tym przypominać… Wybieramy rezystory 220 Ohma (bo takie mamy pod ręką) – co nie jest idealne, gdyż każdy LED ma inne napięcie przewodzenia… My to świadomie ignorujemy i dla prostoty (czytaj: wygodny) używamy tych samych oporników. Ale coś za coś – nie będziemy mieć tej samej jasności każdego LEDa (płynie przez nie inny prąd!) a więc biały nie będzie taki biały…

(Może znajdę czas i dopiszę tu kiedyś konkretne wartości oporników dla każdego LEDa)

Pierwszy program

Proponuję zdefiniować trzy zmienne (byte, int – jakkolwiek, oczywiście #define będzie też OK) dla każdej nóżki diody RGB (ja swoje podłączyłem do pinów 11,10 i 9). Dzięki temu będziemy wiedzieli, co właściwie robimy.

byte ledR=11;
byte ledG=10;
byte ledB=9;

void setup(){
  pinMode(ledR, OUTPUT);
  pinMode(ledG OUTPUT);
  pinMode(ledB, OUTPUT);
}

void loop(){
  digitalWrite(ledR, LOW); //włączamy czerowny kolor
  delay(1000);
  digitalWrite(ledR, HIGH); //wyłączamy czerowny kolor
  delay(1000);
  digitalWrite(ledG, LOW); //włączamy zielony kolor
  delay(1000);
  digitalWrite(ledR, HIGH); //wyłączamy zielony kolor
  delay(1000);
  digitalWrite(leB, LOW); //włączamy niebieski kolor
  delay(1000);
  digitalWrite(ledB, HIGH); //wyłączamy neiebieski kolor
  delay(1000);

  //a teraz mieszamy kolory
  digitalWrite(ledB, LOW); //włączamy niebieski kolor
  digitalWrite(ledR, LOW); //włączamy niebieski kolor... mamy FIOLET!
  delay(1000);
  digitalWrite(ledB, HIGH); 
  digitalWrite(ledR, HIGH); 
  delay(1000);
}

Nie pomyslilem się – włączamy LEDy wyłączając napięcie – komendy digitalWrite(ledX, LOW) – bo program dotyczy RGB LEDa ze wspólną anaodą. Napięcie na wspólnej nóżce wynosi 5V dlatego muszę podać napięcie mniejsze (LOW) na drógą nóżkę, aby prąd płynął (nie płynie, jeśli nie ma różnicy napięć! jak woda, która się nie przelewa gdy tern jest płaski).

Mieszanie kolorów ułatwia poniższa grafika:

Warto trochę pobawić się w rozbudowę programu i uzyskać ciekawe kolorki… to na prawdę fajne!

Drugi program – mieszanie z „czułością” 😉

Pamiętamy działanie cyfrowych pinów PWM? Są one oznaczone tyldą (~, „falką”) i w przypadku LED-a umożliwiają płynną zmienę jasności świecenia. Ja od razu do podłączenia wybrałem właśnie piny PWM więc mogę przystąpić do zabawy w zmienę jasności

byte ledR=11;
byte ledG=10;
byte ledB=9;

void setup(){
  pinMode(ledR, OUTPUT);
  pinMode(ledG OUTPUT);
  pinMode(ledB, OUTPUT);
}

void loop(){
  for (i=255; i>0; i--){
     analogWrite(ledR, i); //powoli włączamy czerowny kolor
     delay(10);
  }
  for (i=255; i>0; i--){ 
     analogWrite(ledB, i); //powoli włączamy niebieski kolor 
     delay(10); 
  }   
  delay(1000);
}

Fajna i prosta sprawa, nieprawdaż? Ci, którzy nie pamiętają o co chodzi – zachęcam do uruchomienia Przykłady -> 01 Basics -> Fade z Arduino IDE.

Prąd pobierany z Arduino

Każdy kolor to około 20mA, więc ustawiając światło białe mamy około 60mA prądu. Oznacza to, że nasze Arduino UNO nie pociągnie za dużo takich LEDów (bez kombinowania, ale o tym później).

1 RGB LED = 3 piny PWM !!!

Oczywiście, jeśli chcemy mieć możliwość kontrolowania jansności. To dużo – Arduino UNO ma tylko (aż?) 6 takich pinów. Co więc zrobić, aby świecić 5 RGB LEDami? albo 10? Nie da się? Da się, da. Na kolejnych zajęciach właśnie się tym zajmiemy. Zapraszam! 

Praca domowa

Proponuję poćwiczyć programowanie struktularne – stworzyć funkcję

void rgb(byte red, byte green, byte blue),

która ustawi trzy LEDy na zadane wartości – niech dodatkowo podawane wartości będą z przedziału 0..100, a więc należy dokonać odpowieniej konwersji na liczby z przedziału 0..255. Jeśli tak zrobomy, to wówczas rgb(30,0,0) oznacza lekki kolor czerwony, rgb(0,100,0) to jansy kolor zielony a rgb(77,0,77) jasno-fioletowy. Proszę pobawić się w wirtualnym Arduino!

(c) KG 2018

Rejestr przesuwny 74HC595

Na ostatnich zajęciach nadal zajmowaliśmy się programowaniem wyświetlaczy siedmiosegmentowych. W przypadku podłączania wyświetlacza bezpośrednio do Arduino, zajmujemy aż osiem pinów cyfrowych. To sprawia, że płytka Arduino UNO (wyposażona w 14 wejść/wyjść cyfrowych) może sterować tylko jednym wyświetlaczem. Można co prawda wykorzystać piny analogowe (A0..A5) jako cyfrowe, ale to da możliwość podłączenia jedynie drugiego wyświetlacza. To mało. Jest jednak sposób, aby sterować wieloma wyświetlaczami bez straty wszystkich pinów cyfrowych. Umożliwia nam to rejestr przesuwny 74HC595. Dzięki temu małemu układowi scalonemu mamy możliwość sterowania osmioma wyjściami za pomocą jedynie trzech pinów cyfrowych z Arduino. Bardziej szczegółowe informacje o tym układzie znajdują się w jego specyfikacji technicznej (ang. datasheet).

Podłączanie rejestru przesuwnego

Rejestr przesuwny podłączamy używając schematu pokazanego poniżej. Należy zwrócić uwagę na wyżłobienie po jednej stronie układu, które oznacza górną część.

Wyjście 8 (GND) podłączamy standardowo do pinu o tej samej nazwie na Arduino. Układ wymaga zasilania (to oczywiste) – które podłączamy do pinu 16 (VCC). Rejstr akceptuje zasilanie z przedziału od 2 do 6V – dlatego pin 16 śmiało łączymy z pinem 5V w Arduino UNO. Dodatkowo wyjścia 10 i 16 rejestru łączymy ze sobą (10 to pin odpowiedzialny za czyszczenie stanów rejestru – my to będziemy robić „ręcznie”, więc ustawiamy go w stan wysoki). Kluczowe są wyjście 14, 12 i 11 rejestru, które sterują jego pracą – łączymy je z wybranymi pinami cyfrowymi Arduino (ja wybrałam piny 8,9 i 10 na mojej płytce Arduino). Osiem wyjść rejestru (QA..QH, czyli piny 15, 1..7) podłączamy do kolejnych ledów na wyświetlaczu według tego schematu:

Oczywiście aby układ działał prawidłowo, do wyświetlacza siedmiosegmentowego również należy podłączyć zasilanie i odpowiedni rezystor (poprzednie zajęcia).

Opis pinów i sposób działania rejestru

Do pinów cyfrowych Arduino podłączamy trzy wyjścia rejestru. Są one kluczowe we wzajemnej komunikacji.

  • Pin 11 SRCLK to pin przesuwający wszystkie osiem stanów rejestru – przesuwanie odbywa się zawsze do przodu. Praca rejestru polega właśnie na cyklicznym przesuwania swoich stanów. Aby wykonać przesunięcie ustawiamy SRCLK w stanie LOW, a potem w stanie HIGH – ta sekwencja to komenda „przesuń stany rejestru”.
  • Pin 14 SER to pin ustawiający pierwszy rejest w stanie wysokim (gdy SER= HIGH) lub niskim (gdy SER=LOW).
  • Pin 12 RCLK (latch pin) – ustawienie go w stan niski (LOW) powoduje zablokowanie wyjść rejestru QA..QH, przez co nie widać zmian na tych pinach a tym samym nie widać etapów przejściowych przesuwania (które są wymagane do uzyskania końcowej konfigurajci ośmiu pinów). Ustawienie go w stan wysoki (HIGH) powoduje aktywację pinów QA..QH i to, co jest do nich podłączone – działa tak, jak chcieliśmy. 

Rejestr przesuwny działa w taki sposób, że ustawia (bądź pozostawia je w stanie zerowym) pierwsze wyjście (SER), po czym stan wszystkich wejść przesuwa o jedno miejsce do przodu (SRCLK). Następnie powtarza te czynności tyle razy ile tego zarządamy, aż osiągniemy oczekiwany ciąg zer i jedynek.  Wynika z tego, że zapisując docelową konfigurację wyjść QA..QH w tablicy (gdzie na pierwszym miejscu tablicy powinien znajdować się pierwszy led itd) to odczyt takiej tablicy (i związane z tym ustawianie pinu SER) powinien odbywać się „od tyłu” – aby po ośmiu przesunięciach osiągnąć naszą konfigurację.

Kod programu

Na początku programu definiujemy dwie stałe (dyrektywy #define). Pierwsza stała oznacza liczbę  rejestrów przesuwnych (u nas na razie 1), natomiast druga całkowitą liczbę pinów podłączonych do wyświetlaczy ledowych (liczbę ileScalaków mnożymy razy osiem, ponieważ każdy wyświetlacz ma osiem ledów). Następnie deklarujemy trzy piny cyfrowe łączące Arduino z rejestrem. Należy zwrócić na to uwagę, gdyż w przypadku nieprawidłowego podłączenia, nasz program może zachowywać się nieprzewidywalnie, bądź nie działać. Tablica rejestr odnosi się do wcześniejszej stałej ilePinow, czyli oznacza całkowitą liczbę pinów, którymi będziemy sterować.

#define ileScalakow 1
#define ilePinow ileScalakow * 8
int SER=8; 
int RCLK=9;
int SRCLK=10; 
int rejestr[ilePinow];

Funkcja void czyscRejestr() pozwala na wyczyszczenie tablicy rejestr, aby umożliwić jej ponowne zapełnienie. Robimy to używając pętli for, ustawiając kolejno każdą wartość na zqero (LOW).

Funkcja void zapiszRejestr() to główna funkcja programująca rejest przesuwny – ustawia piny QA..QH w takich stanach, jakie ma tablica rejestr w pamięci Arduino. Ustawienie pinu RCLK na pozycję LOW zamraża stany QA..QH – nie widać przełączania (=przesuwania) stanów rejestru. Pętlę for wykonujemy od końca, od liczby pinów odejmujemy 1, ze względu na numerowanie tablic od 0. Dzięki włączeniu pinu RCLK w stan HIGH zobaczymy dokonane zmiany.

W funkcji void ustawPin(int ktory, int wartosc) zmieniamy tablicę rejestr na pozycji ktory, nadającj jej wartość. Można się jej pozbyć – programując bezpośrednio tablicę rejestr – ale funkcja ta powstała aby ćwiczyć programowanie strukturalne.

void setup(){
  pinMode(SER, OUTPUT);
  pinMode(RCLK, OUTPUT);
  pinMode(SRCLK, OUTPUT);
  czyscRejestr();
  zapiszRejestr();
}
void czyscRejestr(){
  for(int i=0; i<ilePinow; i++)
    rejestr[i]=LOW;
}
void zapiszRejestr(){
  digitalWrite(RCLK, LOW); 
  for(int i=ilePinow-1; i>=0; i--){
    digitalWrite(SRCLK, LOW);
    digitalWrite(SER, rejestr[i]);
    digitalWrite(SRCLK, HIGH); 
  }
  digitalWrite(RCLK, HIGH); 
}
void ustawPin(int ktory, int wartosc){
  rejestr[ktory]=wartosc;
}

W funkcji głównej void loop() tworzymy pętlę, która najpierw ustawi wszystkie piny w pozycję low, abyśmy mogli zobaczyć przyszłe zmiany. Program ten najpierw zapali wszystkie ledy, poczeka pół sekundy, po czym po kolei je zgasi i ponownie zapali po półsekundowej przerwie.

void loop(){
  int i;
  for(i=0;i<ilePinow;i++)
    ustawPin(i, LOW);
    zapiszRejestr();
    delay(500);
   for(i=0;i<ilePinow;i++){
    ustawPin(i, HIGH);
    zapiszRejestr();
    delay(500);
}
}

Nie jest to program wyświetlający cyferki 0,1,2,…9 a jedynie program testujący działanie ośmiu wyjść QA..QH rejestru – naszą pracą domową jest zamiana powyższego kodu aby wyświetlała cyferki.

Podsumowanie

W tym tygodniu poznaliśmy prosty sposób na sterowanie wyświetlaczem siedmiosegmentowym za pomocą jedynie trzech pinów cyfrowych. Stwarza to duże możliwości, ponieważ rejestry przesuwne można ze sobą łączyć – a ciągle do ich sterowania będą potrzebne tylko 3 piny cyfrowe  z Arduino! Ale o tym za tydzień.

Praca domowa

Wykorzystując powyższy kod, wyświetlić cyfry na wyświetlaczu.

(c) Ewelina, 2017

 

Sterowanie wyświetlaczem siedmiosegmentowym. Programowanie strukturalne.

Wyświetlacze siedmiosegmentowe (sevseg).

Na dzisiejszym spotkaniu poznaliśmy jedno z wielu praktycznych zastosowań LEDów. Siedmiosegmentowe wyświetlacze są układami diod emitujących światło w odpowiednim ustawieniu umożliwiającym wyświetlanie cyfr. Wyświetlacze te, nazywane sevseg (ang. seven sevseg

segment display) są wszechobecne w świecie elektroniki i służą reprezentowaniu danych w przystępny (i niedrogi) sposób. Tego typu wyświetlacz może zastąpić droższe ekrany (np. LCD) w przypadku gdy chcemy zobaczyć tylko wartości liczbowe.

Anoda czy katoda?

Najprostsze układy wyświetlaczy siedmiosegmentowych opierają się na wspólnej katodzie lub wspólnej anodzie, co oznacza (w przypadku wspólnej anody), że z aż 10 pinów dwa środkowe będą otrzymywały napięcie, a 8 pozostałych – uziemienia lub na odwrót (w przypadku wspólnej katody).

My pracowaliśmy na wyświetlaczu ze wspólną anodą. Każdy pin pozwala na przepływ prądu przez inny segment (LED) na obszarze wyświetlania. Segmenty mają swoje oznaczenia od a do g (oraz kropka dziesiętna DP – decimal point).
 

Sterowanie wyświetlaczem przy pomocy arduino

Po podłączeniu 8 pinów wyświetlacza do pinów cyfrowych Arduino oraz doprowadzeniu z Arduino zasilania (dodając po drodze opornik) przyszedł czas na programowanie.

Przed dowolnym programem należało przypisać odpowiednie piny w programie.

int start=6;
int end=13;
int i;

„Start” oznacza pierwszy z użytych pinów Arduino, „end” – ostatni. Zmienna „i” jest pomocniczym licznikiem do tablic.

Na próbę stworzyliśmy prosty program pozwalający zapalić wszystkie segmenty wyświetlacza, co pozwoliło przetestować prawidłowe podłączenie wyświetlacza.

void setup(){
  for(i=start;i<=end;i++){
      pinMode(i,OUTPUT);
      digitalWrite(i,1); //0=LOW, 1=HIGH
  }
}

void loop(){
  for(i=start;i<=end;i++)
      digitalWrite(i,1);
  delay(500);
  for(i=start;i<=end;i++)
      digitalWrite(i,0);
  delay(500);
}

W pętlach for widocznych w bloku funkcji void loop() możemy zobaczyć przypisanie stanów wysokich i niskich każdemu z pinów podłączonych do wyświetlacza. Ze względu na to, że jest to wyświetlacz o wspólnej anodzie, to stan niski powoduje zapalenie się lampek, gdyż następuje wtedy przepływ prądu.

Wyświetlanie cyfr

Następnie rozpoczęliśmy tworzenie programu wyświetlającego konkretne cyfry. Stworzyliśmy prosty program w którym wprowadziliśmy własne funkcje – wyświetlające jedynkę (funkcja void jedynka()) , dwójkę (void dwojka()) oraz „czyszczące” wyświetlacz (funkcja void nic()). Budowanie takich funkcji ma ogromny sens – będą to nasz „cegiełki”, które wielokrotnie można później używać – patrz główna funkcja loop() w Arduino. 

int i;
int ledA =8;
int ledB = 9;
int ledC = 11;
int ledD = 12;
int ledE = 13;
int ledF = 7;
int ledG = 6;
int ledDP = 10;
// Kolejność podpięcia diod a - g,DP to właśnie 8,9,11,12,13,7,6,10
void setup(){
  pinMode(ledA,OUTPUT);
  pinMode(ledB,OUTPUT);
  pinMode(ledC,OUTPUT);
  pinMode(ledD,OUTPUT);
  pinMode(ledE,OUTPUT);
  pinMode(ledF,OUTPUT);
  pinMode(ledG,OUTPUT);
  pinMode(ledDP,OUTPUT);
  digitalWrite(ledDP,1);
  nic();
}

void loop(){
  jedynka();
  delay (500);
  dwojka();
  delay (500);
  dwojka();
  delay (500);
  jedynka();
  delay (500);
  nic();
  delay (500);
}

void nic(){
  digitalWrite(ledA,1);
  digitalWrite(ledB,1);
  digitalWrite(ledC,1);
  digitalWrite(ledD,1);
  digitalWrite(ledE,1);
  digitalWrite(ledF,1);
  digitalWrite(ledG,1);
}//nic

void jedynka(){
  digitalWrite(ledA,1);
  digitalWrite(ledB,0);
  digitalWrite(ledC,0);
  digitalWrite(ledD,1);
  digitalWrite(ledE,1);
  digitalWrite(ledF,1);
  digitalWrite(ledG,1);
}//jedynka

void dwojka(){
  digitalWrite(ledA,0);
  digitalWrite(ledB,0);
  digitalWrite(ledC,1);
  digitalWrite(ledD,0);
  digitalWrite(ledE,0);
  digitalWrite(ledF,1);
  digitalWrite(ledG,0);
}//dwojka

W naszym kodzie, są również widoczne zmienne „ledA”, „ledB” itd (linijki 2 – 9), które były tworzone właśnie w nawiązaniu do nazewnictwa widocznym na rysunkach pokazującym budowę wyświetlacza (widocznym na samym początku wpisu). Warto zauważyć, że opłaca się używać nazw zmiennych mających jakieś konkretne znaczenie – tutaj wybraliśmy nazewnictwo zaczerpnięte z budowy sevseg-a. 

Łatwo zauważyć, że powyższy kod jest bardzo powtarzalny i wizualnie zajmuje sporo miejsca, przez co jest też mniej czytelny i nieprofesjonalny. W/w program jest przykładem programowania strukturalnego, czyli hierarchicznego podziału programu na odpowiednie procedury i bloki kodu. Widoczne są utworzone funkcje „nic()”, „jedynka()” i „dwojka()”. Analogicznie należy tworzyć kolejne funkcje generujące kolejne cyfry i wywoływać je w void loop().

Oczywiście na tym nie poprzestaliśmy.

Program z tablicami

Jak widać każda funkcja kolejno zapala odpowiednie segmenty wyświetlacza. Jest to robione „ręcznie”, tj za każdym razem musieliśmy przypisywać każdemu pinowi stan wysoki i niski. Znacznie bardziej optymalną metodą było stworzenie dwuwymiarowej tablicy. Każdy 8-elementowy wiersz tablicy odpowiadał przypisaniu odpowiedniego stanu logicznego danemu segmentowi (jest ich osiem, gdyż poza 7 segmentami jest również 'kropka dziesiętna’ – decimal point). Ten proces pozwolił nam porzucić metodę nazywania każdej diody po kolei (tj. „ledA”, „ledB”…). Na potrzeby tej metody należało dodać tablicę kontrolną z numerami pinów do których podłączone są piny wyświetlacza (linijka 2).

int i;
int led[8]={8,9,11,12,13,7,6,10};
int digits[5][8]={ //na razie definiuje tylko 5 cyfr
// A B C D E F G DP
  {0,0,0,0,0,0,1,0}, //zero
  {1,0,0,1,1,1,1,0}, //wyswietla 1
  {0,0,1,0,0,1,0,0}, //wyswietla 2
  {0,0,0,0,1,1,0,0}, //wyswietla 3
  {1,0,0,1,1,0,0,0}
  }; //...
   //macierz, 4 tablice, kazda z osmioma elementami

void loop(){
  jedynka();
  delay (500);
  dwojka();
  delay (500);
  trojka();
  delay (500);
  czworka();
  delay (500);
  nic();
  delay (500);
}

  void nic(){
    for(i=0;i<8;i++)
      digitalWrite(led[i],digits[0][i]);
  }//nic

  void jedynka(){
    for(i=0;i<8;i++)
      digitalWrite(led[i],digits[1][i]);
  }//jedynka
  
  void dwojka(){
    for(i=0;i<8;i++)
      digitalWrite(led[i],digits[2][i]);
  }//dwojka

Teraz pozostało jedynie przewidzieć który segment ma dostać stan wysoki albo niski, by całość reprezentowała daną liczbę. Kolejne liczby były reprezentowane przez kolejne wiersze w tablicy dwuwymiarowej.

By zrozumieć działanie tej tablicy należy przyjrzeć się działaniu funkcji wywołujących kolejne liczby. Dla przykładu: „jedynka()” zamiast odwoływać się bezpośrednio do każdego pinu przez zmienne ledA, ledB, ledC… (poprzednio), zastąpiliśmy to teraz pętlą „for” przypisującą kolejne stany logiczne (zera lub jedynki) z wiersza tablicy. Każda kolumna tej tablicy odpowiada kolejnej diodzie w wyświetlaczu, czyli w pierwsza kolumna to (poprzednio) ledA (0=świeci, 1=nie świeci), druga to (poprzednio) ledB (0=świeci, 1=nie swieci) itd.

Jeśli wywołujemy jedynkę, pętla „bierze” drugi wiersz w tablicy „digits[]” (uwaga: indeksowanie od zera, więc indeks wiersza=1) i przypisuje diodzie „A” stan wysoki (obszar A nie zaświeci się), diodzie „B” stan niski (dioda zaświeci się). Rysowanie cyfry dwa to branie wiersza numer trzy (indeks wiersza tablicy=2) itd.

Ta operacja zarówno skraca kod, jak i zwiększa jego czytelność i wygodę dodawania kolejnych wyświetlanych liczb lub znaków.

Program wciąż można było ulepszyć.

Ostateczna wersja programu

Optymalizacja kodu dotyczy wywoływania liczb – mamy wiele podobnych funkcji (jedynka(), dwojka() itd). Zamiast tworzyć kolejne funkcje stworzyliśmy jedną funkcję void cyfra(int n), które wywoływały z tablicy dwuwymiarowej kolejne wiersze, czyli kolejne cyfry.

int i;
int led[8]={8,9,11,12,13,7,6,10};
int digits[5][8]={
// A B C D E F G DP
  {0,0,0,0,0,0,1,0}, //zero
  {1,0,0,1,1,1,1,0}, //swieci 1
  {0,0,1,0,0,1,0,0}, //swieci 2
  {0,0,0,0,1,1,0,0}, //swieci 3
  {1,0,0,1,1,0,0,0}
  }; //...
   //macierz, 4 tablice, kazda z osmioma elementami

void setup(){
    for(i=0;i<8;i++)
      pinMode(led[i],OUTPUT);
}

void cyfra(int nr){
  for(i=0;i<8;i++)
    digitalWrite(led[i],digits[nr][i]);
}

void loop(){
  cyfra(1);
  delay (500);
  cyfra(2);
  delay (500);
  cyfra(3);
  delay (500);
  cyfra(4);
  delay (500);
 }

Dodawanie kolejnych liczb stało się niezwykle proste i przejrzyste. Program sprawia wrażenie bardziej profesjonalnego i czytelnego. Uproszczone jest także wyświetlanie. Wystarczy rozszerzyć tablicę o kolejny wiersz i dopisać odpowiednie stany logiczne kolejnym segmentom wyświetlacza.

Podsumowanie

W tym tygodniu poznaliśmy czym jest wyświetlacz 7-segmentowy i w jaki sposób funkcjonuje, odkryliśmy kolejne zastosowania tablic oraz że tablica może być również macierzą, tj. mieć więcej niż jeden wymiar. Ostatecznie zastosowaliśmy metody programowania strukturalnego, które jest obok programowania obiektowego, jedną z najszerzej stosowanych metod w świecie programowania.

Praca domowa

Wykorzystać powyższy kod (np. w wirtualnym arduino) i rozbudować o wczytywanie cyfr z klawiatury (komunikacja szeregowa), czym bawiliśmy się poprzednio.

Do zobaczenia w przyszłym tygodniu!
(c) Maciej 2017

 

Sterowanie ledami za pomocą klawiatury – ASCII i (znowu) tablice

Na ostatnich zajęciach kontynuowaliśmy naukę obsługi ledów przez monitor szeregowy. Tym razem nie ograniczaliśmy się do sterowania wszystkimi ledami jednocześnie, a dążyliśmy do możliwości dowolnego włączania i wyłączania pojedynczych lampek. Podczas tych zajęć uczyliśmy się sprytnego (zaawansowanego?) wykorzystania tablic.

Switch … case

Na zajęciach wykorzystaliśmy układy przygotowane tydzień temu. Podłączyliśmy je w taki sam sposób. Do naszego pierwszego programu wykorzystaliśmy warunek wielokrotnego wyboru, czyli składnię switch … case.

Na początku kodu standardowo  podłączamy każdy z ledów do pinu cyfrowego. Następnie tworzymy pętlę if, która sprawdza, czy są dane (bajty) na porcie szeregowym do odczytania przez Arduino – linia #11. W 12 linii wczytujemy jeden bajt i przypisujemy go do zmiennej znakowej c (omawialiśmy to tydzień temu). W celu umożliwienia sterowania pojedynczymi lampkami za pomocą konkretnych liter w 13 linii tworzymy przełącznik switch zależny właśnie od zmiennej c. W liniach 14-23 tworzymy warunki, czyli przypisujemy do wybranych znaków (u nas: a b c d e A B C D i E)  włączanie lub wyłączanie danego LED-a. Fajne jest to, że do bufora możemy od razu wpisać całe „zdanie” a nie tylko pojedynczy znak. Arduino będzie odczytywać znak-po-znaku (linia 12), a my zobaczymy daną sekwencję włączania/wyłączania LED-ów na płytce. Aby uatrakcyjnić ten fragment etap zabawy z Arduino i LED-ami dodaliśmy specjalny case z wartośćią #, który tworzy przerwę – pauzę (linia 24).

#define MAX 5
int piny[5]={2,3,4,5,6};
int i;
char c;
void setup(){
  for(i=0;i<MAX;i++)
  pinMode(piny[i],OUTPUT);
  Serial.begin(9600);
}
void loop(){
  if(Serial.available()>0){
  c=Serial.read();  
   switch(c){
      case 'a': digitalWrite(piny[0],HIGH);break;
      case 'A': digitalWrite(piny[0],LOW);break;
      case 'b': digitalWrite(piny[1],HIGH);break;
      case 'B': digitalWrite(piny[1],LOW);break;
      case 'c': digitalWrite(piny[2],HIGH);break;
      case 'C': digitalWrite(piny[2],LOW);break;
      case 'd': digitalWrite(piny[3],HIGH);break;
      case 'D': digitalWrite(piny[3],LOW);break;
      case 'e': digitalWrite(piny[4],HIGH);break;
      case 'E': digitalWrite(piny[4],LOW);break;
      case '#': delay(200);break; 
}}}

Właśnie dzięki nowemu symbolowi # (pauza) było możliwe wpisywanie sekwencji (=”zdań”) typu abcde#####A#B#C#D#E (jednoczesne włączenie wszystkich 5-ciu LEDów, odczekanie sekundy a następnie wyłączenie, z krótkimi przerwami, po kolei LED-ów). Inne sekwencje to, np. abcde##E##D##C##B##A##abcde###ABCDE###abcde###ABCDE (włączenie wszystkich, wyłączenie po kolei wszystkich w odwrotnej kolejności a na koniec dwukrotne „mrygnięcie” wszystkimi na raz LED-ami).

Obserwacje/uwagi

Powyższy program jest prosty ale ciągle efektowny – dzięki wprowadzeniu pauzy (#). Jednak z informatycznego punktu widzenia cierpi na następujące problemy:

  • chcąc dodać więcej LED-ów musimy jak „małpa” skopiować linie 14-15 dodając nowe literki do sterowania. Zauważamy jednak pewną regularność w oprogramowaniu każdej literki (linie 14-23 niewiele różnią się od siebie). Może nie ma w tym nic złego, ale czy nie da się tego jakoś lepiej zaprogramować? 
  • jak rozbudować program o możliwość sterowania literkami w ten sposób, że dana literka włącza LED-a gdy był on wyłączony, a wyłącza gdy był on włączony? Jak na razie do włączania używamy małych liter a do wyłączania dużych – to chyba zbyteczna rozrzutność.

Zaczynamy od rozwiązania pierwszego problemu i przechodzimy do wykorzystania tablic. Tablice pojawiają się tu w sposób naturalny – przyglądając się liniom 14-23 zauważamy, że włączamy/wyłaczamy LED-y podpięte do portów cyfrowych Arduino zapisanych w tablicy piny[0,1,2,3,4]. Przy czym pierwszy LED podłączony jest do portu piny[0], drugi do portu piny[1] i tak dalej. Jak więc dobrać odpowiedni indeks tablicy do konkretnego LED-a?

ASCII

Dobranie indeksu tablicy piny[] będzie bazować na kodowaniu znaków ASCII. Dane wczytywane przez Serial.read() to w rzeczywistości bajty, które możemy interpretować jako literki (typ char) lub jako liczby (typ int). Możemy więc patrzeć na literkę d jak znak 'd’ (typ char) lub jak na kod ASCII wynoszący 100 (liczba całkowita, typ int). Dlaczego liczba 100? Przypatrz się uważnie tablicy kodów ASCII z poprzedniego linku (kolumna DEC) lub tutaj. Kolejna literka po d to e – czyli kod ASCII 101 i tak dalej. Co więcej, możemy odejmować literki od siebie, bo to będzie zrozumiałe jako… odejmowanie liczb całkowitych! Tak więc d-a oznacza 100-97, czyli 3. Jesli więc umówimy się, że pod literką a mamy sterowanie pierwszego LEDa, pod b drugiego i tak dalej – to właśnie różnica wczytanej literki i znaku a da nam dobrze określenie indeksu tablicy dla konkretnego LED-a! Zapisane jest to w linii #6 poniższego kodu:

void loop(){
  if(Serial.available()>0){
    c=Serial.read();
    Serial.print("Wczytałem znak = ");
    Serial.println(c);
    int idx=c-'a';
    Serial.print("indeks =");
    Serial.print(idx);
    if(idx>=0&&idx<5){ //gdy mamy 5 LEDow
      Serial.print("Włączam / wyłączam LED-a nr");
      Serial.print(idx);
      //dalsza część kodu
    }
}

Na małą uwagę zasługuje jeszcze linia #9 – sprawdzenie, czy indeks nie jest większy niż liczba podłączonych LED-ów (oczywiste) oraz czy indeks jest większy od zera. To drugie może nastąpić  gdy, np. omyłkowo wpiszem z klawiatury znak [ (o numerze ASCII 91), więc w wyniku odejmowania mamy nieistnieący element tablicy o indeksie 91-97=-6.

Tablica – zapamiętanie stanów pinów

Drugi problem na naszej liście to zapamiętanie stanów portów cyfrowych Arduino. Chodzi o to, aby po odczytaniu danej literki włączyć LED-a gdy był on w stanie wyłączonym, i wyłączyć – gdy  był on włączony. Arduino nie ma jakiejś specjalnej funkcji do „zapytania się” o aktualny stan portu, dlatego więc musimy zrobić do samodzielnie. Wykorzystamy pamięć operacyjną płytki Arduino, czyli stany portów będziemy zapisywać w zmiennych. Może do tego służyć zmienna typu logicznego bool. Przechowuje ona tylko dwie wartości: 0, czyli fałsz (false), oraz liczbę różną od zera, czyli prawdę (true). Pewnie nie ma nic złego w utworzeniu pięciu takich zmiennych dla naszych pięciu LED-ów, ale gdy podłączymy ich 20? 30? Dlatego ponownie używamy tablice:

bool stan[]={false,false,false,false,false};
void loop(){
  if(Serial.available()>0){
  c=Serial.read();
  int idx=c-'a';
  if(idx>=0&&idx<5)//gdy mamy 5 LEDow
    if(stan[idx]==true){
      digitalWrite(piny[idx],HIGH);
      stan[idx]=false;
    }
    else{
      digitalWrite(piny[idx],LOW);
      stan[idx]=true;
    }
  else//jesli idx rozny od zera to moze... nasza pauza?
  if(c=='#') delay(200);

Na początku (linia #1) wprowadzamy zmienną tablicową stan z informacją o wyłączeniu wszystkich LED-ów (pięć false-ów). Kluczowe są linie #7-14, gdzie sprawdzamy stan portu i jeśli jest on włączony (wartość true) to wyłączamy LED-a i zmieniamy stan na false (linia #9), a gdy jest wyłączony (wartość false – u nas „w przeciwnym przypadku” linia #11) to włączamy LED-a i także zmieniamy stan portu – tym razem na true (linia #13). 

Program ponownie akceptuje całe sekwencje rozkazów („zdania”) a dodatkowo nie potrzebuje już oddzielnej literki dla włączenia (poprzednio mała literka) i wyłączenia (poprzednio duża literka) LED-a. Piszemy więc zdania typu   abcde######edcba##a##a##b##b##c##c##b##b  i obserwujemy płytkę stykową.

Podsumowanie

Wszystko dało się tak prosto zapisać dzięki tablicom oraz sprytnie wyliczonemu indeksowi tablicy (kodowanie ASCII). Jak widać indeks wykorzystaliśmy dwukrotnie – raz w odniesieniu do włączania/wyłączania LED-a (funkcja digitalWrite i LEDy podłączone do portów zapisanych w tablicy piny) a drugi raz do zapisu stanu portu cyffrowego Arduino (tablica stan). Siłę tego programy docenimy wówczas, gdy podłączymy dużo LEDów (np. 20) i jedyne rozbudowanie tego kodu polegać będzie na… zmienie stałej MAX w pierwszej linii programu – a nie dopisywaniu prawie identycznych linii kodu dla każdego nowego LED-a (i jego stanu!).

Proszę przemyśleć dzisiejszą lekcję, bo za tydzień ponownie spotykamy się z tablicami (no i z wyświetlaczem siedmiosegmentowym).

(c) Ewelina & KG

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);
    }
    
    

 

Podstawy: Programowanie strukturalne cz.2 + czujka pola magnetycznego

Kontynuujemy – wyświetlacz 7-segmentowy

Tym razem dopięliśmy swego i wyświetliliśmy wszystkie cyferki 😉 Przy okazji użyliśmy tablic – ba, nawet tablic dwuwymiarowych! Ostro… Znalezione obrazy dla zapytania wyswietlacz 7 segmentowy

Na dodatek stworzyliśmy funkcję z argumentem – jaką cyferkę chcemy wyświetlić.

void cyfra(int nr){
//kod do wyświetlania...
}

void loop(){
  for (int i=0; i<=9; i++){
    cyfra(i);
    delay(500);
  }
}

Czujka pola – SS49E

Poznaliśmy też czujkę pola, działającą w zakresie -1500..+1500 G. Podłączyliśmy ją do woltomierza a Pan Kamil nawet do Arduino. Za tydzień każdy z nas podłączy sobie ten układ 😉

Podstawy: (7-seg.) + programowanie strukturalne cz.1

Podstawy – wyświetlacz 7-segmentowy

Nic nas nie goni, więc możemy poznawać tajniki programowania bez pośpiechu. Dlatego wróciliśmy do zagadnienia LED-ów, ale tym razem bazowaliśmy na całym układzie połączonych ze sobą LED-ów w „kostkę” – dzięki temu można wyświetlać cyfry. Znalezione obrazy dla zapytania wyswietlacz 7 segmentowy

Zabawę z tym układem rozpoczęliśmy od zestawu: płytka stykowa, bateryjka + opornik. Do zrozumienia co jest w środku tej kostki przydatny może być taki oto rysunek:

Znalezione obrazy dla zapytania wyswietlacz 7 segmentowy schemat

który właściwie pokazuje dwie wersje tego układu: ze wspólną katodą i anodą.

Podstawy – programowanie strukturalne

Po sprawdzeniu układu bateryjką na płytce stykowej przeszliśmy do programowania – na Arduino. Właściwie na… wirtualnym Arduino. Utworzyliśmy funkcje pomocnicze wyświetlające cyferki 0,1 i 2, oraz funkcję kasującą „ekran” wyświetlacza. Tworzenie takich funkcji – małych cegiełek, które możemy wielokrotnie wykorzystać – to właśnie programowanie strukturalne. 

//zmienne z informacja, gdzie podlaczylismy kazda z nozek kostki z cyferka
int ledA = 5;
int ledB = 4;
...

void setup(){
  pinMode(ledA, OUTPUT);
  pinMode(ledB, OUTPUT);
  ...
}

void nic(){
  kod do zerowania tego, co na wyświetlaczu
}

void jeden(){
  "rysujemy" jedynke
}

void dwa(){
  "rysujemy" dwojke
}

void loop(){
  nic();
  delay(500);
  jeden();
  delay(500);
  dwa();
  delay(500);
}

Zapraszam za tydzień!