Sunteți pe pagina 1din 636

http://www.robofun.

ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Ce este Arduino ?

Arduino este una dintre cele mai simplu de utilizat platforme cu


microcontroller. Te poti gandi la el ca la un minicalculator (are puterea de calcul
a unui computer obisnuit de acum 15 ani), fiind capabil sa culeaga informatii
din mediu si sa reactioneze la acestea.
In jurul lui Arduino exista un ecosistem de dispozitive extrem de bine
dezvoltat. Orice fel de informatie ti-ai dori sa culegi din mediu, orice fel de
conexiuni cu alte sisteme ai avea nevoie, exista o sansa foarte mare sa gasesti
un dispozitiv pentru Arduino capabil sa iti ofere ceea ce ai nevoie.
Astfel, daca discutam despre preluarea de informatii din mediu, mai jos
sunt doar cateva exemple de senzori : senzori ce determina nivelul de alcool in
aerul respirat, senzor de incediu, gaz GPL, monoxid de carbon, acceleratii ale
dispozitivelor in miscare, curent consumat de diverse dispozitive casnice, forta
de apasare, gradul de rotire, cartele RFID, distante, nivel de iluminare, directia
nordului, prezenta umana, sunet, temperatura, umiditate, presiune atmosferica
sau video. Daca ne referim la posibilitatea de a ne conecta cu alte sisteme,
exista placi de retea Ethernet pentru Arduino capabile sa comunice informatii
prin Internet, dispozitive capabile sa transmita date prin conexiune radio, placi
de retea WIFI, dispozitive GSM pentru Arduino (capabile sa trimita /
receptioneze SMS-uri, sa initieze apeluri de voce sau sa trimita date prin
reteaua 3G) sau conectori Bluetooth pentru conectarea Arduino cu telefonul
mobil sau laptop. In zona mecanica, exista motoare de curent continuu
(utilizate pentru robotica), motoare pas cu pas (utilizate de obicei in zona
industriala) sau servomotoare, controlate foarte exact. Pentru afisarea
informatiilor preluate, exista ecrane LCD pentru Arduino, incepand cu cele mai
simple (LCD text cu 16 caractere) pana la ecran LCD grafice. In prima parte a
acestui curs vom dezvolta integrarea Arduino cu fiecare dintre dispozitivele pe
care le-am amintit mai sus (si alte cateva in plus). In cea de-a doua parte a
cursului vom prezenta pe larg o serie de proiecte interesante realizate prin
combinarea Arduino cu unul sau mai multe dispozitive dintre cele enumerate
mai devreme.
Pentru a-ti face o idee despre ceea ce se poate face cu Arduino, in
continuare iti prezint cateva exemple de proiecte care se pot realiza cu Arduino
(proiecte pe care le vom detalia pe larg in cea de-a doua parte a cursului) :
– senzor de alcool conectat la Arduino, Arduino conectat la PC; atunci cand
nivelul de alcool in aerul expirat depaseste un anumit nivel prestabilit,
computerul iti da un warning cand incerci sa postezi lucruri pe Facebook. Aici
poti gasi un articol cu mai multe poze despre acest proiect.
– robot autonom care ocoleste obstacole.
Cateva exemple de filme cu roboti care fac acest lucru :

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

– http://www.youtube.com/watch?v=Xk3-HZpSm2U – robot care


parcheaza singur
– http://www.youtube.com/watch?v=4nMNOugxf3I – masina de taiat
iarba (autonoma)
– http://www.youtube.com/watch?v=X5nqCcMxGBs – robot cu
recunoastere video a obstacolelor
– http://www.youtube.com/watch?v=6b4ZZQkcNEo – robot dezvoltat
de armata americana
– http://www.youtube.com/watch?v=cNZPRsrwumQ – un alt robot
dezvoltat de armata americana

– robot controlat prin Bluetooth folosind telefonul mobil sau laptop-ul


– aici poti gasi mai multe exemple de filme cu un astfel de robot
http://www.robofun.ro/magician-robot-arduino-driver-bluetooth

– dispozitiv pentru pictat oua ("the EggBot").


– http://www.youtube.com/watch?v=ZC-VTRjaHk0

– Arduino + senzor temperatura + senzor umiditate + senzor presiune


atmosferica + placa de retea Ethernet care transmite datele de mediu pe
Google Docs, la fiecare 10 secunde.

– mana robotica, bazata pe o manusa cu senzori de indoire si servomotoare.


– aici gasesti un film cu acest gen de mana -
http://www.tehnorama.ro/animatronic-hand

– Quadcopter-e
– aici gasest un film cu mai multe quad-uri care zboara in formatie -
http://www.youtube.com/watch?v=YQIMGV5vtd4

– OpenEnergyMonitor, sistem bazat pe Arduino care monitorizeaza energia


electrica consumata in casa.
– prastie reala (din lemn) combinata cu Arduino, un accelerometru si Bluetooth,
pentru jucat Angry Birds pe PC.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

– acces bazat pe cartele RFID + notificari prin Twitter.


In cazul Arduino, totul este foarte simplu de utilizat. Ai nevoie de circa 5
minute ca sa iti instalezi mediul de dezvoltare si sa scrii primul tau program pe
Arduino. Nu este necesar sa lipesti fire, tot ce ai nevoie este un port USB liber.

Instalare Drivere Arduino

Primul lucru pe care trebuie sa il faci inainte de a putea programa placa


Arduino, este sa ii instalezi driver-ele pe PC. Daca rulezi Linux sau MAC, ai
scapat, nu ai nevoie de driver-e. Daca insa rulezi Window, va trebui instalezi si
drivere-le, ca pentru orice alt dispozitiv hardware. Driver-ele sunt disponibile in
mediul de dezvoltare, pe care il vei descarca de la adresa
http://arduino.cc/en/Main/Software . Descarca arhiva .zip, si dezarhiveaz-o intr-
un director la alegerea ta. Conecteaza apoi placa Arduino la portul USB. PC-ul
va detecta ca ai un nou dispozitiv, si iti va cere sa instalezi drivere pentru el.
Alege optiunea de instalare prin care ii spui Windows ca ai tu drivere, si ii ceri
sa nu se conecteze la Internet pentru a cauta in mod automat. Selecteaza
directorul "drivers" din directorul unde ai dezarhivat arhiva .zip de la pasul
precedent (NU directorul "FTDI Drivers" !). Procesul continua apoi cu "Next". In
final, daca deschizi Device Manager, in sectiunea "Ports (COM & LPT)" ar trebui
sa vezi o intrare numita "Arduino UNO".
Aici - http://arduino.cc/en/Guide/Windows - gasesti un ghid detaliat, cu
screenshot-uri, referitor la instalarea driver-elor pentru Arduino.

Arduino IDE, Program Arduino, Upload

Dupa ce ai instalat drivere-ele, urmatorul pas este sa iti programezi placa


Arduino. Ruleaza programul "arduino", din mediul de dezvoltare pe care tocmai
l-ai descarcat la pasul precedent (vezi screenshot-ul de mai jos). Arduino se
conecteaza la PC prin intermediul unui port serial. Primul pas pe care il ai de
facut este sa determini acest port. Cea mai simpla cale este de conectezi placa,
astepti circa 30 de secunde – 1 minut, ca sa fii sigur ca a fost detectata de PC,
iar apoi deschizi meniul "Tools -> Serial Port". Ar trebui sa vezi una sau mai
multe intrari. Memoreaza-le (sau scrie-le pe o foaie de hartie / fa un
screenshot). Deconecteaza placa Arduino din portul USB (scoate cablul din PC).
Deschide din nou meniul "Tools -> Serial Port". Acel port care a disparut este
portul asociat placii Arduino. Conecteaza din nou placa Arduino la PC, asteapta
sa fie recunoscuta de PC, si apoi selecteaza portul respectiv din meniul "Tools
-> Serial Port".
Urmatorul pas este selectarea tipului de placa cu care lucrezi. Din meniul
"Tools -> Board", selecteaza tipul de placa cu care lucrezi (Arduino Uno,

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Leonardo, Mega, etc).

Anatomia unui program Arduino

Orice program Arduino are doua sectiuni. Sectiunea "setup", care este
rulata doar o singura data, atunci cand placa este alimentata (sau este apasat
butonul "Reset"), si sectiunea "loop", care este rulata in ciclu, atat timp cat este
alimentata placa. Sa luam un exemplu.

void setup() {
//codul scris aici ruleaza o singura data
}
void loop() {
//codul scris aici ruleaza tot timpul
}

Astfel, in rutina "setup" vom pune de obicei cod de initializare, iar in


rutina "loop" vom scrie partea principala a programului nostru.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino Blink

Pentru cel de-al doilea exemplu Arduino, vom folosi un led montat din
fabricatie pe placa. Placa Arduino are din constructie un led conectat la pinul
digital 13. Acest led se aprinde atunci cand pinul 13 digital este pus in HIGH
(din programul scris pe Arduino) se stinge atunci cand pinul 13 este pus in
LOW.
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}

Daca urci acest program pe placa Arduino si urmaresti led-ul conectat la


pinul 13 vei observa ca el clipeste o data pe secunda. Sa analizam un pic
programul de mai sus. In sectiunea "setup" avem o singura instructiune, care
declara ca pinul 13 digital va fi folosit in continuare pentru a controla un
dispozitiv (daca am fi vrut sa citim informatie din mediul – sa atasam un senzor
la el – am fi scris "pinMode(13, INPUT)"). Aceasta instructiune se executa o
singura data. Urmeaza sectiunea "loop", care aprinde led-ul conectat la pinul
13 ("digitalWrite(13, HIGH)"), asteapta o secunda, il stinge si iarasi asteapta o
secunda. Asa cum am spus mai sus, instructiunile din sectiunea "loop" se
executa ciclic, astfel ca imediat dupa ce s-a terminat un ciclu, led-ul iarasi se
aprinde, apoi iarasi se stinge si tot asa pana cand taiem alimentarea placii.
Exemplul urmator este extrem de similar cu acesta, doar ca in locul led-ului
montat din fabrica pe placa Arduino vom utiliza un led fizic conectat la pinul 13
al placii.

Led Brick, ON/OFF

Un led brick reprezinta cea mai simpla posibilitate de a genera un semnal


luminos folosind Arduino. Un led brick necesita un port digital liber pentru a fi
controlat de catre Arduino.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino GND GND Led


Arduino Digital 13 IN Led

void setup() {
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}

Rutina setup, care se executa exact o singura data cand Arduino este
alimentat, declara pinul digital 13 (cel la care am conectat led-ul) ca fiind un
pin de iesire (in sensul ca va controla un dispozitiv extern conectat la Arduino,
si nu va citi o informatie digitala din mediu).
Rutina loop, care se executa atata timp cat Arduino este alimentat,
aprinde led-ul ridicand pinul 13 in HIGH (mai exact, face ca tensiunea pinului sa
fie 5 V), apoi asteapta o secunda, stinge led-ul (tensiunea pinului devine 0 V) si
apoi iarasi asteapta o secunda.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

De ce nu merge ?
–sigur ai conectat corect firele ?
–sigur programul s-a incarcat pe Arduino (ai vazut mesajul "Done Uploading" ) ?
–daca scoti firul de conectare din pinul 13 (marcat pe led cu "IN") si il muti in
pinul VCC, se aprinde led-ul ? (daca nu, atunci led-ul probabil este defect)

Aceasta a fost lectia 1. In final, as vrea sa te rog sa ne oferi feedback


asupra acestei lectii, pentru a ne permite sa le facem mai bune pe
urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe


care il poti accesa dand click aici. Sondajul este complet anonim.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Led Brick, intensitate variabila

In prima lectie am vazut cum putem aprinde si stinge un led. In acest exemplu vom folosi
acelasi led, dar il vom aprinde variabil. Chiar daca Arduino nu poate scoate tensiune variabila pe
porturile digitale (scoate ori 5V ori 0V), exista o posibilitate de a genera un semnal de putere variabila
pe unul dintre porturile sale. Acest lucru este posibil prin generarea unui semnal dreptunghiular, care se
plimba periodic intre 0V si 5V, foarte rapid. In functie de cat timp sta in 5V si cat timp sta in 0V,
puterea semnalului variaza. Numele acestui gen de semnal este "PWM". Vom detalia intr-o lectie
viitoare acest tip de semnal, deocamdata este suficient sa stim ca exista si ca ii putem controla puterea
prin variatia raportului intre timpul cat sta in 1 si cat sta in 0.
Este interesant de remarcat faptul ca doar 6 din cei 13 pini ai Arduino UNO sunt capabili sa
genereze semnal PWM (pinii 3, 5, 6, 9, 10 si 11).
Pentru cazul Arduino Mega, avem 15 pini PWM (de la 2 la 13 si de la 44 la 46).

void setup() {
pinMode(11, OUTPUT);
}
void loop() {
for (int i = 0; i < 255; i++){
analogWrite(11, i);
delay(50);
}
for (int i = 255; i > 0; i--){
analogWrite(11, i);
delay(50);
}
}

Rutina setup, care se executa exact o singura data cand Arduino este alimentat, declara pinul
digital 11 (cel la care am conectat led-ul) ca fiind un pin de iesire.
In rutina loop este interesanta instructiunea analogWrite, care defineste puterea semnalului
PWM de iesire. Ca parametri, instructiunea analogWrite primeste pinul (11, in cazul nostru), si puterea
semnalului (variabila, de la 0 la 255). Aceasta instructiune este apelata intr-un ciclu for, care modifica
valoarea variabilei i intre 0 si 255. Efectul va fi ca led-ul se va aprinde gradat pana la maxim, iar apoi se
va stinge treptat.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino GND GND Led


Arduino Digital 11 IN Led

De ce nu merge ?
–sigur ai conectat corect firele ?
–sigur programul s-a incarcat pe Arduino (ai vazut mesajul "Done Uploading" ?)
–daca scoti firul de conectare din pinul 13 (marcat pe led cu "IN") si il muti in pinul VCC, se aprinde
led-ul ? (daca nu, atunci led-ul probabil este defect)

Breadboard

Un breadboard este un dispozitiv care permite conectarea extrem de simpla a componentelor


electronice, fara lipituri. Pentru a conecta dispozitivele se folosesc fire tata-tata (cu pini la ambele
capete), care se introduc in gaurile din breaboard.
Gaurile existente in breaboard sunt conectate intre ele (de obicei pe linie), astfel incat firele
introduse pe aceeasi linie vor fi conectate intre ele. In imaginea de mai jos am marcat cu linie neagra
pinii conectati intre ei (eu am marcat doar pentru primele 3 coloane, dar toate liniile breadboard-ului
sunt conectate intre ele). Un exemplu frecvent de utilizare a breadboard-ului este acela in care dorim sa
conectam simultan mai multe dispozitive brick la Arduino (care are doar un singur pin de 5V, si doar 3
pini de GND). In aceasta situatie, vom conecta folosind fire tata-tata pinul de 5V Arduino la una dintre
liniile breaboard-ului, la alta linie din breadboard vom conecta unul dintre pinii GND, si in acest mod
vom avea disponibile inca patru pini care sunt conectati la 5V (cei care sunt pe aceeasi lini cu cel

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

conectat la 5V), si patru pini conectati la GND (cei care sunt pe aceeasi linie cu GND). Pentru toate
proiectele care urmeaza am considerat ca folosirea unui breadboard se subintelege peste tot pe unde apar
doar fire legate impreuna in schema.
Exista multe tipuri de breadboard, mai mari sau mai mici. Unul dintre cele mai mici
breadboard-uri este cel de aici - http://www.robofun.ro/breadboard/breadboard_mini , care este
suficient pentru situatia in care vrei sa alimentezi mai multe dispozitive folosind acelasi Arduino. Un
breadboard ceva mai mare (necesar pentru atunci cand vrei sa mai adaugi si alte componente pe
breadboard, in afara de componente brick) este acesta –
http://www.robofun.ro/breadboard/breadboard-82x52x10 . Evident, daca si acesta este prea mic pentru
ce ai nevoie, poti oricand inlantui doua sau mai multe breadboard-uri intre ele, cu fire.

Debug Serial

Asa cum spuneam mai devreme, o data ce ai urcat programul pe Arduino, acesta ruleaza pe
procesorul Arduino, si nu pe PC. La fel de bine poti deconecta complet Arduino de la calculator si sa il
alimentezi cu o baterie, programul va continua sa ruleze. Sunt situatii (si nu putine! ) cand rezultatele
rularii programului sunt cu totul altele decat iti doresti tu, si atunci iti doresti sa ai acces in interiorul
Arduino ca sa poti vedea ce se intampla acolo. Din fericire, exista si o alta solutie, ceva mai simpla.
Cablul USB de conectare la calculator, pe langa alimentarea Arduino, poate transmite si date catre PC
sau de la PC catre Arduino. Acest lucru este extrem de util pentru a vizualiza pe PC valorile din
programul care ruleaza pe Arduino.
De exemplu, sa spunem ca avem un senzor de lumina conectat la Arduino si vrem sa aprindem
un led atunci cand nivelul de iluminare scade sub o anumita valoare. Am scris programul, l-am urcat pe
Arduino, dar cand testam, lucrurile nu functioneaza corect. Ne-am dori sa vedem ce valoare citeste
senzorul de lumina, ca sa vedem daca pragul setat de noi in program este corect. Vom face acest lucru
trimitand prin cablul USB valoarea citita de senzorul de lumina si vizualizand aceasta valoare pe PC.

void setup() {
Serial.begin(9600);
}
void loop() {
int lumina = analogRead(0);
Serial.println(lumina);
delay(10);
}

Pentru a rula codul sursa de mai sus nu este necesar sa conectezi un senzor de lumina. Poti sa
urci pur si simplu progamul de mai sus pe Arduino si apoi sa deschizi Serial Monitor (din meniul
"Tools", alegi optiunea "Serial Monitor"). Vei vedea o serie de valori aleatoare afisate pe ecran (citiri ale
portului analogic 0 al Arduino, la care nu este conectat nimic).
Instructiunile interesante din programul de mai sus sunt "Serial.begin(9600)", care initializeaza
o comunicare seriala intre Arduino si PC cu viteza de 9600 de biti pe secunda si
"Serial.println(lumina)", care trimite valoarea variabilei "lumina" catre PC.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Poti utiliza aceasta metoda ori de cate ori vrei sa vezi ce valori au variabilele din programul tau
Arduino.

De ce nu merge ?
–daca in loc sa vezi valori numerice in Serial Monitor, primesti o eroare atunci cand alegi optiunea,
atunci cel mai probabil portul serial selectat de tine nu este cel pe care este conectat Arduino; mergi in
meniul "Tools" -> "Serial Port" si alege o alta optiune. Daca nu ai nici o idee care este optiunea corecta,
atunci deconecteaza Arduino de PC si intra din noul in "Tools "-> "Serial Port". Portul care a disparut
este acel port pe care era conectat Arduino. Reconecteaza acum Arduino, si selecteaza-l pe acesta.
– daca in loc sa vezi valori numerice in Serial Monitor vezi o serie de caractere ciudate care se schimba
continuu, inseamna ca rata de transfer selectata in Serial Monitor nu este aceeasi cu rata de transfer
selectata in codul sursa Arduino. Verifica in dreapta jos a ferestrei Serial Monitor ca valoarea selectata sa
fie 9600 (aceeasi pe care am selectat-o in functia "setup" din codul Arduino – "Serial.begin(9600);").
Buton Brick

Am vazut in exemplele precedente cum putem folosi porturile digitale Arduino pentru a
comanda dispozitive din exterior (led-uri, in exemplele de pana acum). Acum vom vedea cum putem
folosi un port digital Arduino pentru a citi informatie din mediu (starea unui buton).

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino GND GND Buton


Arduino 5V VCC Buton
Arduino Digital 7 OUT Buton

void setup() {
pinMode(7, INPUT);
Serial.begin(9600);
}
void loop() {
int stareButon = digitalRead(7);
Serial.println(stareButon);
delay(10);
}

Primul lucru interesant este faptul ca acum pinul digital 7 (cel la care am conectat un buton)
este setat in mod INPUT (spre deosebire de exemplele precedente, unde era de tip OUTPUT). Asta
pentru ca urmeaza sa il folosim ca sa citim informatie din mediu.
Rutina loop citeste starea butonului (care poate fi 0 sau 1 – apasat sau destins) si afiseaza aceasta
stare in consola seriala. Poti vedea aceasta informatie deschizand Serial Monitor in Arduino IDE.

De ce nu merge ?

–sigur ai conectat corect firele ?


–sigur programul s-a incarcat pe Arduino (ai vazut mesajul "Done Uploading") ?

Senzor Lumina Brick

Dupa ce am comandat led-uri si am citit valori digitale din mediu, senzorul de lumina este
primul exemplu de citire a valorilor analogice din mediu. Un senzor de lumina da o valoare numerica
intre 0 si 1023, valoare proportionala cu nivelul de iluminare din mediul ambiant.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino GND GND Senzor


Arduino 5V VCC Senzor
Arduino Analog 0 OUT Senzor

void setup() {
Serial.begin(9600);
}
void loop() {
int nivelIluminare = analogRead(0);
Serial.println(nivelIluminare);
delay(10);
}

In rutina setup singurul lucru pe care il facem este sa initializam o comunicare seriala cu PC-ul, pe care
o vom folosi ca sa transmitem si sa vizualizam pe PC valorile citite de senzorul de lumina.
Rutina loop citeste valoarea data de senzorul de lumina (conectat la portul serial 0) si afiseaza aceasta
valoare in consola seriala. Poti vedea aceasta informatie deschizand Serial Monitor in Arduino IDE.
Pentru a testa ca lucrurile functioneaza corect, pune degetul peste senzorul de lumina. Vei observa ca
valoarea pe care o vezi in Serial Monitor scade.

De ce nu merge ?

–sigur ai conectat corect firele ?

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

–sigur programul s-a incarcat pe Arduino (ai vazut mesajul "Done Uploading" ) ?

Mini Difuzor

Mini difuzorul este cea mai simpla modalitate de a crea sunete cu Arduino. Utilizarea acestuia
este extrem de simpla. Conectezi firul negru la pinul GND al placii Arduino, iar firul rosu la un pin
PWM digital al placii Arduino. Placa Arduino UNO are 6 astfel de pini (3, 5, 6, 9, 10 si 11), iar placa
Arduino Mega are 15 astfel de pini (de la pinul 2 pana la pinul 13 si de la pinul 44 la pinul 46). Un
semnal de tip PWM este un semnal care se misca foarte rapid intre 5V si 0V, astfel incat membrana
difuzorului este si ea miscata la fel de rapid, generand sunete. Frecventa cu care semnalul se misca intre
5V si 0V determina frecventa sunetului.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino GND Fir Negru Difuzor


Arduino Digital 11 Fir Rosu Difuzor

void setup() {
pinMode(11, OUTPUT);
}

void loop() {
for (int i = 1500; i < 4000; i++) {
tone(11, i);
delay(10);
}
for (int i = 4000; i > 1500; i--) {
tone(11, i);
delay(10);
}
}

Partea interesanta din codul de mai sus este instructiunea tone, care primeste ca parametri pinul la care
este conectat difuzorul (in cazul nostru pinul 11) si frecventa sunetului (in cazul nostru, variabila i).
Variabila i se modifica intre 1500 de Hertzi si 4000 de Hertzi. Efectul obtinut este cel de sirena. Ca sa
opresti sunetul complet, instructiunea este noTone(<pin>); In cazul de mai sus, noTone(11) opreste
complet sunetul.

Senzor Temperatura Brick

Senzorul de temperatura brick este un alt exemplu de senzor care ofera valori analogice care

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

depind de temperatura din mediul ambiant. Din valorile citite de la senzori se obtine valoarea
temperaturii in mediul ambiant in grade Celsius, aplicand o formula matematica simpla, formula
prezentata in codul sursa de mai jos.

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

void loop() {
Serial.println(citesteTempInCelsius(10));
}

float citesteTempInCelsius(int count) {


float temperaturaMediata = 0;
float sumaTemperatura;
for (int i =0; i<10; i++) {
int reading = analogRead(0);
float voltage = reading * 5.0;
voltage /= 1024.0;
float temperatureCelsius = (voltage - 0.5) * 100 ;
sumaTemperatura = sumaTemperatura + temperatureCelsius;
}
return sumaTemperatura / (float)count;
}

La fel ca in exemplele precedente, in rutina setup singurul lucru pe care il facem este sa initializam o
comunicare seriala cu PC-ul, pe care o vom folosi ca sa transmitem si sa vizualizam pe PC valorile citite
de senzorul de temperatura.
Rutina loop nu face altceva decat sa apeleze rutina "citesteTempInCelsius" care calculeaza temperatura
in grade Celsius pe baza valorii citite de la senzor. Pentru a diminua influenta surselor de erori asupra
citirilor, temperatura se calculeaza pe baza a zece citiri succesive, care sunt mediate.
Ca sa testezi ca lucrurile functioneaza corect, pune degetul peste senzorul de temperatura. Vei observa ca
valoarea pe care o vezi in Serial Monitor creste.
De ce nu merge ?

–sigur ai conectat corect firele ?


–sigur programul s-a incarcat pe Arduino (ai vazut mesajul "Done Uploading" ) ?

Senzor Umiditate Brick

Senzorul de umiditate brick este un senzor care ofera o valoare analogica care depind de nivelul
de umiditate din mediul ambiat. Din valoarea citita de la senzor se poate deduce valoarea exacta a
umiditatii (%), dar deducerea formulei matematice este destul de dificila, asa ca in cele ce urmeaza ne
vom multumi sa obtinem un nivel calitativ al nivelului umiditatii (“mai umed”, “mai putin umed”).

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Mai exact vom obtine o valoare care variaza in functie de umiditate exact in acelasi mod tot timpul.
Daca astazi valoarea citita pe senzor este 453, si ieri a fost tot 453, atunci vom putea spune “astazi
umiditatea din aer are acelasi nivel ca si ieri”.
Ca o paranteza, daca ai nevoie de un senzor foarte precis, si care iti ofera direct nivelul umiditatii
din aer, in unitati standard, atunci iti sugerez STH15, un senzor etalonat si extrem de precis -
http://www.robofun.ro/senzor_temperatura_umiditate_sht15.

Arduino GND GND Senzor


Arduino 5V VCC Senzor
Arduino Analog 0 OUT Senzor

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

void loop() {
int nivelUmiditate = analogRead(0);
Serial.println(nivelUmiditate);
delay(50);
}

Codul sursa de mai sus este aproape identic cu cel de la senzorul de lumina, asa ca nu voi insista

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

asupra lui.
Ca sa testezi ca lucrurile functioneaza corect, sufla peste senzor, usor. Vei observa ca valoarea pe
care o vezi in Serial Monitor se modifica, datorita faptului ca respiratia ta contine vapori de apa. Alta
varianta este sa desfaci o sticla de plastic care contine apa pe jumatata, si sa introduci senzorul in prima
jumatate a sticlei (NU in apa, in zona in care sticla este goala).

Aceasta a fost lectia 2. In final, as vrea sa te rog sa ne oferi feedback asupra acestei
lectii, pentru a ne permite sa le facem mai bune pe urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe care il poti
accesa dand click aici.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Semafor, Trei Led-uri Brick

In acest proiect vom folosi un led verde brick, un led galben brick si un led rosu brick pentru a
genera un efect de tip semafor. Pentru alimentarea tuturor celor trei led-uri, vom utiliza un breaboard,
cel despre care am vorbit in lectia precedenta. Conectarea se face exact ca in situatia in care ai folosit un
singur led, doar ca vei folosi breadboard-ul pentru a obtine mai multe puncte GND (daca nu iti este
clar, mai vezi o data sectiunea despre breadboard).

void setup() {
pinMode(13, OUTPUT);
pinMode(12, OUTPUT);
pinMode(11, OUTPUT);
}

void loop() {
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(12, HIGH);
delay(200);
digitalWrite(13, LOW);
digitalWrite(12, LOW);
digitalWrite(11, HIGH);
delay(1000);
digitalWrite(12, HIGH);
delay(200);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
digitalWrite(13, HIGH);
delay(1000);
}

Rutina setup face acelasi lucru ca in exemplul cu un singur led, doar ca acum declara trei pini in
loc de unul.
Rutina loop aprinde initial led-ul verde vreme de o secunda. Apoi aprinde led-ul galben vreme
de 0.2 secunde si apoi stinge led-ul verde si il aprinde pe cel rosu. Dupa o secunda, face exact acelasi
ciclu, dar de data aceasta cu led-ul verde aprins.

De ce nu merge ?
–sigur ai conectat corect firele ?
–sigur programul s-a incarcat pe Arduino (ai vazut mesajul "Done Uploading" ) ?
–daca scoti firul de conectare din pinul 13 (marcat pe led cu "IN") si il muti in pinul VCC, se aprinde
led-ul ? (daca nu, atunci led-ul probabil este defect)

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Lampa de veghe

Sau mai bine spus, led de veghe. Pentru acest proiect ai nevoie de un led brick, un senzor de
lumina brick, si evident, un Arduino. Vom programa Arduino ca ori de cate ori nivelul de iluminare
scade sub o anumita valoare, sa aprinda led-ul si sa il stinga atunci cand nivelul de iluminare creste
iarasi. Daca mai folosesti si o bila de ping-pong in care bagi led-ul brick (si folosesti un led brick
albastru), rezultatul arata chiar excelent.
Pentru conectarea componentelor la Arduino, vezi mai sus sectiunea despre led brick si despre
senzorul de lumina. Probabil ca vei vrea sa folosesti un breadboard pentru a obtine mai multe puncte
VCC si GND.

void setup() {
pinMode(11, OUTPUT);
}

void loop() {
int nivelIluminare = analogRead(0);
if (nivelIluminare < 300) {
digitalWrite(11, HIGH);
} else {
digitalWrite(11, LOW);
}
}

Singurul lucru pe care il face rutina setup este sa declare pinul la care este conecta ledul ca fiind
pin de iesire.
Rutina loop verifica daca nivelul de iluminare a scazut sub un anumit prag predefinit, si daca da,
atunci aprinde led-ul. In caz contrar, il stinge. S-ar putea ca pragul ales de mine sa nu fie bine ales
pentru parametrii din incaperea ta, si atunci led-ul sa stea stins tot timpul. Daca se intampla acest lucru,
cel mai simplu este sa maresti valoarea pragului (cu cat vrei tu), sau sa folosesti debug-ul serial ca sa vezi
exact valoarea pe care o masoara senzorul in camera ta (vezi lectia a doua despre debug).
Daca valoarea prag-ului este bine aleasa, atunci led-ul va sta stins in mod obisnuit. Ca sa testezi
ca se stinge, pune degetul peste senzorul de lumina, iar led-ul se va aprinde.

Buton + LED

Un proiect simplu care aprinde un led atunci cand apesi un buton. Ai nevoie de un led brick, un
buton brick si un Arduino. Proiectul este destul de similar cu cel anterior, doar ca am inlocuit senzorul
de lumina cu butonul.
Pentru conectarea componentelor la Arduino, vezi mai sus sectiunea despre led brick si despre
butonul brick. Probabil ca vei vrea sa folosesti un breadboard pentru a obtine mai multe puncte VCC si
GND.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

void setup() {
pinMode(11, OUTPUT);
pinMode(7, INPUT);
}

void loop() {
int stareButon = digitalRead(7);
if (stareButon == 1) {
digitalWrite(11, HIGH);
} else {
digitalWrite(11, LOW);
}
}

Este interesanta cea de-a doua instructiune din rutina setup, care declara ca pinul 7, cel pe care
este conectat butonul, este un pin de intrare.
Rutina loop verifica starea butonului (folosind digitalRead) si actualizeaza starea led-ului in
consecinta.

In ritmul muzicii : Microfon + Led

O combinatie intre microfonul cu breakout board si mai multe led-uri, si vei obtine ceva in
genul unui afisaj digital sensibil la volumul muzicii. In schema de mai jos am evidentiat doar un singur
led. Tu va trebui sa folosesti patru led-uri si nu doar unul. Celelalte led-uri se vor conecta la pinii 4, 5,
si 6 (digitali).

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

#define PIN_LED1 7
#define PIN_LED2 6
#define PIN_LED3 5
#define PIN_LED4 4

#define PRAG_LED1 100


#define PRAG_LED2 200
#define PRAG_LED3 300
#define PRAG_LED4 500

#define NUMAR_ESANTIOANE_MEDIERE 100

void setup() {
pinMode(PIN_LED1, OUTPUT);
pinMode(PIN_LED2, OUTPUT);
pinMode(PIN_LED3, OUTPUT);

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

pinMode(PIN_LED4, OUTPUT);
}

void loop() {
int intensitateSonora = intensitateSonora();

if (intensitateSonora > PRAG_LED1) {


digitalWrite(PIN_LED1, HIGH);
} else {
digitalWrite(PIN_LED1, LOW);
}
if (intensitateSonora > PRAG_LED2) {
digitalWrite(PIN_LED2, HIGH);
}else {
digitalWrite(PIN_LED1, LOW);
}
if (intensitateSonora > PRAG_LED3) {
digitalWrite(PIN_LED3, HIGH);
}else {
digitalWrite(PIN_LED1, LOW);
}
if (intensitateSonora > PRAG_LED4) {
digitalWrite(PIN_LED4, HIGH);
}else {
digitalWrite(PIN_LED1, LOW);
}
}

int intensitateSonora(){
long intensitate = 0;
for (int i = 0; i < NUMAR_ESANTIOANE_MEDIERE; i++){
intensitate = intensitate + abs(analogRead(0));
}
return intensitate / NUMAR_ESANTIOANE_MEDIERE;
}

Codul de mai sus citeste valoarea mediata a esantioanelor sonore, si in functie de aceasta valoare
aprinde unul sau mai multe led-uri. Tu va trebui sa modifici valorile
"NUMAR_ESANTIOANE_MEDIERE" si pragurile de declansare ale led-urilor pana cand obtii un
rezultat care iti place.
Pentru un efect mai spectaculos, ar fi interesant sa pui fiecare led intr-o minge de ping-pong, ca
in proiectul "Termometru : Senzor Temperatura Brick + LED-uri".

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Termometru : Senzor Temperatura Brick + LED-uri

Cu trei led-uri brick de culori diferite, introduse in bile de ping-pong, impreuna cu un senzor de
temperatura brick si un Arduino UNO poti crea un termometru deosebit si elegant.

Ai nevoie de trei led-uri brick (ideal verde, galben si rosu), trei mingi de ping-pong, un senzor
de temperatura brick si un Arduino UNO. La baza fiecarei mingi de ping-pong creezi o gaura folosind
un cutter, astfel incat sa poti introduce led-ul brick in interiorul mingii. Mai departe, Arduino citeste
temperatura din camera, si aprinde gradat led-urile din interiorul mingilor de ping-pong.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

#define NIVEL1 15
#define NIVEL2 25
#define NIVEL3 38
void setup() {
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
}
void loop() {
int temperatura = citesteTempInCelsius();
int intensitateVerde = 255 – 10 * (NIVEL1 – temperatura);
int intensitateGalben = 255 – 10 * (NIVEL2 – temperatura);
int intensitateRosu = 255 – 10 * (NIVEL3 – temperatura);
if (temperatura < NIVEL1) {
analogWrite(3, intensitateVerde);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
} else if (temperatura < NIVEL2) {
analogWrite(3, intensitateVerde);
analogWrite(5, intensitateGalben);
digitalWrite(6, LOW);
} else if (temperatura < NIVEL3) {
analogWrite(3, intensitateVerde);
analogWrite(5, intensitateGalben);
analogWrite(6, intensitateRosu);
}
}

float citesteTempInCelsius() {
float temperaturaMediata = 0;
float sumaTemperatura;
for (int i =0; i<10; i++) {
int reading = analogRead(0);
float voltage = reading * 5.0;
voltage /= 1024.0;
float temperatureCelsius = (voltage - 0.5) * 100 ;
sumaTemperatura = sumaTemperatura + temperatureCelsius;
}
return sumaTemperatura / (float)count;
}

Codul de mai sus imparte valorile posibile ale senzorului de temperatura in trei intervale (sub 15
grade, intre 15 si 25 de grade si peste 25 de grade). In primul interval, se aprinde doar led-ul verde, cu
cat temperatura este mai aproape de 15 grade, cu atat led-ul se aprinde mai puternic. Intre 15 si 25 de
grade led-ul verde este aprins la intensitate maxima, iar led-ul galben se aprinde progresiv. Peste 25 de
grade, led-ul verde si cel galben sunt aprinse complet, iar led-ul rosu se aprinde progresiv, pana la 38 de
grade, cand toate led-urile sunt aprinse la intensitate maxima..

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Aceasta a fost lectia 3. In final, as vrea sa te rog sa ne oferi feedback asupra acestei
lectii, pentru a ne permite sa le facem mai bune pe urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe care il poti
accesa dand click aici.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Despre Shield-uri Arduino

Shield-urile Arduino reprezinta o modalitate foarte simpla de a extinde functionalitatile


Arduino. Orice shield Arduino este standard, in sensul ca pinii acestuia se potrivesc perfect peste pinii
placii Arduino. In plus, in marea majoritate a cazurilor, pinii shield-ului sunt prelungiti in sus cu
conectori de tip mama. Acesti pini, fiind infipti in pinii Arduino, ii prelungesc practic in sus pe acestia.
Astfel, daca am pus un shield peste Arduino si vrem sa conectam un senzor la pinul A0 al Arduino,
atunci vom conecta senzorul la pinul A0 al shield-ului, si totul va functiona exact ca si cum l-am fi
infipt in pinul A0 al Arduino.
Fiecare shield utilizeaza anumiti pini pentru a se conecta cu Arduino. Astfel, spre exemplu,
shield-ul cu LCD 16X2 utilizeaza pinii 7, 6, 5, 4, 3, 2 iar shield-ul Wifly foloseste pinii 10, 11, 12, 13.
Acesti pini nu mai pot fi folositi in acelasi timp cu shield-ul. Astfel, daca avem un senzor care se
conecteaza pe pinul 3 la Arduino, si noi folosim deja shield-ul cu L298 (care foloseste pinii 3, 5, 6 si 9),
atunci nu vom putea conecta senzorul in acelasi timp cu shield-ul L298. Mai mult, se poate intampla
chiar sa avem doua shield-uri care utilizeaza aceeasi pini (sau o parte dintre pini sunt aceeasi). In aceasta
situatie, de cele mai multe ori se poate aplica o solutie clasica. Anume, pinii shield-ului care intra in
Arduino se indoaie un pic in afara, astfel incat sa nu mai intre in Arduino, ci sa iasa in afara. Apoi, acesti
pini se conecteaza pe deasupra cu pini tata-tata cu alti pini Arduino nefolositi. De la caz la caz, s-ar
putea sa fie nevoie sa faci modificari in libraria asociata senzorului, sau sa modifici doar codul sursa din
programul tau, astfel incat pinii pe care i-ai mutat in alta parte sa fie actualizati si in cod.
Mai jos sunt doua exemple de shield-uri montate peste Arduino.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Modalitati de Comunicare Intre Arduino si Componente

Mai departe vom trece in revista cateva modalitati prin care Arduino se conecteaza cu celelalte
componente (senzori, shield-uri, etc). S-ar putea ca atunci cand vom ajunge la comunicarea seriala, SPI
si I2C lucrurile sa ti se para un pic complicate si dificil de inteles, pentru ca inca nu am introdus nici un
exemplu de dispozitiv care sa comunice astfel. Dupa ce vei vedea mai multe dispozitive explicate in
detaliu in lectiile viitoare, vei intelege mai usor despre ce este vorba.

Citire Date pe Porturile Analogice sau Digitale

Anumite componente se conecteaza direct la porturile digitale sau analogice ale Arduino si astfel
primesc comenzi sau comunica date catre acesta. Astfel, un led se conecteaza la un pin digital si atunci
cand pinul este in HIGH, led-ul se aprinde. Un senzor de lumina se conecteaza la un pin analogic si
folosind "analogRead(<pin>)" obtii valoarea data de senzor. Un buton se conecteaza la un pin digital si
"digitalRead(<pin>)" intoarce 1 daca butonul este apasat si 0 altfel. Un shield driver de motoare cu
L298 sau un LCD se conecteaza la mai multi pini digitali (4, respectiv 7) si primeste comenzi de la

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino prin intermediul acestora.


Voi reaminti ca ori de cate ori avem nevoie sa folosim un pin digital ca sa comandam un
dispozitiv, este necesar sa declaram acest pin ca fiind de tip OUTPUT ("pinMode(<pin>, OUTPUT").
Altfel, nu se va intampla absolut nimic atunci cand trecem pinul in HIGH sau in LOW.
Merita sa insistam un pic si asupra citirii datelor pe porturile analogice. Un senzor, la nivel
electric, da pe iesire o tensiune electrica. Este absolut necesar ca aceasta tensiune sa fie intre 0 si 5 V.
Orice senzor special creat pentru Arduino va respecta deja aceasta regula. Mai departe, aceasta tensiune
este preluata de o componenta specializata a lui Arduino, numita "convertorul analog-digital". Aceasta
componenta ofera la iesirea sa un numar intre 0 si 1023, in functie de nivelul de tensiune de la intrare.
Asftel, folosind Arduino, putem citi senzori analogici cu o precizie de exact 1024 de nivele distincte. De
exemplu, folosind senzorul de lumina, vom putea citi cu Arduino exact 1024 de nivele distincte de
iluminare ale mediului ambiant. Daca avem nevoie de o precizie mai buna, atunci va trebui sa trecem la
alt tip de senzori (cel mai probabil, senzori pe I2C).

Comunicare Seriala

Comunicarea seriala este o comunicare de tip digital, in sensul ca pe fir se transmit biti (ca la fel
cum se intampla intr-o retea de calculatoare, doar ca folosind un protocol mult simplificat). Aceasta
comunicare seriala se intampla intotdeauna intre Arduino si calculator, atunci cand Arduino este
programat. O comunicare seriala se intampla intotdeauna la o anumita rata de transfer, care determina
viteza cu care se transmit bitii pe fir. Rate comune de transfer sunt 9600, 19200, 57600, 115200.

Software Serial

SoftwareSerial este tot o modalitate de comunicare seriala, doar ca in loc de a utiliza pinii RX si
TX ai microcontroller-ului (care sunt dedicati pentru o astfel de comunicare), utilizam o librarie
software care emuleaza comunicarea folosind (aproape) oricare doi pini digitali ai placii Arduino.
Avantajul imediat este faptul ca in acest mod putem conecta placa Arduino cu mult mai multe
dispozitive seriale.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup() {
Serial.begin(9600);
Serial.println("Goodnight moon!");
mySerial.begin(4800);
mySerial.println("Hello, world?");
}

void loop() {
if (mySerial.available()) {
Serial.write(mySerial.read());
}
if (Serial.available()) {
mySerial.write(Serial.read());
}
}

In codul de mai sus am declarat pinii 10 si 11 ca fiind cei doi pini care vor emula comunicarea
seriala. Pinul 10 este pinul RX iar pinul 11 este pinul TX. Mai departe, am declarat rata de transfer a
acestei conexiuni seriale ca fiind 4800 ( mySerial.begin(4800)) (rata de transfer o stim din specificatiile
dispozitivului cu care urmeaza sa ne conectam). In continuare, orice caracter primit peste conexiunea
seriala emulata este scrisa in Serial Monitor, si orice caracter introdus in Serial Monitor este trimis peste
conexiunea seriala emulata software.
Vei intalni des in proiectele de mai departe acest tip de conexiune. Chiar daca in proiectul
respectiv este folosita conexiunea de tip serial standard, vei putea oricand sa o inlocuiesti cu
SoftwareSerial, ca mai sus.

SPI

SPI este o modalitate de a comunica cu dispozitive de tipul master-slave. Un dispozitiv este


master (de obicei Arduino), si celelalte dispozitive sunt slave. In practica, vei gasi de obicei librarii scrise
de altcineva care incapsuleaza deja comunicare cu dispozitivul peste SPI, asa ca nu va trebui sa iti bati
prea mult capul cu amanuntele. Voi prezenta totusi mai jos cateva elemente ale SPI, ca sa recunosti
termenii atunci cand auzi vorbindu-se de ei.
Comunicarea SPI se face folosind patru canale (fire de conexiune) :
MISO – firul prin care dispozitivele slave trimit date catre master.
MOSI – firul prin care dispozitivul master trimite date catre slave.
SCK – firul prin catre este transmis clock-ul (ritmul de comunicatie)
SS (Slave Select) – acest canal este specific SPI, si este interesant. SPI permite conectarea pe
acelasi bus a mai multor dispozitive, fiecare dispozitiv avand atasat un canal Slave Select. Atunci cand
valoarea din acest canal este LOW, dispozitivul slave comunica cu master-ul. Cand valoarea Slave Select
este HIGH, atunci dispozitivul ignora comunicarea SPI. In acest mod, poti conecta pe acelasi canal SPI
oricat de multe dispozitive, cu conditia ca fiecarui dispozitiv sa ii atasezi un canal Slave Select. Un

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

exemplu pe care il vei intalni este comunicarea cu shield-ul Ethernet, si in acelasi timp cu SD card-ul
montat pe shield. Ambele folosesc comunicare SPI. Pinul Slave Select conectat la chip-ul Ethernet este
pinul digital 10 Arduino, iar pinul Slave Select conectat la SD card este pinul digital 4. Astfel, atunci
cand vrei sa comunici Ethernet, vei seta pinul 10 in LOW, si pinul 4 in HIGH (doar chip-ul Ethernet
activ), iar atunci cand vrei sa comunici cu SD card-ul, vei seta pinul 10 in HIGH si pinul 4 in LOW
(doar SD card-ul activ). Daca omiti sa faci acest lucru, comenzile trimise catre chip-ul Ethernet vor fi in
acelasi timp receptionate si procesate si de catre SD card, ceea ce va conduce la o functionare
defectuoasa.
In cazul Arduino UNO, pinii Arduino SPI sunt MISO – pinul digital 12, MOSI – pinul digital
11, SCK – pinul digital 13. Pinul default SS este pinul digital 10. In cazul in care ai mai mult de un
dispozitiv SPI, vei folosi mai multi pini Slave Select, nu doar pinul digital 10, fiecare dispozitiv fiind
conectat cu cate un pin Slave Select distinct.
In cazul Arduino Mega, pinii SPI sunt MISO - pinul digital 50, MOSI – pinul digital 51, SCK
– pinul digital 52, si SS – pinul digital 53.
La modul concret, daca ai doua dispozitive SPI, vei incepe prin a identifica pinii MOSI, MISO,
SCK si SS pentru fiecare dispozitiv. Vei conecta apoi impreuna pinii MOSI ai celor doua dispozitive, si
impreuna cu pinul Arduino MOSI, la fel si pentru MISO si SCK. Pentru pinii SS, vei conecta pinul
primului dispozitiv la un pin digital Arduino, iar pinul celui de-al doilea dispozitiv la un alt pin digital
Arduino.

I2C

Comunicarea I2C este un mod interesant de comunicare, in sensul ca necesita doar doua fire de
comunicare, si permite conectarea a oricat de mult dispozitive (cu adrese diferite). Fiecare dispozitiv
I2C are o adresa (care se poate sau nu modifica). De obicei, vei intalni dispozitive I2C cu adresa fixa (pe
care nu o poti modifica), sau dispozitive la care vei putea alege adresa I2C dintr-o lista de cateva adrese
prestabilite (lucru pe care de obicei il faci prin conectarea unui pin de adresa – marcat de obicei ADDR
– la pinul GND, sau VCC, sau SDA, sau SCL).
Ca si in cazul SPI, a intelege modul de comunicare citind datasheet-ul dispozitivului I2C nu
este facil. Primul lucru pe care il fac atunci cand am nevoie sa comunic cu un dispozitiv I2C este sa caut
o librarie deja scrisa pentru dispozitivul respectiv. In acest mod, singurul lucru de care trebuie eu sa tin
cont este adresa dispozitivului. Mai departe, modul concret de comunicare este realizat in intregime de
librarie, eu avand acces doar la informatia utila.
In cazul Arduino UNO, pinii I2C pentru Arduino sunt pinul analogic 4 (care este pinul SDA),
si pinul analogic 5 (care este pinul SCL). Pentru Arduino Mega, pinul digital 20 este pinul SDA si
pinul digital 21 este pinul SCL. In cazul Arduino Leonardo, cei doi pini SDA si SCL sunt distincti,
marcati ca atare pe placa. Pentru a folosi un dispozitiv I2C, vei conecta pinul SDA al dispozitivului cu
pinul SDA al Arduino, pinul SCL al dispozitivului cu pinul SCL al Arduino. In plus, in functie de
dispozitiv, s-ar putea sa fie necesar sa conectezi si pinul de adresa la GND sau la VCC (in cele mai
multe cazuri, pinul de adresa este deja conectat, dar nu intotdeauna).
Un exemplu de senzor I2C este senzorul de temperatura I2C. Pinul de adresa este marcat pe
placa cu “ADDR0”. Dispozitivul acest pin se poate conecta la pinul GND (si atunci dispozitivul va avea

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

adresa “0x48”), poate fi conectat la VCC (si atunci dispozitivul va avea adresa “0x49”, poate fi conectat
la pinul SDA (si atunci dispozitivul va avea adresa “0x4A”), sau poate fi conectat la pinul SCL (si atunci
dispozitivul va avea adresa “0x4C”). In acest mod, poti conecta pana la patru senzori TMP102 la placa
Arduino.
Daca esti curios, un exemplu de cod care comunica pe I2C poti gasi aici :
http://www.robofun.ro/senzor_temperatura_tmp102

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Aceasta a fost lectia 4. In final, as vrea sa te rog sa ne oferi feedback asupra acestei
lectii, pentru a ne permite sa le facem mai bune pe urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe care il poti
accesa dand click aici.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Senzori Acceleratie

Senzorii de acceleratie detecteaza (destul de evident :), acceleratia. Se pot folosi pentru masurarea
acceleratiilor instantanee pe care le inregistreaza un element in miscare, sau pentru a detecta directia
verticala (pe baza acceleratiei gravitationale g, care are intotdeauna directia verticala). Orice smart-
phone are deja incorporat un accelerometru (pe langa multe alte dispozitive), care accelerometru este
folosit pentru rotirea automata a ecranului atunci cand intorci telefonul. Atunci cand rotesti telefonul,
acceleratia gravitationala a Pamantului (care intotdeauna are directia verticala) isi schimba orientarea in
raport cu telefonul (pentru ca telefonul se roteste), si astfel pozitia telefonului este detectata.
De asemenea, un accelerometru este utilizat pentru a sesiza miscarea. De exemplu, in cazul unui
joystick WII, accelerometrul pe 3 axe din interiorul acestuia simte miscarea mainii si misca jucatorul de
pe ecran in consecinta (ca o mica paranteza, un pic mai tarziu vom vedea cum putem conecta direct la
Arduino joystick-ul WII).
Din punct de vedere al conectarii la Arduino, exista doua tipuri de accelerometre : cu conectare
analogica si cu conectare I2C. Cele cu conectare analogica folosesc pinii analogici ai Arduino (cate un
pin pentru fiecare axa). Cele cu conectare I2C folosesc cei doi pini I2C (SDA si SCL, care in cazul
Arduino sunt conectati la pinii analogici 4 si 5). Ca principiu general, accelerometrele digitale (cu
conectare pe I2C) sunt mai exacte si mai putin afectate de zgomot decat cele analogice. Accelerometrele
cu conectare analogica sunt insa cu mult mai simplu de folosit.
Un alt parametru al unui accelerometru este scala acestuia. Spre exemplu, ADXL335 poate
masura de la -3g pana la 3g (are o scala de 6g). Altele, cum ar fi LIS331, au o scala selectabila din
software (maxim -24g pana la 24g). Ca regula, cu cat scala este mai mica, cu atat precizia este mai mare.
In functie de proiect, vei vrea sa-ti alegi un accelerometru cu o scala suficient de mare incat sa poata
masura intreaga gama de acceleratii pe care le vei intalni, dar nu cu mult mai mare de atat, ca sa iti
pastrezi totusi precizia.
Banda unui accelerometru ("bandwidth") determina de cate ori pe secunda poate fi citit
senzorul de catre Arduino. Un accelerometru cu o banda de 100 Hz poate fi citit de 100 de ori pe
secunda.
Din punct de vedere al numarului de axe citite, exista accelerometre cu o axa, cu doua, sau
cu trei axe. Cele cu trei axe sunt cel mai des intalnite.

ADXL335

ADXL335 este unul dintre cele mai simplu de utilizat accelerometre pe 3 axe. Este un
accelerometru analogic, ceea ce inseamna ca informatia este transmisa catre Arduino sub forma unui
semnal analogic a carui tensiune variaza direct proportional cu acceleratia. ADXL335 poate masura
acceleratii in gama +/- 3 g (adica de trei ori mai mult decat acceleratia gravitationala obisnuita).
Conectarea la Arduino este foarte simpla. Se conecteaza pinul VCC al ADXL335 la pinul 3.3 V
Arduino (ADXL335 functioneaza la 3.3V si nu la 5V, cum am intalnit pana acum), se conecteaza pinul
GND al ADXL335 la pinul GND al Arduino, si se conecteaza pinii X, Y si Z ai ADXL335 la trei pini
analogici ai Arduino (sa spunem pinul analogic 0, 1 si 2). In afara acestor pini mai ramane o singura
conexiune de facut – pinul 3.3 al Arduino la pinul AHREF al Arduino - . In acest mod, valorile date pe

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

pinii X, Y si Z de catre ADXL335 sunt raportate la tensiunea maxima de 3.3 V.

Arduino 3.3 V ADXL335 VCC


Arduino GND ADXL335 GND
Arduino Analog0 ADXL335 X
Arduino Analog1 ADXL335 Y
Arduino Analog2 ADXL335 Z
Arduino 3.3 Arduino AREF

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

void loop() {
float xAcc=readAcc(0);
float yAcc=readAcc(1);
float zAcc=readAcc(2);

Serial.print("Acceleratie X: ");

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Serial.print(xAcc,DEC);
Serial.print("Acceleratie Y: ");
Serial.print(yAcc,DEC);
Serial.print("Acceleratie Z: ");
Serial.print(zAcc,DEC);
Serial.println();
delay(50);
}

float readAcc(int port) {


int value=analogRead(port);
int miliVolts=map(value,0,1023,0,3300)-3300/2;
float acc=(float)miliVolts/360;
return acc;
}

Interesant in codul de mai sus este "analogReference(EXTERNAL)", in rutina setup. Acest


lucru seteaza ca referinta de tensiune pentru toate porturile analogice acea tensiune externa pusa pe
pinul AHREF (noi in acest exemplu am pus acolo 3.3 V). Mai departe, valoarea citita de pe portul
analogic (intre 0 si 1023) este procesata pentru a fi transformata intr-o valoare de acceleratie, exprimata
ca multiplu al acceleratiei gravitationale "g".
Ca sa testezi ca functioneaza corect, misca accelerometrul in aer. In functie de orientarea
acestuia in raport cu acceleratia gravitationala (care este intotdeauna verticala), vei obtine valori diferite
pe cele trei axe X, Y si Z.

De ce nu merge ?

–un motiv des intalnit este ca ai uitat sa cuplezi firul 3.3 V la pinul AHREF (in cazul meu, cel putin,
acesta este un motiv des intalnit :).

ADXL345

ADXL345 este un accelerometru digital, care se conecteaza la Arduino prin I2C. Are avantajul
de a fi mult mai precis decat ADXL335 (care este analogic), si de asemenea de a fi capabil de scale
dinamice care pot fi setate de catre utilizator, ceea ce ii permite o rezolutie mult mai buna.
In plus, dispune intern de un mecanism capabil sa detecteze ciocanitul (simplu sau dublu) si
caderea libera. In acest mod, atunci cand accelerometrul este in cadere libera, va notifica Arduino
printr-unul dintre cei doi pini INT1 sau INT2. In cele ce urmeaza ne vom ocupa doar de citirea
acceleratiilor pe cele trei axe, si nu vom aprofunda regimul functionarii cu intreruperi.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino 3.3 V ADXL345 VCC


Arduino GND ADXL345 GND
Arduino SDA ADXL345 SDA
Arduino SCL ADXL345 SCL
Arduino 3.3 V ADXL345 CS

Codul sursa este complicat, dar din fericire este deja scris integral, tot ce ai de facut este sa il
utilizezi. Il gasesti pe pagina http://www.robofun.ro/accelerometru_adxl345 (urmeaza ultimul link din
pagina pe bildr.org).

BMA180

BMA180 este un accelerometru foarte capabil, si extrem de configurabil. Suporta masurarea de


acceleratii intr-o multitudine de game distincte – 1g, 1.5g, 2g, 3g, 4g, 8g, 16g).
Conectarea la Arduino se face folosind pinii I2C, ca in figura de mai jos.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino 3.3 V BMA180 VIO


Arduino 3.3 V BMA180 CS
Arduino 3.3 V BMA180 VDD
Arduino GND BMA180 SDO
Arduino GND BMA180 GND
Arduino SDA BMA180 SDI
Arduino SCL BMA180 SCK

#include <Wire.h>
#define DEVICE ((byte)0x40)
#define DATA_X0 0x02
#define AXIS_SHIFT 2
#define DELAY_RATE 500

int counter = 0;

static void readFrom(byte address, byte num, byte *buff) {


Wire.beginTransmission(DEVICE);
Wire.write(address);
Wire.endTransmission();

Wire.requestFrom(DEVICE, num);
num = Wire.available();

while(num-- > 0) {
*(buff++) = Wire.read();
}

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

void setup()
{
Wire.begin();
Serial.begin(115200);
Serial.flush();
delay(15);
}

int axis[5] = {0x0101, 0, 0, 0, 0};

void loop()
{

readFrom(DATA_X0, 6, (byte*)(axis+1));

Serial.print(millis());
Serial.print("-");
Serial.print(counter);
Serial.print(":");
Serial.print(axis[1]);
Serial.print(", ");
Serial.print(axis[2]);
Serial.print(", ");
Serial.print(axis[3]);
Serial.println();
counter ++;
}

Varianta de cod de mai sus doar citeste informatia asociata acceleratiei pe cele trei axe. Un
exemplu de cod mai complex, in care este setata si gama, este disponibil aici -
http://www.robofun.ro/accelerometru_bma180

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

MMA8452Q

Arduino 3.3 V MMA8452Q 3.3V


Arduino GND MMA8452Q GND
Arduino SDA MMA8452Q SDA
Arduino SCL MMA8452Q SCL

MMA8452Q este un accelerometru ieftin, suficient de capabil. Suporta trei game de acceleratie
(2g, 4g, 8g). Conectarea la Arduino se face folosind patru fire, ca in figura de mai sus.
Pentru cod, exista o librarie foarte bine documentata, disponibila aici -
http://www.robofun.ro/accelerometru_MMA8452Q

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Accelerometru pentru automobil

O idee relativ simpla, dar de efect, bazata pe un accelerometru, o placa Arduino si cateva led-uri
(prinse sau nu in bordul masinii). Atunci cand accelerezi sau cand iei curbe cu viteza, accelerometrul
detecteaza acceleratiile atat pe directia de inaintare a masinii, cat si pe axa laterala (perpendiculara pe
directia de inaintare). Informatiile culese de accelerometru sunt afisate pe un panou cu led-uri. Obtii,
astfel, un dispozitiv care iti ofera informatii despre acceleratia masinii tale, atat pe directia de inaintare
cat si pe directie laterala.
Numarul de led-uri depinde de tine. In configuratia de mai jos, eu am ales 13 led-uri, montate
in cruce. Atunci cand masina sta pe loc (sau se deplaseaza pe un drum drept, cu viteza uniforma), sta
aprins doar led-ul din centru. In momentul in care accelerezi, se aprind gradual led-urile pe directia
verticala, iar atunci cand iei o curba, se aprind led-urile orizontale. Ca sa fie mai spectaculos, poti monta
led-uri de culoare diferita. In centru, si cele 4 led-uri care inconjoara centrul, sugerez led-uri verzi, apoi
led-uri galbene, iar pe exterior led-uri rosii. Evident, la fel de simplu poti opta pentru un afisaj LCD,
obtinand astfel valori numerice.

Ai mai multe variante de a monta led-urile. Spre exemplu, poti folosi led-uri brick si o placa din
plexiglass negru sau gri, in care dai gauri exact pe dimensiunea led-urilor. Montezi apoi fiecare led in
gaura lui (eventual pui o picatura de SuperGlue), lasand placa led-ului pe partea inferioara a placii de
plexiglass. Astfel, pe partea superioara a placii de plexiglass (cea care se vede) vei avea vizibile doar 13
led-uri (pentru ca placutele led-urilor sunt prinse pe partea inferioara a placii de plexiglass si nu se vad).

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Alta varianta (daca esti dispus sa faci cateva modificari in bordul masinii) ar fi sa dai cateva gauri
direct in bord, si sa montezi led-urile direct, fara a mai folosi placa de plexiglas. Efectul va fi net
superior, dar iti trebuie ceva curaj sa gauresti bordul masinii.
In afara de led-uri, mai ai nevoie de o placa Arduino si de un accelerometru. Poti alege orice
accelerometru ai la indemana. Ideal ar fi un accelerometru cu o gama de masura in gama a cativa g, in
ideea de a avea totusi precizie. Spre exemplu, ADXL335 (masoara +/- 3g), BMA180 (poate fi
configurat sa masoare in gama +/- 4g), ADXL345 sau MMA8452Q (masoara in gama +/- 4g) sunt
toate alegeri excelente. De departe, cel mai simplu de utilizat este ADXL335, care functioneaza in
mod analogic. Din acest motiv il voi folosi mai departe in acest proiect.
Conexiunile intre componente sunt destul de simple. Singurul lucru despre care merita sa
vorbim este conectarea led-urilor la Arduino. Daca ai ales sa folosesti Arduino Mega, atunci ai suficienti
pini de conectare pentru led-uri, tot ce ai de facut este sa conectezi cele 14 fire de GND (13 led-uri +
accelerometru) impreuna si sa le conectezi la pinul GND al placii Arduino, apoi sa conectezi pinii IN ai
led-urilor la cate un pin digital al Arduino (sa spunem ca alegi pinii de la 2 la 14) si in final sa conectezi
accelerometrul ADXL335 asa cum este descris in sectiunea dedicata acestuia (sa spunem ca ai ales
porturile analogice 0, 1 si 2). Daca insa alegi sa folosesti un Arduino UNO, va trebui sa folosesti un mic
artificiu pentru a putea conecta cele 13 led-uri la cei 12 pini digitali ai Arduino UNO (pinii de la 2 la
13, pentru ca pinii 0 si 1 sunt cei folositi pentru programarea placii si nu este bine sa ne atingem de ei).
Artificiul despre care vorbesc se refera la faptul ca oricare pin analogic al placii Arduino UNO poate fi
folosit si pe post de pin digital. Pur si simplu, pinul analogic 0 va fi adresat ca pinul digital 14, pinul
analogic 1 va fi adresat ca pinul digital 15, si tot asa (daca vrem sa aprindem led-ul legat la pinul digital
0, vom folosi digitalWrite(14, 0) – dupa ce in setup am setat corect pinul – pinMode(14, OUTPUT) ).
Recapituland, codul de mai jos corespunde urmatoarei configuratii hardware :
–Arduino UNO
–ADXL335
–5 led-uri brick verzi
–4 led-uri brick galbene
–4 led-uri brick rosii
–conectarea led-urilor la pinii Arduino ca in poza de mai jos (led-ul din centru la pinul digital 2, led-ul
din dreapta lui la pinul digital 3, led-ul de deasupra lui la pinul digital 12, si tot asa).

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

#define PRAG_X_1 0.5


#define PRAG_X_2 1
#define PRAG_X_3 2
#define PRAG_Y_1 0.5
#define PRAG_Y_2 1
#define PRAG_Y_3 2
#define SMOOTH_X 0.4
#define SMOOTH_Y 0.4

void setup(){
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);
//pinul analogic A5 poate fi adresat ca pin digital 19

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

pinMode(19, OUTPUT);
//led-ul din centru va sta aprins tot timpul
digitalWrite(2, HIGH);
}

float oldAccX;
float oldAccY;
void loop() {
float accX = smooth(readAcc(0), SMOOTH_X, oldAccX);
float accY = smooth(readAcc(1), SMOOTH_Y, oldAccY);

//led-urile pe directie orizontala, din dreapta


if (accX > PRAG_X_1){
digitalWrite(3, HIGH);
}
else {
digitalWrite(3, LOW);
}

if (accX > PRAG_X_2){


digitalWrite(4, HIGH);
}
else {
digitalWrite(4, LOW);
}

if (accX > PRAG_X_3){


digitalWrite(5, HIGH);
}
else {
digitalWrite(5, LOW);
}

//led-urile pe directie orizontala, din stanga


if (accX < - PRAG_X_1){
digitalWrite(6, HIGH);
}
else {
digitalWrite(6, LOW);
}

if (accX < -PRAG_X_2){


digitalWrite(7, HIGH);
}
else {
digitalWrite(7, LOW);
}

if (accX < -PRAG_X_3){


digitalWrite(8, HIGH);
}
else {
digitalWrite(8, LOW);
}

//led-urile pe directie verticala, din partea de sus

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

if (accX > PRAG_X_1){


digitalWrite(9, HIGH);
}
else {
digitalWrite(9, LOW);
}

if (accX > PRAG_X_2){


digitalWrite(10, HIGH);
}
else {
digitalWrite(10, LOW);
}

if (accX > PRAG_X_3){


digitalWrite(11, HIGH);
}
else {
digitalWrite(11, LOW);
}

//led-urile pe directie verticala, din partea de jos


if (accX < - PRAG_X_1){
digitalWrite(12, HIGH);
}
else {
digitalWrite(12, LOW);
}

if (accX < -PRAG_X_2){


digitalWrite(13, HIGH);
}
else {
digitalWrite(13, LOW);
}

if (accX < -PRAG_X_3){


digitalWrite(19, HIGH);
}
else {
digitalWrite(19, LOW);
}

float readAcc(int port) {


int value=analogRead(port);
int miliVolts=map(value,0,1023,0,3300)-3300/2;
float acc=(float)miliVolts/360;
return acc;
}

float smooth(float data, float filterVal, float smoothedVal) {


if (filterVal > 1) {
filterVal = .99;
}
else if (filterVal <= 0){

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

filterVal = 0;
}
smoothedVal = (data * (1 - filterVal)) + (smoothedVal * filterVal);
return (float)smoothedVal;
}

Codul de mai sus citeste valoarea celor doua acceleratii (pe directia inainte si pe directia laterala)
si apoi aprinde led-urilor corespunzatoare celor doua valori. Dupa citire, valorile acceleratiilor sunt
filtrate trece-jos pentru a obtine un raspuns mai lent. Filtrarea se face de catre functia smooth. Daca
eliminam functia smooth, vom obtine un raspuns extrem de rapid, dificil de remarcat cu ochiul liber.
Printr-o filtrare trece-jos, led-urile se vor schimba mai lent. Cat de lent se schimba led-urile este
controlat de valorile parametrilor SMOOTH_X si SMOOTH_Y. Cu cat valorile acestor parametrii
sunt mai apropiate de unu, cu atat led-urile reactioneaza mai lent. Cu cat valorile sunt mai apropiate de
zero, cu atat led-urile reactioneaza mai rapid. Nivelurile la care se aprind led-urile sunt de asemenea
preconfigurate la inceputul programului ( PRAG_X_1, PRAG_X_2 ...). Aceste prag-uri definesc
nivelurile la care se aprinde si se stinge fiecare led in parte. In cazul folosirii accelerometrului ADXL335,
care masoara valori ale acceleratiei intre 0 si 3 g, pragurile vor fi si ele setate intre 0 si 3.
Mai departe, tot ceea ce face codul de mai sus este sa compare valorile acceleratiilor cu pragurile
prestabilite si sa aprinda sau sa stinga fiecare led. Astfel, spre exemplu, pentru led-ul conectat la portul
digital 3 (imediat in dreapta led-ului din centru), avem urmatoarea secventa :
if (accX > PRAG_X_1){
digitalWrite(3, HIGH);
}
else {
digitalWrite(3, LOW);
}

In rest, esti liber sa te joci cu valorile pragurilor si cu cele doua valori de filtrare pana cand
sistemul functioneaza exact asa cum vrei tu.
O implementare interesanta a acestui gen de proiect (simplificata de faptul ca masina respectiva
avea deja led-uri in bord, vei gasi aici - http://www.instructables.com/id/G-Meter/?ALLSTEPS )
Iar aici - http://www.caranddriver.com/features/the-racelogic-driftbox-feature - gasesti o
implementare comerciala extinsa a principiului.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Aceasta a fost lectia 5. In final, as vrea sa te rog sa ne oferi feedback asupra acestei
lectii, pentru a ne permite sa le facem mai bune pe urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe care il poti
accesa dand click aici.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Senzori de Apasare

Senzorii de apasare ofera o modalitate simpla de a sesiza forta care actioneaza asupra lui. Sunt
disponibili in mai multe dimensiuni. Din punct de vedere al functionarii, un astfel de senzor poate fi
vazut ca un potentiometru rezistiv care isi schimba valoarea proportional cu forta care este aplicata
asupra lui. Pentru a-l utiliza impreuna cu Arduino, cea mai simpla abordare este sa-l conectam in serie
cu un rezistor de 10K, si sa folosim principiul divizorului de tensiune pentru a citi caderea de tensiune
pe rezistorul de 10K. In acest mod, atunci cand senzorul de apasare isi modifica rezistenta, se va
modifica si curentul prin circuit, si implicit si caderea de tensiune pe rezistorul de 10 K (pe care o citim
noi pe un port analogic).
Codul sursa este extrem de simplu, nu face altceva decat sa citeasca valoarea de pe pinul analogic
A0 si sa o afiseze in Serial Monitor. Valorile afisate in Serial Monitor in aceasta situatie sunt valori de
ordin calitativ ("acum apas mai tare decat am apasat data trecuta"), fara a fi etalonate neaparat in
newtoni. Senzorul este capabil de o precizie de aproximativ 10 %, lucru pe care trebuie sa-l iei in
considerare daca vrei sa construiesti un cantar de farmacie.

Arduino 5V PIN1 senzor


Arduino GND PIN1 Rezistor 10K
PIN2 Rezistor 10K Pin2 Senzor
Arduino Analog0 PIN2 Rezistor 10K

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

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

void loop() {
int nivelForta = analogRead(0);
Serial.print("Nivel Forta: ");
Serial.println(nivelForta,DEC);
}

Cand lipesti firele pe terminalele senzorului, fii foarte atent. Pastreaza cat mai putin timp
letconul in contact cu terminalele senzorului, altfel risti sa topesti plasticul din jur (ceea ce va duce la
distrugerea senzorului). Cea mai buna metoda este sa topesti mai intai un pic de fludor pe terminal,
apoi separat topesti un pic de fludor pe fir, apoi le pui in contact si finalizezi lipitura. Daca din diverse
motive fludorul nu adera rapid pe terminalul senzorului (1-2, maxim 3 secunde), atunci ridica letconul
si incearca din nou peste 30 de secunde cand s-a racit terminalul.

Senzor de Atingere HotPot

Senzorii de atingere determina punctul in care sunt apasati cu degetul. Practic, senzorul se
comporta ca un rezistor variabil care isi modifica rezistenta in functie de punct in care este apasat.
Limitele sunt intre 100 ohm si 10 KOhm.
Utilizarea cu Arduino este la fel de simpla ca mai sus, doar ca nu mai ai nevoie de rezistorul
extra. Schema de conectare este mai jos.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino 5V PIN1 Senzor


Arduino GND PIN3 Senzor
Arduino Analog0 PIN2 Senzor

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

void loop() {
int nivelForta = analogRead(0);
Serial.print("Nivel Forta: ");
Serial.println(nivelForta,DEC);
}

Senzor de Indoire

Senzorii de indoire ofera o modalitate simpla de a sesiza gradul de indoire al unui element din
mediu. Sunt disponibili in mai multe variate de dimensiuni.
Din punct de vedere al functionarii, un astfel de senzor poate fi vazut ca un potentiometru
rezistiv care isi schimba valoarea corespunzator cu gradul de indoire la care este supus. Pentru a-l utiliza
impreuna cu Arduino, cea mai simpla abordare este sa-l conectam in serie cu un rezistor de 10K, si sa
folosim principiul divizorului de tensiune pentru a citi caderea de tensiune pe rezistorul de 10K. In
acest mod, atunci cand senzorul de apasare isi modifica rezistenta, se va modifica si curentul prin circuit
si implicit si caderea de tensiune pe rezistorul de 10 K (pe care o citim noi pe un port analogic).
Codul sursa este extrem de simplu, nu face altceva decat sa citeasca valoarea de pe pinul analogic
A0 si sa o afiseze in Serial Monitor. Valorile afisate in Serial Monitor sunt proportionale cu gradul de
indoire al senzorului. Senzorul sesizeaza si directia de indoire (in sensul ca daca il indoi spre stanga,
valoarea rezistentei electrice creste, iar daca il indoi spre dreapta, valoarea scade). Astfel, poti determina
exact atat directia indoirii, cat si cat de mult este indoit senzorul.
Pentru etalonare, cel mai simplu este sa faci incercari repetate. Astfel, prima data vei lasa
senzorul liber si vei urmari ce valoare ai in Serial Monitor. Acea valoare este valoarea pe care o vei folosi
mai departe in codul tau ca sa detectezi cand senzorul este perfect drept.

Arduino 5V PIN1 senzor


Arduino GND PIN1 Rezistor 10K
PIN2 Rezistor 10K Pin2 Senzor
Arduino Analog0 PIN2 Rezistor 10K

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

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

void loop() {
int nivelForta = analogRead(0);
Serial.print("Nivel Indoire: ");
Serial.println(nivelForta,DEC);
}

Senzor Piezo

Senzorul piezo ofera o modalitate foarte simpla de a sesiza vibratiile din mediul ambiat.
Functionarea lui este extrem de simpla, ori de cate ori senzorul este supus unei vibratii mecanice,
genereaza o diferenta de potential intre cele doua borne ale sale. Mai departe, daca vom conecta firul
negru (GND) la pinul GND Arduino si firul rosu (semnal) la unul dintre pinii analogici Arduino (sa
spunem ca alegem pinul A0), vom sesiza o citire pozitiva pe pinul A0 ori de cate ori senzorul vibreaza.
Daca ne-am opri doar aici (si poti incerca sa faci doar montajul descris mai sus si sa vezi cum se
comporta), vei sesiza ca odata ce senzorul a vibrat la un moment dat, valoarea citita pe portul analogic
va ramane la valoarea citita in momentul vibratiei (sau va scadea foarte incet spre 0). Ca sa fortam o
revenire la 0 dupa ce vibratia mecanica a disparut, se conecteaza un rezistor cu valoare mare (de
exemplu, 1 Mega Ohm) intre cele doua fire ale senzorului. Astfel, diferenta de potential produsa de
senzor este descarcata prin rezistor intr-un anumit interval de timp (care depinde de valoarea
rezistorului – cu cat rezistorul este mai mare, cu atat valoarea citita ajunge la 0 mai rapid si cu cat
rezistorul este mai mare, cu atat valoarea citita scade mai incet). Din teste, 1 Mega Ohm pare a fi o
valoare suficient de buna.
Codul sursa este extrem de simplu, nu face altceva decat sa citeasca valoarea de pe pinul analogic
A0 si sa o afiseze in Serial Monitor. O schema cu conectarea pentru sase senzori piezo vei gasi mai jos.
Firul negru al fiecarui senzor se conecteaza la pinul GND Arduino, firul rosu al fiecarui senzor se
conecteaza la cate un pin analogic, iar intre firul rosu si firul negru se conecteaza un rezistor de 1 Mega
Ohm.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

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

void loop() {
int nivelVibratie = analogRead(0);
Serial.print("Nivel Vibratie: ");
Serial.println(nivelVibratie,DEC);
}

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Toba cu senzori piezo

Un senzor piezo este capabil sa detecteze vibratiile. Ori de cate ori este facut sa vibreze, la
bornele lui apare o tensiune electrica. Aceasta tensiune electrica este detectata folosind o placa Arduino,
care placa Arduino comanda catre Music Instrument Shield generarea unui sunet corespunzator unui
instrument de percutie, la alegerea ta. Obtii astfel o toba virtuala controlata de Arduino.
Schema de conectare este simpla. Senzorul piezo are doua fire, unul negru (masa) si unul rosu.
Intre cele doua fire se inregistreaza diferenta de tensiune generata in cazul vibratiilor. Vei conecta toate
firele negre impreuna la pinul GND al Arduino si fiecare fir rosu la cate un pin analogic. Daca faci doar
atat, tensiunea generata de senzorul piezo va scadea extrem de incet (dupa ce senzorul a vibrat la un
moment dat, vei avea aceeasi valoare pe portul analogic Arduino, chiar daca senzorul nu mai vibreaza).
Poti incerca acest lucru cu codul de mai jos.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

void setup() {
Serial.begin(9600);
}
void loop() {
int v = analogRead(0);
Serial.println(v);
}

Daca vei misca (sau vei atinge cu degetul) senzorul piezo conectat la portul analogic zero, vei
vedea ca valoarea afisata in interfata de debug se modifica, si apoi scade foarte foarte incet inapoi la zero.
Ca sa fortam valoarea sa scada spre zero mai rapid, vom cupla in paralel cu fiecare senzor un
rezistor de valoare mare (de exemplu, un megaOhm). Unul dintre pinii rezistorului se va conecta la firul
rosu, iar celalalt pin la firul negru al senzorului piezo. In acest fel, tensiunea generata de senzor se va
descarca incet prin rezistor, si dupa o secunda, vom avea iarasi o citire zero pe senzor. Cu cat alegi un

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

rezistor mai mare, cu atat valoarea citita de Arduino va persista mai mult. Cu cat rezistorul este mai mic,
cu atat raspunsul va fi mai rapid. Poti verifica acest lucru cu programul de mai jos.

#define PRAG 3
void setup() {
Serial.begin(9600);
}
void loop() {
int v = analogRead(0);
if (v > PRAG) {
Serial.println(v);
}
}

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Rolul instructiunii IF este de a-ti permite sa vezi valorile modificate. Daca eliminam if-ul, vei
vedea in debug foarte multe valori zero si doar pentru o perioada foarta scurta vor aparea valori mai
mari ca zero. Datorita faptului ca perioada este extrem de scurta, cel mai probabil nu vei reusi sa vezi
nimic. Cu instructiunea if, vei vedea practic doar valorile mai mari ca zero in interfata de debug.
Pentru montarea efectiva, iti recomand sa cumperi din Hornbach, BricoStore, Praktiker si alte
magazine de profil o bucata de burete gros (in jur de 7 - 10 cm grosime, se foloseste in mod normal
pentru saltele). Din acest burete taie discuri cu diametru mai mic si altele cu diametru mai mare. Pune
apoi discul pe masa, si foloseste un cutter ascutit si ingust pentru a taia un buzunar in interiorul
discului.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Realizeaza sase astfel de discuri, cate unul pentru fiecare senzor. In buzunarul taiat cu cutter,
baga un senzor piezo. Testeaza in interfata de debug ca atunci cand bati in discul din burete sa vezi
valori care se modifica corespunzator. Dupa ce te-ai convins ca senzorul functioneaza corect, poti sigila
buzunarul cu un lipici pentru plastic sau cu banda dublu adeziva.
Vei obtine in final sase astfel de discuri de burete, fiecare disc din burete avand inglobat un
senzor piezo in interior. Mai verifica inca o data ca atunci cand lovesti fiecare disc in parte, vezi
informatiile corespunzatoare in interfata de debug. Foloseste programul de mai jos pentru acest test.

#define PRAG 3
void setup() {
Serial.begin(9600);
}
void loop() {
for (int i = 0; i < 5; i++) {
int v = analogRead(i);
if (v > PRAG) {
Serial.print("DISC :");
Serial.print(i);
Serial.print(";");
Serial.print("VAL :");
Serial.println(v);
}
}
}

Fata de varianta anterioara, in care afisam doar senzorul conectat la portul analogic zero in
interfata de debug, acum verificam toti cei sase senzori pe rand, si daca vreunul dintre ei depaseste
valoarea de prag, atunci il afisam in interfata de debug.
Daca totul este OK pana in acest punct, este momentul sa montezi peste Arduino si Music
Instrument Shield. Codul sursa complet este mai jos.
#include <SoftwareSerial.h>

#define NOTE_DURATION 800


#define DELAY_PER_SOUND 100
#define SENSOR_COUNT 6
#define LED_PIN 13
#define MIDI_RESET_PIN 4

byte string[8] = {35, 38, 49, 45, 75, 76, 77, 85};

boolean inProgress[SENSOR_COUNT];
long sum[SENSOR_COUNT];
long count[SENSOR_COUNT];
int values[SENSOR_COUNT];
long timeStart[SENSOR_COUNT];

long playStartTime[SENSOR_COUNT];

SoftwareSerial mySerial(2, 3);

void setup() {

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Serial.begin(9600);
Serial.println("BEGIN");
for (int i=0; i<SENSOR_COUNT; i++){
inProgress[i] = false;
sum[i] = 0;
count[i] = 0;
playStartTime[i] = 0;
}

mySerial.begin(31250);

pinMode(MIDI_RESET_PIN, OUTPUT);
digitalWrite(MIDI_RESET_PIN, LOW);
delay(100);
digitalWrite(MIDI_RESET_PIN, HIGH);
delay(100);

talkMIDI(0xB0, 0, 0x78);

void loop() {
checkStop();

for (int i = 0; i < SENSOR_COUNT; i++){


values[i] = analogRead(i);

if (values[i] > 10) {


if (!inProgress[i]){
inProgress[i] = true;
sum[i] = 0;
count[i] = 0;
timeStart[i] = millis();
}
}

if (inProgress[i]) {
sum[i] = sum[i] + values[i];
count[i] = count[i] + 1;
if ((values[i] <= 10)&&((millis() - timeStart[i]) > DELAY_PER_SOUND))
{
inProgress[i] = false;
doPlay(i, sum[i]);
}
}
}
}

void checkStop() {
for (int i = 0; i < SENSOR_COUNT; i++){
if ((millis() - playStartTime[i]) > NOTE_DURATION) {
playStartTime[i] = 0;
noteOff(0, string[i] ,127);
}
}

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

void doPlay(int index, double strength) {


Serial.print(index);
Serial.print("-");
Serial.println(strength);

noteOn(0, string[index], 127);


playStartTime[index] = millis();

void noteOn(byte channel, byte note, byte attack_velocity) {


talkMIDI( (0x90 | channel), note, attack_velocity);
}

void noteOff(byte channel, byte note, byte release_velocity) {


talkMIDI( (0x80 | channel), note, release_velocity);
}

void talkMIDI(byte cmd, byte data1, byte data2) {


digitalWrite(LED_PIN, HIGH);
mySerial.write(cmd);
mySerial.write(data1);

if( (cmd & 0xF0) <= 0xB0) {


mySerial.write(data2);
}
digitalWrite(LED_PIN, LOW);

Codul de mai sus se bazeaza pe exemplul dat in sectiunea despre Musical Instrument Shield, asa
ca daca vrei sa-ti amintesti cum anumite se foloseste Musical Instrument Shield, iti recomand sa recitesti
aceasta sectiune.
Constanta NOTE_DURATION defineste cat de mult dureaza sunetul dupa ce unul dintre
discuri a fost lovit. Am ales o durata de 800 de milisecunde, dar poti experimenta cu valoarea aceasta
dupa cum iti place tie. Dupa ce a fost lovit un disc, vreme de NOTE_DURATION milisecunde se
genereaza sunetul. Functia checkStop, apelata imediat la inceputul functiei loop verifica pe rand fiecare
senzor daca nu cumva a trecut NOTE_DURATION milisecunde de cand a inceput sunetul asociat
acelui senzor. Daca a trecut, atunci opreste sunetul. Imediat dupa ce a fost apelata functia checkStop in
loop, urmeaza un ciclu for care verifica fiecare senzor pe rand. Daca valoarea citita pe unul dintre
senzori depaseste o valoare prestabilita, inseamna ca cercul de burete respectiv a fost lovit si atunci se
genereaza sunetul corespunzator.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Aceasta a fost lectia 6. In final, as vrea sa te rog sa ne oferi feedback asupra acestei
lectii, pentru a ne permite sa le facem mai bune pe urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe care il poti
accesa dand click aici.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Senzori de Distanta

Senzorii de distanta sunt capabili sa spuna cate de departe este obiectul din fata lor. In functie de
principiul constructiv, exista mai multe categorii de senzori.
Avem astfel senzorii care se bazeaza pe emiterea de ultrasunete si masurarea timpului necesar ca
sa se intoarca ecoul (principiul pe care functioneaza si navigatia liliacului). Acestia sunt senzori destul
de precisi, foarte usor de folosit si a caror iesire variaza direct proportional cu distanta masura (un obiect
situat la 2 metri va da un semnal de iesire de doua ori mai mare decat un obiect situat la 1 metru). Din
cauza faptului ca sunetul se deplaseaza cu o viteza fixa, aceasta categorie de senzori este relativ lenta (in
sensul ca daca vrem sa facem 100 de determinari intr-o secunda, acesti senzori nu vor fi capabili sa faca
asta). In aceasta categorie se incadreaza sonarele MaxBotics si senzorul tip PING)).
A doua categorie de senzori sunt cei bazati pe reflexia unei raze de lumina infrarosie. Acesti
senzori au doua zone active, o zona care emite lumina si o zona care receptioneaza raza reflectata de
obiectul pana la care dorim sa masuram distanta. In functie de unghiul sub care se reflecta raza de
lumina se poate determina distanta pana la obiect.
Acesti senzori sunt mult mai rapizi decat cei ultrasonici, insa functioneaza corect doar intr-o
gama mai stricta de distante. Astfel avem un tip de senzor infrarosu in gama 3 – 40 cm, un alt tip in
gama 10 – 80 cm si un alt tip in gama 15 – 150 cm. Mai exista si doua tipuri de senzori digitali, unul
de 5 cm si unul de 10 cm. Senzorii digitali determina daca exista un obiect la o distanta mai mica de 5,
respectiv 10 cm in fata senzorului. Pentru senzorul de tip 10-80 cm, valoarea citita de Arduino pe
portul analogic la care este conectat senzorul va fi aproape de zero atunci cand nu exista nici un obiect
in fata senzorului si aproximativ 630 atunci cand obiectul este la 10 cm in fata senzorului. Daca
senzorul se apropie si mai mult de obiect (astfel ca distanta devine mai mica de 10 cm), valoarea citita
scade iarasi, ajungand sa fie in jur de 430 cand senzorul este la cativa milimetri de obiect. Din acest
motiv, daca avem nevoie de o determinare exact intr-o gama mai larga de distante, o solutie buna este sa
utilizezi o combinatie de doi sau mai multi senzori, in functie de ce ai nevoie. Spre exemplu, ca sa faci
un robot care ocoleste obstacole, un singur senzor 10-80 cm este suficient (cand obiectul ajunge la mai
putin de 15 cm, faci robotul sa-si schimbe directia si sa-l ocoleasca. Pentru un robot de sumo insa, unde
este important sa stii cand adversarul a ajuns la 2 cm de tine, vei vrea sa combini un senzor de 10-80 cm
cu un senzor digital de 10 cm. Astfel vei folosi senzorul digital de 10 cm ca sa iti spuna daca adversarul
este la mai putin de 10 cm de tine, si senzorul de 10-80 ca sa determini exact distanta. Senzorii Sharp
sunt unii dintre cei mai des folositi senzori, intrucat sunt o combinatie echilibrata intre pret si
performanta.
In sfarsit, a treia categorie de senzori sunt senzorii de tip laser. Acestia sunt cei mai precisi si cei
mai rapizi, dar pot costa cu un ordin sau doua de marime fata de cele doua categorii anterioare (in gama
sutelor sau miilor de euro pe bucata).

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Sharp 3-40 cm, Sharp 10-80 cm si Sharp 15-150 cm

Acesti trei senzori sunt extrem de similari, difera doar gama distantelor in care sunt utili.
Conectarea la Arduino este identica, iar codul folosit este aproape identic.
Pentru ca mufa de conectare este mai complicat de folosit altfel, recomand achizitionarea unui
cablu special JST, care intra direct in mufa si ofera ca iesire 3 fire (ROSU – alimentare – VCC Arduino,
NEGRU – masa – GND Arduino, si ALB – semnal – un pin analogic Arduino).
Imediat dupa ce ai conectat senzorul, urmatorul pas ar fi sa vezi valorile date de senzor, fara a
mai aplica nici o procesare suplimentara. Pentru aceasta, incarca pe placa Arduino un program care
afiseaza valorile senzorului, ca mai jos.

void setup() {
Serial.begin(9600);
}
void loop() {
int valoareSenzor = analogRead(0);
Serial.print("Valoare Senzor: ");
Serial.println(valoareSenzor,DEC);
}

Deschide Serial Monitor (Tools -> Serial Monitor) si apropiind si departand mana de senzor
urmareste ce se intampla cu valorile citite. Pentru toti senzorii vei observa ca atunci cand nu ai nici un
obiect in fata senzorului valoarea citita este mica, in zona 10-20-30. Pe masura ce mana ta se apropie de
senzor, valoarea incepe sa creasca, pana la aproximativ 630 cand mana ta ajunge la 10 cm de senzor
(valoare pentru senzorul 10 – 80 cm). Daca apropii mana si mai mult, valoarea incepe iarasi sa scada.
Pentru marea majoritate a proiectelor, acest cod este suficient. Sigur, te intrebi probabil "si unde
e distanta, ca deocamdata sunt doar niste numere ???" . Asa este, ai dreptate. Cea mai simpla varianta ar
fi sa-ti etalonezi singur cateva valori care te intereseaza (spre exemplu, masori experimental ca la distanta
de 25 de cm ai o valoare citita de 432). O varianta ceva mai complicata este sa analizezi graficul valorilor
din datasheet-urile senzorilor si sa faci o determinare matematica prin calcule, alegand puncte de
referinta din grafic (folosind de exemplu metoda celor mai mici patrate). De remarcat ca pentru fiecare
dintre senzori caracteristica (modul cum variaza valoarea citita de Arduino cu distanta pana la obiect )
este diferita.
Pentru senzorul 10-80 cm spre exemplu, functia matematica de mai jos (determinata matematic
plecand de la caracteristica din datasheet) aproximeaza distanta in centimetri in functie de valoarea citita
de Arduino (este valabila doar pentru senzorul 10-80 cm).

int readDistance() {
float volts = analogRead(0)* ((float) 5 / 1024);
float distance = 65*pow(volts, -1.10);
return distance;
}

Datorita faptului ca emit lumina infrarosie foarte des, in mod automat senzorii Sharp sunt

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

destul de mari consumatori de curent si sunt afectati de perturbatii in sursa de alimentare (cum ar fi, de
exemplu, situatia unui robot alimentat cu o baterie mai putin capabila – sa spunem o baterie
dreptunghiulara de 9 V – si la care atat motoarele cat si senzorii merg pe aceeasi baterie). Intr-o situatia
de acest gen, valorile indicate de senzori pot fi mai mult sau mai putin eronate. Pentru a evita acest
lucru, este bine ca intotdeauna senzorii sa fie alimentati separat (dintr-o alta baterie sau sursa de energie)
decat motoarele sau alti mari consumatori de energie. Alta abordare este sa faci medierea valorilor citite
de la senzor, ca mai jos.

int readDistanceMediata() {
int sum = 0;
for (int i=0; i<10;i++){
float volts = analogRead(0)* ((float) 5 / 1024);
float distance = 65*pow(volts, -1.10);
sum = sum + distance;
delay(5);
}
return (int)(sum / 10);
}

In acest exemplu am ales sa mediez 10 valori ale senzorului, lucru care ajuta foarte mult pentru
situatiile cand valorile citite de la senzor nu sunt stabile. Evident, poti alege sa mediezi un alt numar de
valori. Cu cat mediezi mai multe valori, cu atat senzorul este mai stabil, dar mai lent. Cu cat mediezi
mai putine, cu atat senzorul este mai rapid.
Alte abordari pentru a face ca citirile senzorilor sa fie cat mai exact (abordari la nivel electric, de
data aceasta) sunt sa adaugi in circuit unul sau doi condensatori, cu rolul de a netezi fluctuatiile
tensiunii de alimentare.

De ce nu merge ?

–Asa cum spuneam si mai sus, senzorii Sharp sunt mari consumatori de curent. Daca sursa ta de
alimentare nu este suficient de capabila, atunci valorile citite de senzori nu vor fi corecte. Spre exemplu,
daca ai Arduino alimentat doar prin USB, atunci vei obtine valori mai mici decat cele reale. De
asemenea, daca ai alimentat din aceeasi sursa de tensiune si motoarele robotului tau, si Arduino, iar
sursa ta de alimentare nu este foarte capabila, atunci vei observa ca valorile citite de senzori sunt afectate
de activitatea motoarelor (spre exemplu, cand motoarele pleaca de pe loc, acestea consuma mult curent,
lasand senzorii fara curent). Exista mai multe solutii pentru a corecta aceasta problema. Cea mai simpla
este ca intotdeauna sa alimentezi Arduino separat si motoarele separat, folosind o sursa de alimentare
capabila (in mod normal, 6 baterii R6 de 1.5V fiecare, sau o baterie LIPO reprezinta surse de
alimentare capabile; o baterie patrata de 9V insa, NU este niciodata o sursa capabila). Alta varianta este
ca pur si simplu sa mediezi valorile intoarse de senzori (vei avea o latenta in citiri, dar erorile vor fi
diminuate). In sfarsit, cea de-a treia solutie este din zona hardware si presupune conectarea in paralel cu
alimentarea senzorului a unui condensator electrolitic de cativa zeci de microfarazi. Daca vrei sa
aprofundezi aceasta abordare, iti recomand o cautare folosind Google dupa "sharp sensor capacitor
filtering".

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Sharp digital 10 cm, Sharp digital 5 cm

Senzorii digitali scot pe iesire valoarea 0 daca nu exista nici un obiect in raza lor si 1 daca exista
un obiect. Conectarea la Arduino este la fel de simpla ca si in cazul senzorilor de mai sus. Pinul VCC se
conecteaza la pinul 5V al Arduino, pinul GND se conecteaza la pinul GND al Arduino, iar pinul de
semnal se conecteaza la un pin digital al Arduino. Codul sursa este foarte simplu, ca mai jos (unde am
considerat ca senzorul este conectat pe pinul digital 7).

void setup() {
Serial.begin(9600);
pinMode(7, INPUT);
}

void loop() {
int valoareSenzor = digitalRead(7);
Serial.print("Valoare Senzor: ");
Serial.println(valoareSenzor,DEC);
}

Senzor de Linie Analogic

Senzorul de linie este capabil sa detecteze gradul de reflectivitate pentru suprafata din fata
senzorului. Ca aplicatie imediata, tinand cont de faptul ca o zona de culoare neagra reflecta foarte putin,
iar o zona de culoare alba reflecta foarte puternic, acest senzor este utilizat in mod deosebit in robotica,
pentru a permite unui robot sa faca distinctia intre suprafete de culoare neagra si suprafete de culoare
alba. Acest lucru este util, spre exemplu, in cadrul concursurilor de sumo robotic, unde ringul de
culoare neagra este marginit de o banda de culoare alba, sau pentru a face ca un robot sa urmareasca o
linie de culoare neagra, pe fundal alb.
Ca principiu constructiv, senzorul consta intr-un led infrarosu si un receptor infrarosu, montati
unul langa celalalt. Periodic (in mod automat, fara a fi controlat de tine in vreun fel) led-ul infrarosu
emite lumina, lumina care este reflectata de suprafata din fata senzorului. Receptorul infrarosu culege
lumina infrarosie reflectata de suprafata, si ofera pe pinul OUT o tensiune proportionala cu nivelul de
lumina reflectata.
Astfel, conectarea la Arduino este foarte simpla. Senzorul trebuie alimentat (pinul VCC la pinul
5V al Arduino, pinul GND la pinul GND al Arduino, si pinul OUT la unul dintre pinii analogici
Arduino – sa alegem A0 pentru programul de mai jos).

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino 5V PIN1 senzor


Arduino GND PIN1 Rezistor 10K
PIN2 Rezistor 10K Pin2 Senzor
Arduino Analog0 PIN2 Rezistor 10K

void setup() {
Serial.begin(9600);
}
void loop() {
int nivelReflectanta = analogRead(0);
Serial.print("Nivel Reflectanta: ");
Serial.println(nivelReflectanta,DEC);
}

Senzori Prezenta Umana

Senzorii de prezenta umana ("PIR", de la :"Passive Infrared") detecteaza miscarea corpurilor vii
in zona senzorului. Probabil ca stii deja acesti senzori (spre exemplu, cam toate toaletele benzinariilor

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

sau restaurantelor ii au pentru a aprinde lumina in mod automat cand intri tu). Functioneaza pe baza
detectarii radiatiei infrarosii. Orice corp (si cu atat mai mult oamenii sau animalele) emit radiatie
infrarosie in continuu. Elementul de detectie al unui senzor PIR este impartit in doua jumatati egale, iar
citirile celor doua jumatati se anuleaza in mod normal (fiind egale). In momentul in care apare insa
miscare, una dintre jumatati va detecta mai multa radiatie, iar acest lucru va activa senzorul de prezenta.
Raza de detectie a unui senzor PIR poate varia in functie de producator, asa ca va trebui sa citesti
datasheet-ul sau sa il testezi. Distanta de detectie cel mai des intalnita este in jurul a cativa metri (3-6
metri).

Senzor PIR

Senzorul PIR este cel mai simplu senzor care detecteaza prezenta umana. Un astfel de senzor are
trei fire de conectare. Un fir este VCC (alimentare la 5 V), al doilea este pinul de GND, iar cel de-al
treilea este pinul de semnal. Cel mai comun este ca acest fir de semnal sa functioneze in regim "open-
collector" (asa functioneaza si senzorul din oferta Robofun – http://www.robofun.ro/senzor_pir). Acest
lucru inseamna ca atunci cand senzorul nu detecteaza nimic, pinul de semnal nu este conectat la nimic
(este ca si cum ar fi un fir lasat pe birou, neconectat). Atunci cand senzorul detecteaza miscare, pinul de
semnal este conectat la GND. Acest comportament este foarte util pentru situatiile in care vrei sa faci o
actiune in cazul detectiei de prezenta, fara a folosi un microcontroller. Astfel, este suficient sa conectezi
un led inseriat cu un rezistor intre VCC si pinul de semnal, si atunci cand senzorul detecteaza prezenta
umana, pinul de semnal este conectat la GND, adica prin led circula curent electric, deci led-ul se
aprinde.
Pentru a-l folosi cu Arduino, avem nevoie doar de un rezistor de cativa zeci de Kilo (valoarea
exacta nu este prea importanta), si de un alimentator extern de 12 V (sau o baterie de 9V). Cele doua
scheme de conectare sunt mai jos.
Atunci cand senzorul nu detecteaza prezenta, firul negru conectat la senzor este ca si cand ar fi
lasat pe birou, liber, fara a fi conectat cu nimic. Acest lucru inseamna ca pinul digital 5 al Arduino este
tras spre 5V, prin rezistorul de 10K. Atunci cand senzorul detecteaza prezenta, firul negru conectat la
senzor este pus la GND, deci pinul digital 5 al Arduino va citi 0 V.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino VIN Fir Rosu Senzor


Arduino 5V PIN1 Rezistor 10K
Arduino GND Fir Maro Senzor
Arduino Pin Digital 5 PIN2 Rezistor 10K
PIN2 Rezistor 10K Fir Negru Senzor

int pirPin = 5;

void setup(){
Serial.begin(9600);
pinMode(pirPin, INPUT);
}

void loop(){
int prezenta = digitalRead(pirPin);
if(pirVal == LOW){
Serial.println("Este cineva in camera !");

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

delay(2000);
}
}

In codul de mai sus, in rutina setup pinul digital 5 (cel la care este conectat senzorul) este
declarat ca fiind un pin de INPUT, iar apoi in rutina loop, ori de cate ori acest senzor trece in LOW
(0V), inseamna ca senzorul a detectat prezenta.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Proiect : Harpa cu laser

Harpa cu laser este un proiect destul de simplu de realizat, bazat pe senzori de lumina pe care
cad raze laser. Atunci cand blochezi cu mana una dintre razele laser (similar cu atingerea unei coarde
dintr-o harpa reala) este redata o nota muzicala corespunzatoare folosind Music Shield.
Pentru simplitate, in cele ce urmeaza vom alege sa folosim sase senzori de lumina brick si o placa
Arduino UNO sau Arduino Leonardo. Cea mai simpla varianta este sa montezi cei sase senzori de
lumina pe o bucata de lemn, folosind suruburi cu piulita sau suruburi pentru lemn. Conectarea
senzorilor de lumina brick la Arduino o vei face asa cum este descris in sectiunea dedicata acestora
(pinul GND la pinul GND al Arduino, pinul VCC la pinul 5V al Arduino, iar pinii de semnal la cate
un pin analogic, incepand cu A0 pana la A5).
Music Shield il vei infige pur si simplu in placa Arduino.
Pentru lasere, poti folosi pointer-e laser din comert, cea mai ieftina varianta. Acestea vor fi
montate deasupra senzorilor, cate unul deasupra fiecare senzor, astfel incat lumina laser-ului sa fie exact
deasupra zonei active a senzorului (fototranzistorul, piesa de culoare galbena). Chiar daca proiectul se
cheama "harpa cu laser", laserele sunt mai mult sau mai putin optionale. Daca le montezi, sensibilitatea
harpei va fi mai mare, pentru ca lumina generata de laser (si care pica pe senzor) este foarte puternica, si
atunci cand o intrerupi cu mana, vei obtine o variatie mare in valoarea citita de senzor. Daca alegi sa nu
montezi laserele, in continuare atunci cand misti mana deasupra senzorilor vei obtine o variatie in
valoarea citita de senzor (pentru ca vei obtura o parte din lumina naturala care pica pe senzor). Variatia
va fi insa mai mica decat atunci cand ai laserele montate si va varia cu distanta la care iti misti mana fata
de senzori. Sugestia mea ar fi sa incerci prima data fara lasere si daca nu iti place cum functioneaza, sa le
adaugi ulterior.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino va monitoriza cei sase senzori de lumina in mod continuu si atunci cand valoarea citita
de unul dintre senzori scade sub un anumit prag prestabilit (din cauza faptul ca am obturat cu mana
raza laser), atunci Arduino va comanda Music Shield generarea notei respective.

#include <SoftwareSerial.h>

#define PRAG_SENZORI 90
#define DURATA_NOTA 2000

#define INSTRUMENT 7 //(de la 1 la 128)

#define VOLUME 127 // (maxim 127)

SoftwareSerial mySerial(2, 3);

byte note = 0;
byte resetMIDI = 4;
byte ledPin = 13;
static byte senzori[6]= {
0, 1, 2, 3, 4, 5};

byte triggered[16] = {
0, 0, 0, 0, 0, 0};

static byte string[6] = {


60, 62, 64, 65, 67, 68};

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

byte hitNote[6] = {
0, 0, 0, 0, 0, 0};

uint32_t timestamp[6];

void setup() {
Serial.begin(57600);
mySerial.begin(31250);
pinMode(resetMIDI, OUTPUT);
digitalWrite(resetMIDI, LOW);
delay(100);
digitalWrite(resetMIDI, HIGH);
delay(100);

for(int i=0; i<6; ++i) {


timestamp[i] = 0xFFFFFFFF;
}

talkMIDI(0xB0, 0x07, VOLUME); //setare volum

talkMIDI(0xC0, INSTRUMENT, 0); //setare instrument


}

void loop() {
for(int i=0; i<6; ++i) {
if((analogRead(senzori[i]) < PRAG_SENZORI) && (triggered[i] == 0)){
triggered[i] = 1;
noteOn(0, string[i], 127);
}
else if((triggered[i] == 1) && (analogRead(senzori[i]) >=
PRAG_SENZORI)){
triggered[i] = 0;
timestamp[i] = millis();
hitNote[i] = 1;
}
}

for(int i=0; i<6; ++i) {


if( (millis() > timestamp[i] + DURATA_NOTA) && (hitNote[i] == 1) ) {
noteOff(0, string[i] ,127);
hitNote[i] = 0;
}
}
}

void noteOn(byte channel, byte note, byte attack_velocity) {


talkMIDI( (0x90 | channel), note, attack_velocity);
}

void noteOff(byte channel, byte note, byte release_velocity) {


talkMIDI( (0x80 | channel), note, release_velocity);
}

void talkMIDI(byte cmd, byte data1, byte data2) {


digitalWrite(ledPin, HIGH);
mySerial.write(cmd);

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

mySerial.write(data1);

if( (cmd & 0xF0) <= 0xB0) {


mySerial.write(data2);
}

digitalWrite(ledPin, LOW);
}

Constanta PRAG_SENZORI (definita chiar la inceputul programului) stabileste nivelul la care


se genereaza o nota. Valoarea acestei constante trebuie sa fie cu putin mai mare decat valoarea citita de
senzorul de lumina cand obturam raza laser cu mana. Daca setam pentru aceasta constanta o valoarea
prea mare, riscam sa depasim valoarea citita de senzor in mod normal, si atunci notele vor fi generate tot
timpul. Daca setam o valoare prea mica, atunci vom ajunge sub valoarea citita atunci cand obturam raza
laser cu mana si nu vom reusi sa generam note niciodata. Vezi schema de mai jos pentru mai multa
claritate. Cel mai simplu sa obtii o valoare functionala este sa afisezi in interfata de debug valorile citite
de senzori atunci cand raza laser lumineaza senzorul si cea atunci cand raza laser este obturata cu mana,
si apoi sa setezi o valoare care sa fie cu 50 – 100 mai mare decat valoarea citita atunci cand raza laser este
obturata.
Urmatoarea constanta, DURATA_NOTA defineste cat timp se aude o nota dupa ce a fost
generata. Cu cat valoarea este mai mica, cu atat notele vor fi mai scurte. Esti liber sa experimentezi cu
aceasta valoare cum doresti tu.
Constanta INSTRUMENT defineste ce tip de instrument va reda notele muzicale. Valoarea
aleasa in programul de mai sus, 7, corespunza unei harpe. Tu poti alege orice valoare doresti din lista de
mai jos. Denumirile instrumentelor sunt in limba engleza (lista a fost extrasa direct din documentul de
specificatii pentru Music Instrument Shield), asa ca simte-te liber sa experimentezi si sa alegi ce-ti place
mai mult. Cum ar fi oare o harpa care sa sune ca un acordeon ? Acum poti sa afli singur.
VOLUME defineste cat de tare doresti sa se auda notele. Valorile posibile sunt intre 0 si 127.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Un film cu o astfel de harpa laser gasesti aici :


http://www.tehnorama.ro/the-sound-of-shadow-and-light- the-movie/

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Aceasta a fost lectia 7. In final, as vrea sa te rog sa ne oferi feedback asupra acestei
lectii, pentru a ne permite sa le facem mai bune pe urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe care il poti
accesa dand click aici.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Ethernet Shield

Prin intermediul acestui shield, Arduino se poate conecta la Internet exact


ca un PC obisnuit. Poate functiona in regim de client (accesand alte site-uri web
din Internet, asa cum faci tu cand navighezi pe Internet) sau poate functiona in
regim de server web (si atunci tu – sau oricine altcineva – il poate accesa de
oriunde din Internet folosind un browser obisnuit).
Aplicatiile sunt multe si spectaculoase. Spre exemplu, poti face ca
Arduino sa citeasca date de la senzori de mediu (temperatura, presiune
atmosferica, umiditate, nivel de monoxid de carbon) si sa le trimita la fiecare 5
secunde prin Internet catre un formular tip Excel creat in Google Docs. La fel de
simplu este ca in loc de Google Docs sa folosesti COSM.COM, un serviciu
dedicat pentru culegere si stocare de date de la senzori. Sau poti folosi un
senzor de umiditate montat intr-un ghiveci, si atunci cand planta nu are
suficienta apa, Arduino iti va trimite mesaje pe Twitter. Sau, daca ai un spatiu
comun in care se patrunde pe baza de card-uri RFID, atunci Arduino poate
anunta pe Twitter prezenta unei anumite persoane (solutie pe care chiar o
folosim in acest moment pentru accesul la hacker-space-ul inventeaza.ro din
Bucuresti). Sau poti face ca Arduino sa se conecteze la serverul weather.com,
sa obtina vremea probabila, si sa o afiseze pe un LCD montat pe oglinda din
baie.

Client Web, IP prin DHCP

Exemplul de mai jos demonstreaza o conexiune facuta cu Arduino la


serverul google.com, conexiune pe care Arduino o foloseste ca sa caute pe
Google termenul "arduino". Rezultatul cautarii (la nivel de HTML) este afisat in
Serial Monitor. Inainte de a trece la cod, sa povestim un pic de comunicarea
prin Internet. Un browser (cel pe care il folosesti tu ca sa citesti stirile online)
face o cerere catre un server (calculatorul aflat la sediul firmei de hosting care
stocheaza informatia), iar in urma acestei cereri, serverul raspunde cu un text
in format HTML. HTML este un mod de reprezentare a informatiei vizuale, care
contine atat textul pe care il citesti tu, cat si elementele de formatare in
pagina. Poti vedea exact codul HTML al unei pagini daca folosesti optiunea
"view source" din browser. Pe langa HTML, raspunsul serverului mai contine si
un text care contine informatii despre raspuns (numit "header HTTP"). Daca
atunci cand accesezi o pagina in browser, toata informatia suplimentara legata
de formatarea in pagina si de header-e HTTP este deja interpretata si folosita
de browser (astfel incat tu vezi doar rezultatul final, informatia vizuala), in cazul
in care facei o cerere web cu Arduino nu se intampla asta. La Arduino ajunge

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

intreaga informatie generata de browser, neprocesata in vreun fel, inclusiv


header-ele HTTP. Astfel, ceea ce vei vedea in Serial Monitor in cazul exemplului
de mai jos nu va fi chiar ceea ce vezi in browser cand faci o cautare pe Google,
dar informatia va fi exact aceeasi.

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };


IPAddress server(209,85,148,101); // Google

EthernetClient client;

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

if (Ethernet.begin(mac) == 0) {
Serial.println("Nu s-a reusit initializarea placii de retea folosind
DHCP");
}

delay(1000);
Serial.println("conectare in progress...");

if (client.connect(server, 80)) {
Serial.println("conectat");
client.println("GET /search?q=arduino HTTP/1.0");
client.println();
}
else {
Serial.println("conectare esuata");
}
}

void loop() {
if (client.available()) {
char c = client.read();
Serial.print(c);
}

if (!client.connected()) {
Serial.println();
Serial.println("deconectare acum.");
client.stop();

for(;;)
;
}
}

Primul lucru de remarcat in codul sursa de mai sus este declaratia adresei
MAC. Orice dispozitiv conectat intr-o retea este identificat in mod unic de
adresa sa MAC. Aceasta este un numar unic alocat de producator, care permite
adresarea dispozitivului respectiv. Daca te uiti pe shield-ul tau Ethernet vei

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

vedea acest numar de identificare scris pe un sticker. Este bine sa folosesti


acest numar de identificare ori de cate ori scrii cod pentru shield-ul Ethernet
respectiv. Cu toate ca pana acum am spus ca acest numar este "unic", lucrurile
nu sunt chiar asa de stricte. Este absolut necesar sa fie unic dar nu neaparat la
nivelul intregii retele Internet, ci doar in reteaua locala (pana la primul router)
in care este cuplat dispozitivul. Exista sanse sa functioneze corect (aproape)
orice valori ai seta in codul de mai sus pentru adresa MAC (spun "aproape"
pentru ca exista o serie de reguli care determina o adresa MAC valida, dar care
nu sunt neaparat respectate). Ca si concluzie, cel mai bine este sa declari ca
adresa MAC exact ceea ce scrie pe shield. Daca nu scrie, sau daca sticker-ul s-a
rupt, poti pune si alte valori si exista sanse mari sa functioneze corect.
Al doilea lucru este adresa IP. Pe langa adresa MAC de care am discutat
mai sus, fiecare dispozitiv conectat in Internet mai are asociata si o adresa IP.
Daca este prima data cand te intalnesti cu aceste concepte, probabil ca ti se
pare totul anapoda si te intrebi de ce atunci cand a fost gandit Internetul n-au
dat fiecarui dispozitiv o adresa unica si s-au complicat in halul asta. Exista o
serie de motive, dar nu voi insista asupra lor aici. Deocamdata este suficient sa
acceptam ca pe langa adresa MAC, pentru fiecare dispozitiv mai exista si o
adresa IP. Ca sa poate fi vizibil in Internet (adica oricine sa-l poata accesa din
Internet), atunci adresa IP a dispozitivului trebuie sa fie unica (si aici chiar
trebuie, nu mai merg lucrurile ca la adresa MAC). In cazul nostru, in care un
Arduino care se conecteaza la serverul Google, putem identifica doua adrese IP
– o adresa IP pentru serverul Google (anume " 173,194,33,104") si o adresa IP
pentru Arduino. Adresa IP a serverului Google este unica in intreg Internetul,
pentru a fi accesibil de oriunde. In cazul adresei IP pentru Arduino, este
suficient ca adresa sa fie unica doar la nivelul retelei locale (pana la primul
router – ceea ce de obicei inseamna casa sau biroul tau), pentru ca in aceasta
situatia noi folosim Arduino drep client doar (adica Arduino nu este accesat de
catre cineva din Internet, ci el acceseaza). Din acest motiv, putem lasa
alocarea unei adrese IP pentru placa Arduino pe seama router-ului, fara sa ne
mai batem noi capul cu ea (procedeul se numeste alocare prin DHCP). Evident,
acest lucru presupune ca avem un router capabil sa ofere adrese prin DHCP in
reteaua locala ! Daca nu ai, atunci va trebui sa setezi tu o adresa IP statica
pentru placa de retea (si in exemplu urmator vom face asta).
Inca o remarca utila este ca adresa IP a serverului Google se poate
schimba in timp. In momentul in care eu scriu aceste randuri, exemplul de mai
sus functioneaza perfect. Se poate intampla insa ca pana cand tu le vei citi,
inginerii de la Google sa fi modificat deja adresa IP a serverului, iar tie sa nu-ti
functioneze corect exemplul. Un browser web obisnuit, ca sa obtina
intotdeauna adresele IP corecte utilizeaza un serviciu numit "DNS" (serviciu pe
care il poate folosi si Arduino, dar intr-un exemplu urmator). Deocamdata, daca
nu-ti functioneaza exemplul de mai sus, va trebui sa determini si sa actualizezi
manual adresa serverului Google. Pentru aceasta, deschide o consola
command prompt pe PC (daca esti pe Windows, apasa "Start", "Run", scris

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

"cmd" si apasa Enter). In consola deschisa scrie "ping google.com". Vei vedea
ca raspuns IP-ul serverului Google, ca mai jos.

In sfarsit, daca totul merge bine, atunci ar trebui sa vezi in Serial Monitor
o serie de caractere care defileaza. Acestea sunt raspunsul serverului Google la
cautarea ta (acel HTML pe care browserul il interpreteaza si il afiseaza intr-un
format vizual adecvat).
Exemplul pe care tocmai l-am vazut nu are o utilitate clara in sine exact
in forma aceasta, dar este baza pentru orice proiect care presupune extragere
de informatia din Internet.

Client Web, IP static

Sa presupunem ca nu ai in casa un router capabil sa aloce adresa IP prin


DHCP. In aceasta situatie, vei vedea in Serial Monitor un mesaj de eroare in
momentul in care vei incerca sa rulezi exemplul de mai sus. In aceasta situatie,
va trebui sa declari tu manual o adresa IP statica pentru shield-ul Ethernet, ca
mai jos.

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };


IPAddress server(209,85,148,101); // Google
IPAddress arduinoIP(192,168,0,99); // Arduino

EthernetClient client;

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

if (Ethernet.begin(mac, arduinoIP) == 0) {
Serial.println("Nu s-a reusit initializarea placii de retea folosind o
adresa IP statica");
}

delay(1000);
Serial.println("conectare in progress...");

if (client.connect(server, 80)) {
Serial.println("conectat");
client.println("GET /search?q=arduino HTTP/1.0");
client.println();
}
else {

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Serial.println("conectare esuata");
}
}

void loop(){
//EXACT LA FEL CA IN EXEMPLUL PRECEDENT
}

Singurele linii diferite sunt cele doua linii marcate cu bold. Prima linie
defineste o adresa IP pentru shield-ul Ethernet, iar cea de-a doua linie o
utilizeaza in sectiunea de initializare a shield-ului. Ca sa alegi o adresa IP valida
pentru reteaua ta, va trebui sa determini mai intai ce adresa IP are calculatorul
tau, ca sa poti da si pentru Arduino o adresa IP din aceeasi clasa. Acest lucru se
face (in Windows) apasand "Start", apoi "Run", apoi tastand "cmd" si Enter. In
consola deschisa tasteaza "ipconfig". Vei observa (daca nu ai foarte mult
ghinion) o linie care zice "IP Address : 192.168.0.2" sau ceva similar. Aceasta
este adresa IP a calculatorului tau. In cele mai multe cazuri, tu va trebui sa
modifici ultima cifra astfel incat adresa nou obtinuta sa nu mai fie utilizata de
nimeni in reteaua ta locala. Depinzand de la caz la caz, acest lucru ar putea fi
simplu sau mai complicat. Incearca sa alegi un numar mai mare (99, 149, 253
sunt exemple bune). Daca totusi nu reusesti sa gasesti o adresa IP valida,
atunci o varianta ar fi sa apelezi la ajutorul unui amic care se pricepe la retele
de calculatoare si sa ii ceri sa-ti indice o adresa IP libera in reteaua ta. In final,
vei obtine acelasi rezultat ca in exemplul de mai sus, doar ca acum adresa IP
pentru placa Arduino este setata de tine.

Server Web

Acum ca ai reusit sa faci placa Arduino sa citeasca date din Internet,


urmatorul pas este sa faci un server care sa poata fi accesat de alti utilizatori
din Internet, interesati sa vada informatie culeasa de placa ta Arduino. Inainte
de a incepe, este bine sa stii ca in cele de urmeaza voi prezenta in detaliu tot
ce trebuie sa faci pentru a avea un server functional pe placa Arduino (si care
sa functioneze cel putin accesat dintr-un browser de pe laptopul tau). Ca
serverul sa fie accesibil chiar din Internet, pentru oricine, lucrurile sunt putin
mai complicate la nivel de configurari de router si retea locala (nu la nivelul
Arduino). Cu aceste configurari de router va trebui sa te descurci singur. Din
fericire, exista foarte multe tutoriale in acest sens pe Internet (poti incerca o
cautare pe Google cu "access home server from internet" sau "cum accesez
serverul de acasa").

#include <SPI.h>
#include <Ethernet.h>

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };


IPAddress ip(192,168,1, 177);

EthernetServer server(80);

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

Ethernet.begin(mac, ip);
server.begin();
Serial.print("adresa IP a server-ului este: ");
Serial.println(Ethernet.localIP());
}

void loop() {

EthernetClient client = server.available();


if (client) {
Serial.println("conectare client nou");
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
if (c == '\n' && currentLineIsBlank) {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connnection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<meta http-equiv=\"refresh\" content=\"5\">");
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("* pe portul analogic ");
client.print(analogChannel);
client.print(" s-a citit valoare ");
client.print(sensorReading);
client.println("<br />");
}
client.println("</html>");
break;
}
if (c == '\n') {
currentLineIsBlank = true;
}
else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
delay(1);
client.stop();
Serial.println("clientul a incheiat sesiunea");
}
}

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Deja am explicat in exemplele precedente ce inseamna adresa MAC si


adresa IP, asa ca nu vom mai relua aici. Prima linie interesanta (si prima
notiune nou introdusa), este cea care declara un server web pe portul 80. Un
server web functioneaza pe unul sau mai multe porturi. Un port este un
identificator pentru un anumit serviciu pe un anumit calculator fizic. Astfel, pe
un calculator fizic putem avea un server web pe portul 80, si un server de baze
de date care raspunde pe portul 3306. Portul 80 este ales de obicei pentru
serverele web, si este presupus in mod obisnuit in browsere cand vrem sa
accesam un site.
Mai departe, in rutina loop se asteapta conectarea unui client web (adica
un vizitator oarecare din Internet) (apelul "server.available()" astepta, fara sa
treaca mai departe, pana cand se conecteaza un vizitator la server). Cand
acesta s-a conectat, este generata o instanta "client", care va face toata treaba
pentru acel vizitator. Mai exact, va incepe prin a genera header-ele HTTP
(necesare pentru ca browser-ul vizitatorului sa stie ce sa faca cu informatia pe
care o primeste de la server – in cazul nostru, sa o afiseze ca text). Urmeaza
apoi un ciclu "for" care citeste toate cele 6 porturi analogice ale placii Arduino
si le trimite catre browser-ul vizitatorului.

Daca deschizi un browser si accesezi serverul pe care tocmai l-ai creat,


vei vedea un rezultat similar cu cel din imagine.
Dat fiind faptul ca nu ai nimic conectat la porturile analogice ale placii
Arduino, valorile citite sunt aleatoare. Daca insa vei conecta un senzor de
lumina brick sau un senzor de temperatura brick, vei vedea imediat ca valorile
capata sens.
Asa cum spuneam si la inceputul acestei sectiuni, ca sa accesezi placa

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino chiar din Internet (si nu de pe laptop cum am testat mai sus), mai
trebuie doar sa setezi router-ul local ca atunci cand cineva il acceseaza din
afara pe un port pe care ti-l alegi tu, sa trimita cererea catre IP-ul alocat placii
Arduino pe portul 80. Pentru detalii despre cum anume sa faci acest lucru, poti
incerca o cautare pe Google cu "access home server from internet" sau "cum
accesez serverul de acasa".

Client Web, cu DNS

In ambele exemple de mai sus in care am folosit placa Arduino ca sa citim


informatie din Internet am avut adresa IP a server-ului scrisa in clar in codul
sursa. Dupa cum am vazut, acest lucru poate cauza probleme atunci cand
adresa IP a server-ului s-a schimbat intre timp. Exista un singur lucru care nu se
schimba, si acesta este domeniul server-ului (numele acestuia – "google.com").
Trecerea de la domeniu la adresa IP se cheama "rezolvarea domeniului" si este
asigurata de o serie de servere dedicate prezente in Internet, numite servere
DNS. Arduino este capabil sa le utilizeze ca sa obtina IP-ul unui anumit server
pe baza domeniului acestuia, ca mai jos. Este exact acelasi exemplu ca mai sus
(cautam pe Google termenul "arduino"), dar de data asta folosind serviciul
DNS.

#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
char serverName[] = "www.google.com";

EthernetClient client;

void setup() {
Serial.begin(9600);
if (Ethernet.begin(mac) == 0) {
Serial.println("Eroare in configurarea folosind DHCP.");
}
delay(1000);
Serial.println("conectare in progres...");

if (client.connect(serverName, 80)) {
Serial.println("conectat");
client.println("GET /search?q=arduino HTTP/1.0");
client.println();
}
else {
Serial.println("conexiune esuata");
}
}

void loop() {
//LA FEL CA IN EXEMPLELE PRECEDENTE

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Multumita librariei excelent scrise, modificarile sunt minimale (doar cele


doua linii marcate cu bold), toata implementarea fiind facuta direct in librarie.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Ultimul tweet al unui user Twitter afisat pe LCD Shield, folosind Ethernet
Shield (sau Arduino Ethernet)

Acest exemplu demonstreaza utilizarea unui Ethernet Shield (sau al unui


Arduino Ethernet) pentru a afisa ultimul tweet al unui utilizator Twitter pe LCD.
Poti folosi orice fel de LCD doresti. In acest exemplu vom folosi un LCD shield,
pentru simplitatea conectarii. Ai la dispozitie doar 32 de caractere pe acest
LCD, asa ca vom folosi facilitatea de scroll, pentru a vedea intreg tweet-ul. LCD
Shield-ul foloseste pinii 2, 3, 4, 5, 6 si 7, in timp ce Ethernet Shield-ul foloseste
pinii 10, 11, 12 si 13, asa ca din fericire nu avem nici un conflict de pini.

Din cauza faptului ca Ethernet Shield este mai inalt decat de obicei,

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

datorita mufei Ethernet, daca incercam sa infigem direct LCD Shield-ul, s-ar
putea ca mufa Ethernet Shield-ului sa atinga anumite contacte de pe spatele
LCD Shield-ului. Pentru a evita acest lucru, vom folosi un set de pini ca cei din
imaginea de mai sus. Vom infige mai intai pinii in Ethernet Shield si apoi in pini
vom infige LCD Shield-ul. In acest fel, ne vom asigura ca exista suficient spatiu
intre Ethernet Shield si LCD Shield.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

#include <SPI.h>
#include <Ethernet.h>
#include <LiquidCrystal.h>
#include <Wire.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

char username[] = "arduino";

byte mac[] = {
0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x01 };
IPAddress ip(192,168,1,20);

EthernetClient client;

const unsigned long requestInterval = 60000;


char serverName[] = "api.twitter.com";

boolean requested;
unsigned long lastAttemptTime = 0;

String currentLine = "";


String tweet = "";
boolean readingTweet = false;

void setup() {

currentLine.reserve(256);
tweet.reserve(150);

Serial.begin(9600);

Serial.println("Incerc sa obtin o adresa IP folosind DHCP:");


if (!Ethernet.begin(mac)) {
Serial.println("esec in obtinerea unei adresa IP prin DHCP, vom folosi
adresa IP setata manual");
Ethernet.begin(mac, ip);
}

Serial.print("Adresa IP:");
Serial.println(Ethernet.localIP());

connectToServer();

lcd.autoscroll();
lcd.clear();
}

void loop() {
if (client.connected()) {
if (client.available()) {
char inChar = client.read();

currentLine += inChar;

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

if (inChar == '\n') {
currentLine = "";
}
if ( currentLine.endsWith("<text>")) {
readingTweet = true;
tweet = "";
}
if (readingTweet) {
if (inChar != '<') {
tweet += inChar;
}
else {
readingTweet = false;
Serial.println(tweet);
lcd.clear();
lcd.print(tweet);
lcd.autoscroll();
client.stop();
}
}
}
}
else if (millis() - lastAttemptTime > requestInterval) {
connectToServer();
}
}

void connectToServer() {
Serial.println("conectare la server...");
if (client.connect(serverName, 80)) {
Serial.println("lansez request HTTP...");
client.print("GET /1/statuses/user_timeline.xml?screen_name=");
client.print(username);
client.println("&count=1 HTTP/1.1");
client.println("HOST: api.twitter.com");
client.println();
}
lastAttemptTime = millis();
}

Constanta username defineste userul Twitter pentru care ne intereseaza


sa obtinem ultimul tweet. Constanta MAC este un identificator unic al placii tale
Ethernet. Este foarte probabil sa il gasesti scris chiar pe placa (ca in poza de
mai jos). Chiar daca shield-ul tau nu are MAC-ul scris pe el, nu este nici o
problema. Poti sa-l folosesti pe cel din codul de mai sus fara probleme. Singura
situatie in care s-ar putea intampla sa ai probleme este aceea in care un alt
echipament din reteaua ta (de exemplu un laptop) sa aiba exact acelasi MAC
(lucru care nu este foarte probabil).

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Constanta ip este adresa IP a placii, pentru cazul in care nu s-a reusit


obtinerea unei adresa IP in mod automat, prin DHCP. Pentru mai multe detalii
despre adrese IP si DHCP, vezi sectiunea dedicata Shield-ului Ethernet.

requestInterval defineste intervalul intre doua actualizari succesive, in


milisecunde. Esti liber sa folosesti ce interval doresti, dar nu mai putin de
20000, pentru a oferi un interval de 20 de secunde minim pentru a se finaliza
executia unei actualizari.
api.twitter.com este URL-ul server-ului Twitter catre care vom lansa
cererile HTTP.
In functia setup se incearca obtinerea unei adrese IP in mod automat,
folosind protocolul DHCP. Daca nu s-a reusit acest lucru, se foloseste adresa IP
setata manual la inceputul programului. connectToServer lanseaza cererea
HTTP catre server-ul Twitter (include in cererea HTTP si username-ul setat la
inceputul programului).
Imediat ce s-a terminat connectToServer, in functia loop incepe citirea
caracterelor trimise de server. Se citeste caracter cu caracter, iar in variabila
currentLine se concateneaza caracterele pentru a obtine intreaga linie (sfarsitul

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

unei linii de text este marcat prin caracterul "\n"). Atunci cand linia curenta
este "<text>", inseamna ca incepand din acest punct, pana cand intalnim
textul "</text>" avem continutul tweet-ului care ne intereseaza. Imediat ce am
intalnit caracterul "<" (care marcheaza inceputul pentru </text>) tweet-ul s-a
incheiat. Putem afisa tweet-ul pe LCD ( lcd.print(tweet) ) si putem inchide
conexiunea la server (client.stop()).
Dupa ce s-au scurs requestInterval milisecunde, este apelata din nou
functia connectToServer, si procesul se reia.
Daca Shield-ul LCD 16X2 ti se pare prea mic, poti folosi orice alt LCD iti
place. Intr-o lectie viitoare vom prezenta exact acelasi proiect folosind insa un
Wifly Shield in loc de Ethernet Shield si un LCD 20X4 pe I2C in loc de LCD-ul
2X16.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Aceasta a fost lectia 8. In final, as vrea sa te rog sa ne oferi feedback


asupra acestei lectii, pentru a ne permite sa le facem mai bune pe
urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe


care il poti accesa dand click aici.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Senzori Atmosferici

Presiune Atmosferica – BMP085

Senzorul BMP085 este un senzor foarte precis produs de firma Bosch, capabil sa masoare
presiunea atmosferica si temperatura. Cum presiunea atmosferica variaza cu altitudinea, pe baza
presiunii atmosferice masurate se poate calcula si altitudinea (lucru foarte util la drone si alte dispozitive
zburatoare). Conectarea senzorului la Arduino se face prin I2C, astfel ca avem nevoie de doar doi pini
(in afara celor doi pini de alimentare). Pentru a citi valorile senzorului recomand o librarie open-source,
disponibila aici : http://www.robofun.ro/senzor_presiune_bmp085 (primul link, "Librarie Arduino").

Dupa instalarea librariei, codul sursa este extrem de simplu, ca mai jos.

Arduino 3.3 V BMP085 VCC


Arduino GND BMP085 GND
Arduino SDA BMP085 SDA
Arduino SCL BMP085 SCL

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

#include <Wire.h>
#include <BMP085.h>

BMP085 dps = BMP085();


long Temperature = 0, Pressure = 0, Altitude = 0;

void setup(void) {
Serial.begin(9600);
Wire.begin();
delay(1000);
dps.init();
delay(5000);
}

void loop(void) {
dps.getTemperature(&Temperature);
dps.getPressure(&Pressure);
dps.getAltitude(&Altitude);

Serial.print("Temp(C):");
Serial.print(Temperature);
Serial.print(" Alt(cm):");
Serial.print(Altitude);
Serial.print(" Pressure(Pa):");
Serial.println(Pressure);
}

Singurul lucru de remarcat aici este delay-ul de 5 secunde din setup, necesar pentru initializarea
senzorului.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Presiune Atmosferica – MPL115A1

MPL115A1 este destul de similar cu BMP085. Difera modul de conectare cu Arduino (I2C in
cazul BMP085 si SPI in cazul MPL115A1). Conectarea se face folosind pinii SPI, ca mai jos.

Arduino 3.3 V MPL115A1 VCC


Arduino GND MPL115A1 GND
Arduino Digital 9 MPL115A1 SDN
Arduino Digital 10 MPL115A1 CSN
Arduino Digital 12 MPL115A1 SDO
Arduino Digital 11 MPL115A1 SDI
Arduino Digital 13 MPL115A1 SCK

Codul sursa integral in vei gasi la adresa:


http://www.robofun.ro/senzor_presiune_atmosferica_MPL115A1

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Temperatura si Umiditate – SHT15

SHT15 este un senzor care masoare presiunea si umiditatea mediului ambiant extrem de precis
(precizie de 0.3 C, si 2 % RH ). Conectarea la Arduino se face folosind doi pini digitali.

Arduino 5 V SHT15 VCC


Arduino GND SHT15 GND
Arduino Digital 9 SHT15 DATA
Arduino Digital 8 SHT15 SCK

Codul sursa integral este disponibil aici -


http://www.robofun.ro/senzor_temperatura_umiditate_sht15 .

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Temperatura si Umiditate – DHT22

Daca nu ai nevoie de o precizie chiar asa de mare ca in cazul SHT15 si te multumesti si cu +/-
0.5 C, atunci DTH22 s-ar putea sa fie alegerea corecta pentru tine. Frecventa de citire pentru acest
senzor este de asemenea destul de scazuta comparata cu SHT15 (poti face cel mult o citire la 2
secunde). Ca necesar de pini, este foarte modest, avand nevoie doar de un singur pin digital pentru
conectarea cu Arduino.

Arduino 5 V DHT22 VCC


Arduino GND DHT22 GND
Arduino Digital 2 DHT22 PIN2
Rezistor 10K conectat intre
DTH22 VCC si DHT22
PIN2

Mai departe, instaleaza libraria pentru Arduino disponibila aici :


http://www.robofun.ro/senzor_umiditate_temperatura_dht22

#include <DHT22.h>
#define DHT22_PIN 2

DHT22 myDHT22(DHT22_PIN);

void setup(void)

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

{
Serial.begin(9600);
Serial.println("DHT22 Library Demo");
}

void loop(void) {
DHT22_ERROR_t errorCode;

delay(2000);
Serial.print("Requesting data...");
errorCode = myDHT22.readData();
switch(errorCode)
{
case DHT_ERROR_NONE:
Serial.print("Got Data ");
Serial.print(myDHT22.getTemperatureC());
Serial.print("C ");
Serial.print(myDHT22.getHumidity());
Serial.println("%");
break;
case DHT_ERROR_CHECKSUM:
Serial.print("check sum error ");
Serial.print(myDHT22.getTemperatureC());
Serial.print("C ");
Serial.print(myDHT22.getHumidity());
Serial.println("%");
break;
case DHT_BUS_HUNG:
Serial.println("BUS Hung ");
break;
case DHT_ERROR_NOT_PRESENT:
Serial.println("Not Present ");
break;
case DHT_ERROR_ACK_TOO_LONG:
Serial.println("ACK time out ");
break;
case DHT_ERROR_SYNC_TIMEOUT:
Serial.println("Sync Timeout ");
break;
case DHT_ERROR_DATA_TIMEOUT:
Serial.println("Data Timeout ");
break;
case DHT_ERROR_TOOQUICK:
Serial.println("Polled to quick ");
break;
}
}

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Temperatura – TMP102

TMP102 este un senzor de temperatura care comunica pe I2C, cu o rezolutie de 0.0625 C si o


precizie de 0.5 C. Alimentarea se face la 3.3 V, iar conectarea la Arduino se face folosind pinii I2C.
Limitele sale sunt -25 C pana la 85 C, iar consumul este de-a dreptul impresionant – 10 microAmperi !.

Arduino 3.3 V TMP102 V+


Arduino GND TMP102 GND
Arduino SDA TMP102 SDA
(Analog 4)
Arduino SCL TMP102 SCL
(Analog 5)
Arduino GND TMP102 ADD0

#include <Wire.h>
int tmp102Address = 0x48;

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

void loop(){
float celsius = getTemperature();
Serial.print("Celsius: ");
Serial.println(celsius);

float fahrenheit = (1.8 * celsius) + 32;


Serial.print("Fahrenheit: ");

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Serial.println(fahrenheit);

delay(200);
}

float getTemperature(){
Wire.requestFrom(tmp102Address,2);

byte MSB = Wire.read();


byte LSB = Wire.read();

int TemperatureSum = ((MSB << 8) | LSB) >> 4;

float celsius = TemperatureSum*0.0625;


return celsius;
}

Senzorul TMP102 are 4 adrese distincte posibile, adresa curenta fiind selectata prin conectarea
pinului ADD0 la GND, 3.3 V, SDA sau respectiv SCL. Astfel, in exemplul de mai sus, pinul ADD0
este conectat la GND si atunci adresa senzorului este 0x48. Daca vom conecta pinul ADD0 la 3.3 V,
atunci adresa senzorului va deveni 0x49. Conectarea pinului ADD0 la pinul SDA va determina adresa
0x4A, iar conectarea la SCL va determina adresa 0x4B. Acest lucru este excelent pentru situatiile in care
avem nevoie de mai multi senzori conectati la acelasi Arduino. Putem astfel conecta pana la cel mult
patru senzori, toti conectati pe acelasi bus I2C. Pentru primul senzor, pinul ADD0 se conecteaza la
GND, pentru al doilea senzor, pinul ADD0 se conecteaza la 3.3V, pentru a treilea senzor, pinul ADD0
se conecteaza la SDA, iar pentru a al patrulea senzor, pinul ADD0 se conecteaza la pinul SCL. Toti
ceilalti pini se conecteaza exact ca mai sus.
In cod, vom avea patru adrese distincte, cate o adresa pentru fiecare senzor, ca mai jos.
#include <Wire.h>
int tmp102Address1 = 0x48;
int tmp102Address2 = 0x49;
int tmp102Address3 = 0x4A;
int tmp102Address4 = 0x4B;

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

void loop(){
float celsius = getTemperature(tmp102Address1);
Serial.print("Celsius, Senzor 1: ");
Serial.println(celsius);

celsius = getTemperature(tmp102Address2);
Serial.print("Celsius, Senzor 2: ");
Serial.println(celsius);

celsius = getTemperature(tmp102Address3);
Serial.print("Celsius, Senzor 3: ");
Serial.println(celsius);

celsius = getTemperature(tmp102Address4);

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Serial.print("Celsius, Senzor 4: ");


Serial.println(celsius);

delay(200);
}

float getTemperature(int address){


Wire.requestFrom(address,2);

byte MSB = Wire.read();


byte LSB = Wire.read();

int TemperatureSum = ((MSB << 8) | LSB) >> 4;

float celsius = TemperatureSum*0.0625;


return celsius;
}

Temperatura la Distanta – MLX90614

MLX90614 este un senzor de temperatura cu o functionalitate unica. Determina temperatura


obiectelor de la distanta, fara a le atinge ! Senzorul functioneaza pe baza determinarii lungimii de unda a
radiatiei infrarosie emisa de obiectul in cauza. Determina temperaturi intre -70 C si 382 C, cu o
rezolutie imensa (0.0034 C !).
Conectarea la Arduino este ceva mai complexa decat de obicei, pentru ca senzorul nu este inclus
pe un montaj, ci montajul va trebui sa il faci tu. Doua rezistoare de 4.7 K si un condensator de 0.1 uF
sunt tot ce iti trebuie.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino 3.3 V MLX90614 PIN2


Arduino GND MLX90614 PIN1
Arduino SDA (Analog 4) MLX90614 PIN3
Arduino SCL (Analog 5) MLX90614 PIN4
Condensator 100nF Conectat intre
MLX90614 PIN1 si
MLX90614 PIN2
Rezistor 4.7 K Conectat intre
MLX90614 PIN3 si
Arduino 3.3V
Rezistor 4.7 K Conectat intre
MLX90614 PIN4 si
Arduino 3.3V

Mai departe, vei avea nevoie sa iti instalezi in mediul tau de dezvoltare Arduino libraria
I2CMaster (disponibila ca download de pe pagina :
http://www.robofun.ro/senzor_infrarosu_MLX90614 ).
Codul sursa integral este disponibil mai jos.

#include <i2cmaster.h>
void setup(){
Serial.begin(9600);
i2c_init();

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

PORTC = (1 << PORTC4) | (1 << PORTC5);


}

void loop(){
int dev = 0x5A<<1;
int data_low = 0;
int data_high = 0;
int pec = 0;

i2c_start_wait(dev+I2C_WRITE);
i2c_write(0x07);

i2c_rep_start(dev+I2C_READ);
data_low = i2c_readAck();
data_high = i2c_readAck();
pec = i2c_readNak();
i2c_stop();

double tempFactor = 0.02;


double tempData = 0x0000;
int frac;

tempData = (double)(((data_high & 0x007F) << 8) + data_low);


tempData = (tempData * tempFactor)-0.01;

float celsius = tempData - 273.15;


float fahrenheit = (celsius*1.8) + 32;

Serial.print("Celsius: ");
Serial.println(celsius);

Serial.print("Fahrenheit: ");
Serial.println(fahrenheit);

delay(1000);
}

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Aceasta a fost lectia 9. In final, as vrea sa te rog sa ne oferi feedback asupra acestei
lectii, pentru a ne permite sa le facem mai bune pe urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe care il poti
accesa dand click aici.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

LCD 16 X 2, LCD 16 X 4, LCD 20 X 4

Toate aceste LCD-uri se interfateaza cu Arduino exact la fel. Singura


diferenta este dimensiunea lor. Astfel, LCD-ul 16 X 2 permite 16 coloane si
doua linii de caractere (adica in total 32 de caractere), LCD-ul 16X4 permite 4
linii (64 de caractere in total), iar cel de 20X4 permite 80 de caractere afisate.
Ca sa-l folosesti cu Arduino, ai nevoie de fire de conectare si de un
potentiometru de 10K pentru reglarea contrastului (nu merge fara el). Schema
de conectare este cea de mai jos (nu este simpla).
Daca esti la primele tale teste cu Arduino, din pacate s-ar putea sa
gasesti conectarea LCD-ului o experienta frustranta. Sunt destul de multe fire
de conectat, si daca gresesti unul singur nu-ti va functiona. Iti recomand sa faci
montajul incet si sa verifici de cateva ori fiecare conexiune. Daca ai ajuns la
final, vei avea atat de multe fire incat iti va fi dificil sa vezi care fir duce unde.
Verifica cu atentie pe parcurs ca sa fii sigur ca fiecare fir duce acolo unde
trebuie.
Daca totusi nu ti-a iesit si vrei sa incerci ceva mai simplu, iti recomand
shield-ul cu LCD 2X16 (http://www.robofun.ro/bricks/shield-lcd-16x2) care nu
face altceva decat sa-ti ascunda conexiunile complicate.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino 5 V Pin1 Potentiometru


Arduino GND Pin3 Potentiometru
Pin2 Potentiometru VO (PIN3) LCD
Arduino GND GND (PIN1) LCD
Arduino GND RW (PIN5) LCD
Arduino 5 V VCC (PIN2) LCD
Arduino Digital 12 RS (PIN4) LCD
Arduino Digital 11 E (PIN6) LCD
Arduino Digital 5 D4 (PIN11) LCD

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino Digital 4 D5 (PIN12) LCD


Arduino Digital 3 D6 (PIN13) LCD
Arduino Digital 2 D7 (PIN14) LCD

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
lcd.begin(16, 2);
lcd.print("hello, world!");
}

void loop() {
lcd.setCursor(0, 1);
lcd.print(millis()/1000);
}

Codul sursa de mai sus utilizeaza libraria LiquidCrystal (inclusa in mod


standard in mediul de dezvoltare Arduino). Singura modificare pe care va trebui
sa o faci cand folosesti un alt tip de LCD este sa schimbi parametrii din rutina
de initializare. Astfel, pentru un LCD 20X4, linia 3 se schimba la "lcd.begin(20,
4)".

Alte rutine interesante ale librariei LiquidCrystal sunt mai jos :


• clear() - curata ecranul complet. Se apeleaza fara parametri – "lcd.clear()"
• home() - muta cursorul in partea din stanga, sus. Se apeleaza fara parametri
– "lcd.home()"
• setCursor() - muta cursorul la pozitia specificata. Textul care urmeaza a fi
scris este scris la pozitia specificata de aceasta metoda. Astfel, pentru a scrie
text pe linia 2, coloana 4, vom apela "lcd.setCursor(1,3); lcd.print("TEXT");"
• noDisplay() - opreste LCD-ul, fara a pierde textul afisat. Se apeleaza fara
parametri – "lcd.noDisplay()"
• display() - porneste LCD-ul dupa ce a fost oprit folosind "noDisplay". Se
apeleaza fara parametri – "lcd.display()"
• scrollDisplayLeft() - deplaseaza textul afisat pe LCD cu un caracter spre
stanga. Se apeleaza fara parametri – "lcd.scrollDisplayLeft()"
• scrollDisplayRight() - deplaseaza textul afisat pe LCD cu un caracter spre
dreapta. Se apeleaza fara parametri – "lcd.scrollDisplayRight()"

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

LCD 16 X 2 pe I2C, LCD 20 X 4 pe I2C

Ambele LCD-uri sunt LCD-urile obisnuite despre care am discutat mai sus,
carora li s-a atasat o placa suplimentara care comunica pe I2C cu Arduino si
seteaza cei 8 pini pentru controlul LCD-ului la valorile care trebuie astfel incat
pe LCD sa fie afisat text-ul care trebuie. In acest fel, intre Arduino si LCD sunt
necesare doar doua fire (SDA si SCL), in afara firului de GND si alimentare.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Conexiunile la Arduino sunt ca in cele doua imagini de mai jos. Ultimii doi
pini din mufa lipita pe placa LCD-ului nu se folosesc. In rest, de la stanga la
dreapta, avem SDA (se conecteaza la pinul analogic 4 pe Arduino UNO sau la
pinul SDA pe Arduino Leonardo), SCL (se conecteaza la pinul analogic 5 pe
Arduino UNO sau la pinul SCL pe Arduino Leonardo), 5V (se conecteaza la pinul
5V pe Arduino, si pinul GND (se conecteaza la pinul GND).

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino UNO

Arduino 5 V LCD 5V
Arduino GND LCD GND
Arduino Analog 4 LCD SDA
Arduino Analog 5 LCD SCL

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino Leonardo

Arduino 5 V LCD 5V
Arduino GND LCD GND
Arduino SDA LCD SDA
Arduino SCL LCD SCL

Urmatorul pas este actualizarea librariei LCD, astfel incat sa suporte si


comunicarea I2C.
Mergi la adresa http://www.robofun.ro/lcd_20x4_i2c_negru_verde si
descarca libraria din acea pagina. Este bine sa o incerci prima data pe cea de
pe GITHUB, care este intotdeauna la zi. Dupa ce ai descarcat-o, inchide mediul
Arduino si deschide folder-ul "libraries" din folder-ul in care este instalat mediul
Arduino. Folder-ul "libraries" ar trebui sa arate similar cu imaginea de mai jos.
Deschide si folder-ul "LiquidCrystal" ca sa vezi ce fisiere sunt in interior.
Ar trebui sa vezi ceva similar cu ce este mai jos.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Sterge apoi tot ceea ce este in acest folder si inlocuieste cu fisierele


descarcate anterior. Ar trebui sa fie similar cu imaginea de mai jos.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Porneste acum mediul de dezvoltare Arduino si incearca programul de


mai jos.

#include "Wire.h"
#include "LiquidCrystal.h"
LiquidCrystal lcd(0);
void setup() {
lcd.begin(20, 4);

lcd.setBacklight(HIGH);
lcd.print("hello, world 0 !");
lcd.setCursor(0, 1);
lcd.print("hello, world 1 !");
lcd.setCursor(0, 2);
lcd.print("hello, world 2 !");
lcd.setCursor(0, 3);
lcd.print("hello, world 3 !");
}

void loop() {

Daca LCD-ul tau nu arata ca mai sus, pe spatele placutei rosii vei gasi un
potentiometru de culoare albastra. Acest potentiometru stabileste contrastul
LCD-ului, si probabil ca s-a miscat in timpul transportului. Folosind o surubelnita
mica, un varf de cutit ascutit, foarfeca sau pila de unghii, roteste-l usor si
urmareste in acelasi timp textul pe LCD pana cand devine foarte clar.
Si partea frumoasa abia acum vine ! Cu acest tip de LCD, poti conecta
simultan pana la opt LCD-uri la acelasi Arduino, folosind aceeasi doi pini I2C.
Pentru aceasta, intoarce LCD-ul pe spate, si observa cei 3 jumperi pentru

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

setarea adresei I2C. In mod obisnuit, nici unul dintre acesti jumperi nu este
lipit, asa ca adresa shield-ului este zero (lucru pe care il vezi in cod la linia
LiquidCrystal lcd(0)). Fiecare LCD va trebuie sa aiba o adresa I2C diferita, asa
ca ceea ce ai de facut este sa folosesti un letcon si putin fludor pentru a
conecta unul sau mai multi jumperi impreuna. Adresele sunt in cod binar, astfel
ca folosind cei trei jumperi poti obtine exact opt adrese. Pentru a conecta un
jumper, incalzeste ambele pad-uri, apoi adauga fludor si intinde fludorul astfel
incat sa faca contact intre ambele pad-uri, ca mai jos.

Pentru a conecta mai multe LCD-uri la acelasi Arduino, tot ce ai de facut


este conectezi toti pinii de SDA impreuna de la toate LCD-urile, toti pinii SCL
impreuna, si la fel si GND si 5V. In prealabil, ai grija sa setezi adrese I2C diferite
lipind cei trei jumperi de adresa in configuratii diferite. Apoi, in cod definesti
mai multe obiecte de tip LCD, ca mai jos.

#include "Wire.h"
#include "LiquidCrystal.h"

LiquidCrystal lcd1(0);
LiquidCrystalc lcd2(1);
LiquidCrystal lcd3(2);

void setup() {
lcd1.begin(20, 4);
lcd2.begin(20, 4);
lcd.3begin(20, 4);

lcd1.setBacklight(HIGH);
lcd1.print("LCD1, hello, world 0 !");
lcd1.setCursor(0, 1);
lcd1.print("LCD1, hello, world 1 !");
lcd1.setCursor(0, 2);
lcd1.print("LCD1, hello, world 2 !");
lcd1.setCursor(0, 3);
lcd1.print("LCD1, hello, world 3 !");

lcd2.setBacklight(HIGH);
lcd2.print("LCD2, hello, world 0 !");

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

lcd2.setCursor(0, 1);
lcd2.print("LCD2, hello, world 1 !");
lcd2.setCursor(0, 2);
lcd2.print("LCD2, hello, world 2 !");
lcd2.setCursor(0, 3);
lcd2.print("LCD2, hello, world 3 !");

lcd3.setBacklight(HIGH);
lcd3.print("LCD3, hello, world 0 !");
lcd3.setCursor(0, 1);
lcd3.print("LCD3, hello, world 1 !");
lcd3.setCursor(0, 2);
lcd3.print("LCD3, hello, world 2 !");
lcd3.setCursor(0, 3);
lcd3.print("LCD3, hello, world 3 !");
}

void loop() {

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Aceasta a fost lectia 10. In final, as vrea sa te rog sa ne oferi feedback


asupra acestei lectii, pentru a ne permite sa le facem mai bune pe
urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe


care il poti accesa dand click aici.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

MP3 Player Shield

Shield-ul MP3 Player contine chip-ul VS1053b, capabil sa decodeze


stream-uri MP3, OGG Vorbis, AAC, WMA, MIDI, si de asemenea contine si un slot
de card microSD pentru incarcarea fisierelor audio. Shield-ul mai contine si un
conector pentru casti sau boxe audio, astfel ca in final, ceea ce obtii este un
player MP3 complet.
Ce ai tu de facut este sa citesti informatia stocata pe SD card si sa o
trimiti catre chip-ul MP3, atunci cand acesta o solicitia. Suna complicat in
teorie, dar din fericire exista deja mai multe librarii care fac asta in locul tau.
Cea mai interesanta este libraria disponibila ca download la adresa
http://www.robofun.ro/mp3_player_shield (link-ul "Librarie pentru Arduino").
Fisierul .zip pe care il descarci contine atat libraria MP3, cat si libraria pentru SD
card. Va trebui sa le copiezi pe ambele in directorul "libraries" din mediul tau de
dezvoltare Arduino. Codul sursa este relativ simplu de inteles, toata partea
complexa este ascunsa de librarie.

#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <SFEMP3Shield.h>

SFEMP3Shield MP3player;

byte temp;
byte result;

char title[30];
char artist[30];
char album[30];

void setup() {

Serial.begin(115200);

result = MP3player.begin();
if(result != 0) {
Serial.print("Error code: ");
Serial.print(result);
Serial.println(" when trying to start MP3 player");
}

Serial.println("STARTED");

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

void loop() {
result = MP3player.playMP3("melodie1.mp3");
delay(3000);
if (MP3player.isPlaying()){
MP3player.stopTrack();
}

Avem posibilitatea de a porni redarea unui fisier mp3 la alegere, putem


verifica daca s-a terminat intre timp redarea audio (daca s-a terminat fisierul)
sau putem opri redarea intr-un moment ales de noi. Spre exemplu, in codul
sursa de mai sus, pornim redarea pentru fisierul "melodie1.mp3", si daca dupa
3 secunda fisierul inca nu s-a terminat, atunci il oprim noi fortat.
Libraria mai permite sa facem fastForward pe un fisier pana la o anume
pozitie folosind "MP3player.skipTo(<pozitieInSecunde>);" si putem determina
pozitia curenta ("MP3player.currentPosition();"). Spre exemplu,
"MP3player.skipTo(30000);" va derula mp3-ul curent pana la secunda 30, iar
"int pozitie = MP3player.currentPosition();" va incarca in variabila "pozitie"
timpul in milisecunde de la inceperea redarii.
Pinii ocupati de acest shield sunt 2, 3, 4, 6, 7, 8, 9, 11, 12, 13 (aproape
toti, pentru Arduino UNO). Daca ai nevoie de mai multi pini, poti folosi Arduino
Mega in locul lui Arduino UNO sau poti schimba MP3 Player Shield-ul cu un MP3
Trigger (care are nevoie de mult mai putini pini).

MP3 Trigger

MP3 Trigger este varianta mult imbunatatita a lui shield-ului MP3 Player
prezentat in sectiunea anterioara. Pe langa chip-ul capabil sa redea MP3-uri, SD
Card-ul deja prezent pe placa, MP3 Trigger-ul are in plus si un microcontroller
pre-programat. Astfel, numarul de pini necesari pentru interfatarea cu Arduino
scade drastic (doar doi pini sunt necesari) si in plus, MP3 Trigger-ul poate
functiona chiar si standalone, fara Arduino. Dat fiind ca este cel mai simplu, sa
incepem cu acest mod de functionare.
MP3 Trigger-ul ofera 18 pini, fiecare dintre ei declansand redarea melodiei
al carei nume incepe cu numarul asociat pinului. Astfel, spre exemplu, atunci
cand pinul 3 este conectat la pinul GND, este redata melodia al carei nume
incepe cu "003" (un exemplu de nume valid este "003 Avion cu Motor.mp3".). O
schema de conectare folosind butoane brick este mai jos. Am pus in schema
doar doua butoane, pentru exemplificare. Evident ca tu poti conecta cate ai
nevoie, maxim 18 butoane.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Buton 1 VCC MP3 Trigger TRIG18 (pinul din interior)


Buton 1 OUT MP3 Trigger TRIG18 (pinul din exterior)
Buton 2 VCC MP3 Trigger TRIG9 (pinul din interior)
Buton 2 OUT MP3 Trigger TRIG9 (pinul din exterior)

Pinii din interior marcati "TRIGNN" sunt conectati la microcontroller-ul


placii, si atunci cand unul dintre acesti pini este conectat la GND, incepe
redarea melodiei corespunzatoare de pe SD Card. In mod convenabil, toti pinii
din sirul exterior sunt conectati deja la pinul GND. Tot ce ai tu de facut atunci
cand vrei sa porneasca redarea unei melodii, este sa faci contact intre pinul din
interior si pinul din exterior. Butonul brick, in conectarea de mai sus,
conecteaza pinul din exterior (GND) cu pinul din interior (TRIGNN) atunci cand
este apasat. Acest mod de utilizare este foarte util pentru situatiile cand ai
nevoie sa pornesti redarea unei melodii MP3 ca raspuns la un stimul extern,
situatie in care nu mai ai nevoie de Arduino. Pentru situatiile mai complexe,
MP3 Trigger-ul ofera un API elaborat, accesibil peste un protocol serial TTL,
folosind Arduino. Schema de conectare este cea de mai jos.

Arduino 5V MP3 Trigger USBVCC


Arduino GND MP3 Trigger GND
Arduino Digital 7 MP3 Trigger TX
Arduino Digital 8 MP3 Trigger RX

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Mai departe, tot ce ai de facut este sa folosesti libraria SoftwareSerial pe


pinii 7 si 8 si sa-i trimiti placii MP3 Trigger comenzi peste conexiunea seriala.
Cele mai des folosite comenzi sunt disponibile mai jos.

Comanda: Start/Stop
Numar de bytes: 1
Byte de comanda: ‘O’
Functionare: Daca exista o melodie care este redata la momentul primirii
comenzii, se opreste redarea. Altfel, incepe redarea.

Comanda: Inainte
Numar de bytes: 1
Byte de comanda: ‘F’
Functionare : Urmatoarea melodie MP3 este redata.

Comanda: Inapoi
Numar de bytes: 1
Byte de comanda: ‘R’
Functionare: Melodia precedenta MP3 este redata.

Comanda: Trigger (binary)


Numar de bytes: 2
Byte de comanda: ‘t’
Byte de date: n = 1 to 255
Functionare: Daca exista, melodia cu numele “NNNxxxx.MP3” este redata,
unde NNN is echivalentul ASCII al bitului de comanda.

Comanda: Play (binary)


Numar de bytes: 2
Byte de comanda: ‘p’
Byte de date: n = 0 to 255
Functionare: Daca exista, melodia numarul n va fi redata.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Comanda: Set Volume (binary)


Numar de bytes: 2
Byte de comanda: ‘v’
Byte de date: n = 0 to 255
Comments: Volumul va fi setat la valoarea n. Volumul maxim se obtine cu
valoarea "0", iar volumul minim in jur de 100.

Toata gama de comenzi suportata este prezentata pe larg in manual de


utilizare al placii, disponibil la adresa http://www.robofun.ro/mp3_trigger_v2

Music Instrument Shield

Music Instrument Shield este capabil sa genereze note muzicale conform


standardului MIDI. Shield-ul comunica serial cu Arduino, pe pinii digitali 2 si 3,
pinul 4 digital functionand drept pin de reset. Controlul shield-ului se face
trimitand comenzi pe interfata seriala formata din pinii 2 si 3. Comenzile seriale
de control nu sunt foarte simple (lucru care se datoreaza protocolului MIDI,
care, in opinia mea, este destul de incurcat).
Shield-ul este capabil sa redea 248 de instrumente, de la cele mai
comune (pian, harpa, acordeon, chitara), pana la unele destul de ciudate (latrat
de caine, impuscatura, elicopter). Instrumentele sunt organizate in 3 "bank-
uri".

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Cea mai simpla abordare pentru a intelege modul cum se foloseste acest
shield este sa urmarim mai jos un exemplu de program scris de Nathan Seidle
de la Sparkfun, program care genereaza cate zece note pentru fiecare
instrument inclus.

/*
2-12-2011
Spark Fun Electronics 2011
Nathan Seidle

This code is public domain but you buy me a beer if you use this and we
meet someday (Beerware license).

This code works with the VS1053 Breakout Board and controls the VS1053 in
what is called Real Time MIDI mode.
To get the VS1053 into RT MIDI mode, power up the VS1053 breakout board
with GPIO0 tied low, GPIO1 tied high.

I use the NewSoftSerial library to send out the MIDI serial at 31250bps.
This allows me to print regular messages
for debugging to the terminal window. This helped me out a ton.

5V : VS1053 VCC
GND : VS1053 GND
D3 (SoftSerial TX) : VS1053 RX
D4 : VS1053 RESET

Attach a headphone breakout board to the VS1053:


VS1053 LEFT : TSH

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

VS1053 RIGHT : RSH


VS1053 GBUF : GND

When in the drum bank (0x78), there are not different instruments, only
different notes.
To play the different sounds, select an instrument # like 5, then play
notes 27 to 87.

To play "Sticks" (31):


talkMIDI(0xB0, 0, 0x78); //Bank select: drums
talkMIDI(0xC0, 5, 0); //Set instrument number
//Play note on channel 1 (0x90), some note value (note), middle velocity
(60):
noteOn(0, 31, 60);

*/
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //Soft TX on 3, we don't use RX in this code

byte note = 0; //The MIDI note value to be played


byte resetMIDI = 4; //Tied to VS1053 Reset line
byte ledPin = 13; //MIDI traffic inidicator
int instrument = 0;

void setup() {
Serial.begin(57600);

//Setup soft serial for MIDI control


mySerial.begin(31250);

//Reset the VS1053


pinMode(resetMIDI, OUTPUT);
digitalWrite(resetMIDI, LOW);
delay(100);
digitalWrite(resetMIDI, HIGH);
delay(100);
}

void loop() {

talkMIDI(0xB0, 0x07, 120); //0xB0 is channel message, set channel volume


to near max (127)

/*
//Demo Basic MIDI instruments, GM1
//=================================================================
Serial.println("Basic Instruments");
talkMIDI(0xB0, 0, 0x00); //Default bank GM1

//Change to different instrument


for(instrument = 0 ; instrument < 127 ; instrument++) {

Serial.print(" Instrument: ");


Serial.println(instrument, DEC);

talkMIDI(0xC0, instrument, 0); //Set instrument number. 0xC0 is a 1

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

data byte command

//Play notes from F#-0 (30) to F#-5 (90):


for (note = 30 ; note < 40 ; note++) {
Serial.print("N:");
Serial.println(note, DEC);

//Note on channel 1 (0x90), some note value (note), middle velocity


(0x45):
noteOn(0, note, 60);
delay(50);

//Turn off the note with a given off/release velocity


noteOff(0, note, 60);
delay(50);
}

delay(100); //Delay between instruments


}
//=================================================================
*/

//Demo GM2 / Fancy sounds


//=================================================================
Serial.println("Demo Fancy Sounds");
talkMIDI(0xB0, 0, 0x78); //Bank select drums

//For this bank 0x78, the instrument does not matter, only the note
for(instrument = 30 ; instrument < 31 ; instrument++) {

Serial.print(" Instrument: ");


Serial.println(instrument, DEC);

talkMIDI(0xC0, instrument, 0); //Set instrument number. 0xC0 is a 1


data byte command

//Play fancy sounds from 'High Q' to 'Open Surdo [EXC 6]'
for (note = 27 ; note < 87 ; note++) {
Serial.print("N:");
Serial.println(note, DEC);

//Note on channel 1 (0x90), some note value (note), middle velocity


(0x45):
noteOn(0, note, 60);
delay(50);

//Turn off the note with a given off/release velocity


noteOff(0, note, 60);
delay(50);
}

delay(100); //Delay between instruments

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

/*
//Demo Melodic
//=================================================================
Serial.println("Demo Melodic? Sounds");
talkMIDI(0xB0, 0, 0x79); //Bank select Melodic
//These don't sound different from the main bank to me

//Change to different instrument


for(instrument = 27 ; instrument < 87 ; instrument++) {

Serial.print(" Instrument: ");


Serial.println(instrument, DEC);

talkMIDI(0xC0, instrument, 0); //Set instrument number. 0xC0 is a 1


data byte command

//Play notes from F#-0 (30) to F#-5 (90):


for (note = 30 ; note < 40 ; note++) {
Serial.print("N:");
Serial.println(note, DEC);

//Note on channel 1 (0x90), some note value (note), middle velocity


(0x45):
noteOn(0, note, 60);
delay(50);

//Turn off the note with a given off/release velocity


noteOff(0, note, 60);
delay(50);
}

delay(100); //Delay between instruments


}
*/
}

//Send a MIDI note-on message. Like pressing a piano key


//channel ranges from 0-15
void noteOn(byte channel, byte note, byte attack_velocity) {
talkMIDI( (0x90 | channel), note, attack_velocity);
}

//Send a MIDI note-off message. Like releasing a piano key


void noteOff(byte channel, byte note, byte release_velocity) {
talkMIDI( (0x80 | channel), note, release_velocity);
}

//Plays a MIDI note. Doesn't check to see that cmd is greater than 127, or
// that data values are less than 127
void talkMIDI(byte cmd, byte data1, byte data2) {
digitalWrite(ledPin, HIGH);

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

mySerial.write(cmd);
mySerial.write(data1);

//Some commands only have one data byte. All cmds less than 0xBn have 2
//data bytes
//(sort of: http://253.ccarh.org/handout/midiprotocol/)
if( (cmd & 0xF0) <= 0xB0)
mySerial.write(data2);

digitalWrite(ledPin, LOW);
}

Primul lucru la care merita sa ne oprim este declaratia conexiunii seriale


de tip sofware pe pinii 2 si 3 : "SoftwareSerial mySerial(2, 3);". Vom folosi
aceasta conexiune seriala pentru a trimite date catre shield. Rata de transfer
pentru aceasta conexiune seriala (rata presetata in shield) este de 31250 bps
(motiv pentru care avem in setup linia mySerial.begin(31250)). Tot in setup
dam o comanda de reset shield-ului (folosim pinul 4 digital, care este conectat
la pinul de reset al shield-ului, pin pe care il coboram in LOW si apoi il ridicam
in HIGH dupa 100 de milisecunde).
Prima instructiune din loop este talkMIDI(0xB0, 0x07, 120), care seteaza
volumul shield-ului la valoarea 120 (sunt posibile 127 de valori, intre 0 si 127).
Codul este apoi structurat in 3 sectiuni ("Demo Basic MIDI instruments",
"Demo GM2 / Fancy sounds" si "Demo Melodic"). La inceputul fiecarei sectiuni
avem cate o comanda care seteaza "bank-ul" (una dintre cele trei categorii de
instrumente). Astfel, la inceputul primei sectiune avem comanda
"talkMIDI(0xB0, 0, 0x00)", care seteaza bank-ul de instrumente MIDI clasice,
apoi la inceputul celei de-a doua sectiuni avem "talkMIDI(0xB0, 0, 0x78)" care
seteaza bank-ul cu instrumente de percutie, iar apoi in cea de-a treia sectiune
avem "talkMIDI(0xB0, 0, 0x79)", care seteaza bank-ul de instrumente melodice.
In prima sectiune avem doua instructiuni for. Prima instructiune for
cicleaza printre cele 128 de instrumente disponibile in acest bank, iar cel de-al
doilea for genereaza 10 note muzicale pentru fiecare instrument. Comanda
interesanta in aceasta sectiune este "talkMIDI(0xC0, instrument, 0)", care
seteaza instrumentul care va reda notele muzicale. Pentru bank-ul 0X00 (setat
anterior prin comanda talkMIDI(0xB0, 0, 0x00), avem 128 de instrumente
posibile, intre 0 si 128. Cel de-al doilea for genereaza zece note pentru fiecare
instrument. Redarea unui note muzicale este pornita cu "noteOn(0, note, 60)"
si este oprita cu "noteOff(0, note, 60)".
Cea de-a doua sectiune ("Demo GM2 / Fancy sounds") este ceva mai
speciala decat celelalte doua. Acest lucru se intampla din cauza protocolului
MIDI, care specifica faptul ca atunci cand este selectat bank-ul cu instrumente
de percutie, comanda care seteaza instrumentul nu mai are nici un efect, ci
fiecare instrument este de fapt o nota. Alt mod de a spune acelasi lucru este ca
in bank-ul cu instrumente de percutie este un singur instrument cu foarte

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

multe note, iar fiecare nota de fapt reda un alt instrument. Prima comanda din
aceasta sectiune selecteaza bank-ul cu instrumente de percutie
("talkMIDI(0xB0, 0, 0x78)"). Urmatoarea instructiune for va face exact un singur
ciclu (pentru ca asa cum am spus mai sus, instrumentul nu conteaza in cazul
bank-ului cu instrumente de percutie. A doua instructiune for din aceasta
sectiune cicleaza intre 27 si 87, cele 60 de instrumente disponibile pentru
bank-ul de percutie. Instructiunea "noteOn(0, note, 60)" genereaza o nota pe
cate unul dintre cele 60 de instrumente.
Cea de-a treia sectiune este perfect similara cu prima sectiune, doar ca in
bank-ul cu instrumente melodice instrumentele sunt intre 27 si 87.
Sa analizam acum mai atent functia noteOn, care genereaza o anumita
nota muzicala. Functia noteOn primeste trei parametri. Cel de-al doilea
parametru este nota muzicala, iar ultimul parametru reprezinta cat de
"puternic" este generata nota (daca ne gandim ca folosim un pian, atunci
ultimul parametru reprezinta cat de puternic apasam pe clapa pianului).
In rezumat :
–3 bank-uri cu instrumente
–talkMIDI(0xB0, 0, 0x00) – selecteaza bank-ul cu instrumente clasice
–talkMIDI(0xB0, 0, 0x78) – selecteaza bank-ul cu instrumente de percutie
–talkMIDI(0xB0, 0, 0x79) – selecteaza bank-ul cu instrumente melodice
–noteOn(0, note, 120) – reda nota muzicala note; pentru bank-ul 0x78 valoarea
lui note selecteaza si instrumentul muzical (pentru bank-ul 0x78, valorile
posibile pentru note sunt intre 27 si 87).
–noteOff(0, note, 120) – opreste redarea notei muzicala note;
–talkMIDI(0xB0, 0x07, volum) – stabileste volumul instrumentului; valoarea
pentru volum este intre 0 si 127.
–talkMIDI(0xC0, instrument, 0) – stabileste instrumentul care va reda notele
muzicale; acest lucru este valabil doar pentru bank-urile 0X00 si 0X79; pentru
bank-ul 0X78, aceasta comanda nu are nici un efect.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Aceasta a fost lectia 11. In final, as vrea sa te rog sa ne oferi feedback


asupra acestei lectii, pentru a ne permite sa le facem mai bune pe
urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe


care il poti accesa dand click aici.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

WiFly Shield

Daca ai nevoie sa obtii informatii direct din Internet folosind Arduino, sau
sa ai un server web ruland pe Arduino si vrei sa-l accesezi tu din Internet, si
toate astea fara fir de retea, atunci WiFly Shield este ceea ce ai nevoie.
Functioneaza prin WIFI, se conecteaza la un router si iti ofera conexiune la
Internet pe Arduino. Daca nu iti este foarte clar cum functioneaza o retea de
calculatoare (termeni gen IP, DNS, MAC, DHCP iti suna ciudat), atunci iti
recomand sa citesti mai intai sectiunea in care se discuta despre shield-ul
Ethernet pentru Arduino, sectiune in care am prezentat si aceste concepte.
Libraria de care vei avea nevoie in codul de mai jos o gasesti in aceasta
pagina – http://www.robofun.ro/wifly_shield, descarc-o si instaleaz-o in mediul
tau Arduino inainte de a rula exemplul de mai jos.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

WiFly Shield – Client Web

//pune "" la ambele daca nu ai parola la WIFI


#define SSID "networkID"
#define PASSPHRASE "password"

#include "WiFly.h"
#include "Credentials.h"

Client client("google.com", 80);

void setup() {

Serial.begin(9600);
WiFly.begin();
if (!WiFly.join(SSID, PASSPHRASE)) {
Serial.println("Conectare la reteaua WIFI esuata.");
}

Serial.println("Conectare in progres...");

if (client.connect()) {
Serial.println("Conectare reusita !");
client.println("GET /search?q=arduino HTTP/1.0");

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

client.println();
} else {
Serial.println("Conectare esuata");
}

void loop() {
if (client.available()) {
char c = client.read();
Serial.print(c);
}

if (!client.connected()) {
Serial.println();
Serial.println("disconnecting.");
client.stop();
for(;;)
;
}
}

Daca ai parcurs deja sectiunea despre Ethernet shield, vei vedea ca ceea
ce avem mai sus seamana foarte mult cu codul de acolo. Practic, se modifica
doar modul de conectare la retea. Sunt de remarcat cele doua constante de la
inceputul programului, care iti permit sa declari care este identificatorul tau de
retea WIFI si care este parola. Daca ai o retea fara parola, pune "" in loc de
parola si de id de retea.
Codul se conecteaza la serverul google.com si afiseaza in Serial Monitor
rezultatele cautarii pentru termenul "arduino" (tu vei vedea informatie in
format HTML, asa cum am explicat la sectiunea despre Ethernet Shield).

WiFly Shield – Server Web

//pune "" la ambele daca nu ai parola la WIFI


#define SSID "networkID"
#define PASSPHRASE "password"

#include "WiFly.h"
#include "Credentials.h"

Server server(80);

void setup() {
WiFly.begin();
if (!WiFly.join(SSID, PASSPHRASE)) {
Serial.println("Conectare la reteaua WIFI esuata.");
}

Serial.begin(9600);
Serial.print("IP: ");

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Serial.println(WiFly.ip());

server.begin();
}

void loop() {
Client client = server.available();
if (client) {
boolean current_line_is_blank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (c == '\n' && current_line_is_blank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();

for (int i = 0; i < 6; i++) {


client.print("* pe portul analogic ");
client.print(i);
client.print(" s-a citit valoarea ");
client.print(analogRead(i));
client.println("<br />");
}
break;
}
if (c == '\n') {
current_line_is_blank = true;
} else if (c != '\r') {
current_line_is_blank = false;
}
}
}
delay(100);
client.stop();
}
}

Exemplul de mai sus creaza un server web care ruleaza pe placa Arduino
si la fiecare cerere din browser raspunde cu valorile de pe porturile analogice,
ca mai jos. IP-ul server-ului este alocat in mod dinamic de router, asa ca, pentru
a sti care este adresa pe care o folosesti in browser, iti recomand sa deschizi
Serial Monitor si sa vezi in debug IP-ul alocat placii.

Stocarea online a datelor culese de Arduino, folosind Google Docs

Google Docs reprezinta o solutie excelenta pentru a loga online date


culese cu Arduino. Temperatura, umiditatea sau presiunea atmosferica sunt
exemple foarte bune in acest sens. Trimiterea lor online intr-un document Excel
se bazeaza pe functionalitatea Forms, oferita de Google Docs. Ideea de

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

principiu este de a genera un request HTTP din Arduino, care request sa fie
perfect similar cu cel generat de pagina din form-ul Google. Astfel, Google este
"pacalit" sa creada ca datele trimise de Arduino sunt de fapt trimise de un form
creat cu Google Docs.
Pentru acest proiect ai nevoie un Arduino cu conectare la Internet. Ai de
ales intre Arduino Ethernet sau Arduino UNO + Ethernet Shield. Senzorii sunt la
alegerea ta, in functie de ce date vrei sa trimiti in Google Docs. Pentru
exemplul de mai jos, eu am ales un BMP085 (ca sa masor presiunea
atmosferica si temperatura), si un HIH-4030 pentru masurarea umiditatii.
Evident ca tu poti alege ce senzori doresti.
Mai departe, acceseaza http://docs.google.com si creaza un document tip
spreasheet ("CREATE", apoi "Spreadsheet"). Ar trebui sa vezi un document
similar unui document Excel. Din meniul "Tools", alege "Create a form". Form-ul
creat ar trebui sa aiba cate un camp de tip "Text" pentru fiecare senzor pe care
il vei trimite catre Google Docs. Spre exemplu, eu am creat un camp
"temperatura", un camp "umiditate" si un camp "presiune", toate de tip "Text".
Selecteaza apoi din meniul "Form (0)" intrarea "Go to live form". Vei
vedea formularul creat de Google Docs pentru culegerea datelor. Mai departe,
va trebui sa analizezi codul sursa al paginii (in functie de browser-ul pe care il
folosesti, acest lucru se face diferit – spre exemplu in Chrome trebuie sa dai
click dreapta si apoi sa selectezi "View page source"). In codul sursa al paginii
localizeaza sirul de caractere "formkey=". Vei gasi ceva de genul
"formkey=dE9MTmlMc3N1RVNfdVJIRkFMNDltaXc6MQ". Acest sir de caractere
reprezinta identificatorul unic al formularului tau, identificator pe care Arduino il
va utiliza ca sa trimita informatiile. Localizeaza si campurile in care introduci
informatia utila (va fi simplu, pentru ca vor fi prefixate de numele campurilor
pe care le-ai dat tu cand ai creat formularul – vezi si imaginea de mai jos).
Numele acestor campuri ar trebui sa fie ceva de genul "entry.0.single",
"entry.1.single", "entry.2.single" si tot asa pentru toate campurile care le-ai
declarat.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Mai departe, ca sa trimita datele catre Google, Arduino va trimite o cerere


HTTP catre serverul Google, care cerere va fi identica cu cea pe care o trimite
browser-ul atunci cand apesi pe butonul "Submit" din formular. Practic, serverul
Google va fi convins ca acele date vin din formularul obisnuit si nu din Arduino.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Codul sursa integral pentru Arduino il gasesti aici -


http://robofun.ro/blog/cum-sa-trimiti-loghezi-pe-google-docs-temperatura-
presiunea-atmosferica-si-umiditatea-direct-din-arduino . In cele ce urmeaza
vom analiza partile interesante din cod. Chiar la inceput ai o declaratie de
forma "char formkey[] = "dG9HWmNXWjNRdWhBWG5ITlpNeUVBU2c6MQ";"
Aici va trebui sa modifici cheia din cod cu cheia din documentul tau, pe care ai
obtinut-o mai sus. Mai departe, in functia "loop" vei gasi denumirile campurilor
din document, pe care le-ai identificat deja mai sus. Va trebui sa modifici
aceasta zona din cod pentru a trimite exact informatiile culese de tine. Spre
exemplu, in cazul meu codul este ca mai jos :

String data;
data+="";

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

data+="entry.2.single=";
data+=temperatura;
data+="&entry.3.single=";
data+=presiune;
data+="&entry.4.single=";
data+=umiditate;
data+="&submit=Submit";

Adaug in varianta data rand pe rand denumirea unui camp si valoarea


acestuia, citita de Arduino. Mai departe, codul trimite request-ul catre serverul
Google pentru a inregistra informatia in document.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Aceasta a fost lectia 12. In final, as vrea sa te rog sa ne oferi feedback


asupra acestei lectii, pentru a ne permite sa le facem mai bune pe
urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe


care il poti accesa dand click aici.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino Leonardo pe post de tastatura

Exact, daca ai un Arduino Leonardo, poti sa-l faci sa se comporte ca o


tastatura sau un mouse absolut obisnuite (din punct de vedere al
calculatorului). Este o facilitate a noului microcontroller Atmega32u4. Tot ce ai
facut este ca in codul Arduino sa apelezi libraria Keyboard si calculatorul (la
care ai conectat Arduino prin USB) se va comporta ca si cum ai fi apasat taste
pe tastatura obisnuita.
Inainte de a trece mai departe, este necesar sa iti atrag atentia asupra
unui lucru care ar putea fi neplacut. Imediat ce ai programat placa sa trimita
taste apasate catre calculator, Arduino le va trimite tot timpul, pana cand ii
spui sa se opreasca. Singurul mod in care ii poti spune sa se opreasca este
incarcand alt program. Dar daca ai pus placa sa trimita taste prea rapid, atunci
nu vei putea face acest lucru, pentru ca se vor apasa taste chiar in mediul de
dezvoltare, acolo unde vei vrea sa scrii codul. Ca sa nu se intample asta, ai
grija ca sa existe un mecanism prin care sa opresti trimiterea de taste (cum ar
fi un buton conectat la Arduino, sau un delay mare pus un setup). Cu un delay
in setup, poti oricand sa dai un reset placii altfel incat sa o fortezi sa ruleze
functia setup, si apoi cat timp placa sta in delay, tu ii vei putea modifica
programul.

Exemplu 1 -

void setup() {
delay(15000);
Keyboard.begin();
}

void loop() {
Keyboard.print("Hello!");
delay(10000);
}

In exemplul de mai sus, nu facem altceva decat sa initializam modul


tastatura (Keyboard.begin()) si apoi sa trimitem la fiecare 10 secunde sirul de
caractere "Hello" (exact ca si cum am apasa pe tastatura consecutiv tastele H
e l l o. Am pus un delay in setup de 15 secunde in ideea ca atunci cand vei vrea
sa schimbi programul placii, sa poti da un reset si astfel sa ai la dispozitie 15
secunde pentru a incarca noul program.
Cu Arduino Leonardo poti apasa si tastele CTRL, ALT, sau SHIFT, ca mai
jos.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Exemplu 2 -

char ctrlKey = KEY_LEFT_CTRL;

void setup() {
Keyboard.begin();
delay(15000);
}

void loop() {
delay(1000);
Keyboard.press(ctrlKey);
Keyboard.press('n');
delay(100);
Keyboard.releaseAll();
delay(30000);
}

Dupa ce au trecut cele 15 secunde din setup, Arduino apasa tasta CTRL
(si o mentine apasata), apoi apasa tasta "n" si apoi elibereaza ambele taste.
Efectul, pe majoritatea sistemelor de operare, este deschiderea unei ferestre
noi.
Mai jos, lista tuturor comenzilor asociate tastaturii emulate de Arduino.
Keyboard.begin()
- deschide o sesiune de emulare tastatura. Este necesar sa apelezi
aceasta comanda inainte de a le putea folosi pe restul.
Keyboard.end()
- inchide o sesiune de emulare tastatura.
Keyboard.press(<TASTA>)
- apasa si mentine apasata o tasta (utila pentru a trimite combinatii de
taste, gen CTRL + N).
Keyboard.print(<SIR_DE_TASTE>)
- apasa si elibereaza o tasta sau un sir de taste. Util pentru a apasa o
tasta sau un sir de taste apasate succesiv spre calculator.
Keyboard.println(<SIR_DE_TASTE>)
- acelasi lucru ca print, doar ca la final apasa si tasta ENTER. Util pentru a
introduce informatie intr-un document text si a trece automat la linie noua.
Keyboard.release(<TASTA>)
- elibereaza o tasta apasata anterior (cu Keyboard.press()).
Keyboard.releaseAll()
- elibereaza toate tastele apasate anterior (cu Keyboard.press())
Keyboard.write(<TASTA>)

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

–apasa si elibereaza o tasta.

Arduino Leonardo pe post de mouse

Exact in acelasi mod cum emuleaza tastatura, Arduino Leonardo poate fi


vazut de calculator si ca mouse. Poate misca cursorul pe ecran la orice pozitie
si poate simula apasarea pe butoanele mouse-ului.

Exemplu 1 -

void setup(){
Mouse.begin();
}

void loop(){
Mouse.move(50, 50, 0);
delay(10000);
}

Codul de mai sus initializeaza modul mouse, iar apoi la fiecare 10


secunde misca pointer-ul mouse-ului cu 50 de pixeli pe fiecare axa.
Mai jos, lista tuturor comenzilor asociate controlului mouse-ului din
Arduino Leonardo.
Mouse.begin()
–initializeaza modul de control al mouse-ului.
Mouse.end()
–inchide sesiunea de emulare mouse.
Mouse.click(<BUTON>)
- apasa si elibereaza un buton al mouse-ului. Valori posibile sunt
MOUSE_LEFT , MOUSE_RIGHT, MOUSE_MIDDLE. Astfel,
Mouse.click(MOUSE_LEFT) genereaza un click obisnuit pe butonul din stanga al
mouse-ului.
Mouse.move(<X>, <Y>, <SCROLL>)
- genereaza o miscare a cursorului de mouse pe fiecare axa in parte.
Primul parametru este miscarea pe axa orizontala, al doilea pe axa verticala,
iar al treilea reprezinta deplasarea rotitei de scroll.
Mouse.press(<BUTON>)
- apasa (fara a elibera) unul dintre butoanele mouse-ului. Valori posibile
sunt MOUSE_LEFT , MOUSE_RIGHT, MOUSE_MIDDLE. Astfel,

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Mouse.press(MOUSE_LEFT) este ca si cum am apasa manual pe butonul din


stanga al mouse-ului, fara a-l elibera.
Mouse.release()
–elibereaza unul dintre butoanele mouse-ului apasate anterior cu Mouse.press.
Valori posibile sunt MOUSE_LEFT , MOUSE_RIGHT, MOUSE_MIDDLE.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Logare presiune atmosferica, umiditate, nivel de iluminare si


temperatura in Excel, cu Arduino Leonardo

Folosindu-ne de capacitatea lui Arduino Leonardo de a emula o tastatura,


devine foarte simplu sa logam informatie pe calculator. Tot ce avem de facut
este sa apasam din Arduino acele taste corespunzatoare valorilor citite (ca sa
cand le-am introduce manual din tastatura).
Acest proiect foloseste un senzor BMP085 (presiune atmosferica si
temperatura), un senzor de lumina brick si un senzor de umiditate brick,
impreuna cu un Arduino Leonardo pentru a introduce periodic informatie intr-un
document Excel.
Primul pas este conectarea componentelor la Arduino, ca in schema de
mai jos. Probabil ca la prima vedere schema de conectare pare un fel de
paianjen cu multe picioare, dar daca vei reveni la schema de conectare pentru
fiecare senzor in parte (in sectiunea unde fiecare senzor este prezentat
separat), atunci lucrurile vor deveni mult mai simple. Cele doua componente
brick sunt conectate la 5V si GND pentru alimentare, iar apoi la pinii analogici
A0 si A1. Senzorul BMP085 este conectat la cei doi pini I2C SDA si SCL (care in
cazul Arduino Leonardo sunt in partea din stanga sus).

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Mai departe, codul sursa nu face altceva decat sa combine exemplele


care demonstreaza citirea datelor de la senzori cu cel care demostreaza
utilizarea Arduino Leonardo pe post de tastatura.

#include <Wire.h>
#include <BMP085.h>

BMP085 dps = BMP085();


long Temperature = 0, Pressure = 0;

void setup(void) {
Serial.begin(9600);
Wire.begin();
delay(1000);
dps.init();
delay(5000);
Keyboard.begin();
}

void loop(void) {
dps.getTemperature(&Temperature);
dps.getPressure(&Pressure);
int nivelIluminare = analogRead(1);
int nivelUmiditate = analogRead(0);

Keyboard.print(String(Temperature));
Keyboard.print(KEY_RIGHT_ARROW);
Keyboard.print(String(Pressure));
Keyboard.print(KEY_RIGHT_ARROW);
Keyboard.print(String(nivelIluminare));
Keyboard.print(KEY_RIGHT_ARROW);
Keyboard.print(String(nivelUmiditate));
Keyboard.println();
}

Mouse cu accelerometru si Arduino Leonardo

Acest proiect se bazeaza pe capacitatea placii Arduino Leonardo de a se


comporta ca mouse. Prin combinarea unui Arduino Leonardo cu un
accelerometru pe 3 axe, vom obtine un mouse pe care il vom controla prin
miscarea mainii. Poti folosi orice fel de accelerometrul doresti. In cele ce
urmeaza vom folosi un accelerometru ADXL335, pentru simplitate.
Accelerometrul se conecteaza la Arduino in modul obisnuit, ca in schema mai
jos.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

#define SENSIBILITATE_X 3
#define SENSIBILITATE_Y 3

void setup() {
Serial.begin(9600);
analogReference(EXTERNAL);
Mouse.begin();

void loop() {
float xAcc=readAcc(0);
float yAcc=readAcc(1);
float zAcc=readAcc(2);

Serial.print("Acceleratie X: ");
Serial.print(xAcc,DEC);
Serial.print("Acceleratie Y: ");
Serial.print(yAcc,DEC);
Serial.println();
delay(50);

Mouse.move(xAcc * SENSIBILITATE_X, yAcc * SENSIBILITATE_Y, 0);

float readAcc(int port) {


int value=analogRead(port);
int miliVolts=map(value,0,1023,0,3300)-3300/2;
float acc=(float)miliVolts/360;
return acc;
}

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino 3.3 V ADXL335 VCC


Arduino GND ADXL335 GND
Arduino Analog0 ADXL335 X
Arduino Analog1 ADXL335 Y
Arduino Analog2 ADXL335 Z
Arduino 3.3 Arduino AREF

Constantele SENSIBILITATE_X si SENSIBILITATE_Y definesc cat de mult se


misca mouse-ul pe ecran atunci cand miscam accelerometrul. Cu cat valorile
pentru aceste constante sunt mai mari, cu atat mouse-ul se va misca mai mult
pe ecran atunci cand miscam accelerometrul. Esti liber sa te joci cu aceste
constante pana cand miscarea pe ecran este exact asa cum vrei tu.
Principiul de functionare al acestui mouse se bazeaza pe faptul ca in orice
locatie de pe Pamant avem o acceleratie gravitionala 1g, indreptata
intotdeauna pe directia verticala. Cand accelerometrul ADXL335 este orientat
pe directie orizontala, atunci pe axa X si pe axa Y acceleratiile citite sunt zero.
Este o acceleratie de 1g citita pe axa Z. Atunci cand inclinam accelerometrul in
plan, acceleratia de 1g care se manifesta doar pe axa Z cand accelerometrul
este orizontal, incepe sa se manifeste si pe axele X si Y. Astfel daca inclinam
accelerometrul la un unghi de 45 de grade pe axa X, vom avea o acceleratie de
0.5g pe axa X.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Acceleratiile citite de accelerometru sunt inmultite cu o valoare constanta


(in cazul nostru cu 3, valoarea constantei SENSIBILITATE_X) si mouse-ul este
miscat pe ecran corespunzator valorii obtinute. Poate vei spune ca o deplasare
de 3 pixeli atunci cand accelerometrul este inclinat maximum este putin, dar
adu-ti aminte ca functia loop se executa non-stop, astfel incat mouse-ul este
miscat cu 3 pixeli la fiecare 50 de milisecunde (pentru ca in loop exista o
instructiune delay(50)).
Daca ti se pare complicat sa tii mouse-ul fix pe ecran (pentru ca este
destul de dificil sa tii ADXL335 perfect orizontal), atunci putem imbunatati
programul de mai sus prin setarea unei zone in care mouse-ul nu se misca
deloc pe ecran, ca mai jos (modificarile in bold) :

#define SENSIBILITATE_X 3
#define SENSIBILITATE_Y 3
#define ZONA_MOARTA_X 0.3
#define ZONA_MOARTA_Y 0.3

void setup() {
Serial.begin(9600);
analogReference(EXTERNAL);
Mouse.begin();
}

void loop() {
float xAcc=readAcc(0);
float yAcc=readAcc(1);
float zAcc=readAcc(2);

Serial.print("Acceleratie X: ");
Serial.print(xAcc,DEC);
Serial.print("Acceleratie Y: ");
Serial.print(yAcc,DEC);
Serial.println();
delay(50);

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

int miscareX = 0;
if (abs(xAcc) > ZONA_MOARTA_X) {
miscareX = xAcc * SENSIBILITATE_X;
}

int miscareY = 0;
if (abs(yAcc) > ZONA_MOARTA_Y) {
miscareY = yAcc * SENSIBILITATE_Y;
}

Mouse.move(miscareX, miscareY, 0);

float readAcc(int port) {


int value=analogRead(port);
int miliVolts=map(value,0,1023,0,3300)-3300/2;
float acc=(float)miliVolts/360;
return acc;
}

Am introdus doua constante, ZONA_MOARTA_X si ZONA_MOARTA_Y, care


definesc valorile acceleratiei sub care mouse-ul nu face nici o miscare. Astfel,
daca tii accelerometrul intr-o pozitie aproape de orizontala, mouse-ul nu se
misca deloc pe ecran.
In final, ca sa poti misca simplu accelerometrul, iti sugerez sa il prinzi pe
o manusa de piele (cumparata de la standul cu elemente de protectie din
Hornbach, BricoStore sau Practiker).
Urmatoarea extindere a acestui proiect este sa adaugi sistemului si doua
butoane brick, obtinand astfel un mouse perfect functional. Schema de
conectare este cea de mai jos. Butoanele le poti monta pe cate un deget al
fiecarei manusi, astfel incat sa le poti apasa cu degetul mare (prin
suprapunerea degetului mare peste unul dintre cele doua degete pe care sunt
lipite butoanele).

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

#define SENSIBILITATE_X 3
#define SENSIBILITATE_Y 3
#define ZONA_MOARTA_X 0.3
#define ZONA_MOARTA_Y 0.3

#define BUTON1_PIN 9
#define BUTON1_PIN 10
#define DEBOUNCE_TIME 100

void setup() {
Serial.begin(9600);
analogReference(EXTERNAL);
pinMode(BUTON1_PIN, INPUT);
pinMode(BUTON2_PIN, INPUT);

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Mouse.begin();
}

long lastButtonPress1 = 0;
long lastButtonPress2 = 0;

void loop() {

int buton1 = digitalRead(BUTON1_PIN);


int buton2 = digitalRead(BUTON2_PIN);
if (buton1 == 1) {
if ((millis() - lastButtonPress1) > DEBOUNCE_TIME) {
lastButtonPress1 = millis();
Mouse.click(BUTTON_LEFT);
}
}
if (buton2 == 1) {
if ((millis() - lastButtonPress2) > DEBOUNCE_TIME) {
lastButtonPress2 = millis();
Mouse.click(BUTTON_RIGHT);
}
}

float xAcc=readAcc(0);
float yAcc=readAcc(1);
float zAcc=readAcc(2);

Serial.print("Acceleratie X: ");
Serial.print(xAcc,DEC);
Serial.print("Acceleratie Y: ");
Serial.print(yAcc,DEC);
Serial.println();
delay(50);

int miscareX = 0;
if (abs(xAcc) > ZONA_MOARTA_X) {
miscareX = xAcc * SENSIBILITATE_X;
}

int miscareY = 0;
if (abs(yAcc) > ZONA_MOARTA_Y) {
miscareY = yAcc * SENSIBILITATE_Y;
}

Mouse.move(miscareX, miscareY, 0);

float readAcc(int port) {


int value=analogRead(port);
int miliVolts=map(value,0,1023,0,3300)-3300/2;
float acc=(float)miliVolts/360;
return acc;
}

De remarcat in codul de mai sus este constanta DEBOUCE_TIME. Asa cum

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

am povestit mai pe larg in cadrul sectiunii despre butoane brick, atunci cand se
apasa un buton, semnalul receptionat de catre Arduino variaza de cateva ori
intre 0 si 1 (nu trece instantaneu din 0 in 1). Acest lucru se intampla datorita
faptului ca atunci cand apasam butonul, lamelele metalice care inchid
contactul nu se ating perfect. Ca sa evitam ca Arduino sa citeasca mai multe
apasari de buton, vreme de 100 de milisecunde dupa prima apasare
receptionata (valoarea lui DEBOUNCE_TIME) vom ignora orice alta apasare.
Acest lucru inca permite conceptul de dublu click (doar ca diferenta intre doua
click-uri succesive va fi exact DEBOUNCE_TIME milisecunde). Daca dublu click
nu este sesizat corect de calculatorul tau, poti sa micsorezi valoarea acestei
constante, sau sa modifici pe calculator durata intre cele doua click-uri
succesive pentru a obtine un dublu click.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Aceasta a fost lectia 13. In final, as vrea sa te rog sa ne oferi feedback


asupra acestei lectii, pentru a ne permite sa le facem mai bune pe
urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe


care il poti accesa dand click aici.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Analogie electricitate – curgerea fluidelor


Una dintre cele mai simple modalitati de a intelege conceptele de baza
ale electricitatii este de a apela la o analogie cu modul de curgere al fluidelor,
pe care il intelegem intuitiv din experienta proprie. Astfel, sa ne inchipuim apa
curgand printr-un mecanism de tevi, de diverse diametre. Sa ne inchipuim ca
avem pompe care imping apa prin tevi, pompe cu puteri diverse. Acum, daca in
loc de apa ne inchipuim un flux de electroni, in loc de tevi, fire conductoare si
in loc de pompe surse de tensiune (baterii sau alimentatoare), obtinem o
analogie care functioneaza aproape perfect pentru a intelege teoria
electricitatii.
Astfel, la un moment dat printr-o anumita teava trece o anumita cantitate
de apa. La fel, printr-un fir, la un moment dat trece o anumita cantitate de
curent. Cat de mult curent trece printr-un fir la un moment data este un
element caracterizat de intensitatea curentului electric, masurata in
Amperi.
Daca ne inchipuim un circuit format din mai multe tevi mufate intre ele
sub forma unui circuit inchis, este clar ca prin fiecare teava circula exact
aceeasi cantitate de apa la un moment dat (apa pleaca din pompa, trece prin
fiecare teava, si apoi se intoarce inapoi in pompa, exact cata apa pleaca, exact
atata se intoarce). Exact in acelasi mod, intensitatea curentului electric este
aceeasi in oricare punct al unui circuit electric simplu (fara bifurcatii). Altfel
spus, prin oricare punct al unui circuit fara bifurcatii trece aceeasi
cantitate de curent.
Mai departe, daca ne gandim ca tevile au diametre diferite, dar prin ele
circula aceeasi cantitate de apa, atunci presiunea apei este diferita in fiecare
teava, in functie de diametrul acesteia. Echivalentul presiunii apei din tevi, in
cazul curentului electric, este potentialul electric (sau tensiunea) si se
masoara in Volti.
Daca ai udat vreodata cu furtunul in gradina, atunci stii ca pentru a
creste presiunea apei, tot ce ai de facut este sa strangi furtunul (sa-i micsorezi
diametrul). Diametrul tevii (practic, rezistenta pe care o opune teava trecerii
apei) este echivalentul in cazul circuitelor electrice cu rezistenta elementului
electric, si se masoara in Ohm. Exista elemente electrice speciale, care se
cheama rezistoare si care sunt folosite tocmai pentru rezistenta cu care se
opun trecerii curentului electric. Daca ne gandim ca in cazul furtunului cu apa,
cu cat diametrul furtunului este mai mic (deci rezistenta opusa apei este mai
mare) cu atat presiunea apei este mai mare, atunci putem scrie :
intensitatea = tensiunea / rezistenta
Daca notam fiecare marime cu o singura litera, obtinem :

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

I=U/R
care reprezinta legea lui Ohm.
Mai departe, fiecare pompa de lichid este capabila sa impinga lichidul in
tevi cu o anumita presiune. In cazul unui surse electrice, echivalenta este
tensiunea electromotoare a sursei (notata cu U sau cu V). In plus, o pompa
de lichid este capabila sa impinga la un moment dat doar o cantitate finita de
apa (adica, daca la pompa nu conectam absolut nimic si lasam apa sa curga
liber – adica fara a intampina nici o rezistenta), atunci pompa va impinge cea
mai mare cantitate de lichid pe secunda. Exact la fel se intampla si in cazul
surselor electrice (baterii sau alte surse). O sursa este capabila sa furnizeze un
curent de maxim N amperi. Din acest motiv, intotdeauna vom intalni scris pe
alimentatoarele electrice "9 V, 1 A" sau "12 V, 4 A". Este important de inteles
ca aceasta valoare a curentului notat pe alimentator reprezinta valoarea
maxima a curentului pe care acea sursa este capabila sa il furnizeze (atunci
cand nu are nici o rezistenta la borne) si NU valoarea curentului pe care il
furnizeaza intotdeauna, in orice circuit. In cazul unui pompe care impinge apa
in tevi, cantitatea de apa din teava (adica intensitatea) este data de diametrul
tevii (adica de rezistenta circuitului), tot asa si in cazul circuitelor electrice
intensitatea curentului electric este stabilita de catre circuitul electric, si nu
este un parametru al sursei. Sursa limiteaza insa superior aceasta valoare. Din
aceasta cauza, nu este nici un fel de problema sa alimentam un motor care
functioneaza la 6 Volti si 1 Amper cu o sursa electrica pe care scrie "6V 4A".
Acei 4 Amperi notati pe sursa reprezinta valoarea maxima a intensitatii
curentului electric pe care acea sursa ii poate furniza. Cuplata insa cu motorul
de 1 Amper, prin circuit se va stabili un curent stabilit de motor (care va fi mai
mic de 1 Amper atunci cand motorul se invarte liber, si se va apropia de 1
Amper atunci cand blocam rotirea motorului folosind un cleste).
Recapituland, avem pana acum :
•intensitatea curentului electric (notata cu I si masurata in Amperi (A)) = cata
apa trece prin tevi
•tensiunea intr-un punct din circuit (notata cu V sau U si masurata in Volti (V) )
= presiunea apei intr-un numit punct
•rezistenta (notata cu R si masurata in Ohm) = ce rezistenta opune teava
trecerii apei (cat de subtire este teava)
•prin orice punct al unui circuit electric simplu (fara bifurcatii) trece acelasi
curent I.
•I = U / R (legea lui Ohm) (cantitatea de apa este direct proportionala cu
presiunea cu care este impinsa apa si invers proportionala cu rezistanta opusa
apei de tevi).

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Divizorul de tensiune

Sa consideram circuitul electric de mai sus, format dintr-o sursa si doua


rezistoare inseriate. Curentul stabilit prin circuit este determinat foarte simplu
ca fiind I = U / (R1 + R2) (legea lui Ohm). Mai departe, daca ne concentram
doar pe R2, aceeasi lege se aplica si pentru ea, luata separat. In plus, am mai
stabilit ca in orice punct al unui circuit electric simplu (fara bifurcatii) avem
aceeasi intensitate a curentului electric. Asadar, putem scrie : I = U2 / R2 (unde
U2 este caderea de tensiune la capetele rezistorului R2. Putem astfel determina
U2 ca fiind U2 = I * R2, adica, folosind si prima relatie de mai sus : U2 = U *
R2 / (R1 + R2). Aceasta relatie, care ne da caderea de tensiune pe rezistorul R2
in functie de R1, R2 si U este foarte utila intr-o multitudine de situatii. Spre
exemplu, daca in loc de R1 (care in cazul nostru este fix), avem un senzor care
isi modifica rezistenta in functie de un element extern (de exemplu un
fotorezistor), atunci masurand cu Arduino caderea de tensiune U2 (pe un pin
analogic), indirect, masuram si valoarea lui R1, deci implicit nivelul de
iluminare al incaperii.

Circuite electrice cu bifurcatii

Desi nu te vei intalni prea des cu astfel de circuite, este interesant sa ne


aruncam o privire si asupra lor. Este vorba despre un circuit care la un moment
dat se separa, ca cel de mai jos.
Daca vom apela iarasi la analogia cu furtunul si cu apa, este evident ca
volumul de apa care trece prin sectiunea S este egal cu suma volumelor de apa
care trec prin sectiunile S1 si S2. Exact la fel, intensitatea curentului electric
care trece prin sectiunea S1 este suma intensitatilor curentilor electrici care
trec prin sectiunile S1 si S2. Adica :
I = I1 + I2
care este prima lege a lui Kirchoff.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Sa luam apoi bucla formata din R1 si R2. Nu stiu cat de evident este
acest lucru din analogia cu curgerea lichidelor, dar intotdeauna pe o bucla de
circuit inchisa suma caderilor de tensiune este zero. Adica :
U1 + U2 = 0
care este a doua lege a lui Kirchoff.
Gata ! Inarmati cu legea lui Ohm si cu cele doua legi ale lui Kirchoff,
putem acum determina curenti si tensiuni pe circuite oricat de complicate.

Condensatorul

Un condensator nu este altceva decat o galeata in care cad electronii.


Cand galeata s-a umplut, sarcinile incep sa curga mai departe pe fir. Din acest
motiv, vom intalni folositi condesatori peste tot unde avem nevoie de un buffer
de curent. Spre exemplu, aproape de alimentarea unui motor de curent
continuu. Astfel, atunci cand motorul porneste, are nevoie de o mare cantitate
de curent. Posibil chiar mai mare decat poate da sursa. In aceasta situatie, un
condensator de valoare mare va stoca acel curent in regimul de functionare
normal si il va oferi motorului la pornire. In acest fel, si restul dispozitivelor din
circuit vor avea suficient curent ca sa functioneze.

Semnalul PWM

Semnalul PWM (sau Pulse Width Modulation) este un tip de semnal pe


care il vom intalni destul de des cand lucram cu Arduino. Dat fiind ca Arduino
scoate porturile lui digitale doar semnal digital (cu doar doua nivele – 5V si 0V),
semnalul PWM reprezinta o modalitate de a da in exterior informatie care sa
varieze pe mai multe trepte. Astfel, daca modificam raportul intre cat timp sta

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

semnalul in 5V si cat timp sta semnalul in 0V, obtinem un semnal a carui


putere se modifica in trepte. Acest raport il vom numi in cele ce urmeaza
"factor de umplere" al semnalului PWM.
Arduino poate genera un semnal de tip PWM doar pe o parte din porturile
digitale. Astfel, pentru Arduino UNO, porturile capabile de semnal PWM sunt : 3,
5, 6, 9, 10 si 11 iar pentru Arduino Mega porturile capabile de semnal PWM
sunt de la pinul 2 (inclusiv) pana la pinul 13, si de la pinul 44 la pinul 46 .

Una dintre cele mai comune aplicatii ale semnalului PWM este controlul
motoarelor de curent continuu. Un motor de curent continuu caruia i s-a aplicat
un semnal PWM cu factor de umplere 100% va functiona la viteza maxima.
Daca factorul de umplere scade la 50%, si viteza motorului se va modifica in
consecinta (tinand cont ca doar o jumatate din timp mai este actionat practic,
cealalta jumatate din timp invartindu-se din inertie).

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Cum sa faci o floare sa te traga de maneca atunci cand uiti sa o uzi

Cu un Arduino, destul de simplu. Iti mai trebuie doar un senzor de


umiditate "home-made" format din doua fire introduse in ghiveci, si un
dispozitiv care sa alerteze (un led – care sa se aprinda atunci cand planta vrea
apa, un shield Ethernet – care sa te contacteze pe Twitter sau sa-ti dea email
atunci cand este cazul, sau chiar un shield GSM care sa iti dea SMS sau apel de
voce pe telefon).
Schema de principiu este cea de mai jos.

In ghiveci avem cei doi electrozi metalici. Pot fi din orice metal, dar
pentru a nu oxida, cel mai bine este sa fie din inox. Daca este dificil sa gasiti
sarma sau electrozi din inox, sunt la fel de bune si doua cozi de furculita din
inox. Acestea se infig la o distanta de circa 1 cm intre ele (nu este foarte
importanta distanta, important este sa NU se atinga si sa nu fie foarte
departate - gen unul intr-o margine de ghiveci si celalalt in cealalta margine).
Urmatorul pas este sa stabilim valoarea rezistorului asociat celor doi

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

electrozi infipti in pamant. Pentru aceasta, avem nevoie de un ohmetru, aparat


de masura pentru rezistenta. Cei doi electrozi infipti in sol (sau cozi de furculita
din inox), impreuna cu pamantul dintre ei, formeaza un rezistor a carui valoare
depinde de cat de umed este pamantul. Cu cat mai umed este pamantul, cu
atat avem o rezistenta mai mica asociata sistemului. Folosind ohmetrul,
masoara valoarea rezistentei electrice intre cei doi electrozi. Porneste cu scala
aparatului in zona de megaohmi, si modifica scala pana cand obtii o valoare.
Valoarea depinde de tipul pamantului din ghiveci, de cat de departe ai infipt
electrozii, si de cat de ud este pamantul cand faci masuratoarea. Dupa ce ai
obtinut o valoare, alege o valoare similara si pentru rezistorul conectat in
sistem.
Mai departe, asambleaza sistemul conform schemei de mai sus. Ceea ce
obtii este de fapt un banal divizor de tensiune. Unul dintre rezistori este fizic,
montat in schema, iar cel de-al doilea este constituit de cei doi electrozi
impreuna cu pamantul dintre ei din ghiveci. Atunci cand valoarea rezistorului
format de cei doi electrozi se modifica (pentru ca pamantul se usuca sau
devine mai ud), atunci si valoarea citita de Arduino se modifica.
De aici incolo, tot ce ai de facut este sa testezi iar si iar, pentru a obtine
exact valorile corespunzatoare pentru a genera alarme. Incepe cu pamant
perfect uscat, si noteaza valoarea citita de Arduino pe portul analogic 0. Poti
vedea aceasta valoare in debug, folosind un program simplu ca cel de mai jos.

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

void loop() {
int v = analogRead(0);
Serial.println(v);
}

Adauga apoi apa, foarte putina, si asteapta sa se raspandeasca uniform


in intreg ghiveciul. Astfel vei obtine mai multe valori, fiecare valoare pentru
anumit nivel de umiditate din ghiveci. Mai departe, tot ce ai de facut este sa iti
alegi ce tip de alarma iti doresti. Poti alege un simplu led, un shield WIFI, un
shield Ethernet, sau un shield GSM.
Cel mai simplu este sa folosesti un led brick, conectat la unul dintre
porturile digitale (sa spunem portul digital 12). Pinul IN il conectezi la pinul
digital 12, iar pinul GND la pinul GND al Arduino.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

#define LED_PIN 12
#define ALARM 300

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

void loop() {
int v = analogRead(0);
if (v < ALARM) {
digitalWrite(LED_PIN, HIGH);
} else {
digitalWrite(LED_PIN, LOW);
}
delay(5000);
Serial.println(v);
}

Ca sa stabilesti o valoare pentru constanta ALARM cat mai aproape de


realitate, poti chiar sa lasi sistemul pornit mai multe zile, si ori de cate ori
constati ca planta are nevoie de apa sa te conectezi mai intai cu laptop-ul la
Arduino si sa citesti valoarea citita de Arduino, inainte de a pune apa si dupa ce
ai pus apa.

Aceasta a fost lectia 14. In final, as vrea sa te rog sa ne oferi feedback


asupra acestei lectii, pentru a ne permite sa le facem mai bune pe
urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

care il poti accesa dand click aici.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Textul si imaginile din acest document sunt licentiate


Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Arduino Leonardo, accelerometru MMA8452Q si Excel

Arduino 3.3 V MMA8452Q 3.3V


Arduino GND MMA8452Q GND
Arduino SDA MMA8452Q SDA
Arduino SCL MMA8452Q SCL

MMA8452Q este un accelerometru relativ ieftin, suficient de capabil pentru pretul lui. Suporta
trei game de acceleratie (2g, 4g, 8g). Conectarea la Arduino se face folosind patru fire, ca in figura de
mai sus. Putem utiliza un accelerometru de acest tip impreuna cu un Arduino Leonardo pentru a
construi o aplicatie ce detecteaza vibratiile cum ar fi cele produse de un cutremur. Datele vor fi salvate
intr-un fisier excel pentru a fi stocate in caz ca vrei sa le utilizezi la ceva anume. Sau se pot construi mai
multe module de acest gen si interconectate intr-o retea iar daca sunt gestionate de catre un server pot fi
transformate intr-o adevarata retea de detectie a cutremurelor.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Cum functioneaza?

Accelerometrul se alimenteaza direct de la platforma Arduino si comunica cu microcontroller-ul


prin doua fire: SDA si SCL. Orice vibratie mica, orice fel de miscare aplicata accelerometrului provoaca
o schimbare la cele trei variabile de iesire. Variabilele de iesire sunt raportate la cele trei axe de
coordonate: X, Y, Z.
Astfel daca accelerometrul va sta cu axa Z perpendiculara pe planul orizontal, la iesire vei
observa trei valori. Primele doua valori, X si Y vor oscila in jurul valorii lui 0, pentru ca nu actioneaza
nici o forta asupra lor dar oscileaza pentru ca e posibil ca accelerometrul sa aibe o usoara inclinatie. Dar
asupra lui Z actioneaza forta gravitationala. Imaginea luata din Excel arata mai bine aceasta
situatie(coloanele sunt in ordinea: X, Y si Z, cel din urma fiind in jurul valorii de 250, aproximativ 1g).

Cum incarci datele in Excel ? In primul rand, vrem ca datele referitoare la vibratii sa se incarce
in Excel doar atunci cand se detecteaza vibratii si nu incontinuu. Apoi datele vor fi grupate in cate 10
esantioane si se va face o medie. Va exista si un threshold sau valoare limita, depinde cum vrei sa o
numesti.
Daca media celor 10 esantioane depaseste valoarea thresholdului atunci Arduino va incarca
datele in Excel si va realiza acest lucru pentru 10 secunde. Apoi va realiza din nou o mediere asupra
altor 10 esantioane si din nou va testa daca s-a depasit thresholdul iar daca nu, el va ramane in
standby(nu va transmite nimic in Excel).
Cum transmite Arduino Leonardo setul de date in Excel ? Arduino Leonardo se va comporta ca
o tastatura sau keyboard emulator. Exista niste functii interesante care realizeaza acest lucru si vom
vedea in continuare.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Codul sursa.

Avem doua directive ce reprezinta defapt librariile: I2C pentru protocol si libraria
accelerometrului. Se initializeaza si obiectul accel. Librariile se vor copia in directorul libraries din
directorul arduino.
arduino-1.0.1-windows/arduino-1.0.1/libraries/I2C/I2C.cpp
arduino-1.0.1-windows/arduino-1.0.1/libraries/I2C/I2C.h
arduino-1.0.1-windows/arduino-
1.0.1/libraries/MMA8453_n0m1/MMA8453_n0m1.cpp
arduino-1.0.1-windows/arduino-
1.0.1/libraries/MMA8453_n0m1/MMA8453_n0m1.h

#include <I2C.h>
#include <MMA8453_n0m1.h>
MMA8453_n0m1 accel;

Se declara variabilele de tip int:

int contor;
int X[10];
int Y[10];
int Z[10];
int mediaX, mediaY, mediaZ;
int thresX, thresY, thresZ;

Functia setup initializeaza variabilele declarate mai sus, adresa accelerometrului, modul de lucru
al senzorului si emularea tastaturii. Aici am stabilit si valorile de threshold si le poti modifica daca vrei sa
modifici sensibilitatea senzorului la vibratii.

void setup()
{
mediaX=0;
mediaY=0;
mediaZ=0;
thresX=10;
thresY=10;
thresZ=300;

accel.setI2CAddr(0x1D); //change your device address if necessary, default


is 0x1C
accel.dataMode(true, 2); //enable highRes 10bit, 2g range [2g,4g,8g]
Keyboard.begin();
}

Loop() este compusa din mai multe bucle for. Prima bucla se ocupa de esantionul de date, zece
la numar. Citirile de la accelerometru sunt salvate in trei vectori: X, Y, Z.

for (contor=0; contor <= 9; contor++) {


accel.update();
X[contor]=accel.x();

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Y[contor]=accel.y();
Z[contor]=accel.z();
}

Se executa o alta bucla for care aduna toate elementele vectorilor. Adunarea se imparte la 10,
adica se realizeaza media aritmetica. Media este utila daca apare o vibratie generata de o alta sursa, care
nu ne intereseaza si vrem sa o eliminam.
for (contor=0; contor <= 9; contor++) {
mediaX=mediaX+X[contor];
mediaY=mediaY+Y[contor];
mediaZ=mediaZ+Z[contor];
}
mediaX=mediaX/10;
mediaY=mediaY/10;
mediaZ=mediaZ/10;

Se compara cele trei medii cu 3 valori de threshold iar daca una dintre cele 3 medii(am folosit
functia OR) depaseste valoarea de threshold, se incarca datele in Excel. Echivalent, daca apare o vibratie
anormala si este importanta, aceasta este salvata in Excel prin apelarea functiei tipareste(). Am introdus
si o intarziere pentru ca a emula o tastatura la o viteza foarte mare, inseamna sa soliciti procesorul putin
mai mult. Am folosit intarzierea si ca etalon pentru a crea o perioada de aproximativ 10 secunde in care
datele sunt incarcate in Excel.

if (mediaX > thresX || mediaY > thresY || mediaZ > thresZ) {

for (contor=0; contor < 50; contor++){


accel.update();
tipareste();
delay(100);
}

Functia tipareste are urmatoarea forma. Se printeaza valorile x, y si z prin functia


keyboard.print(). Dar pentru o ordonare frumoasa in Excel se transmite Enter, sageata dreapta si sageata
sus. Pentru asta se apeleaza functiile keyboard.write(). In Excel se intampla cum ai vazut in imaginea
capturata mai sus. Datele sunt ordonate de sus in jos.

void tipareste(){
Keyboard.print(accel.x());
Keyboard.write(KEY_RETURN);
Keyboard.write(KEY_RIGHT_ARROW);
Keyboard.write(KEY_UP_ARROW);

Keyboard.print(accel.y());
Keyboard.write(KEY_RETURN);
Keyboard.write(KEY_RIGHT_ARROW);
Keyboard.write(KEY_UP_ARROW);

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Keyboard.print(accel.z());
Keyboard.write(KEY_RETURN);
Keyboard.write(KEY_RIGHT_ARROW);
Keyboard.write(KEY_UP_ARROW);

Keyboard.write(KEY_DOWN_ARROW);
Keyboard.write(KEY_LEFT_ARROW);
Keyboard.write(KEY_LEFT_ARROW);
Keyboard.write(KEY_LEFT_ARROW);
Keyboard.write(KEY_LEFT_ARROW);
}

Vedere din ansamblu:

Concluzie.

Am optat sa montez accelerometrul cu un surub direct pe Arduino, din cauza ca este simplu.
Aplicatia nu detecteaza vibratiile foarte mici. Personal am dat volumul tare pe o melodie rock dar
vibratiile produse nu au fost detectate de senzor. Aici intra in calcul si valoarea de threshold dar si
sensibilitatea accelerometrului pe gama de lucru(2, 4 sau 8g).
In schimb aplicatia da rezultate foarte bune la vibratiile banale. In cazul unui cutremur, stim ca
miscarea se poate propaga pe orizontala sau pe verticala, adica pe una dintre cele 3 axe.
Va urez succes in constructie.

http://www.robofun.ro/forum
http://www.robofun.ro Curs Gratuit Arduino si Robotica

Aceasta a fost lectia 15. In final, as vrea sa te rog sa ne oferi feedback asupra acestei
lectii, pentru a ne permite sa le facem mai bune pe urmatoarele.

Este vorba despre un sondaj cu 4 intrebari (oricare este optionala), pe care il poti
accesa dand click aici. Sondajul este complet anonim.

Sau ne poti contacta direct prin email la contact@robofun.ro .

Iti multumim,
Echipa Robofun.RO

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Comanda motoarelor de curent continuu folosind Arduino si driver-ul de
motoare shield L298

Driver-ul de motoare L298 se utilizeaza pentru controlul motoarelor de curent continuu.


Arduino este capabil sa scoata pe porturile lui o putere foarte mica, total insuficienta pentru a invarti un
motor. Daca vom conecta un motor electric direct la un port Arduino, cel mai probabil vom obtine
arderea procesorului din placa Arduino.
Ca sa nu se intample acest lucru, avem nevoie de un amplificator de putere, care sa ia putere din
sursa de alimentare (baterie, de exemplu), si sa o transmita motoarelor asa cum ii spune Arduino. Acest
amplificator poarta numele generic de "driver de motoare". Exista o multitudine de drivere de motoare,
diferenta majora intre ele fiind cat de multa putere pot conduce (cat de puternice pot fi motoarele pe
care le pot controla).
Driver-ul din aceasta sectiune este bazat pe integratul L298, fiind un driver de nivel mediu din
punct de vedere al puterii conduse. Poate controla motoare care necesita cel mult 2 Amperi (daca nu-ti
e clar ce sunt aia "Amperi", vezi tutorialul "Analogie electricitate - curgerea fluidelor").
Ca sa intelegi mai bine lucrurile, in cele ce urmeaza vom prezenta simplificat modul de
functionare interna al integratului L298. Nu este necesar sa intelegi neaparat cum functioneaza in
interior ca sa il poti utiliza, dar ajuta. Integratul L298 este forma din foarte multe tranzistoare conectate
in cascada. Pentru simplificare, vom considera doar patru tranzistoare, conectate ca mai jos.
In schema de mai jos este o punte H alcatuita din tranzistoare bipolare. Motorul este simbolizat
cu M si diodele au rol de protectie. Daca aplici tensiune pe punctele A,B,C,D conform tabelului de
adevar, vei obtine cele 4 situatii. Daca nu aplici nici o tensiune pe bazele tranzistoarelor atunci motorul
ramane in starea in care era inainte, adica nu se va roti. Punctele A,B,C,D se conecteaza la porturile
platformei Arduino.

http://www.robofun.ro/forum
A B C D Rezultat obtinut
1 0 1 0 Motorul se roteste in
sensul acelor de
ceasornic
0 1 0 1 Motorul se roteste in
sensul invers acelor de
ceasornic
1 0 0 1 Motorul franeaza
0 1 1 0 Motorul franeaza

http://www.robofun.ro/forum
Pe shield sunt prezenti 3 conectori cu surub unde la MOTOR1 si MOTOR2 se conecteaza cele
doua motoare iar la conectorul marcat cu Vin si Gnd se conecteaza sursa de alimentare externa pentru
motoare. Pinii de comanda ai driverului sunt conectati prin shield la pinii 3, 5, 6 si 9 de pe platforma
Arduino.
Codul sursa este prezentat mai jos.

http://www.robofun.ro/forum
int MOTOR2_PIN1 = 3;
int MOTOR2_PIN2 = 5;
int MOTOR1_PIN1 = 6;
int MOTOR1_PIN2 = 9;

void setup() {
pinMode(MOTOR1_PIN1, OUTPUT);
pinMode(MOTOR1_PIN2, OUTPUT);
pinMode(MOTOR2_PIN1, OUTPUT);
pinMode(MOTOR2_PIN2, OUTPUT);
Serial.begin(9600);
}

void loop() {
go(255,-255);
delay(1000);
go(-255,-255);
delay(1000);
go(-255,255);
delay(1000);
go(255,255);
delay(1000);

void go(int speedLeft, int speedRight) {


if (speedLeft > 0) {
analogWrite(MOTOR1_PIN1, speedLeft);
analogWrite(MOTOR1_PIN2, 0);
}
else {
analogWrite(MOTOR1_PIN1, 0);
analogWrite(MOTOR1_PIN2, -speedLeft);
}

if (speedRight > 0) {
analogWrite(MOTOR2_PIN1, speedRight);
analogWrite(MOTOR2_PIN2, 0);
}
else {
analogWrite(MOTOR2_PIN1, 0);
analogWrite(MOTOR2_PIN2, -speedRight);
}
}

http://www.robofun.ro/forum
Functia setup() seteaza pinii 3, 5, 6 si 9 ca fiind iesire. In interiorul buclei loop() se executa
functia go() care determina viteza cu care se vor roti motoarele dar si sensurile de rotatie.
Iti recomand sa nu modifici continutul functiei go() (cel putin deocamdata). Ca sa poti folosi
shield-ul, tot ce ai de facut este sa apelezi functia go() in loop() cu cei doi parametri, vitezaMotorStanga
respectiv vitezaMotorDreapta. Valorile posibile pentru acesti doi parametri sunt intre -255 si 255.
In general, este important ca motoarele sa fie alimentate de la o sursa de putere alta decat cea
care alimenteaza placa Arduino. Shield-ul tine cont de aceasta recomandare, astfel incat asa cum
spuneam si mai sus, este necesar sa il alimentezi prin pinii VIN si GND de la o sursa de putere extern
(cutie cu baterii sau acumulator). Motoarele consuma foarte mult curent, mult mai mult decat poate
furniza portul USB. Driverul poate fi alimentat la o tensiune mult mai mare decat 5V. In plus,
motoarele introduc zgomot in circuit atunci cand isi schimba sensul sau daca nu sunt decuplate corect
cu condensatori. Daca alimentezi motoarele extern, atunci toate riscurile de mai sus sunt eliminate.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
Arduino Leonardo, accelerometru si Google Earth

Arduino 3.3 V MMA8452Q 3.3V


Arduino GND MMA8452Q GND
Arduino SDA MMA8452Q SDA
Arduino SCL MMA8452Q SCL

Folosind faptul ca Arduino Leonardo poate simula un mouse virtual, si


faptul ca un accelerometru este capabil de a detecta acceleratia gravitationala
(adica directia verticala), poti utiliza Arduino Leonardo si accelerometrul
MMA8452Q pentru a simula zborul in aplicatia Google Earth
(http://www.google.com/earth/index.html).
Principiul de functionare al acestei aplicatii este extrem de simplu.
Arduino preia datele de la accelerometru prin interfata I2C iar apoi se comporta
ca un mouse ce iti permite sa zbori in Google Earth Flight Simulator. Diagrama

http://www.robofun.ro/forum
de conectare a senzorului este cea din tabel si deoarece consumul este redus,
platforma si senzorul se vor alimenta din portul USB.

Codul sursa.
#include <I2C.h>
#include <MMA8453_n0m1.h>

MMA8453_n0m1 accel;

int x,y;

void setup() {
accel.setI2CAddr(0x1D); //change your device address if
//necessary, default is 0x1C
accel.dataMode(true, 2); //enable highRes 10bit, 2g
//range[2g,4g,8g]
Mouse.begin();
}

void loop() {
accel.update();
x=accel.x();
y=accel.y();

x=map(x,-200,200,-10,10);
y=map(y,-200,200,-10,10);
Mouse.move(y,x,0);
delay(10);
}

Primele doua linii sunt directivele preprocesor pentru ca te vei utiliza de


magistrala I2C si de senzorul MMA8452Q. Librariile acestea le vei avea in
directorul libraries din arduino, altfel aplicatia nu se va compila cu succes.
Prin linia nr.3 se creeaza obiectul accel apoi se initializeaza doua variabile
x si y.
Rutina setup initializeaza accelerometrul(adresa, rezolutie inalta,
domeniul 2g). Prin linia Mouse.begin(), Arduino va emula mouse-ul conectat la
calculator.
Rutina loop: se obtin datele de la accelerometru si sunt impinse in doua
variabile, x si y.
Domeniul variabilelor x si y este schimbat prin functia map. Valorile -200
si 200 reprezinta limitele inferioare si superioare date de accelerometru.
Valorile -10 si 10 reprezinta domeniul modificat pe baza valorilor precedente.

http://www.robofun.ro/forum
Daca nu se apeleaza cele doua functii map vei observa ca mouse-ul va sta
intotdeauna catre marginea monitorului si va fi incontrolabil.
Functia Mouse.move(y,x,0) transmite coordonatele x si y iar cursorul
mouse-ului de pe monitor isi modifica pozitia. Al treilea termen(zero in cazul
acesta) reprezinta valoarea rotitei scroll.

Cum functioneaza?
Instaleaza Google Earth (http://www.google.com/earth/index.html) si
deschide simulatorul de zbor din Tools-Enter Flight Simulator. Alege un
avion, F16 daca vrei sa zbori la viteza mare, o locatie anume si intra in zbor.
Decolarea de pe aeroport o faci cu Pg Up si cele doua sageti. Cand ai
ajuns in aer pozitioneaza mouse-ul(undeva in fereastra de zbor) si da-i un click.
Conecteaza platforma Arduino la portul USB si asteapta cateva momente pana
cand mouse-ul devine activ pe monitor. Din acest moment zborul este controlat
de Arduino Leonardo.
Experimenteaza misca accelerometrul in aer pe toate cele trei directii, si
urmareste cum se misca mouse-ul pe ecran.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
Arduino, motoare stepper si Easydriver

Motoarele pas cu pas sau motoarele stepper sunt motoare de curent continuu, fara perii si sunt
ideale daca vrei sa le integrezi intr-o anumita aplicatie, ce necesita o anumita viteza de rotatie sau daca
vrei ca motorul sa se roteasca pana intr-un anumit punct si apoi sa isi pastreze pozitia.
Un motor de curent continuu poate fi controlat in sensul miscarii intr-un anumit sens cu o
viteza data, lucru pe care il faci prin aplicarea unei anume tensiune la bornele sale. Motorul se roteste
cat timp exista tensiune aplicata. Nu vei putea insa sa ii controlezi exact rotatia (spre exemplu, nu ai
cum sa-l rotesti cu fix 45 de grade, si apoi sa il opresti).
Modul de functionare al motoarelor pas cu pas este diferit. O rotatie completa a unui motor
stepper este alcatuita din mai multi pasi, fiecare pas reprezentand doar o fractiune din rotatie completa a
motorului. Lucrul asta se datoreaza constructiei interne, rotorul fiind compus din magneti permanenti,
iar statorul din infasurari. Din acest motiv, un motor pas cu pas poate fi controlat extrem de precis. Il
poti roti spre exemplu cu 1 grad spre stanga (adica a 360-a parte dintr-o rotatie completa a axului). Sau
il poti roti cu 45 de grade spre dreapta si apoi il poti bloca.
Sigur, si controlul este ceva mai complicat decat in cazul unui motor de curent continuu. Din
fericire, folosind Arduino si un driver specializat, lucrurile devin simple. In cele ce urmeaza vom
prezenta folosirea EasyDriver (un driver de motor pas cu pas specializat) pentru a controla un motor pas
cu pas.

http://www.robofun.ro/forum
Diagrama de conectare:

Arduino PWM 3 EasyDriver STEP


Arduino PWM 2 EasyDriver DIR
Aduino GND EasyDriver GND

EasyDriver iti permite sa comanzi motorul in pasi foarte mici. Aceasta tehnica se numeste
microstepping, practic driverul imparte un pas in 8 micropasi. Motoarele de uz general realizeaza o
rotatie completa in 200 de pasi sau unghiul unui pas este de 1,8°. Dar pentru ca EasyDriver imparte un
pas in 8 micropasi atunci sunt necesari 1600 de micropasi pentru o rotatie completa a motorului. Asta
inseamna ca motorul se poate roti cu precizie ridicata. La viteze mari, motorul dezvolta insa o forta
redusa.
Inainte de a pune in functiune circuitul trebuie sa fii atent cand alegi sursa de tensiune, pentru
ca trebuie sa respecti parametrii motorului: tensiunea de alimentare, si consum. In general, motoarele se
alimenteaza la 12 V. Spre exemplu, si aceasta - http://www.robofun.ro/stepper_motor_100g_cm si
acesta - http://www.robofun.ro/motor_stepper si acesta –
http://www.robofun.ro/motor_stepper_400_pasi_4_8_kg_cm, toate functioneaza la 12 V. Celalalt
parametru important este intensitatea curentului necesar (eista o relatie directa intre aceasta si forta
motorului; cu cat motorul necesita un curent mai mare pentru a functiona, cu atat trebuie sa te astepti
ca va avea o forta mai mare).
Inainte de a trece la cod, vreau sa te pun in garda asupra faptului ca un motor pas cu pas se va

http://www.robofun.ro/forum
incalzi in timpul functionarii, iar acest lucru este normal. Pentru a functiona, prin bobinele motorului
trece curent electric tot timpul, chiar si cand motor sta pe loc (in regim de blocare). Cat timp poti
atinge motorul cu mana, este OK (60 – 80 de grade Celsius). Vezi si discutia de aici -
http://robofun.ro/forum/viewtopic.php?f=4&t=139&p=478&hilit=caldura#p478
Daca vrei sa tii motorul mai rece, ai doua solutii. Prima ar fi sa-i reduci curentul. Pe placa EasyDriver,
exista un mic potentiometru din care poti face acest lucru. Evident, cu cat curentul este mai mic, cu atat
forta motorului este mai mica. Al doilea lucru pe care il poti face este ca atunci cand motorul sta, sa faci
disable la driver. Pentru a realiza acest lucru, conecteaza pinul ENABLE de pe placa EasyDriver la un
pin digital Arduino. Atunci cand cobori in zero pinul digital, prin motor nu va mai circula curent
(motorul se va raci). Evident, motorul va fi liber in acest moment sa se invarta (daca exista forte externe
in sistemul tau mecanic). De la caz la caz, poti sau nu a aplici aceasta abordare. Spre exemplu, pentru
un robot pasitor umanoid, nu poti face asta, pentru ca in momentul in care faci disable la driver,
robotul tau va cadea la pamant. Daca insa este vorba despre un sistem care misca o draperie, atunci nu
este nici o problema daca dupa ce am terminat miscarea draperiei fac disable la driver. Draperia va
ramane in pozitia curenta, iar motorul nu va mai consuma curent si nu se va mai incalzi.

Codul sursa

Primele linii de cod se evidentiaza prin doua directive:

#define DIR_PIN 2
#define STEP_PIN 3

Oriunde este scris in cod DIR_PIN, programul se refera la pinul 2 de la Arduino. Acelasi lucru
este valabil si pentru STEP_PIN.

void setup() {
pinMode(DIR_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
}

Nivelele logice, impulsurile sau bitii, depinde cum preferi sa ii numesti circula dinspre Arduino
spre EasyDriver asa ca DIR_PIN si STEP_PIN vor fi setati ca iesire.

http://www.robofun.ro/forum
void loop(){
//rotate a specific number of degrees
rotateDeg(360, 1);
delay(1000);
rotateDeg(-360, 0.1); //reverse
delay(1000);
//rotate a specific number of microsteps (8 microsteps per step)
//a 200 step stepper would take 1600 micro steps for one full
//revolution
rotate(1600, 0.5);
delay(1000);
rotate(-1600, 0.25); //reverse
delay(1000);
}

Loop este o bucla repetitiva, executa consecutiv liniile de cod din interiorul acesteia. In bucla vei
observa ca se apeleaza functiile rotateDeg, rotate si delay. Functia delay accepta ca parametru un numar
de milisecunde asa ca delay(1000) inseamna ca programul va sta pe loc timp de o secunda.

void rotate(int steps, float speed){


//rotate a specific number of microsteps (8 microsteps per
//step) - (negative for reverse movement)
//speed is any number from .01 -> 1 with 1 being fastest - Slower
//is stronger
int dir = (steps > 0)? HIGH:LOW;
steps = abs(steps);

digitalWrite(DIR_PIN,dir);

float usDelay = (1/speed) * 70;

for(int i=0; i < steps; i++){


digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(usDelay);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(usDelay);
}
}

Functia rotate accepta ca parametrii steps de tip int si speed de tip float. Se stabileste directia de
rotatie, daca steps are o valoare mai mare ca zero atunci dir va trece in "1" logic, invers daca steps este
negativ, dir va trece in "0" logic. Se transmite directia catre EasyDriver prin:
digitalWrite(DIR_PIN,dir);

Daca dir este 1 atunci motorul se va roti intr-un sens iar daca dir trece in 0 motorul isi va
schimba sensul de rotatie.
Bucla for transmite numarul de pasi. Observam o variabila usDelay. Sa presupunem ca speed =
1 (viteza foarte mare). Atunci usDelay ar fi egal cu 70. Dar daca speed = 0.5 atunci usDelay = 140. Am

http://www.robofun.ro/forum
scos in evidenta lucrul asta pentru ca o intarziere mai mare este echivalenta cu o viteza mai mica.

void rotateDeg(float deg, float speed){


//rotate a specific number of degrees (negitive for reverse
//movement)
//speed is any number from .01 -> 1 with 1 being fastest - Slower
//is stronger
int dir = (deg > 0)? HIGH:LOW;
digitalWrite(DIR_PIN,dir);
int steps = abs(deg)*(1/0.225);
float usDelay = (1/speed) * 70;

for(int i=0; i < steps; i++){


digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(usDelay);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(usDelay);
}
}

Functia rotateDeg este asemanatoare. Diferenta sta in parametrii de intrare si in linia de cod care
transforma numarul de grade in numarul de pasi:
int steps = abs(deg)*(1/0.225);

Restul liniilor functioneaza pe acelasi principiu.

//////////////////////////////////////////////////////////////////
//©2011 bildr
//Released under the MIT License - Please reuse change and share
//Using the easy stepper with your arduino
//use rotate and/or rotateDeg to controll stepper motor
//speed is any number from .01 -> 1 with 1 being fastest -
//Slower Speed == Stronger movement
/////////////////////////////////////////////////////////////////

#define DIR_PIN 2
#define STEP_PIN 3

void setup() {
pinMode(DIR_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
}

void loop(){
//rotate a specific number of degrees
rotateDeg(360, 1);
delay(1000);
rotateDeg(-360, 0.1); //reverse
delay(1000);

http://www.robofun.ro/forum
//rotate a specific number of microsteps (8 microsteps per step)
//a 200 step stepper would take 1600 micro steps for one full
//revolution

rotate(1600, 0.5);
delay(1000);

rotate(-1600, 0.25); //reverse


delay(1000);
}

void rotate(int steps, float speed){


//rotate a specific number of microsteps (8 microsteps per
//step) - (negitive for reverse movement)
//speed is any number from .01 -> 1 with 1 being fastest - Slower
//is stronger

int dir = (steps > 0)? HIGH:LOW;


steps = abs(steps);
digitalWrite(DIR_PIN,dir);
float usDelay = (1/speed) * 70;

for(int i=0; i < steps; i++){


digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(usDelay);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(usDelay);
}
}
void rotateDeg(float deg, float speed){
//rotate a specific number of degrees (negitive for reverse
//movement)
//speed is any number from .01 -> 1 with 1 being fastest - Slower
//is stronger

int dir = (deg > 0)? HIGH:LOW;


digitalWrite(DIR_PIN,dir);

int steps = abs(deg)*(1/0.225);


float usDelay = (1/speed) * 70;

for(int i=0; i < steps; i++){


digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(usDelay);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(usDelay);
}
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
Arduino UNO si cititorul RFID ID-12

In urmatorul tutorial vei utiliza un Arduino UNO si un cititor RFID pentru a


citi diverse tag-uri care pot fi folosite la un sistem simplu de securitate sau la
identificarea unor obiecte.
RFID este prescurtarea de la termenul Radio-Frequency Identification si
este format din trei parti:
• o antena, care alimenteaza cu energie tag-urile si stabileste comunicatia
dintre cititor si tag.
• cititorul, care interpreteaza datele.
• tag-ul, care are un cod unic.

Atunci cand tag-ul se afla la mai putin de 5 cm de antena acesta


raspunde cu un cod unic format din 12 digiti. Cititorul preia codul unic si il
transmite mai departe catre Arduino.

Pentru acest tutorial vei avea nevoie de urmatoarele componente:


• Arduino UNO
• led brick
• adaptor RFID pe USB
• cititor RFID ID-12
• diverse tag-uri
• un alimentator extern (12V)
• fire pentru conexiuni

http://www.robofun.ro/forum
Diagrama de conectare este cea din tabelul de mai jos.

Adaptor RFID Vcc Arduino UNO 5V


Adaptor RFID Gnd Arduino UNO Gnd
Adaptor RFID TX Arduino UNO Digital 7
Led brick IN Arduino UNO Digital 12
Led brick Gnd Arduino UNO Gnd

http://www.robofun.ro/forum
Cum functioneaza.

Cititorul RFID ID-12 se conecteaza la adaptorul USB deoarece vei prelua


semnalul TX si il vei duce acest semnal la pinul digital 7 al Arduino. Alimentarea
adaptorului o vei face din Arduino ( din pinii parcati cu 5V si GND). Daca
cititorul detecteaza un tag, acesta va transmite adresa lui prin pinul TX catre
Arduino.

http://www.robofun.ro/forum
Alimenteaza platforma Arduino UNO din alimentatorul extern. Daca vei
apropia tagul RFID de cititor, acesta va produce un sunet scurt si se va aprinde
led-ul Read ceea ce inseamna ca cititorul detecteaza corect tag-ul.
Poti utiliza multe tipuri de tag-uri (tip breloc, bratara, buton sau cartela,
ca mai jos).

http://www.robofun.ro/forum
Codul sursa.

Incarca urmatorul sketch in Arduino.

#include <SoftwareSerial.h>
SoftwareSerial rfid(7, 6); // RX, TX

const int ledRosu = 12;


boolean stare = false;
int reading = 0;

void setup() {
Serial.begin(9600); // initializeaza portul serial la 9600 baud
rfid.begin(9600); // initializeaza modulul rfid la 9600 baud
pinMode(ledRosu, OUTPUT);
}

void loop() {
while (rfid.available()) {
reading = rfid.read(); // citeste byte-ul
if (reading == 2) {
stare = true; // '2' reprezinta inceput de string
Serial.print("Serie RFID tag: ");
}
if (reading == 3) {
stare = false; // '3' reprezinta sfarsit de string
Serial.println("");
digitalWrite(ledRosu,HIGH);
delay(5000);
digitalWrite(ledRosu,LOW);
}
if (stare && reading != 2 && reading != 10 && reading != 13)
{ // transmite fiecare byte la serial monitor
Serial.write(reading);
}
}
}

Dupa ce ai incarcat sketch-ul, deschide monitorul serial. Apropie diverse


tag-uri de cititorul RFID. Vei auzi un beep scurt, led-ul brick se va aprinde
pentru 5 secunde iar monitorul serial va afisa seria unica a tagului.
Monitorul serial va indica cod-urile unice RFID ca mai jos.

http://www.robofun.ro/forum
In functia setup() sunt initializate doua porturi seriale. Primul este folosit
de Arduino pentru transmiterea informatiei catre calculator (serial hardware),
iar cel de-al doilea este o emulare de comunicare serial pe pinul digital 7
(software serial). In acest mod, nu vei fi obligat sa deconectezi firul TX de
fiecare data cand incarci sketch-ul.
Bucla loop() monitorizeaza aparitia adreselor RFID. Daca apare o adresa,
ea va incepe intotdeauna cu caracterul „2“ si se va sfarsi cu caracterul „3“.
Monitorul serial va printa seria unica si checksum-ul codului. Atunci cand s-a
detectat digit-ul „3“ inseamna ca nu mai urmeaza nici un caracter astfel ca se
printeaza o noua linie la monitorul serial si se porneste led-ul timp de 5
secunde.

http://www.robofun.ro/forum
Incarca urmatorul sketch.

#include <SoftwareSerial.h>
SoftwareSerial rfid(7, 6); // RX, TX
const int ledRosu = 12;
boolean stare = false;
int reading = 0;
int contor=0;
char serieTag[13];
char serieUnica[13] = "290067647D57";
void setup() {
Serial.begin(9600); // initializeaza portul serial la 9600 baud
rfid.begin(9600); // initializeaza modulul rfid la 9600 baud
pinMode(ledRosu, OUTPUT);
}

void loop() {
while (rfid.available()) {
reading = rfid.read(); // citeste byte-ul
if (reading == 2) {
stare = true; // '2' reprezinta inceput de string
Serial.print("Serie RFID tag: ");
}
if (reading == 3) {
stare = false; // '3' reprezinta sfarsit de string
Serial.println("");
contor = 0;
if (strcmp(serieTag, serieUnica) == 0) {
digitalWrite(ledRosu,HIGH);
delay(5000);
digitalWrite(ledRosu,LOW);
}
}
if (stare && reading != 2 && reading != 10 && reading != 13)
{ // transmite fiecare byte la serial monitor
serieTag[contor]=reading;
Serial.write(reading);
contor++;
}
}
}

http://www.robofun.ro/forum
Sketch-ul pe care l-ai incarcat functioneaza asemanator cu primul,
diferenta fiind ca led-ul se va aprinde doar la un anumit tag, respectiv cel care
are seria „290067647D57“.
In sketch s-a declarat o variabila numita contor, ce va tine cont de pozitia
fiecarui caracter al adresei unice, si doua string-uri de tip char respectiv
serieTag si serieUnica. In serieTag se va stoca adresa detectata de cititor iar
seriaUnica reprezinta seria tagului ce va aprinde led-ul.
Prin functia strcmp(serieTag, serieUnica) == 0 se compara cele doua
string-uri. Daca functia returneaza 0, inseamna ca exista egalitate (tag-ul va
aprinde led-ul).

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
Arduino UNO si MOD-IO2

In acest tutorial vom exemplifica functionarea modulului MOD-IO2


impreuna cu Arduino UNO. Modulul MOD-IO2 este un modul cu microcontroller
dedicat, comunica cu Arduino prin protocolul I2C, si dispune de doua relee si
mai multe porturi GPIO (similare cu porturile digitale din Arduino).

Vei avea nevoie de urmatoarele componente:

• Arduino UNO
• Placa cu relee MOD-IO2
• Adaptor Rpi-UEXT
• 3 led-uri brick de culori diferite
• Breadboard
• Fire pentru conexiuni

Cateva lucruri despre MOD-IO2 :

• contine pe placa un microcontroller dedicat care controleaza cele doua


relee de pe placa, precum si mai multe porturi GPIO (similare cu porturile
digitale din Arduino).
• se conecteaza cu Arduino doar prin 2 fire (SCL, SDA – protocol I2C) la
Arduino.
• se alimenteaza de la o sursa de tensiune stabilizata de 12V.
• este adresabil, ceea ce inseamna ca poti inlantui mai multe module MOD-
IO2.

In cele de mai jos vom utiliza un breadboard, impreuna cu adaptorul


UEXT pentru a simplifica lucrurile si (astfel vom avea masa comuna GND intre
led-uri, Arduino si MOD-IO2).

http://www.robofun.ro/forum
Pentru exemplificare, vom folosi trei led-uri brick conectate la placa MOD-
IO2. Nu vom conecta nimic la relee, zgomotul pe care il fac acestea la cuplare
si decuplare va fi suficient pentru a ne da seama ca acestea functioneaza. In
proiectul tau, poti folosi doar releele (daca nu ai nevoie de porturi GPIO
suplimentare; ceea ce inseamna ca in cele ce urmeaza esti liber sa ignori led-
urile) conectate la porturile GPIO.

http://www.robofun.ro/forum
Tabelul de conexiuni:

Arduino UNO SCL Rpi-UEXT SCL


Arduino UNO SDA Rpi-UEXT SDA
Led brick galben IN MOD-IO2 GPIO 0
Led brick verde IN MOD-IO2 GPIO 1
Led brick rosu IN MOD-IO2 GPIO 2
Led brick galben GND Breadboard GND
Led brick verde GND Breadboard GND
Led brick rosu GND Breadboard GND
Arduino UNO GND Breadboard GND
MOD-IO2 GND Breadboard GND

Pentru comunicarea I2C intre Arduino si MOD-IO2, Arduino este master


iar placa MOD-IO2 functioneaza pe post de slave. Arduino transmite comenzi
prin magistrala I2C la frecventa de 100Khz. Din pacate, MOD-IO2 intelege doar
comenzi trimise la cel mult 50KHz, asa ca va fi necesar sa modifici frecventa
placii Arduino in fisierului de configurare de mai jos.

arduino-1.0.2/libraries/Wire/utility

Deschide fisierul twi.h si cauta liniile:


#ifndef TWI_FREQ
#define TWI_FREQ 100000L
#endif

Schimba valoarea 100000L in 50000L.


Cand vrei sa abordezi alte proiecte, nu uita sa schimbi la loc valoarea.

Programul.

Incarca in Arduino urmatorul sketch.

http://www.robofun.ro/forum
#include <Wire.h>
String inputString = "";
boolean stringComplete = false;
int led = 0;
int whichRelay = 0;

void setup() {
Serial.begin(9600);
inputString.reserve(200);
Wire.begin();
setareGPIO();
setGPIOState(0,0);
setGPIOState(1,0);
setGPIOState(2,0);
setRelayState(0,0);
setRelayState(1,0);
}

void loop() {

if (stringComplete) {
if (inputString == "led 1 on\n") {
setGPIOState(0,1);
Serial.println("GPIO Led 1 ON");
} else if (inputString == "led 1 off\n") {
setGPIOState(0,0);
Serial.println("GPIO Led 1 OFF");
} else if (inputString == "led 2 on\n") {
setGPIOState(1,1);
Serial.println("GPIO Led 2 ON");
} else if (inputString == "led 2 off\n") {
setGPIOState(1,0);
Serial.println("GPIO Led 2 OFF");
} else if (inputString == "led 3 on\n") {
setGPIOState(2,1);
Serial.println("GPIO Led 3 ON");
} else if (inputString == "led 3 off\n") {
setGPIOState(2,0);
Serial.println("GPIO Led 3 OFF");
} else if (inputString == "relay 1 on\n") {
setRelayState(0,1);
Serial.println("RELAY 1 ON");
} else if (inputString == "relay 1 off\n") {
setRelayState(0,0);
Serial.println("RELAY 1 OFF");
} else if (inputString == "relay 2 on\n") {
setRelayState(1,1);
Serial.println("RELAY 2 ON");

http://www.robofun.ro/forum
} else if (inputString == "relay 2 off\n") {
setRelayState(1,0);
Serial.println("RELAY 2 OFF");
} else if (inputString == "relays on\n") {
setRelayState(0,1);
setRelayState(1,1);
Serial.println("BOTH RELAYS ON");
} else if (inputString == "relays off\n") {
setRelayState(0,0);
setRelayState(1,0);
Serial.println("BOTH RELAYS OFF");
}
inputString = "";
stringComplete = false;
}
}

void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inChar == '\n') {
stringComplete = true;
}
}
}

void setareGPIO() {
Wire.beginTransmission(0x48);
Wire.write(0x02);
Wire.write(0xA0);
Wire.write(0x01);
Wire.write(0x00);
Wire.endTransmission();
}

/* Exemple de situatii
setGPIOState(0,1) – led-ul conectat la GPIO 0 devine ON; restul
led-urilor nu isi modifica starea
setGPIOState(1,1) – led-ul conectat la GPIO 1 devine ON
setGPIOState(0,0) – led-ul conectat la GPIO 0 devine OFF
setGPIOState(1,0) – led-ul conectat la GPIO 1 devine OFF
setGPIOState(2,1) – led-ul conectat la GPIO 2 devine ON
setGPIOState(2,0) – led-ul conectat la GPIO 2 devine OFF
*/

http://www.robofun.ro/forum
void setGPIOState(int gpio, int state) {
if (state == 1) bitSet(led, gpio);
if (state == 0) bitClear(led, gpio);
Wire.beginTransmission(0x48);
Wire.write(0x02);
Wire.write(0xA0);
Wire.write(0x02);
Wire.write(led);
Wire.endTransmission();
}

/* Exemple de situatii:
setRelayState(0,1) – releu 1 cuplat; releu 2 decuplat
setRelayState(1,1) – releu 2 cuplat; releu 1 ramane cuplat(din
instructiunea anterioara)
setRelayState(0,0) – releu 1 decuplat; releu 2 ramane cuplat(din
instructiunea anterioara)
setRelayState(1,0) – releu 2 decuplat; releu 1 ramane decuplat(din
instructiunea anterioara)
*/

void setRelayState(int relay, int state) {


if (state == 1) bitSet(whichRelay, relay);
if (state == 0) bitClear(whichRelay, relay);
Wire.beginTransmission(0x48);
Wire.write(0x02);
Wire.write(0xA0);
Wire.write(0x40);
Wire.write(whichRelay);
Wire.endTransmission();
}

Cum functioneaza?

Dupa ce ai incarcat sketch-ul in Arduino, deschide monitorul serial si


tasteaza in casuta alaturi de buton Send urmatoarele comenzi:

• led 1
• led 2
• led 3

http://www.robofun.ro/forum
• relay 1
• relay 2
• relay on
• relay off

Vei observa ca led-urile si releele isi schimba starea in functie de


comanda utilizata (pentru led-uri, vei sesiza vizual modificarea starii, iar pentru
relee vei auzi click-ul pe care il fac cand isi modifica starea).

Ce se intampla in program ?

Functia setup() initializeaza portul serial la 9600 baud, interfata I2C la


frecventa de 50Khz si aduce modulul MOD-IO2 in starea in care led-urile si
releele sunt oprite, prin cele 3 functii: setareGPIO, setLedGPIO, setRelay.
Se aloca din memorie 200 de caractere pentru variabila inputString.

In bucla loop() se testeaza daca stringComplete este true. Aceasta


variabila este legata de functia serialEvent(), ea fiind executata automat de

http://www.robofun.ro/forum
Arduino, adica nu trebuie sa o apelezi undeva in program.

In functia serialEvent() se receptioneaza caracterele de la monitorul


serial si se stocheaza in inputString. Tot aici se cauta daca s-a tastat Enter
( echivalentul lui '\n' sau new line). Daca s-a tastat inseamna ca s-a introdus
comanda completa.
if (inChar == '\n') {
stringComplete = true;
}

Cand s-a receptionat o comanda (un Enter), stringComplete devine


true.
Revenind in bucla loop(), daca variabila este true atunci se cauta
comanda (se testeaza inputString de mai multe ori) iar pentru fiecare comanda
se apeleaza o functie (fie ea setGPIOState sau setRelayState).

Functia setareGPIO() seteaza portul GPIO al placii MOD-IO, ca iesire


(output). Se comporta exact ca porturile lui Arduino (INPUT/OUTPUT).

Functia setGPIOState(int gpio, int state) primeste doua argumente si


anume portul GPIO si starea in care va comuta. In interiorul functiei, Arduino ii
transmite placii MOD-IO, comanda de a aprinde led-ul conectat la portul GPIO.
Asemanator functioneaza si functia setRelayState(int relay, int
state). Primeste doua argumente: relay si state respectiv „care dintre relee“ si
in ce stare va comuta.

Detaliile despre placa MOD-IO2 si anume, setul de comenzi, formatul


adreselor, etc sunt explicate in manualul acesteia.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
Alcoolmetru realizat cu Arduino Leonardo

Utilizand un Arduino, un senzor MQ-3, un LCD shield si trei leduri brick de culori diferite se
poate construi un alcoolmetru hobby foarte rapid.
Senzorul MQ-3 are o sensibilitate ridicata, un timp de raspuns rapid si este sensibil la vaporii de
alcool care provin de la o sursa din vecinatate. Se alimenteaza in curent continuu de la o sursa de
tensiune de 5V si scoate la iesire un semnal analogic raportat la concentratia alcoolului.
Datele privind nivelul de alcool in aerul expirat vor fi afisate pe un LCD avand 2 linii si 16
coloane. Ledurile vor indica 3 nivele prestabilite de concentratie astfel pentru o concentratie mica se va
aprinde doar ledul verde, pentru o concentratie moderata se vor aprinde ledurile verde si galben iar
pentru o concentratie mare se vor aprinde toate cele 3 leduri.
Trebuie sa iti spun de la inceput sa nu te astepti sa obtii o concentratie in procente a nivelului
de alcool, acest lucru este destul de complicat de realizat, si necesita conditii de calibrare intr-un
laborator specializat. NU folosi acest alcoolmetru pentru situatii in care poti pune vieti in pericol ! Si
NU conduce sub influenta bauturilor alcoolice !
OK, acum ca am trecut de partea avertizarilor obligatorii, sa trecem la treaba.

Componentele necesare:
• Arduino UNO http://www.robofun.ro/arduino/arduino_uno_v3
• LCD shield 16x2 http://www.robofun.ro/shield-lcd-16x2
• 3 LED-uri brick http://www.robofun.ro/index.php?route=product/search&keyword=led
%20brick&category_id=0
• Stabilizator 5V brick http://www.robofun.ro/stabilizator-5v
• Senzor alcool brick http://www.robofun.ro/senzor-alcool-brick
• Sursa de alimentare externa http://www.robofun.ro/alimentator-extern-arduino

http://www.robofun.ro/forum
Schema de conectare: stabilizator 5V + senzor alcool brick

Conecteaza shield-ul LCD la Arduino (prin infigere) iar urmareste tabelul de mai jos pentru
restul conexiunilor:

Stabilizator 5V brick Vin Arduino Vin


Stabilizator 5V brick Gnd Arduino Gnd
Stabilizator 5V brick Gnd Senzor alcool brick Gnd
Led verde brick IN Arduino digital 13
Led galben brick IN Arduino digital 12
Led rosu brick IN Arduino digital 11
Senzor alcool brick OUT Arduino analog A0
Led verde brick Gnd Arduino Gnd
Led galben brick Gnd Arduino Gnd
Led rosu brick Gnd Arduino Gnd

http://www.robofun.ro/forum
In final, vei obtine urmatorul montaj.

Cum functioneaza?

Platforma Arduino se alimenteaza de la o sursa de tensiune externa. Iesirea VIN (care este
conectata prin placa Arduino la intrarea sursei de tensiune externa) a platformei se conecteaza la intrarea
stabilizatorului 5V brick. Stabilizatorul primeste la intrare tensiunea de 7.5 V – 9 V si scoate la iesire
5V, alimentand senzorul MQ-3. Este necesar sa folosesti un stabilizator extern pentru ca senzorul de
alcool MQ-3 consuma un curent relativ ridicat (contine in interior o rezistenta care se incinge in timpul
functionarii), asa ca daca l-ai conecta direct la pinul 5V Arduino exista sansa sa arzi placa Arduino.

http://www.robofun.ro/forum
Codul sursa

#include <LiquidCrystal.h>
#define nivel1 40
#define nivel2 60
#define nivel3 80

int analog_in = A0;


int led_verde = 13;
int led_galben = 12;
int led_rosu = 11;
int analog_reading = 0;
int percent_reading = 0;

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

void setup() {
pinMode(led_verde, OUTPUT);
pinMode(led_galben, OUTPUT);
pinMode(led_rosu, OUTPUT);

lcd.begin(16, 2);
lcd.print("Alcoolmetru");
delay(1000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Indicatie senzor");
}

http://www.robofun.ro/forum
void loop() {
lcd.setCursor(0,1);
analog_reading = analogRead(analog_in);
lcd.print(analog_reading);
percent_reading=map(analog_reading, 0, 1023, 0, 100);

if (percent_reading < nivel1){


digitalWrite(led_verde,HIGH);
digitalWrite(led_galben,LOW);
digitalWrite(led_rosu,LOW);
} else if (percent_reading < nivel2){
digitalWrite(led_verde,HIGH);
digitalWrite(led_galben,HIGH);
digitalWrite(led_rosu,LOW);
} else if (percent_reading < nivel3){
digitalWrite(led_verde,HIGH);
digitalWrite(led_galben,HIGH);
digitalWrite(led_rosu,HIGH);
}
}

Programul incepe cu directiva preprocesor aferenta afisajului:


#include<LiquidCrystal.h>

Se definesc 3 constante de nivel avand valorile aferente:


#define nivel1 40
#define nivel2 60
#define nivel3 80

Urmatoarele instructiuni declara pinul aferent intrarii care provine de la senzor, ledurile
conectate la platforma, variabila ce va stoca valoarea concentratiei si variabila ce va stoca procentul de
concentratie.

int analog_in = A0;


int led_verde = 13;
int led_galben = 12;
int led_rosu = 11;
int analog_reading = 0;
int percent_reading = 0;

Se initializeaza afisajul LCD:

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

http://www.robofun.ro/forum
In rutina setup() pinii care controleaza led-urile sunt declarati ca fiind pini de iesire :
pinMode(led_verde, OUTPUT);
pinMode(led_galben, OUTPUT);
pinMode(led_rosu, OUTPUT);

Instructiunea urmatoare seteaza numarul de linii si de coloane pentru LCD, respectiv 16


coloane si 2 linii:

lcd.begin(16, 2);

Urmatorul set de instructiuni afiseaza pe display text.

lcd.print("Alcoolmetru");
delay(1000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Indicatie senzor");

Se continua cu executia buclei loop(). Instructiunea schimba pozitia cursorului la coloana 0 si


linia 1 deoarece acolo se va afisa informatia analogica furnizata de senzor.
lcd.setCursor(0,1);

Functia analogRead(analog_in) returneaza in analog_reading valoarea citita de la senzor.


analog_reading = analogRead(analog_in);

Instructiunea afiseaza pe LCD continutul variabilei analog_reading:


lcd.print(analog_reading);

Functia map schimba domeniul intervalului 0 – 1023 in 0 – 100 iar rezultatul se stocheaza in
percent_reading:

percent_reading=map(analog_reading, 0, 1023, 0, 100);

Urmatorul bloc de instructiuni testeaza daca variabila percent_reading a depasit un anumit nivel
si aprinde ledurile astfel:

http://www.robofun.ro/forum
if (percent_reading < nivel1){ // daca percent_reading este mai mic
//decat nivel1
digitalWrite(led_verde,HIGH); // aprinde ledul verde
digitalWrite(led_galben,LOW); // stinge celelalte doua leduri
digitalWrite(led_rosu,LOW);
} else if (percent_reading < nivel2){ // daca prima conditie nu a
//fost satisfacuta se testeaza a doua
digitalWrite(led_verde,HIGH); // se aprind primele doua leduri
digitalWrite(led_galben,HIGH);
digitalWrite(led_rosu,LOW); // cel de-al treilea ramane stins,
//suntem in concentratie medie
} else if (percent_reading < nivel3){ // daca s-a depasit nivelul 3
//de concentratie
digitalWrite(led_verde,HIGH); // se aprind toate ledurile.
digitalWrite(led_galben,HIGH);
digitalWrite(led_rosu,HIGH);
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.

http://www.robofun.ro/forum
Arduino UNO, senzor de indoire si servomotor

Senzorii de indoire sau senzorii flex au proprietatea de a isi modifica


rezistenta atunci cand sunt indoiti. Cu cat gradul de indoire este mai mare, cu
atat rezistenta creste mai mult. Senzorii sunt utilizati in manusi pentru a simti
miscarile degetelor, exemplu fiind manusa Nintendo Power Glove.
Senzorul poate fi folosit si in alte scopuri, cum ar fi, sa controlezi un
servomotor in functie de gradul de indoire.
Vei avea nevoie de urmatoarele componente:

• Arduino UNO
• Servomotor medium
• Senzor de indoire 11.4 cm brick (sau varianta mai mica de 5.5 cm)
• Breadboard
• Fire pentru conexiuni.

Servomotorul are un consum suficient de mic ca sa il poti alimenta direct


din Arduino. Firele servomotorului au urmatoarele semnificatii:

Firul negru – Gnd


Firul rosu – Vcc
Firul alb – PWM

Senzorul brick se conecteaza direct la portul analogic al lui Arduino.


Semnificatiile firelor sunt marcate pe placuta de cablaj:

http://www.robofun.ro/forum
Intern, placuta contine un rezistor de 10 K (sub plasticul rosu), circuitul
obtinut formand o configuratie de divizor de tensiune, ca mai jos. Ca sa il
utilizezi, tot ce ai de facut este sa conectezi fire la cei trei pini mama (avantajul
versiunii brick).

http://www.robofun.ro/forum
Tabelul de conexiuni:

Senzor indoire pin OUT Arduino analog A0


Senzor indoire pin Vcc Arduino 5V
Senzor indoire pin Gnd Arduino Gnd
Servomotor fir alb Arduino digital 7
Servomotor fir rosu Arduino 5V
Servomotor fir negru Arduino Gnd

Cum functioneaza?

La nivelul sketch-ului, Arduino citeste in mod repetat valori ale senzorului


de indoire si le utilizeaza in functia smooth() pentru a returna o valoare cat
mai aproape de cea reala deoarece senzorul, ca orice sistem electronic,
introduce erori - salturi de la o valoare la alta. Aceste salturi pot fi declansate
de miscari bruste ale senzorului sau de o indoire incorecta. Gradul de atenuare
al erorilor il controlezi din variabila filterVal. Pentru atenuarea maxima a
erorilor poti sa alegi valoarea 0.0001. Daca servomotorul devine incontrolabil

http://www.robofun.ro/forum
sau se deplaseaza brusc in pozitii aleatorii inseamna ca este afectat de erori.
Valoarea medie obtinuta (smoothedVal) este redimensionata prin functia
map() pentru a fi adaptata servomotorului si este mentinuta corect intre
valorile (0,179) prin functia constrain().
Valoarea medie si unghiul servomotorului sunt transmise si la monitorul
serial ca sa poti vedea usor cum variaza la indoirea senzorului.
Monitorul serial va arata ca mai jos.

In plus, vei vedea ca servomotorul se misca atunci cand indoi senzorul


intr-o parte sau in alta.
Daca vei folosi 5 senzori si 5 servomotoare, vei obtine ceva ca in acest
film: http://www.tehnorama.ro/animatronic-hand/ . Tot in link-ul anterior vei
vedea si cateva poze din procesul de fabricatie al degetelor.

http://www.robofun.ro/forum
Codul sursa.

#include <Servo.h>

Servo myservo;
int sensVal; // for raw sensor values
float filterVal = 0.0001; // this determines //smoothness - .0001
is max 1 is off (no smoothing)
float smoothedVal; // this holds the last loop value just use a
//unique variable for every different sensor that needs smoothing

void setup()
{
Serial.begin(9600);
myservo.attach(7);
}

void loop()
{

sensVal = analogRead(0);
smoothedVal = smooth(sensVal, filterVal, smoothedVal);
int pos = map(smoothedVal, 440, 545, 0, 179);
pos = constrain(pos, 0, 179);
myservo.write(pos);
Serial.print("Position: ");
Serial.print(pos);
Serial.print(" Smoothed value: ");
Serial.println(smoothedVal);
delay(50);
}

int smooth(int data, float filterVal, float smoothedVal){


if (filterVal > 1){ // check to make sure param's are within
range
filterVal = .99;
}
else if (filterVal <= 0){
filterVal = 0;
}
smoothedVal = (data * (1 - filterVal)) + (smoothedVal *
filterVal);
return (int)smoothedVal;
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Priza telecomandata prin Arduino

Acest tip de priza iti permite sa pornesti/opresti, de la distanta, diversi consumatori. Comanda
ON/OFF a prizei se realizeaza prin semnalele radio emise de o telecomanda speciala conectata la placa
Arduino.
Emitatorul arata ca in imaginea de mai jos si se conecteaza la placa Arduino prin 3 pini. Modul
cum se conecteaza la placa Arduino este explicat mai jos.

Fiecare priza are o adresa unica ce poate fi setata prin 10 microswich-uri. In acest mod poti
controla pana la 1024 de prize utilizand doar o singura telecomanda. Priza arata ca in imaginea de mai
jos iar accesul la microswitch-uri se face desfacand surubul ce tine capacul fixat ferm.
Cele 10 microswitch-uri sunt marcate cu 1, 2, 3, 4, 5, respectiv A, B, C, D, E. Iti recomand sa
nu modifici configuratia actuala a producatorului, cel putin pentru inceput deoarece ele sunt
configurate cu adrese unice. Este totusi important sa deschizi capacul si sa observi configuratia switch-
urilor pentru ca ea va fi necesara in sketch-ul din Arduino.

http://www.robofun.ro/forum
Pentru acest tutorial vei avea nevoie de urmatoarele:

• Arduino UNO - http://www.robofun.ro/arduino/arduino_uno_v3.


• Una sau mai multe prize telecomandate - http://www.robofun.ro/set-trei-prize-telecomandate-
arduino.
• Telecomanda speciala pentru Arduino (inclusa in pachetul de prize).
• Fire pentru conexiuni - http://www.robofun.ro/fire_conexiune_tata_tata-140mm.

http://www.robofun.ro/forum
Cum functioneaza ?

Fiecare priza are o adresa unica si poate fi comandata ON/OFF wireless. Comanda se realizeaza
direct din Arduino. Emitatorul se conecteaza la placa astfel:

Pin Vcc telecomanda Arduino 5V


Pin Gnd telecomanda Arduino Gnd
Pin OUT telecomanda Arduino digital 10

Aplicatia.

Inainte de a scrie aplicatia sau sketch-ul este necesar sa instalezi o librarie. Aceasta librarie
contine rutinele si functiile telecomenzii si o poti descarca de aici:
http://robofun.ro/docs/RCswitch_2_51.zip

Poti sa o dezarhivezi direct in locatia unde se afla toate librariile Arduino:

http://www.robofun.ro/forum
arduino-1.0.x/libraries

Dupa dezarhivare vei obtine:

arduino-1.0.x/libraries/RCSwitch

Codul sursa.

Codul sursa este listat mai jos si il poti copia direct (copy/paste) in mediul Arduino. Incarca
sketch-ul in placa si deschide monitorul serial. In monitor ai doua optiuni: on sau off. In functie de
comanda tastata vei obtine rezultatul acesteia adica priza se va porni sau opri.

La nivelul sketch-ului vei observa 2 functii anume:

mySwitch.switchOn("11111", "11111");

Aceasta functie transmite comanda de pornire a prizei. Functia accepta doi parametrii de tip

http://www.robofun.ro/forum
string. In exemplul de fata cei doi parametrii sunt "11111" si "11111". Acesti parametrii se deduc din
pozitiile celor 10 microswitch-uri. Mai exact, pentru primul parametru, pentru fiecare microswitch
marcat de la 1 la 5 care se afla pe pozitia ON, vei pune in string ''1'' iar pentru fiecare microswitch care
este invers, vei pune ''0''. Exact la fel vei proceda si cu al doilea parametru pentru microswitch-urile
marcate de la A la E.

mySwitch.switchOff("11111", "11111");

Aceasta functie transmite comanda de oprire a prizei si accepta aceeasi parametrii explicati ca in
prima functie.

#include <RCSwitch.h>
String inputString = "";
boolean stringComplete = false;
RCSwitch mySwitch = RCSwitch();

void setup() {
Serial.begin(9600);
Serial.println("Power up ok.");
inputString.reserve(200);
mySwitch.enableTransmit(10);

// Optional, poti seta numarul de retransmiteri


// mySwitch.setRepeatTransmit(15);

}
void loop() {
if (stringComplete) {
if (inputString == "on\n") {
mySwitch.switchOn("11111", "11111");
Serial.println("Stare: pornit.");
} else if (inputString == "off\n") {
mySwitch.switchOff("11111", "11111");
Serial.println("Stare: oprit.");
}
inputString = "";
stringComplete = false;
}
}

http://www.robofun.ro/forum
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inChar == '\n') {
stringComplete = true;
}
}
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Arduino UNO si senzorul de vibratii brick

Senzorul de vibratii brick este o componenta care sesizeaza vibratiile mecanice (este capabil sa
detecteze vibratiile de genul unei batai in usa). In acest tutorial, vei conecta senzorul de vibratii brick
direct la placa Arduino si vei utiliza 3 led-uri brick (portocaliu, rosu, verde) pentru a evidentia
comportamentul senzorului.
Al doilea exemplu pe care il vom discuta va fi cel al unei yale electronice care deschide usa
atunci cand bati in usa conform unui anumit cod. Mai exact, daca bati in usa conform cu un anumit
tipar, senzorul va detecta vibratiile iar Arduino le va compara cu un model deja existent in memoria lui.
Daca tiparele se potrivesc, se va aprinde led-ul portocaliu, echivalentul deblocarii usii.

Proiectul complet il vei gasi la adresa de mai jos:


http://www.instructables.com/id/Secret-Knock-Detecting-Door-Lock/?ALLSTEPS

http://www.robofun.ro/forum
Nu trebuie decat sa bati in usa dupa modelul explicat in link-ul de mai sus (in pagina, il vei gasi
cu numele: "Shave and a Hair Cut, two bits.") iar led-ul portocaliu se va aprinde.
In imagine este prezent si un buton. Este necesar doar atunci cand incarci sketch-ul de la adresa
anterioara. In cazul tau, poti conecta foarte usor un buton brick.

Vei avea nevoie de urmatoarele componente:

• Arduino UNO.
• Senzor de vibratii brick.
• 3 led-uri brick.
• Fire pentru conexiuni.
• Breadboard.

Tabelul de conexiuni este mai jos.

Senzor vibratii pin IN Arduino analog A0


Senzor vibratii pin Gnd Arduino Gnd
Led brick portocaliu pin IN Arduino digital 3
Led brick rosu pin IN Arduino digital 4
Led brick verde pin IN Arduino digital 5
Led brick portocaliu pin Gnd Arduino Gnd
Led brick rosu pin Gnd Arduino Gnd
Led brick verde pin Gnd Arduino Gnd

Ce incarc in Arduino ?

Mai jos este listat sketch-ul (varianta simplista). Il copiezi (copy/paste) direct in mediul de
programare Arduino si il incarci in placa Arduino UNO.
Incearca sa bati in apropierea senzorului ca si cum ai bate intr-o usa. Daca ai batut dupa
modelul "Shave and a Hair Cut, two bits." (explicat in link-ul de mai sus - Instructables), led-ul verde se
aprinde urmarind fiecare bataie. La sfarsit, daca modelul de batai este recunoscut cu cel din memoria
interna, se aprinde led-ul portocaliu. In caz contrar, se aprinde led-ul rosu intr-o scurta secventa.
Daca vrei sa te asiguri ca bataile sunt detectate corect, deschide monitorul serial si vei obtine
ceva ca in imaginea de mai jos.

http://www.robofun.ro/forum
Codul sursa.

Codul sursa de mai jos este o varianta mult simplificata a celui prezentat in Instructables (spre
exemplu, nu poti inregistra un nou tipar).

const int senzorVibratii = 0;


const int ledPortocaliu = 3;
const int ledRosu = 4;
const int ledVerde = 5;
const int pragDetectie = 3;
const int gradRespingere = 25;
const int gradMediuRespingere = 15;
const int perioadaOFF = 150;
const int perioadaON = 650;
const int bataiMax = 20;
const int perioadaTotala = 1200;

int modelBatai[bataiMax] = {50, 25, 25, 50, 100, 50, 0, 0, 0, 0, 0,


0, 0, 0, 0, 0, 0, 0, 0, 0};
int bufferCitiri[bataiMax];
int nivelSenzor = 0;

http://www.robofun.ro/forum
void setup() {
pinMode(ledPortocaliu, OUTPUT);
pinMode(ledRosu, OUTPUT);
pinMode(ledVerde, OUTPUT);
Serial.begin(9600);
Serial.println("Start program.");
digitalWrite(ledVerde, HIGH);
}

void loop() {
nivelSenzor = analogRead(senzorVibratii);
if (nivelSenzor >=pragDetectie){
capturaTipar();
}
}

void capturaTipar(){
Serial.println("S-a detectat o bataie");

int i = 0;
for (i=0;i<bataiMax;i++){
bufferCitiri[i]=0;
}

int indexBatai=0;
int perioadaStart=millis();
int perioadaCurenta=millis();

digitalWrite(ledVerde, LOW);
delay(perioadaOFF);
digitalWrite(ledVerde, HIGH);

do {
nivelSenzor = analogRead(senzorVibratii);
if (nivelSenzor >=pragDetectie){
Serial.println("cioc.");
perioadaCurenta=millis();
bufferCitiri[indexBatai] = perioadaCurenta-perioadaStart;
indexBatai ++;
perioadaStart=perioadaCurenta;
digitalWrite(ledVerde, LOW);
delay(perioadaOFF);
digitalWrite(ledVerde, HIGH);
}

perioadaCurenta=millis();

http://www.robofun.ro/forum
} while ((perioadaCurenta-perioadaStart < perioadaTotala) &&
(indexBatai < bataiMax));

if (modelValid() == true){
activeazaLED();
} else {
Serial.println("Tipar de batai incorect.");
digitalWrite(ledVerde, LOW);
for (i=0;i<4;i++){
digitalWrite(ledRosu, HIGH);
delay(100);
digitalWrite(ledRosu, LOW);
delay(100);
}
digitalWrite(ledVerde, HIGH);
}
}

void activeazaLED(){
Serial.println("Tipar de batai corect. Usa deblocata.");
int i=0;
digitalWrite(ledPortocaliu, HIGH);
digitalWrite(ledVerde, HIGH);
delay (perioadaON);
digitalWrite(ledPortocaliu, LOW);
digitalWrite(ledVerde, LOW);
}

boolean modelValid(){
int i=0;
int indexBataieCurenta = 0;
int indexBataieModel = 0;
int intervalMaximBatai = 0;

for (i=0;i<bataiMax;i++){
if (bufferCitiri[i] > 0){
indexBataieCurenta++;
}
if (modelBatai[i] > 0){
indexBataieModel++;
}
if (bufferCitiri[i] > intervalMaximBatai){
intervalMaximBatai = bufferCitiri[i];
}
}
if (indexBataieCurenta != indexBataieModel){

http://www.robofun.ro/forum
return false;
}

int diferentaTotala=0;
int diferentaTimp=0;
for (i=0;i<bataiMax;i++){
bufferCitiri[i]= map(bufferCitiri[i],0, intervalMaximBatai, 0,
100);
diferentaTimp = abs(bufferCitiri[i]-modelBatai[i]);
if (diferentaTimp > gradRespingere){
return false;
}
diferentaTotala += diferentaTimp;
}
if (diferentaTotala/indexBataieModel>gradMediuRespingere){
return false;
}
return true;
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
RaspberryPI, Firmata si Arduino

Ce este Firmata ?

Firmata este un protocol prin care o aplicatie software poate comunica cu


un microcontroller. Pe placa Arduino se instaleaza un firmware care va stabili o
conexiune cu calculatorul pe care il utilizezi, folosind un protocol special.
Evident, in loc de un calculator personal, poti folosi o placa RaspberryPI. Ceea
ce obtii este posibilitatea de a utiliza multitudinea de componente din
ecosistemul Raspberry PI impreuna cu placa Raspberry PI, intr-un mod extrem
de simplu.
In cele ce urmeaza voi exemplifica aceste lucruri demonstrand cum anume se
controleaza doua motoare de curent continuu din Raspberry PI, folosind o placa
Arduino cu Firmata, si cum anume se citesc valorile unui senzor de distanta
conectat la placa Arduino direct din codul sursa Python ruland pe Raspberry PI.

Componentele de care vei avea nevoie sunt:

• RaspberryPI
• Arduino UNO
• motor cu reductor
• senzor SharpIR Rangefinder
• sursa de alimentare pentru RaspberryPI (5V)
• sursa de alimentare pentru shield L298 (functie de tensiunea de
alimentare a motorului)

http://www.robofun.ro/forum
Prima pas este sa testezi protocolul Firmata pe calculatorul personal, iar
apoi il vei instala direct pe RaspberryPI.

1. Cupleaza placa shield peste Arduino, pinii Vin si Gnd la o sursa de


alimentare(acumulator sau baterii); motoarele le vei conecta la pinii marcati cu
MOTOR1 si MOTOR2. Conecteaza platforma Arduino la portul USB al
calculatorului personal.

2. Deschide Arduino 1.0.2 (functioneaza si pe Arduino 1.0) si vei


selecta:
File – Examples – Firmata – StandardFirmata.

3. Incarca sketch-ul pe Arduino.


4. Descarca urmatoarea aplicatie fie de pe site:
http://www.firmata.org/wiki/Main_Page sau direct pentru Windows.
5. Deschide aplicatia, selecteaza portul si configureaza fereastra
astfel.

http://www.robofun.ro/forum
6. Conecteaza senzorul SharpIR Rangefinder astfel.

Arduino SharpIR
Rangefinder
5V rosu
Gnd negru
A0 alb

Daca vei apropia un obiect de senzorul IR, vei observa cum variaza A0,
din Firmata Test, in functie de distanta.
Urmeaza sa testezi motoarele direct din Firmata Test. In cazul acestui
shield, intrarile se afla pe pinii 3, 5, 6 si 9. Fie poti selecta Output pe acesti pini
si vei putea controla motoarele prin Low si High, fie poti selecta PWM si sa misti

http://www.robofun.ro/forum
de slider. In cazul acesta poti controla viteza de rotatie a motorului. Noteaza-ti
care sunt pinii pentru mersul inainte/inapoi pentru fiecare motor.

Poti descoperi si altfel in ce sens se rotesc motoarele astfel incat robotul


sa se miste corect.
7. Incarca pe Arduino programul scris mai jos si ajusteaza ordinea
pinilor pana cand robotul se misca in mod corect.

http://www.robofun.ro/forum
#define motor_stanga_inainte 5
#define motor_stanga_inapoi 3
#define motor_dreapta_inainte 6
#define motor_dreapta_inapoi 9
void setup() {
//initializam pinii pt motoare ca iesiri
pinMode(motor_stanga_inainte, OUTPUT);
pinMode(motor_stanga_inapoi, OUTPUT);
pinMode(motor_dreapta_inainte, OUTPUT);
pinMode(motor_dreapta_inapoi, OUTPUT);
//e bine sa oprim motoarele pt inceput
analogWrite(motor_stanga_inapoi, 0);
analogWrite(motor_stanga_inainte, 0);
analogWrite(motor_dreapta_inapoi, 0);
analogWrite(motor_dreapta_inainte, 0);
}
void loop() {
//inainte, cu viteza maxima, pt 2 secunde
analogWrite(motor_stanga_inapoi, 0);
analogWrite(motor_stanga_inainte, 255);
analogWrite(motor_dreapta_inapoi, 0);
analogWrite(motor_dreapta_inainte, 255);
delay(2000);
//inapoi, cu viteza mica, pt 2 secunde
analogWrite(motor_stanga_inapoi, 180);
analogWrite(motor_stanga_inainte, 0);
analogWrite(motor_dreapta_inapoi, 180);
analogWrite(motor_dreapta_inainte, 0);
delay(2000);
//la stanga: motor_dreapta inainte, motor_stanga oprit
analogWrite(motor_stanga_inapoi, 0);
analogWrite(motor_stanga_inainte, 0);
analogWrite(motor_dreapta_inapoi, 0);
analogWrite(motor_dreapta_inainte, 255);
delay(2000);//aprox 90 de grade, depinde de baterie
//stop pt 5 secunde
analogWrite(motor_stanga_inapoi, 0);
analogWrite(motor_stanga_inainte, 0);
analogWrite(motor_dreapta_inapoi, 0);
analogWrite(motor_dreapta_inainte, 0);
delay(5000);
}

8. Dupa ce ai descoperit ordinea pinilor, incarca firmware-ul


StandardFirmata din File – Example – Firmata.

http://www.robofun.ro/forum
Ai inteles in acest moment ce este Firmata si cum se poate folosi impreuna cu
Arduino pentru a controla direct senzori / motoare dintr-un calculator personal.
Mai departe vom instala Firmata pe Raspberry PI.
Firmata pe RaspberryPI

1. Deschide o sesiune SSH si logheaza-te la RaspberryPI.

2. Conecteaza Arduino la portul USB.

3. Instaleaza pachetele necesare prin comanda:


sudo apt-get install python-serial mercurial

4. Descarca pyFirmata, modulul de Firmata pentru Python:


hg clone https://bitbucket.org/tino/pyfirmata

5. Schimba locatia directorului:


cd pyfirmata

6. Instaleaza modulul.
sudo python setup.py install

7. Deschide editorul de texte nano:


sudo nano bumper.py

http://www.robofun.ro/forum
8. Copiaza codul listat mai jos.
#!/usr/bin/python
import pyfirmata #pt legatura cu Arduino
# Creeaza un obiect Arduino pe portul specificat
board = pyfirmata.Arduino('/dev/ttyACM0')
#Pinii Arduino pt motoare (ca variabile)
PIN_stanga_inainte = board.get_pin('d:5:p') #pinul digital 5 = pwm
PIN_stanga_inapoi = board.get_pin('d:3:p')
PIN_dreapta_inainte = board.get_pin('d:6:p')
PIN_dreapta_inapoi = board.get_pin('d:9:p')
# Pornim un thread Iterator care sa se ocupe de datele pe serial
(pt analog)
it = pyfirmata.util.Iterator(board)
it.start()
board.analog[0].enable_reporting() #A0 va trimite date
#Primele date citite pot fi eronate si le ignor
while board.analog[0].read() is None:
pass
def mergi(stanga, dreapta): #functie pt controlul
motoarelor(0..255)
if(stanga > 0):
PIN_stanga_inapoi.write(0)
PIN_stanga_inainte.write(stanga/255.0) #aici se opereaza in
#0..1
else:
PIN_stanga_inapoi.write(-stanga/255.0)
PIN_stanga_inainte.write(0)
if(dreapta > 0):
PIN_dreapta_inapoi.write(0)
PIN_dreapta_inainte.write(dreapta/255.0)
else:
PIN_dreapta_inapoi.write(-dreapta/255.0)
PIN_dreapta_inainte.write(0)
print 'Am pornit!'
try:
while (1):
if(board.analog[0].read() * 1024 < 400 ):
mergi(255,255) #inainte
else:
print 'Obstacol!'
mergi(180,-180) #dreapta
board.pass_time(0.8) #timpul trebuie recalibrat pt
#90grade.
except: #daca se intrerupe programul (Ctrl-C)
mergi(0,0) #stop motoare
board.exit() #inchide pyFirmata, inclusiv Iteratorul

http://www.robofun.ro/forum
9. Salveaza-l cu CTRL + X si Y pentru a confirma.

10. Executa-l cu:


sudo python bumper.py

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Telecomanda universala Arduino in infrarosu

In acest tutorial vei afla cum se poate realiza o aplicatie pe platforma


Arduino care sa se comporte ca o telecomanda universala IR sau sa primeasca
un set de comenzi de la o telecomanda de TV. Spre exemplu, vei putea sa iti
controlezi televizorul sau aerul conditionat direct din Arduino (cu comanda
peste Internet sau bluetooth).
Poti controla diverse aparate care accepta comenzi IR, roboti sau se
poate realiza o comunicatie intre doua platforme Arduino. In a doua instanta,
platforma poate receptiona si interpreta diverse comenzi de la o telecomanda
de TV si ar putea sa realizeze, de exemplu, comanda unui motor, modificarea
unghiului unui servomotor, aprinderea/stingerea unor led-uri de putere mare,
joc de lumini, textul care defileaza pe o matrice de leduri, s.a.m.d.

Vei avea nevoie de urmatoarele componente:

• Led IR brick
http://www.robofun.ro/bricks/led-telecomanda-infrarosu
• Senzor TSOP brick
http://www.robofun.ro/bricks/senzor-telecomanda-infrarosu
• Buton brick
http://www.robofun.ro/buton-mare-brick
• Breadboard
http://www.robofun.ro/breadboard-82x52x10
• O placa Arduino
• Mediul de programare Arduino-1.x
• Telecomanda IR (orice fel de telecomanda de televizor) (pentru testare si
invatarea comenzilor)

http://www.robofun.ro/forum
Cum se conecteaza ?

Conform imaginii de mai sus, senzorul TSOP se pozitioneaza cu partea


plana in jos. Firele de conexiune sunt marcate pe placuta senzorului prin VCC,
GND si OUT.
Pentru led-ul IR, conexiunile sunt marcate cu IN si GND.

Tabelul de conexiuni.

Senzor TSOP pin VCC Arduino 5V


Senzor TSOP pin GND Arduino GND
Senzor TSOP pin OUT Arduino pin digital 11
LED IR IN Arduino pin digital 3
LED IR GND Arduino GND

Libraria IRremote.

Acceseaza https://github.com/shirriff/Arduino-IRremote si descarca fisierul


.zip. Dezarhiveaza fisierul si redenumeste-l in IRremote. Muta directorul

http://www.robofun.ro/forum
IRremote in arduino-1.x/libraries/
Libraria iti pune la dispozitie mai multe exemple. Spre exemplu cu
IRsendDemo, poti sa transmiti coduri IR catre diferite dispozitive ce accepta
aceste coduri (televizor, sistem audio, etc) iar IRrecvDemo iti afiseaza in
monitorul serial, diferite coduri IR ale unei telecomenzi.

Exista foarte multe tipuri de telecomenzi si fiecare telecomanda emite


intr-un mod diferit fata de celelalte. Practic fiecare telecomanda are propriul
protocol si lucrul asta se datoreaza unui numar foarte mare de echipamente
audio/video si de producatorii acestora.
Exemplu de protocoale: ITT, JVC, Mitsubishi, NEC, Nokia, Sharp, Sony,
Phillips RC-5, Phillips RC-6, Phillips RC-MM, Phillips RECS80, RCA, X-Sat

Cum citesc o telecomanda existenta?

Sa luam exemplul unei telecomenzi RC5. Pentru asta vei deschide si vei
incarca in Arduino sketch-ul IRrecvDump. Senzorul TSOP este deja conectat la
Arduino (daca inca nu l-ai conectat, urmareste tabelul de conexiuni). El va
prelua comenzile RC5 de la telecomanda, Arduino le va decoda si le va afisa in
monitorul serial.
Astfel, apasa diferite butoane cu telecomanda indreptata spre senzor si
urmareste monitorul serial. Vei obtine diverse informatii cu privire la codul
receptionat:

• protocolul decodat (Decoded RC5 in imaginea de mai jos)


• codul butonului ( ex: 820 daca butonul este apasat separat de mai multe
ori si 20 daca butonul este apasat incontinuu)

http://www.robofun.ro/forum
• o serie de valori Raw (perioadele semnalelor)

Din acest exemplu te intereseaza: tipul protocolului, codul butonului si nr.


de biti (in imaginea de mai sus avem: RC5, valoarea: 20 si nr. de biti: 12)
pentru ca le vei utiliza in urmatoarele exemple.
Aici am apasat butonul Program +.
Un alt exemplu este cel al unei telecomenzi al carui protocol este
necunoscut.

http://www.robofun.ro/forum
Chiar daca nu se cunoaste protocolul, tot poti sa obtii ceva informatii
despre codul telecomenzii (valoarea butonului si nr. de biti).

Cum transmit coduri IR pentru Sonny ?

Avem Arduino, senzorul TSOP si led-ul IR. Mai devreme ai aflat cum se
citeste o telecomanda, ce protocol ii apartine, ce cod are butonul apasat si nr.
de biti. Te vei utiliza de aceste informatii in urmatorul exemplu.
Deschide sketch-ul IRsendDemo, dar deocamdata nu il vei incarca.
Codul este simplu de inteles. In rutina setup() se initializeaza portul
serial la 9600 baud. In rutina loop() se urmareste daca se receptioneaza ceva
anume (orice) de la monitorul serial. Daca s-a receptionat se transmite un cod.
In exemplu, este vorba de codul de pornire al televizoarelor Sony.
Daca dispui de o telecomanda/televizor Sony poti testa acest lucru.
Incarca sketch-ul in Arduino, deschide monitorul serial si tasteaza ceva anume
in el. Asigura-te ca led-ul IR se afla indreptat spre televizor.
La nivelul codului, Arduino receptioneaza ce ai tastat in Serial monitor
(orice, important este sa fie ceva) si transmite codul de pornire Sony prin led-ul
IR. (daca nu l-ai conectat, urmareste tabelul de mai sus).

http://www.robofun.ro/forum
Cum procedez daca vreau sa transmit coduri RC5 (sa schimb canalul
unui TV)?

Daca te uiti in codul sursa al exemplului anterior, vei observa liniile:

for (int i = 0; i < 3; i++) {


irsend.sendSony(0xa90, 12); // Sony TV power code
delay(40);
}

Daca vrei sa schimbi canalul unui televizor cu RC5, modifici:

for (int i = 0; i < 10; i++) {


irsend.sendRC5(0x20, 12);
//delay(40);
}

Utilizand parametrii de la exemplul cu monitorul serial (IRrecvDump), i-ai


introdus in functia irsend.sendRC5(0x20, 12) si ai schimbat canalele.
Parametrii pe care i-a preluat functia sunt: 0x20 si 12 ceea ce inseamna ca s-a
transmis codul pentru Program + iar 12 reprezinta nr. de biti.
Daca vrei sa observi lumina infrarosie emisa de led, poti sa folosesti
camera foto a telefonului.

Cum procedez in cazul unui protocol necunoscut?

In primul exemplu, ai vazut cum apare si codul unei telecomenzi cu


protocol necunoscut. In cazul acesta poti testa exemplul IRrecord. Pentru
acest exemplu te vei utiliza de butonul brick.

Tabelul de conectare al butonului brick.

http://www.robofun.ro/forum
Pin OUT Arduino digital pin 12
Pin GND Arduino GND
Pin VCC Arduino VCC

Incarca sketch-ul in Arduino si deschide monitorul serial. Indreapta


telecomanda (cea cu protocol necunoscut) catre senzorul TSOP si apasa un
buton. Ar trebui sa iti apara ceva asemanator cu imaginea de mai jos.

http://www.robofun.ro/forum
Acum apasa butonul brick si vei obtine urmatoarea imagine.

Ce se intampla la nivelul programului ?

Acest exemplu de program te ajuta oarecum sa reproduci codul IR al unei


telecomenzi cu protocol necunoscut. In prima faza Arduino detecteaza codul si
il stocheaza in memoria interna (Received unknown code, saving as raw). In a
doua faza, daca apesi butonul, Arduino reproduce prin led-ul IR codul pe care
tocmai l-a salvat.

Alte informatii cu privire la protocoale ?

Daca vrei sa testezi mult mai multe comenzi si doresti sa afli care sunt
codurile specifice fiecarui buton al telecomenzii, iti recomand sa studiezi
pagina urmatoare:

http://www.sbprojects.com/knowledge/ir/index.php

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Cum sa construiesti un robot line follower
BASIC

In acest tutorial iti propun sa construiesti un robot line follower basic. In prima parte a
tutorialului vei descoperi ce este un robot line follower si cum functioneaza. In a doua parte vei afla
cum se poate construi un robot cu platforma Magician, special conceputa pentru acest tip de robot.
In ultima parte a tutorialului vei implementa codul sursa dar nu inainte sa testezi senzorii printr-un
program separat.

Ce este un robot line follower ?

Robotii line follower sunt construiti cu un singur scop: sa urmareasca o linie neagra pe
fundal alb si sa nu o piarda iar daca o pierde, sa o regaseasca intr-un timp scurt. Robotul de fata va
realiza acest lucru utilizand 2 senzori de infrarosu care detecteaza culoarea respectiv linia neagra
fata de fundalul alb.
Fiecare senzor de infrarosu este compus dintr-o fotodioda si un fototranzistor. Atunci cand
fotodioda este parcursa de un curent electric, ea emite lumina infrarosie. Lumina infrarosie este
reflectata sau absorbita de linia neagra sau fundalul alb. Daca lumina este reflectata atunci cea mai
mare parte din ea ajunge si la fototranzistor. In functie de modul de conectare al fototranzistorului in
circuit, tensiunea de iesire creste sau scade.

In schema de mai sus, atunci cand lumina IR este absorbita de linia neagra (nu ajunge la
fototranzistor), valoarea tensiunii de iesire OUT este de 5V. Cu cat ajunge mai multa lumina pe
fototranzistor, cu atat OUT scade mai mult.

http://www.robofun.ro/forum
Cum se poate construi un robot ?

Pentru ca robotul sa execute o decizie corecta (in functie de cum va urmari linia) va avea
nevoie si de o placa Arduino. Iti propun sa utilizezi un kit special construit pentru acest tip de robot
format din: platforma Magician Robot, shield L298 deja asamblat, o placa Arduino UNO R3 si doi
senzori de linie. Ca sursa de alimentare poti opta pentru o cutie de baterii sau un acumulator Li-PO.

Poti conecta componentele in ordinea urmatoare: placa Arduino se monteaza pe robotul


Magician (cu suruburi si piulite). Tot pe robot se monteaza si acumulatorul, alaturi de placa, fie in
fata sau in spatele robotului. Urmeaza sa conectezi shield-ul L298 la placa Arduino si senzorii IR.
Conecteaza cele 2 motoare la pinii marcati cu “MOTOR1” si “MOTOR2” de pe placa cu L298.
Sursa de alimentare pentru motoare se conecteaza la pinii marcati cu “VIN” si “GND” dar pentru
moment pastrezi robotul nealimentat.
Fiecare senzor de linie are 3 terminale: Vcc, OUT, GND si se vor conecta dupa tabelul de
mai jos.
Senzor Vcc Arduino 5V
Senzor OUT* Arduino A0 - A1
Senzor Gnd Arduino Gnd

*Iesirea OUT a primului senzor se conecteaza la A0 iar iesirea OUT al celui de-al doilea
senzor se conecteaza la A1.

http://www.robofun.ro/forum
Codul sursa.

Dupa ce ai terminat de asamblat robotul este timpul sa incarci sketch-ul in Arduino. In prima
parte vei incarca un program simplu cu scopul de a testa modul de functionare al senzorilor. Incarca
urmatorul cod in placa Arduino si deschide monitorul serial.

int senzor1 = A0;


int senzor2 = A1;
int valoareSenzor = 0;

void setup() {

Serial.begin(9600);

void loop() {
valoareSenzor = analogRead(senzor1);
Serial.print(" Valoare senzor 1: ");
Serial.print(valoareSenzor);

valoareSenzor = analogRead(senzor2);
Serial.print(" Valoare senzor 2: ");
Serial.println(valoareSenzor);
delay(100);
}

http://www.robofun.ro/forum
Acum incearca sa plimbi senzorii pe deasupra liniei negre si vei observa cum variaza cele
doua valori. Atunci cand senzorii se afla pe fundal alb, valorile vor fi mari si invers cand senzorii se
afla pe banda neagra.
Sketch-ul urmator este programul de line follower. Este relativ simplu si usor de inteles.

int senzor1 = A0;


int senzor2 = A1;
int valoareSenzor1 = 0;
int valoareSenzor2 = 0;

int MOTOR2_PIN1 = 3;
int MOTOR2_PIN2 = 5;
int MOTOR1_PIN1 = 6;
int MOTOR1_PIN2 = 9;

void setup() {
pinMode(MOTOR1_PIN1, OUTPUT);
pinMode(MOTOR1_PIN2, OUTPUT);
pinMode(MOTOR2_PIN1, OUTPUT);
pinMode(MOTOR2_PIN2, OUTPUT);
Serial.begin(9600);

void loop() {
valoareSenzor1 = analogRead(senzor1);
Serial.print(" Valoare senzor 1: ");
Serial.print(valoareSenzor1);

valoareSenzor2 = analogRead(senzor2);
Serial.print(" Valoare senzor 2: ");
Serial.println(valoareSenzor2);

if (valoareSenzor1 > valoareSenzor2) { // robotul se ghideaza la


stanga
go(-255,255);
} else if (valoareSenzor1 < valoareSenzor2) { // robotul se
ghideaza la dreapta
go(255,-255);
} else if ((valoareSenzor1 - valoareSenzor2) <= 10) { // robotul
merge inainte
go(255,255);
} else if ((valoareSenzor2 - valoareSenzor1) <= 10) { // robotul
merge inainte
go(255,255);
}

http://www.robofun.ro/forum
delay(10); // aici se poate modifica perioada
}

void go(int speedLeft, int speedRight) {


if (speedLeft > 0) {
analogWrite(MOTOR1_PIN1, speedLeft);
analogWrite(MOTOR1_PIN2, 0);
}
else {
analogWrite(MOTOR1_PIN1, 0);
analogWrite(MOTOR1_PIN2, -speedLeft);
}

if (speedRight > 0) {
analogWrite(MOTOR2_PIN1, speedRight);
analogWrite(MOTOR2_PIN2, 0);
}
else {
analogWrite(MOTOR2_PIN1, 0);
analogWrite(MOTOR2_PIN2, -speedRight);
}
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Senzorul capacitiv

Prezentare.

In acest tutorial vei descoperi cum se poate construi si utiliza, cu o placa Arduino, un senzor
capacitiv. Libraria pe care o vei instala iti transforma 2 pini de pe placa Arduino intr-un senzor
capabil sa detecteze capacitatea electrica a corpului uman. Senzorul se poate construi relativ usor si
este format dintr-un rezistor de valoare mare, un fir de conexiune si o folie de Al. In functie de
valoarea rezistentei si de suprafata foliei, senzorul poate detecta corpul uman de la o distanta de
cativa cm.

Unde se poate aplica ?

Senzorul capacitiv se poate utiliza in orice loc unde detectia prin atingere este preferabila si
detectia este posibila chiar si prin cativa mm de material plastic, lemn, ceramica sau alte materiale
izolatoare. In acest mod senzorul poate fi acoperit si protejat.
Daca senzorul este acoperit cu un izolator ca foaia de hartie, atunci el se poate comporta ca
un senzor de forta avand un raspuns aproximativ logaritmic.

Cum functioneaza?

http://www.robofun.ro/forum
In imaginea de mai sus, cei 2 pini “Send” si “Receive” se vor conecta la placa Arduino. In
libraria speciala a senzorului exista o functie capacitiveSensor care schimba starea pinului Send. In
tot acest timp functia testeaza si cronometreaza daca pinul Receive a ajuns la starea pinului Send si
in final returneaza o valoare care variaza in functie de capacitatea senzorului.
Fizic, senzorul este alcatuit dintr-un rezistor care are o valoare cuprinsa intre 500KΩ-50MΩ.
Rezistorul se conecteaza intre pinii Send si Receive, iar la pinul Receive se conecteaza o folie din
Al, printr-un fir de conexiune si reprezinta de fapt partea sensibila a senzorului.
Atunci cand starea pinului Send este schimbata de placuta Arduino, dupa o perioada de
timp, pinul Receive isi schimba starea functie de Send. Perioada de tranzitie a pinului Send si a
pinului Receive este data de R * C, R fiind valoarea rezistentei si C este capacitatea care se
formeaza la pinul Receive. Valoarea rezistentei este constanta, dar capacitatea se schimba atunci
cand exista o atingere pe folia de Al. In acest mod exista intotdeauna o diferenta notabila atunci
cand folia este sau nu atinsa.

Functiile librariei.

CapacitiveSensor CapacitiveSensor(byte sendPin, byte receivePin)

Functia creaza o instanta a librariei si accepta 2 parametrii de tip byte, respectiv pinul Send
si pinul Receive.

long capacitiveSensorRaw(byte samples)

Functia returneaza o valoare de tip long integer a capacitatii absolute. Accepta ca parametru
un numar de samples sau esantioane. Cu cat samples este mai mare, cu atat rezolutia este mai mare
dar performanta este mai scazuta (timpi de executie mai mari). Daca valoarea returnata este -2
inseamna ca valoarea capacitatii depaseste valoarea CS_Timeout_Millis. Valoarea nominala
CS_Timeout_Millis este de 2000 mS.

long capacitiveSensor(byte samples)

Functia necesita parametrul samples si returneaza o valoare cumulata de tip long a


capacitatii. Functia returneaza o valoare foarte mica atunci cand nu exista nicio atingere pe folia de
Al.

void set_CS_Timeout_Millis(unsigned long timeout_millis)

Functia iti permite sa alegi perioada de timeout in care se asteapta ca pinul Receive sa isi
schimbe starea dupa pinul Send. Daca in perioada aleasa nu se realizeaza tranzitia Send / Receive,
se paraseste automat din functie cu valoarea -2. Valoarea nominala este de 2 secunde.

http://www.robofun.ro/forum
void reset_CS_AutoCal()

Prin aceasta functie se poate initia o calibrare fortata a senzorului.

void set_CS_AutocaL_Millis(unsigned long autoCal_millis)

Functia stabileste perioada de timeout pentru cealalta functie capacitiveSensor.

Cum utilizez senzorul cu placa Arduino ?

Iti propun urmatorul test pe care il poti realiza pe un breadboard avand o rezistenta, 3 fire de
conexiuni si o folie de Al. Se poate urmari schema orientativa din prima imagine.
Fizic, testul va arata astfel:

Descarca libraria de aici si dezarhiveaza continutul fisierului libraries in locatia:


arduino-1.0.x/libraries.
Deschide un sketch nou si copiaza (copy-paste) codul listat mai jos.
Incarca sketch-ul in placuta Arduino si deschide monitorul serial. Vei observa o serie de
valori ce se vor schimba atunci cand atingi sau nu folia de Al.
Monitorul va arata astfel.

http://www.robofun.ro/forum
Cand senzorul nu este atins, valorile vor oscila intre 1 si 2 (cea de-a doua coloana). Cand
senzorul este atins apare o diferenta notabila intre valori (peste 200).

Codul sursa.

http://www.robofun.ro/forum
#include <CapacitiveSensor.h>

CapacitiveSensor cs_4_2 = CapacitiveSensor(4,2); // 10M


resistor between pins 4 & 2, pin 2 is sensor pin, add a wire and or
foil if desired

void setup()
{
cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF); // turn off
autocalibrate on channel 1 - just as an example
Serial.begin(9600);
}

void loop()
{
long start = millis();
long total1 = cs_4_2.capacitiveSensor(30);

Serial.print(millis() - start); // check on performance


in milliseconds
Serial.print("\t"); // tab character for
debug windown spacing
Serial.print(total1); // print sensor output 1
Serial.println("\t");

delay(100); // arbitrary delay to


limit data to serial port
}

Concluzie.

Este important ca placa Arduino sa fie conectata la o impamantare (GND). Daca utilizezi un
laptop, este posibil ca senzorul sa devina instabil. Daca devine instabil atunci poti conecta
incarcatorul, pentru ca iti ofera si punct de masa. O alta cale de a conecta placa Arduino este printr-
un fir de conexiune direct la un punct care face contact cu impamantarea, dar numai daca se doreste
si daca este posibil.
Stabilitatea senzorului se poate imbunatati printr-un condensator de 100 pF - .01 uF conectat
intre pin-ul Receive sau punctul senzitiv si GND.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Raspberry PI te anunta cand primesti e-mail

In cadrul acest tutorial vei realiza o mica aplicatie ce va anunta primirea unui email nou. Vei
folosi doua leduri brick de culori diferite, acestea fiind conectate la portul GPIO al placii Raspberry PI
si se vor aprinde in mod diferit atunci cand primesti email-uri pe contul tau de Gmail.

Conexiunile led-urilor.

Led Rosu IN RaspberryPI #18


Led Rosu GND RaspberryPi GND
Led Galben IN RaspberryPI #23
Led Galben GND RaspberryPi GND

http://www.robofun.ro/forum
Instalarea scriptului.

Inainte de a instala scriptul asigura-te ca Raspberry booteaza Raspbian "wheezy", se afla


conectat la reteaua de internet si poate fi accesat printr-o sesiune SSH. Adresa de IP a calculatorului o
poti lua fie din tabela routerului, fie daca atasezi un monitor HDMI sau un TV. Adresa IP apare inainte
de prompt-ul in care ti se cer datele de conectare(user si parola).
Deschide putty sau clientul de SSH, introdu: username, parola si conecteaza-te la placa
Raspberry PI folosind SSH.

Este posibil sa ai deja python instalat si pachetele aferente, dar daca ai inceput de putin timp sa
experimentezi cu Raspberry atunci trebuie sa urmezi pasii de instalare.
1. Instaleaza Python:
sudo apt-get install python-dev
sudo apt-get install python-pip

2. Instaleaza libraria python care gestioneaza parsarea feed-ului de e-mail.


sudo pip install feedparser

3. Realizeaza un update al distributiei python prin comanda:

http://www.robofun.ro/forum
sudo easy_install -U distribute

4. Instaleaza libraria GPIO prin comanda:


sudo pip install RPI.GPIO

5. Deschide editorul nano pentru a scrie codul sursa (copy-paste):


sudo nano raspi_gmail.py

6. Copiaza codul de mai jos in editor (copy-paste):


cat <<! > raspi_gmail.py
#!/usr/bin/env python
import RPi.GPIO as GPIO, feedparser, time
DEBUG = 1
USERNAME = "username" # just the part before the @ sign, add yours
PASSWORD = "password"
NEWMAIL_OFFSET = int(feedparser.parse("https://" + USERNAME + ":" +
PASSWORD +"@mail.google.com/gmail/feed/atom")["feed"]["fullcount"])
MAIL_CHECK_FREQ = 60 # check mail every 60 seconds
GPIO.setmode(GPIO.BCM)
YELLOW_LED = 18
RED_LED = 23
GPIO.setup(YELLOW_LED, GPIO.OUT)
GPIO.setup(RED_LED, GPIO.OUT)
while True:
newmails = int(feedparser.parse("https://" + USERNAME + ":" +
PASSWORD +"@mail.google.com/gmail/feed/atom")["feed"]["fullcount"])
if DEBUG:
print "You have", newmails, "new emails!"
if newmails > NEWMAIL_OFFSET:
GPIO.output(YELLOW_LED, True)
GPIO.output(RED_LED, False)
else:
GPIO.output(YELLOW_LED, False)
GPIO.output(RED_LED, True)
time.sleep(MAIL_CHECK_FREQ)

http://www.robofun.ro/forum
In loc de username si password vei scrie datele de conectare ale contului tau de gmail. Vei avea
ceva similar cu ce este mai jos.

7. Urmeaza sa ii dai permisiunea de executie:


sudo chmod +x raspi_gmail.py

8. Executa script-ul cu comanda:


sudo ./raspi_gmail.py

Concluzie.
Vei avea doua led-uri care se vor aprinde in functie de numarul de email-uri primite.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Raspberry PI si cititorul RFID ID-12

Cititorul RFID ID-12 se poate conecta foarte usor la Raspberry PI. Pentru urmatorul tutorial
vei avea nevoie de urmatoarele componente:

• Raspberry PI
• sursa de alimentare (5V)
• adaptor RFID pe USB
• cititor ID-12
• tag-uri RFID
• cablu miniUSB
• o pereche de casti audio/boxe de calculator

http://www.robofun.ro/forum
Cum procedez ?

Conecteaza cititorul RFID la adaptorul USB. Vei conecta adaptorul prin cablu miniUSB la unul
dintre porturile USB ale lui Raspberry PI. Daca vrei sa te loghezi prin SSH asigura-te ca ai si o
conexiune de internet. Totusi nu este obligatoriu daca dispui de un monitor HDMI, tastatura si mouse.
Daca optezi pentru a doua varianta ti-ar fi necesar si un hub USB cu mai multe porturi pentru ca doua
sunt insuficiente.
Indiferent de metoda aleasa, vei testa aceeasi aplicatie si vei aplica aceleasi comenzi.
Aplicatia pe care o vei testa va afisa in terminal sau pe monitor seria unica a tag-ului. Tot in
aplicatie se va detecta si se va afisa daca una dintre seriile unice apartine unei persoane (printr-un mesaj
de intampinare vocal).

Varianta prin SSH.

Daca ai optat pentru prima varianta atunci este cazul sa deschizi Putty, sa tastezi IP-ul placii
Raspberry si sa te loghezi cu id-ul si parola.

Fereastra de conectare Putty si terminal-ul.

http://www.robofun.ro/forum
Varianta cu monitor HDMI.

Pentru a doua varianta, cea cu monitor HDMI, nu trebuie decat sa alimentezi placa Raspberry si
sa astepti sa te loghezi in sistemul de operare (cu id-ul si parola)

Aplicatia python ?

Dupa ce te-ai logat folosind una dintre variante, poti trece la scrierea aplicatiei.

1. Optional instaleaza Festival daca nu ai parcurs tutorialul de sinteza vocala:

sudo apt-get install festival

2. Deschide editorul nano:

sudo nano rfid_reader.py

3. Copiaza urmatorul cod (copy/paste):

http://www.robofun.ro/forum
#!/usr/bin/python
# -*- coding: utf-8 -*-

from serial import Serial


import os
import subprocess

id = 0
serialADD = '290067647D57'
text = '"Welcome Mr Robert!"'
textDenied = '"Access denied!"'

ser = Serial('/dev/ttyUSB0',9600)
os.system('clear')

while 1:
id = ser.readline()

print 'Serie RFID tag: ' + id


if (serialADD in id):
print text
subprocess.call('echo '+text+'|festival --tts', shell=True)
else:
print textDenied
subprocess.call('echo '+textDenied+'|festival --tts',
shell=True)

ser.close()

4. Salveaza si apeleaza aplicatia cu:

sudo python rfid_reader.py

5. Daca apropii tag-urile de cititor vei obtine urmatoarea fereastra:

http://www.robofun.ro/forum
Ce se intampla in interiorul aplicatiei?

Se citeste seria tag-ului prin functia ser.readline() si se stocheaza in variabila id. Se printeaza pe
monitor „Serie RFID tag“ + id.
Se testeaza daca seria citita (cea din variabila id) corespunde cu seria unica (serialADD). La
nivelul codului daca serialADD face parte din id se printeaza variabila text („Welcome Mr Robert“) si
se executa deasemenea subprocess.call('echo '+text+'|festival --tts', shell=True) adica se apeleaza
programul festival (cel de sinteza de voce) cu variabila text.
Daca serialADD nu corespunde cu id, atunci se afiseaza „Access denied“ si se reda audio prin
acelasi procedeu.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Raspberry PI, senzor apasare brick si SensorShield

Senzorul de apasare brick are particularitatea de a isi modifica rezistenta in functie de forta
aplicata pe suprafata acestuia. Caracteristica senzorului variaza aproximativ logaritmic cu forta aplicata.
Senzorul brick contine un rezistor de 10K conectat in configuratie de divizor de tensiune impreuna cu
senzorul activ.
Raspberry PI nu este echipat cu convertor analog/digital pentru a citi semnalul produs de
senzor. Din aceasta cauza vei utiliza shield-ul creat special pentru a ii oferi aceasta functie placii
Raspberry. Shield-ul preia semnalul analogic al senzorului si il transforma intr-un semnal digital, acesta
fiind citit de placa Raspberry. Shield-ul iti permite citirea a cel mult 8 senzori analogici.
In acest tutorial vei scrie o mica aplicatie in Python ce va citi, va afisa valoarea senzorului iar
daca valoarea a depasit un anumit prag, aplicatia va afisa o avertizare.

In cadrul acestui tutorial vei avea nevoie de urmatoarele componente:

• Raspberry PI.
• Sursa de alimentare (5V).
• Senzor de apasare patrat brick.
• SensorShield V2.
• Fire pentru conexiuni.

http://www.robofun.ro/forum
Tabelul conexiunilor.

Sensor Shield 3.3V Raspberry PI 3.3V


Sensor Shield 5V Raspberry PI 5V
Sensor Shield Gnd Raspberry PI Gnd
Sensor Shield IN1 Raspberry PI GPIO18
Sensor Shield IN2 Raspberry PI GPIO23
Sensor Shield IN3 Raspberry PI GPIO24
Sensor Shield IN4 Raspberry PI GPIO25
Senzor apasare brick VCC SensorShield 5V Power(Sensors)
Senzor apasare brick GND SensorShield GND Power(Sensors)
Senzor apasare brick OUT SensorShield A0

Dupa ce ai realizat toate conexiunile din tabel vei obtine ceva similar ca mai jos.

http://www.robofun.ro/forum
Cum functioneaza aplicatia ?

Aplicatia python citeste datele de la senzorul analogic de apasare brick prin intermediul shield-
ului. In acelasi timp aplicatia testeaza daca valoarea senzorului a depasit pragul. Daca l-a depasit va afisa
o avertizare.
1. Mai intai creezi un fisier si copiezi codul sursa listat mai jos. Fisierul se creeaza prin
comanda:

sudo nano SenzorApasare.py

2. Salveaza-l cu CTRL X si Y.
3. Executa-l cu comanda:

sudo python SenzorApasare.py

Daca nu ai primit nici o eroare vei obtine valorile senzorului in terminal ca in imagine.

http://www.robofun.ro/forum
Codul sursa.

#!/usr/bin/env python
import time
import os
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

def readadc(adcnum, clockpin, mosipin, misopin, cspin):


if ((adcnum > 7) or (adcnum < 0)):
return -1
GPIO.output(cspin, True)

GPIO.output(clockpin, False)
GPIO.output(cspin, False)

http://www.robofun.ro/forum
commandout = adcnum
commandout |= 0x18
commandout <<= 3
for i in range(5):
if (commandout & 0x80):
GPIO.output(mosipin, True)
else:
GPIO.output(mosipin, False)
commandout <<= 1
GPIO.output(clockpin, True)
GPIO.output(clockpin, False)

adcout = 0
for i in range(12):
GPIO.output(clockpin, True)
GPIO.output(clockpin, False)
adcout <<= 1
if (GPIO.input(misopin)):
adcout |= 0x1

GPIO.output(cspin, True)

adcout >>= 1
return adcout

SPICLK = 18
SPIMISO = 23
SPIMOSI = 24
SPICS = 25

GPIO.setup(SPIMOSI, GPIO.OUT)
GPIO.setup(SPIMISO, GPIO.IN)
GPIO.setup(SPICLK, GPIO.OUT)
GPIO.setup(SPICS, GPIO.OUT)

prag = 700

while True:
value = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS)
print ""Nivelul de apasare (0-1023): " + str(value)
if value > prag:
print “Nivelul de prag a fost depasit!”
time.sleep(0.5)

http://www.robofun.ro/forum
Iti apar erori la executie ?

Este posibil sa-ti lipseasca o librarie sau extensie python. Iti recomand sa parcurgi urmatorii
pasi:
1. Instaleaza python:

sudo apt-get install python-dev

2. Instaleaza python – pip:

sudo apt-get install python-pip

3. Instaleaza extensia RPI.GPIO:

sudo pip install rpi.gpio

4. Este posibil sa primesti o eroare legata de easy_install.

sudo easy_install -U distribute

5. Daca ai primit eroare tasteaza din nou comanda de la pasul 3.


Acum totul ar trebui sa functioneze fara probleme.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Arduino+Senzor Vibratii Brick + MODIO2 + Telefon Vechi =>
Sistem de control la distanta peste GSM

In acest tutorial iti propun ideea de a folosi un telefon vechi (setat pe


vibratii) impreuna cu un senzor de vibratii brick. Atunci cand apelezi telefonul,
acesta vibreaza, senzorul de vibratii sesizeaza acest lucru, si ca raspuns
Arduino actioneaza un releu. Care releu poate actiona orice vrei tu. De
exemplu, o pompa de irigantii. Sau un reflector. Sau orice altceva ai nevoie.
Poti folosi orice telefon din generatia mai veche, cu conditia sa dispuna
de apel prin vibratii. Senzorul il vei conecta la o placa Arduino UNO. Pentru
exemplul de mai jos, ca sarcina pentru releu vom folosi un led brick. Evident ca
tu il poti inlocui cu orice sarcina de putere mare.

Componentele necesare:

• Arduino UNO.
• MOD-IO2.
• Senzor de vibratii brick.
• Adaptor Rpi-UEXT.
• Breadboard.
• Sursa de alimentare pentru MOD-IO2 (12V).
• LED brick.
• Fire pentru conexiuni.
• Telefon.

http://www.robofun.ro/forum
Tabelul de conexiuni:

Arduino UNO SCL Rpi-UEXT SCL


Arduino UNO SDA Rpi-UEXT SDA
Arduino UNO A0 Senzor vibratii brick IN
Arduino UNO GND Rpi-UEXT GND
Arduino UNO GND Senzor vibratii brick GND
Led brick IN MOD-IO2 GPIO 0
Led brick GND MOD-IO2 GND

Realizeaza conexiunile conform tabelului. Vei obtine o schema


asemanatoare cu cea din imaginea de mai jos:

Incarca pe Arduino cod de mai jos. Pentru testarea sistemului, nu trebuie


decat sa apelezi telefonul si sa observi cum MOD-IO2 comuta releul (si led-ul se
aprinde).
Totusi inainte de a incarca sketch-ul, este necesar sa realizezi o
modificare in mediul Arduino. Magistrala I2C a placii Arduino lucreaza la
frecventa de 100Khz dar MOD-IO2 lucreaza cu succes doar la 50Khz. Vei
modifica frecventa placii Arduino din fisierul de mai jos.

http://www.robofun.ro/forum
arduino-1.0.2/libraries/Wire/utility/twi.h

Deschide fisierul twi.h (cu Notepad, de exemplu) si cauta liniile:


#ifndef TWI_FREQ
#define TWI_FREQ 100000L
#endif

Schimba valoarea 100000L in 50000L.


Cand vrei sa abordezi alte proiecte, nu uita sa schimbi la loc valoarea.

http://www.robofun.ro/forum
#include <Wire.h>
int led = 0;
int whichRelay = 0;

const int contor1=5; // secunde


const int contor2=5; // secunde
const int nivelVibratii = 1; // nivelul de vibratii

void setup() {
Serial.begin(9600);
Wire.begin();
setareGPIO();
setGPIOState(0,0);
setRelayState(0,0);
}

void loop() {
int val = maxim(0, 100);
if (val > nivelVibratii) {
setGPIOState(0,1);
setRelayState(0,1);
delay(contor1*1000);
setGPIOState(0,0);
setRelayState(0,0);
delay(contor2*1000);
}
}

int maxim(int pin, int count) {


int valoareMaxima = 0;
for (int i = 0; i < count; i++) {
valoareMaxima = max(analogRead(pin), valoareMaxima);
}
return valoareMaxima;
}

void setareGPIO() {
Wire.beginTransmission(0x48);
Wire.write(0x02);
Wire.write(0xA0);
Wire.write(0x01);
Wire.write(0x00);
Wire.endTransmission();
}

void setGPIOState(int gpio, int state) {

http://www.robofun.ro/forum
if (state == 1) bitSet(led, gpio);
if (state == 0) bitClear(led, gpio);
Wire.beginTransmission(0x48);
Wire.write(0x02);
Wire.write(0xA0);
Wire.write(0x02);
Wire.write(led);
Wire.endTransmission();
}

void setRelayState(int relay, int state) {


if (state == 1) bitSet(whichRelay, relay);
if (state == 0) bitClear(whichRelay, relay);
Wire.beginTransmission(0x48);
Wire.write(0x02);
Wire.write(0xA0);
Wire.write(0x40);
Wire.write(whichRelay);
Wire.endTransmission();
}

In program sunt definite 2 constante: contor1 si contor2, constante


responsabile cu temporizarea releului. Daca cele 2 constante au valori mai mari
atunci temporizarea releului va fi la fel de mare.
A treia constanta stabileste nivelul de vibratii la care va reactiona
Arduino. Daca nivelul este depasit in bucla loop() atunci Arduino comanda
placa MOD-IO2.
O idee simpla (si ieftina !) de a comanda un anumit consumator de la
distanta, prin telefonul mobil.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Arduino UNO si matricea de led-uri inlantuibila 8x8

Matricea de led-uri 8x8 este o matrice inlantuibila capabila sa afiseze


siruri de caractere sau sa creeze diverse efecte luminoase. Poti conecta mai
multe matrici impreuna, obtinand astfel afisaje de dimensiuni oricat de mari.
La baza unei matrici se afla 2 circuite integrate 74HC595D. Acest circuite
se numesc registre de deplasare sau shift registers (termenul echivalent in
engleza). Un astfel registru de deplasare iti permite sa controlezi 8 iesiri
digitale utilizand doar 3 pini ale placii Arduino (pini corespunzatori intrarilor in
matrice Clock, Latch si Data). Iar partea cu adevarat frumoasa este ca si pentru
doua matrici ai nevoie tot de trei pini. Si pentru trei matrici la fel. Si tot asa,
poti controla sute de matrici folosind exact trei pini.
Arduino transmite pe pinul Data 8 biti (serial, unul dupa altul) cate unul
pentru fiecare dintre cele 8 iesiri. Delimitarea intre biti se realizeaza prin pinul
Clock, comandat tot de catre Arduino (citirea semnalului util se face atunci
cand semnalul Clock trece prin zero). Folosind pinul Latch valorile celor 8 biti
sunt trimisi pe iesire.

Cum conectez o matrice la placa Arduino ?

Conectarea unei matrici la placa Arduino se realizeaza foarte usor. Iti sunt
necesare 5 fire pe care le vei conecta ca in tabelul urmator (2 fire reprezinta
alimentarea matricei):

Arduino UNO 5V Matrice led-uri VCC


Arduino UNO GND Matrice led-uri GND
Arduino UNO Digital 7 Matrice led-uri SCK
Arduino UNO Digital 6 Matrice led-uri LATCH
Arduino UNO Digital 5 Matrice led-uri DATA

http://www.robofun.ro/forum
In continuare poti testa 2 exemple de programe. Primul program iti
creeaza un efect luminos in functie de valorile variabilelor numberToDisplay1
si numberToDisplay2.
Cel de-al doilea program iti afiseaza litera A dintr-un array de 8 octeti,
respectiv
byte message[8] = {63,127,136,136,136,136,127,63};

http://www.robofun.ro/forum
Primul exemplu de program.

int latchPin = 6;
int clockPin = 7;
int dataPin = 5;

void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}

void loop() {

byte numberToDisplay1 = 170;


byte numberToDisplay2 = 170;

digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay1);
shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay2);
digitalWrite(latchPin, HIGH);
delay(100);

delay(500);

numberToDisplay1 = 85;
numberToDisplay2 = 85;

digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay1);
shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay2);
digitalWrite(latchPin, HIGH);
delay(100);

delay(300);

http://www.robofun.ro/forum
Al doilea exemplu de program.

int latchPin = 6;
int clockPin = 7;
int dataPin = 5;
byte message[8] = {63,127,136,136,136,136,127,63};

void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}

void loop() {

int numberToDisplay1 = 1;
byte numberToDisplay2 = 64;

for (int contor=0; contor<=7; contor++) {

http://www.robofun.ro/forum
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, message[contor]);
shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay1);
digitalWrite(latchPin, HIGH);
numberToDisplay1 = numberToDisplay1 << 1;
delay(1);
}
}

http://www.robofun.ro/forum
Cum conectez mai multe matrici impreuna?

Fiecare matrice este prevazuta cu 2 conectori amplasati pe parti opuse


care faciliteaza inlantuirea matricelor. Conecteaza-le impreuna si alimenteaza
placa Arduino. Vei observa ca acelasi tipar care apare pe prima matrice se va
regasi si pe cea de-a doua.
Exact la fel vei face si pentru trei, patru, sau oricate matrici.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Raspberry PI si senzorul SHT11

Senzorul SHT11 ofera posibilitatea de a masura temperatura si umiditatea din mediul


inconjurator cu o precizie ridicata. Se conecteaza la placa Raspberry PI prin intermediul a 2 pini digitali.
Consumul senzorului este foarte redus, rezolutia temperaturii masurata de catre senzor este de 0.01 º C
si 0.03 % pentru umiditatea relativa. In cel mai rau caz temperatura poate avea o acuratete de ± 2 º C si
± 3.5 % pentru umiditate.
Senzorul se alimenteaza cu o tensiune cuprinsa intre 2.4 si 5.5V, comunica printr-un protocol
serial (Two-Wire Serial) si iesirea digitala este deja calibrata din fabrica.
In prima parte a tutorialului, vei conecta senzorul la placa Raspberry si vei afisa 3 valori
distincte in terminal. In cea de-a doua parte, vei conecta un shield LCD pe care vei afisa 2 din cele 3
valori.

Cum conectez senzorul ?

Senzorul se conecteaza foarte simplu la placa Raspberry PI. Foloseste tabelul si imaginea de mai
jos.
Raspberry PI 5V SHT11 VCC
Raspberry PI GND SHT11 GND
Raspberry PI pin 13 SHT11 pin DAT
Raspberry PI pin 7 SHT11 pin SCK

http://www.robofun.ro/forum
Asa arata senzorul conectat la placa Raspberry, conform tabelului.

Programul senzorului.

Exista un pachet Python special construit pentru acest senzor. Instaleaza pachetul in modul
urmator:

1. Logheaza-te prin SSH in consola Raspbian. Poti folosi Putty daca vrei sa te conectezi de
pe Windows sau ssh <ip> de pe Ubuntu.
2. Pachetul se afla aici: https://pypi.python.org/pypi/rpiSht1x si din documentatie el
depinde de un alt modul.
3. Descarca modulul prin comanda:

http://www.robofun.ro/forum
sudo wget
https://pypi.python.org/packages/source/R/RPi.GPIO/RPi.GPIO-
0.4.1a.tar.gz

4. Dupa ce l-ai descarcat, acum il dezarhivezi prin comanda:

sudo tar -xvf Rpi.GPIO-0.4.1a.tar.gz

5. Schima locatia in noul fisier:

cd Rpi.GPIO-0.4.1a

6. Instaleaza modulul prin comanda:

sudo python setup.py install

http://www.robofun.ro/forum
7. Pentru pachetul senzorului vei proceda la fel dar mai intai trebuie sa iesi din fisierul
actual:

cd ..

sudo wget
https://pypi.python.org/packages/source/r/rpiSht1x/rpiSht1x-
1.2.tar.gz

8. Dezarhiveaza pachetul:

sudo tar -xvf rpiSht1x-1.2.tar.gz

9. Schimba locatia:

cd rpiSht1x-1.2

10. Instaleaza pachetul prin comanda:

sudo python setup.py install

11. Codul sursa il vei scrie in nano dar mai intai schimba locatia:

cd ..

sudo nano senzorSHT11.py

12. Copiaza in nano codul sursa:

http://www.robofun.ro/forum
from sht1x.Sht1x import Sht1x as SHT1x
dataPin = 13
clkPin = 7
sht1x = SHT1x(dataPin, clkPin, SHT1x.GPIO_BOARD)

temperature = sht1x.read_temperature_C()
humidity = sht1x.read_humidity()
dewPoint = sht1x.calculate_dew_point(temperature, humidity)

print("Temperature: {} Humidity: {} Dew Point:


{}".format(temperature, humidity, dewPoint))

13. Salveaza-l cu CTRL X si Y si executa-l cu:

sudo python senzorSHT11.py

14. Daca vrei sa obtii citiri la fiecare 5 secunde atunci modifica fisierul py:

import time
from sht1x.Sht1x import Sht1x as SHT1x
dataPin = 13
clkPin = 7
sht1x = SHT1x(dataPin, clkPin, SHT1x.GPIO_BOARD)

while 1:
temperature = sht1x.read_temperature_C()
humidity = sht1x.read_humidity()
dewPoint = sht1x.calculate_dew_point(temperature, humidity)
print("Temperature: {} Humidity: {} Dew Point:
{}".format(temperature, humidity, dewPoint))
time.sleep(5)

http://www.robofun.ro/forum
Cum afisez temperatura si umiditatea pe un LCD?

Daca vrei sa afisezi temperatura si umiditatea pe un LCD, atunci iti propun shield-ul LCD 16x2.
Exista 2 tipuri de shield: primul tip se conecteaza la Raspberry PI prin cablu cobbler iar cel de-al doilea
tip se infige direct in portul GPIO, fara nici un alt cablu.
Placa expune in acelasi timp si toti pinii GPIO ai Raspberry PI (conectorul 2X13, nepopulat, de
langa LCD). Daca vrei sa ai acces la orice pin al portului GPIO dar in acelasi timp sa folosesti si LCD-
ul, atunci este necesara lipirea conectorului mama 2x13.
In tutorialul de fata este necesara lipirea acestui conector, altfel nu vei putea conecta senzorul
SHT11.

Cum procedez?

1. Lipeste bareta mama 2x13 pe shield. Daca vrei sa sari peste aceasta operatiune, atunci la
achizitionarea shield-ului opteaza pentru bareta lipita.
2. Infige shield-ul in portul placii Raspberry PI.
3. Conecteaza senzorul SHT11, prin fire, urmand acelasi tabel de mai sus.
4. Copiaza codul listat mai jos si executa-l.

http://www.robofun.ro/forum
Cum arata shield-ul si senzorul conectat ?

http://www.robofun.ro/forum
import RPi.GPIO as GPIO
from sht1x.Sht1x import Sht1x as SHT1x
import time

LCD_RS = 22
LCD_E = 18
LCD_D4 = 16
LCD_D5 = 11
LCD_D6 = 12
LCD_D7 = 15
LED_ON = 15

LCD_WIDTH = 16
LCD_CHR = True
LCD_CMD = False

LCD_LINE_1 = 0x80
LCD_LINE_2 = 0xC0

E_PULSE = 0.00005
E_DELAY = 0.00005

dataPin = 13
clkPin = 7

def main():

lcd_init()
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string("ROBOFUN.RO",2)
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string("Raspberry PI",2)
time.sleep(5)
while 1:
sht1x = SHT1x(dataPin, clkPin, SHT1x.GPIO_BOARD)
temperature = sht1x.read_temperature_C()
humidity = sht1x.read_humidity()
dewPoint = sht1x.calculate_dew_point(temperature, humidity)

print("Temperatura: {} Umiditate: {} Punct de roua:


{}".format(temperature, humidity, dewPoint))

textLCDOne = str("%.1f" % temperature)


textLCDOne = "Temperatura:" + textLCDOne
textLCDTwo = str("%.2f" % humidity)
textLCDTwo = "Umiditate: " + textLCDTwo

lcd_init()

lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(textLCDOne,1)
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(textLCDTwo,1)

http://www.robofun.ro/forum
def lcd_init():
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LCD_E, GPIO.OUT)
GPIO.setup(LCD_RS, GPIO.OUT)
GPIO.setup(LCD_D4, GPIO.OUT)
GPIO.setup(LCD_D5, GPIO.OUT)
GPIO.setup(LCD_D6, GPIO.OUT)
GPIO.setup(LCD_D7, GPIO.OUT)
GPIO.setup(LED_ON, GPIO.OUT)

lcd_byte(0x33,LCD_CMD)
lcd_byte(0x32,LCD_CMD)
lcd_byte(0x28,LCD_CMD)
lcd_byte(0x0C,LCD_CMD)
lcd_byte(0x06,LCD_CMD)
lcd_byte(0x01,LCD_CMD)

def lcd_string(message,style):
# style=1 Left justified
# style=2 Centred
# style=3 Right justified

if style==1:
message = message.ljust(LCD_WIDTH," ")
elif style==2:
message = message.center(LCD_WIDTH," ")
elif style==3:
message = message.rjust(LCD_WIDTH," ")

for i in range(LCD_WIDTH):
lcd_byte(ord(message[i]),LCD_CHR)

def lcd_byte(bits, mode):


# Send byte to data pins
# bits = data
# mode = True for character
# False for command

GPIO.output(LCD_RS, mode) # RS

# High bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x10==0x10:
GPIO.output(LCD_D4, True)
if bits&0x20==0x20:
GPIO.output(LCD_D5, True)
if bits&0x40==0x40:
GPIO.output(LCD_D6, True)
if bits&0x80==0x80:

http://www.robofun.ro/forum
GPIO.output(LCD_D7, True)

# Toggle 'Enable' pin


time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)

# Low bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x01==0x01:
GPIO.output(LCD_D4, True)
if bits&0x02==0x02:
GPIO.output(LCD_D5, True)
if bits&0x04==0x04:
GPIO.output(LCD_D6, True)
if bits&0x08==0x08:
GPIO.output(LCD_D7, True)

# Toggle 'Enable' pin


time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)

if __name__ == '__main__':
main()

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
RaspberryPI Wireless-Hotspot

Un hotspot este un punct de acces wireless care iti ofera internet pe


tableta, smartphone, laptop sau calculator. Sunt deseori prezente in cafenele,
supermarket-uri sau restaurante. Deseori sunt libere dar unele sunt si private.
Daca sunt private inseamna ca sunt limitate doar unui anumit grup de
utilizatori.
In acest tutorial vei configura placa Raspberry PI sa se comporte ca un
hotspot si sa accepte mai multe dispozitive ca cele enumerate mai sus iar
accesul la internet se va realiza numai printr-o singura conexiune la internet.
Vei avea nevoie de urmatoarele componente:

• Raspberry PI (cu sistemul de operare Raspbian)


• Stick WI-PI.
• Sursa de alimentare (5V).
• Router cu conexiune la Internet.
• Cablu Ethernet straight-through.

http://www.robofun.ro/forum
Cum functioneaza?

Placa Raspberry PI se va comporta ca un hotspot acceptand dispozitivele


prin stick-ul Wi-PI. Conexiunea la Internet se va realiza prin placa de retea a
placii. Configuratia pe care o vei aplica in continuare va realiza o punte intre
placa de retea si stick-ul Wi-PI.
Tutorialul nu acopera si partea de realizare a setarilor in router. Motivul
este ca routerele difera de la model la model. In orice caz, ar trebui sa ai deja o
conexiune la Internet activa, adica un cablu conectat la portul Internet sau
WAN al routerului. In mod normal Raspberry PI este configurat sa-si aloce IP-ul
automat din router prin server-ul DHCP.
Primul pas este sa conectezi totul:
• Mai intai conecteaza cablul ethernet intre router si placa
Raspberry PI.
• Conecteaza stick-ul Wi-PI intr-unul din cele 2 porturi USB.
• Conecteaza sursa de alimentare si asigura-te ca Raspberry PI a
pornit fara nici o problema adica toate led-urile incep sa se aprinda intermitent.
Conecteaza-te prin SSH la placa Raspberry PI. IP-ul placii il poti afla din
tabela routerului sau cu un monitor HDMI. Mai simplu este din router si arata
asa:

• Deschide utilitarul Putty, tasteaza IP-ul, portul 22 si OK.


• Te-ai logat si ai ajuns in terminal. Instaleaza urmatoarele programe:

sudo apt-get install hostapd udhcpd

• Configureaza DHCP-ul placii. Deschide cu nano fisierul


/etc/udhcpd.conf si configureaza urmatoarele linii ca mai jos:

http://www.robofun.ro/forum
sudo nano /etc/udhcpd.conf

start 192.168.42.2
end 192.168.42.20
interface wlan0
remaining yes
opt dns 8.8.8.8 4.2.2.2
opt subnet 255.255.255.0
opt router 192.168.42.1
opt lease 864000

• Deschide fisierul /etc/default/udhcpd si pune un # in fata liniei:


DHCPD_ENABLED="no"

• Acum ii vei da un IP static stick-ului Wi-PI prin comanda:


sudo ifconfig wlan0 192.168.42.1

• Pentru ca Raspberry PI sa realizeze alocarea IP-ului automat la boot


atunci deschide fisierul /etc/network/interfaces :

sudo nano /etc/network/interfaces

• Cauta linia iface wlan0 inet dhcp sau iface wlan0 inet manual
si schimba cu urmatoarele linii:

iface wlan0 inet static


address 192.168.42.1
netmask 255.255.255.0

• Este posibil ca linia iface wlan0 inet dhcp sa nu apara. In cazul


asta adauga liniile de mai sus la capatul fisierului.

http://www.robofun.ro/forum
• Tot in acest fisier vei pune un # in fata urmatoarelor linii:

allow-hotplug wlan0
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
iface default inet dhcp

• Acum este momentul sa configurezi setarile retelei Wi-FI. Poti opta


pentru o retea securizata cu parola sau o retea publica. O retea securizata este
recomandata pentru ca o poti tine sub control si este protejata de atacuri. Poti
opta pentru o retea publica dar nu vei avea aceeasi siguranta.
• Deschide fisierul /etc/hostapd/hostapd.conf

sudo nano /etc/hostapd/hostapd.conf

• Pentru o retea securizata adauga urmatoarele setari:

interface=wlan0
driver=nl80211
ssid= <Numele routerului>
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase= <Parola>
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

• Schimba liniile ssid, channel si wpa_passphrase dupa cum doresti.

http://www.robofun.ro/forum
SSID seteaza numele hotspot-ului care este vizibil atunci cand vrei sa te
conectezi. Channel stabileste frecventa de lucru iar wpa_passphrase reprezinta
parola.
• Pentru o retea nesecurizata adauga urmatoarele setari:

interface=wlan0
ssid= <Numele routerului>
hw_mode=g
channel=6
auth_algs=1
wmm_enabled=0

• In aceeasi situatie si pentru o retea nesecurizata, alege dupa cum


doresti numele routerului si canalul.

• Deschide fisierul /etc/default/hostapd si schimba linia


#DAEMON_CONF="" in
DAEMON_CONF="/etc/hostapd/hostapd.conf"

• Configureaza serviciul NAT. Deschide fisierul /etc/sysctl.conf si


adauga la sfarsit linia

http://www.robofun.ro/forum
net.ipv4.ip_forward=1

• Executa urmatoarele comenzi:

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state


RELATED,ESTABLISHED -j ACCEPT

sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT

• Ca sa nu tastezi la fiecare reboot liniile de mai sus, tasteaza


comanda:

sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"

• Deschide din nou fisierul /etc/network/interfaces si adauga la


sfarsit linia:

up iptables-restore < /etc/iptables.ipv4.nat

• Ultimul pas! Porneste serviciile hotspot-ului si seteaza-le sa


porneasca automat la boot:

http://www.robofun.ro/forum
sudo service hostapd start

sudo service udhcpd start

sudo update-rc.d hostapd enable

sudo update-rc.d udhcpd enable

In acest moment Raspberry PI a devenit un hotspot si poate fi accesat


foarte usor.
Windows 7:

Smartphone:

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Raspberry PI si senzorul BMP085 Blue Edition

BMP085 Blue Edition este un senzor de inalta precizie pentru presiune


atmosferica si temperatura. Senzorul poate masura de la 300 la 1100 hPa cu o
precizie absoluta de pana la 0.03 hPa. Senzorul se alimenteaza cu o tensiune
cuprinsa intre 1.8 si 3.6V si se conecteaza direct la portul I2C al placii
Raspberry PI.
In acest tutorial vei programa placa Raspberry PI sa afiseze pe un shield
LCD 16x2 temperatura si presiunea atmosferica.
Vei avea nevoie de urmatoarele componente:

• O placa Raspberry PI.


• Un shield LCD 16x2 pentru Raspberry PI.
• Un senzor BMP085 Blue Edition.
• Fire pentru conexiuni.
• O sursa de alimentare pentru Raspberry (5V).

Cum conectez shield-ul LCD si senzorul BMP085 ?

1. Conecteaza shield-ul la portul GPIO al placii Raspberry PI. Shield-ul


poate fi infipt direct in portul GPIO sau il poti conecta prin
intermediul panglicii de tip cobbler.

2. Asigura-te ca bareta mama 2x13 este lipita pe shield, altfel nu poti


conecta senzorul de temperatura si presiune atmosferica. La
achizitionarea shield-ului poti opta pentru shield cu bareta lipita.

http://www.robofun.ro/forum
3. Conecteaza senzorul BMP085 conform tabelului urmator:

Raspberry PI 3.3V BMP085 pin VCC


Raspberry PI GND BMP085 pin GND
Raspberry PI pin SDA BMP085 pin SDA
Raspberry PI pin SCL BMP085 pin SCL

4. Foloseste aceasta schema a portului GPIO ca referinta:

http://www.robofun.ro/forum
Configurarea portului I2C.

Inainte de a instala programul este necesara configurarea portului I2C al


Raspberry PI.

1. Deschide urmatorul fisier prin comanda:

sudo nano /etc/modules

2. Adauga in acest fisier urmatoarele linii:

i2c-bcm2708

i2c-dev

http://www.robofun.ro/forum
3. Salveaza fisierul cu CTRL X si Y si restarteaza Raspberry PI prin:

reboot

4. Dupa restartare executa urmatoarele 2 comenzi:

sudo apt-get install python-smbus

sudo apt-get install i2c-tools

5. Deschide urmatorul fisier prin comanda:

sudo nano /etc/modprobe.d/raspi-blacklist.conf

6. Comenteaza cele 2 linii ca in imagine:

blacklist spi-bcm2708

blacklist i2c-bcm2708

http://www.robofun.ro/forum
7. Asigura-te ca senzorul este detectat corect. Tasteaza urmatoarea
comanda:

sudo i2cdetect -y 1

8. Senzorul este detectat corect la adresa 0x77.

Programul senzorului.

Exista o librarie special construita pentru acest senzor. Instalarea este


structurata pe urmatorii pasi:

1. In primul pas vei creea un fisier. Acolo se vor regasi libraria si


programul senzorului.

sudo mkdir senzor_bmp085

2. Executa urmatoarea comanda:

http://www.robofun.ro/forum
sudo git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-
Python-Code.git

3. Schimba locatia:

cd Adafruit-Raspberry-Pi-Python-Code

cd Adafruit_BMP085

4. Executa urmatoarea comanda:

http://www.robofun.ro/forum
sudo python Adafruit_BMP085_example.py

5. Acest program citeste datele senzorului si le afiseaza in terminal.


Urmeaza sa modifici acest program pentru ca datele sa fie afisate
pe shield-ul LCD.

Cum afisez temperatura si presiunea pe un LCD?

In continuare este listat codul sursa modificat. Copiaza-l si executa-l cu


python.

#!/usr/bin/python
from Adafruit_BMP085 import BMP085
import RPi.GPIO as GPIO
import time

LCD_RS = 22
LCD_E = 18
LCD_D4 = 16
LCD_D5 = 11
LCD_D6 = 12
LCD_D7 = 15

LCD_WIDTH = 16
LCD_CHR = True
LCD_CMD = False

LCD_LINE_1 = 0x80
LCD_LINE_2 = 0xC0

E_PULSE = 0.00005
E_DELAY = 0.00005

http://www.robofun.ro/forum
#
===================================================================
========
# Example Code
#
===================================================================
========

# Initialise the BMP085 and use STANDARD mode (default value)


# bmp = BMP085(0x77, debug=True)
def main():
lcd_init()
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string("ROBOFUN.RO",2)
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string("Raspberry PI",2)
time.sleep(5)

bmp = BMP085(0x77)

# To specify a different operating mode, uncomment one of the


following:
# bmp = BMP085(0x77, 0) # ULTRALOWPOWER Mode
# bmp = BMP085(0x77, 1) # STANDARD Mode
# bmp = BMP085(0x77, 2) # HIRES Mode
# bmp = BMP085(0x77, 3) # ULTRAHIRES Mode
while 1:
temp = bmp.readTemperature()
pressure = bmp.readPressure()
altitude = bmp.readAltitude()

http://www.robofun.ro/forum
print "Temperatura: %.2f C" % temp
print "Presiune: %.2f hPa" % (pressure / 100.0)
print "Altitudine: %.2f" % altitude

textLCDOne = "Temp:%s C" % temp


textLCDTwo = "Pres:%s hPa" % (pressure / 100.0)

lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(textLCDOne,1)
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(textLCDTwo,1)
time.sleep(1)

def lcd_init():
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LCD_E, GPIO.OUT)
GPIO.setup(LCD_RS, GPIO.OUT)
GPIO.setup(LCD_D4, GPIO.OUT)
GPIO.setup(LCD_D5, GPIO.OUT)
GPIO.setup(LCD_D6, GPIO.OUT)
GPIO.setup(LCD_D7, GPIO.OUT)

lcd_byte(0x33,LCD_CMD)
lcd_byte(0x32,LCD_CMD)
lcd_byte(0x28,LCD_CMD)
lcd_byte(0x0C,LCD_CMD)
lcd_byte(0x06,LCD_CMD)
lcd_byte(0x01,LCD_CMD)

def lcd_string(message,style):
# style=1 Left justified
# style=2 Centred
# style=3 Right justified

if style==1:
message = message.ljust(LCD_WIDTH," ")
elif style==2:
message = message.center(LCD_WIDTH," ")
elif style==3:
message = message.rjust(LCD_WIDTH," ")

http://www.robofun.ro/forum
for i in range(LCD_WIDTH):
lcd_byte(ord(message[i]),LCD_CHR)

def lcd_byte(bits, mode):


# Send byte to data pins
# bits = data
# mode = True for character
# False for command

GPIO.output(LCD_RS, mode) # RS

# High bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x10==0x10:
GPIO.output(LCD_D4, True)
if bits&0x20==0x20:
GPIO.output(LCD_D5, True)
if bits&0x40==0x40:
GPIO.output(LCD_D6, True)
if bits&0x80==0x80:
GPIO.output(LCD_D7, True)

# Toggle 'Enable' pin


time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)

# Low bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x01==0x01:
GPIO.output(LCD_D4, True)
if bits&0x02==0x02:
GPIO.output(LCD_D5, True)
if bits&0x04==0x04:
GPIO.output(LCD_D6, True)
if bits&0x08==0x08:
GPIO.output(LCD_D7, True)

http://www.robofun.ro/forum
# Toggle 'Enable' pin
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)

if __name__ == '__main__':
main()

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Raspberry PI si ULN2803 shield

Shield-ul ULN2803 se conecteaza impreuna cu placa Raspberry PI iar rolul lui este sa iti
permita controlul unor sarcini de putere mai mare, sarcini pe care pinii GPIO nu le poate suporta.
Spre exemplu, poti controla motoare de putere mica (consumul sa nu depaseasca 0.5A/motor) sau
poti controla bobinele unor relee.
Shield-ul iti permite sa comanzi ON/OFF pana la 8 sarcini independent. Consumul general
la nivelul placii este de 500mA (toti pinii insumati).

Cum se utilizeaza shield-ul ?

Pentru a controla o sarcina folosind shield-ul ULN2803, va trebui sa conectezi sarcina intre
unul dintre pinii marcati cu 5V (ai la dispozitie 8 pini) si unul dintre pinii de deasupra (marcat cu
„G“ urmat de un numar). Pinul marcat cu „G“ functioneaza ca un intrerupator conectat intre sarcina
ta si GND. Atunci cand din codul sursa activezi pinul GPIO corespunzator (vezi codul sursa de mai
jos), intrerupatorul se inchide si permite trecerea curentului, inchizand circuitul si alimentand
sarcina conectata. Atunci cand pinul GPIO este in LOW, intrerupatorul este deschis si curentul nu
trece prin sarcina.
Shield-ul expune in acelasi timp si toti pinii GPIO ai placii Raspberry PI, in cazul in care
vrei sa conectezi si alte componente la placa (senzori, led-uri sau alte placi de extensie).
Ce vei face in tutorialul de fata:

1. Conecteaza shield-ul la placa Raspberry PI.

2. Ca sa vedem cum functioneaza shield-ul si programul de mai jos, conecteaza 3


consumatori la pinii shield-ului. Poti conecta motoare, relee, led-uri de putere. In acest tutorial s-au
conectat 3 led-uri brick la pinii urmatori:

Led Galben Pin IN Shield ULN2803 5V


Led Rosu Pin IN Shield ULN2803 5V
Led Verde Pin IN Sield ULN2803 5V
Led Galben Pin GND Shield ULN2803 G04
Led Rosu Pin GND Shield ULN2803 G25
Led Verde Pin GND Shield ULN2803 G24

http://www.robofun.ro/forum
Vei obtine urmatoarea imagine:

3. Conecteaza placa Raspberry PI la retea si logheaza-te prin SSH.

4. Creeaza un director nou si un fisier cu urmatoarele 2 comenzi:

mkdir shield_uln2803
sudo nano shield.py

5. Copiaza codul sursa de mai jos. Salveaza-l cu CTRL X si Y.

http://www.robofun.ro/forum
6. Executa programul cu urmatoarele comenzi:

sudo python shield.py 4 1


sudo python shield.py 25 1
sudo python shield.py 24 1

sudo python shield.py 4 0


sudo python shield.py 25 0
sudo python shield.py 24 0

Cum functioneaza programul ?

Atunci cand apelezi programul, trebuie sa ii dai 2 argumente. Primul argument este pinul
GPIO care poate fi 4, 24 sau 25 iar cel de-al doilea argument este starea pinului, care poate fi „1“
sau „0“, adica pentru cele 3 led-uri „1“ inseamna aprins iar „0“ inseamna stins.

http://www.robofun.ro/forum
#!/usr/bin/env python
import sys
import time
import os
import RPi.GPIO as GPIO

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(int(sys.argv[1]), GPIO.OUT)
GPIO.output(int(sys.argv[1]), int(sys.argv[2]))
print "Starea pinului " + sys.argv[1] + " a fost setata pe " +
sys.argv[2] + " logic"

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Raspberry PI si LCD Shield 20x4

Shield-ul LCD 20x4 functioneaza perfect impreuna cu placa Raspberry PI.


Shield-ul se poate conecta direct la portul placii sau prin intermediul unei
panglici cobbler. Placa expune in acelasi timp si toti pinii GPIO ai Raspberry PI
(conectorul 2X13, nepopulat, de langa LCD). In acest mod, poti avea acces la
oricare pin GPIO doresti si in acelasi timp poti folosi si LCD-ul.
In acest tutorial vei utiliza shield-ul LCD 20x4 pentru a afisa data/ora,
adresa IP a placii, temperatura si nivelul de utilizare al procesorului. Pentru a
scoate in evidenta utilitatea placii Raspberry PI, programul sintetizeaza vocal
parametrii de mai sus.
Pentru acest tutorial ai nevoie de urmatoarele componente:

• O placa Raspberry PI.


• Un shield LCD 20x4.
• O boxa audio cu alimentare prin USB.
• O sursa de alimentare pentru Raspberry PI (5V).

Cum procedez ?

1. Conecteaza shield-ul LCD la placa Raspberry PI.


2. Conecteaza mufa USB a boxei la unul din porturile USB ale placii.
3. Conecteaza mufa jack a boxei la iesirea audio a placii Raspberry.
4. Alimenteaza Raspberry PI si logheaza-te la placa prin Putty sau
orice alt utilitar doresti.

Pachetul Python RPi.GPIO 0.4.1a.

Inainte de a executa programul listat mai jos trebuie sa instalezi pachetul


python RPi.GPIO 0.4.1a. Programul shield-ului depinde de acest pachet.

1. Descarca modulul prin comanda:

http://www.robofun.ro/forum
sudo wget
https://pypi.python.org/packages/source/R/RPi.GPIO/RPi.GPIO-
0.4.1a.tar.gz

2. Dezarhiveaza-l prin comanda:

sudo tar -xvf Rpi.GPIO-0.4.1a.tar.gz

3. Schimba locatia in noul fisier:

cd Rpi.GPIO-0.4.1a

4. Urmeaza sa il instalezi prin comanda:

sudo python setup.py install

Programul shield-ului.

1. Creeaza un fisier cu numele lcd20x4.

sudo mkdir lcd20x4

2. Deschide editorul nano si copiaza codul sursa listat mai jos. Dupa
ce l-ai copiat, salveaza-l cu CTRL X si Y:

sudo nano lcd.py

3. Executa programul cu comanda:

sudo python lcd.py

4. Pe afisaj vei obtine urmatoarele linii, ca in imaginile de mai jos, iar


sintetizorul va reda vocal parametrii:

http://www.robofun.ro/forum
http://www.robofun.ro/forum
import os
import subprocess
import RPi.GPIO as GPIO
import time
from datetime import datetime
import socket
import fcntl
import struct

LCD_RS = 25
LCD_E = 24
LCD_D4 = 23
LCD_D5 = 17
LCD_D6 = 18
LCD_D7 = 22
LED_ON = 15

http://www.robofun.ro/forum
LCD_WIDTH = 20
LCD_CHR = True
LCD_CMD = False

LCD_LINE_1 = 0x80
LCD_LINE_2 = 0xC0
LCD_LINE_3 = 0x94
LCD_LINE_4 = 0xD4

E_PULSE = 0.00005
E_DELAY = 0.00005

def main():

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(LCD_E, GPIO.OUT)
GPIO.setup(LCD_RS, GPIO.OUT)
GPIO.setup(LCD_D4, GPIO.OUT)
GPIO.setup(LCD_D5, GPIO.OUT)
GPIO.setup(LCD_D6, GPIO.OUT)
GPIO.setup(LCD_D7, GPIO.OUT)
GPIO.setup(LED_ON, GPIO.OUT)

lcd_init()

while 1:
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string("ROBOFUN.RO",2)
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string("Raspberry PI",2)
lcd_byte(LCD_LINE_3, LCD_CMD)
lcd_string("LCD Shield", 2)
lcd_byte(LCD_LINE_4, LCD_CMD)
lcd_string("20x4", 2)
os.system('espeak -v en "{0}"'.format('www.robofun.ro
introducing'))
os.system('espeak -v en "{0}"'.format('the new Raspberry PI'))
os.system('espeak -v en "{0}"'.format('20 characters by 4 lines
LCD Shield'))

http://www.robofun.ro/forum
for i in range(0,50):
lcd_byte(LCD_LINE_1, LCD_CMD)
textTime = datetime.now().strftime('%b %d %H:%M')
lcd_string(textTime, 2)

lcd_byte(LCD_LINE_2, LCD_CMD)
textIP = get_ip_add('eth0')
lcd_string(textIP, 2)

lcd_byte(LCD_LINE_3, LCD_CMD)
textTemp = 'CPU Temp %s C' % (get_cpu_temp())
lcd_string(textTemp, 2)

lcd_byte(LCD_LINE_4, LCD_CMD)
textCpuUse = 'CPU Use %s' % (get_cpu_use()) + '%'
lcd_string(textCpuUse, 2)

os.system('espeak -v en "{0}"'.format('The temperature is %s


degrees Celsius' % (get_cpu_temp())))
os.system('espeak -v en "{0}"'.format('IP adress is %s' %
textIP))
os.system('espeak -v en "{0}"'.format('The procesor is being
used at %s percent' % get_cpu_use()))
os.system('espeak -v en "{0}"'.format('The time is %s' %
textTime))

time.sleep(0.2)

http://www.robofun.ro/forum
def get_cpu_use():
return(str(os.popen("top -n1 | awk '/Cpu\(s\):/ {print
$2}'").readline().strip()))

def get_cpu_temp():
res = os.popen('vcgencmd measure_temp').readline()
return (res.replace("temp="," ").replace("'C\n",""))

def get_ip_add(ifname):
s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return
socket.inet_ntoa(fcntl.ioctl(s.fileno(),0x8915,struct.pack('256s',
ifname[:15]))[20:24])

def lcd_init():
lcd_byte(0x33,LCD_CMD)
lcd_byte(0x32,LCD_CMD)
lcd_byte(0x28,LCD_CMD)
lcd_byte(0x0C,LCD_CMD)
lcd_byte(0x06,LCD_CMD)
lcd_byte(0x01,LCD_CMD)

def lcd_string(message,style):
if style==1:
message = message.ljust(LCD_WIDTH," ")
elif style==2:
message = message.center(LCD_WIDTH," ")
elif style==3:
message = message.rjust(LCD_WIDTH," ")

for i in range(LCD_WIDTH):
lcd_byte(ord(message[i]),LCD_CHR)

http://www.robofun.ro/forum
def lcd_byte(bits, mode):
GPIO.output(LCD_RS, mode)
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x10==0x10:
GPIO.output(LCD_D4, True)
if bits&0x20==0x20:
GPIO.output(LCD_D5, True)
if bits&0x40==0x40:
GPIO.output(LCD_D6, True)
if bits&0x80==0x80:
GPIO.output(LCD_D7, True)

time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x01==0x01:
GPIO.output(LCD_D4, True)
if bits&0x02==0x02:
GPIO.output(LCD_D5, True)
if bits&0x04==0x04:
GPIO.output(LCD_D6, True)
if bits&0x08==0x08:
GPIO.output(LCD_D7, True)

time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)

if __name__ == '__main__':
main()

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Priza telecomandata cu Raspberry PI

Acest tip de priza iti permite sa pornesti/opresti, de la distanta, diversi consumatori.


Comanda ON/OFF a prizei se realizeaza prin semnalele radio emise de o telecomanda speciala
conectata la placa Raspberry PI.
Emitatorul arata ca in imaginea de mai jos si se conecteaza la placa prin 3 pini. Modul cum
se conecteaza la Raspberry PI este explicat mai jos.

Fiecare priza are o adresa unica ce poate fi setata prin 10 microswich-uri. In acest mod poti
controla pana la 1024 de prize utilizand doar o singura telecomanda. Priza arata ca in imaginea de
mai jos iar accesul la microswitch-uri se face desfacand surubul ce tine capacul fixat ferm.
Cele 10 microswitch-uri sunt marcate cu 1, 2, 3, 4, 5, respectiv A, B, C, D, E. Iti recomand
sa nu modifici configuratia actuala a producatorului, cel putin pentru inceput deoarece ele sunt
configurate cu adrese unice. Este totusi important sa deschizi capacul si sa observi configuratia
switch-urilor pentru ca ea va fi necesara in programul care va fi executat pe placa Raspberry.

http://www.robofun.ro/forum
Pentru acest tutorial vei avea nevoie de urmatoarele:

• O placa Raspberry PI.


• Una sau mai multe prize telecomandate - http://www.robofun.ro/set-trei-prize-
telecomandate-arduino.
• Telecomanda speciala (inclusa in pachetul de prize).
• Fire pentru conexiuni.

Cum functioneaza ?

Fiecare priza are o adresa unica si poate fi comandata ON/OFF wireless. Comanda se
realizeaza direct dintr-un program care se executa pe placa Raspberry PI. Emitatorul se conecteaza
la placa astfel:

Pin Vcc telecomanda Raspberry PI 5V


Pin Gnd telecomanda Raspberry PI Gnd
Pin OUT telecomanda Raspberry PI GPIO 22

http://www.robofun.ro/forum
Ca referinta, foloseste schema portului GPIO de mai jos.

Dupa ce ai realizat toate cele 3 conexiuni, vei obtine imaginea de mai jos.

http://www.robofun.ro/forum
Pasii necesari pentru a comanda o priza.

1. Instaleaza git-core cu comanda (daca nu e deja instalat):

sudo apt-get install git-core

2. Realizeaza un update si upgrade al sistemului de operare:

sudo apt-get update && sudo apt-get upgrade

3. Instaleaza wiringPi prin urmatoarele comenzi:

sudo git clone git://git.drogon.net/wiringPi

cd wiringPi

sudo git pull origin

sudo ./build

4. Descarca RCSwitch:

sudo git clone https://github.com/r10r/rcswitch-pi.git

5. Schimba locatia:

cd rcswitch-pi

http://www.robofun.ro/forum
6. Deschide fisierul send.cpp si modifica valoarea variabilei PIN conform cu imaginea
de mai jos:

sudo nano send.cpp

Daca pinul OUT al telecomenzii se afla conectata la pinul BCM GPIO 22, atunci valoarea
variabilei PIN va fi 3, conform tabelului de mai sus.

http://www.robofun.ro/forum
7. Compileaza aplicatia ruland:

sudo make

8. Deschide capacul prizei si modifica starea microswitch-urilor astfel:

Switch-urile marcate cu 1, 2, 3, 4, 5 si A vor fi pe ON iar restul switch-urilor vor fi pe OFF.

9. Executa urmatoarea comanda:

• pentru a porni priza:

sudo ./send 11111 1 1

• pentru a opri priza:

http://www.robofun.ro/forum
sudo ./send 11111 1 0

Unde: primul parametru „11111“ reprezinta starea switch-urilor 1-5, al doilea parametru „1“
reprezinta pozitia switch-ului din grupul A-E, iar ultimul parametru „1“ sau „0“ reprezinta starea
prizei – inchis sau deschis.
Un alt exemplu: Daca vrei sa controlezi o alta priza, atunci seteaza switch-urile 1-5 si B pe
pozitia ON. Restul switch-urilor vor sta pe pozitia OFF.

sudo ./send 11111 2 1

sau

sudo ./send 11111 2 0

Dupa cum observi, poti comanda un numar foarte mare de prize.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
RaspberryPI si ADXL345

ADXL345 este un accelerometru de dimensiuni mici, are un consum redus de energie iar
masuratorile efectuate pe cele 3 axe au o rezolutie mare (13 biti). Poate masura pana la ± 16g, iar
datele sunt reprezentate in format digital, la alegere, prin interfata SPI sau I2C.
ADXL345 este foarte potrivit pentru masuratori ale acceleratiei statice a gravitatiei in
aplicatii care sesizeaza bascularea, dar si acceleratia dinamica rezultata din miscare sau socuri.
Accelerometrul are o rezolutie mare (4 mg/LSB) si permite masurarea schimbarilor de inclinatie
mai mici de 1,0°.
Mai multe functii de sesizare speciale sunt furnizate. Sesizarea activitatii si inactivitatii
depisteaza prezenta sau lipsa miscarii si daca acceleratia pe oricare axa excede un nivel setat de
catre utilizator. Sesizarea batailor usoare depisteaza bataile simple sau duble. Sesizarea caderii
libere depisteaza daca senzorul se afla se afla in cadere. Aceste functii pot fi mapate pe unul din doi
pini de iesire de intrerupere. Un buffer first in, first out (FIFO) cu 32 de nivele integra poate fi
folosit pentru a stoca datele pentru a minimiza interventia procesorului cu care comunica senzorul.
Senzorul poate functiona si in moduri cu consum redus de energie.

http://www.robofun.ro/forum
In acest tutorial vei programa placa Raspberry PI sa afiseze pe un shield LCD 20x4
acceleratiile corespunzatoare celor 3 axe.
Vei avea nevoie de urmatoarele componente:

• O placa Raspberry PI.


• Un shield LCD 20x4 pentru Raspberry PI.
• Un senzor ADXL345.
• Fire pentru conexiuni.
• Breadboard.
• O sursa de alimentare pentru Raspberry PI (5V)

Cum conectez shield-ul LCD si senzorul ADXL345 ?

1. Conecteaza shield-ul la portul GPIO al placii Raspberry PI. Shield-ul poate fi infipt
direct in portul GPIO sau il poti conecta prin intermediul panglicii de tip cobbler.

2. Asigura-te ca bareta mama 2x13 este lipita pe shield, altfel nu poti conecta senzorul
ADXL345. La achizitionarea shield-ului poti opta pentru shield cu bareta lipita.

3. Conecteaza accelerometrul la placa Raspberry PI conform tabelului urmator:

Raspberry PI 3.3V ADXL345 VCC


Raspberry PI 3.3V ADXL345 CS
Raspberry PI GND ADXL345 GND
Raspberry PI GND ADXL345 SDO
Raspberry PI SDA ADXL345 SDA
Raspberry PI SCL ADXL345 SCL

4. Foloseste, ca referinta, schema portului GPIO si schema electronica de mai jos:

http://www.robofun.ro/forum
Dupa realizarea conexiunilor, vei obtine urmatoarea imagine.

http://www.robofun.ro/forum
Cum programez placuta Raspberry PI ?

Mai jos sunt listate 2 programe, dintre care, primul se executa cu Python si se ocupa cu
initializarea afisajului LCD si afisarea acceleratiilor pe fiecare rand iar cel de-al doilea program este
scris in limbajul C si se ocupa cu initializarea interfetei I2C a senzorului si citirea acceleratiilor din
el. In mod normal vei executa doar programul scris in C, deoarece acesta realizeaza apel automat
catre programul Python.
Codul sursa este listat mai jos si il poti copia cu copy/paste, dar inainte de asta sunt necesare
cateva configurari:

1. Deschide urmatorul fisier si asigurate ca ai cele 2 linii:

sudo nano /etc/modules

Liniile:

http://www.robofun.ro/forum
i2c-bcm2708

i2c-dev

2. Executa o restartare cu:

sudo reboot

3. Dupa restartare, executa cele 2 comenzi:

sudo apt-get install python-smbus

sudo apt-get install i2c-tools

4. Deschide fisierul cu urmatoarea comanda si asigura-te ca este prezent cate un # pe


fiecare linie:

sudo nano /etc/modprobe.d/raspi-blacklist.conf

5. Verifica daca senzorul este detectat corect prin comanda:

sudo i2cdetect -y 1

Comanda returneaza toate adresele detectate. Daca senzorul este detectat corect, atunci el va

http://www.robofun.ro/forum
raporta adresa 0x53.

6. Descarca si instaleaza pachetul python RPi.GPIO 0.4.1a. Programul Python depinde


de acest pachet.

sudo wget
https://pypi.python.org/packages/source/R/RPi.GPIO/RPi.GPIO-
0.4.1a.tar.gz

7. Dezarhiveaza-l prin comanda:

sudo tar -xvf Rpi.GPIO-0.4.1a.tar.gz

8. Schimba locatia in noul fisier:

cd Rpi.GPIO-0.4.1a

9. Executa instalarea:

sudo python setup.py install

Codul sursa ?

1. Creeaza un fisier cu editorul nano si copiaza codul Python. Inchide editorul si


salveaza-l cu CTRL X si Y.

sudo nano lcd.py

2. Creeaza un fisier cu acelasi editor si copiaza codul in limbajul C. Inchide editorul in


aceeasi maniera:

sudo nano readingADXL345.c

3. Compileaza programul C cu comanda:

gcc -o read_adxl readingADXL345.c

4. Dupa compilare vei obtine un executabil denumit read_adxl.

http://www.robofun.ro/forum
5. Porneste programul care citeste si afiseaza senzorul prin comanda:

./read_adxl

Vei obtine urmatoarele imagini:

http://www.robofun.ro/forum
Programul Python.

from datetime import datetime


import RPi.GPIO as GPIO
import time
import os
import subprocess
import sys

LCD_RS = 25
LCD_E = 24
LCD_D4 = 23
LCD_D5 = 17
LCD_D6 = 18
LCD_D7 = 22
LED_ON = 15

http://www.robofun.ro/forum
LCD_WIDTH = 20
LCD_CHR = True
LCD_CMD = False

LCD_LINE_1 = 0x80
LCD_LINE_2 = 0xC0
LCD_LINE_3 = 0x94
LCD_LINE_4 = 0xD4

E_PULSE = 0.00005
E_DELAY = 0.00005

def main():

textLineTwo = "ACCEL X: " + str(int(float(sys.argv[1])))


textLineThree = "ACCEL Y: " + str(int(float(sys.argv[2])))
textLineFour = "ACCEL Z: " + str(int(float(sys.argv[3])))

lcd_init()
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string("Rpi and ADXL345",2)
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(textLineTwo,1)
lcd_byte(LCD_LINE_3, LCD_CMD)
lcd_string(textLineThree,1)
lcd_byte(LCD_LINE_4, LCD_CMD)
lcd_string(textLineFour,1)

def lcd_init():
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(LCD_E, GPIO.OUT)
GPIO.setup(LCD_RS, GPIO.OUT)
GPIO.setup(LCD_D4, GPIO.OUT)
GPIO.setup(LCD_D5, GPIO.OUT)
GPIO.setup(LCD_D6, GPIO.OUT)
GPIO.setup(LCD_D7, GPIO.OUT)

lcd_byte(0x33,LCD_CMD)
lcd_byte(0x32,LCD_CMD)
lcd_byte(0x28,LCD_CMD)
lcd_byte(0x0C,LCD_CMD)
lcd_byte(0x06,LCD_CMD)
lcd_byte(0x01,LCD_CMD)

http://www.robofun.ro/forum
def lcd_string(message,style):
# style=1 Left justified
# style=2 Centred
# style=3 Right justified

if style==1:
message = message.ljust(LCD_WIDTH," ")
elif style==2:
message = message.center(LCD_WIDTH," ")
elif style==3:
message = message.rjust(LCD_WIDTH," ")

for i in range(LCD_WIDTH):
lcd_byte(ord(message[i]),LCD_CHR)

def lcd_byte(bits, mode):


# Send byte to data pins
# bits = data
# mode = True for character
# False for command

GPIO.output(LCD_RS, mode) # RS

# High bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x10==0x10:
GPIO.output(LCD_D4, True)
if bits&0x20==0x20:
GPIO.output(LCD_D5, True)
if bits&0x40==0x40:
GPIO.output(LCD_D6, True)
if bits&0x80==0x80:
GPIO.output(LCD_D7, True)

http://www.robofun.ro/forum
# Toggle 'Enable' pin
time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)

# Low bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x01==0x01:
GPIO.output(LCD_D4, True)
if bits&0x02==0x02:
GPIO.output(LCD_D5, True)
if bits&0x04==0x04:
GPIO.output(LCD_D6, True)
if bits&0x08==0x08:
GPIO.output(LCD_D7, True)

# Toggle 'Enable' pin


time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)

if __name__ == '__main__':
main()

Programul C.

http://www.robofun.ro/forum
// gcc -o read_adxl readingADXL345.c

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/i2c-dev.h>

#define ADXL345_I2C_ADDR 0x53

http://www.robofun.ro/forum
void selectDevice(int fd, int addr, char * name)
{
if (ioctl(fd, I2C_SLAVE, addr) < 0)
{
fprintf(stderr, "%s not present\n", name);
//exit(1);
}
}

void writeToDevice(int fd, int reg, int val)


{
char buf[2];
buf[0]=reg; buf[1]=val;
if (write(fd, buf, 2) != 2)
{
fprintf(stderr, "Can't write to ADXL345\n");
//exit(1);
}
}

int main(int argc, char **argv)


{
unsigned int range;
int count, b;
short x, y, z;
float xa, ya, za;
int fd;
unsigned char buf[16];
char str[80] = {};
char system_str[256] = {};

if ((fd = open("/dev/i2c-1", O_RDWR)) < 0)


{
// Open port for reading and writing
fprintf(stderr, "Failed to open i2c bus\n");
exit(1);
}
/* initialise ADXL345 */

selectDevice(fd, ADXL345_I2C_ADDR, "ADXL345");

writeToDevice(fd, 0x2d, 0);


writeToDevice(fd, 0x2d, 16);
writeToDevice(fd, 0x2d, 8);
writeToDevice(fd, 0x31, 0);
writeToDevice(fd, 0x31, 11);

while (1) {

http://www.robofun.ro/forum
/* select ADXL345 */

selectDevice(fd, ADXL345_I2C_ADDR, "ADXL345");

buf[0] = 0x32;
if ((write(fd, buf, 1)) != 1)
{
// Send the register to read from
fprintf(stderr, "Error writing to i2c slave\n");
//exit(1);
}
if (read(fd, buf, 6) != 6)
{
// X, Y, Z accelerations

fprintf(stderr, "Unable to read from ADXL345\n");


//exit(1);
}
else
{
x = buf[1]<<8| buf[0];
y = buf[3]<<8| buf[2];
z = buf[5]<<8| buf[4];
xa = (90.0 / 256.0) * (float) x;
ya = (90.0 / 256.0) * (float) y;
za = (90.0 / 256.0) * (float) z;
//printf("x=%d, y=%d, z=%d\n", x, y, z);
printf("%4.0f %4.0f %4.0f\n", xa, ya, za);
//for (b=0; b<6; b++) printf("%02x ",buf[b]);
printf("\n");
sprintf(system_str, "sudo python lcd.py %f %f %f", xa, ya,
za);
system( system_str );

}
// usleep(9000);
}
return 0;
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Arduino si senzorul SHT11

Senzorul SHT11 ofera posibilitatea de a masura temperatura si umiditatea din mediul


inconjurator cu o precizie ridicata. Se conecteaza la placa Arduino prin intermediul a 2 pini digitali.
Consumul senzorului este foarte redus, rezolutia temperaturii masurata de catre senzor este de 0.01 º C
si 0.03 % pentru umiditatea relativa. In cel mai rau caz temperatura poate avea o acuratete de ± 2 º C si
± 3.5 % pentru umiditate.
Senzorul se alimenteaza cu o tensiune cuprinsa intre 2.4 si 5.5V, comunica printr-un protocol
serial (Two-Wire Serial) si iesirea digitala este deja calibrata din fabrica.
In prima parte a tutorialului, vei conecta senzorul la placa Arduino si vei afisa 3 valori distincte
in terminal. In cea de-a doua parte, vei invata cum se poate calcula indicele de confort termic in functie
de temperatura si umiditate.
Vei avea nevoie de urmatoarele componente:
• O placa Arduino Uno.
• Un senzor de temperatura si umiditate SHT11.
• 4 fire pentru conexiuni.

http://www.robofun.ro/forum
Cum conectez senzorul ?

Senzorul se conecteaza foarte simplu la placa Arduino. Foloseste tabelul din continuare.

Arduino 5V SHT11 VCC


Arduino GND SHT11 GND
Arduino pin digital 10 SHT11 pin DAT
Arduino pin digital 11 SHT11 pin SCK

Dupa ce ai realizat conexiunile senzorului cu placa Arduino, vei obtine urmatoarea imagine.

Libraria senzorului.

Senzorul SHT11 are o librarie special scrisa pentru el. Libraria se poate descarca de aici:
https://github.com/practicalarduino/SHT1x
Descarca libraria (butonul Download ZIP) si copiaz-o in fisierul libraries din directorul
Arduino. Restarteaza mediul Arduino si continua cu programele de mai jos.

Primul program.

Mai jos este listat sketch-ul. Il copiezi (copy/paste) direct in mediul de programare Arduino si il

http://www.robofun.ro/forum
incarci in placa Arduino UNO. Sketch-ul afiseaza in Serial Monitor 3 valori distincte: temperatura in
grade Celsius, in grade Fahrenheit si procentul de umiditate relativa.
Dupa ce ai incarcat sketch-ul in placa Arduino, deschide Serial Monitor ca sa poti vizualiza
valorile de temperatura si umiditate. Valorile vor aparea la fiecare 2 secunde, ca in imaginea de mai jos.

Codul sursa.

#include <SHT1x.h>
#define dataPin 10
#define clockPin 11
SHT1x sht1x(dataPin, clockPin);

float temp_c;
float temp_f;
float humidity;

void setup()
{
Serial.begin(9600);
// dump first reading
temp_c = sht1x.readTemperatureC();

http://www.robofun.ro/forum
temp_f = sht1x.readTemperatureF();
humidity = sht1x.readHumidity();
}

void loop()
{
// Read values from the sensor
temp_c = sht1x.readTemperatureC();
temp_f = sht1x.readTemperatureF();
humidity = sht1x.readHumidity();

Serial.print("Temperatura: ");
Serial.print(temp_c, 2);
Serial.print("C / ");
Serial.print(temp_f, 2);
Serial.print("F. Umiditate: ");
Serial.print(humidity);
Serial.println(" %");
delay(2000);
}

Al doilea program.

Indicele de confort termic iti arata cat de sufocanta este vremea si este dat de o formula care
contine doua variabile: temperatura si umiditatea. Cand valoarea indicelui este sub 65, atunci aerul este
placut si usor de respirat dar cand indicele sare peste pragul de 80, atunci apare o stare de disconfort,
aerul fiind irespirabil.
Acest lucru se intampla atunci cand temperatura este ridicata si umiditatea din aer este mare.
Din cauza nivelului mare de umiditate din aer, evaporarea la nivelul pielii este ingreunata si astfel
temperatura corpului scade mult mai greu (sau nu mai scade deloc).
In sketch-ul listat mai jos s-a utilizat urmatoarea formula pentru a determina indicele de confort
termic:
indice = (temp_c * 1.8 + 32) – (0.55 – 0.0055 * humidity) * ((temp_c * 1.8 + 32) – 58)
unde:
temp_c reprezinta temperatura exprimata in grade Celsius iar humidity reprezinta umiditatea
relativa exprimata in procente.
Dupa ce ai incarcat sketch-ul in placa Arduino, deschide Serial Monitor si urmareste valorile de
temperatura, umiditate si indicele de confort termic. Vei obtine urmatoarea imagine.

http://www.robofun.ro/forum
Codul sursa.

#include <SHT1x.h>
#define dataPin 10
#define clockPin 11
SHT1x sht1x(dataPin, clockPin);

float temp_c;
float temp_f;
float humidity;
int indice;

void setup()
{
Serial.begin(9600);
// dump first reading
temp_c = sht1x.readTemperatureC();
temp_f = sht1x.readTemperatureF();
humidity = sht1x.readHumidity();
}

void loop()
{

http://www.robofun.ro/forum
// Read values from the sensor
temp_c = sht1x.readTemperatureC();
temp_f = sht1x.readTemperatureF();
humidity = sht1x.readHumidity();
indice = (temp_c * 1.8 + 32) - (0.55 - 0.0055 * humidity) *
((temp_c * 1.8 + 32) - 58);
// Print the values to the serial port
Serial.print("Temperatura: ");
Serial.print(temp_c, 2);
Serial.print("C / ");
Serial.print(temp_f, 2);
Serial.print("F. Umiditate: ");
Serial.print(humidity);
Serial.print(" %");
Serial.print(" Indice de confort termic: ");
Serial.println(indice);
delay(2000);
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Arduino si MOD-GPS

MOD-GPS este un modul de GPS echipat cu o antena interna si conector UEXT. Iti permite
sa afli pozitia (latitudine si longitudine), viteza de deplasare, altitudinea, rata de ascensiune, ceasul si nr.
de sateliti. Conexiunea cu placa Arduino se realizeaza prin portul serial (RX,TX) si modulul GPS
transmite coduri NMEA (format text) care pot fi citite foarte usor prin Serial Monitor.
Pentru acest tutorial, vei avea nevoie de urmatoarele componente:
• O placa Arduino UNO.
• Un modul MOD-GPS.
• 4 fire pentru conexiuni.

Cum conectez modulul GPS ?

Modulul GPS se conecteaza foarte simplu la placa Arduino. Foloseste cabluri tata-tata ca sa
conectezi pinii GND, 3.3V, TX si respectiv RX. Foloseste tabelul si imaginea conectorului UEXT de
mai jos.

http://www.robofun.ro/forum
Arduino 3.3V MOD-GPS 3.3V
Arduino GND MOD-GPS GND
Arduino pin digital 3 MOD-GPS TX
Arduino pin digital 4 MOD-GPS RX

Dupa ce ai conectat modulul GPS la placa Arduino, vei obtine urmatoarea imagine.

http://www.robofun.ro/forum
Libraria TinyGPS.

Exista o librarie special conceputa care gestioneaza protocolul NMEA al GPS-ului. Libraria se
numeste TinyGPS si se poate descarca de la adresa:
http://arduiniana.org/libraries/tinygps/
Descarca libraria si copiaz-o in fisierul libraries din directorul Arduino. Restarteaza mediul
Arduino si continua cu programul de mai jos.

Sketch-ul Arduino.

Mai jos este listat sketch-ul. Il copiezi (copy/paste) direct in mediul de programare Arduino si il
incarci in placa Arduino UNO. Dupa ce ai pornit placa, este necesar sa astepti o perioada de timp pana
cand datele vor aparea treptat in Serial Monitor, deoarece modulul GPS genereaza datele doar atunci
cand sunt calculate de la cel putin 3 sateliti. Sketch-ul afiseaza informatii despre latitudine, longitudine,
nr. de sateliti receptionati si o valoare estimativa a calitatii preciziei.

http://www.robofun.ro/forum
Codul sursa.
#include <SoftwareSerial.h>
#include <TinyGPS.h>

TinyGPS gps;
SoftwareSerial ss(3, 4);

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

void loop()
{
bool newData = false;

for (unsigned long start = millis(); millis() - start < 1000;)


{
while (ss.available())
{
char c = ss.read();
if (gps.encode(c));
newData = true;
}
}
if (newData)
{
float flat, flon;
unsigned long age;
gps.f_get_position(&flat, &flon, &age);
Serial.print("LAT=");
Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat,
6);
Serial.print(" LON=");
Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon,
6);
Serial.print(" SAT=");
Serial.print(gps.satellites() ==
TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());
Serial.print(" PREC=");
Serial.println(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 :
gps.hdop());
}
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Arduino GSM Shield

Shield-ul Arduino GSM permite unei placi Arduino sa se conecteze la


reteaua de Internet, sa trimita sau sa primeasca mesaje SMS si sa realizeze
apeluri de voce. Shield-ul este compatibil cu placa Arduino UNO insa pentru
placile Arduino Mega, Mega ADK si Leonardo sunt necesare cateva modificari
minore. Momentan, placa Due nu este compatibila cu shield-ul.
In acest tutorial vei descoperi cum se realizeaza un apel de voce si cum
se transmite un SMS, utilizand shield-ul Arduino GSM.

Pentru acest tutorial, vei avea nevoie de urmatoarele componente:


• O placa Arduino Mega - http://www.robofun.ro/arduino_mega2560.
• Un shield Arduino GSM - http://www.robofun.ro/arduino_gsm_gprs_shield.
• Cablu USB.
• Fire de conexiune tata-tata
http://www.robofun.ro/fire_conexiune_tata_tata-140mm.
• Un alimentator extern pentru Arduino (9V @ 1A)
http://www.robofun.ro/alimentator-extern-arduino.

http://www.robofun.ro/forum
• O pereche de casti cu microfon.

Modificarea necesara pentru placa Arduino Mega.

Pentru ca placa Arduino Mega sa comunice corect cu shield-ul GSM, sunt


necesare 2 modificari si anume:
• pinul 2 al shield-ului se indoaie deoarece nu trebuie sa fie conectat cu
placa Arduino.
• pinul 2 al shield-ului se conecteaza printr-un fir cu capete tata-tata la
pinul 10.

Pentru celelalte placi, respectiv pentru placa Arduino UNO, nu este


necesara nici o modificare. Nu trebuie decat sa conectezi shield-ul si atat.
Pentru placa Leonardo, urmeaza aceeasi pasi ca mai sus cu diferenta ca pinul 2
se conecteaza la pinul 8.

Apel de voce.

Pentru a realiza apelul de voce, iti vor fi necesare castile si microfonul.


Pentru conectarea celor doua, se vor urmari diagramele de mai jos:

Imaginea de mai sus reprezinta partea interioara a shield-ului. Pe aceasta


parte vei gasi pad-urile M1P / M1N fiind intrarea pozitiva si negativa pentru
microfon si pad-urile S1P / S1N fiind iesirea pozitiva si negativa pentru speaker
(difuzor).

http://www.robofun.ro/forum
Intre casti/microfon si pad-urile shield-ului este necesar un circuit
intermediar, dat de diagrama de mai jos.

In final, conecteaza alimentatorul de 9V in mufa placii Arduino. Atentie !


Nu se recomanda alimentarea shield-ului direct din USB, fara alimentator.
Modemul de pe placa shield-ului consuma mult mai mult decat poate sa
genereze portul USB. Acest lucru poate duce la o functionare incorecta sau , in
cel mai rau caz, la o defectiune.

Dupa realizarea tuturor conexiunilor, tot ce iti ramane este sa infigi


shield-ul in placa Arduino si sa fixezi cartela SIM in slot. Urmeaza imaginile de
mai jos.

http://www.robofun.ro/forum
http://www.robofun.ro/forum
In imaginea de mai sus se observa si modificarea de care am vorbit mai
devreme.

Sketch-ul pentru apelul de voce

Incarca sketch-ul de mai jos in placa Arduino. Deschide Serial Monitor si


asteapta pana cand ti se va cere numarul de telefon. Tasteaza numarul si
asteapta pana cand se realizeaza apelul. Pentru a incheia apelul, nu trebuie
decat sa tastezi un caracter de la tastatura si sa il trimiti prin Serial Monitor.

http://www.robofun.ro/forum
#include <GSM.h>

// PIN Number
#define PINNUMBER ""

// initialize the library instance


GSM gsmAccess; // include a 'true' parameter for debug enabled
GSMVoiceCall vcs;

String remoteNumber = ""; // the number you will call


char charbuffer[20];

void setup()
{

// initialize serial communications


Serial.begin(9600);

Serial.println("Realizeaza apel de voce");

// connection state
boolean notConnected = true;

// Start GSM shield


// If your SIM has PIN, pass it as a parameter of begin() in
quotes
while(notConnected)
{
if(gsmAccess.begin(PINNUMBER)==GSM_READY)
notConnected = false;
else
{
Serial.println("Lipsa conexiune");
delay(1000);
}
}

Serial.println("Modul GSM initializat");


Serial.println("Tasteaza nr. de telefon: ");

void loop()
{

http://www.robofun.ro/forum
// add any incoming characters to the String:
while (Serial.available() > 0)
{
char inChar = Serial.read();
// if it's a newline, that means you should make the call:
if (inChar == '\n')
{
// make sure the phone number is not too long:
if (remoteNumber.length() < 20)
{
// show the number you're calling:
Serial.print("Apelez : ");
Serial.println(remoteNumber);
Serial.println();

// Call the remote number


remoteNumber.toCharArray(charbuffer, 20);

// Check if the receiving end has picked up the call


if(vcs.voiceCall(charbuffer))
{
Serial.println("Apel realizat. Tasteaza o noua linie
pentru a inchide.");
// Wait for some input from the line
while(Serial.read()!='\n' &&
(vcs.getvoiceCallStatus()==TALKING));
// And hang up
vcs.hangCall();
}
Serial.println("Apel incheiat.");
remoteNumber="";
Serial.println("Tasteaza nr. de telefon: ");
}
else
{
Serial.println("Reintrodu nr. de telefon.");
remoteNumber = "";
}
}
else
{
// add the latest character to the message to send:
if(inChar!='\r')
remoteNumber += inChar;
}
}
}

http://www.robofun.ro/forum
Cum transmit un SMS ?

Shield-ul GSM este capabil de a trimite si SMSuri. Sketch-ul de mai jos


realizeaza o conexiune cu reteaua GSM si transmite un mesaj catre un numar
pe care il specifici in program.

http://www.robofun.ro/forum
#include <GSM.h>

#define PINNUMBER ""

// initialize the library instance


GSM gsmAccess; // include a 'true' parameter for debug enabled
GSM_SMS sms;

// char array of the telephone number to send SMS


// change the number 1-212-555-1212 to a number
// you have access to
char remoteNumber[20]= "9999999999";

// char array of the message


char txtMsg[200]="Salut ! Acesta este un test.";

void setup()
{
// initialize serial communications
Serial.begin(9600);

http://www.robofun.ro/forum
Serial.println("Transmitere SMS");

// connection state
boolean notConnected = true;

// Start GSM shield


// If your SIM has PIN, pass it as a parameter of begin() in
quotes
while(notConnected)
{
if(gsmAccess.begin(PINNUMBER)==GSM_READY)
notConnected = false;
else
{
Serial.println("Lipsa conexiune");
delay(1000);
}
}
Serial.println("Modul GSM initializat");
sendSMS();
}

void loop()
{
// nothing to see here
}

void sendSMS(){

Serial.print("Nr. de telefon la care transmit mesajul: ");


Serial.println(remoteNumber);

// sms text
Serial.println("TRIMITERE");
Serial.println();
Serial.println("Mesaj:");
Serial.println(txtMsg);

// send the message


sms.beginSMS(remoteNumber);
sms.print(txtMsg);
sms.endSMS();
Serial.println("\nIncheiat!\n");
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Arduino GSM/GPRS Shield

Shield-ul Arduino GSM/GPRS permite placii Arduino sa se conecteze la reteaua de Internet, sa


trimita sau sa primeasca mesaje SMS si sa realizeze apeluri de voce. Shield-ul este compatibil cu placa
Arduino UNO, fara nici un fel de modificare. Pentru placile Arduino Mega si Arduino Leonardo sunt
necesare cateva modificari minore. Momentan, placa Due nu este compatibila cu shield-ul.
In acest tutorial vei descoperi cum se realizeaza o conexiune la reteaua de Internet si cum se
poate programa o aplicatie care citeste temperatura si o incarca la fiecare 5 secunde, intr-un serviciu de
stocare al datelor online. Shield-ul GSM/GPRS arata ca in imaginea de mai jos (fara modificarea
necesara)

Pentru acest tutorial, vei avea nevoie de urmatoarele componente:


• O placa Arduino UNO - http://www.robofun.ro/arduino/arduino_uno_v3
SAU
• O placa Arduino Mega - http://www.robofun.ro/arduino_mega2560
• Un shield Arduino GSM/GPRS - http://www.robofun.ro/arduino_gsm_gprs_shield
• Cablu USB.
• Fire de conexiune tata-tata
http://www.robofun.ro/fire_conexiune_tata_tata-140mm

http://www.robofun.ro/forum
• Un alimentator extern pentru Arduino (9V @ 1A)
http://www.robofun.ro/alimentator-extern-arduino
• Un senzor de temperatura brick.
http://www.robofun.ro/senzor-temperatura-brick?keyword=temperatura&category_id=0

Modificarea necesara pentru placa Arduino Mega

Daca folosesti placa Arduino UNO, sari peste aceasta sectiune. Daca folosesti Arduino Mega
sau Arduino Leonardo, fa pasii care urmeaza :
• pinul 2 al shield-ului se indoaie deoarece nu trebuie sa fie conectat cu placa Arduino.
• pinul 2 al shield-ului se conecteaza printr-un fir cu capete tata-tata la pinul 10.
Pentru celelalte placi, respectiv pentru placa Arduino UNO, nu este necesara nici o modificare.
Nu trebuie decat sa conectezi shield-ul si atat. Pentru placa Leonardo, urmeaza aceeasi pasi ca mai sus
cu diferenta ca pinul 2 se conecteaza la pinul 8.

Conexiunea la Internet

Conexiunea la Internet se realizeaza printr-o cartela SIM. Cartela necesita configurarea in


prealabil cu optiunea de Internet pe mobil. Acest pas il poti realiza citind instructiunile providerului de
la care detii cartela (vei gasi instructiunile online sau pe pagina lor de internet). Iti sunt necesare si
urmatoarele date de conectare (pe care le vei gasi online sau dupa ce ai configurat cartela cu serviciul de
Internet):
• GPRS APN
• GPRS Login
• GPRS Password

Datele de conectare le vei folosi mai tarziu in sketch, dar pentru moment asigura-te ca ai realizat
pasul precedent.

Stocarea temperaturii online

In continuare vei folosi o conexiune Internet peste reteaua de telefonie 3G pentru a stoca
temperatura citita de Arduino de la un senzor pe serviciul online Xively.com. Pagina de web iti pune la
dispozitie nu doar inregistrarea temperaturii dar si evolutia in timp, prin grafice.
Pentru aceasta, ai nevoie de un cont pe care il inregistrezi la adresa: https://xively.com/ iar aici
iti vei adauga primul dispozitiv pe care il vei numi dupa preferinta ta (numele il vei utiliza mai tarziu in
sketch).

http://www.robofun.ro/forum
Dupa ce ai creat primul dispozitiv, asigura-te ca ai urmatoarele informatii, deoarece iti vor fi
necesare in sketch-ul de mai jos:
• API KEY
• FEED ID
• Numele proiectului (ales anterior)

Conectarea shield-ului si a senzorului de temperatura.

Conecteaza componentele in urmatoarea ordine:


• Shield-ul GSM/GPRS (cu modificarea pentru Arduino Mega, daca ai utilizat Arduino Mega).
Acesta se infige, foarte usor, in placa Arduino.
• Cartela SIM se introduce in slotul shield-ului.
• Senzorul de temperatura brick se conecteaza dupa urmatorul tabel:

Arduino PIN GND Senzor brick PIN GND


Arduino PIN VCC Senzor brick PIN VCC
Arduino PIN A0 Senzor brick PIN OUT

• Conecteaza sursa de alimentare de 9V si cablul USB. Atentie ! Nu se


recomanda alimentarea shield-ului direct din USB, fara alimentator.

http://www.robofun.ro/forum
Modemul de pe placa shield-ului consuma mult mai mult decat poate sa
genereze portul USB. Acest lucru poate duce la o functionare incorecta
sau, in cel mai rau caz, la o defectiune.

Codul sursa.

Copiaza cu copy/paste codul sursa de mai jos. Cauta in cod liniile urmatoare si modifica-le cu
datele personale:

#define APIKEY "API KEY"


#define FEEDID 0000000000
#define USERAGENT "Project Name"

#define GPRS_APN "live.vodafone.com"


#define GPRS_LOGIN "live"
#define GPRS_PASSWORD "vodafone"

Incarca codul in placa Arduino si deschide Serial Monitor. Asteapta cateva momente si vei
obtine urmatoarea imagine.

http://www.robofun.ro/forum
Deschide pagina unde ti-ai creat contul si ar trebui sa obtii, dupa o perioada mai indelungata de
timp, evolutia in timp a temperaturii sub forma de grafic.

http://www.robofun.ro/forum
#include <GSM.h>

// Pachube Client data


#define APIKEY "API KEY" // replace your pachube api key
here
#define FEEDID 0000000000 // replace
your feed ID
#define USERAGENT "Project Name" // user agent is
the project name
// PIN Number
#define PINNUMBER ""
// APN data
#define GPRS_APN "live.vodafone.com" // replace your GPRS
APN
#define GPRS_LOGIN "live" // replace with your GPRS login
#define GPRS_PASSWORD "vodafone" // replace with your GPRS
password
// initialize the library instance:
GSMClient client;
GPRS gprs;
GSM gsmAccess;
char server[] = "api.pachube.com"; // name address for pachube
API

unsigned long lastConnectionTime = 0; // last time you


connected to the server, in milliseconds
boolean lastConnected = false; // state of the
connection last time through the main loop
const unsigned long postingInterval = 10*1000; //delay between
updates to Pachube.com

void setup()
{
Serial.begin(9600);
while (!Serial) {
;
}
boolean notConnected = true;

while(notConnected)
{
if((gsmAccess.begin(PINNUMBER)==GSM_READY) &
(gprs.attachGPRS(GPRS_APN, GPRS_LOGIN,
GPRS_PASSWORD)==GPRS_READY))
notConnected = false;
else
{
Serial.println("Not connected");
delay(1000);

http://www.robofun.ro/forum
}
}
}

void loop()
{
int sensorReading = readTempInCelsius(10,0);

if (client.available())
{
char c = client.read();
Serial.print(c);
}

if (!client.connected() && lastConnected)


{
client.stop();
}

if(!client.connected() && ((millis() - lastConnectionTime) >


postingInterval))
{
sendData(sensorReading);
}

lastConnected = client.connected();
}

/*
Conexiunea HTTP cu server-ul.
*/
void sendData(int thisData)
{
if (client.connect(server, 80))
{
Serial.println("connecting...");

// send the HTTP PUT request:


client.print("PUT /v2/feeds/");
client.print(FEEDID);
client.println(".csv HTTP/1.1");
client.println("Host: api.pachube.com");
client.print("X-ApiKey: ");
client.println(APIKEY);
client.print("User-Agent: ");
client.println(USERAGENT);
client.print("Content-Length: ");

http://www.robofun.ro/forum
// calculate the length of the sensor reading in bytes:
// 8 bytes for "sensor1," + number of digits of the data:
int thisLength = 8 + getLength(thisData);
client.println(thisLength);

// last pieces of the HTTP PUT request:


client.println("Content-Type: text/csv");
client.println("Connection: close");
client.println();

// here's the actual content of the PUT request:


client.print("sensor1,");
client.println(thisData);
}
else
{
// if you couldn't make a connection:
Serial.println("connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// note the time that the connection was made or attempted
lastConnectionTime = millis();
}

/*
This method calculates the number of digits in the
sensor reading. Since each digit of the ASCII decimal
representation is a byte, the number of digits equals
the number of bytes.
*/
int getLength(int someValue)
{
// there's at least one byte:
int digits = 1;

// continually divide the value by ten,


// adding one to the digit count for each
// time you divide, until you're at 0:
int dividend = someValue /10;
while (dividend > 0)
{
dividend = dividend /10;
digits++;
}

http://www.robofun.ro/forum
// return the number of digits:
return digits;
}

float readTempInCelsius(int count, int pin) {


float temperaturaMediata = 0;
float sumaTemperatura;
for (int i =0; i<count; i++) {
int reading = analogRead(pin);
float voltage = reading * 5.0;
voltage /= 1024.0;
float temperatureCelsius = (voltage - 0.5) * 100 ;
sumaTemperatura = sumaTemperatura + temperatureCelsius;
}
return sumaTemperatura / (float)count;
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Arduino Ethernet – senzor de temperatura – Xively.com

In acest tutorial vei descoperi cum se conecteaza un senzor de


temperatura brick la o placa Arduino Ethernet si cum se poate programa placa
pentru a incarca valoarea temperaturii, pe un serviciu online de stocare al
datelor denumit Xively.

Pentru acest tutorial, iti vor fi necesare urmatoarele componente:


• O placa Arduino Ethernet
- http://www.robofun.ro/arduino/arduino_ethernet_w_o_poe
• Un modul FTDI
- http://www.robofun.ro/conector-ftdi-5v
• Fire de conexiune tata-tata
- http://www.robofun.ro/fire_conexiune_tata_tata-140mm
• Un senzor de temperatura brick
http://www.robofun.ro/senzor-temperatura-brick

http://www.robofun.ro/forum
• Un cablu mini USB
• Acces prin cablu la Ethernet

Stocarea temperaturii online.

Xively.com este un serviciu care permite stocarea informatiei preluata de


la senzori. Pagina de web iti pune la dispozitie nu doar inregistrarea
temperaturii dar si evolutia in timp, prin grafice. Pentru asta, ai nevoie de un
cont pe care il inregistrezi la adresa: https://xively.com/ iar aici iti vei adauga
primul dispozitiv pe care il vei numi dupa preferinta ta (numele il vei utiliza mai
tarziu in sketch).
Asa arata 2 dispozitive adaugate.

http://www.robofun.ro/forum
Dupa ce ai creat dispozitivul, asigura-te ca ai urmatoarele informatii,
pentru ca iti vor fi necesare in sketch:
• API KEY
• FEED ID
• Numele proiectului (ales anterior)

Cum functioneaza ?

1. Senzorul brick de temperatura se conecteaza la placa Arduino


Ethernet, urmand tabelul de mai jos:

Arduino PIN GND Senzor brick PIN GND


Arduino PIN VCC Senzor brick PIN VCC
Arduino PIN A0 Senzor brick PIN OUT

2. Conectorul FTDI se conecteaza prin cablu mini USB, la


calculator si prin conector la placa Arduino Ethernet.

3. Placa Arduino Ethernet se conecteaza la router, prin cablul


Ethernet.

http://www.robofun.ro/forum
Codul sursa

Copiaza cu copy/paste codul sursa de mai jos. Cauta in cod liniile


urmatoare si modifica-le cu datele personale:

#define APIKEY "api_key"


#define FEEDID 999999999999
#define USERAGENT "Arduino Temperature"

Cauta in cod urmatoarea linie si modifica adresa IP conform setarilor tale


din router.

IPAddress ip(192,168,2,110);

Incarca sketch-ul in router si deschide Serial Monitor. Iti vor aparea


urmatoarele date, ca in imaginea de mai jos.

http://www.robofun.ro/forum
Deschide pagina unde ti-ai creat contul si ar trebui sa obtii, dupa o
perioada mai indelungata de timp, evolutia in timp a temperaturii sub forma de
grafic.

http://www.robofun.ro/forum
#include <SPI.h>
#include <Ethernet.h>

#define APIKEY "api_key" // replace your pachube api key


here
#define FEEDID 9999999999 // replace your feed ID
#define USERAGENT "Arduino Temperature" // user agent is the
project name

byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

http://www.robofun.ro/forum
IPAddress ip(192,168,2,110);
EthernetClient client;

IPAddress server(216,52,233,122);
char server[] = "api.pachube.com";

unsigned long lastConnectionTime = 0;


boolean lastConnected = false;
const unsigned long postingInterval = 10*1000;

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}

if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
Ethernet.begin(mac, ip);
}
}

void loop() {
int sensorReading = readTempInCelsius(10,0);

if (client.available()) {
char c = client.read();
Serial.print(c);
}

if (!client.connected() && lastConnected) {


Serial.println();
Serial.println("disconnecting.");
client.stop();
}

if(!client.connected() && (millis() - lastConnectionTime >


postingInterval)) {
sendData(sensorReading);
}
lastConnected = client.connected();
}

// this method makes a HTTP connection to the server:


void sendData(int thisData) {
// if there's a successful connection:
if (client.connect(server, 80)) {

http://www.robofun.ro/forum
Serial.println("connecting...");
// send the HTTP PUT request:
client.print("PUT /v2/feeds/");
client.print(FEEDID);
client.println(".csv HTTP/1.1");
client.println("Host: api.pachube.com");
client.print("X-PachubeApiKey: ");
client.println(APIKEY);
client.print("User-Agent: ");
client.println(USERAGENT);
client.print("Content-Length: ");

// calculate the length of the sensor reading in bytes:


// 8 bytes for "sensor1," + number of digits of the data:
int thisLength = 8 + getLength(thisData);
client.println(thisLength);

// last pieces of the HTTP PUT request:


client.println("Content-Type: text/csv");
client.println("Connection: close");
client.println();

// here's the actual content of the PUT request:


client.print("sensor1,");
client.println(thisData);

}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
// note the time that the connection was made or attempted:
lastConnectionTime = millis();
}

int getLength(int someValue) {


// there's at least one byte:
int digits = 1;
// continually divide the value by ten,
// adding one to the digit count for each
// time you divide, until you're at 0:
int dividend = someValue /10;
while (dividend > 0) {
dividend = dividend /10;
digits++;

http://www.robofun.ro/forum
}
// return the number of digits:
return digits;
}

float readTempInCelsius(int count, int pin) {


float temperaturaMediata = 0;
float sumaTemperatura;
for (int i =0; i<count; i++) {
int reading = analogRead(pin);
float voltage = reading * 5.0;
voltage /= 1024.0;
float temperatureCelsius = (voltage - 0.5) * 100 ;
sumaTemperatura = sumaTemperatura + temperatureCelsius;
}
return sumaTemperatura / (float)count;
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Arduino si libraria TVOut

In acest tutorial vei descoperi cum se poate programa o placa Arduino


pentru a genera semnal video format PAL, pentru televizoarele obisnuite. In
prima parte a tutorialului vei instala libraria, iar in cea de-a doua parte vei
incarca 2 sketch-uri. Primul program afiseaza pe ecranul televizorului un desen,
cateva propozitii cu font-uri diferite, forme geometrice si un cub animat in 3D.
Al doilea program afiseaza pe ecran jocul Game of Life.
Vei avea nevoie de urmatoarele componente:
• O placa Arduino - http://www.robofun.ro/arduino
• Breadboard - http://www.robofun.ro/breadboard
• Fire de conexiuni tata – tata
http://www.robofun.ro/cabluri/fire_conexiune_tata_tata-110mm
• Un rezistor de 1kΩ - http://www.robofun.ro/electronice/rezistoare
• Un rezistor de 330Ω - http://www.robofun.ro/electronice/rezistoare
• Un cablu RCA pentru televizor.

Conecteaza placa Arduino la televizor urmand diagrama de mai jos.

http://www.robofun.ro/forum
Foloseste imaginea urmatoare ca referinta pentru a conecta corect placa
Arduino:

Libraria TVOut.

Aceasta librarie este capabila de a genera diverse tipuri de semnale. In


cazul de fata, te vei concentra doar pe un singur tip, mai exact pe format-ul
PAL. Libraria se descarca de la urmatoarea adresa si se instaleaza ca orice alta
librarie in Arduino:
https://code.google.com/p/arduino-tvout/downloads/list

http://www.robofun.ro/forum
Exemplul DemoPAL.

Deschide exemplul DemoPAL din libraria TVOut si incarca-l in placa


Arduino. Comuta televizorul pe modul A/V sau EXT1. Vei observa cum vor
aparea diverse formate de text, forme geometrice si un cub 3D.

Acest exemplu te poate familiariza cu modul de functionare al placii


Arduino. Imaginile urmatoare iti vor arata cum ar trebui sa arate ecranul
televizorului tau.

http://www.robofun.ro/forum
http://www.robofun.ro/forum
http://www.robofun.ro/forum
Jocul Game of Life.

Game of Life este un „automat celular“ creat de un matematician


britanic pe nume John Horton Conway. Jocul se desfasoara pe o matrice
bidimensionala alcatuita din celule, fiecare luand una din cele 2 stari: on sau
off. Jocul simuleaza evolutia celulelor pe baza a 4 reguli. Pe parcursul evolutiei
multe celule vor muri, iar altele voi trai mai multe generatii.
Programul de mai jos simuleaza acest joc pe placa Arduino. Tot ce trebuie
sa faci este sa copiezi codul in Arduino si sa incarci sketch-ul.
Dupa ce ai incarcat sketch-ul, la scurt timp iti vor aparea celulele pe
ecran.

http://www.robofun.ro/forum
http://www.robofun.ro/forum
/**
*
* Copyright 2012-02-26 Joseph Lewis <joehms22@gmail.com>
*
* Conway's game of life in cpp. The world is looped (life at top
can
* move to bottom &c.) Built to run on the Arduino with the TVout
* library.
*
* Apache 2.0 License
*
* http://code.google.com/p/arduino-tvout/
*
*/

#include "TVout.h"
#include "fontALL.h"
TVout TV;

const int COLS = 29;


const int ROWS = 15;

// The "Alive" cells on the board.


uint32_t alive[ROWS] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

bool isAlive(int row, int col)


{
return alive[row] & (1<<(col));
}

void setAlive(int row, int col)


{
alive[row] |= 1 << col;
}

int boardnum = 0; // number of boards run by the game


int iteration = 0; // current round in the current board

int numberAround(int row, int col);

/**
* Sets the alive array to all falses.
*/
void blank_alive()
{
for(int i = 0; i < ROWS; ++i)

http://www.robofun.ro/forum
alive[i] = 0;
}

/**
* Writes output to the console.
*/
void do_output()
{
TV.clear_screen();
TV.print("Board: ");
TV.print(boardnum);
TV.print(" Iteration: ");
TV.println(iteration);

for(int i = 0; i < ROWS; i++)


{

for(int j = 0; j < COLS; j++)


{
// WIDTH, HEIGHT
if(isAlive(i,j))
TV.print("0");
else
TV.print(" ");
}
if(i != ROWS -1)
TV.print("\n");
}

/**
* Randomly fills the grid with alive cells after blanking.
*/
void random_fill()
{
blank_alive();
randomSeed(analogRead(0));

http://www.robofun.ro/forum
// Fill 30% of the cells
int numToFill = (ROWS * COLS) * 30 / 100 ;

for(int r = 0; r < numToFill; r ++)


{
int row = rand() % ROWS;
int col = rand() % COLS;

setAlive(row,col);
}
}

/**
* Returns the index of the row below the current one.
*/
int rowBelow(int row)
{
return (row + 1 < ROWS) ? row + 1 : 0;
}

/**
* Returns the index of the row above the given one
*/
int rowAbove(int row)
{
return (row > 0) ? row - 1 : ROWS - 1;
}

/** Returns the index of the col to the right of this one */
int colRight(int col)
{
return (col + 1 < COLS) ? col + 1 : 0;
}

/** Returns the index of the col to the left of this one */
int colLeft(int col)
{
return (col > 0) ? col - 1 : COLS -1;
}

/** true if the cell to the left is alive*/


bool left(int row, int col)
{
col = colLeft(col);
return isAlive(row,col);
}

/** true if the cell to the right is alive*/

http://www.robofun.ro/forum
bool right(int row, int col)
{
col = colRight(col);
return isAlive(row,col);
}

/** true if the cell above is alive*/


bool above(int row, int col)
{
row = rowAbove(row);
return isAlive(row,col);
}

/** true if the cell below is alive*/


bool below(int row, int col)
{
row = rowBelow(row);
return isAlive(row,col);
}

/** true if the cell NE is alive*/


bool aboveright(int row, int col)
{
row = rowAbove(row);
col = colRight(col);
return isAlive(row,col);
}

/** true if the cell SE is alive*/


bool belowright(int row, int col)
{
row = rowBelow(row);
col = colRight(col);
return isAlive(row,col);
}

/** true if the cell NW is alive*/


bool aboveleft(int row, int col)
{
row = rowAbove(row);
col = colLeft(col);
return isAlive(row,col);
}

/** true if the cell SW is alive*/


bool belowleft(int row, int col)
{
row = rowBelow(row);

http://www.robofun.ro/forum
col = colLeft(col);
return isAlive(row,col);
}

/**Returns the number of living cells sorrounding this one.*/


int numberAround(int row, int col)
{
int around = 0;
if(left(row,col))
around++;

if(right(row,col))
around++;

if(above(row,col))
around++;

if(below(row,col))
around++;

if(aboveright(row,col))
around++;

http://www.robofun.ro/forum
if(aboveleft(row,col))
around++;

if(belowright(row,col))
around++;

if(belowleft(row,col))
around++;

return around;
}

/**
* Moves all of the cells
*/
void move()
{
uint32_t nextRows[ROWS] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0 };

for(int i = 0; i < ROWS; i++)


{
for(int j = 0; j < COLS; j++)
{
int na = numberAround(i,j);
if((na == 2 && isAlive(i,j)) || na == 3)
nextRows[i] |= 1 << j;
}
}

for(int i = 0; i < ROWS; i++)


alive[i] = nextRows[i];
}

void setup()
{
TV.begin(NTSC,120,96);
TV.select_font(font4x6);
}

void loop() {
boardnum++;

http://www.robofun.ro/forum
TV.println("Conways game of life for Arduino, Copyright 2012
Joseph Lewis <joehms22@gmail.com>");
TV.delay(2000);

random_fill();

TV.print("Doing iterations");

for(iteration = 0;iteration < 50; iteration++)


{
do_output();
move();
TV.delay(500);
}
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Cum se controleaza sensul de rotatie al unui motor prin Wi-Fi

In acest tutorial vei descoperi cum se poate controla sensul de rotatie al


unui motor de curent continuu, utilizand un Arduino WiFi Shield si un Driver de
motoare L298. Tutorialul poate fi un punct de start foarte bun atunci cand vrei
sa realizezi un robot pe care sa il comanzi de la distanta sau vrei sa controlezi
alte dispozitive prin WiFi.
Comanda motorului se va realiza prin reteaua locala, mai exact prin
protocolul UDP. Te vei folosi de tastatura calculatorului pentru a transmite 3
comenzi catre placa Arduino. Comenzile sau tastele apasate vor fi preluate
printr-o aplicatie scrisa in Processing.

Vei avea nevoie de urmatoarele componente:


• O placa Arduino - http://www.robofun.ro/arduino
• Arduino Wifi Shield - http://www.robofun.ro/arduino_wifi_shield
• Driver Motoare L298 versiunea 2:
http://www.robofun.ro/mecanice/driver/shield-motoare-l298-v2
• Un motor compatibil cu Driver-ul L298:
http://www.robofun.ro/mecanice/motoare
• Alimentator extern Arduino 9V @ 1A:
http://www.robofun.ro/surse_de_alimentare/alimentatoare/alimentator-
extern-arduino-9V

http://www.robofun.ro/forum
Cum se asambleaza ?

Asamblarea celor 3 placi este foarte simpla:

http://www.robofun.ro/forum
1. Shield-ul Arduino Wifi se infige in placa Arduino.

2. Shield-ul L298 se infige in pinii shield-ului WiFi.

http://www.robofun.ro/forum
http://www.robofun.ro/forum
3. Cele 2 fire ale motorului de curent continuu se infig in conectorul
MOTOR1 si se fixeaza ferm prin strangerea suruburilor.

http://www.robofun.ro/forum
4. Se conecteaza cablul USB si alimentatorul extern de 9V.

Codul sursa Arduino.

Urmatorul pas este sa incarci in placa Arduino sketch-ul de mai jos. Dupa
ce ai copiat codul in mediul Arduino, urmeaza sa modifici cateva linii de cod si
anume:

char ssid[] = "default"; // your network SSID (name)


char pass[] = "password"; // your network password (use for WPA,
or use as key for WEP)

Valoarea „default“ reprezinta SSID-ul routerului wireless. Modifica


aceasta valoare conform routerului tau.
Valoarea password reprezinta parola routerului wireless. Modifica aceasta
valoare conform parolei routerului tau.

http://www.robofun.ro/forum
#include <SPI.h>
#include <WiFi.h>
#include <WiFiUdp.h>

int status = WL_IDLE_STATUS;


char ssid[] = "default"; // your network SSID (name)
char pass[] = "password"; // your network password (use for WPA,
or use as key for WEP)
int keyIndex = 0; // your network key Index number
(needed only for WEP)

unsigned int localPort = 2390; // local port to listen on

char packetBuffer[255]; //buffer to hold incoming packet

WiFiUDP Udp;

int MOTOR1_PIN1 = 6;
int MOTOR1_PIN2 = 9;
int MOTOR2_PIN1 = 3;
int MOTOR2_PIN2 = 5;

void setup(){
pinMode(MOTOR1_PIN1, OUTPUT);
pinMode(MOTOR1_PIN2, OUTPUT);
pinMode(MOTOR2_PIN1, OUTPUT);
pinMode(MOTOR2_PIN2, OUTPUT);

http://www.robofun.ro/forum
go(255,-255);
delay(2000);
go(-255,255);
delay(2000);
go(0,0);
Serial.begin(9600);
//UDP Configuration
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while(true);
}

// attempt to connect to Wifi network:


while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open
or WEP network:
status = WiFi.begin(ssid,pass);

// wait 10 seconds for connection:


delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus();

http://www.robofun.ro/forum
Serial.println("\nStarting connection to server...");
// if you get a connection, report back via serial:
Udp.begin(localPort);
}

void loop() {
// if there's data available, read a packet
int packetSize = Udp.parsePacket();
if(packetSize)
{
Serial.print("Received packet of size ");
Serial.println(packetSize);
Serial.print("From ");
IPAddress remoteIp = Udp.remoteIP();
Serial.print(remoteIp);
Serial.print(", port ");
Serial.println(Udp.remotePort());

// read the packet into packetBufffer


int len = Udp.read(packetBuffer,255);
if (strcmp(packetBuffer,"1") == 0) {
go(255,-255);
} else if (strcmp(packetBuffer,"2") == 0) {
go(-255,255);
} else if (strcmp(packetBuffer,"3") == 0) {
go(0,0);
}
if (len >0) packetBuffer[len]=0;
Serial.println("Contents:");
Serial.println(packetBuffer);

}
}

void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());

// print your WiFi shield's IP address:


IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);

// print the received signal strength:


long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);

http://www.robofun.ro/forum
Serial.println(" dBm");
}

void go(int speedLeft, int speedRight) {


if (speedLeft > 0) {
analogWrite(MOTOR1_PIN1, speedLeft);
analogWrite(MOTOR1_PIN2, 0);
}
else {
analogWrite(MOTOR1_PIN1, 0);
analogWrite(MOTOR1_PIN2, -speedLeft);
}

if (speedRight > 0) {
analogWrite(MOTOR2_PIN1, speedRight);
analogWrite(MOTOR2_PIN2, 0);
}
else {
analogWrite(MOTOR2_PIN1, 0);
analogWrite(MOTOR2_PIN2, -speedRight);
}
}

Aplicatia Processing.

Urmatorul pas este sa descarci, sa instalezi si sa pornesti mediul


Processing de la adresa: http://processing.org/ . Codul sursa care comanda
motorul de curent continuu este listat mai jos.
Dupa ce ai copiat codul sursa, modifica urmatoarea linie cu IP-ul placii
Arduino. Acesta il vei afla din Monitorul Serial ca in imaginea de mai jos:

String ip = "192.168.2.101"; // remote ip address

http://www.robofun.ro/forum
http://www.robofun.ro/forum
import hypermedia.net.*;

UDP udp; // define the UDP object

void setup() {
udp = new UDP( this, 6000 ); // create a new datagram connection
on port 6000
//udp.log( true ); // <-- printout the connection activity
udp.listen( true ); // and wait for incoming message
}

void draw()
{
}

void keyPressed() {
String ip = "192.168.2.101"; // remote ip address
int port = 2390; // destination port

if (key == CODED) {
if (keyCode == UP) {
udp.send("1", ip, port);
}
else if (keyCode == DOWN) {
udp.send("2", ip, port);
}
}
else if (key == BACKSPACE) {
udp.send("3", ip, port);
}
}

void receive( byte[] data ) { // <-- default handler


//void receive( byte[] data, String ip, int port ) { // <--
extended handler

for (int i=0; i < data.length; i++)


print(char(data[i]));
println();
}

http://www.robofun.ro/forum
Concluzie.

To ce trebuie sa faci acum este sa pornesti aplicatia in Processing si sa


tastezi UP, DOWN si Backspace. Apasand tasta UP motorul se va roti intr-un
sens, apasand tasta DOWN motorul se va roti in sens opus si apasand tasta
Backspace motorul se va opri.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Raspberry PI – timelapse

In acest tutorial vei descoperi cum se poate realiza fotografie in timelapse utilizand o placa
Raspberry PI, o camera Raspberry PI montata pe un suport special si un card SD de 8GB. Vei
alimenta placa folosind un alimentator cu mufa micro USB de 5V sau un acumulator solar.
Acumulatorul ofera o autonomie de aproximativ 2 ore, in cazul in care vrei sa amplasezi placa intr-
un spatiu deschis.
Componentele de care vei avea nevoie sunt cele din imaginea de mai jos.

Suportul pentru camera Raspberry PI:


http://www.robofun.ro/raspberry-pi-si-componente/suport-reglabil-camera-raspberry-pi
Permite reglajul pozitiei camerei atat fata-spate, cat si lateral. Reglajul fata-spate este
suficient de larg incat sa permita pozitionarea camerei paralel cu solul, ideal pentru timelapse cu
nori.
Acumulatorul cu incarcare solara:
http://www.robofun.ro/surse_de_alimentare/acumulatori/acumulator-incarcator-usb-solar

http://www.robofun.ro/forum
Cum vei realiza timelapse ?

1. Monteaza camera Raspberry PI pe suportul special. Instructiunile de montare


le vei gasi la urmatoarea adresa:

http://www.robofun.ro/raspberry-pi-si-componente/suport-reglabil-camera-raspberry-pi

2. Conecteaza cablul panglica al camerei, la placa Raspberry PI, avand marcajul


albastru orientat catre portul de retea.

http://www.robofun.ro/forum
3. Conecteaza cardul SD in slotul placii. Pe card poti rula Raspbian care se
poate instala cu ajutorul interfetei NOOBS.

4. Conecteaza alimentarea placii si cablul de retea. Logheaza-te prin SSH in


terminal.

5. Creeaza un fisier nou in care vei pastra codul sursa al programului dar si
fotografiile:

mkdir timelapse

6. Deschide editorul nano si copiaza codul sursa de mai jos:

sudo nano raspiLapseCam.py

7. Salveaza programul cu CTRL, X si Y.

8. Poti programa placa sa porneasca programul de timelapse de fiecare data


cand alimentezi Raspberry PI-ul. In acest mod, vei fi scutit de a te loga de fiecare data in
SSH si a porni programul manual.

http://www.robofun.ro/forum
sudo crontab -e

9. Adauga urmatoarea linie:

@reboot python /home/pi/timelapse/raspiLapseCam.py &

10. Amplaseaza camera foto intr-un loc preferat, alimenteaz-o si asteapta


aproximativ 2 ore pana cand cardul devine full.

Codul sursa.

#!/usr/bin/env python

# Import some frameworks


import os
import time
import RPi.GPIO as GPIO
from datetime import datetime

# Grab the current datetime which will be used to generate dynamic


folder names
d = datetime.now()
initYear = "%04d" % (d.year)
initMonth = "%02d" % (d.month)
initDate = "%02d" % (d.day)
initHour = "%02d" % (d.hour)
initMins = "%02d" % (d.minute)

folderToSave = "/home/pi/timelapse/timelapse_" + str(initYear) +


str(initMonth) + str(initDate) + str(initHour) + str(initMins)
os.mkdir(folderToSave)

# Set the initial serial for saved images to 1


fileSerial = 1

# Run a WHILE Loop of infinitely


while True:

http://www.robofun.ro/forum
d = datetime.now()
if d.hour > 2:

# Set FileSerialNumber to 000X using four digits


fileSerialNumber = "%04d" % (fileSerial)

# Capture the CURRENT time (not start time as set above) to


insert into each capture image filename
hour = "%02d" % (d.hour)
mins = "%02d" % (d.minute)

# Define the size of the image you wish to capture.


imgWidth = 2592 # Max = 2592
imgHeight =1944 # Max = 1944
print " ====================================== Saving file
at " + hour + ":" + mins

os.system("raspistill -w " + str(imgWidth) + " -h " +


str(imgHeight) + " -o " + str(folderToSave) + "/" +
str(fileSerialNumber) + "_" + str(hour) + str(mins) + ".jpg" + "
-t 0 -q 100")

# Increment the fileSerial


fileSerial += 1

# Wait 5 seconds before next capture


time.sleep(5)

else:

# Just trapping out the WHILE Statement


print " ====================================== Doing
nothing at this time"

Editarea video.

Vei observa ca dupa aproximativ 2 ore, vei obtine un numar foarte mare de imagini.
Imaginile le poti returna de pe card folosind WinSCP, daca esti utilizator de Windows. Aceste
imagini le poti uni intr-un singur film de prezentare. Lucrul asta il vei realiza intr-un software de
editare video (de exemplu: Movie Maker).
Cateva exemple le poti gasi pe Youtube - http://www.youtube.com/results?
search_query=timelapse+raspberry+pi&sm=3

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Controller PID cu Arduino

Prezentare generala.

In acest tutorial vei descoperi cum se poate realiza un controller PID avand o placa Arduino,
cum functioneaza metoda PID si ce putem realiza cu aceasta metoda.
Controlul PID (proportional, integral, derivativ) este o metoda utilizata la scara larga in reglarea
proceselor, cum ar fi reglarea temperaturii, reglarea nivelului de apa intr-o incinta, controlul vitezei unui
motor electric sau pozitionarea capului de imprimanta cu jet de cerneala. Acestea sunt doar cateva
exemple.
Desi aplicatiile difera intre ele, metoda de abordare folosind controlul PID este asemanatoare.
Ecuatia care descrie comportamentul unui controller PID exista sub diverse forme, dar forma generala
este urmatoarea:

Control = kP*Eroare + kI*Σ Eroare + kD * dP/dT

Eroarea reprezinta diferenta dintre valoarea actuala a procesului (sa presupunem ca reglam
viteza de rotatie a unui motor) si valoarea pe care ne-o dorim sa o atingem (referinta).
Intr-un limbaj de programare, eroarea se poate exprima astfel:

Eroare = Valoare – Referinta

Σ Eroare reprezinta suma erorilor anterioare iar dP/dT - rata de schimb a valorii procesului in
raport cu timpul. Nu vei insista foarte mult asupra ecuatiilor, deoarece vei descoperi mai tarziu cum
functioneaza algoritmul direct intr-un sketch Arduino.

Coeficientul proportional kP, integral kI si derivativ kD sunt responsabili cu reglarea


controllerului PID corespunzator procesului pe care il regleaza. Cu alte cuvinte, in cazul unui robot,
daca reglezi corect PID-ul, atunci robotul va fi foarte rapid si foarte precis.

Control este o valoare de tensiune sau curent pe care o vei utiliza atunci cand vrei sa controlezi
elementele de executie. In cazul unui robot, vei utiliza valoarea Control pentru a regla tensiunea de
alimentare a motoarelor (elementul de executie).

http://www.robofun.ro/forum
Algoritmul controllerului PID.

Iti propun urmatorul pseudocod care iti va arata ca metoda PID nu este foarte complicata.

PID:
Eroare = Referinta – Eroare_Actuala
Integral = Integral + (Eroare*dt)
Derivativ = (Eroare - Eroare_anterioara)/dt
Control = (Eroare*kP) + (Integral*kI) + (Derivativ*kD)
Eroare_anterioara = Eroare
Asteapta(dt)
GOTO PID

Pseudocodul iti arata pasii pe care ii urmeaza un controller PID atunci cand se afla in functiune.
Poate fi util atunci cand vrei sa programezi un controller PID, intr-un limbaj diferit de catre cel folosit
in Arduino.

Mai jos poti observa un controller PID realizat in Arduino. Programul nu este orientat catre un
exemplu anume, ci este unul general. Ramane la decizia ta sa alegi cum citesti valoarea Pozitie si cum
realizezi comanda motorului.

Actual = analogRead(Pozitie);
Eroare = Referinta - Actual;

if (abs(Eroare) < PragIntegral){ // previne saturatia integralei


Integral = Integral + Eroare; // acumuleaza
}
else {
Integral=0; // trece in 0 daca a depasit limita
}
P = Eroare*kP; // termenul proportional
I = Integral*kI; // termenul integrativ
D = (Eroare_anterioara-Actual)*kD; // termenul derivativ
Drive = P + I + D; // Control total = P+I+D
Drive = Drive*FactorScalare; // scaleaza Drive in domeniul 0-255
if (Drive < 0){ // Verifica directia
digitalWrite (Direction,LOW); // schimba directia
}
else { // schimba directia
digitalWrite (Direction,HIGH);
}
if (abs(Drive)>255) {
Drive=255;
}

http://www.robofun.ro/forum
analogWrite (Motor,Drive); // transmite un semnal PWM catre Motor
Eroare_anterioara = Actual; // pastreaza valoarea actuala
}

Comanda PWM.

In exemplul de mai sus s-a utilizat o iesire PWM pentru a controla tensiunea de alimentare a
unui motor. Valoarea din interiorul functiei analogWrite() trebuie sa fie de tip intreg si cuprinsa intre 0 si
255. Valoarea Drive este redimensionata pentru acest interval.

Reglarea PID-ului.

Partea de reglare a controllerului PID nu este foarte simpla. Ea se realizeaza din coeficientii kP,
kI si kD.
Se procedeaza astfel:

• Initial coeficientii kI si kD se egaleaza cu 0 si se va utiliza numai coeficientul kP.

• Se va creste valoarea coeficientului kP pana cand raspunsul controllerului incepe si oscileaza. Cu


alte cuvinte, daca incerci sa reglezi un robot urmaritor de linie, se va mari valoarea kP pana cand
robotul incepe si „se plimba“ in jurul liniei, adica oscileaza. In acest moment s-a ajuns intr-un
punct in care robotul nu se comporta corect, asa ca trebuie sa miscorezi putin valoarea kP pana
cand robotul tinde sa oscileze dar nu foarte mult.

• Se va mari valoarea coeficientul kD care se comporta ca si cum ar anticipa inceputul unei


oscilatii.

• In final, se va mari foarte putin coeficientul kI care imbunatateste timpul de raspuns al


robotului.

Concluzie.

Scopul acestui tutorial este de a-ti realiza o scurta introducere in ceea ce se numeste Regulator
PID. Tutorialul acopera aspectele importante de functionare si este util atunci cand doresti sa realizezi o
comanda cat mai buna a unui proces. Ca exemplu, poti sa reglezi temperatura intr-o incinta sau a unui
recipient (dar nu este absolut necesar sa utilizezi metoda PID), poti sa reglezi viteza de rotatie a unui
motor sau poti mentine in echilibru un pendul invers.

http://www.robofun.ro/forum
http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Arduino si indicatoare pentru CPU si memoria RAM

In acest tutorial vei descoperi cum se poate construi un bord cu 2 indicatoare pentru activitatea
procesorului si capacitatea memoriei RAM. Vei descoperi cum se citesc cele 2 valori printr-un script
Python si cum se vor transmite, serial, catre o placa Arduino.
Ca indicatoare vei folosi 2 servomotoare conectate la o placa Arduino. In functie de valorile
primite pe seriala placa va modifica pozitia bratelor servomotoarelor.
Vei avea nevoie de urmatoarele componente:

• O placa Arduino - http://www.robofun.ro/arduino

• 2 servomotoare - http://www.robofun.ro/mecanice/servo

• Un alimentator extern Arduino


http://www.robofun.ro/surse_de_alimentare/alimentatoare/alimentator-extern-arduino

• Un breadboard - http://www.robofun.ro/breadboard

• Un cablu USB - http://www.robofun.ro/cabluri/cablu_usb_1_5m_male_a_male_b

Cum construiesc indicatorul ?

In tutorialul de fata indicatorul cu cele 2 servomotoare a fost realizat dintr-o bucata de carton
peste care s-a lipit o coala alba desenata cu 2 cadrane. S-au dat 2 gauri pe unde se fixeaza bratele
servomotoarelor iar servomotoarele s-au lipit cu banda dublu adeziva.
Panoul va arata ca in imaginea de mai jos.

http://www.robofun.ro/forum
Cum se conecteaza servomotoarele ?

Cele 2 servomotoare se vor conecta urmand tabelul de mai jos. Te vei folosi de breadboard
pentru a conecta alimentarile servomotoarelor.

Arduino 5V Servomotor 1 fir Rosu


Arduino GND Servomotor 1 fir Negru
Arduino digital 5 Servomotor 1 fir Alb
Arduino 5V Servomotor 2 fir Rosu
Arduino GND Servomotor 2 fir Negru
Arduino digital 6 Servomotor 2 fir Alb

Deoarece servomotoarele consuma mai mult decat poate oferi portul USB al calculatorului, vei
conecta alimentatorul extern de 9V in mufa placii Arduino.
In final vei obtine urmatorul montaj.

http://www.robofun.ro/forum
Codul sursa pentru Arduino.

Codul sursa pentru placa Arduino este listat mai jos. Se copiaza cu copy/paste si se incarca in
placa.

#include <Servo.h> //Used to control the Pan/Tilt Servos

//These are variables that hold the servo IDs.


char tiltChannel=0, panChannel=1;

//These are the objects for each servo.


Servo servoTilt, servoPan;

//This is a character that will hold data from the Serial port.
char serialChar=0;

http://www.robofun.ro/forum
void setup(){
servoTilt.attach(5); //The Tilt servo is attached to pin 5.
servoPan.attach(6); //The Pan servo is attached to pin 6.
servoTilt.write(70); //Initially put the servos both
servoPan.write(160); //at 90 degress.
//delay(5000);
Serial.begin(9600); //Set up a serial connection for 9600 bps.
}

void loop(){
while(Serial.available() <=0); //Wait for a character on the
serial port.
serialChar = Serial.read(); //Copy the character from the
serial port to the variable
if(serialChar == tiltChannel){ //Check to see if the character
is the servo ID for the tilt servo
while(Serial.available() <=0); //Wait for the second command
byte from the serial port.
servoTilt.write(180 - Serial.read()); //Set the tilt servo
position to the value of the second command byte received on the
serial port
}
else if(serialChar == panChannel){ //Check to see if the initial
serial character was the servo ID for the pan servo.
while(Serial.available() <= 0); //Wait for the second command
byte from the serial port.
servoPan.write(180 - Serial.read()); //Set the pan servo
position to the value of the second command byte received from the
serial port.
}
//If the character is not the pan or tilt servo ID, it is
ignored.
}

Codul sursa Python.

Codul sursa de mai jos se executa in Python 2.7

• Inainte de toate se va instala Python de la urmatoarea adresa:


http://www.python.org/download/releases/2.7/

• Se adauga linia de mai jos in System Path. In Windows 7 System Path se acceseaza din
Computer – Properties – Advanced System Settings – Advanced – Environment Variables.

Linia ce trebuie adaugata:

http://www.robofun.ro/forum
C:\Python27

• Asa arata System Path cu linia de mai sus.

• Se deschide IDLE(Python GUI) si din File – New Window se creaza fereastra in care vei copia
codul sursa de mai jos.

http://www.robofun.ro/forum
• Urmeaza sa modifici o linie care reprezinta defapt portul USB la care este conectata placa
Arduino.

usbport = 'COM7'

• In cazul de fata placa Arduino a fost conectata la portul COM7. Portul se poate identifica direct
din mediul Arduino.

• Urmeaza sa rulezi programul din Run – Run Module.

http://www.robofun.ro/forum
• Din acest moment script-ul Python va transmite catre placa Arduino 3 valori dintre care 2 sunt
valorile la care se vor deplasa bratele servomotoarelor. Un servomotor este responsabil cu
indicarea nivelului de utilizare al procesorului iar celalalt servomotor se ocupa cu indicarea
capacitatii memoriei RAM.

• In functie de sistemul de operare pe care ai instalat Python, este posibil sa primesti erori cu
privire la lipsa unor librarii. Adica este posibil ca unul din modulele serial, sys, time si psutil sa iti
lipseasca. In acest caz vei instala librariile lipsa.

http://www.robofun.ro/forum
#!/usr/bin/env python
import serial, sys, time, psutil

# Assign Arduino's serial port address


# Windows example
# usbport = 'COM3'
# Linux example
# usbport = '/dev/ttyUSB0'
# MacOSX example
# usbport = '/dev/tty.usbserial-FTALLOK2'
usbport = 'COM7'

# Set up serial baud rate


ser = serial.Serial(usbport, 9600, timeout=1)

def move(servo, angle):


'''Moves the specified servo to the supplied angle.

Arguments:
servo
the servo number to command, an integer from 1-4
angle
the desired servo angle, an integer from 0 to 180

(e.g.) >>> servo.move(2, 90)


... # "move servo #2 to 90 degrees"'''

if (0 <= angle <= 180):


ser.write(chr(255))
ser.write(chr(servo))
ser.write(chr(angle))
else:
print "Servo angle must be an integer between 0 and 180.\n"

def main():
while 1:
cpu_percent = psutil.cpu_percent(interval=1,
percpu=False)
mem_percent = psutil.phymem_usage().percent

cpu_angle = int(cpu_percent / 100 * 180)


mem_angle = int(mem_percent / 100 * 180)

cpu_str = "CPU: " + str(cpu_percent) + " % (" +


str(cpu_angle) + "/180)"
mem_str = "Mem: " + str(mem_percent) + " % (" +
str(mem_angle) + "/180)"

http://www.robofun.ro/forum
print cpu_str
print mem_str

move(0, cpu_angle)
move(1, mem_angle)

if __name__ == "__main__":
sys.exit(main())

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Arduino – monitorizare locuinta

In acest tutorial vei descoperi cum se poate monitoriza o locuinta utilizand un senzor de
temperatura, un senzor de efractie, o placa Arduino si un shield Wi-FI. Este o solutie simpla prin care
poti observa daca cineva ti-a deschis usa de la intrare sau daca temperatura este normala.
Exista o gama variata de senzori care pot detecta efractia (senzor magnetic, inductiv,
fotoelectric). In cazul de fata s-a utilizat, pe post de senzor de efractie, un buton brick. Daca butonul a
fost apasat se considera ca usa a fost deschisa si senzorul a fost declansat.
Toata informatia o vei citi cu ajutorul unui browser deoarece placa Arduino se va comporta ca
si un server web. Asta inseamna ca iti poti monitoriza locuinta chiar si de pe un smartphone cu
conexiune la internet.
Vei avea nevoie de urmatoarele componente:

• O placa Arduino - http://www.robofun.ro/arduino

• Un Arduino Wifi Shield - http://www.robofun.ro/arduino_wifi_shield

• Un alimentator extern Arduino


http://www.robofun.ro/surse_de_alimentare/alimentatoare/alimentator-extern-arduino

• Un senzor de presiune atmosferica si temperatura BMP085 Blue Edition


http://www.robofun.ro/senzori/vreme/senzor-presiune-atmosferica-bmp085-blue

• Un buton mare brick - http://www.robofun.ro/electronice/butoane/buton-mare-brick

• Un breadboard - http://www.robofun.ro/breadboard/breadboard_mini

• Fire de conexiune mama-tata si tata-tata - http://www.robofun.ro/cabluri

Cum se conecteaza senzorul si butonul brick ?

1. Infige shield-ul Wifi in pinii placii Arduino.


2. Conecteaza senzorul de presiune atmosferica si temperatura BMP085 Blue Edition dupa
urmatorul tabel:

http://www.robofun.ro/forum
Senzor pin VCC Arduino pin 3.3V
Senzor pin GND Arduino pin GND
Senzor pin SDA Arduino pin SDA
Senzor pin SCL Arduino pin SCL

3. Conecteaza butonul brick astfel:

Buton pin GND Arduino pin GND


Buton pin VCC Arduino pin 5V
Buton pin OUT Arduino pin D2

4. Conecteaza alimentatorul Arduino in mufa Jack.

http://www.robofun.ro/forum
Codul sursa.

Dupa ce ai realizat toate conexiunile fizice dintre senzori si placa Arduino, acum este momentul
sa incarci sketch-ul de mai jos.
Inainte de a incarca sketch-ul in Arduino cauta cele 2 linii si modifica-le conform routerului tau:

char ssid[] = "ssid";


char pass[] = "parola secreta";

Copiaza codul de mai jos cu copy/paste, incarca-l in placa Arduino si deschide Monitorul
Serial. La cateva momente de la deschiderea Monitorului Serial iti va aparea urmatoarea informatie.

Informatia de mai sus iti arata ca placa Arduino s-a conectat cu succes la router si este pregatita
sa primeasca cereri. IP-ul care apare in imagine este IP-ul pe care il tastezi in browser.
Poti sa deschizi orice browser si sa tastezi IP-ul in bara de link-uri. Asa iti va aparea informatia
dupa ce te-ai conectat la placa Arduino.

Utilizand un smartphone iti va aparea asa.

http://www.robofun.ro/forum
In acelasi timp poti observa in Monitorul Serial cateva detalii despre dispozitivul care se
conecteaza la placa Arduino.

http://www.robofun.ro/forum
#include <SPI.h>
#include <WiFi.h>
#include <Wire.h>

#define BMP085_ADDRESS 0x77 // I2C address of BMP085

const unsigned char OSS = 0; // Oversampling Setting

// Calibration values
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;

long b5;

char ssid[] = "ssid";


char pass[] = "parola secreta";

int status = WL_IDLE_STATUS;

boolean door_status = false;

WiFiServer server(80);

void setup() {
pinMode(2, INPUT);
// start serial port for debugging purposes
Serial.begin(9600);
Wire.begin();
bmp085Calibration();

// Attach interrupt to pin 2


attachInterrupt(0, setDoorStatus, FALLING);

// attempt to connect to Wifi network:


while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);

http://www.robofun.ro/forum
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
server.begin();
// you're connected now, so print out the status:
printWifiStatus();
}

void loop() {

// listen for incoming clients


WiFiClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a
newline
// character) and the line is blank, the http request has
ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connnection: close");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<meta http-equiv=\"refresh\"
content=\"5\">");

float temperature = bmp085GetTemperature(bmp085ReadUT());


float pressure = bmp085GetPressure(bmp085ReadUP());
float atm = pressure / 101325; // "standard atmosphere"
float altitude = calcAltitude(pressure);
client.print("Temperatura: ");
client.print(temperature);
client.print(" grade C.");
client.print(" Presiunea: ");
client.print(atm);
client.print(" atm.");

http://www.robofun.ro/forum
if (door_status == false){
client.println(" Usa este securizata");
}
else {
client.println(" Atentie! Usa a fost deschisa.");
}
client.println("<br />");
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disonnected");
}
}

void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());

// print your WiFi shield's IP address:


IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);

// print the received signal strength:


long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}

http://www.robofun.ro/forum
void setDoorStatus() {
door_status = true;
}

void bmp085Calibration()
{
ac1 = bmp085ReadInt(0xAA);
ac2 = bmp085ReadInt(0xAC);
ac3 = bmp085ReadInt(0xAE);
ac4 = bmp085ReadInt(0xB0);
ac5 = bmp085ReadInt(0xB2);
ac6 = bmp085ReadInt(0xB4);
b1 = bmp085ReadInt(0xB6);
b2 = bmp085ReadInt(0xB8);
mb = bmp085ReadInt(0xBA);
mc = bmp085ReadInt(0xBC);
md = bmp085ReadInt(0xBE);
}

// Calculate temperature in deg C


float bmp085GetTemperature(unsigned int ut){
long x1, x2;

x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;


x2 = ((long)mc << 11)/(x1 + md);
b5 = x1 + x2;

float temp = ((b5 + 8)>>4);


temp = temp /10;

return temp;
}

long bmp085GetPressure(unsigned long up){


long x1, x2, x3, b3, b6, p;
unsigned long b4, b7;

b6 = b5 - 4000;
// Calculate B3
x1 = (b2 * (b6 * b6)>>12)>>11;
x2 = (ac2 * b6)>>11;
x3 = x1 + x2;
b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;

// Calculate B4
x1 = (ac3 * b6)>>13;

http://www.robofun.ro/forum
x2 = (b1 * ((b6 * b6)>>12))>>16;
x3 = ((x1 + x2) + 2)>>2;
b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;

b7 = ((unsigned long)(up - b3) * (50000>>OSS));


if (b7 < 0x80000000)
p = (b7<<1)/b4;
else
p = (b7/b4)<<1;

x1 = (p>>8) * (p>>8);
x1 = (x1 * 3038)>>16;
x2 = (-7357 * p)>>16;
p += (x1 + x2 + 3791)>>4;

long temp = p;
return temp;
}

char bmp085Read(unsigned char address)


{
unsigned char data;

Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(address);
Wire.endTransmission();

Wire.requestFrom(BMP085_ADDRESS, 1);
while(!Wire.available())
;

return Wire.read();

http://www.robofun.ro/forum
}

// Read 2 bytes from the BMP085


// First byte will be from 'address'
// Second byte will be from 'address'+1
int bmp085ReadInt(unsigned char address)
{
unsigned char msb, lsb;

Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(address);
Wire.endTransmission();

Wire.requestFrom(BMP085_ADDRESS, 2);
while(Wire.available()<2)
;
msb = Wire.read();
lsb = Wire.read();

return (int) msb<<8 | lsb;


}

// Read the uncompensated temperature value


unsigned int bmp085ReadUT(){
unsigned int ut;

// Write 0x2E into Register 0xF4


// This requests a temperature reading
Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(0xF4);
Wire.write(0x2E);
Wire.endTransmission();

// Wait at least 4.5ms


delay(5);

// Read two bytes from registers 0xF6 and 0xF7


ut = bmp085ReadInt(0xF6);
return ut;
}

// Read the uncompensated pressure value


unsigned long bmp085ReadUP(){

unsigned char msb, lsb, xlsb;


unsigned long up = 0;

http://www.robofun.ro/forum
// Write 0x34+(OSS<<6) into register 0xF4
// Request a pressure reading w/ oversampling setting
Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(0xF4);
Wire.write(0x34 + (OSS<<6));
Wire.endTransmission();

// Wait for conversion, delay time dependent on OSS


delay(2 + (3<<OSS));

// Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)


msb = bmp085Read(0xF6);
lsb = bmp085Read(0xF7);
xlsb = bmp085Read(0xF8);

up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) |


(unsigned long) xlsb) >> (8-OSS);

return up;
}

void writeRegister(int deviceAddress, byte address, byte val) {


Wire.beginTransmission(deviceAddress); // start transmission to
device
Wire.write(address); // send register address
Wire.write(val); // send value to write
Wire.endTransmission(); // end transmission
}

int readRegister(int deviceAddress, byte address){

int v;
Wire.beginTransmission(deviceAddress);
Wire.write(address); // register to read
Wire.endTransmission();

Wire.requestFrom(deviceAddress, 1); // read a byte

while(!Wire.available()) {
// waiting
}

http://www.robofun.ro/forum
v = Wire.read();
return v;
}

float calcAltitude(float pressure){

float A = pressure/101325;
float B = 1/5.25588;
float C = pow(A,B);
C = 1 - C;
C = C /0.0000225577;

return C;
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Raspberry PI – Twitter

In acest tutorial vei descoperi cum se poate construi o aplicatie care publica automat un mesaj
pe Twitter. Spre exemplu, poti programa aplicatia sa publice automat temperatura procesorului,
temperatura masurata de un senzor extern sau chiar si o imagine de la o camera web.
Vei avea nevoie de urmatoarele componente:

• O placa Raspberry PI - http://www.robofun.ro/raspberry-pi-si-componente

• Un alimentator Raspberry PI
http://www.robofun.ro/surse_de_alimentare/alimentatoare/alimentator-raspberry-pi

• Un senzor de temperatura si umiditate SHT11


http://www.robofun.ro/senzori/vreme/senzor-temperatura-umiditate-raspberrypi-sht11

• O camera web compatibila

Cum se instaleaza Twython?

Primul pas este sa instalezi Twython, libraria Python care conecteaza aplicatia la Twitter.
Urmeaza sa inregistrezi o aplicatie in contul Twitter iar apoi vei scrie codul sursa care publica mesaje
sau imagini.
Logheaza-te in consola placii Raspberry PI si executa urmatoarele comenzi:

sudo apt-get update

sudo apt-get upgrade

sudo apt-get install python-setuptools

sudo easy_install pip

sudo pip install twython

Cum se inregistreaza o aplicatie Twitter ?

http://www.robofun.ro/forum
Daca vrei sa interactionezi cu Twitter din afara paginii web atunci este necesar sa inregistrezi o
aplicatie. Acceseaza link-ul urmator si completeaza campurile asemanator ca in imaginea de mai jos.
https://dev.twitter.com/apps/new

Dupa ce ai completat campurile de mai sus si ai creat aplicatia vei ajunge aici:

Vei folosi codurile Consumer key si Consumer secret in aplicatia Python. Din motive de
securitate acestea au fost ascunse din imagine.

http://www.robofun.ro/forum
In mod normal accesul aplicatiei este setat pe Read only. Asta inseamna ca nu vei putea publica
mesaje pe Twitter pana nu schimbi nivelul accesului.
Intra in tab-ul Settings si schimba accesul de la Read only la Read and Write.

Salveaza setarile si intoarce-te in tab-ul Details. In partea de jos a paginii apasa butonul Recreate
my access token.

Te vei folosi de Access token si Access token secret in aplicatia Python. Din motive de
securitate codurile au fost ascunse din imagine.

Prima aplicatie Python.

#!/usr/bin/env python
import sys
from twython import Twython
CONSUMER_KEY = 'aici vei scrie cheia de mai sus'
CONSUMER_SECRET = 'aici vei scrie cheia de mai sus'
ACCESS_KEY = 'aici vei scrie cheia de mai sus'
ACCESS_SECRET = 'aici vei scrie cheia de mai sus'

api =
Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET)

http://www.robofun.ro/forum
api.update_status(status=sys.argv[1])

Salveaza aplicatia si apeleaz-o sub urmatoarea forma:

sudo python Twitter.py 'Hello ! Am creat prima aplicatie Twitter.'

Cum se publica temperatura procesorului ?

#!/usr/bin/env python
import sys
from twython import Twython
import os

CONSUMER_KEY = 'aici vei scrie cheia de mai sus'


CONSUMER_SECRET = 'aici vei scrie cheia de mai sus'
ACCESS_KEY = 'aici vei scrie cheia de mai sus'
ACCESS_SECRET = 'aici vei scrie cheia de mai sus'

api =
Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET)

cmd = '/opt/vc/bin/vcgencmd measure_temp'


line = os.popen(cmd).readline().strip()
temp = line.split('=')[1].split("'")[0]
api.update_status(status='My current CPU temperature is '+temp+'
C')

Salveaza aplicatia si apeleaz-o sub urmatoarea forma:

sudo python cpuTempTwitter.py

http://www.robofun.ro/forum
Cum se publica imagini?

Pentru a publica imagini ai nevoie de o camera web compatibila. Camera se conecteaza in


portul USB. Consulta lista de camere compatibile de aici: http://elinux.org/RPi_USB_Webcams sau
tasteaza urmatoarea comanda:

ls /dev/video*

Daca apare video0 inseamna ca placa Raspberry PI detecteaza corect camera web.

#!/usr/bin/env python
import sys
from twython import Twython
import os

import pygame
import pygame.camera
from pygame.locals import *

pygame.init()
pygame.camera.init()
cam = pygame.camera.Camera("/dev/video0",(640,480))
cam.start()
image = cam.get_image()
pygame.image.save(image,'webcam.jpg')

CONSUMER_KEY = 'aici vei scrie cheia de mai sus'


CONSUMER_SECRET = 'aici vei scrie cheia de mai sus'

http://www.robofun.ro/forum
ACCESS_KEY = 'aici vei scrie cheia de mai sus'
ACCESS_SECRET = 'aici vei scrie cheia de mai sus'

photo = open('webcam.jpg','rb')
api =
Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET)
api.update_status_with_media(media=photo, status='I can post images
now ')

Salveaza aplicatia si apeleaz-o sub urmatoarea forma:

sudo python webcamTwitter.py

Cum se publica temperatura unui senzor SHT11?

Senzorul se conecteaza foarte simplu la placa Raspberry PI. Foloseste tabelul de mai jos.

Raspberry PI 5V SHT11 VCC


Raspberry PI GND SHT11 GND
Raspberry PI pin 13 SHT11 pin DAT
Raspberry PI pin 7 SHT11 pin SCK

http://www.robofun.ro/forum
#!/usr/bin/env python
import sys
from twython import Twython
from sht1x.Sht1x import Sht1x as SHT1x

dataPin = 13
clkPin = 7

sht1x = SHT1x(dataPin, clkPin, SHT1x.GPIO_BOARD)


temperature = sht1x.read_temperature_C()
humidity = sht1x.read_humidity()
dewPoint = sht1x.calculate_dew_point(temperature, humidity)
print("Temperature: {} Humidity: {} Dew Point:
{}".format(temperature, humidity, dewPoint))

CONSUMER_KEY = 'aici vei scrie cheia de mai sus'


CONSUMER_SECRET = 'aici vei scrie cheia de mai sus'
ACCESS_KEY = 'aici vei scrie cheia de mai sus'
ACCESS_SECRET = 'aici vei scrie cheia de mai sus'

api =
Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET)

api.update_status(status='Hi! This is an automatic message from a


Raspberry PI. The current temperature in Bucharest, Romania is: ' +
str(temperature) + ' C')

Salveaza aplicatia si apeleaz-o sub urmatoarea forma:

sudo python tempTwitter.py

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Raspberry PI – Emitator FM

In acest tutorial vei descoperi cum se poate transforma placa Raspberry PI intr-un emitator
FM. Poti asculta melodiile preferate pe o distanta relativ scurta in jurul placii (cativa zeci de metri) iar
pentru a realiza acest lucru este nevoie de o antena.
Antena va fi un fir lung de 20 cm care se conecteaza la pinul GPIO4 sau pinul 7, din imaginea
de mai jos.

http://www.robofun.ro/forum
Asa arata antena conectata la placa Raspberry PI:

Dupa ce ai conectat antena urmeaza sa conectezi alimentatorul de 5V si cablul de retea.


Logheaza-te la placa prin SSH si executa urmatoarele comenzi:

1. Creeaza fisierul pifm:

mkdir pifm

2. Schimba locatia:

cd pifm

3. Descarca arhiva care contine codul sursa si fisierul executabil:

sudo wget http://www.icrobotics.co.uk/wiki/images/c/c3/Pifm.tar.gz

4. Dezarhiveaza fisierul:

http://www.robofun.ro/forum
sudo tar -xzvf Pifm.tar.gz

5. Executa programul specificand melodia (sound.wav) si frecventa (100.0 Mhz)

sudo ./pifm sound.wav 100.0

http://www.robofun.ro/forum
Din acest moment, placa Raspberry PI a inceput sa transmita pe frecventa 100.0 Mhz melodia
sound.wav.
Porneste aparatul de radio (sau telefonul mobil daca are aceasta functie) si schimba frecventa
acestuia la 100 Mhz.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Cronometru cu Arduino

In acest tutorial vei descoperi cum se poate construi un cronometru simplu care poate masura
perioada de timp cuprinsa intre 2 evenimente. Cronometrul nostru va utiliza un senzor de distanta
Sharp ca declansator.
Daca un obiect trece prin fata senzorului suficient de aproape, atunci cronometrul este
declansat. Daca acelasi obiect trece din nou prin fata senzorului, atunci cronometrul este oprit.
Timpul cronometrat este afisat in Monitorul Serial. Cu acest cronometru poti masura timpi de
ordinul minutelor, secundelor sau chiar milisecundelor.
Ca idee, poti folosi cronometrul pentru a masura timpii robotilor urmaritori de linie.

Vei avea nevoie de urmatoarele componente:

• O placa Arduino - http://www.robofun.ro/arduino

• Un senzor de distanta Sharp


http://www.robofun.ro/senzori/infrarosu/senzor_sharp_%20GP2D120XJ00F

• Un cablu senzor 3 fire - http://www.robofun.ro/cablu_senzor_3_fire_12_7_cm

Cum se conecteaza senzorul ?

Senzorul de distanta Sharp se conecteaza la placa Arduino urmand tabelul de mai jos:

Arduino GND Senzor Sharp fir Negru


Arduino 5V Senzor Sharp fir Rosu
Arduino A0 Senzor Sharp fir Galben

Dupa ce ai conectat senzorul, vei obtine o imaginea ca cea de mai jos.

http://www.robofun.ro/forum
Codul sursa.

Acum este momentul sa incarci sketch-ul in placa Arduino. Copiaza codul sursa de mai jos
(copy/paste) si deschide Monitorul Serial.
Modul de functionare al cronometrului este simplu. Placa Arduino citeste in mod constant
valoarea senzorului de distanta. Daca valoarea s-a incadrat in pragul presetat din sketch, atunci
cronometrul s-a declansat. Cu alte cuvinte, daca senzorul a detectat (sa presupunem) un robot, atunci
placa Arduino incepe cronometrarea. Daca acelasi robot trece din nou prin fata senzorului, atunci placa
Arduino opreste cronometrarea si o afiseaza pe Monitorul Serial.
Iata un exemplu:

http://www.robofun.ro/forum
unsigned long start, finished, elapsed;
int IRpin = 0;
boolean stareSenzor = false;

void setup()
{
Serial.begin(9600);
Serial.println("Cronometru");
}
void displayResult()
{
float h, m, s, ms;
unsigned long over;
elapsed = finished - start;
h = int(elapsed / 3600000);
over = elapsed % 3600000;
m = int(over / 60000);
over = over % 60000;
s = int(over / 1000);
ms = over % 1000;
Serial.print("Timp brut: ");
Serial.println(elapsed);
Serial.print("Timp scurs: ");
Serial.print(h, 0);
Serial.print("h ");
Serial.print(m, 0);

http://www.robofun.ro/forum
Serial.print("m ");
Serial.print(s, 0);
Serial.print("s ");
Serial.print(ms, 0);
Serial.println("ms");
Serial.println();
}
void loop()
{
int pragSenzor = 300;
if (analogRead(IRpin) > pragSenzor && stareSenzor == false)
{
delay(500);
stareSenzor = true;
start = millis();
Serial.println("Start...");
}
if (analogRead(IRpin) > pragSenzor && stareSenzor == true) {
stareSenzor = false;
finished = millis();
delay(1000);
displayResult();
}
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Raspberry PI – Internet Radio

In acest tutorial vei descoperi cum se pot asculta posturi de radio online utilizand o placa
Raspberry PI. Iti va fi necesara o conexiune la internet prin cablu sau printr-un stick WiFI. Aplicatiile
pe care le vei instala iti vor permite sa schimbi posturile de radio, volumul si multe alte functii utilizand
o telecomanda de TV.
Vei avea nevoie de urmatoarele componente:

• O placa Raspberry PI
http://www.robofun.ro/raspberry-pi-si-componente/RASPBERRY-PI-B

• Un alimentator Raspberry PI
http://www.robofun.ro/raspberry-pi-si-componente/alimentator-raspberry-pi

• O pereche de casti compatibila cu mufa audio de pe placa

• Un senzor de telecomanda infrarosu brick


http://www.robofun.ro/bricks/senzor-telecomanda-infrarosu

• O telecomanda IR - http://www.robofun.ro/telecomenzi/telecomanda_ir

• Fire tata – mama - http://www.robofun.ro/cabluri/fire-conexiune-tata-mama-140mm

http://www.robofun.ro/forum
Cum se conecteaza senzorul de telecomanda infrarosu brick?

Primul lucru pe care il vei realiza este sa conectezi senzorul de telecomanda la portul placii
Raspberry PI. Foloseste firele mama – tata si conecteaza senzorul urmand tabelul si schema portului de
mai jos.

Raspberry PI 3.3V Senzor telecomanda brick VCC


Raspberry PI GND Senzor telecomanda brick GND
Raspberry PI GPIO4 Senzor telecomanda brick OUT

http://www.robofun.ro/forum
http://www.robofun.ro/forum
Instalarea aplicatiilor mpc si mpd

1. Efectueaza un update prin comanda:

sudo apt-get update

2. Instaleaza aplicatiile mpc si mpd:

sudo apt-get install mpc mpd

3. Adauga cateva posturi de radio:

mpc add http://stream-sd.radioparadise.com:8056

mpc add http://icecast2.rte.ie/ieradio1

mpc add http://listen.radionomy.com/the-smooth-lounge

mpc add http://radionova128.media.vistatec.ie:80

mpc add http://newstalk.fmstreams.com:8080

4. Le poti reda prin comanda:

mpc play <nr. postului de radio>

mpc play 1 pentru a reda primul post

5. Poti asculta postul de radio in perechea de casti.

6. Poti descoperi mai multe comenzi daca tastezi

mpc help

http://www.robofun.ro/forum
Cum poti schimba posturile de radio cu ajutorul telecomenzii ?

1. Instaleaza lirc prin comanda:

sudo apt-get install lirc

2. Incarca modulul lirc_rpi:

sudo modprobe lirc_rpi gpio_in_pin=4 gpio_out_pin=7

3. Realizeaza urmatorul test:

sudo mode2 -d /dev/lirc0

4. Apasa butoanele telecomenzii si vei obtine informatii cu privire la cadrele de pulsuri si spatii:

http://www.robofun.ro/forum
5. Configureaza fisierul hardware.conf prin comanda:

sudo nano /etc/lirc/hardware.conf

6. Modifica urmatoarele linii ca mai jos:

LIRCD_ARGS="--uinput"

DRIVER="default"

DEVICE="/dev/lirc0"

7. Acum este momentul sa inveti aplicatia lirc cu comenzile telecomenzii tale. Executa urmatoarea
comanda:

sudo /etc/init.d/lirc stop

8. Executa utilitarul si urmeaza instructiunile prin care iti stabilesti butoanele pe care le vei folosi:

irrecord -n -d /dev/lirc0 ~/lircd.conf

9. Daca vrei sa vezi fisierul de configuratie:

cd /home/pi

sudo nano lircd.conf

10. Muta fisierul in urmatoarea locatie:

sudo mv ~/lircd.conf /etc/lirc/lircd.conf

11. Porneste utilitarul lirc:

sudo /etc/init.d/lirc start

12. Executa urmatoarea comanda si apasa butoanele pe care le-ai setat mai devreme. Butoanele iti
vor aparea pe ecran:

http://www.robofun.ro/forum
irw

13. Executa urmatoarea comanda si copiaza codul sursa de mai jos. Pentru fiecare comanda se va
executa un proces. De exemplu pentru comanda programUP se va executa mpc next si mpc
play. Eticheta programUP reprezinta numele butonului ales la pasul 8. Daca ti-ai ales un alt
nume nu trebuie decat sa il schimbi in cod.

sudo nano ~/.lircrc

begin
prog = irexec
button = toggle
config = mpc repeat on
end
begin
prog = irexec
button = programUP
config = mpc next;mpc play
end
begin
prog = irexec
button = programDOWN
config = mpc prev;mpc play
end
begin
prog = irexec
button = KEY_1
config = mpc play 1
end
begin
prog = irexec
button = volumeUP
config = mpc volume +5
end
begin
prog = irexec
button = volumeDOWN
config = mpc volume -5
end

14. Acum poti testa daca aplicatia reda corect posturile de radio. Executa urmatoarea comanda si
apasa butoanele telecomenzii:

http://www.robofun.ro/forum
irexec -d

15. Si acum ca sa porneasca aplicatia la start-up deschide urmatorul fisier si adauga inainte de linia
exit 0 codul de mai jos.

sudo nano /etc/rc.local

#before exit 0 paste the following


(sleep 5;
sudo modprobe lirc_rpi gpio_in_pin=4 gpio_out_pin=7
sleep 5;
sudo -u pi irexec -d
#note: irexec can't run as root. Also note it shuts down if lircd
is restarted
)&

16. Tot ce iti ramane este sa restartezi placa Raspberry PI.

sudo reboot

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Raspberry PI – Internet Radio cu shield LCD 20x4

In partea a doua a tutorialului, vei descoperi cum se poate adauga un shield LCD20x4 care va
afisa informatii cu privire la postul de radio: nume, melodie, timpul de redare, volum, etc.
Informatiile sunt redate printr-un program Python care verifica, in acelasi timp, datele postului
de radio si actualizeaza informatiile pe ecranul LCD-ului.
Vei avea nevoie de un shield LCD 20x4 pentru Raspberry PI:
http://www.robofun.ro/shield-lcd-raspberry-pi-20x4?keyword=lcd&category_id=0

Primul pas este sa conectezi shield-ul LCD la portul GPIO al placii Raspberry PI. Shield-ul se
infige pur si simplu in port. Mufa 2x13 care permite conectarea este deja inclusa si lipita pe shield.

http://www.robofun.ro/forum
Placa expune in acelasi timp si toti pinii GPIO ai Raspberry PI (conectorul 2x13 care se
populeaza la cerere). Este necesar sa ai acces la port, pentru ca in urmatorul pas vei conecta senzorul de
telecomanda brick.
Ca si in tutorialul precedent, senzorul de telecomanda se conecteaza la portul GPIO in
urmatorii pini:

Raspberry PI 3.3V Senzor telecomanda brick VCC


Raspberry PI GND Senzor telecomanda brick GND
Raspberry PI GPIO4 Senzor telecomanda brick OUT

De aceasta data, vei conecta senzorul in mufa 2x13 de pe shield care respecta aceeasi ordine a
pinilor ca si portul GPIO. Pentru a te orienta cat mai bine urmeaza imaginea de mai jos.

http://www.robofun.ro/forum
Tot ce iti ramane este sa conectezi castile audio in mufa jack a placii, alimentatorul de 5V si
cablul de retea. Poti conecta o pereche de casti (nivelul audio este suficient de mare) sau o pereche de
boxe.
La aceasta data, versiunea de Raspbian nu necesita nicio modificare cu privire la setarile placii
de sunet. Setarile sunt default si sunetul functioneaza fara probleme.
Daca doresti mobilitate poti opta pentru un acumulator cu incarcare solara:
http://www.robofun.ro/raspberry-pi-si-componente/acumulator-incarcator-usb-solar
si un conector WI-PI:
http://www.robofun.ro/raspberry-pi-si-componente/oficial-wifi-raspberry-pi-wi-pi

Partea de conectare hardware este gata, urmeaza sa copiezi si sa executi codul Python listat mai
jos. Daca doresti ca programul sa se execute automat la pornire, trebuie sa deschizi cu editorul nano
urmatorul fisier:

http://www.robofun.ro/forum
sudo nano /etc/rc.local

Adauga urmatoarea linie:

sudo python /home/pi/lcd.py

imediat dupa linia:

sudo -u pi irexec -d

Executa un restart, iar dupa cateva momente iti va aparea pe ecranul lcd-ului postul de radio
detaliat. Textul va defila in asa fel incat sa poti citi mai multe informatii (in mod normal acestea nu
incap pe toata suprafata lcd-ului).

http://www.robofun.ro/forum
http://www.robofun.ro/forum
#!/usr/bin/python

import RPi.GPIO as GPIO


import time
import sys
from subprocess import check_output

stringToDivide = "Hello"

LCD_RS = 25
LCD_E = 24
LCD_D4 = 23
LCD_D5 = 17
LCD_D6 = 18
LCD_D7 = 22
LED_ON = 15

LCD_WIDTH = 20
LCD_CHR = True
LCD_CMD = False

http://www.robofun.ro/forum
LCD_LINE_1 = 0x80
LCD_LINE_2 = 0xC0
LCD_LINE_3 = 0x94
LCD_LINE_4 = 0xD4

E_PULSE = 0.00005
E_DELAY = 0.00005

def main():

GPIO.setmode(GPIO.BCM)
GPIO.setup(LCD_E, GPIO.OUT)
GPIO.setup(LCD_RS, GPIO.OUT)
GPIO.setup(LCD_D4, GPIO.OUT)
GPIO.setup(LCD_D5, GPIO.OUT)
GPIO.setup(LCD_D6, GPIO.OUT)
GPIO.setup(LCD_D7, GPIO.OUT)
GPIO.setup(LED_ON, GPIO.OUT)

lcd_init()
while 1:
output = check_output(["mpc", "play"])
output = output.replace('\n', ' ')
dim = len(output)
for x in range(0, dim-80):
lcd_byte(LCD_LINE_1, LCD_CMD)
lcd_string(output[x+0:x+20],1)
lcd_byte(LCD_LINE_2, LCD_CMD)
lcd_string(output[x+20:x+40],1)
lcd_byte(LCD_LINE_3, LCD_CMD)
lcd_string(output[x+40:x+60],1)
lcd_byte(LCD_LINE_4, LCD_CMD)
lcd_string(output[x+60:x+80],1)

checkOutput = check_output(["mpc", "play"])


checkOutput = checkOutput.replace('\n', ' ')

if checkOutput[0:10] == output[0:10]:
print "ok"
else:
break
time.sleep(0.4)

time.sleep(1)

def lcd_init():
lcd_byte(0x33,LCD_CMD)
lcd_byte(0x32,LCD_CMD)

http://www.robofun.ro/forum
lcd_byte(0x28,LCD_CMD)
lcd_byte(0x0C,LCD_CMD)
lcd_byte(0x06,LCD_CMD)

http://www.robofun.ro/forum
lcd_byte(0x01,LCD_CMD)

def lcd_string(message,style):
# style=1 Left justified
# style=2 Centred
# style=3 Right justified

if style==1:
message = message.ljust(LCD_WIDTH," ")
elif style==2:
message = message.center(LCD_WIDTH," ")
elif style==3:
message = message.rjust(LCD_WIDTH," ")

for i in range(LCD_WIDTH):
lcd_byte(ord(message[i]),LCD_CHR)

def lcd_byte(bits, mode):


# Send byte to data pins
# bits = data
# mode = True for character
# False for command

GPIO.output(LCD_RS, mode) # RS

# High bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x10==0x10:
GPIO.output(LCD_D4, True)
if bits&0x20==0x20:
GPIO.output(LCD_D5, True)
if bits&0x40==0x40:
GPIO.output(LCD_D6, True)
if bits&0x80==0x80:
GPIO.output(LCD_D7, True)

# Toggle 'Enable' pin


time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)

http://www.robofun.ro/forum
# Low bits
GPIO.output(LCD_D4, False)
GPIO.output(LCD_D5, False)
GPIO.output(LCD_D6, False)
GPIO.output(LCD_D7, False)
if bits&0x01==0x01:
GPIO.output(LCD_D4, True)
if bits&0x02==0x02:
GPIO.output(LCD_D5, True)
if bits&0x04==0x04:
GPIO.output(LCD_D6, True)
if bits&0x08==0x08:
GPIO.output(LCD_D7, True)

# Toggle 'Enable' pin


time.sleep(E_DELAY)
GPIO.output(LCD_E, True)
time.sleep(E_PULSE)
GPIO.output(LCD_E, False)
time.sleep(E_DELAY)

if __name__ == '__main__':
main()

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Arduino – senzor de umiditate pentru plante

In acest tutorial vei descoperi cum se poate programa o placa Arduino sa citeasca si sa afiseze,
printr-o matrice de led-uri, nivelul de umiditate din solul unei plante. Astfel, poti afla rapid daca planta
are nevoie de apa sau nu.
Daca planta are nevoie de apa, atunci matricea de led-uri va desena o expresie umana care
indica tristetea, iar daca planta are suficienta apa atunci expresia umana va fi fericita.
In ultima instanta, daca planta duce lipsa majora de apa, matricea va desena o figura moarta.
Pentru a realiza acest montaj vei avea nevoie de urmatoarele componente:

• O placa Arduino - http://www.robofun.ro/arduino

• O matrice de led-uri 8x8 - http://www.robofun.ro/electronice/led/matrice-leduri-8x8

• Un senzor de umiditate pe care il vei construi singur.

• Fire de conexiune diverse - http://www.robofun.ro/cabluri

Cum se conecteaza matricea de led-uri ?

Matricea de led-uri se conecteaza direct la porturile placii Arduino. Iti recomand totusi sa
conectezi cate un rezistor de 330 de ohmi in serie cu fiecare coloana a matricei. In felul asta vei proteja
porturile placii in eventualitatea unui scurt circuit.
Urmeaza diagrama de mai jos.

http://www.robofun.ro/forum
Cum se construieste senzorul de umiditate ?

Principiul de functionare al senzorului este simplu. Vei avea nevoie de 2 conductoare pe care le
vei infige direct in pamantul din ghiveci. Conductoarele formeaza un rezistor a carei rezistenta variaza
in functie de umiditatea pamantului.
Ca si conductoare poti folosi o placuta de cablaj dublu strat. Fiecare strat de cupru se comporta
ca un electrod.

http://www.robofun.ro/forum
Pe langa acest rezistor vei mai avea nevoie de un rezistor secundar pe care il vei determina si va
avea o valoare fixa. Vei conecta cele 2 rezistoare in configuratie de divizor de tensiune.
In primul rand vei masura rezistenta dintre cele 2 conductoare atunci cand pamantul este uscat
si cand este ud. In cazul de fata s-au masurat valori cuprinse intre 10 si 100 kΩ. Pentru rezistorul fix o
valoare de 30 kΩ este ok.
Scopul placii Arduino este sa culeaga tensiunea de pe rezistorul variabil (senzorul de umiditate).
Divizorul de tensiune este un senzor a carui iesire este liniara cu marimea de intrare, adica umiditatea.
Cu acest avantaj placa Arduino poate determina simplu si rapid, fara calcule necesare, care este
nivelul de umiditate din pamant.
Mai jos este diagrama senzorului de umiditate.

http://www.robofun.ro/forum
Sketch-ul pentru afisarea umiditatii ?

Tot ce iti ramane este sa incarci sketch-ul listat mai jos. Il copiezi cu Copy/Paste si il incarci
direct in placa Arduino. Dupa cateva momente, matricea va afisa starea plantei in functie de nivelul de
umiditate din sol. Daca nivelul este suficient de mare, matricea iti va indica aceasta stare printr-o
expresie fericita. Daca nivelul este mediu sau scazut, expresiile se vor schimba.

http://www.robofun.ro/forum
http://www.robofun.ro/forum
#include <FrequencyTimer2.h>

#define SAD { \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 1, 1, 0, 0, 1, 1, 0}, \
{0, 1, 1, 0, 0, 1, 1, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 0, 1, 1, 1, 1, 0, 0}, \
{0, 1, 1, 1, 1, 1, 1, 0}, \
{0, 1, 0, 0, 0, 0, 1, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0} \
}

#define HAPPY { \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 1, 1, 0, 0, 1, 1, 0}, \
{0, 1, 1, 0, 0, 1, 1, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 1, 0, 0, 0, 0, 1, 0}, \
{0, 1, 1, 1, 1, 1, 1, 0}, \
{0, 0, 1, 1, 1, 1, 0, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0} \
}

http://www.robofun.ro/forum
#define MEH { \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 1, 1, 0, 0, 1, 1, 0}, \
{0, 1, 1, 0, 0, 1, 1, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 1, 1, 1, 1, 1, 1, 0}, \
{0, 1, 1, 1, 1, 1, 1, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0} \
}

#define DEAD { \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{1, 0, 1, 0, 0, 1, 0, 1}, \
{0, 1, 0, 0, 0, 0, 1, 0}, \
{1, 0, 1, 0, 0, 1, 0, 1}, \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 0, 0, 0, 0, 0, 0, 0}, \
{0, 1, 1, 1, 1, 1, 1, 0}, \
{1, 0, 0, 0, 0, 0, 0, 1} \
}

byte col = 0;
byte leds[8][8];

// pin[xx] on led matrix connected to nn on Arduino (-1 is dummy to


make array start at pos 1)
int pins[17]= {-1, 5, 4, 3, 2, 14, 15, 16, 17, 13, 12, 11, 10, 9,
8, 7, 6};

// col[xx] of leds = pin yy on led matrix


int cols[8] = {pins[13], pins[3], pins[4], pins[10], pins[06],
pins[11], pins[15], pins[16]};

// row[xx] of leds = pin yy on led matrix


int rows[8] = {pins[9], pins[14], pins[8], pins[12], pins[1],
pins[7], pins[2], pins[5]};

const int numPatterns = 6;


byte patterns[numPatterns][8][8] = {
HAPPY, MEH, SAD, DEAD
};

int pattern = 0;

http://www.robofun.ro/forum
void setup() {
Serial.begin(9600);
// sets the pins as output
for (int i = 1; i <= 16; i++) {
pinMode(pins[i], OUTPUT);
}

// set up cols and rows


for (int i = 1; i <= 8; i++) {
digitalWrite(cols[i - 1], LOW);
}

for (int i = 1; i <= 8; i++) {


digitalWrite(rows[i - 1], LOW);
}

clearLeds();

// Turn off toggling of pin 11


FrequencyTimer2::disable();
// Set refresh rate (interrupt timeout period)
FrequencyTimer2::setPeriod(2000);
// Set interrupt routine to be called
FrequencyTimer2::setOnOverflow(display);

setPattern(pattern);
}

void loop() {
int pragUmiditateSuperior = 700;
int pragUmiditateMediu = 500;
int pragUmiditateInferior = 300;

int nivelUmiditate = analogRead(5);

Serial.println(nivelUmiditate);
if (nivelUmiditate > pragUmiditateSuperior) {
setPattern(0); // happy face
} else if (nivelUmiditate < pragUmiditateSuperior &&
nivelUmiditate > pragUmiditateMediu) {
setPattern(1); // meh face
} else if (nivelUmiditate < pragUmiditateMediu &&
nivelUmiditate > pragUmiditateInferior) {
setPattern(2); // sad face
} else if (nivelUmiditate < pragUmiditateInferior) {
setPattern(3); // dead face
}

http://www.robofun.ro/forum
delay(1000);
}

void clearLeds() {
// Clear display array
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
leds[i][j] = 0;
}
}
}

void setPattern(int pattern) {


for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
leds[i][j] = patterns[pattern][i][j];
}
}
}

// Interrupt routine
void display() {
digitalWrite(cols[col], LOW); // Turn whole previous column off
col++;
if (col == 8) {
col = 0;
}
for (int row = 0; row < 8; row++) {
if (leds[col][7 - row] == 1) {
digitalWrite(rows[row], LOW); // Turn on this led
}
else {
digitalWrite(rows[row], HIGH); // Turn off this led
}
}
digitalWrite(cols[col], HIGH); // Turn whole column on at once
(for equal lighting times)
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Arduino– detector de camp electromagnetic

In acest tutorial vei descoperi cum se poate realiza un detector de camp electromagnetic,
utilizand o placa Arduino si cateva componente pasive. Un detector de camp sau mai simplu EMF
(Electromagnetic Field) este bun, atunci cand vrei sa observi daca un aparat emite energie sub forma
undelor sau sa descoperi si sa urmaresti traseul firelor de curent ingropate in perete.
Am dat ca exemplu doar 2 situatii utile, dar il poti folosi si pentru amuzament: oare fantomele
emit energie ? Daca da, putem sa detectam energia ?
Pentru acest tutorial vei avea nevoie de urmatoarele componente:

• O placa Arduino - http://www.robofun.ro/arduino

• Fire de conexiune cu capete tata-tata


http://www.robofun.ro/cabluri/fire_conexiune_tata_tata-110mm

• Un breadboard - http://www.robofun.ro/breadboard

• Trei rezistoare de 1MΩ


http://www.robofun.ro/electronice/rezistoare/set_rezistoare-1_4W_500

• Un minidifuzor brick
http://www.robofun.ro/minidifuzor-brick?keyword=brick&category_id=0

Cum functioneaza?

Detectorul citeste in mod continuu valoarea semnalului care ajunge pe portul analog. Acest
semnal se induce in antena si ajunge in placa Arduino sub forma unei tensiuni electrice. Antena si cele 3
rezistoare (conectate in serie) formeaza un divizor rezistiv. Acest lucru este necesar pentru a atenua
semnalele foarte puternice.
Dupa ce a citit valoarea tensiunii, detectorul genereaza un sunet pentru ca tu sa poti aprecia
nivelul semnalului detectat. Daca semnalul este puternic atunci sunetul are o frecventa ridicata (sub
forma unei alarme) si o frecventa mica daca semnalul are un nivel redus.

http://www.robofun.ro/forum
Cum se conecteaza componentele electronice ?

Constructia detectorului este relativ simpla. Mai jos este data o diagrama care te va ajuta sa
conectezi cat mai simplu componentele electronice. Difuzorul brick se conecteaza astfel: firul negru la
pinul GND iar firul rosu la pinul digital 8 de pe placa Arduino.
Pentru antena ai nevoie de un fir de 5cm lungime.

http://www.robofun.ro/forum
http://www.robofun.ro/forum
Sketch-ul Arduino ?

Mai jos este listat codul sursa pe care il vei incarca in placa Arduino. Codul citeste nivelul de
semnal de pe intrarea analogica 5. Placa transmite aceasta valoare catre Monitorul Serial si genereaza un
ton de frecventa variabila, in functie de nivelul semnalului.
Odata ce ai incarcat programul, Monitorul Serial va arata ca mai jos. Acum este momentul sa
descoperi care dintre aparatele electronice genereaza campuri electromagnetice intense.

int inPin = 5;
int val = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
val = analogRead(inPin);
Serial.println(val);
tone(8, val);
delay(200);
noTone(8);
}

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Raspberry PI – ce se intampla acasa?

Ce se intampla daca pleci de acasa si doresti sa vezi ce se intampla in interior din cand in cand ?
Bineinteles, poti sa iti achizitionezi un sistem de securitate suficient de costisitor si complicat de utilizat.
In schimb, tu ai nevoie de un sistem de supraveghere simplu, care iti permite sa vezi imagini si
eventual sa le salvezi undeva pe disk pentru a le pastra sub forma unei arhive.
In acest tutorial vei descoperi cum se poate transforma placa Raspberry PI si camera oficiala
intr-o camera de supraveghere simpla.
Vei avea nevoie de urmatoarele componente:

• O placa Raspberry PI - http://www.robofun.ro/raspberry-pi-si-componente

• O camera video
http://www.robofun.ro/raspberry-pi-si-componente/camera-video-raspberrypi

• O carcasa special conceputa pentru camera


http://www.robofun.ro/raspberry-pi-si-componente/carcasa-curcubeu-camera-raspberry-pi

• Daca nu preferi carcasa atunci poti opta pentru un suport reglabil


http://www.robofun.ro/raspberry-pi-si-componente/suport-reglabil-camera-raspberry-pi

• Un alimentator Raspberry PI
http://www.robofun.ro/surse_de_alimentare/alimentatoare/alimentator-raspberry-pi

http://www.robofun.ro/forum
Asamblarea componentelor

Primul pas pe care trebuie sa il faci este sa asamblezi componentele. Intai vei asambla carcasa
sau suportul reglabil impreuna cu camera video. Carcasa curcubeu este alcatuita din placi plexiglass de
3mm grosime, 4 suruburi M3 si 4 piulite. Carcasa este gandita sa protejeze in totalitate camera, inclusiv
lentila.
Daca ai optat pentru carcasa curcubeu, te poti orienta dupa imaginile de mai jos. Nu uita sa
dezlipesti foliile protectoare de pe fiecare placa din plexiglass.

http://www.robofun.ro/forum
http://www.robofun.ro/forum
http://www.robofun.ro/forum
Urmeaza sa conectezi camera video in mufa dedicata a placii Raspberry. Cablul panglica se
orienteaza cu eticheta albastra catre mufa RJ45 (mufa de retea).

http://www.robofun.ro/forum
Ce software instalam?

Procesul de instalare a software-ului este simplu. Urmeaza pasii de mai jos.

1. Realizeaza un update executand cele 3 comenzi de mai jos:

sudo apt-get update

sudo apt-get dist-upgrade

sudo rpi-update

2. Descarca script-ul:

sudo wget -N
http://grustu.ch/share/rpi_cam/RPi_Cam_Browser_Control_Installer.sh

3. Ofera persmisiunea de acces userului (u+x = permite userului curent de a executa fisierul):

sudo chmod u+x RPi_Cam_Browser_Control_Installer.sh

4. Apeleaza script-ul cu argumentul de instalare:

sudo ./RPi_Cam_Browser_Control_Installer.sh install

5. Dupa instalare apeleaza din nou script-ul cu argumentul autostart_idle. Comanda va determina
pornirea automata a interfetei la startup:

sudo ./RPi_Cam_Browser_Control_Installer.sh autostart_idle

6. Deschide orice browser si tasteaza adresa de IP a placii Raspberry:

http://www.robofun.ro/forum
http://www.robofun.ro/forum
http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website /
blog, printare, sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul
sursa din acest document poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara
nici un fel de limitari.
Arduino – stabilizator giroscopic

In acest tutorial iti propun o varianta simpla de stabilizator giroscopic, ce se poate construi
cu urmatoarele componente:
• o placa Arduino
• un accelerometru+giroscop MPU6050
• un servomotor Medium
• o sursa de alimentare ce poate fi un acumulator Li-PO de 7.4V
• un breadboard
• fire de conexiune

La ce se poate utiliza un stabilizator giroscopic ?

Stabilizatorul giroscopic se poate utiliza pentru a echilibra o camera de filmat, pentru a


echilibra o drona ce se afla in zbor, un avion rc sau un robot de tip Segway. Am mentionat numai
cateva exemple, dar in continuare vei descoperi cum se poate construi un sistem simplu avand un
singur servomotor.
Stabilizatoarele giroscopice performante utilizeaza o gama variata de
motoare/servomotoare/motoare pas cu pas, in functie de aplicatie.
Pentru a demonstra principiul, in acest tutorial s-a folosit un singur servomotor care este
suficient cat sa echilibreze o camera web, spre exemplu.

http://www.robofun.ro/forum
Componentele minime necesare pentru stabilizator:

Ce este giroscopul ?

Giroscopul, in termeni simpli, este un mic dispozitiv folosit la masurarea si mentinerea


orientatiei. In ziua de azi, aproape orice telefon mobil are un mic giroscop pe care il utilizeaza
atunci cand se schimba pozitia ecranului din modul Portrait in Landscape. Avioanele, elicopterele
sau aparatele de zbor in general, utilizeaza giroscoape ce le ajuta la orientarea in spatiu.

Cum construiesti stabilizatorul giroscopic ?

Avand componentele de mai sus, urmeaza sa le conectezi folosind diagrama de mai jos. Poti
alimenta servomotorul fie din placa Arduino, fie dintr-un stabilizator de 5V separat, in functie de
servomotorul pe care l-ai ales si consumul acestuia.

http://www.robofun.ro/forum
Placuta accelerometru+giroscop se conecteaza la placa Arduino dupa urmatorul tabel:

Arduino pin 3.3V MPU 6050 pin VDD


Arduino pin 3.3V MPU 6050 pin VIO
Arduino pin GND MPU 6050 pin GND
Arduino pin SDA MPU 6050 pin SDA
Arduino pin SCL MPU 6050 pin SCL

Majoritatea servomotoarelor necesita alimentare printr-un stabilizator de 5V separat. Poti


opta pentru stabilizatorul de aici http://www.robofun.ro/bricks/stabilizator-5v (cel din imaginea de
mai sus).

http://www.robofun.ro/forum
Dupa ce ai realizat diagrama cu componentele giroscopului, vei obtine o schema
asemanatoare ca in imagine:

http://www.robofun.ro/forum
http://www.robofun.ro/forum
Ceea ce vezi in imagine sunt doar componentele de baza, iar tu vei avea nevoie de asemenea
de un cadru de sustinere, o carcasa sau o constructie mecanica simpla care poate fi utilizata la ceva
anume.
Un exemplu despre cum poti construi un robot care se echilibreaza singur pe 2 roti este aici:
http://letsmakerobots.com/node/1505
Un exemplu despre cum poti construi un robot care sa se echilibreze singur pe o minge, prin
intermediul a mai multor roti este aici:
http://spectrum.ieee.org/automaton/robotics/robotics-software/042910-a-robot-that-
balances-on-a-ball
Spre exemplu, folosind mai multe servomotoare (sau chiar si motoare) se poate construi un
robot care isi poate mentine echilibrul pe o minge. Acest tip de robot nu implica doar utilizarea unui
giroscop dar si a unui accelerometru. Utilizarea celor 2 senzori in paralel presupune fiziunea
acestora intr-o unitate de masura inertiala sau IMU.
In functie de robotul pe care doresti sa il realizezi, exista o gama variata de senzori IMU cu
grade de libertate de 6 sau 9:
http://www.robofun.ro/senzori/imu
Pentru tutorialul de fata este absolut necesar sa studiezi catusi de putin cum se
implementeaza o unitate de masura inertiala (IMU) si faptul ca acest lucru implica utilizarea unor
filtre (Kalman fiind unul foarte des utilizat).

Un material de studiu foarte util despre fuziunea senzorilor se afla aici:


http://web.mit.edu/scolton/www/filter.pdf
Pentru a simplifica lucrurile, afla ca exista deja implementari cu privire la filtrul Kalman
daca accesezi link-ul de mai jos:
https://github.com/TKJElectronics/KalmanFilter
Mai multe detalii despre implementarea filtrului Kalman (libraria de mai sus) pe o placa
Arduino se afla aici:
http://blog.tkjelectronics.dk/2012/09/a-practical-approach-to-kalman-filter-and-how-to-
implement-it/

http://www.robofun.ro/forum
Revenind la exemplul stabilizarii unei camere, nu avem nevoie decat de un servomotor. In
codul Arduino vei include libraria si vei declara un obiect servoToControl:

#include <Servo.h>
Servo servoToControl;

Pentru filtrul Kalman vei include libraria si vei declara 2 obiecte kalmanX si kalmanY:

#include "Kalman.h"
Kalman kalmanX;
Kalman kalmanY;

Pentru placa MPU-6050 vei include libraria <Wire> care permite placii sa comunice prin
magistrala I2C si vei declara cateva variabile cum ar fi adresa giroscopului si locatiile de memorie
prin care vei citi valorile giroscopului si ale accelerometrului.

#include <Wire.h>
uint8_t IMUAddress = 0x68; // adresa placutei MPU6050
int16_t accX;
int16_t accY;
int16_t accZ;
int16_t tempRaw;
int16_t gyroX;
int16_t gyroY;
int16_t gyroZ;

In rutina setup() vei initializa servomotorul atasandu-l la pinul 10 de pe placa Arduino si vei
porni monitorul serial la viteza de 115200 baud (prin care poti sa vizualizezi informatii sau datele
de iesire):

servoToControl.attach(10);
Serial.begin(115200);

Stabilizarea giroscopica

Stabilizarea presupune citirea accelerometrului si a giroscopului din placa MPU-6050,


calculul tangajului si a ruliului (pitch and roll) prin functii trigonometrice inverse si filtrarea
valorilor pentru o corectie buna.
In rutina loop() placa Arduino va citi acceleratia si giratia celor 3 axe de coordonate
respectiv in cod vor aparea variabilele: accX, accY, accZ, gyroX, gyroY, gyroZ.

http://www.robofun.ro/forum
uint8_t* data = i2cRead(0x3B,14);
accX = ((data[0] << 8) | data[1]);
accY = ((data[2] << 8) | data[3]);
accZ = ((data[4] << 8) | data[5]);
tempRaw = ((data[6] << 8) | data[7]);
gyroX = ((data[8] << 8) | data[9]);
gyroY = ((data[10] << 8) | data[11]);
gyroZ = ((data[12] << 8) | data[13]);

Tangajul si riuliul se calculeaza prin urmatoarele formule:

accYangle = (atan2(accX,accZ)+PI)*RAD_TO_DEG;
accXangle = (atan2(accY,accZ)+PI)*RAD_TO_DEG;

Limitele functiei atan2 sunt de la -π la π asa ca pentru a realiza conversia din radiani in
grade nu trebuie decat sa faci inmultirea cu: 57.295779513082320876798154814105 valoare care
este deja declarata in Arduino: RAD_TO_DEG.
Totusi nu este suficient deoarece trebuie sa iei in calcul si datele generate de catre giroscop,
pentru a utiliza cu succes filtrul Kalman.
Pentru mai multe detalii despre echilibrarea unei camere de filmat viziteaza urmatoarele
adrese:

http://www.instructables.com/id/Guide-to-gyro-and-accelerometer-with-Arduino-inclu/
http://www.instructables.com/id/Gyro-Camera-for-Motorcycle/

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Arduino – cereri HTTP de tip GET si POST

Despre HTTP.

HTTP este un protocol de comunicare intre un client si un server web. In cazul acestui
protocol comunicatia incepe de la client, dar sunt si situatii in care server-ul doreste sa initieze
comunicatia cu clientul, cum vei descoperi in continuare.
In urma unei cereri HTTP prin care un client initiaza o comunicatie cu un server, acesta din
urma proceseaza cererea si trimite un raspuns inapoi clientului (dar sunt situatii in care nu este
obligatoriu sa trimita raspuns, ci o proceseaza si atat).
HTTP, alaturi de alte protocoale este foarte cunoscut deoarece opereaza la nivelul 7 (nivelul
Aplicatie) din modelul OSI.
Pentru a afla mai multe detalii despre acest protocol sau despre modelul OSI acceseaza link-
urile de mai jos. Sunt foarte utile deoarece te ajuta sa iti aprofundezi cunostintele despre retelistica,
tipurile de protocoale ce opereaza in spatele unei conexiuni de internet, tipurile de retele ce se pot
construi, s.a.m.d.
http://support.microsoft.com/kb/103884
http://www.webopedia.com/quick_ref/OSI_Layers.asp
http://en.wikipedia.org/wiki/OSI_model
http://compnetworking.about.com/cs/designosimodel/g/bldef_osi.htm

GET si POST ?

Pana aici ai inteles ca un client initiaza o comunicatie HTTP cu un server web. Exista 2 tipuri de
cereri pe care un client le poate lansa catre un server si anume: GET si POST.
La ce te ajuta pe tine aceste cereri ? Cererile GET si POST te vor ajuta pe tine sa publici
informatii pe Internet, mai exact sa programezi o placa Arduino sa citeasca „ceva“ si sa faca vizibila
aceasta informatie pe Internet.
Ca si exemplu, sa ne gandim la o statie meteo construita cu o placa Arduino. Statia meteo este
alcatuita dintr-o multitudine de senzori ce sunt responsabili cu masurarea: temperaturii, presiunii,
umiditatii, vitezei/directiei vantului, cantitatii de ploaie, indicelui de confort termic. Asta este doar un
exemplu, dar sunt foarte multe situatii la care trebuie sa publici informatiile pe internet.
Urmatoarea intrebarea care se poate naste este: cum public aceste informatii pe internet si cum
pot sa le vizualizez, ce pot sa fac cu ele sau cum le stochez ?

http://www.robofun.ro/forum
Cererile GET si POST sunt doar o parte a raspunsului. Aceste cereri te ajuta sa initiezi
comunicatia intre statia meteo si server-ul web. Mai departe server-ul web proceseaza informatiile, le
publica pe o pagina web si le salveaza intr-o baza de date.
Server-ul web proceseaza cererile printr-o pagina scrisa in PHP. Pagina PHP initiaza conexiunea
cu baza de date, unde printr-un alt protocol salveaza informatiile procesare prin GET sau POST. Mai
departe, o alta pagina initiaza o conexiune cu baza de date, preia informatiile si le afiseaza sub forma
unui grafic.
Tocmai am descris, sumar, un serviciu de procesare a datelor online (mai este cunoscut sub
serviciu Cloud).
Totusi sunt 2 cereri si trebuie sa alegi doar una, dar inainte de a face lucrul asta trebuie sa vezi
din ce este compusa o cerere:

• in primul rand resursa solicitata de client. In cazul statiei meteo, resursa este o cale catre un
fisier PHP, fisierul care proceseaza cererea. (exemplu: /meteo/preiadate.php)

• tipul cererii: GET sau POST.

• Headere HTTP: sunt informatii standard transmite de client catre server. Practic aceste
informatii ajuta la identificarea clientului.

• Informatiile statiei meteo (temperatura, presiune, umiditate, s.a.m.d).

Ca sa intelegi cat mai usor trebuie sa te gandesti la un exemplu. Revenind la statia meteo,
aceasta este programata sa publice datele printr-un server. Statia meteo initiaza cereri la intervale
regulate de timp (spre exemplu, o data pe minut sau o data la 10 minute) prin GET sau POST. Practic
statia meteo specifica serverului urmatoarele lucruri: pagina php care proceseaza temperatura,
umiditatea, etc; ii spune serverului la ce tip de cerere sa se astepte, ii da de asemenea detalii despre
propria identitate (cine sunt eu, cu ce host vreau sa comunic) si in final ii transfera informatiile
(temperatura, umiditate, etc).
Daca statia meteo a realizat acest lucru si server-ul web preia corect datele, poti sa spui ca ai
reusit sa publici cu succes datele pe un server web.

Cum arata o cerere POST scrisa in cod Arduino ?

Iata mai jos cum o placa Arduino poate sa initializeze o cerere POST cu un server web. Asa
cum am explicat mai sus despre structura cererii HTTP, se poate observa acelasi lucru si in structura
cereri POST.
Mai exact, daca conexiunea cu serverul s-a realizat cu succes se va executa toata structura de
cod cuprinsa intre acolade. Clientul ii spune serverului la ce tip de cerere sa se astepte urmata de adresa
paginii php, apoi ii transmite mai multe detalii despre el insasi (adresa host-ului, tipul agentului:
Arduino, ce ar trebui sa faca server-ul dupa ce primeste datele adica sa inchida conexiunea, formatul
headerului http, dimensiunea informatiilor si in final informatia utila).

http://www.robofun.ro/forum
if (client.connect(server,80)) { // daca s-a conectat cu succes
Serial.println("connected"); // afiseaza pe Monitorul Serial
client.println("POST /pagethattakesdata.php HTTP/1.1"); //
transmite tipul cererii si adresa paginii care proceseaza cererea
client.println("Host: 192.168.2.1"); // adresa host-ului
client.println("User-Agent: Arduino/1.0"); // detalii despre
client
client.println("Connection: close"); // inchide conexiunea
client.println("Content-Type: application/x-www-form-
urlencoded"); // formatul headerului http
client.print("Content-Length: "); // dimensiunea informatiilor
client.println(sizeof(date));
client.println();
client.println(String(date)); // informatiile in sine sub forma
de String
client.println();
client.flush(); // inchide conexiunea
client.stop();
}

Cum proceseaza o pagina PHP cererea de mai sus ?

<?php
$file = 'date.txt';
$current = file_get_contents($file);
if (isset($_POST['data'])) {
$t = $_POST['data'];
$current .= $t;
file_put_contents($file, $current);
} else {
$t = 0;
$current .= $t;
file_put_contents($file, $current);
}
?>

Ce se intampla cu codul php de mai sus ? La fiecare cerere lansata de statia meteo (placa
Arduino) codul este executat si realizeaza urmatorul lucru: deschide un fisier text (a doua linie), preia
continutul (a treia linie), verifica daca exista o cerere POST care incepe cu 'data' (a patra linie), daca
exista atunci codul salveaza toata informatia intr-o variabila iar mai apoi variabila este stocata in
continutul fisierului si apoi rescris in fisierul text (liniile 5, 6 si 7).
Daca exista cereri dar care nu sunt identificate cu 'data', atunci codul scrie un 0 in fisierul text.
Acel 0 poate fi interpretat ca si eroare, daca este cazul.

http://www.robofun.ro/forum
Cum testez codul de mai sus ?

Primul lucru pe care trebuie sa il faci este sa instalezi un server Apache, un compilator PHP, o
si o baza de date MySQL. Pentru simplitate iti recomand utilitarul XAMPP, pe care il poti descarca si
instala de la adresa de mai jos:
http://www.apachefriends.org/ro/index.html
Ai la dispozitie varianta pentru Windows, Linux si Apple.
Descarca utilitarul Notepad++ si creeaza o pagina PHP. Copiaza codul sursa de mai sus in
pagina PHP.

Pagina PHP nou creata trebuie salvata la urmatoarea adresa unde ai instalat utilitarul xampp,
adica /xampp/htdocs/.

http://www.robofun.ro/forum
Daca server-ul este pornit si configurat corect, acesta poate primi cereri de la placa Arduino.
Asa cum am spus mai sus, tot ce face pagina php care serveste cererile este sa le salveze intr-un fisier
text.
Daca codul de mai sus functioneaza cu succes, fisierul text va arata sub urmatoarea forma:

Tot ce vezi acolo este o succesiune de valori salvate pe spatiul serverului, valori generate de o
placa Arduino avand un shield Wifi conectat in pinii acesteia si un senzor de temperatura care la
anumite intervale de timp genereaza si o eroare (valorile 85 prezente in fisier).

Ce poti realiza tu in continuare ?

Afla cum poti salva aceste valori intr-o baza de date ! De asemenea afla cum poti sa generezi un
grafic pe baza unui fisier text continand informatii cu privire la temperatura, umiditate, presiune.
Poti sa iti creezi un sistem dinamic de prelucrare a datelor studiind link-urile de mai jos:

http://blog.protoneer.co.nz/arduino-http-post-requests/
http://www.codetorment.com/2009/11/12/arduino-temperature-and-light-data-logging-and-
chartplotting-webmonitor/
http://forum.arduino.cc/index.php?topic=155218.0
https://github.com/ericbenwa/POST-Arduino-Data-Wireless

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Arduino – software PWM

Ce este PWM ?

Termenul de PWM provine din limba engleza de la Pulse Width Modulation ceea ce inseamna
Modulatia Pulsurilor in Lungime si este o tehnica de a simula un semnal analogic folosindu-te de un
semnal digital.
Semnalul digital poate lua doar 2 stari: ON sau OFF ; „1“ sau „0“ ; 5V sau 0V. Un semnal
PWM te ajuta sa obtii o multime de valori cuprinse intre 5 si 0V. De exemplu poti obtine 2.5V ceea ce
inseamna ca poti ajusta luminozitatea unui LED sau viteza de rotatie a unui motor.
Semnalele PWM sunt utile in urmatoarele situatii: atunci cand vrei sa creezi jocuri de lumini
daca ai la dispozitie o multitudine de LED-uri sau matrici, atunci cand vrei sa variezi viteza de rotatie a
unui motor sau cand vrei sa controlezi unghiul unui servomotor. Am enumerat situatiile des intalnite
dar pot exista si altele: daca doresti sa controlezi automat temperatura unei camere si sa folosesti un
element de incalzire al carui raspuns sa fie proportional cu semnalul PWM, ori doresti sa produci sunete
de frecvente diferite folosindu-te de un difuzor sau vrei sa ajustezi automat tensiunea unei surse de
alimentare.
Semnalele PWM sunt foarte utile in diverse situatii iar placa Arduino nu duce lipsa de aceasta
functie. O placa Arduino UNO poate genera pana la 6 semnale PWM prin pinii 3, 5, 6, 9, 10 si 11
deoarece microcontroller-ul este echipat cu un modul hardware special care se ocupa exclusiv de aceste
semnale.
Pentru a afla mai multe detalii despre metoda PWM acceseaza link-urile de mai jos:
http://arduino.cc/en/Tutorial/PWM#.UxJAW_l_uSo
http://arduino.cc/en/Reference/analogWrite#.UxJFbvl_uSo
http://web.cecs.pdx.edu/~gerry/class/EAS199A/topics/pdf/PWM_output_Arduino.pdf

Totusi placa Arduino poate genera pana la 6 semnale si sunt cazuri cand doresti sa generezi un
numar mai mare. Spre exemplu un hexapod are un numar foarte mare de servomotoare care il pun in
miscare, iar un robot biped ajunge pana la 32 de servomotoare care concomitent lucreaza si il ajuta sa
isi mentina echilibrul.
In situatiile de mai sus cei 6 pini PWM sunt insuficienti asa ca vei avea nevoie de mai multi. Aici
iti vine in ajutor o tehnica de a genera semnale PWM nu hardware (folosindu-te de cei 6 pini) ci prin
software. Asta inseamna ca, teoretic, orice pin digital de intrare/iesire de pe placa Arduino poate genera
semnale PWM si asta ti-ar creste semnificativ numarul de pini.

http://www.robofun.ro/forum
De ce teoretic si nu practic ? Se pare ca metoda software PWM este mai greu de inteles si putin
mai complexa. Daca prin metoda hardware PWM (cei 6 pini enumerati mai sus) te foloseai de cateva
functii si instructiuni, la metoda software PWM este necesar sa scrii linie cu linie codul din spatele
functiilor.

Cum generez un semnal PWM cu placa Arduino ?

Exemplu: Cum pot sa comand un motor brushless cu controller ESC (Electronic Speed
Controller):

#include <Servo.h>

Servo esc;
int throttle = 0;
void setup()
{
Serial.begin(9600);
esc.attach(6);
delay(15);
esc.write(30);
delay(2000);
}

void loop()
{
for (throttle = 0; throttle <=179; throttle++ ) {
esc.write(throttle);
Serial.println(throttle);
delay(400);
}
for (throttle = 179; throttle >=0; throttle-- ) {
esc.write(throttle);
Serial.println(throttle);
delay(400);
}
}

Exemplul de mai sus te poate ajuta sa controlezi viteza de rotatie a unui motor brushless
folosindu-te de un controller ESC. Controller-ul este responsabil cu intrepretarea semnalului PWM
provenit de la placa Arduino si alimentarea motorului brushless.
Te vei folosi de libraria Servo pentru a realiza acest lucru.
Prima linie de cod, directiva preprocesor, ii spune compilatorului ce librarie vei folosi in
program, respectiv libraria Servo.h
A doua linie: se declara obiectul esc adica motorul pe care placa Arduino il va comanda.

http://www.robofun.ro/forum
A treia linie: se declara variabila throttle si se initializeaza cu 0. Variabila te va ajuta sa variezi
viteza de rotatie a motorului (vei vedea mai jos cum).
In rutina setup () se initializeaza Monitorul Serial, se ataseaza motorul esc la pinul 6 (unul din
cei 6 pini PWM), se executa o intarziere de 15 milisecunde, se transmite catre motor un semnal PWM
cu valoarea 30 si se asteapta 2 secunde.
De ce acest semnal PWM ? Raspunsul este ca ESC-urile (controller-ul electronic de viteza)
necesita o armare inainte de a porni motorul. Armarea ii permite controllerului sa isi calibreze plaja de
reactie. Aceasta plaja poate varia de la controller la controller (nu exista un standard) dar poate fi
descoperita usor. Plaja de reactie inseamna minimul si maximul pe care il poate atinge motorul.
In rutina loop() se executa o bucla for() care incrementeaza variabila throttle de la 0 la 179 in
pasi de cate o unitate.
Linia esc.write(throttle) transmite motorului viteza de rotatie, astfel ca la 0 motorul nu se
misca deloc iar la 179 motorul se roteste cu viteza maxima. Practic bucla for() creste treptat viteza de
rotatie a motorului.
Ultimele 2 linii din bucla transmite valoarea vitezei catre Monitorul Serial si introduce o
intarziere de 400 de milisecunde in asa fel incat panta de acceleratie a motorului sa nu fie abrupta.
A doua bucla for() scade treptat viteza motorului in aceeasi maniera ca si prima.
Pentru a afla mai multe detalii despre motoarele brushless si tehnica de comanda a acestora
acceseaza link-urile de mai jos:
http://techvalleyprojects.blogspot.ro/2012/06/arduino-control-escmotor-tutorial.html
http://dronesandrovs.wordpress.com/2012/11/24/how-to-control-a-brushless-motor-esc-
with-arduino/

Codul sursa de mai sus este perfect functional si poate fi utilizat cu succes dar exista un
dezavantaj si anume ca poti genera pana la 6 semnale PWM, ceea ce nu te ajuta foarte mult daca doresti
sa comanzi un numar si mai mare de: motoare de curent continuu, servomotoare sau LED-uri.

Cum generez un semnal PWM software ?

Tehnica de generare a semnalului PWM software este putin mai complexa decat exemplul
anterior. La inceput placa porneste cu iesirea PWM in „0“ logic. Urmeaza ca placa Arduino sa activeze
un timer, acesta sa contorizeze iar cand se „umple“ sau cand a ajuns la capatul contorizarii, timer-ul sa
genereze o intrerupere.
Ce este o intrerupere ?
Orice microcontroller executa un program, o rutina, genereaza semnale, citeste date, afiseaza
informatii pe un display, comanda o turbina, s.a.m.d.
In timpul functionarii programului pot aparea situatii neprevazute. Iata un exemplu: sa
presupunem ca placa Arduino executa un program care este in mare parte o rutina oarecare. Dar din
cand in cand placa Arduino trebuie sa raspunda prompt la o intamplare, la ceva care apare din exterior
sau din interior si sa faca lucrul asta fara sa deranjeze intr-un fel executia programului.

http://www.robofun.ro/forum
Raspunsul pentru acest gen de situatii este sa folosesti intreruperile microcontrollerului. Pentru
fiecare intrerupere nou aparuta sau situatie, microcontroller-ul sare rapid din executia programului apoi
executa programul special de intrerupere (intr-un timp foarte rapid) si apoi se intoarce de unde a plecat
si isi continua treaba de la care a plecat.
In stilul asta placa Arduino executa programul principal dar in acelasi timp poate executa si
anumite coduri specifice intreruperii.

Iata un exemplu de generare a unui semnal PWM folosind un timer si o intrerupere:

#include <avr/interrupt.h>
#include <avr/io.h>

// Pinul pe care dorim sa generam semnal PWM


#define PWM_PIN 7

#define PWM_TICK_SIZE 50 // uS

#define PWM_PERIOD 20000 // uS (20ms)

#define PWM_TICK_PERIOD (int) (PWM_PERIOD / PWM_TICK_SIZE)

volatile unsigned int timer2_counter = 0;


volatile unsigned int timer2_trigger_low = 150;

ISR(TIMER2_OVF_vect) {
timer2_counter++;
if(timer2_counter == timer2_trigger_low) {
digitalWrite(PWM_PIN, LOW);
} else if(timer2_counter >= PWM_TICK_PERIOD) {
timer2_counter = 0;
digitalWrite(PWM_PIN, HIGH);
}

TCNT2 = 0;
}

void setup() {
pinMode(PWM_PIN, OUTPUT);
TIMSK2 = 1<<TOIE2; // Timer 2 overflow interrupt enable
TCNT2 = 0;
}

http://www.robofun.ro/forum
void loop() {
timer2_trigger_low = 100;
delay(2000);
timer2_trigger_low = 200;
delay(2000);
timer2_trigger_low = 300;
delay(2000);
timer2_trigger_low = 400;
delay(2000);
timer2_trigger_low = 300;
delay(5000);
timer2_trigger_low = 200;
delay(2000);
}

Cum functioneaza codul ?


Primele doua linii, directivele preprocesor, includ librariile responsabile cu intreruperile
microcontrollerului Atmega si registrii acestuia. Mai jos vei vedea cum se acceseaza in mod direct
anumiti registrii din microcontroller si cum se activeaza timer-ul + intreruperea.
A treia linie: defineste pinul pe care placa Arduino va genera semnalul PWM. A fost ales un pin
pe care nu se poate genera semnal PWM hardware.
Prin urmatoarele 3 linii se definesc cativa parametrii: primul parametru PWM_TICK_SIZE iti
spune ca timer-ul va contoriza pentru 50 de microsecunde, al doilea parametru PWM_PERIOD iti
spune care este perioada totala a semnalului PWM iar al treilea parametru PWM_TICK_PERIOD se
obtine din raportul celorlalti 2 parametrii si iti arata cand se va reseta semnalul PWM din „1“ logic in
„0“ logic.
Urmatoarele 2 linii initializeaza 2 variabile dintre care una va mentine valoarea contorului
(timer-ul) iar cealalta mentine valoarea la care semnalul PWM sa isi schimbe nivelul logic.
Functia ISR este apelata ori de cate ori timer-ul genereaza o intrerupere adica ori de cate ori
timer-ul a terminat de contorizat. La fiecare intrerupere gestionata de catre microcontroller se
incrementeaza timer2_counter.
Pentru inceput tensiunea pe pinul 7 PWM este de 0V. Apoi se testeaza daca variabila
incrementata este egala cu parametrul timer2_trigger_low. Daca este egala atunci pinul 7 este in
continuare mentinut cu 0V.
Se continua incrementarea timp in care tensiunea pinului PWM este de 0V. Tensiunea se
schimba in 5V atunci cand variabila incrementata este mai mare sau egala decat parametrul
PWM_TICK_PERIOD. Tensiunea ramane la 5V, contorul de timp este resetat si din nou incrementat.
Din nou se incrementeaza contorul la fiecare intrerupere, timp in care tensiunea pe pinul PWM
ramane la 5V. Tensiunea se schimba in 0V atunci cand se produce egalitatea intre variabila incrementata
si parametrul timer2_trigger_low.
In acest fel s-a generat un semnal PWM folosindu-te de un timer si o intrerupere.
In rutina setup() se initializeaza pinul PWM, intreruperea timerului 2 prin scrierea bitului
TOIE2 cu valoarea logica „1“ din registrul TIMSK2 (am mentionat ca vei afla cum se acceseaza in mod

http://www.robofun.ro/forum
direct un registru) si se reseteaza valoarea contorului pin scrierea registrului TCNT2 = 0;
Pentru a demonstra ca semnalul PWM isi poate schimba factorul de umplere (lungimea
nivelului „1“), in bucla loop() se modifica treptat la intervale de 2 secunde valoarea parametrului
timer2_trigger_low. Asta inseamna ca nivelele semnalului PWM se vor declansa la momente diferite
(100, 200, 300, 400, 300, 200).
Daca vrei sa studiezi in detaliu sistemul de intreruperi al microcontrollerului Atmega328 de pe
placa Arduino urmeaza link-urile de mai jos:
http://courses.cs.washington.edu/courses/csep567/10wi/lectures/Lecture7.pdf
http://www.avr-tutorials.com/interrupts/about-avr-8-bit-microcontrollers-interrupts
http://www.avrfreaks.net/index.php?
name=PNphpBB2&file=viewtopic&t=89843&start=all&postdays=0&postorder=asc
http://www.avr-tutorials.com/interrupts/avr-external-interrupt-c-programming
http://playground.arduino.cc/Code/Interrupts#.UxJiTvl_uSo

Tot ce iti ramane de facut este sa descoperi cum poti genera mai multe semnale PWM
folosindu-te de aceeasi tehnica software de generare a semnalelor. In principiu trebuie sa ai in vedere
declararea in plus a unor parametrii, cate un set pentru fiecare pin PWM si rescrierea rutineri de
intrerupere in asa fel incat sa fie capabila sa gestioneze mai multi pini.
Acest lucru iti da un avantaj pentru ca poti creea miscari complexe cu servomotoare, poti
controla motoare la viteze diferite (poti creea o tractiune diferentala in care, pe scurt, rotile unei masini
trebuie sa se roteasca la viteze diferite atunci cand masina vireaza intr-o curba) sau poti creea un joc de
lumini cu fiecare LED controlat independent.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Arduino – comparatorul intern

Ce este comparatorul ?

In electronica digitala, comparatorul este un mic dispozitiv care compara 2 tensiuni sau curenti
si produce un semnal care iti spune care din cele doua este mai mare. Acesta este rolul de baza al
comparatorului. El este format din doua intrari analogice si o singura iesire digitala. Intrarile analogice
sunt marcate cu V+ si V-, iar iesirea digitala cu Vo. Iesirea poate genera doar 2 stari si anume: „1“ logic
daca intrarea V+ este mai mare decat intrarea V- sau poate genera „0“ logic daca intrarea V+ este mai
mica decat intrarea V-.
In aceeasi maniera functioneaza si comparatorul placii Arduino si daca vrei sa descoperi in ce
situatii poti sa il folosesti, atunci viziteaza link-urile de mai jos:

http://www.electronicsblog.net/very-simple-arduino-capacitance-meter-using-16-bit-timer-and-
analog-comparator/

Poti sa iti construiesti un capacimetru folosind o placa Arduino, comparatorul intern si timer-ul
placii sau un osciloscop digital:

http://www.instructables.com/id/Girino-Fast-Arduino-Oscilloscope/?ALLSTEPS

Afla ca exista si o librarie Arduino care te poate ajuta foarte mult in proiectele tale:

http://www.leonardomiliani.com/2012/analogcomp-una-libreria-per-gestire-il-comparatore-
analogico/?lang=en

Cum genereaza intreruperi comparatorul intern ?

Pe langa faptul ca poate compara 2 semnale asta fiind functia lui, comparatorul poate genera si
intreruperi. Asta inseamna ca poti scrie un program care sa execute „ceva“, iar atunci cand apare o

http://www.robofun.ro/forum
situatie exterioara, spre exemplu: iesirea unui senzor a depasit o valoare de referinta, atunci placa
Arduino poate sa raspunda prompt la intrerupere, opreste executia normala a programului si executa
codul asociat intreruperii.
In programarea de nivel scazut (low level) poti sa spui ca microcontroller-ul executa rutina ISR
(Interrupt Service Routine).
Iata cum arata o rutina ISR care deserveste o intrerupere generata de comparatorul intern:

ISR(ANALOG_COMP_vect)
{
digitalWrite(13, !digitalRead(13));
}

Structura intreruperii este simpla si anume: ISR este o instructiune macro pe care compilatorul
o detecteaza automat si o interpreteaza ca si rutina ISR. Asa ca ori de cate ori comparatorul intern
genereaza o intrerupere, microcontroller-ul opreste executia normala a programului si executa toate
liniile de cod din aceasta rutina. Apoi se intoarce de unde a plecat si continua cu executia programului
principal.
Link-ul de mai jos te ajuta sa descoperi si alte intreruperi pe care le poti gestiona cu rutina ISR,
pentru ca nu doar comparatorul intern poate genera intreruperi, dar mai sunt si alte module interne:

http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

Cum se configureaza comparatorul intern ?

La nivel de cod, configurarea comparatorului este simpla. Configurarea este totusi necesara
pentru functionarea corecta a comparatorului. Tot ce trebuie sa faci este sa accesezi un registru si sa
setezi anumiti biti. Lucrul asta il vei face in rutina setup(). Spre exemplu iata cum se configureaza
comparatorul intern:

void setup() {
pinMode(7,INPUT);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Serial.begin(9600);
ACSR = B01011010;
}

Linia de cod cu care nu esti tocmai familiar este ACSR = B01011010. Indicatorul B din fata
sirului de biti ii indica compilatorului ca are de-a face cu un sir de biti si nu o valoare numerica. ACSR
este registrul de status si control al comparatorului analogic si are urmatoarea structura de biti:
ACD, ACBG, ACO, ACI, ACIE, ACIC, ACIS1, ACIS0

http://www.robofun.ro/forum
Fiecare bit are rolul lui. Daca te uiti la linia de cod de mai sus vei observa ca placa seteaza niste
biti pe „1“ si alti biti ii pastreaza pe „0“.
Prin setarea bitului ACBG, placa Arduino va selecta singura tensiunea de referinta pentru
intrarea pozitiva a comparatorului. Adu-ti aminte ca un comparator are 2 intrari (una pozitiva, cealalta
negativa) si o iesire. Practic placa Arduino va alege singura o tensiune de prag pentru intrarea pozitiva
care este de aproximativ 1,2V. Intrarea negativa este accesibila la pinul digital 7. La acest pin tu vei aplica
o tensiune analogica pe care doresti ca placa Arduino sa o compare cu tensiunea de referinta (1,2V).
Prin setarea bitului ACI se sterge bitul de flag al intreruperii. Lucrul asta te ajuta pentru ca in
primul moment de functionare al placii pot aparea intreruperi false si chiar daca vor aparea, bitul flag
este sters deocamdata si placa nu raspunde la aceste intreruperi.
Prin setarea bitului ACIE (Analog Comparator Interrupt Enable) se activeaza intreruperea
comparatorului intern asa ca ori de cate ori apare o tranzitie sau o schimbare la iesirea comparatorului,
acesta va genera o intrerupere, iar placa Arduino va executa rutina ISR.
Prin setarea bitilor ACIS1 si ACIS0, comparatorul va genera intreruperi pe frontul descrescator
al iesirii, adica atunci cand iesirea trece din „1“ in „0“ logic.

Totusi ce valori are iesirea comparatorului ?


Intotdeauna iesirea va fi „1“ daca tensiunea de referinta este mai mare decat tensiunea aplicata
pe pinul digital 7. In schimb iesirea comuta in „0“ daca tensiunea de pe pinul 7 creste si depaseste
tensiunea de referinta. Cu alte cuvinte, cand are loc aceasta tranzitie din „1“ in „0“, comparatorul
genereaza o intrerupere, iar placa Arduino executa rutina ISR asociata.

Cum testez codul pe o placa Arduino ?

Tot ce trebuie sa faci este sa incarci sketch-ul de mai jos. Copiaza codul sursa si incarca-l in
placa Arduino.

void setup() {
pinMode(7,INPUT);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
Serial.begin(9600);
ACSR = B01011010;
}

void loop() {
}

http://www.robofun.ro/forum
ISR(ANALOG_COMP_vect) {
digitalWrite(13, !digitalRead(13));
}

Folosindu-te de un fir, conecteaza pinul marcat cu 5V la pinul digital 7 (atentie mare sa nu il


conectezi la pinul VIN deoarece poate duce la defectarea placii). Apoi incepe si comuta firul de pe pinul
5V pe pinul GND. De fiecare data cand comuti, poti observa ca se aprinde led-ul, adica se executa linia
de cod digitalWrite(13, !digitalRead(13)); din interiorul rutinei ISR.

Iata un alt exemplu:

void setup() {
Serial.begin(9600);
ACSR =
(0 << ACD) |
(0 << ACBG) |
(0 << ACO) |
(1 << ACI) |
(1 << ACIE) |
(0 << ACIC) |
(1 << ACIS1) |
(1 << ACIS0);

pinMode(13, OUTPUT);
pinMode(9, OUTPUT);
}

void loop() {

if(ACSR & (1 << ACO))


digitalWrite(9, HIGH);
else
digitalWrite(9, LOW);

delay(100);
}

ISR(ANALOG_COMP_vect ) {
digitalWrite(13, !digitalRead(13));
}

De aceasta data poti observa o forma noua de scriere a registrului ACSR. Spre deosebire de
sketch-ul precedent acesta compara nivelele semnalelor aduse pe pinii digitali 6 si 7 (mai sus programul
compara tensiunea de pe pinul 7 cu tensiunea de referinta interna).

http://www.robofun.ro/forum
Spre exemplu, poti folosi acest sketch pentru a regla temperatura intr-o incinta. Pentru asta vei
avea nevoie de urmatoarele componente:

• O placa Arduino UNO

• Un tranzistor TIP122 brick - http://www.robofun.ro/bricks/tranzistor-tip122-brick

• sau o placa 2 relee SPDT - http://www.robofun.ro/placa_2_relee_12vdc

• Un microventilator - http://www.robofun.ro/electronice/generale/microventilator-12V

• Un alimentator extern - http://www.robofun.ro/surse_de_alimentare/alimentatoare

• Un senzor de temperatura brick - http://www.robofun.ro/bricks/senzor-temperatura-brick

• Rezistoare pentru a construi un divizor rezistiv - http://www.robofun.ro/electronice/rezistoare

De ce tranzistorul TIP122 brick ? Pentru ca tranzistorul iti permite sa comanzi o sarcina de


putere mare direct cu placa Arduino. Pe de alta parte, poti opta pentru placa cu 2 relee SPDT daca
doresti sa comanzi nu unul, ci doi consumatori care se alimenteaza in curent alternativ.

Cum se conecteaza componentele de mai sus ?

• Mai intai vei incepe cu ventilatorul sau sursa de putere pe care doresti sa o comanzi. Firele
ventilatorului se conecteaza in conectorul marcat cu MOTOR de pe placa tranzistorului.

• Pentru tranzistorul TIP122: pinii marcati cu VIN si GND se conecteaza la bornele „+“ si „-“
ale sursei de alimentare, iar pinul marcat cu IN la pinul digital 13 de pe placa Arduino.

• Pentru senzorul de temperatura brick: pinii VCC si GND la pinii 5V si GND de pe placa
Arduino, iar pinul OUT de pe senzorul brick la pinul digital 7.

• Divizorul rezistiv ? Aici trebuie sa descoperi cum sa conectezi 2 rezistori la pinul digital 6,
pentru ca aici vei alege tensiunea de prag la care se va declansa ventilatorul.

Totusi iti raman foarte multe lucruri de facut. Spre exemplu, trebuie sa descoperi ce tensiune
scoate senzorul brick, trebuie sa calculezi divizorul rezistiv si sa modifici sketch-ul de mai sus pentru a
efectua comanda ventilatorului cu grade variabile de turatie.

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Arduino – cum accesez o memorie EEPROM externa ?

Ce sunt memoriile EEPROM externe ?

Termenul EEPROM inseamna Electrically Erasable Programmable Read-Only Memory, adica


acest termen se refera la memoriile nevolatile care pot fi citite/scrise si rescrise de nenumarate ori.
Memoriile nevolatile sunt cele care isi pastreaza continutul, chiar si dupa ce ai intrerupt
alimentarea. Spre exemplu, un alt dispozitiv care isi pastreaza datele este hard disk-ul. Chiar daca ai
oprit calculatorul, hard disk-ul pastreaza toate informatiile intacte. Ele nu se sterg si pot fi accesate din
nou la urmatoarea pornire a calculatorului.
In aceeasi maniera functioneaza si o memorie EEPROM. Poti sa salvezi date in ea si sa le citesti
ori de cate ori vrei tu, chiar si dupa ce ai intrerupt alimentarea.

In ce conditii poti sa folosesti o memorie EEPROM ?

In primul rand, memoriile EEPROM nu sunt destinate pentru a salva blocuri uriase de
informatii (asa cum face un hard disk), dar poti folosi o memorie EEPROM pentru a salva o cantitate
minima de informatii, adica cel mult cativa MB.
In al doilea rand, memoriile sunt simplu de utilizat si sunt produse in capsule de circuite
integrate, adica poti sa le adaugi foarte usor si foarte rapid in proiectul tau.
Alt avantaj al memoriilor EEPROM este ca multumita interfetei de comunicare cu placa
Arduino, poti sa folosesti nu doar una, ci mai multe memorii inlantuite pe o magistrala I2C sau SPI.

http://www.robofun.ro/forum
Dar totusi in ce situatii poti sa folosesti aceste memorii?
Iata un data logger ce se foloseste de memoria EEPROM pentru a salva un numar mare de
esantioane cu valori de temperatura:

http://forum.arduino.cc/index.php/topic,111366.0.html

Un alt proiect asemanator celui de mai sus este un data logger care inregistreaza viteza de
deplasare a unei biciclete:

http://www.eightlines.com/blog/2008/09/data-logging-to-the-arduino-eeprom/

Daca nu stiai afla ca si placa Arduino, mai exact microcontroller-ul placii, are propria memorie
EEPROM pe care poti salva pana la 4096 de octeti (4KB). Poti afla mai multe detalii despre memoria
interna accesand urmatoarele link-uri:

http://arduino.cc/en/Reference/EEPROM#.UySH7Pl_uSo
http://arduino.cc/en/Tutorial/EEPROMWrite#.UySIYPl_uSo
http://arduino.cc/en/Tutorial/EEPROMRead#.UySIefl_uSo

http://www.robofun.ro/forum
Cum conectez o memorie EEPROM la o placa Arduino ?

In acest tutorial s-a folosit o memorie EEPROM AT24C02, a carei fisa de catalog se poate
descarca de la urmatoarea adresa:

http://www.atmel.com/Images/doc3256.pdf

Spre exemplu, din fisa de catalog se pot afla urmatoarele specificatii ale memoriei:

• Tensiunea de alimentare: 5 V sau 2.7 V.

• Organizarea interna a memoriei care iti va fi de folos atunci cand o adresezi.

• Tipul interfetei seriale (memoria de fata necesita o interfata seriala pe 2 fire)

• Viteza de scriere a datelor in functie de tensiunea de alimentare.

• Numarul de scrieri posibile (memoria de fata suporta 1 milion de cicluri de scrieri).

• Configuratia pinilor (pinii de adresare, pinii interfetei seriale, pinii de alimentare si pinul de
citire/scriere).

Dar totusi cum conectez memoria la placa Arduino ? Pentru a realiza acest lucru vei avea
nevoie de o placa breadboard, fire de conexiune tata-tata si memoria in sine.
Conexiunea placii Arduino cu memoria EEPROM se va realiza dupa urmatoarea schema:

http://www.robofun.ro/forum
Mai exact vei conecta pinii placii Arduino cu memoria EEPROM dupa urmatorul tabel:

Arduino 5V Memorie EEPROM VCC


Arduino GND Memorie EEPROM GND, A0, A1, A2, WP
Arduino SCL Memorie EEPROM SCL
Arduino SDA Memorie EEPROM SDA

Pinii memoriei se pot afla direct din fisa de catalog (link-ul de mai sus) sau din urmatoarea
diagrama:

http://www.robofun.ro/forum
http://www.robofun.ro/forum
Ce reprezinta pinii marcati cu A0, A1, A2 si WP ?
Am spus mai devreme ca o placa Arduino poate adresa mai multe memorii, iar pinii A0, A1 si
A2 te pot ajuta sa inlantuiesti pe magistrala seriala pana la 8 memorii EEPROM. In cazul in care doresti
sa folosesti o singura memorie, tot ce trebuie sa faci este sa conectezi pinii la GND, adica toti pinii sa
capete valoarea logica „0“. Daca vrei sa adaugi o noua memorie, tot ce trebuie sa faci este sa alegi o
configuratie diferita pentru noua memorie, adica sa conectezi pinii A0 si A1 la GND iar pinul ramas,
A2, la VCC. Pentru o a treia memorie trebuie sa alegi o noua configuratie, diferita fata de celelalte
doua. In final poti adauga pana la 8 memorii.
In cazul de fata, placa Arduino va adresa o singura memorie EEPROM, dar tie iti ramane sa
descoperi cum se poate adresa o a doua memorie si chiar mai multe.
Ramane pinul WP care inseamna „Write Protect“. Acest pin iti permite sa protejezi datele de pe
memoria EEPROM dupa anumite reguli pe care le poti descoperi in fisa de catalog.
In cazul de fata, pinul WP este conectat la GND si asta inseamna ca esti liber sa scrii si sa citesti
memoria ori de cate ori vrei tu, adica functia de protectie la scriere este dezactivata.

Cum citesc/scriu memoria EEPROM din Arduino ?

Iata 2 functii simple care iti permit sa scrii si sa citesti in/din memoria EEPROM:

http://www.robofun.ro/forum
void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte
data )
{
Wire.beginTransmission(deviceaddress);
Wire.write((int)eeaddress);
Wire.write(data);
Wire.endTransmission();

delay(5);
}

byte readEEPROM(int deviceaddress, unsigned int eeaddress )


{
byte rdata = 0xFF;

Wire.beginTransmission(deviceaddress);
Wire.write((int)eeaddress);
Wire.endTransmission();
Wire.requestFrom(deviceaddress,1);

if (Wire.available()) rdata = Wire.read();

return rdata;
}

Cum functioneaza functia de scriere ? La prima vedere, functia pare extrem de simpla deoarece
este formata din 5 instructiuni. La apelare functia accepta 3 parametrii, dintre care primul reprezinta
adresa fizica a memoriei EEPROM, al doilea parametru reprezinta adresa locatiei din memorie la care
vrei sa faci scrierea, iar al treilea parametru reprezinta informatia pe care doresti sa o salvezi. Simplu ?
Cum stabilesc adresa fizica a memoriei ? In primul rand, mai devreme am vorbit despre pinii
A0, A1 si A2 pe care i-ai conectat la GND, adica le-ai dat tuturor valoarea logica „0“.
Daca te uiti in fisa de catalog a memoriei vei intalni urmatoarea imagine:

http://www.robofun.ro/forum
Pentru memoria de fata este valabila doar prima linie marcata cu 1K/2K in care apar bitii A2,
A1 si A0. Daca acesti biti sunt conectati la GND, inseamna ca toti bitii capata valoarea „0“.
Daca realizezi conversia din binar in hexazecimal a urmatorului sir de biti „1010000“, vei
descoperi adresa hardware pe care o poti folosi in functia de mai sus, respectiv 0x50.
Scrierea propriu-zisa a informatiei in memoria EEPROM se realizeaza dupa urmatoarea
diagrama (pe care o poti descoperi tot din fisa de catalog). Iti ramane ca tu sa descoperi cum lucreaza
instructiunile din interiorul functiei de scriere, asa cum indica si diagrama de mai jos.

Cum functioneaza functia de citire ? Diferenta intre functia de scriere si cea de citire este ca cea
din urma returneaza ceva dintr-o locatie de memorie. Asta inseamna ca la apelare, functia accepta 2
parametrii, respectiv adresa hardware a memoriei (descoperita mai sus) si locatia din memorie.
Instructiunile de citire sunt asemanatoare functiei de scriere, dar exista ceva in plus.
Tot ce trebuie sa faci este sa cauti diagrama de citire din fisa de catalog si sa corelezi
instructiunile.

Am functiile de scriere si citire, dar cum le apelez ?


Iata un exemplu:

#include <Wire.h>
#define disk1 0x50 //adresa hardware a memoriei

void setup(void)
{
Serial.begin(9600);
Wire.begin();
unsigned int address = 0;
writeEEPROM(disk1, address, 123);
Serial.println(readEEPROM(disk1, address), DEC);
}
void loop(){
}

http://www.robofun.ro/forum
Prima linie de cod, directiva preprocesor, apeleaza libraria Wire. Libraria este responsabila cu
protocolul de comunicatie intre placa Arduino si memoria EEPROM.
Am mentionat mai sus ca fiecare memorie poate capata o adresa hardware (prin configurarea
pinilor A0, A1 si A2). In codul de mai sus, adresa poarta numele disk1 si are valoarea hexazecimala
0x50.
In rutina setup() se initializeaza Monitorul Serial, conexiunea seriala cu memoria EEPROM,
adresa locatiei la care vrei sa faci o scriere si apoi o citire.
Dupa care se apeleaza functia de scriere si dupa cum observi se scrie valoarea 123 in locatia 0,
din memoria EEPROM cu adresa hardware 0x50.
Apoi se citeste si se afiseaza din memoria EEPROM, valoarea scrisa anterior prin functia:
Serial.println(readEEPROM(disk1, address), DEC);

Ce altceva poti sa faci cu o memorie EEPROM ?


Pe langa a salva si a scrie date, poti spre exemplu sa salvezi un fisier wav pentru a il folosi mai
tarziu la redare. Iata un exemplu:
http://www.enide.net/webcms/index.php?page=pcm2pwm-multiplayer

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Arduino si protocolul One Wire

Ce este protocolul One Wire ?

Nu este decat un alt protocol care iti permite sa interconectezi diverse dispozitive periferice, in
special senzori, direct cu placa Arduino. Spre exemplu, senzorul de temperatura DS18B20 este un
senzor care face decat conversia temperaturii. Dar avantajul vine datorita interfetei cu care senzorul este
dotat.
Interfata identifica in mod unic senzorul cu care placa Arduino comunica. Asta inseamna ca nu
esti limitat in a utiliza unul sau doi senzori. In schimb, poti folosi zeci de senzori conectati in retea,
folosind ca si magistrala de date un singur fir. De aici vine si numele protocolului – One Wire.
Cati senzori pot folosi ? Nu exista un numar clar deoarece trebuie sa iei in calcul foarte multe
aspecte cum ar fi: distanta intre senzori, tipul de cablu folosit, sursa de alimentare, ecranarea cablului,
parazitii externi s.a.m.d.
Iti propun sa studiezi un ghid care te poate ajuta in proiectarea unei retele One Wire de
dimensiuni mari:

http://www.maximintegrated.com/app-notes/index.mvp/id/148

Senzorul de temperatura DS18B20.

Iata cateva lucruri interesante despre acest senzor:

• Conversia temperaturii o face la rezolutii mari cuprinsa intre 9 si 12 biti.

• Are o functie interesanta de alarmare atunci cand temperatura citita depaseste limitele
programate de utilizator.

• Poti alimenta senzorul in modul parasite (parasite power). La ce te ajuta modul asta ? Afla mai
jos.

• Fiecare senzor are un cod unic pe 64 de biti. Asta inseamna ca poti interconecta foarte multi
senzori, pe acelasi fir, sub forma unei retele.

http://www.robofun.ro/forum
• Poate masura temperaturii negative (pana la -55 de grade Celsius) dar si pozitive (pana la 125 de
grade Celsius) cu o acuratete de ± 0.5 grade.

• Poate fi alimentat cu tensiuni cuprinse intre 3 si 5.5V.

Modul parasite power ?

In mod normal, senzorul necesita 3 fire pentru o functionare corecta, respectiv 2 fire de
alimentare si un fir One Wire. Un lucru interesant este ca senzorul iti permite sa renunti la un fir de
alimentare si sa folosesti doar cele 2 fire ramase.
Practic modul parasite power iti permite sa alimentezi, dar sa si „vorbesti“ cu senzorul folosind
firul GND si firul One Wire. In acest caz, firul One Wire este folosit pentru 2 lucruri: alimentarea
senzorului si comunicatia cu placa Arduino.
Lucrul asta este foarte util atunci cand vrei pur si simplu sa scazi costurile pentru cel de-al
treilea fir. Aceasta tehnologie se foloseste foarte des in industria producatoare de masini. Doar prin
eliminarea firului de alimentare al senzorilor, o masina foloseste pana la 50 m de cablu, in timp ce o
masina echipata cu senzori din generatia precedenta (care foloseste toate cele 3 fire) poate folosi pana la
600 m de cablu. Mai ales ca depanarea unei probleme se poate face mult mai repede si mult mai usor.
Cat timp dureaza sa verifici continuitatea unui cablu de 50 m si a unuia de 600 ? Ce probleme apar oare
in cazul cablului de 600 m ? (coliziuni pe magistrala, diafonie, s.a.m.d).

Daca doresti sa studiezi in plus modul parasite power, acceseaza link-ul de mai jos:

http://www.maximintegrated.com/app-notes/index.mvp/id/3754

Cum conectez senzorul de temperatura ?

Iata un proiect care iti permite sa conectezi 3 senzori de temperatura si sa ii afisezi pe un ecran
LCD, folosind o placa Arduino:

http://www.instructables.com/id/Temperature-with-DS18B20/

Diverse proiecte folosind placa Raspberry PI:

https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/temperature/
http://learn.adafruit.com/adafruits-raspberry-pi-lesson-11-ds18b20-temperature-
sensing/hardware

http://www.robofun.ro/forum
Pentru a conecta senzorul la o placa Arduino vei avea nevoie de 3 fire de conexiune si un
rezistor de 4.7K. Rezistorul se conecteaza intre pinul de date si pinul de alimentare VCC. Urmareste
diagrama de mai jos:

Cum comunica senzorul de temperatura cu placa Arduino ?

Pentru ca placa Arduino sa comunice corect cu senzorul de temperatura trebuie indepliniti 3


pasi:

1. Initializarea – in primul rand, orice tranzactie sau orice schimb de date incepe cu o secventa de
initializare. Secventa de initializare este alcatuita dintr-un semnal de reset transmis de placa
Arduino (master) urmat de un semnal de prezenta transmis de senzori (slave-uri). Semnalul de
prezenta este util pentru placa Arduino, pentru ca aceasta trebuie sa identifice prezenta
senzorilor pe magistrala One Wire.
2. Comenzi ROM – imediat dupa ce placa Arduino a identificat senzorii de pe magistrala urmeaza
un schimb de date folosind o serie de comenzi ROM. Spre exemplu, exista o comanda de
cautare (Search ROM) prin care master-ul (placa Arduino) identifica numarul slave-urilor de pe
magistrala si tipurile lor. Mai exista o comanda (Read ROM) care este utila doar daca pe
magistrala se afla conectat un singur senzor. In felul asta, placa Arduino nu pierde timp util la
cautarea altor senzori (pentru ca exista doar unul). O alta comanda se numeste Skip ROM
,atunci cand master-ul doreste sa se adreseze tuturor senzorilor. Acestea sunt doar cateva
comenzi, deoarece exista mult mai multe, fiecare avand un mod mai complex de functionare.
3. Comenzi specifice senzorului de temperatura – imediat ce placa Arduino a identificat senzorii
de temperatura prin comenzile ROM, urmeaza ca placa sa faca un schimb de date cu senzorul
in sine. Lucrul asta se face printr-un set specific de comenzi. Spre exemplu, comanda Convert T
prin care placa Arduino initializeaza o conversie de temperatura. Imediat dupa ce senzorul a
primit si a executat comanda de conversie, pune toata informatia pe un spatiu intern de
memorie format din 2 bytes. Urmeaza ca placa Arduino sa citeasca, prin alta comanda, spatiul

http://www.robofun.ro/forum
intern de memorie al senzorului. Aceasta comanda se numeste Read Scratchpad prin care
master-ul cireste toata zona de memorie a senzorului. Exista si alte comenzi de citire si scriere,
setare alarma, identificare senzori care functioneaza in modul parasite power s.a.m.d.

Studiaza fisa de catalog a senzorului pentru a descoperi mult mai multe comenzi specifice
senzorului:

http://robofun.ro/docs/DS18B20.pdf

http://www.robofun.ro/forum
Textul si imaginile din acest document sunt licentiate
Attribution-NonCommercial-NoDerivs
CC BY-NC-ND

Codul sursa din acest document este licentiat


Public-Domain

Esti liber sa distribui acest document prin orice mijloace consideri (email, publicare pe website / blog, printare,
sau orice alt mijloc), atat timp cat nu aduci nici un fel de modificari acestuia. Codul sursa din acest document
poate fi utilizat in orice fel de scop, de natura comerciala sau nu, fara nici un fel de limitari.
Asamblare statie meteo

Statia meteo este capabila de a masura 3 parametrii importanti: viteza, directia vantului si
cantitatea de precipitatii. Senzorii din aceasta statie sunt formati doar din switch-uri reed si magneti,
ceea ce inseamna ca sunt foarte usor de utilizat, dar pentru a functiona acestia au nevoie de o sursa de
alimentare.
Componentele principale ale statiei meteo sunt:

• anemometrul este responsabil cu masurarea vitezei vantului. Analogic vorbind, acesta


functioneaza asemeni unui buton conectat la o placa Arduino. La o viteza de 2.4km/h
anemometrul inchide un switch la intervale de o secunda.

• Girueta determina directia vantului si utilizarea senzorului presupune citirea unei tensiuni

http://www.robofun.ro/forum
folosind un convertor analog-digital. In interiorul giruetei se afla o retea de 8 rezistori cu 8
switch-uri, care pot indica pana la 16 directii posibile. In plus, vei avea nevoie de un rezistor fix
care impreuna cu celelalte 8 formeaza un divizor rezistiv. Pentru fiecare directie, senzorul
genereaza o tensiune electrica. Tensiunea poate fi citita de catre o placa Arduino si corelata cu
directia vantului.

• Pluviometrul determina cantitatea de precipitatii, se goleste singur, iar fiecare 0.2794 mm de


ploaie produce declansarea unui switch. Aceasta declansare poate fi interpretata de catre o placa
Arduino ca si un buton sau ca o „intrerupere“.

Statia meteo se asambleaza urmand pasii de mai jos:

1. Bratul care sprijina senzorii enumerati mai sus este alcatuit din 2 bare. Cele 2 bare se infig una
intr-alta (vezi capatul de sectiune mai mica a barei de sus).

2. Vei obtine o bara mult mai mare avand la un capat o gaura pentru surub si un canal de fixare
(vezi imaginea).

3. Urmeaza montarea anemometrului si a giruetei pe bara de sustinere folosind un suport de

http://www.robofun.ro/forum
fixare. Suportul este cel din imagine, pe care se monteaza anemometrul si girueta, iar in partea
de jos se fixeaza in bara de sustinere (vezi imaginea).

4. Inainte de a fixa suportul, mai intai trebuie sa montezi senzorii de vant. Montarea este simpla,
tot ce trebuie sa faci este sa fixezi senzorii pe cele 2 brate si sa montezi surubul si piulita.

http://www.robofun.ro/forum
5. Anemometrul se fixeaza in suportul lui special, apoi se fixeaza ferm folosind surubul si piulita.

http://www.robofun.ro/forum
http://www.robofun.ro/forum
http://www.robofun.ro/forum
6. Girueta se monteaza in acelasi mod ca si anemometrul. Se monteaza in suport si se fixeaza ferm
cu surubul si piulita.

http://www.robofun.ro/forum
http://www.robofun.ro/forum
7. Urmeaza sa montezi acest suport in bara de sustinere a statiei. Montarea este simpla, tot ce
trebuie sa faci este sa fixezi suportul in capatul barei de sustinere si sa strangi cele 2 holsuruburi.

http://www.robofun.ro/forum
http://www.robofun.ro/forum
8. Pluviometrul se monteaza pe un brat secundar al statiei meteo.

http://www.robofun.ro/forum
9. Mai intai trebuie sa fixezi bratul secundar de bara de sustinere si sa strangi ferm suruburile (vezi
imaginea)

http://www.robofun.ro/forum
10. Pluviometrul se fixeaza in capatul bratului secundar prin intermediul unui holsurub.

http://www.robofun.ro/forum
http://www.robofun.ro/forum
http://www.robofun.ro/forum
11. In urmatorul pas, trebuie sa pozezi cablurile senzorilor in clipsurile din plastic aflate dedesubt
de suport. Cablul anemometrului este scurt, deoarece acesta se conecteaza in mufa giruetei (vezi
imaginea)

http://www.robofun.ro/forum
http://www.robofun.ro/forum
http://www.robofun.ro/forum
12. Cablurile ramase (cele care practic se conecteaza in placa cu microcontroller) se fixeaza cu
colierele din plastic de bara de sustinere a statiei.

http://www.robofun.ro/forum
http://www.robofun.ro/forum
http://www.robofun.ro/forum
13. Asamblarea a luat sfarsit !

Daca doresti sa realizezi o implementare rapida a statiei meteo folosind o placa Arduino,
foloseste codul sursa de mai jos:
Sunt aspecte importante pe care trebuie sa le cunosti in avans:

• Sketch-ul de mai jos realizeaza citirea anemometrului si a giruetei dar nu si a pluviometrului.

• Diferenta de cod dintre pluviometru si anemometru este minima deoarece pluviometrul inchide
un simplu contact la fiecare 0.2794 mm de precipitatii.

• Pentru conectarea anemometrului ai la dispozitie firele centrale ale cablului RJ11.

• Pentru conectarea giruetei ai la dispozitie firele exterioare ale cablului RJ11.

• Urmeaza explicatiile si diagrama de conectare din codul sursa de mai jos.

http://www.robofun.ro/forum
/* Arduino sketch for Weather device from Sparkfun.
Uses only the wind direction vane and the anemometer (not the rain
gauge).

Although the inclination for a weather logger is to run it for


a long time, due to the way Wiring.c implements the millis()
function,
this should be restarted, oh, monthly. The millis() functions
overflows
after about 49 days. We could allow for that here, and handle the
wraparound, but you've got bigger problems anyway with the delay()
function at an overflow, so it's best to "reboot".

=========================================================
ANEMOMETER
=========================================================
This is connected to Arduino ground on one side, and pin 2 (for the
attachInterrupt(0, ...) on the other.
Pin 2 is pulled up, and the reed switch on the anemometer will send
that to ground once per revolution, which will trigger the
interrupt.
We count the number of revolutions in 5 seconds, and divide by 5.
One Hz (rev/sec) = 1.492 mph.

=========================================================
WIND DIRECTION VANE
=========================================================
We use a classic voltage divider to measure the resistance in
the weather vane, which varies by direction.
Using a 10K resistor, our ADC reading will be:
1023 * (R/(10000+R))
where R is the unknown resistance from the vane. We'll scale
the 1023 down to a 255 range, to match the datasheet docs.

+5V
|
<
> 10K
< Resistor
<
>
|
Analog Pin 5------|
|
-----------| To weather vane
| (mystery resistance)
-----------|
|
|

http://www.robofun.ro/forum
-----
---
-
The ADC values we get for each direction (based on a 255 max)
follow, assuming that pointing away from the assembly center
is sector zero. The sector number is just which 45-degree sector
it is, clockwise from the "away" direction. The direction
shown is assuming that "away" is West. Depending how
you orient the system, you'll have to adjust the directions.

Sector Reading Direction


0 18 W
1 33 NW
2 57 N
7 97 SW
3 139 NE
6 183 S
5 208 SE
4 232 E
The values in the ADC table below list the midpoints between
these, so our reading can vary a bit. We'll pick the first value
that's >= our reading.
=========================================================
RAIN GAUGE
=========================================================
Not implemented here. Hey. I live in Seattle. It's ALWAYS raining.
Who
cares how much?
Okay, it would probably be done the same way as the anemometer, and
use
attachInterrupt(1, ...) on pin 3. Each interrupt represents
.011 inches of rain, according to the docs.

*******************************************************************
**/

#define uint unsigned int


#define ulong unsigned long

#define PIN_ANEMOMETER 2 // Digital 2


#define PIN_VANE 5 // Analog 5

// How often we want to calculate wind speed or direction


#define MSECS_CALC_WIND_SPEED 5000
#define MSECS_CALC_WIND_DIR 5000

volatile int numRevsAnemometer = 0; // Incremented in the interrupt


ulong nextCalcSpeed; // When we next calc the wind
speed

http://www.robofun.ro/forum
ulong nextCalcDir; // When we next calc the
direction
ulong time; // Millis() at each start of
loop().

// ADC readings:
#define NUMDIRS 8
ulong adc[NUMDIRS] = {26, 45, 77, 118, 161, 196, 220, 256};

// These directions match 1-for-1 with the values in adc, but


// will have to be adjusted as noted above. Modify 'dirOffset'
// to which direction is 'away' (it's West here).
char *strVals[NUMDIRS] = {"W","NW","N","SW","NE","S","SE","E"};
byte dirOffset=0;

//=======================================================
// Initialize
//=======================================================
void setup() {
Serial.begin(9600);
pinMode(PIN_ANEMOMETER, INPUT);
digitalWrite(PIN_ANEMOMETER, HIGH);
attachInterrupt(0, countAnemometer, FALLING);
nextCalcSpeed = millis() + MSECS_CALC_WIND_SPEED;
nextCalcDir = millis() + MSECS_CALC_WIND_DIR;
}

//=======================================================
// Main loop.
//=======================================================
void loop() {
time = millis();

if (time >= nextCalcSpeed) {


calcWindSpeed();
nextCalcSpeed = time + MSECS_CALC_WIND_SPEED;
}
if (time >= nextCalcDir) {
calcWindDir();
nextCalcDir = time + MSECS_CALC_WIND_DIR;
}
}

//=======================================================
// Interrupt handler for anemometer. Called each time the reed
// switch triggers (one revolution).
//=======================================================
void countAnemometer() {

http://www.robofun.ro/forum
numRevsAnemometer++;
}

//=======================================================
// Find vane direction.
//=======================================================
void calcWindDir() {
int val;
byte x, reading;

val = analogRead(PIN_VANE);
val >>=2; // Shift to 255 range
reading = val;

// Look the reading up in directions table. Find the first value


// that's >= to what we got.
for (x=0; x<NUMDIRS; x++) {
if (adc[x] >= reading)
break;
}
//Serial.println(reading, DEC);
x = (x + dirOffset) % 8; // Adjust for orientation
Serial.print(" Dir: ");
Serial.println(strVals[x]);
}

//=======================================================
// Calculate the wind speed, and display it (or log it, whatever).
// 1 rev/sec = 1.492 mph
//=======================================================
void calcWindSpeed() {
int x, iSpeed;
// This will produce mph * 10
// (didn't calc right when done as one statement)
long speed = 14920;
speed *= numRevsAnemometer;
speed /= MSECS_CALC_WIND_SPEED;
iSpeed = speed; // Need this for formatting below

Serial.print("Wind speed: ");


x = iSpeed / 10;
Serial.print(x);
Serial.print('.');
x = iSpeed % 10;
Serial.print(x);

numRevsAnemometer = 0; // Reset counter

http://www.robofun.ro/forum
}

http://www.robofun.ro/forum

S-ar putea să vă placă și