You are on page 1of 108
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), flind 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 continu (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. it .com/watch?v=Xk3-HZpSm21 - robot care parcheaza singur — http://www.youtube.com/watch?v=4nMNOugxf3l - masina de taiat iarba (autonoma) — http://www.youtube.com/watch?v=X5SnqCcMxGBs - 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-VTRjaHkO - 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.youtt m/watch?v=YOIMGV5vtd4 — OpenEnerayMonitor, 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. — 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, Leonardo, Mega, etc). Fie Edt Sketch Took Help sketch_septda 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 2 void loop() { //codul scris aici ruleaza tot timpul i Astfel, in rutina "setup" vom pune de obicei cod de initializare, iar in rutina "loop" vom scrie_partea principala a programului nostru, 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(1009) ; 3 Daca urci acest program pe placa Arduino si urmaresti led-ul conectat la pinul 13 vei observa ca el clipeste 0 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/IOFF 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. Neo aUI\ 0) Arduino GND GND Led Arduino Digital 13 IN Led void setup() { pinMode(13, OUTPUT); 3 void loop() { digitalwrite(13, HIGH); delay (1090) ; digitalwrite(13, Low); delay(1090); 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 0 secunda, stinge led-ul (tensiunea pinului devine 0 V) si apoi iarasi asteapta 0 secunda. 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) hup://www.robofun.ro/forum 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 SV ori OV), exista o posibilitare de a genera un semnal de putere varia pe unul dintre porcurile sale, Acest Iucru este posibil prin generarea unui semnal dreptunghiular, care se plimba periodic intre OV si SV, foarte rapid. In functie de cat timp sta in 5V si cat timp sta in OV, 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 pucerea prin variatia raportului intre timpul cat sta in 1 si cat sta in 0. Este interesant de remareat faptul ca doar 6 din cei 13 pini ai Arduino UNO sunt capabili sa sgenereze semnal PWM (pinii 3, 5, 6, 9, 10 si 11) Peneru 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; analogWrite(11, i); delay (50); ie) ( nt i = 255; i > 0; i--){ analogWrite(11, i); delay (50); Rutina serup, 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 Joop este interesanta instructiunea analog Write, care defineste puterea semnalului PWM de iesire. Ca parametti, instructiunea analog Write primeste pinul (11, in cazul nostru), si puterea semnalului (variabila, de la 0 la 255), Aceasta instructiune este apelata intt-un ciclu for, care modifica valoarea variabilei i incre 0 si 255. Efectul va fica led-ul se va aprinde gradat pana la maxim, iar apoi se va stinge treptat. CTE AT (oar 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" 2) daca scoti firul de conectare din pinul 13 (mareat pe led eu "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 cleceronice, fara lipicuri, Pentru a conecta dispozitivele se folosesc fire rara-rata (cu. pini la ambele capete), care se introduc in gautile din breaboard. Gaurile existente in breaboard sunt conectate intre ele (de obicei pe linic), astfel incat fircle introduse pe aceeasi linie vor fi conectate intre ele. In imaginea de mai jos am marcat cu linie neagra pinii conectati intre ei (ew am marcat doar pentru primele 3 coloane, dar toate liniile breadboard-ul 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 SV Arduino la una dintre liniile breaboard-ului, la alta linie din breadboard vom conecta unul dincre pinii GND, si in acesc mod vom avea disponibile inca patru pini care sunt conectati la 5V (cei care sunt pe aceeasi lini cu cel 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 - huepy/Avww.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. Ss — herp:/ 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 sail alimentezi cu o baterie, programul va continua sa ruleze. Sunt situatii (si nu putine! ) cand rezultacele rularii programului sunt cu tovul 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 0 anumita valoare. Am sctis programul, -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 coreet. Vom face acest lucru tsimitand 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.print1n (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 © comunicare seriala intre Arduino si PC cu viteza de 9600 de pe secunda si "Serial.printIn(lumina)", care trimice valoarea variabilei "lumina" catre PC. Poti uti Arduino. aceasta metoda ori de cate ori vrei sa veri ce valori au variabilele din programul tau De ce nu merge ? =daca in loc sa veri 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 Pore’. Portul cate a disparut este acel port pe care era conectat Arduino. Reconecteaza acum Arduino, si selecteaza-I pe acesta. loc sa vezi valori numerice in Serial Monitor vezi o serie de caractere ciudate care se schimba seamna ca rata de uransfer selectata in Serial Monitor nu este aceeasi cu rata de uransfer 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-uti, in exemplele de pana acum). Acum vom vedea cum putem folosi un port digital Arduino pentru a citi informatie din mediu (starea unui buton). en) Arduino GND GND Buton Arduino 5V vec Buton Arduino Digital 7 our Buton void setup() { pinMode(7, INPUT); Serial. begin (9600) ; ) void loop() { int stareButon = digitalRead(7); Serial.print1n(stareButon) + delay (10); Primul lucru interesant este faptul ca acum pinul digital 7 (cel la care am conectat un buton) ceste setat in mod INPUT (spre deosebire de exemplele precedente, unde era de tip OUTPUT). Asta pentru ca urmeaza sail 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 corectfirele? 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 valoare numerica intre 0 si 1023, valoare proportionala cu nivelul de iluminare din mediul ambiant. Arduino GND GND Senzor Arduino 5V vec Senzor Arduino Analog 0 our Senzor void setup() { Serial.begin (9600); ) void loop() { int nivelIluminare = analogRead(0); Serial.print1n(nivelfluminare) ; delay (10); In rutina setup singurul lucru pe care il facem este sa initializam 0 comunicare seriala cu PC-ul, pe care ‘vom folosi ca sa transmirem si sa vizualizam pe PC valorile citite de senzorul de lumina. Rutina Joop citeste valoarea data de senzorul de lumina (conectat 1a portul serial 0) si afiseaza aceasta valoare in consola seriala. Poti vedea aceasta informatie deschizand Serial Monitor in Arduino IDE. Pentru a testa ca lucturile functioneaza corect, pune degetul peste senzorul de lumina, Vei observa ca valoarea pe care 0 veri in Serial Monitor scade. De ce nu merge ? “sigur ai conectat corectfirele ? sigur programul s-a incarcat pe Arduino (ai vazut mesajul "Done Uploading” ) ? Mini Difuzor Mini difwzorul este cea mai simpla modalitate de a crea sunete cu Arduino. Usilizarea acestui 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 SV si OV, astfel incat membrana difazorului este si ea miscata la fel de rapid, generand sunete. Frecventa cu care semnalul se misca intre SV si OV determina frecventa sunetului. Pees Arduino GND Fir Negru Difuzor Arduino Digital 11 Fir Rosu Difuzor void setup() { pinMode(11, OUTPUT); ) void loop() { for (int i = 1900; i < 40007 it#) { tone(11, i); delay (10); 1 for (int i = 4000; i > 1500; i tone(11, i); delay(10); Partea interesanta din codul de mai sus este instructiunea cone, care primeste ca parametti pinul la care este conectat difwzorul (in cazul nostru pinul 11) si frecventa sunetului (in cazul nostru, variabila ’). Variabila ise modifica intre 1500 de Hertzi si 4000 de Hertzi. Efectul obtinut este cel de sirena. Ca sa opresti sunecul complet, instructiunea este noTone(); In cazul de mai sus, noTone(I1) opreste complet sunetul Senzor Temperatura Brick Senzorul de temperatura brick este un alt exemplu de senzor care ofera valori analogice care depind de temperatura din mediul ambiant. Din valorile citice de la senzori se obtine valoarea temperaturit 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.print1n(citesteTemprncelsius(10))7 ) float citesteTempinCelsius(int count) { float temperaturaMediata = 0; float sumaTemperatura; for (int i =0; ic107 itt) ( int reading = analogRead (0); float voltage = reading * 5.0; voltage /= 1024.0; float temperatureCelsius ~ (voltage - 0.5) * 100 ; sumaTemperatura = sumaTemperatura + temperatureCelsius; } return sumaTemperatura / (float)counts ) La fel ca in exemplele precedente, in rutina secup singurul lucru pe care il facem este sa initializam o comunicare seriala cu PC-ul, pe care 0 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 “citesteTemplnCelsius” care calculeaza temperatura in grade Celsius pe baza valoriicitite de la senzor. Pentru a diminua influenta surselor de erori asupra itirilor, temperatura se calculeaza pe baza a zece citiri succesive, care sunt mediate. Ca sa testezi ca lucturile functioneaza corect, pune degetul peste senzorul de temperatura. Vei observa ca valoarea pe care o veri in Serial Monitor crest 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 (9%), dar deducerea formule’ 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”), ‘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 ier”. Cao paranteza, daca ai nevoie de un senzor foarte precis, si care iti ofera direct nivelul umiditat din aer, in unitati standard, acunci iti sugerez STH15, un senzor etalonat si extrem de preci butp://www.robofun.ro/senzor_ temperatura umiditate sht15. Arduino GND GND Senzor Arduino 5V vec Senzor Arduino Analog 0 our Senzor void setup() { Serial.begin (9600); ) void loop() { int nivelUmiditate = analogRead(0); Serial.printin(nivelumiditate) + delay (50) + ) Codul sursa de mai sus este aproape identic cu cel de la senzorul de lumina, asa ca nu voi insista asupra lui Ca sa testeri ca lucrurile functioneaza corect, sufla peste senzor, usor. Vei observa ca valoarea pe care o veri in Serial Monitor se modifica, datorita fapcului 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 jumacace a sticlei (NU in apa, in zona in care sticla este goala). http://www.robofun ro/forum 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 tri led-uri, vom utiliza un breaboard, cel despre care am vorbic in lectia precedenta, Conecrarea se face exact ca in situatia in care a folosic 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); secup face acelasi lucru ca in exemplul cu un singur led, doar ea acum declara tei pi Joc de unul. Rutina /oop aprinde initial led-ul verde vreme de o secunda. Apoi aprinde led-ul galben vreme de 0.2 sccunde si apoi stinge led-ul verde si il aprinde pe cel rosu. Dupa o secunda, face exact acclasi 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 ledeul ? (daca nu, atunci led-ul probabil este defect) 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 anumica 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 albascru), rezultacul 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 nivelTluminare = analogRead(0); if (nivellluminare < 300) [ digitalWrite(11, HIGH); J else { digitalwrite(11, Lom); ) Singurul lucru pe care il face rutina secup este sa declare pinul la care este conecta ledul ca fiind pin de iesire. Rutina /oop 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 pencru parametrii din incaperea ta, si atunci led-ul sa stea stins tor timpul. Daca se intampla acest lucru, cl mai simplu este sa maresti valoarea pragului (cu cat vrei tu), sau sa folosesti debug-ul serial ca sa vezi cexact valoarea pe care 0 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. cca se stinge, pune degetul peste senzorul de lumina, iar led-ul se va aprinde. Buton + LED Un proiect simplu care aprinde un led atunei 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 buronul brick, Probabil ca vei vrea sa folosesti un breadboard pentru a obtine mai multe puncte VC GND. 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 serup, care declara ca pinul 7, cel pe care este conectat butonul, este un pin de intrare. Rutina loop verifica starea butonului (folosind digialRead) si actualizeaza starea led-ului in nea, In ritmul muzicii : Microfon + Led © 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, si6 (digital). define define define define #define #define #define define define PIN_LEDL PIN LED2 PINLED3 PIN_LED4 PRAG_LED1 100 PRAG_LED2 200 PRAG_LED3 300 PRAG_LED4 500 NUMAR_ESANTIOANE_MEDIERE 100 void setup() { pinMode(PIN_LED1, OUTPUT) P: nMode (PIN_LED2, OUTPUT) ; pinMode(PINLED3, OUTPUT); pinMode(PIN_LED4, OUTPUT) ; ) void loop() { int intensitateSonora = intensitateSonora(); if (intensitateSonora > PRAG_LEDI) ( digitalWrite(PIN_LEDL, HIGH); } else { digitalwrite(PIN_LEDL, Low); } if (intensitateSonora > PRAG_LED2) ( digitalWrite(PIN_LED2, HIGH); jelse ( digitalWrite(PIN_LEDL, Low); } if (intensitateSonora > PRAG_LED3) ( digitalWrite(PIN_LED3, HIGH); Jelse ( digitalWrite (PIN LED, LOW); } if (intensitateSonora > PRAG_LED4) ( digitalWrite(PIN_LED4, HIGH) ; jelse ( digitalWrite (PIN LED, Low); } ) int intensitateSonora() { long intensitate = 07 for (int i = 0; i < NOMAR 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 reaultat care iti place. Pentru un efect mai spectaculos, ar fi inceresant sa pui fiecare led intr-o minge de ping-pong, ca in proiectul "Termometru : Senzor Temperatura Brick + LED-uri". Termometru : Senzor Temperatura Brick + LED-uri Cu tei led-uri brick de culoridiferte, introduse in bile de ping-pong, impreuna cu un senzor de temperatura brick si un Arduino UNO poti crea un termometru deosebit si elegant. Led-uri Brick 1evoie de trei led-uti 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. fdefine NIVELL 15 define NIVEL2 25 fdefine 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) { analogWirite(3, intensitateverde) ; digitalWrite(5, LOW); digitalWrite(6, LOW); } else if (temperatura < NIVEL2) { analogWirite(3, intensitateVerde) ; analogWrite(5, intensitateGalben) digitalWrite(6, LOW); } else if (temperatura < NIVEL3) { analogWirite(3, intensitateVerde) ; analoglirite(5, intensitateGalben) ; analogWirite(6, intensitateRosu); ) float citesteTempincelsius() { float temperaturaMediata = 0; float sumaTemperatura; for (int i clo; itt) int reading = analogRead(0); float voltage = reading * 5.0; voltage /= 1024.0; float temperatureCelsius = (voltage * 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 zgrade, 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 intensitare maxima... 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, it prelungesc practic in sus pe acestia. Astfel, daca am pus un shield peste Arduino si vrem sa conectam un senzor la pinul AQ al Arduino, atunci vom conecta senzorul Ia pinul AO al shield-ului, si totul va functiona exact ca si cum Lam fi infipt in pinul AO 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 1.298. Mai mule, 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, sar 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 mucac in alta parte sa fie actualizati si in cod. Mai jos sunt doua exemple de shield-uri montate peste Arduino, 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, SPL si 12C lucrurile sa ti se para un pic complicate si dificil de inteles, pentru ca inca nu am introdus nici un cexemplu de dispozitiv care sa comunice astfel, Dupa ce vei vedea mai multe dispozitive explicate in detaliu in lectile viitoare, vei intelege mai usor despre ce este vorba. Ci ‘e 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 eatre acesta. Astfel, un led se conecteaza la un pin digital si arunci cand pinul este in HIGH, led-ul se aprinde, Un senzor de lumina se conecteaza la un pin analogic si folosind "analogRead()" obti valoarea data de senzor. Un buton se conecteaza la un pin digital si in>)" intoarce 1 daca butonul este apasat si 0 altfel. Un shield driver de motoare cu 1298 sau un LCD se conecteaza la mai multi pini digitali (4, respectiv 7) si primeste comenzi de la 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(, OUTPUT"). Altfel, nu se va intampla absolut nimic atunci cand trecem pinul in HIGH sau in LOW. Merita sa insistam un pic si asupra citiii datelor pe porcurile analogice. Un senzor, la nivel clectric, da pe iesire 0 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. Asfiel, folosind Arduino, putem citi senzori analogici cu o precizie de exact 1024 de nivele distincte. De cexemplu, folosind senzorul de lumina, vom putea citi cu Arduino exact 1024 de nivele distinete de iluminare ale mediului ambiant. Daca avem nevoie de o precizie mai buna, atunci va trebui sa trecem la ale ip de senzori (cel mai probabil, senzori pe I2C).. Comunicare Seriala Comunicarea seriala este o comunicare de tip digital, in sensul ca pe fir se eransmie biti (ca la fel ‘cum se intampla intr-o retea de calculatoare, doar ca folosind un protocol mult simplificat). Aceasta comunicare seriala se intampla intordeauna intre Arduino si calculator, acunci cand Arduino este programat, O comunicare seriala se intampla intotdeauna la o anumita rata de transfer, care determina viteza cu care se transmit biti pe fir. Rate comune de transfer sunt 9600, 19200, 57600, 115200. Software Serial SoftwareSerial este tot © modalitate de comunicare seriala, doar ca in loc de a utiliza pinii RX si ‘TX ai microcontroller-ului (care sunt dedicati pentru 0 astfel de comunicare), utilizam o libratie 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 #include SoftwareSerial mySerial(10, 11); // RX, ™% void setup() ( Serial.begin (9600); Serial.print1n ("Goodnight moon!") mySerial.begin (4800); mySerial.printIn("Hello, world ) "ye void loop() { Af (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 declarac rata de transfer a acestei conexiuni seriale ca find 4800 (mySerial.begin(4800)) (cata de transfer o stim din specificatile dispozitivului cu care urmeaza sa ne conectam). In continuate, orice caracter primi 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 sao inlocuiesti cu SoftwareSerial, ca mai sus. SPI SPI este 0 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 obicci librariiscrise 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 i atunci cand auzi vorbindu-se de ei. Comunicarea SPI se face folosind patru canale (fire de conexiune) MISO ~firul prin care dispozitivele slave trimic 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 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 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 0 functionare defectuoasa. In cazul Arduino UNO, pinii Arduino SPI sunt MISO ~ pinul digital 12, MOSI ~ pinul digital 11, SCK ~ pinul digital 13. Pinul default $S 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. cand vrei sa comunik La modul concret, daca ai doua dispozitive SPI, vei incepe prin a identifica pinii MOSI, MISO, SCK si $S pentru ficcare dispozitiv. Vei conecta apoi impreuna pinii MOSI ai celor doua dispozitive, impreuna cu pinul Arduino MOSI, la fel si pentru MISO. K. Pentru pinii SS, vei conecta pinul primului dispozitiv la un pin digital Arduino, iar pinul celui de-al doilea dispozitiv la un alt pin digical Arduino 2c Comunicarea 12C 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 12C are o adresa (care se poate sau nu modifica). De obicei, vei intalni dispozitive 12C cu adresa fixa (pe care nu o poti modifica), sau disporitive la care vei putea alege adresa I2C dinte-o lista de cateva adrese prestabilite (lucru pe care de obice 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 12C nu ceste facil. Primul lucru pe care il fac atunei cand am nevoie sa comunic cu un dispozitiv I2C este sa caut 6 libratie deja scrisa pentru disporitivul 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 libratie, eu avand acces doar la informatia uta. In cazul Arduino UNO, pinii I2C pentru Arduino sunt pinul analogie 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 12C, 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 conecteri si pinul de adresa la GND sau la VCC (in cele mai multe cazuri, pinul de adresa este deja conectat, dar nu intordeauna). Un exemplu de senzor 12C este senzorul de temperatura 12C, Pinul de adresa este marcat pe placa cu “ADDRO”. Dispozitivul acest pin se poate conecta la pinul GND (si atunci dispozitivul va avea adresa “Ox48”), poate fi conectat la VCC (si atunci dispozitivul va avea adresa “0x49”, poate fi conectac Ja pinul SDA (Gi atunci dispozitivul va avea adresa “Ox4A”), sau poate fi conectat la pinul SCL (si atun dispozitivul va avea adresa “Ox4C”). 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 hetp://www.robofun.ro/senzor_temperatura_tmp102 Senzori Acceleratie Senzorii de acceleratie detecteaza (destul de evident :), acceleratia, Se pot folosi pentru masurarea acceleratilor instantance pe care le inregistreaza un element in miscare, sau pentru a devecta directia verticala (pe baza acceleratiei gravitationale g, care are verticala). Orice smare- phone are deja incorporat un accelerometru (pe langa multe alte dispozitive), care accelerometru este folosic pentru rotirea automata a ecranului atunci cand intorci telefonul. Atunci cand roresti telefonul, acceleratia gravitationala a Pamancului (care intordeauna are verticala) isi schimba oriencarea in raport cu telefonul (pentru ca telefonul se roteste), si astfl pozitia telefonului este derectata, rotdeauna directi De asemenea, un accelerometru este utilizat pentru a sesiza miscarea. De exemplu, in cazul unu joystick WII, acceleromerrul pe 3 axe din interiorul acestuia simte miscarea mainii si misca jucatorul de pe ecran in consecinta (ca 0 mica paranteza, un pic mai tarziu vom vedea cum putem conecta direct la Arduino joystick-ul WI). 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 folosese 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 cconectare pe [2C) sunt mai exacte si mai putin afectate de gomot decat cele analogice. Acceleromertele ‘cu conectare analogica sunt insa cu mult mai simplu de folosie. Un alt parametru al unui acceleromecru 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 mule mai mare de atat, ca sa iti pastrezi totus precizia, Banda unui accelerometru ("bandwidth") determina de cate ori pe secunda poate fi citi senzorul de catre Arduino, Un accelerometru cu 0 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 0 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, ceca ce inscamna 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 mule decar 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 SV, 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 pinii X, Y si Z de catre ADXL335 sunt raportate la tensiunea maxima de 3.3 V. Arduino 3.3 V Arduino GND Arduino Analog0 Arduino Analogi Arduino Analog2 Arduino 3.3 void setup() { Serial.begin (9600); analogReference (EXTERNAL) ; ) void loop() { float xAcc=readAcc (0); float yRec=readAcc (1); float zAcc=readAcc (2); Serial.print ("Acceleratie X: "); ADXL335 VCC ADKL335 GND ‘ADKL35 X ‘ADKL35 Y ADXL335 Arduino AREF Serial. serial. (xAce, DEC) ; ("acceleratie Y: Serial. (yAce, DEC) ; Serial. ("acceleratie Serial.print (zAcc, DEC) ; Serial.printin(); delay (50)7 ) on float readAcc(int port) ( int value-analogRead (port); int milivolts=map (value, 0, 1023, 0, 3300) -3300/27 float acc=(float)milivolts/360; return acc; ) Interesant in codul de mai sus este "analogReference(EXTERNAL)", in rutina secup. 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, exprimaca 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, cesta este un motiv des intalnic ). ADXL345 ADXL345 este un accelerometru digital, care se conecteaza la Arduino prin I2C. Are avantajul de a fi mule 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 ciocanicul (simplu sau dublu) si caderea libera. In acest mod, atunci cand accelerometrul este in cadere libera, va notifica Arduino princr-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 Pare Arduino 3.3 V ADXL345 vec 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, cor 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 acceleromettu foarte capabil, si extrem de configurabil acceleratii intr-o multitudine de game distinete ~ 1g, 1.5g, 2g, 3g; 4g, 8g, 16g). Suporta masuratea de Conectatea la Arduino se face folosind pinii I2C, ca in figura de mai jos. Arduino 3.3 V BMA180 VIO Arduino 3.3 V BMA180 CS Arduino 3.3 V BMALB0 VDD Arduino GND BMAL80 SDO Arduino GND BMAL80 GND Arduino SDA BMALBO SDI Arduino SCL BMALBO SCK #include define DEVICE ( (byte) 0x40) define DATA_xO 0x02, define AXIS SHIFT 2 define DELAY_RATE 500 int counter = 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) { *(bufft+) = Wire.read(); } ) void setup() { Wire.begin(); Serial.begin(115200) ; Serial.flush(); delay (15); int axis(5] = {0x0101, 0, 0, 0, O}; void Loop () ‘ readFrom(DATA_X0, 6, (byte*) (axist1)); serial. (millis()s Serial.print ("="); Serial. (counter); Serial. Meee Serial.print (axis(1])s Serial. alee Serial (axis (21); Serial. tamale Serial.print (axis[3]}s Serial.prii Varianta de cod de mai sus doar citeste informatia asociata acceleratiei pe cele uci axe. Un cexemplu de cod mai complex, in care este setata si gama, este disponibil aici - yw. wn.ro/accelerometru_bmal: MMA8452Q Arduino 3.3 V Mag4529 3.3V Arduino GND 11A84529 GND 11A84520 SDA Mag4529 SCL Arduino SDA Arduino SCL MMA8452Q este un acceleromerru ieftin, suficient de capabil. Suporca trei game de acceleratie (2g, 4g, 8g). Conectarea la Arduino se face folosind pacru fire ca in figura de mai sus. Pentru cod, exista o librarie foarte bine documentata, disponibila aici - sw robofun.r rom. [8452 Accelerometru pentru automobil O idee relativ simpla, dar de efeet, bazata pe un accelerometru, 0 placa Arduino si cateva led-uri (prinse sau nu in bordul masinii). Atunci cand accelerezi sau cand iei curbe cu viteza, acceleromerrul detecteaza accelerat atat pe directia de inaintare a masinii, cat si pe axa laterala (perpendiculara pe directia de inaintare). Informatie culese de acceleromerru sunt afisate pe un panou cu led-uri. Obt astfel, un dispozitiv care iti ofera informatii despre acceleratia masini tale, atat pe directia de inaintare cat si pe directie lacerala. 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, jar acunci 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 cencrul, sugerez led-uri verzi, apoi led-uri galbene, iar pe exterior led-uti 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-uti brick si o placa din plexiglass negru sau gri, in care dai gauti 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).. 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 uebuie ceva curaj sa gauresti bordul masinii. In afara de led-uri, mai ai nevoie de 0 placa Arduino si de un accelerometru, Poti alege orice accelerometru ai la indemana, Ideal ar fi un accelerometru cu 0 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 utiliza 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 Iucru 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 iciu 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 folosici 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 cot asa (daca vrem sa aprindem led-ul legat la pinul digital 0, vom folosi digital Write(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 A 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 dreapra lui la pinul digital 3, led-ul de deasupra lui la pinul digital 12, si wot asa). define #define define #define define define #define si define 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 AS poate fi adresat ca pin digital 19 pinMode(19, OUTPUT) ; //led-ul din centru va sta aprins tot timpul digitalWrite(2, HIGH); ) float oldaccx; float oldaccy; void loop() { float acc = smooth (readAcc (0), SMOOTH_X, oldAccx) float acc = smooth(readAcc(1), SMOOTH_Y, oldAccY) + //led-urile pe directie orizontala, din dreapta if (accX > PRAG_X_1){ digitalWrite (3, AIGH); } else { digitalWrite(3, LOW); } if (accX > PRAG_X_2){ digitalWrite (4, HIGH) ; 1 else { digitalWrite(4, LOW); } if (accX > PRAG_X_3){ digitalwrite (5, HIGH); } else { digitalWrite(5, LOW); } /fed-urile pe directie orizontala, din stanga Af (accX < - PRAG_X_1)/ digitalWrite(6, HIGH) ; } else { digitalWrite(6, LOW); } if (accX < -PRAG_X_2){ digitalwrite(7, AIGH); } else { digitalWrite(7, LOW); b if (accX < -PRAG_X_3){ digitalwrite(8, HIGH); } else ( digitalWrite(8, LOW); } /Med-urile pe directie verticala, din partea de sus if (accX > PRAG_X_1)( digitalWrite (3, RIGH); } else { digitalwrite(9, LOW); } LE (accx > PRAG_X_2){ digitalWrite (Id, st¢H) ; , else { digitalWrite(10, Low); } if (accX > PRAG_X_3)( digitalWrite(I1, HIGH); } else { digitalWrite(11, Low); } //led-urile pe directie verticala, if (accX < - PRAG_X_1)( digitalwrite (12, HIGH); } else { digitalwrite(12, LOW); } Af (accX < -PRAG_X_2){ digitalwrite (13, HIGH); } else { digitalWrite(13, LOW); } if (accX < -PRAG_X_3){ digitalWrite (13, HIGH); 1 else { digitalWrite(19, LOW); } ) float readAcc(int port) ( int value=analogRead (port) + int milivole! float acc~(float)milivolts/360; return acc? ) din partea de jos iap (value, 0, 1023, 0, 3300) -3300/2; float smooth(float data, float filterval, float smoothedVal) { if (filterval > 1) ( filterval = .997 } else if (filterval <= 0){ filterval } smoothedVal = (data * (1 - filterval)) + (smoothedval return (float) smoothedVal; ) 05 * filterval); 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 filtsate trece-jos pentru a obtine un raspuns mai lent, Filtrarea se face de catre functia smooth, Daca climinam 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 parametti sunt mai apropiate de unu, cu atat led-urile reac 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 masoata valori ale acceleratiei intre 0 si 3 g, pragurile vor fi si cle 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 : 4£ (accx > PRAG X_1){ digitalWeite(3, BIGH): , else { digitalWrite(3, LOW); 1 In rest, esti liber sa te joci cu valorile pragurilor si cu cele doua valori de filerare pana cand sistemul functioneaza exact asa cum vrei tu. O implementare interesanta a acestui gen de proiect(simplificata de faprul ca masina respectiva avea deja led-uri in bord, vei gasi aici - pe nbc: Maal STS ) riftbox-feature - gases Tar aici - hupil/www.caranddriver.com he-racel implementare comerciala extinsa a principiului, Senzori de Apasare Senzorii de apasare ofera 0 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 vvazut 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-1 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 apasate isi modifica rezistenta, se va modifica si curencul 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 AO si sao 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 wrecuta"), fara a fi etalonate neaparat in newtoni, Senzorul este capabil de 0 precizie de aproximativ 10 9, Iueru pe care trebuie sal iei in considerare daca veci sa construiesti un cantar de farmacie. UCU] (o sere) 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 nivelForta = analogRead(0); Serial.print ("Nivel Forta: "); Serial.printin(nivelForta, DEC) + ) Cand lipesti firele pe cerminalele senzorului, fii foarte acent. Pastreaza cat mai putin timp lecconul in contact cu terminalele senzorului, altel risti sa topesti plasticul din jur (ccea ce va duce la distrugerea senzorului). Cea mai buna metoda este sa copesti mai intai un pic de fludor pe terminal, poi separat topesti un pic de fludor pe fir, apoi le pui in contact si finalizezi lipieura. Daca din diverse motive fludorul nu adera rapid pe terminalul senzorului (1-2, maxim 3 secunde), atunei ridica letconul siincearca din nou peste 30 de secunde cand s-a racit rerminalul. 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 sunc intre 100 ohm si 10 KOhm. Usilizarea 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. Rae 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 .printin (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 puncr de vedere al functionarii, un astfel de senzor poate fi vazut ca un potentiometry rezistiv cate 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 curencul 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 AO si sao 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, clectrice creste, iar daca il indoi spre dreapta, valoarea scade). Astfel, poti determina cexact atat directia indoiti, cat si cat de mule este indoit senzorul Pentru etalonare, cel mai simplu este sa faci incercari repetate. Astfel, prima data vei lasa tial Monitor. Acca valoare este valoarea pe care o vei folosi mai departe in codul tau ca sa detectezi cand senzorul este perfect drept. senzorul liber si vei urmari ce valoare ai in § Arduino 5V PIN1 senzor Arduino GND PIN1 Rezistor 10K PIN2 Rezistor 10K Pin? Senzor Arduino Analog0 PIN2 Rezistor 10K void setup() { Serial.begin (9600); ) void loop() { int nivelForta = analogRead (0); Serial.print ("Nivel Indoire: "); Serial.printin(nivelForta, DEC) ) Senzor Piezo Senzorul piezo ofera © 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 AO), vom sesiza o citire pozitiva pe pinul AO ori de cate ori senzorul vibreaza. Daca ne-am opti doar aici (si poti incerea sa faci doar montajul deseris 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 vva ramane la valoarea citita in momentul vibratici (sau va scadea foarte incet spre 0). Ca sa fortam 0 revenire la 0 dupa ce vibratia mecanica a disparut, se conecteaza un rezistor cu valoare mare (de cexemplu, 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 0 valoare suficient de buna. Codul sursa este extrem de simplu, nu face altceva decat sa citeasca valoarea de pe pinul analogic ‘AO si sao 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. void setup() { Serial.begin (9600); ) void loop() { int nivelVibratie = analogRead(0)+ Serial.print ("Nivel Vibratie: "); Serial.printin(nivelVibratie, DEC) + ) Toba cu senzori piezo Un senzor piezo este capabil sa dececteze vibratile. Ori de cate ori este facut sa vibreze, la bornele Iui apare o tensiune electrica, Aceasta tensiune clectrica 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. void setup() { Serial.begin (9600); ) void loop() { int v = analogRead (0); Serial.printin(v); Daca vei misca (sau vei atinge cu degetul) senzorul piezo conectat la portul analogic zero, vei vvedea ca valoarea afisaca in interfata de debug se modifica, si apoi scade foarte foarte incec inapoi la zero. Ca sa fortam valoarea sa scada spre zer0 mai rapid, vom cupla in paralel cu fecare senzor un rezitor de valoare mare (de exemplu, un megaOhm). Unul dintre piniirezistorului se va conecta f irl 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 0 secunda, vom avea iarasi o citire zero pe senzor. Cu cat alegi un 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 Iucru cu programul de mai jos. #define PRAG 3 void setup() { Serial.begin (9600); ) void loop() { int v = analogRead (0); if (v > PRAG) { Serial.printin(v) ; ) Rolul instructiunii JF 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 fapcului 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 pencru 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, ysnBu} Jeqno un no yez}jees zeunzng ayeang ulp 2sip Realizeaza sase astfel de discuri, cate unul pentru fiecare senzor. In buzunarul taiac 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 funetioneaza corect, poti sigila buzunarul cu un lipici peneru plastic sau cu banda dublu adeziva. Vei obtine in final sase astfel de discuri de burete, fiecare disc din burete avand inglobac un senzor piezo in interior. Mai verifica inca 0 data ca atunci cand lovesti fiecare disc in parte, veri informatiile corespunzatoare in interfata de debug. Foloseste programul de mai jos pentru acest test. fdefine PRAG 3 void setup() { Serial.begin (9600); ) void loop() { for (int i = 0; i <5; itt) { int v = analogRead(i); if (v > PRAG) { Serial.print ("DISC :"); Serial.print (i); Serial.print (";"); Serial.print ("VAL :"); Serial.printin(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 #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, 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() { Serial begin (9600) ; Serial.printin ("BEGIN"); for (int i=0; i 10) ( if (1inProgress{il) { inProgress[i] = true; sum[i] = 07 count [il = 07 timestart (i] = millis(); ) ) Af (inProgress[i]) { sum[i] = sum[i] + values [ily count [i] = count[i] + 1; if ((values[i] <= 10)&((millis() - timeStart[i]) > DELAY_PER_SOUND)) inProgress[i] = false; doplay(i, sum{il}; ) ) } ) void checkStop() { for (int i = 0; i < SENSOR_COUNT; i++) { Af ((millis() - playStartTime[i]} > NOTB_DURATION) { playStartTime[il = 0; noteOf£ (0, stringli] ,127)+ ) } ) void doPlay(int index, double strength) { Serial.print (index) ; Serial.print ("="); Serial.printin (strength); noteOn (0, string[index], 127) playStartTime(index] = millis(); void noteOn (byte channel, byte note, byte attack talkMIDI( (0x90 | channel), note, attack veloc: ) void noteOff (byte channel, byte note, byte release_velocity) { talkMIDI( (0x80 | channel), note, release_velocity); ) void talkMIDI (byte cmd, byte datal, byte data2) { digitalWrite(LED_PIN, HIGH); mySerial.weite (cmd); mySerial.write(datal) ; if( (omd & OxFO) <= 0xB0) { mySerial.write(data2); } digitalWrite(LED_PIN, LOM); Codul de mai sus se bazeaza pe exemplul dat in sectiunea despre Musical Instrument Shield, asa a 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 lovie un dise, vreme de NOTE_DURATION millisecunde se genereaza sunetul. Functia checkStop, apelata imediat la inceputul functiei oop verifica pe rand fiecare senzor daca nu cumva a trecut NOTE_DURATION milisccunde de cand a inceput sunetul asociat acelui senzor, Daca a trecut, atunci opreste sunetul. Imediat dupa ce a fost apelata funcria checkStop in Joop, urmeaza un ciclu for care verifica ficcate senzor pe rand. Daca valoarca citita pe unul dintre senzori depaseste 0 valoare prestabilita, inseamna ca cercul de burete respectiv a fost lovit si atunci se genereaza sunetul corespunzator. 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 navigatialiliacului). Acestia sunt senzori destul de precisi, foarte usor de folosit si a cator 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 unci raze de humina infrarosic. Acesti senzori au doua zone active, 0 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 0 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 mule 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 tun robot care ocoleste obstacole, un singur senzor 10-80 cm este suficient (cand obicctul ajunge la mai putin de 15 cm, faci roborul sa-si schimbe directia si sa-l ocoleasca. Pentru un robot de sumo insa, unde ste 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 © combinatie echilibrata intre pret si performanca, In sfutsic, a ereia categorie de senzori sunt senzori de ip laser. Acestia sunt cei mai preci si cei mai rapizi, dar por costa cu un ordin sau doua de marime fata de cele doua categorii anterioare (in gama surelor sau miilor de euro pe bucata). 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.printin(valoareSenzor, DEC ss r 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 0 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 destul de mari consumatori de curent si sunt afectati de percurbatii 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 ~ sila care atat motoarele cat si senzorii merg pe aceeasi baterie). Incr-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 motoarcle sau alti mari consumatori de energie. Alta abordare este sa faci medierea valorilor citite de la senzor, ca mai jos. int readDistanceMiediata() { int sum = 0; for (int i=0; i #define PRAG_SENZORT 90 define DURATA_NOTA 2000 define INSTRUMENT 7 //(de 1a 1 le 128) define VOLUME 127 // (maxim 127) Softwareserial mySerial(2, 3); byte note = 0; byte resetMIDI byte ledPin = 13; static byte senzori[6]= ( 0, 1, 2, 3, 4, She byte triggered(16) = ( 0, 0, 0, 0 0, OFF static byte string[6] = ( 60, 62, 64, 65, 67, 6B}7 byte hitNote[6] = ( 0, 0, 0, 0, 0, OFF 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] = OxFFFFFFFF; } talkMIDI(0xB0, 0x07, VOLUME); //setare volum talkMIDI(OxCO, INSTRUMENT, 0); //setare instrument void loop() { for(int in; ix; ++i) { if ((analogRead(senzori[i]) < PRAG_SENZORI) && (triggered{i] triggered[i] = 1; noteOn(0, stringlil, 127)+ ) else if((triggered[i] == 1) &&@ (analogRead(senzori[i]) >= PRAG_SENZORI)) ( triggered{i] = 07 timestamp[i] = millis()s hitNote[i] = 1; ) ore } for(int i=0; i<6; ##i) ( if( (millis() > timestamp[i] + DURATA_NOTA) s& (hitNote[i] noteOf£ (0, string[i] ,127); hitNote[il] = 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 datal, byte data2) { digitalWrite(ledPin, HIGH); mySerial.write (cmd) mySerial.write(datal) ; i£( (cmd & OxFO) <= 0xBO) ( 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 0 valoarea prea mate, riscam sa depasim valoarea citita de senzor in mod normal, si atunci notele vor fi generate tot timpul. Daca setam 0 valoare prea mica, atunci vom ajunge sub valoarea citita atunci cand obturam raza laser cu mana si nu vom reusi sa generam note niciodata, Veei schema de mai jos pentru mai mulea claritate. Cel mai simplu sa obstii 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 oburata cu mana, si apoi sa setezi o valoare care sa fie cu 50 ~ 100 mai mare decat valoarea citita atunci cand raza laser este obcurata. Urmatoarea constanta, DURATA_NOTA defineste cat_ timp se aude 0 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 lege orice valoare doresti din lista de mai jos. Denumirile instrumentelor sunt in limba engleza (lista a fost extrasa direct din documencul 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 afi singur. VOLUME defineste cat de tare doresti sa se auda notele. Valorile posibile sunt intre 0 si 127. Valoare citita sub raza laser (njur de 900-100) — PRAG_SENZOR (injurde 100 420) Valoare citita cand obturam raza cu mana {njude 10-200 Un film cu o astfel de harpa laser gasesti aici http://www. tehnorama.ro/the-sound-of-shadow-and-light-the-movie/ 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 0 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 0 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 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 #include byte mac[] = { OXDE, xAD, OxBE, OxEF, OxFE, OxED }; IpAddress server(209,85,148, 11); // Google EthernetClient client; void setup() { Serial.begin(9600); if (Ethernet .begin(mac) == @) { Serial.println("Nu s-a reusit initializarea placii de retea folosind DHCP"); delay(1000); Serial.printin("conectare in progress..."); if (client.connect(server, 80)) { Serial.println("conectat"); Client .printin("GET /search?q=arduino HTTP/1.0"); Client .printin(); } else { Serial.println("conectare esuata"); i} + void loop() { if (client.available()) { char c = client.read(); Serial.print(c); } if_(!elient.connected()) { serial.print1n( Serial.printin("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 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 0 adresa unica si s-au complicat in halul asta. Exista 0 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-| 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 - 0 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 0 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 "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 |-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 #include byte mac{] = { OXDE, OxAD, OxBE, OXEF, OxFE, OxED }; IPAddress server (209, 85,148,101); // Google IPaddress arduinoIP(192,168,0,99); // Arduino EthernetClient client; void setup() { Serial.begin(9600); Af (Ethernet .begin(mac, arduinoIP) == 0) { Serial.printin("Nu s-a reusit initializarea placii de retea folosind o adresa IP statica"); + delay(1006) ; Serial.printIn("conectare in progress if (client.connect(server, 80)) { Serial.printin("conectat"); client .printin("GET /searchaq=arduino HTTP/1.0"); Client .printin(); } else { Serial.println("conectare esuata"); } 2 void loop(){ //EXACT LA FEL CA IN EXEMPLUL PRECEDENT i 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 #include byte mac[] = { OXDE, OxAD, OxBE, OxEF, OxFE, OxED }; 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.printIn(Ethernet .local1P()); void loop() { EthernetClient client = server.available(); if (client) { serial.printn("conectare client nou"); boolean currentLinersBlank = true; while (client.connected()) { if (client available()) { char c = client.read(); Serial.write(c); if (c == '\n' && currentLinetsBlank) { client. print1n("HTTP/1.1 200 OK"); client. printin("Content-Type: text/html"); client .print1n("Connnection: close"); client .printin(); client .print1n("") ; client .print1n(""); Client .print1n(""); for (int analogChannel = 0; analogChannel < 6; analogChannel++) { int sensorReading = analogkead(analogchannel); client.print("* pe portul analogic "); client . print (analogChannel) ; client.print(" s-a citit valoare client . print (sensorReading) ; client .printin("
"); u 3 client. print1n(""); break; } if (c == '\n') { currentLineIsBlank = true; + else if (c != '\r') { currentLinersBlank = false; a } } delay(1); client .stop(); Serial.printin("clientul a incheiat sesiunea"); 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 0 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. 9 © Obap:/192.168.1.177 pe port analog 0 a cit aloares 10 pepo analoge 1 sa cit valoarea 120, pe port analoge 2 sa cit valoaree 210, saci valoarea 43, ‘a cit valoarea 99 peportl analoge 5 ta cit valoarea 121 Daca deschizi un browser si accesezi serverul pe care tocmai I-ai creat, vei vedea un rezultat similar cu cel din imagine. Dat find 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 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-| 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 0 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 #include byte mac{] = { @x00, OxAA, OxBB, OxCC, @xDE, x02 }; char serverName[] = "wnw.google.com"; EthernetClient client; void setup() { Serial. begin(9600) ; if (Ethernet. begin(mac) == 0) { Serial.printin("Eroare in configurarea folosind DHCP."); } delay (1000) ; Serial.println("conectare in progres..."); if (client.connect(serverName, 80)) { serial.printin("conectat"); client. print1n("GET /search?q=arduino HTTP/1.0"); client .printin(); else { Serial.print1n("conexiune esuata"); + } void loop() { //A FEL CA IN EXEMPLELE PRECEDENTE Multumita librariei excelent scrise, modificarile sunt minimale (doar cele doua linii marcate cu bold), toata implementarea fiind facuta direct in librarie. 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, 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. w#include #include #include #include Liquidcrystal led(7, 6, 5, 4, 3, 2); char username[] = “arduino"; byte mac{] = { ®x08, BXAA, OXBB, OXCC, OXDE, 0x1 }; 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(9690); Serial.print1n("Incere sa obtin o adresa IP folosind DHCP if (!Ethernet.begin(mac)) { Serial.print1n("esec in obtinerea unei adresa IP prin DHCP, vom adresa IP setata manual"); Ethernet.begin(mac, ip); iz Serial.print("Adresa IP:"); Serial. print1n(Ethernet .local1P()); hy connectToServer(); led. autoscroll(); led.clear(); void loop() { if (client.connected()) { if (client.available()) { char inchar = client.read(); currentLine += inChar; folosi if (inChar == '\n') { currentLine ="; } if ( currentLine.endswith("")) { readingTweet = true; tweet ="; } if (readingTweet) { if (inchar != '<') { tweet += inchar; } else { readingTweet = false; Serial. print1n( tweet); Ied.clear(); Icd. print (tweet) ; Icd.autoscroll(); client .stop(); 3 } ; i else if (millis() - lastattemptTime > requestInterval) { connectToServer(); } + void connectToServer() { Serial.print1n("conectare la server...")j if (client.connect(servername, 80)) { Serial.print1n("lansez request HTTP..."); client. print ("GET /1/statuses/user_timeline.xml?screen_name="); client. print (username) ; client .printin("&count=1 HTTP/1.1"); Client.println("HOST: api.twitter.com"); client .printin(); + lastAttemptTime = millis(); 3 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-I 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). 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 unei linii de text este marcat prin caracterul "\n"). Atunci cand linia curenta este "", inseamna ca incepand din acest punct, pana cand intalnim textul "" avem continutul tweet-ului care ne intereseaza. Imediat ce am intalnit caracterul "<" (care marcheaza inceputul pentru ) tweet-ul s-a incheiat. Putem afisa tweet-ul pe LCD ( /cd.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. Senzori Atmosferici Presiune Atmosferica —- BMP085 Senzorul BMPO85 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 acmosferice masurate se poate calcula si altitudinea (lucru foarte util la drone si alte dispo7i zburatoare). Conectarea senzorului la Arduino se face prin I2C, astfl ca avem nevoie de doar doi pi (in afara celor doi pini de alimentare). Pentru a citi valorile senzorului recomand o librarie open-source, disponibila aici : htp://svww.robofun,ro/senzor_presiune bmp085 (primul link, “Librarie Arduino’). Dupa instalarea librariei, codul sursa este extrem de simplu, ca mai jos. Arduino {UNO Arduino 3.3 V BMPOBS VCC Arduino GND BMPO85 GND Arduino SDA BMPO85 SDA Arduino SCL BMPOBS SCL #include include BMPOSS dps = BMPOBS(); long Temperature = 0, Pressure = 0, Altitude = void setup(void) { Serial.begin (9600); Wire.begin(); delay (1000); dps.init (); delay (5000) ; void loop(void) { dps .get Temperature (eTemperature) ; dps .get Pressure (sPressure dps .getAltitude (Gal titude) ; Serial.print ("Temp(C) :")7 Serial.print (Temperature) ; Serial.print(" Alt (cm):")+ Serial.print (Altitude) ; Serial.print(" Pressure (Pa) :"); Serial.printn (Pressure); ngurul hucru de remarcat aici este delay-ul de 5 secunde din setup, necesar pentru initalizarea Presiune Atmosferica — MPL115A1 MPLI1SAL este destul de similar cu BMPO85. 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 MeLLI5A1 vec Arduino GND MPLLISA1 GND Arduino Digital 9 MPLLISA1 SDN Arduino Digital 10 MPLLI5A1 CSN Arduino Digital 12 MPLLISA1 DO Arduino Digital 11 MPLLISA1 SDT Arduino Digital 13 MPLLISA1 SCK ‘Codul sursa integral in vei gasi la adresa: 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 9% RH ). Conectarea la Arduino se face folosind doi pini digital. PC Me AU (0) Arduino 5 V sums vec Arduino GND ‘SHTIS GND Arduino Digital 9 SHT15 DATA Arduino Digital @ SHTLS ScK Codul sursa integral disponibil aici : in.ro/senzor 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 SHTI5 (poti face cel mule o citire la 2 secunde). Ca necesar de pini, este foarte modest, avand nevoie doar de un singur pin digital pentru conectarea cu Arduino, Pero: Arduino 5 V pHT22 vec Arduino GND DET22 GND Arduino Digital 2 DHT22 PIN2 Rezistor 10K conectat intre DTH22 VCC si DHT22 PIN2 Mai departe, instaleaza libraria pentru Arduino disponibila aici : herp://www.robofun.ro/senzor_umiditate temperatura_dht22 #include define DHT22_PIN 2 DHT22 myDHT22 (DHT22_PIN); void setup (void) { Serial.begin (9600); Serial.print1n("DHT22 Library Demo", ) void loop(veid) { DHT22_ERROR_t errorCode; delay (2000) ; Serial.print ("Requesting data...")7 errorCode = myDHT22.readData (); switch (errorCode) t case DHT_ERROR_NONE: Serial-print ("Got Data " Serial.print (myDHT22.getTemperaturec()) + Serial.print ("C "); Serial.print (myDHT22.getHumidity()) + Serial-printin("$"); breal case DHT_ERROR_CHECKSUM: Serial-print ("check sum error "); Serial-print (myDHT22.getTemperaturec()) + Serial.print ("C "); Serial.print (myDHT22.getHumidity()) + Serial.printin("s"); breal case DT_BUS_HUNG: Serial-printin("BUS Hung "); breaks case DAT_ERROR NOT_PRESENT: Serial-printIn("Not Present "); break; case DET_ERROR_ACK_TOO_LONG: Serial-printin("ACK time out "); breal case DHT_ERROR_SYNC_TIMEOUT: Serial-printin("Sync Timeout "); break; case DRT_ERROR_DATA TIMEOUT: Serial-printin("Data Timeout “); break; case DT_ERROR_TOOQUICK: Serial.printIn("Polled to quick "); breal

You might also like