Calculatoare
Calculatoare
Cuprins
Introducere
Capitolul 1. Sisteme mobile
1.1. Roboti mobili
1.2. Clasificarea roboților mobili
1.3. Utilizări ale roboților mobili
Capitolul 2. Tehnologia Bluetooth.
2.1. Modele de utilizare
2.2. Integrarea tehnologiei Bluetooth în dispozitive
2.3. Specificațiile tehnologiei Bluetooth
2.4. Arhitectura de rețea
2.5. Ahitectura hardware
2.6. Arhitectura software
2.7. Versiuni de Bluetooth
2.8. Securitatea tehnologiei Bluetooth
Capitolul 3. Senzori
3.1. Introducere
3.2. Caracteristicile senzorilor
3.3. Clasificarea senzorilor
3.4. Senzorul pentru gaz
Capitolul 4. Implementarea sistemului mobil
4.1. Schema bloc a sistemului
4.2. Introducere
4.3. Descrierea plăcii de dezvoltare Arduino Uno
4.4. Caracteristicile generale ale microcontroller-ului ATmega 328
4.5. Noțiuni de bază despre punte H și driver de motor
4.6. Senzorul de gaz MQ-6
4.7. Modulul Bluetooth Mate Silver
4.8. Descrierea modului de realizare a circuitului imprimat pentru driverul L293D și
senzorul de gaz
4.9. Programarea plăcii de dezvoltare
1
4.10. Structura programului
Capitolul 5. Dezvoltarea aplicației client în Android SDK
5.1. Crearea unui proiect nou
5.2. Structura aplicației Android
5.3. Crearea interfeței grafice
5.4. Implementarea programului principal
5.4.1 Configurarea dispozitivului Bluetooth
5.4.2 Scanarea dispozitivelor Bluetooth disponibile
5.4.3 Conectarea dispozitivelor Bluetooth
5.4.4 Gestionarea conexiunilor
5.5. Principiul de funcționare al aplicației
5.6. Instalarea și testarea aplicației pe telefon
Concluzii
Bibliografie
Anexe
2
Introducere
Unul din cele mai importante aspecte în evoluția ființei umane este folosirea uneltelor care să simplifice munca fizică. În aceasta categorie se înscriu și roboții, ei ocupând totuși o poziție privilegiată datorită complexității lor.
Noțiunea de robot datează de peste patru mii de ani. Omul și-a imaginat dispozitive mecanizate inteligente care să preia o parte însemnata din efortul fizic depus. Astfel a construit jucării automate si mecanisme inteligente sau și-a imaginat roboții in desene, carti, filme "SF" etc.
Revoluția informatică a marcat saltul de la societatea industrializată la societatea avansat informatizată generând un val de înnoiri în tehnologie și în educație. Acest lucru a dus și la apariția roboților.
Termenul "robot" a fost folosit in 1920 de cehul Karel Capek într-o piesa numită "Robotul universal al lui Kossum". Ideea era simplă: omul face robotul după care robotul ucide omul. Multe filme au continuat sa arate că roboții sunt mașinării dăunătoare si distrugătoare.
Roboții oferă beneficii substantiale muncitorilor, industriilor si implicit țărilor. În situatia folosirii în scopuri pașnice, roboții industriali pot influența pozitiv calitatea vieții oamenilor prin înlocuirea acestora în spații periculoase, cu conditii de mediu daunatoare omului, cu conditii necunoscute de exploatare etc.
Domeniile de aplicare a tehnicii roboților se lărgesc mereu, ei putând fi utilizațiîn industrie, transporturi și agricultură, în sfera serviciilor, în cunoasterea oceanului și a spatiului cosmic, în cercetarea științifică etc.
Lucrarea prezintă modul de proiectare și realizare a unui minirobot comandat cu telefonul mobil echipat cu placă de dezvoltare Arduino Uno și un senzor de gaz aducând o contribuție la dezvoltarea bazei teoretice și practice de studiu a platformei de procesare Arduino și a posibilităților nelimitate de dezvoltare de aplicații în domeniul roboticii.
Sistemul este proiectat pentru a ajunge în zone cu risc exploziv sau inaccesibile
omului și a măsura concentrația de gaz.
Comunicația cu minirobotului este realizată prin interfața Bluetooth cu un telefon mobil cu sistem de operare Android, care are instalat o aplicație ce permite controlul și vizualizarea valorilor măsurate de senzorul de gaz.
Caracteristici generale ale sistemului:
Șasiu tip mașină, cu patru roți pentru a imita cât mai bine un minivehicul
Două motoare de curent continuu, unul pentru comanda direcției iar celălalt
pentru deplasare
Unitate de procesare Arduino Uno
Senzor de gaz pentru detectarea GPL( Gaz Petrolier Lichefiat)
3
Modul Bluetooth cu interfață serială UART (Universal Asynchronous Receiver and Transmitter)
Aplicație client dezvoltată în Java cu Android Development Tools
Controlarea sistemului mobil prin intermediul telefonului cu sistem de operare
Android
Vizualizarea direct pe telefon a măsurătorilor realizate de senzorul de gaz
Schema bloc a sistemului este prezentată în figura următoare:
Schema generală a sistemului
4
Capitolul 1. Sisteme mobile
1.1. Roboti mobili
Robotul mobil este un sistem complex care poate efectua diferite activități într-o varietate de situații specifice lumii reale. El este o combinație de dispozitive echipate cu servomotoare și senzori (aflate sub controlul unui sistem ierarhic de calcul) ce operează într- un spațiu real, marcat de o serie de proprietăți fizice (de exemplu gravitația care influențează mișcarea tuturor roboților care funcționează pe pământ) și care trebuie să planifice mișcările astfel încât robotul să poată realiza o sarcină în funcție de starea inițială a sistemului și în funcție de informația existentă, legată de mediul de lucru.
Succesul în îndeplinirea acestor sarcini depinde atât de cunoștințele pe care robotul le are asupra configurației inițiale a spațiului de lucru, cât și de cele obținute pe parcursul evoluției sale.
Problemele specifice ce apar la roboții mobili ar fi următoarele: evitarea impactului cu obiectele staționare sau în mișcare, determinarea poziției și orientării robotului pe teren, planificarea unei traiectorii optime de mișcare.
În cazul unui sistem robotic automat distribuit pozițiile spațiale sunt de o extremă importanță și de ele depinde îndeplinirea scopurilor dorite și funcționarea întregului sistem. Cu alte cuvinte, robotul trebuie să fie capabil să-și planifice mișcările, să decidă automat ce mișcări să execute pentru a îndeplini o sarcină, în funcție de aranjamentul momentan al obiectelor din spațiul de lucru.
Planificarea mișcărilor nu constă dintr-o problemă unică și bine determinată, ci dintr-
un ansamblu de probleme dintre care unele sunt mai mult sau mai puțin variante ale celorlalte.
Evitare coliziunii cu obstacole fixe sau mobile (de exemplu alți roboți mobili) aflate în spațiul de lucru al robotului se poate face prin mai multe metode: realizarea unei apărători mecanice care prin deformare oprește robotul, folosirea senzorilor care măsoară distanța până la obstacolele de pe direcția de deplasare, folosirea senzorilor de proximitate, folosirea informațiilor corelate de la mai multe tipuri de senzori.
Localizarea obiectelor se poate realiza și prin contact fizic, dar acesta impune restricții asupra vitezei de mișcare a structurii manipulate. Contactul fizic dintre robot și obiectele din mediu generează forțe de reacțiune care modifică starea robotului.Vitezele mari de lucru fac ca efectele dinamice ale unui contact fizic cu obstacole sau obiecte manipulate să fie riscante (pot duce la deteriorarea obiectelor sau a robotului).
Navigarea robotului este posibilă și fără o determinare a poziției și orientării față de un sistem de coordonate fix, dar această informație este utilă pentru sisteme de comandă a mișcării. Dintre metodele de navigație mai des utilizate se pot menționa: măsurarea numărului de rotații făcute de roțile motoare, folosirea de acceleratoare și giroscoape, geamanduri electromagnetice instalate în teren, semnalizatoare pasive sau semipasive de tip optic sau
magnetic.[1]
5
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
1.2. Clasificarea roboților mobili
Roboții mobili se clasifică astfel:
În funcție de dimensiuni: macro, micro și nano-roboți.
În funcție de mediul în care acționează: roboți tereștri – se deplasează pe sol,roboți subacvatici – în apă, roboți zburători – în aer, roboți extratereștri – pe solul altor planete sau în spațiul cosmic;
În funcție de sistemul care le permite deplasarea în mediul în care acționează există de exemplu pentru deplasarea pe sol:
1. roboți pe roți sau șenile;
2. roboți pășitori: bipezi, patrupezi, hexapozi, miriapozi;
3. roboți târâtori: care imită mișcarea unui șarpe, care imită mișcarea unei
râme etc.;
4. roboți săritori, care imită deplasarea broaștelor, cangurilor etc.;
5. roboți de formă sferică (se deplasează prin rostogolire) etc.
Fig. 1.0. Diferite tipuri de roboți mobili
1.3. Utilizări ale roboților mobili
Utilizările pentru care au fost, sunt și vor fi concepuți roboții mobili sunt dintre cele mai diverse . Mulți roboți din zona micro își găsesc utilizarea în medicină,fiind capabili să se deplaseze de-a lungul vaselor și tuburilor corpului omenesc, înscopul investigațiilor, intervențiilor chirurgicale, dozării și distribuirii de medicamente etc. La fel de spectaculoase sunt și multe utilizări ale macro-roboților:
În domeniul industrial, agricol, forestier: în domeniul industrial roboții mobili sunt reprezentați de AGV-uri (Automated-Guided Vehicles), vehicule pe roți, cu ghidare automată, care transportă și manipulează piese, constituind o alternativă flexibilă la
benzile de montaj; în agricultură există tractoare și mașini agricole fără pilot, capabile
6
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
să execute singure lucrările pe suprafețele pentru care au fost programate; în domeniul forestier roboții mobili pot escalada copacii înalți
În domeniul militar: este luată în considerare de către armata americană perspective înlocuirii soldaților combatanți cu roboți, pentru a reduce riscul pierderilor umane în luptă; roboți mobili de cele mai ingenioase și robuste configurații sunt aruncați în clădiri și incinte din zone de conflict, în scopuri de investigare și chiar anihilare a inamicului;
În domeniul utilităților publice: una dintre cele mai utile și economice utilizăriale roboților mobili o reprezintă inspectarea conductelor de combustibili gazoși și lichizi și a canalelor de canalizare. De exemplu rețeaua de canalizare a Germaniei însumează
400.000 km, iar inspectarea și curățirea acesteia presupune costuri de 3,6Euro pe metru. Numai 20% din conducte sunt accesibile, iar utilizarea roboților poatereduce costurile cu un sfert.
În domeniul distractiv și recreativ: sunt roboții-jucării, roboții pentru competiții
În domeniul serviciilor: Există posibilități deosebit de largi de implementare.Sunt roboți pentru: deservirea bolnavilor în spitale; ajutorarea persoanelor bătrâne saucu diferite handicapuri; ghidarea și informarea publicului în muzee aspirarea șicurățirea încăperilor; spălarea geamurilor și a pereților clădirilor;
În domeniul securității: Multe operații de inspectare și dezamorsare a unor obiecte și
bagaje suspecte sunt executate de roboți;
În domeniul operațiilor de salvare: Roboții salvatori (Rescue robots) sunt utilizați în operațiile de salvare a victimelor unor calamități: cutremure, incendii,inundații.[1]
Roboții mobili au următoarele caracteristici comune:
1. structura mecanică este un lanț cinematic serie sau paralel respectiv tip“master-slave”;
2. sistemul de acționare util escalada copacii înalți
În domeniul militar: este luată în considerare de către armata americană perspective înlocuirii soldaților combatanți cu roboți, pentru a reduce riscul pierderilor umane în luptă; roboți mobili de cele mai ingenioase și robuste configurații sunt aruncați în clădiri și incinte din zone de conflict, în scopuri de investigare și chiar anihilare a inamicului;
În domeniul utilităților publice: una dintre cele mai utile și economice utilizăriale roboților mobili o reprezintă inspectarea conductelor de combustibili gazoși și lichizi și a canalelor de canalizare. De exemplu rețeaua de canalizare a Germaniei însumează
400.000 km, iar inspectarea și curățirea acesteia presupune costuri de 3,6Euro pe metru. Numai 20% din conducte sunt accesibile, iar utilizarea roboților poatereduce costurile cu un sfert.
În domeniul distractiv și recreativ: sunt roboții-jucării, roboții pentru competiții
În domeniul serviciilor: Există posibilități deosebit de largi de implementare.Sunt roboți pentru: deservirea bolnavilor în spitale; ajutorarea persoanelor bătrâne saucu diferite handicapuri; ghidarea și informarea publicului în muzee aspirarea șicurățirea încăperilor; spălarea geamurilor și a pereților clădirilor;
În domeniul securității: Multe operații de inspectare și dezamorsare a unor obiecte și
bagaje suspecte sunt executate de roboți;
În domeniul operațiilor de salvare: Roboții salvatori (Rescue robots) sunt utilizați în operațiile de salvare a victimelor unor calamități: cutremure, incendii,inundații.[1]
Roboții mobili au următoarele caracteristici comune:
1. structura mecanică este un lanț cinematic serie sau paralel respectiv tip“master-slave”;
2. sistemul de acționare utilizat este electric pentru sarcini mici și medii și hidraulic pentru sarcini mari;
3. sistemul senzorial utilizează senzori interni (de turație, poziție, efort) la nivelul articulațiilor, senzori externi(camere TV) pentru scanarea mediului și senzoride securitate( de proximitate, de prezență cu ultrasunete);
4. sistemul de comandă este ierarhizat, de obicei multiprocesor;
5. limbajele de programare utilizate sunt preluate de la roboții staționari.[1]
7
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Capitolul 2. Tehnologia Bluetooth.
Tehnologia wireless Bluetooth implică cerințe hard, soft și de interoperabilitate. Aceasta a fost adoptată sau este studiată nu numai de majoritatea actorilor de pe scena telecomunicatiilor, computerelor și a industriei de entertainment casnic, dar și din diverse domenii precum cel bancar, cel al industriei auto-moto și de îngrijire a sănătății sau cel al automatizării și jucăriilor, etc.
Bluetooth este o traducere în engleză a cuvântului scandinav Blåtand/Blåtann, cum era supranumit regele viking Harald I al Danemarcei din sec. al X-lea. Harald I a unit Norvegia și Danemarca. El era renumit ca fiind foarte comunicativ și se pricepea să îi facă pe oameni să comunice între ei.[2]
Fig. 2.1Sigla Bluetooth
Tehnologia Bluetooth abordează următoarele preocupări majore:
Comoditatea – Bluetooth elimină grămada de fire și cabluri din spatele calculatorului de birou și promite oamenilor de afaceri ca nu vor mai fi îngrijorați de necesitatea de a cumpăra și a purta cabluri specifice pentru conectarea laptop- urilor, telefoanelor mobile, etc. Oferă sincronizarea datelor, fără bătăi de cap, între dispozitivele aparținând aceleiași rețele.
Interoperabilitatea – tehnologia Bluetooth asigura capacitatea dispozitivelor de a comunica între ele indiferent de producatorul dispozitivelor.
Viteza – tehnologia permite realizarea transmisiilor de date și voce de înaltă calitate. Este proiectată pentru a funcționa și în medii cu multe interferențe. Furnizează o viteză de transmisie de 1Mbps și capacitatea sa totală poate suporta până la trei canale de voce simultane.
Puterea – Bluetooth are capacitatea de a limita puterea de ieșire a emițătorului radio în conformitate cu cerințele specifice ale conexiunii.
Securitatea – asigură pentru transferurile securizate de date și/sau voce:
autentificare, encriptare și securitate la nivel de transmisie.[2]
8
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Ideea ce a dat naștere tehnologiei wireless Bluetooth a apărut in 1994 când compania Ericsson Mobile Communications a decis investigarea fezabilității unei interfețe radio de mică putere și cost redus între telefoanele mobile și accesoriile acestora. Ideea a fost ca un dispozitiv radio de dimensiuni reduse, introdus atât în telefon cât și în laptop să poată înlocui cablurile stânjenitoare utilizate pentru a conecta cele doua dispozitive.
Un an mai târziu a început munca inginerească și adevăratul potențial al acestei tehnologii a început să se cristalizeze. Pe de altă parte, prin ruperea lanțului de dispozitive prin înlocuirea cablurilor, tehnologia radio a scos în evidență posibilitatea de a deveni o punte universală către rețele de date deja existente, către interfețe periferice,
și un mecanism de formare ad-hoc a unor mici grupuri private de dispozitive conectate departe de infrastructuri fixe de rețele.
În februarie 1998 a luat ființă Grupul de Interes Special (SIG). Astăzi Bluetooth SIG include companiile promotoare 3Com, Ericsson, IBM, Intel, Lucent, Microsoft, Motorola, Nokia și Toshiba, și mii de companii – membri asociați sau adoptori. Inițial misiunea SIG a fost de a monitoriza dezvoltarea tehnologiei radio pentru domenii restrânse și de a crea un standard global deschis, prevenind astfel devenirea acestei tehnologii proprietatea unei singure companii. Acest lucru a avut ca rezultat apariția primelor Specificații Bluetooth în Iulie 1999. Dezvoltarea ulterioară a Specificțiilor este încă scopul principal al SIG, alături de asigurarea cerințelor de interoperabilitate, armonizarea benzii de frecvență și promoția tehnologiei.
De la bun început, unul dintre scopurile principale ale SIG a fost să includă în Specificațiile Bluetooth un cadru de lucru general, care să asigure interoperabilitatea între diverse dispozitive aparținând unor producători diferiți – atât timp cât utilizează același Profil.
În vreme ce modelele de utilizare descriu aplicațiile și dispozitivele vizate, Profilurile specifică modul de utilizare a stivei de protocoale Bluetooth pentru a asigura interoperabilitatea dispozitivelor. În fiecare profil se specifică modul de reducere a opțiunilor și a setului de parametri din standardul de bază, modul de utilizare a procedurilor din câteva dintre standardele de bază. Se folosește astfel experiența unei
utilizări comune a dispozitivului. Astfel, spre exemplu, un mouse nu are nevoie să comunice cu un headset, așa că ei sunt construiți să utilizeze Profiluri diferite.
Profilurile sunt subiect al Specificațiilor Bluetooth și toate dispozitivele trebuie testate pentru unul sau mai multe Profiluri pentru a îndeplini cerințele de certificare Bluetooth. Numărul de Profiluri continuă să crească odată cu apariția de noi aplicații.
Programul de certificare Bluetooth garantează interoperabilitatea globală între dispozitive indiferent de producător sau de țara în sunt utilizate. Pe parcursul procedurii de testare prin care toate dispozitivele trebuie să treacă, se verifică dacă sunt îndeplinite cerințele cu privire la: calitatea legăturii radio, protocoalele straturilor joase, profiluri și
informația specifică utilizatorului.[2]
9
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
2.1. Modele de utilizare
Profilurile descrise în prima versiune a Specificațiilor se adresează în principal modelelor de utilizare pentru industria telecomunicațiilor și computerelor.
Trei exemple sunt „Internet Bridge”, „Ultimate Headset” și „Automatic
Syncronizer”.
Internet Bridge oferă acces nelimitat la Internet și este o componentă ce ajută la economisirea timpului, mai ales că banda telefoanelor mobile este în continuă creștere. Tehnologia wireless Bluetooth permite navigarea Internet fără conectarea de cabluri, indiferent de localizare, fie folosind un computer, fie utilizând însuși telefonul mobil. În apropierea unui punct de acces al unei rețele cablate, este posibilă conectarea directă a computerului mobil sau a dispozitivului handheld, și tot fără a utiliza cabluri.
Headset-ul permite utilizarea telefonului mobil, fără a trebui scos din geantă, sau fără a fi nevoie să fie ținut în mână în birou sau în mașină.
Sincronizarea automată a calendarelor, agendelor, etc. este o opțiune
îndelung așteptată de mulți dintre noi. Prin simpla intrare în birou, calendarul din telefonul mobil sau dispozitivul PDA va fi automat actualizat să se potrivească cu cel din PC-ul de pe birou, sau vice versa. Numerele de telefon și adresele din agendă vor fi întotdeauna corecte în dispozitivul portabil fără a fi necesare operații suplimentare prin cablu sau infraroșu.[2]
2.2. Integrarea tehnologiei Bluetooth în dispozitive
Multe companii au declarat că tehnologia wireless Bluetooth va fi încorporată în produsele lor, mai ales pe măsură ce componentele Bluetooth se vor ieftini. Conform estimărilor făcute în 2000 de Cahners In-stat Group, disponibilitatea produselor în următorii ani a fost definită în trei valuri.
Primul val, localizat în timp pe durata anilor 2000-2001, include produse precum:
Telefoane mobile și notebook-uri;
Adaptoare pentru telefoane mobile și adaptoare și cartele PC pentru PC-uri și
laptop-uri;
Headset-ul Bluetooth;
PC-uri handheld și PDA-uri.
Al doilea val îl depășește pe primul în multe aspecte. Acesta cuprinde:
PC-uri cu circuite Bluetooth încorporate pe plăcile de bază;
Camere foto digitale, imprimante, faxuri;
Produse industriale și medicale;
Implementări în industria automotivă.
Al treilea va cuprinde:
Telefoane mobile, PC-uri și dispositive portabile ieftine.
10
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
În această etapă de dezvoltare socială mobilitatea oamenilor a crescut constant și tehnologiile wireless pentru comunicații de date și vocale au evoluat rapid în ultimii ani. Nenumărate dispozitive electronice pentru uz casnic, personal sau de afaceri au
fost propuse pieței în ultima perioadă, dar nici o tehnologie de largă utilizare nu se
adresa satisfacerii necesităților de conectare a dispozitivelor în rețele personale(Personal Area Networks – PAN). Cererea pentru un sistem capabil să conecteze dispozitive pentru comunicații de date și vocale pe distanțe reduse a crescut simțitor.
Tehnologia wireless Bluetooth umple acest gol, oferind soluții pentru comunicații vocale și de date fără cabluri, utilizând alimentări standard low-power, tehnologii de cost redus ce pot fi cu ușurință integrate în orice dispozitiv și deschizând astfel calea unei mobilități totale. Prețurile vor fi reduse pentru producția de masă. De asemenea, odată
cu creșterea numărului de unități Bluetooth, vor crește și beneficiile pentru utilizatori.
În figura următoare este prezentată evoluția pieței de chip-uri Bluetooth.[2]
Fig. 2.2Evoluția pieței de chip-uri
2.3. Specificațiile tehnologiei Bluetooth
Specificațiile Bluetooth definesc capabilități de legături radio pe distanțe scurte (aproximativ 10m) sau opțional pe distanțe medii (aproximativ 100m) pentru transmisii vocale sau de date de capacitate maximă 720kbps pe canal.
Gama de frecvențe de operare o constituie banda nelicențiată industrială, științifică și medicală (ISM) de la 2.4GHz la 2.48Hz, utilizând tehnici de împrăștiere a spectrului, cu salturi de frecvență a semnalului duplex de până la 1600 salturi pe secundă. Semnalul execută salturi prin 79 intervale de frecvență de 1MHz, pentru a realiza o bună imunitate la interferențe. Ieșirea RF este conform specificațiilor 0dBm
(1mW) pentru implementările pentru domenii de 10m sau între –30dBm și 20dBm
11
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
(100mW) pentru versiunile pentru domenii mai extinse.
Când s-au alcătuit specificațiile radio, un mare accent s-a pus pe posibilitatea implementării design-ului într-un singur chip CMOS, în consecință reducându-se costul, puterea consumată și dimensiunile, necesare pentru implementarea în dispozitivele mobile.
Pentru comunicațiile vocale sunt utilizate până la trei canale vocale sincrone simultan sau un canal care suportă simultan transmisie de date asincronă și transmisie vocală sincronă. Fiecare canal vocal suportă sincron 64 kb/s în fiecare sens.
Pentru comunicațiile de date un canal asincron poate suporta maxim 723.2 kbps în sens direct în conexiune asimetrică (și până la 57.6 kbps în sens invers), sau 433.9 kbps în conexiune simetrică.
Un master poate utiliza în comun un canal cu până la 7 dispozitive slave simultan
active într-o pico-rețea (piconet).
Interschimbând dispozitivele slave active și inactive (parcate) din piconet, pot fi virtual conectate 255 de dispozitive slave, utilizând PM_ADDR (unui dispozitiv îi revine rândul să participe la comunicație în 2ms).
Pentru a parca și mai multe dispozitive slave se poate utiliza BD_ADDR; astfel nu
mai rămâne nici o limitare asupra numărului de dispozitive slave.
Dispozitivele slave pot face parte din mai multe piconet-uri și master-ul unui piconet poate fi slave în altul; acest tip de rețea se numește scaternet. Pentru a se respecta normele de imunitate la coliziuni între date, un scaternet poate cuprinde până la 10 piconet-uri.[2]
2.4. Arhitectura de rețea
Unitățile Bluetooth aflate în același domeniu spațial de acțiune radio pot realiza
ad-hoc conexiuni punct-la-punct și/sau punct-la-multipunct. Unitățile pot fi adăugate
sau deconectate în mod dinamic la rețea. Două sau mai multe unități pot utiliza în comun un canal al unui piconet.
Fig. 2.3 Diagrama arhitecturii de rețea
12
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Se pot forma mai multe picorețele și acestea se pot lega ad-hoc împreună formând scatternet , pentru a realiza configurații flexibile de comunicații și schimburi de date. Dacă într-un același domeniu spațial se află mai multe pico-rețele, fiecare lucrează independent și fiecare are acces la întreaga bandă de frecvențe. Fiecare pico-rețea este stabilită pe un canal diferit, cu salt în frecvență. Toți utilizatorii participanți la aceeași pico-rețea sunt sincronizați pe acest canal. Spre deosebire de dispozitivele cu infraroșu (IR), unitățile Bluetooth nu sunt limitate de necesitatea vederii directe între ele.
Pentru a regula traficul pe canal, unul dintre participanți devine master în piconet, în timp ce restul unităților devin slave . În conformitate cu Specificațiile actuale ale Bluetooth, pot comunica cu un master, simultan active, până la șapte dispozitive slave. Totuși, numărul unităților virtual atașate unui master, capabile să intre în comunicație este aproape nelimitat.[2]
2.5.Ahitectura hardware
Componenta hard a Bluetooth constă într-o parte analogică radio și o parte
digitală – Host Controller (HC). HC conține o parte de procesare a semnalului digital, numit Link Controller (LC), un nucleu de procesor (CPU core) și interfețele cu mediul gazdă.
Fig. 2.4Structura hardware
LC constă într-o structură hard care realizează procesări la nivelul benzii de bază (baseband – BB) și al protocoalelor stratului fizic. Între funcțiile LC sunt incluse transferurile asincrone și sincrone, codarea audio și criptarea.
CPU core permite modulului Bluetooth să mânuiască procedurile Inquiry și să filtreze cererile Page fără a implica dispozitivul gazdă. HC poate fi programat să răspundă anumitor mesaje Page și să autentifice legăturile la distanță (remote).
Soft-ul LM rulează în CPU core. LM descoperă alte LM-uri și comunică cu ele
prin intermediul Link Manager Protocol (LMP) spre a-și îndeplini rolul de furnizor de servicii și de a utiliza serviciile oferite de inferiorul său, Link Controller.[2]
13
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
2.6. Arhitectura software
În figura de mai jos protocoalele Bluetooth sunt reprezentate prin căsuțe umplute cu culoare. Pentru a asigura compatibilitatea între diverse implementări hard, dispozitivele hard utilizează Host Controller Interface (HCI) ca o interfață comună
între gazda Bluetooth (un PC portabil, de exemplu) și nucleul Bluetooth.
Fig. 2.5Arhitectura software
Protocoalele nivelelor superioare, precum Service Discovery Protocol (SDP), RFCOMM (emulator de port serial, precum RS-232) și Telephony Control protocol (TCS) sunt interfațate cu serviciile din banda de bază prin intermediul Logic Link Control and Adaptation Protocol (L2CAP). Printre sarcinile pe care le are L2CAP se numără segmentarea și reasamblarea pentru a permite pachetelor de date mai mari să fie transportate printr-o conexiune Bluetooth în banda de bază.
SDP permite aplicațiilor să afle informații despre serviciile disponibile și despre
caracteristicile acestora când, de exemplu dispozitivele sunt mutate sau închise.[2]
2.7.Versiuni de Bluetooth
Bluetooth v1.0 și v1.0B – au avut multe probleme și producătorii au avut dificultăți în a
face produsele lor interoperabile.
Bluetooth v1.1 a remediat multe erori găsite la v1.0B. A fost adaugat suport pentru
canale necriptate. A fost adăugat un indicator al puterii semnalului de transmisie(RSSI).
14
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Bluetooth v1.2 este compatibilă cu v1.1. Viteza practică a transmisiei de date a fost
mărită la 721 Kbps, la fel ca la versiunea 1.1.
Bluetooth v2.0 + EDR este compatibilă cu versiunea 1.2. Principala îmbunătățire este introducerea unei viteze de transmisie mai mari numite Enhanced Data Rate, care permite o viteză de 2,1 Mbps. EDR oferă un consum redus de energie datorită unei frecvențe de lucru reduse.
Bluetooth v2.1 + EDR este compatibilă până la versiunea 1.2. Caracteristica principală a acestei versiuni este SSP (Secure Simple Pairing), aceasta îmbunătățește modul de conectare între dispozitivele Bluetooth crescând gradul de utilizare și securitate.
Bluetooth v3.0 + HS(High-Speed) furnizează o viteză de transfer teoretică de până la
24 Mbps.
Bluetooth v4.0 se bazează pe tehnologia cu consum redus de energie și tehnologia de
viteza mare.
Tehnologia Bluetooth se împarte în trei clase de putere, descrise în tabelul următor:
Tabelul 2.1Clasele de putere
2.8.Securitatea tehnologiei Bluetooth
Deoarece semnalele radio pot fi ușor interceptate, dispozitivele Bluetooth au încorporate proceduri de securizare, pentru prevenirea receptorilor rău-intenționați și nevizați de mesaj.
Trei sunt metodele de securizare a informației:
O rutină de interpelare pentru autentificare;
Cifrarea fluxului informațional, ca metodă de criptare;
Generarea unor chei de sesiune.
În algoritmii de securizare sunt utilizate trei entități:
Adresa dispozitivului Bluetooth, care este o entitate publică unică pentru fiecare dispozitiv. Această adresă se obține prin procedura Inquire.
O cheie privată specifică utilizatorului (128 biți), care este o entitate secretă. Cheia privată derivă din procedura de inițializare și nu este dezvăluită niciodată.
Un număr aleator (128 biți), care diferă la fiecare nouă tranzacție. Acest număr
este derivat dintr-un proces pseudo-aleator în unitatea Bluetooth.
În plus față de aceste funcții la nivel de legătură, salturile de frecvență și transmisia limitată spațial ajută și ele la prevenirea recepționărilor neautorizate.[2]
15
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Capitolul 3. Senzori
3.1.Introducere
Senzorul este definit ca fiind “un dispozitiv care detectează sau măsoară unele condiții sau proprietăți și înregistrează, indică sau uneori răspunde la informația primită”. Astfel, senzorii au funcția de a converti un stimul într-un semnal măsurabil, cuprinzând atât traductorul, care transformă mărimea de intrare în semnal electric util, cât și circuite pentru adaptarea și conversia semnalelor, și eventual pentru prelucrarea și evaluarea informațiilor.
Stimulii pot fi mecanici, termici, electromagnetici, acustici sau chimici la origine, în timp ce semnalul măsurabil este tipic de natură electrică, deși pot fi folosite semnale pneumatice, hidraulice, optice sau bioelectrici.
În gestionarea proceselor industriale, deosebit de importante sunt sistemele inteligente de conducere, sisteme ce sunt bazate pe sisteme de calcul integrat sau nu.
Senzorii și traductoarele elemente esențiale ale sistemelor de automatizare a dispozitivelor civile și industriale și se bazează pe un domeniu larg de principii fizice de operare. De asemenea sunt utilizați și în cazul cercetării, analizelor de laborator – senzorii și traductoarele fiind incluse în lanțuri de măsurare complexe, care sunt conduse automat.
Exista foarte multe clasificari ale senzorilor si traductoarelor: cu sau fara contact, absoluți sau incrementali (in functie de marimea de intrare), analogici sau digitali (în funcție de mărimea de ieșire) etc.
Alegerea senzorilor si traductoarelor trebuie făcută ținând cont de proprietatea de monitorizat, de domeniul în care variază aceasta, de dimensiunile ce trebuie respectate sau de geometria sistemului, de condiții speciale de mediu sau de lucru, de tipul mărimii de ieșire și nu în ultimul rând de cost.
Astfel pot fi identificați senzori de proximitate, traductoare de tip Hall, traductoare de deplasare si viteză, senzori și traductoare de forță, senzori de temperatură, senzori de umiditate, senzori pentru gaze, senzori de curent, switch-uri optice, senzori de presiune, cititoare de coduri de bare etc.[3]
3.2.Caracteristicile senzorilor
Caracteristicile principale ale senzorilor pot fi definite prin următorii parametrii:
domeniul de utilizare,
rezoluția (sensibilitatea – cel mai mic increment măsurabil al
stimulului),
frecvența maximă a stimulului ce poate fi detectat (selectivitatea),
acuratețea (eroarea de măsurare raportată, în procente, la întreaga scală),
dimensiunile și masa senzorului,
16
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
temperatura de operare și condițiile de mediu, durata de viață (în ore sau număr de cicluri de operare),
stabilitatea pe termen lung,
costul.
Majoritatea acestor caracteristici sunt precizate în fișele de fabricație ale senzorilor. Sensibilitatea unui senzor este definită ca panta curbei caracteristicii de ieșire sau,
intrarea minimă a parametrilor fizici care va creea o variație a ieșirii.
La unii senzori, sensibilitatea este definită ca parametrul de intrare cerut pentru a produce o standardizare a schimbării ieșirii. La altele, ea este definită ca tensiunea de ieșire dată pentru schimbarea parametrului de intrare.
Eroarea de sensibilitate este punctul de plecare pentru panta ideală a caracteristicii
curbei.
Domeniul de acoperire al senzorului este maximul si minimul valorilor aplicate
parametrilor care pot fi măsurate.
De exemplu, un senzor de presiune dat poate avea domeniul de variatie intre –400 si
+400 mm Hg. Alternativ, extrema pozitivă și negativă sunt de obicei inegale.
Domeniul dinamic reprezintă domeniul total al variației senzorului de la minim la
maxim.
Termenul de precizie se referă la gradul de reproducere al măsurătorii.
Cu alte cuvinte, dacă exact aceleași valori au fost măsurate de un anumit număr de ori, atunci un senzor ideal va scoate la ieșire aceași valoare de fiecare dată.
Senzorii reali scot însă la ieșire valori apropiate de valoarea reală. Să presupunem că o presiune de 150 mm Hg este aplicată unui senzor. Chiar dacă presiunea aplicată este constantă, valorile de la ieșirea senzorului variază considerabil. Apar astfel câteva probleme din punct de vedere al preciziei când valoarea adevărată si valoarea indicată de senzor nu sunt la o anumita distanță între ele.
Rezoluția reprezintă detecția celui mai mic parametru de intrare care poate fi detectat din semnalul de ieșire. Rezoluția poate fi exprimată proporțional cu semnalul citit, fie in valori absolute.
Acuratețea este dată de diferența dintre valoarea actuală si valoarea indicată la ieșirea senzorului. Din nou, acuratețea poate fi exprimată ca un procent sau în valori absolute.
Eroarea de offset al unui traductor este definită ca valoarea ieșirii care exista atunci când ar trebui să fie zero, sau diferența dintre valoarea reală de la ieșirea traductorului și valoarea de la ieșire specificată de o serie de condiții particulare.
Liniaritatea este expresia cu care curba măsurată se diferențiază de curba ideală. Neliniaritatea statică este uneori subiectul unor factori de mediu, inclusiv temperatura,
vibrațiile, nivelul acustic de zgomot si umiditatea. Este important de știut în ce condiții această caracteristică este validă și se îndepărtează de acele condiții care nu furnizează modificări ale liniarității.
Liniaritatea dinamică a unui senzor este o măsură a abilității sale de a urmării schimbăriile rapide ale parametrilor de intrare. Caracteristicile distorsiunii amplitudinii, caracteristicile distorsiunii fazei, si timpul de răspuns sunt importante pentru a determina
liniaritatea dinamică.[3]
17
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Un traductor trebuie să fie capabil să urmărească schimbările parametrilor de intrare indiferent din ce direcție este facută schimbarea, histerezis-ul fiind măsura a acestei proprietăți.
Senzorii nu-și schimbă starea de ieșire imediat când apare o schimbare a parametrului de intrare, de obicei, va trece în starea nouă abia după o anumită perioadă de timp.
Timpul de răspuns poate fi definit ca fiind timpul necesar ieșirii valorilor unui senzor de a trece din starea precedentă spre o valoare stabilită in limitele unui domeniu de toleranță a noii valori corecte. Acest concept este într-un fel diferit de termenul de timp constant (T) a sistemului. Acest termen poate fi definit într-o manieră similară cu cea a unui condesator care se încarcă printr-un rezistor si este de obicei mai mic decât timpul de răspuns.[3]
3.3.Clasificarea senzorilor
Există mai multe criterii de clasificare a senzorilor utilizați în sistemele de
comandă ale proceselor industriale.
Dacă intră sau nu în contact cu obiectul a cărui proprietate fizică o măsoară,
distingem:
senzori cu contact;
senzori fără contact;
După proprietățile pe care le pun în evidență:
senzori pentru determinarea formelor și dimensiunilor (pentru evaluarea în
mediu de lucru);
senzori pentru determinarea proprietăților fizice ale obiectelor (de forță, presiune, de cuplu, de densitate și elastici);
senzori pentru proprietăți chimice (de compoziție, de concentrație, analizatoare
complexe);
După mediul de culegere a informației:
senzorii pentru mediul extern,
senzorii pentru funcția internă,
După distanța la care sunt culese informațiile:
senzori de contact
Senzorii pot fi : acustici, mecanici, magnetici, termici, pentru radiatii, chimici, bioelectrici (preiau semnalele electrice generate de corpul uman, în general), inteligenți, virtuali. Senzorii sunt conectați la circuite de condiționare si prelucrare a semnalelor furnizate
de aceștia.[3]
18
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
3.4.Senzorul pentru gaz
Dintre categoriile de senzori, cele care semnalează, evaluează și monitorizează prezența unor gaze prezintă o importanță deosebită. În acest context, senzorii pe bază de materiale oxidice (SMO) ocupă un loc deosebit datorită, în special, rezistenței lor chimice și domeniului ridicat de temperatură la care pot fi utilizați.
Studiile asupra unui număr mare de oxizi au demonstrat că variația conductivității electrice în prezența unor urme de gaze din aer constituie un fenomen comun oxizilor și nu aparține unei clase specifice /1,2/. Dacă un material oxidic prezintă valori ale rezistivității cuprinse în domeniul 104-108 Ωcm la 300 – 400o C, atunci el va funcționa ca un senzor de
gaze când este încălzit la o temperatură situată în acest domeniu.[3]
Tabelul 3.1Materiale folosite la senzorii pentru gaz
În principiu, un senzor pentru detecția gazelor este compus din:
două terminale pentru rezistența de încălzire;
două terminale de la filmul semiconductor (SnO2);
capsula poroasă ce protejează mecanic senzorul, lăsând gazul să treacă spre el.
Fig. 3.1 Structura internă a senzorului semiconducor (SnO2) pentru
gaze
19
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
La unele modele de senzori capsula este dintr-un material plastic neinflamabil, iar accesul gazului la elementele senzitive se realizează printr-o fantă în partea superioară, fantă care este acoperită cu o rețea(plasă) din oțel pentru a preveni aprinderea gazului.
Rezistența de încălzire aduce senzorul la temperatura optimă de funcționare pentru gazul care trebuie detectat (de obicei intre 200 oC si 400 oC). Materialul sensibil la gaz este bioxidul de staniu (SnO2). Pe suprafața granulelor de SnO2 se adsoarbe oxigen din aer care preia electroni mobili din banda de conducție. Bioxidul de staniu, fiind semiconductor de tip "n" cu zona interzisă mare (3,8eV), va fi sărăcit la suprafață de purtători de sarcină mobili și din această cauză rezistența electrică la contactul dintre granule va fi mare. În momentul în care apare un gaz capabil să se combine cu oxigenul adsorbit, electronii inițial legați de oxigen sunt eliberați în banda de conducție, rezistența electrică a dispozitivului scăzând mult.[3]
Dependența conductanței senzorului în funcție de concentrația gazului reducător este
de tipul:
unde:
G = G0 + A·ci
G – conductanta senzorului in prezenta gazului reducator; G0 – conductanta senzorului in prezenta aerului curat;
c – concentratia gazului reducator;
i – exponent subunitar al concentratiei de gaz (~0,5); A – constanta.
20
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Capitolul 4. Implementarea sistemului mobil
Fig. 4.1 Sistemul mobil (vedere din lateral)
Fig. 4.2 Sistemul mobil (vedere din față)
21
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
4.1.Schema bloc a sistemului
Fig. 4.1Schema bloc a sistemului mobil
Părțile componente ale sistemului mobil sunt:
Sursă de alimentare pentru motoare – acumulatori 6V
Sursă de alimentare pentru Arduino – baterie 9V
Arduino Uno cu microcontroller Atmega 328
Caroserie mașina radio comandată
Două motoare de curent continuu de 6V
Driver de motoare L293D
Senzor de gaz MQ-6
Modul Bluetooth Mate Silver RN-42
Difuzor piezoelectric
LED roșu
22
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
4.2.Introducere
Arduino este o platformă de dezvoltare prin care se pot realiza sisteme informatice capabile să perceapă și să controleze lumea înconjurătoare . Acest instrument este open- source și este compus dintr-un mediu de dezvoltare și o placă de dezvoltare cu microcontroler
AVR.
Fig. 4.2Sigla Arduino
Arduino poate fi folosit pentru dezvoltarea de obiecte interactive. Informația este preluată de la o gamă variată de senzori și comutatoare, se procesează în interiorul microcontrolerului AVR și este transmisă către o gamă la fel de variată de lumini, motoare, actuatoare etc.
Pe piață există o gamă foarte variată de sisteme de dezvoltare bazate pe microcontroler, avantajele pe care le are Arduino față de aceste sisteme sunt:
Costuri de achiziție reduse
Poate fi folosit pe orice sistem de operare (Linux,Windows sau MacOS).
Un mediu de programare simplu și usor de învățat.
Este open source, atât placa de dezvoltare cât și mediul de programare[4]
4.3.Descrierea plăcii de dezvoltare Arduino Uno
Arduino Uno SMD este o versiune a plăcii de dezvoltare Arduino UNO, dar folosește o versiune de montare SMD a cipului Atmega 328P. Această versiune a fost facută ca raspuns la un deficit în aprovizionarea cu cipurile clasice Atmega328.
Fig. 4.3Placa de dezvoltare Arduino Uno
23
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Aceasta are 14 intrări/ieșiri digitale (din care 6 pot să fie folosite ca ieșiri PWM), 6 intrări analogice, un oscilator la 16Mhz, o conexiune pe USB, o mufă de alimentare, un header ICSP și un buton de reset.
Aceasta conține absolut tot pentru a permite controlul microcontrollerului, se conectează la calculator printr-un cablu USB sau se poate alimenta folosind mufa de alimentare.
Modelul Arduino Uno este diferit față de celelalte plăci deoarece acesta nu folosește un cip FTDI pentru conversia USB-la-Serial. În schimb acesta are un cip Atmega8U2 programat sa functioneze ca un convertor USB-la-Serial.
“Uno” înseamnă Unu în italiană și a fost numit așa deoarece marchează urmatoarea versiune (1.0) a software-ului pentru Arduino.
Caracteristicile plăcii de dezvoltare sunt prezentate în tabelul următor:
Tabelul 4.1Caracteristicile plăcii de dezvoltare
Arduino Uno poate fi alimentat prin USB sau printr-o sursă de alimentare externă, aceasta fiind selectată automat.
Placa poate funcționa pe o sursă externă cu o tensiune între 6 și 20 V. Dacă este alimentată cu o tensiune mai mică de 7 V, pinul de 5 V va scoate o tensiune mai mică de 5 V. Alimentând cu mai mult de 12 V va supraîncălzi stabilizatorul de tensiune și poate duce la defectarea plăcii.[5]
Pinii de alimentare sunt:
VIN. Pinul de alimentare a plăcii când se utilizează o sursă de tensiune externă
5V. Acest pin generează de la stabilizatorul plăcii o tensiune de 5 V.
3V3. Generează o tensiune de la stabilizatorul plăcii de 3,3V și un curent maxim de
50mA.
GND. Pinii sunt conectați la masa plăcii.
IOREF. Acest pin furnizează tensiunea de referință cu care funcționează placa.
Fiecare din cei 14 pini poate fi folosit ca pin de intrare sau ieșire, folosind funcțiile
pinMode(), digitalWrite(), digitalRead(). Acești pini operează la o tensiune de 5V și pot
24
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
furniza sau primii un curent de maxim 40mA, fiecare pin având cate o rezistența internă
de pull-up(deconectată în mod implicit) de 20 – 50 KΩ.
Unii pini au funcții specializate:
Pinii 0 (RX) și 1 (TX) sunt utilizați pentru a recepționa și transmite date serial TTL, aceștia fiind conectați la pinii microcontrollerului Atmega8U2 care este programat să facă conversia USB – TTL.
Pinii 2 și 3 pot fi configurați pentru a activa o întrerupere externă.
Pinii 3, 5, 6, 9, 10 și 11 pot genera semnal PWM folosind funcția analogWrite().
Pinii 10(SS), 11(MOSI), 12(MISO) și 13(SCK) suportă comunicația SPI folosind
libraria SPI.
Arduino Uno are 6 intrari analogice pentru convertorul analogic – digital , numerotate de la A0 la A5, fiecare având o rezolutie de 10 biți. În mod implicit aceștia măsoară de la 0V la
5V, dar este posibil să modificăm această gamă folosind pinul de tensiune de referință AREF.
Microcontroller-ul ATmega328 de pe Arduino vine cu un bootloader care încărcarea programelor fără utilizarea unui programator extern.[5]
4.4.Caracteristicile generale ale microcontroller-ului ATmega 328
Fig. 4.4Microcontroller-ul ATmega 328
Principalele caracteristici ale microcontroller-ului ATmega 328 sunt:
131 instrucțiuni (majoritatea executate pe un singur tact de ceas)
Microcontroller cu performanțe ridicate
Arhitectură RISC
32 x 8 de regiștri de uz general
Până la 20 MIPS la o frecvență de 20MHz
32K Bytes Flash auto programabil
1K Bytes EEPROM
2K Bytes Internal SRAM
Cicluri scriere/ștergere: 10,000 Flash / 100,000 EEPROM
Două Timere/Comparatoare pe 8 biți cu prescalare
Un Timer/Counter pe 16 biți cu prescalare, mod de compare și capturare
25
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Real Time Counter cu oscilator separat
6 canale PWM
Un ADC pe 10 biți cu 8 canale
USART programabil serial
Interfață SPI
Watchdog Timer programabil cu oscilator separat
Comparator analogic
Power-on Reset
Surse interne și externe de întrerupere
6 moduri de Sleep
23 de linii I\O programabile
Regim de funcționare: 1.8V – 5.5V
Gamă de temperaturi: -40°C – 85°C
Fig. 4.5Diagrama bloc a microcontroller-ului ATmega 328
26
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
4.5.Noțiuni de bază despre punte H și driver de motor
În general, chiar și cel mai simplu robot necesită un motor pentru a roti o roată sau pentru a efectua o anumită mișcare. Întrucât motoarele necesită mai mult curent decât poate să genereze pinii microcontroller-ului, se folosesc anumite tipuri de comutatoare ( tranzistori, relee, etc.) care pot accepta un curent de valoare mai mică pe care îl amplifică astfel încât să poată comanda un motor. Acest întreg proces este realizat de un driver de motor.
Driver-ul de motor este, în principiu, un amplificator de curent care preia un semnal de curent mic de la microcontroller și generază un semnal de curent mai mare care poate acționa un motor. În cele mai multe cazuri, un tranzistor poate realiza acestă sarcină și poate acționa motorul într-un singur sens.
Pentru a acționa motorul în sens opus trebuie inversată polaritatea. Acest lucru poate fi realizat prin folosirea a patru comutatoare conectate în așa fel încât circuitul nu doar acționează motorul, ci și controlează direcția. Dintre toate circuitele, cel mai comun este circuitul punte H, în care tranzistoarele sunt aranjate într-o formă care seamănă cu litera H.
După cum se poate observa în imaginea de mai jos, circuitul are patru comutatoare: A,B, C și D. Conectând și deconectând aceste comutatoare se poate acționa motorul în diferite
moduri.
Fig. 4.6Schema de funcționare a punții H
Cuplând comutatoarele A și D duce la acționarea motorului în sensul acelor de ceas.
27
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Cuplarea comutatoarelor B și C acționează motoarele învers acelor de ceas.
Cuplarea comutatoarelor A și C sau B și D duce la scurt-circuitarea circuitului.
O punte H se poate construi folosind relee, tranzistori cu efect de câmp, tranzistori
bipolari, etc. Pentru a acționa motoare care nu necesită curenți mai mari de 1 Amper se poate
folosi un circuit integrat de tip L293D.
Fig. 4.8Circuitul integrat
L293D
Fig. 4.7Cablajul imprimat cu circuitul
L293D
Acest circuit integrat de dimensiuni foarte mici și cost redus poate comanda două motoare de curent continuu în orice sens cu doar patru pini de la microcontroller(dacă nu se utilizează pinii de activare). Circuitul integrat L293D are în componență diode flyback care protejează tranzistoarele de vârfurile de tensiune care apar atunci când bobina motorului se oprește.
Este conceput pentru a oferi curenți bidirecționali de acționare de până la 600mA la tensiuni de la 4,5 V până la 36 V. Acest lucru înseamna că nu se pot comanda motoare foarte mari cu acest circuit integrat.
Pinii de validare au rolul de activa pinii de ieșire. Dacă un pin de validare este în stare logică HIGH, atunci starea pinului de ieșire are aceiași valoare cu starea pinului de intrare. Dacă un pin de validare este în stare logică LOW, atunci pinul de ieșire se află într-o stare de
înaltă impedanță indiferent de starea pinului de intrare.
28
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
O altă caracteristică a circuitului este faptul că are integrat o protecție împotriva supraîncălzirii. Senzorii interni detectează temperatura internă și opresc acționarea motoarelor dacă valoarea temperaturii depășește o valoare prestabilită.
Este proiectat pentru a conduce sarcini inductive cum ar fi: relee, solenoizi, motoare
bipolare pas cu pas și de curent continuu.
Circuitul integrat funcționează în parametrii normali la temperaturi aflate intre 0 ° C
și 70 ° C.
Fig. 4.9Diagrama bloc a circuitului integrat L293D[6]
Semnificația pinilor:
Pinii 1 și 9 sunt pini de activare (Enable) și trebuie conectați la +5V pentru ca driver-
ele sa funcționeze.
Pinii 4, 5, 12 și 13 sunt pinii de masă (Ground).
Pinii 2, 7, 10 și 15 sunt pini de intrare logică (Input). Pinii 2 și 7 controlează un motor, iar pinii 10 și 15 controlează al doilea motor.
Pinii 3, 6, 11 și 14 sunt pini de ieșire (Output). Pinii 3 și 6 se conectează la un motor, iar pinii 11 și 14 la celălalt motor.
Pinul 16 (VCC1) se conectează la o sursă de tensiune de 5 V.
Pinul 8 (Vc) alimentează motoarele.
29
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
4.6.Senzorul de gaz MQ-6
Senzorii de gaz sunt utilizați de ani de zile în sistemele de interior și exterior de monitorizare și detectare a gazului. Principalele preocupări ale utilizatorilor sunt legate de precizie, raza de acțiune și durata de funcționare.
Senzorul de gaz MQ-6 este utilizat în detecția Butanului, Propanului și a GPL-
ului(Gaz Petrolier Lichefiat).
Fig. 4.11Senzorul de gaz MQ-6 Fig. 4.10Cablajul imprimat cu senzorul de gaz
Poate fi utilizat ca detector de gaz de uz casnic, detector de gaz industrial sau detector de gaz portabil.
Structrura și configurația senzorului este prezentată în Fig.4.12, iar descrierea
componentelor este prezentată în Tabelul 4.2.
Tabelul 4.2Elementele compnente ale senzorului
Fig. 4.12Structura și configurația senzorului
30
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Bobina de încălzire oferă parametrii necesari de lucru pentru componentele sensibile. Valoarea rezistenței senzorului este diferită în funcție de tipul gazului(între 10 KΩ și 47 KΩ), iar calibrarea acestuia este necesară înainte de folosire. Pentru detectarea gazului petrolier lichefiat producătorul recomandă folosirea unei rezistențe cu o valoare de 20 KΩ.
În graficul următor este prezentată caracteristica de sensibilitate pentru cateva gaze. Axa verticală este reprezintă raportul rezistențelor Rs/Ro, iar pe axa orizontală unitatea de
măsură a concentrației PPM (Parts Per Million).[7]
Fig. 4.13Caracteristica de sensibilitate a senzorului MQ-6 [7]
31
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
4.7.Modulul Bluetooth Mate Silver
Bluetooth Mate Silver este un modul Bluetooh de clasă 2, de dimensiuni mici și consum redus de energie destinat utilizatorilor care doresc să adauge posibilitatea de conectare fără fir la produsele lor.
Acest modem Bluetooth este foarte simplu de utilizat, pur și simplu datele scrise pe pinii RX/TX sunt disponibili la receptor. Din acest punct de vedere putem considera ca si cum
pinii RX/TX sunt conectati prin fire obișnuite între emițător și receptor.
Fig. 4.14Bluetooth Mate Silver
Modemul are integrat un modul numit RN-42. Modulul consumă, în modul adormire cu funcțiile de descoperire și conectare activate, doar 26µA.
Modemul poate fi configurat în diferite moduri de funcționare permițându-i
utilizatorului sa selecteze cel mai mic profil de putere pentru o anumită aplicație.
Modulul are integrat regulatoare de tensiune astfel încât să poată fi alimentat de la
orice sursă de alimentare între 3.3V până la 6V. [8]
Specificații:
Rate de transfer (Baud rate) pe comunicația serială: 2400 – 115200bps
Rate de transfer fără fir: 721kbps – 2Mbps
Frecvența: 2,4 ~ 2,524 GHz
Comunicație securizată cu encriptare pe 128 biți
Distanța maximă de transmisie: 15 metri
Consum mediu: 25 mA
Antenă inclusă pe placă
32
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
4.8.Descrierea modului de realizare a circuitului imprimat pentru driverul L293D și
senzorul de gaz
În continuare voi prezenta modul de conectare al driver-ului la placa de Arduino:
Fig. 4.15Configurația pinilor circuitului integrat L293
Pinul 1se conectează la Arduino, la pinul de alimentare de 5V
Pinul 2 se conectează la Arduino, la portul I/O, pinul 10
Pinul 3 se conectează la una dintre bornele motorului de direcție
Pinii 4, 5 se conectează la masă
Pinul 6 se conectează la cealaltă borna a motorului de direcție
Pinul 7 se conectează la Arduino ,la portul I/O, pinul 12
Pinul 8 se conectează la borna pozitivă a sursei de alimentare a motoarelor
Pinul 9 se conectează la Arduino, la portul I/O, pinul 3
Pinul 10 se conectează la Arduino, la portul I/O, pinul 4
Pinul 11 se conectează la una din bornele motorului de deplasare
Pinii 12, 13 se conectează la masă
Pinul 14 se conectează la cealaltă bornă a motorului de deplasare
Pinul 15 se conecteaza la Arduino, la portul I/O, pinul 5
Pinul 16 se conecteaza la Arduino, la portul I/O, pinul 6
33
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Am realizat schema electrică în programul Fritzing pentru driver-ul de motor, pentru a putea realiza un circuit cu cablaj imprimat care se suprapune peste placa de dezvoltare.
Fig. 4.16Schema cablajului imprimat pentru driver-ul de motor
Același lucru am făcut și pentru senzorul de gaz, reducând conectarea acestuia de la 4
la 3 conexiuni, schema de conectare fiind prezentată în figura următoare:
Fig. 4.17Schema de conectare a senzorului
Fig. 4.18Schema cablajului imprimat
34
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Pentru realizarea circuitului am folosit metoda termotransferului. În continuare voi descrie pas cu pas întregul proces:
1. Am folosit o placă de textolit din care am decupat la dimensiunile de
6.5×6.5cm cu ajutorul unui minicircular.
2. Am finisat marginile plăcii cu hârtie abrazivă cu granulație foarte mare, apoi am lustruit suprafața cu partea mai aspră a unui burete de vase. Acest pas este foarte important pentru a obține un rezultat final cât mai bun, cu cât este mai bine lustruită placa cu atât substanța de acoperire este mai lucioasă.
3. Am curațat placa cu o solutie degresantă (alcool izopropilic).
4. Am printat circuitul folosind o imprimată laser , iar hârtia utilizată a fost tip A4
fotografică.
5. Am decupat hârtia cu circuitul imprimat lăsând două parți mai lungi și am
suprapus-o peste placa de textolit.
6. Folosind un fier de călcat la o temperatură mai mare de 200 grade, am apăsat placa aproximativ 2 minute, pe urmă am frecat apăsând ușor folosind o bucată de șervețel, apoi am revenit cu fierul de calcat frecând ușor pentru încă 2
minute.
35
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
7. Odată răcită placa la temperatura camerei, am înmuiat-o în apă calduță cu detergent pentru aproximativ 5 minute și apoi am îndepărtat hârtia.
8. Am introdus placa în soluție de corodare (clorură ferică) și am lăsat-o să
corodeze agitând din când în când vasul .
9. După ce am scos placa de la corodat am curat-o cu acetona, apoi am verificat eventualele trasee întrerupte.
10. Ultima etapă a constat în găurirea plăcii și lipirea componentelor.
Fig. 4.20Cablajul imprimat cu L293D (vedere de jos)
Fig. 4.19 Schema cablajului imprimat cu L293D (vedere de sus)
Fig. 4.22Cablajul imprimat cu senzorul MQ-6 (vedere de jos)
Fig. 4.21Cablajul imprimat cu senzorul MQ-6 (vedere de sus)
36
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
4.9.Programarea plăcii de dezvoltare
Pentru programarea microcontroller-ului am folosit mediul de dezvoltare Arduino
1.0.2 care se poate descărca gratis de pe site-ul producătorului.
După deschiderea aplicației am configurat IDE-ul, din meniul Tools -> Board am selectat placa de dezvoltare Arduino Uno.
Fig. 4.23 Selectarea plăcii de dezvoltare
Apoi tot din meniul Tools -> Serial Port am selectat portul serial la care este conectată placa și anume COM3.
Fig. 4.24 Selectarea portului serial
37
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Înainte de încărcarea codului pe placă se recomandă verificarea acestuia prin apăsarea
butonului “Verify”.
Fig. 4.25 Verificarea programului
După verificarea corectitudinii programului și compilarea acestuia se poate încărca pe
placa folosind butonul “Upload”.
Fig. 4.26 Încărcarea programului pe Arduino
38
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
4.10. Structura programului
Pentru a înțelege mai bine funcționarea programului am realizat diagrama de funcționare din figura următoare:
Fig. 4.27 Diagrama de funcționare a programului
Programul începe cu declararea tuturor variabilelor și asignarea pinilor de pe placă ce vor fi folosiți.
// Cod pentru comandarea robotului mobil
// LICENTA 2013
//SARIVAN IONUT
//Facultatea de Inginerie Electrica si Stiinta Calculatoarelor
39
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
int EnableDir = 9; // pin de validare directie int EnableMotor = 3; // pin de validare deplasare
int DirPin1 = 10; // pinii de comanda pentru directie int DirPin2 = 12; //
int MotorPin1 = 4; // pinii de comanda pentru deplasare int MotorPin2 = 5; //
int EnableDriver = 6; //pin de activare driver L293D
int senzorPin = A0; // pinul de intrare analogica pentru senzorul de gaz int ledPin = 13; // led de avertizare
int buzzerPin = 8; //pin pentru difuzor piezoelectric
char val; // se stocheaza datele primite pe serial int senzorVal =0; // valoarea citita de senzor
char stareSenzor; //
int stareLed = 0;
int nr_conversii = 3; // variabila care seteaza numarul de conversii efectuate de ADC
int limit = 500; // valoare limita pentru avertizare sonora int interval = 100;
long previousMillis = 0;
Orice program Arduino are două secțiuni. Secțiunea „setup”, care este rulată doar o singură dată, atunci când placa este alimentată (sau este apăsat butonul "Reset"), și secțiunea
„loop”, care este rulată în ciclu, atât timp cât este alimentată placa.
În rutina „setup” am introdus codul de inițializare al pinilor, inițializare ce se realizează cu funcția pinMode().
Această funcție are doi parametri și configurează un pin ca fiind de intrare sau ieșire.
Tot în rutina „setup” am setat rata de transfer pentru interfața serială la 9600 de biți/secundă.
//initializarea pinilor si setarea Baud rate-ului la 9600bps void setup() {
pinMode(EnableDir, OUTPUT); pinMode(EnableMotor, OUTPUT); pinMode(DirPin1, OUTPUT); pinMode(DirPin2, OUTPUT); pinMode(MotorPin1, OUTPUT); pinMode(MotorPin2, OUTPUT); pinMode(EnableDriver, OUTPUT); pinMode(senzorPin,INPUT);
pinMode(ledPin,OUTPUT);
Serial.begin(9600);
}
În continuare am implementat funcțiile ce realizează comanda motoarelor, precum și cele pentru configurarea senzorului de gaz. Un exemplu de funcție ce realizează o comandă a motorului este prezentat în codul următor:
//functia pentru deplasare inainte void inainte() {
digitalWrite(MotorPin1, HIGH);
digitalWrite(MotorPin2, LOW);
40
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
digitalWrite(EnableMotor, HIGH);
}
În exemplul următor este prezentată funcția ce realizează citirea a trei valori de la senzorul de gaz și returnează ca rezultat o medie a celor trei valori.
//citirea valorilor senzorului si returnarea unei valori medii int readSensor(int PIN, int nr_conversii) {
int val_medie;
int val[nr_conversii];
int suma_val = 0;
for(int x = 0; x < nr_conversii; x++){
val[x] = analogRead(PIN); suma_val = suma_val + val[x]; delay(1000);
}
val_medie = suma_val/nr_conversii;
return val_medie;
}
O altă funcție importantă este “performCommand()” în care o structura de tip if-else-if verifică valoarea primită pe serial și în funcție de aceasta se execută una din comenzile de acționare a motorului.
//functie ce se executa in loop(); care verifica valoarea primita pe
//seriala
//si in functie de acea valoare executa una din comenzile motoarelor
void executaComanda() { digitalWrite(EnableDriver, HIGH); if (Serial.available()) {
val = Serial.read(); \\ receptioneaza valorile de pe seriala
}
if (val == 'f') { // daca valoarea primita pe interfata seriala inainte(); // este egala cu "f" executa comanda inainte();
} else if (val == 'z') { // daca valoarea primita pe interfata seriala stop_inainte(); // este egala cu "z" executa comanda
stop_inainte();
} else if (val == 'b') { // daca valoarea primita pe interfata seriala inapoi(); // este egala cu "b" executa comanda inapoi();
} else if (val == 'y') { // daca valoarea primita pe interfata seriala stop_inapoi(); // este egala cu "y" executa comanda
stop_inapoi();
} else if (val == 'r') { // daca valoarea primita pe interfata seriala dreapta(); // este egala cu "r" executa comanda dreapta();
} else if (val == 'l') { // daca valoarea primita pe interfata seriala
stanga(); // este egala cu "l" executa comanda stanga();
} else if (val == 'v') { // daca valoarea primita pe interfata seriala stop_directie(); // este egala cu "v" executa comanda
stop_directie();
} else if (val == 'g') {// daca valoarea primita pe interfata seriala
41
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
porneste_senzor(); // este egala cu "g" executa comanda porneste_senzor();
}
}
În final am introdus în rutina “loop()” metoda “executaComanda()”, metodă ce se
execută în continuu.
Senzorul de gaz este activat în momentul în care pe interfața serială se trimite caracterul “g”, se citește valoarea de pinul analogic “A0” cu metoda “readSensor” și se trimite pe interfața serială.
În momentul în care valoarea citită de senzor este mai mare decât valoarea limită “limit” declarată la începutul codului, se apelează metoda “blinkLED()” care aprinde un led și trimite un semnal la un difuzor piezo-electric, emițând un semnal sonor.
void loop() {
executaComanda();
}
Capitolul 5. Dezvoltarea aplicației client în Android SDK
5.1.Crearea unui proiect nou
Pentru dezvoltarea aplicației de telefon am folosit interfața pentru programare de aplicații furnizată de site-ul http://developer.android.com. Mai nou, Android SDK(Software Development Kit) se numește ADT de la Android Developer Tools. Acesta conține mediul de dezvoltare Eclipse și uneltele pentru Android.
Dupa descărcarea arhivei, se extrag fișierele într-un dosar care va conține Android
SDK și mediul de dezvoltare Eclipse.
Pentru crearea unei aplicații în Eclipse se accesează meniul File > New > Android
Application Project.
Fig. 5.1 Crearea unui proiect nou în Eclipse
42
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
După această etapă se va afișa un meniu de configurare ca în figura următoare:
Fig. 5.2 Meniul de configurare al proiectului (1)
Pentru configurarea aplicației se realizează urmatorii pași:
1. În câmpul “Application Name” se scrie numele aplicației
2. În câmpul “Project Name” se scrie numele proiectului
3. În acest câmp se inserează automat numele pachetului ce va conține toate clasele aplicației
4. La acest pas se selectează interfața minimă pe care poate rula aplicația
5. Se selectează interfața pentru care dorim să rulăm aplicația
6. După care selectăm compilatorul codului
7. La acest pas se selectează design-ul interfeței grafice al aplicației
8. Se apasă butonul “Next” pentru a avansa la etapa următoare
9. Se selectează spatiul de lucru în care se vor stoca toate fișierele aplicației
43
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
10. Dupa ca care se apasă butonul “Next”
11. În această etapa se pot face modificări ale iconiței de rulare a aplicației sau se pot lăsa setarile implicite și se apasă butonul “Next”
12. La acest pas se selectează tipul de activitate, în mod implicit activitate goală
44
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
13. Și se apasă butonul “Next”
14. În ultima etapă a configuratorului se completează numele activității principale
15. Și se apasă butonul “Finish”.
5.2.Structura aplicației Android
După configurare proiectului se va genera automat o structură de componente bază pentru aplicație. Fiecare componentă reprezintă un punct prin care sistemul de operare poare accesa aplicația.
Cele cinci componente ale unei aplicații sunt:
Activitățile (Activities)
Intenții (Intents)
Serviciile (Services)
Furnizorii de conținut (Content providers)
Receptoarele de mesaje (Broadcast receivers)
O activitate (Activity) este un ecran de interfață cu utilizatorul. O aplicație Android poate avea una sau mai multe activități. Spre exemplu, un joc ar putea avea o activitate pentru meniul principal, o activitate pentru fereastra de opțiuni, una pentru ecranul de joc etc. Fiecare activitate are propriul său ciclu de viață, independent de ciclul de viață al procesului asociat aplicației. În imaginea de mai jos se poate vedea care este ciclul de viață al unui Activity. Acesta este destul de simplu, având o serie de
stări care se succed și prin care trece orice Activity din sistem.[9]
45
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Fig. 5.3 Ciclul de viață a unei activități
Intent-ul este o entitate gestionată de o instantă a clasei “Intent” și folosită pentru a descrie o operațiune care urmează să fie executată, fiind folosită pentru a porni activități, servicii și pentru a emite broadcast-uri.
Fig. 5.4 Modul de activare a unei activități
Serviciile sunt componente care rulează în fundal, pentru interacțiunea cu alte procese sau pentru a desfășura acțiuni îndelungate, fără interacțiune cu utilizatorul. Spre exemplu un serviciu poate derula muzica pentru un joc. Un serviciu este implementat în cod sub forma unei subclase a clasei abstracte “Service”.
Un furnizor de conținut este folosit pentru a gestiona datele, publice sau private, folosite de aplicație. El scrie și citește din sisteme de fișiere, baze de date SQLite, în rețea și poate fi apelat de către alte aplicații pentru a furniza date, dacă dorim acest lucru. Un furnizor
de conținut este implementat ca subclasă a clasei abstracte “ContentProvider”.[9]
46
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Un receptor de broadcast este o componentă ce raspunde la anunțurile de interes general din sistem (spre exemplu un anunț că ecranul a fost stins, că bateria este aproape descărcată etc.). Receptorii de broadcast nu au interfața cu utilizatorul, însă pot crea notificări și pot semnala alte componente ale aplicației. Un receptor de broadcast este implementat ca subclasă a clasei abstracte “BroadcastReceiver”.[9]
După configurare proiectului în Eclipse se va genera automat o structură de bază pentru aplicație ce conține următoarele elemente marcate cu cifre de culoare roșie:
Fig. 5.5 Structura unui proiect Android
1. Scr: conține fișierele sursă ale proiectului
2. Gen: conține fișierele sursă generate automat de Android Developer Tools
3. Assets: conține resurse (sunete, imagini) care vor fi accesate prin căi relative.
4. Bin: director generat de compilator și conține toate clasele utilizate pentru a genera aplicația
5. Libs: conține librăriile private
6. Res: conține resurse (precum imagini, string-uri, icoane, layout, etc.) pentru care se
generează ID-uri unice pentru a fi folosite.
7. Android Manifest.xml: conține o serie de informații despre aplicație pe care le prezintă sistemului, înainte ca acesta sp poată rula aplicația
5.3.Crearea interfeței grafice
În continuare voi face referire la interfața grafică folosind denumirea de layout.
Din directorul “res” am accesat subdirectorul “layout” și am deschis fișierul “activity_main.xml”. După cum se poate observa și în extensia fișierului layout-ul aplicației se configurează sub forma limbajului XML (eXtensible Markup Language), fiind oferit un vocabular XML pentru clase View și subclase ale acestora.
47
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Structura generală a layout-ului conține:
4 butoane pentru comanda dispozitivului mobil
Un buton pentru activarea senzorului
Un buton pentru scanarea dispozitivelor Bluetooth
Un buton pentru deconectarea de la dispozitiv și iesirea din aplicație
O fereastră de text în care se afișează valorile masurate de senzor
Fig. 5.6 Ecranul principal al aplicației
Mai departe este prezentat un exemplu de cod XML pentru a genera un buton:
<Button android:id="@+id/forwardButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="25dp" android:text="Inainte" android:background="@drawable/btn_states"/>
Această secvență de cod conține informații despre identificatorul butonului, dimensiuni, poziționarea acestuia în layout, precum și textul care este scris în interior.
Eclipse permite configurarea butoanelor și într-o interfață grafică, unde se pot seta
dimensiunile, formele și poziționarea acestora.
Pentru adăugarea unei ferestre de text în layout am scris următorul cod XML:
<TextView android:id="@+id/txtArduino" android:layout_width="fill_parent"
48
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
android:layout_height="wrap_content" android:layout_above="@+id/senzor" android:layout_toLeftOf="@+id/rightButton" />
În continuare am creat înca un layout, pentru afișarea dispozitivelor scanate și pentru afișarea
dispozitivelor conectate recent. Pentru afișarea listei am folosit o structură de tip “ListView”:
Fig. 5.7 Lista de tip
"ListView"
Codul XML pentru generarea unei liste:
<ListView android:id="@+id/paired_devices" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:stackFromBottom="true" />
5.4.Implementarea programului principal
Platforma Android include suport pentru stiva de rețea Bluetooth, permițându-i unui dispozitiv sa comunice wireless cu alte dispozitive Bluetooth. Arhitectura aplicației furnizează accesul la platforma Bluetooth prin intermediul interfeței Android Bluetooth.
Folosind interfața Bluetooth, o aplicație Android poate realiza următoarele funcții:
Scanarea pentru găsirea dispozitivelor Bluetooth
Interogarea dispozitivului Bluetooth local pentru afișarea dispozitivelor associate
Stabilirea unui canal de comunicație prin radio frecvență (RFCOMM)
Conectarea la alte dispositive Bluetooth
Transfer de date de la și către alte dispositive
Administrarea conexiunilor multiple
49
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Toate subinterfețele și clasele interfeței Bluetooth se găsesc în pachetul android.bluetooth. În continuare voi prezenta doar clasele pe care le-am utilizat în implementarea aplicației:
BluetoothAdapter: reprezintă dispozitivul Bluetooth local.
BluetoothDevice: reprezintă un dispozitiv Bluetooth la distanță, interoghează dispozitivul returnând informații ca numele, adresa MAC, clasa de putere și starea conexiunii.
BluetoothSocket: reprezintă subinterfața pentru un socket Bluetooth ( similar
cu un socket TCP).
Pentru ca aplicația să aibă acces la toate caracteristicile interfeței Bluetooth, am declarat în fișierul “AndroidManifest.xml” două tipuri de permisiuni: BLUETOOTH și BLUETOOTH_ADMIN.
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
Realizarea unei aplicații ce utilizează platforma Bluetooth presupune parcurgerea pașilor următori:
1. Configurarea dispozitivului Bluetooth
2. Scanarea dispozitivelor Bluetooth disponibile
3. Conectarea dispozitivelor Bluetooth
4. Gestionarea conexiunilor
5.4.1 Configurarea dispozitivului Bluetooth
Pentru partea de început, mi-am declarat în interiorul clasei ”MainActivity” toate butoanele create anterior in layout, apoi am creat o metoda numită “setupButtons()” în care mi-am instanțiat fiecare buton și care arată astfel:
public void setupButtons() {
mScan = (Button) findViewById(R.id.scan_button); mTune = (Button) findViewById(R.id.connect_button); forward = (Button) findViewById(R.id.forwardButton); reverse = (Button) findViewById(R.id.reverseButton); left = (Button) findViewById(R.id.leftButton);
right = (Button) findViewById(R.id.rightButton);
txtArduino = (TextView) findViewById(R.id.txtArduino);
text1 = (TextView) findViewById(R.id.textView1);
senzor = (Button) findViewById(R.id.senzor);
}
Pentru a facilita accesul și controlul resurselor din codul aplicației, compilatorul generează o clasă, numita R, care conține identificatori statici utilizați pentru referirea fiecărei
resurse.
50
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Metoda “findViewById” caută în clasa R identificatorul pentru elementul pe care dorim să-l instanțiem.
Apoi am apelat metoda “setupButtons()” în interiorul metodei “onCreate”, metodă ce se execută în momentul în care o activitate este creată, având rolul de inițializa acea activitate.
Pentru a putea utiliza interfața Bluetooth am creat un obiect de tip “BluetoothAdapter” care îmi permite să utilizez funcțiile unui dispozitiv Bluetooth, cum ar fi descoperirea, scanarea sau interogarea altor dispozitive.
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Metoda statică “getDefaultAdapter()” returnează modului Bluetooth al telefonului, iar
în cazul în care telefonul nu este echipat cu un modul Bluetooth metoda returnează nul.
Următoarea etapă constă în activarea dispozitivului Bluetooth apelând metoda “isEnabled()”. Dacă metoda returnează false atunci dispozitivul este oprit. Pentru a porni dispozitivul am creat un Intent cu acțiunea ACTION_REQUEST_ENABLE, după care am apelat metoda “startActivityForResult()” cu parametrul Intent-ului care are ca efect emiterea unei cereri de activare a Bluetooth-ului. Constanta ACTION_REQUEST_ENABLE trebuie definită local în programul nostru ca un integer cu o valoare mai mare ca zero.
if(!mBluetoothAdapter.isEnabled()){
Intent enableBtIntent=newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent,REQUEST_ENABLE_BT);
}
În urma acestei etape va apărea o fereastră de dialog, ca în figura următoare, cerându-i
utilizatorului permisiunea de a activa Bluetooth-ul.
Fig. 5.8 Fereastră de dialog
pentru activarea Bluetooth
Dacă utilizatorul apasă butonul “Yes”, sistemul va începe acțiunea de activare și se va întoarce la aplicație în momentul în care activarea a fost efectuată.
5.4.2 Scanarea dispozitivelor Bluetooth disponibile
Folosind clasa “BluetoothAdapter” se pot căuta dispozitive Bluetooth prin
descoperirea dispozitivelor, fie prin interogarea listei de dispozitive asociate.
Descoperirea dispozitivelor este o procedură de scanare care caută în aria de acoperire a dispozitivului Bluetooth toate dispozitivele active și solicită informații despre fiecare în
parte. Dispozitivul Bluetooth care se afla în aria de acoperire va răspunde doar dacă are
51
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
modul de descoperire activat. Dacă acest mod este activat, acesta va returna un răspuns ce conține informații despre numele dispozitivului, clasa de putere și adresa unică MAC. Folosind aceste informații dispozitivul care a solicitat informațiile poate iniția o conexiune.
În momentul în care s-a realizat o conexiune cu un dispozitiv la distanță pentru prima oară, o cerere de asociere este prezentată utilizatorului. După procesul de asociere, informațiile de bază ale dispozitivului la distanță (numele și adresa MAC) sunt salvate și pot fi citite utilizând interfața Bluetooth de programare. Folosind adresa MAC a unui dispozititiv se poate realiza o conexiune în orice moment cu acesta fără a iniția procedura de descoperire.
Interfața Android Bluetooth impune ca dispozitivele să se asocieze înaintea stabilirii
unei conexiuni cu canal de date.
Pentru a începe procesul de descoperire am creat o metodă “scanDevice()” în care mi-
am condiționat butonul de scanare ca atunci când este apăsat să execute funcția “scan()”.
public void ScanDevice() {
scan.setOnClickListener(new View.OnClickListener() {
public void onClick(View mView) {
scan();
}
});
}
private void scan() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) { Toast.makeText(MainActivity.this, "Dispozitiv inactiv",
2000).show();
} else {
if (!mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent( BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent,
REQUEST_ENABLE_BT);
} else {
mBluetoothAdapter.startDiscovery();
Intent connectIntent = new Intent(MainActivity.this, DeviceListActivity.class);
startActivityForResult(connectIntent,REQUEST_CONNECT_DEVICE);
}
}
}
Pentru a putea recepționa informații despre fiecare dispozitiv descoperit, am creat un
obiect de tip “BroadcastReceiver” care va recepționa Intent-uri de tip ACTION_FOUND.
52
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Aceste Intent-uri conțin informații despre dispozitivele Bluetooth în câmpurile
EXTRA_DEVICE și EXTRA_CLASS.
private final BroadcastReceiver mReceiver = newBroadcastReceiver(){
public void onReceive(Context context, Intent intent) { String action = intent.getAction();
// cand se descopera un dispozitiv
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// se stocheaza informatiile din Intent
BluetoothDevice device =
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// se adauga numele si adresa intr-o lista de tip
ArrayAdapter
mNewDevicesArrayAdapter.add(device.getName() + "\n" +
device.getAddress());
}
}
};
5.4.3 Conectarea dispozitivelor Bluetooth
După procesul de descoperire am populat lista “mNewDevicesArrayAdapter” cu informații adresa MAC și numele fiecărui dispozitiv. Pentru a stabili o conexiune cu un dispozitiv este nevoie de un “BluetoothDevice” și un “BluetoothSocket”.
Mi-am declarat cele două obiecte: BluetoothSocket mBluetoothSocket; BluetoothDevice mBluetoothDevice;
Folosind “BluetoothDevice” am creat un socket pentru conexiune folosind un
UUID(Universally Unique IDentifier). UUID-ul este un numar pe 128 de biți folosit ca
indentificator unic al unui obiect sau entitate.
Apoi am oprit procesul de descoperire pentru a nu încetinii conexiunea și am apelat metoda “connect()”.
mBluetoothSocket=mBluetoothDevice.createRfcommSocketToServiceRecord
(applicationUUID);
mBluetoothAdapter.cancelDiscovery();
mBluetoothSocket.connect();
Pentru a închide un socket se apelează metoda “close();”
5.4.4 Gestionarea conexiunilor
Odată îndeplinită procedura de la punctul precedent, ambele dispozitive au un “BluetoothSocket” conectat. Pornind de la acesta se obțin un “InputStream” și un “OutputStream”, pe care se pot face operațiuni de read(byte[]) și write(byte[]).
Aplicația este implementată ca după conectarea la un dispozitiv, să citească în
continuu datele din InputStream.
53
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Codul pentru conectarea dispozitivelor și gestionarea conexiunilor este scris în metoda
“run()”. Această metodă este apelată când este pornit un thread nou.
public void run() {
InputStream tmpIn = null; OutputStream tmpOut = null;
try {
mBluetoothSocket = mBluetoothDevice
.createRfcommSocketToServiceRecord(applicationUUID);
mBluetoothAdapter.cancelDiscovery(); mBluetoothSocket.connect(); mHandler.sendEmptyMessage(0);
tmpIn = mBluetoothSocket.getInputStream();
tmpOut = mBluetoothSocket.getOutputStream();
} catch (IOException eConnectException) {
Log.d(TAG, "CouldNotConnectToSocket", eConnectException);
closeSocket(mBluetoothSocket);
return;
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
byte[] buffer = new byte[256];
int bytes;
while (true) {
try {
bytes = mmInStream.read(buffer);
h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
Metodele de “write()” și “read()” sunt implementate pe thread-uri separate pentru că ambele proceduri folosesc apeluri blocante. Metoda “read()” va rămâne blocată până când va găsi ce să citească din stream.
Metoda “write()” este apelată doar atunci când unul din butoanele înainte, înapoi, stânga sau dreapta este accesat. În continuare voi prezenta cum este apelată această
metodă pentru butonul înainte.
54
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
5.5.Principiul de funcționare al aplicației
Mi-am propus ca atunci cât timp butonul este apăsat, dispozitivul mobil să se deplaseze înainte, iar atunci când butonul nu mai este apăsat să se oprească. Pentru asta, în metoda “forward()” mi-am creat două cazuri.
public void forward() {
forward.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
write("z");
}
});
forward.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
}
});
}
write("f");
return false;
Atunci când butonul este apăsat, forward.setOnTouchListener face un write(“f”) care trimite litera “f” modulului Bluetooth conectat la Arduino. În programul din Arduino există metoda “performCommand()”, fiind apelată în “loop()”. Atunci când pe interfața serială se recepționează caracterul “f”, se execută funcția “go_forward()” care deplasează
motorul înainte.
Fig. 5.9 Schema de funcționare a sistemului cand este apăsat butonul Înainte
În momentul în care se ridică degetul de pe buton, forward.setOnClickListener() face un
“write(“z”) care trimite litera “z” modulului Bluetooth conectat la Arduino.
55
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Fig. 5.10 Schema de funcționare a sistemului când butonul Înainte nu mai este apasat
Pe lângă clasa “MainActivity” am mai implementat o clasa numită “DeviceListActivity”, care este apelată în momentul în care se apasă unul dintre butoanele “Scanare dispozitive” sau “Lista recente”. Această clasă apare ca o fereastră de dialog și listează toate dispozitivele descoperite și asociate. Această activitate se apelează printr-un Intent declarat într-una dintre funcțiile butoanelor menționate mai sus.
Intent connectIntent = new Intent(MainActivity.this, DeviceListActivity.class);
startActivityForResult(connectIntent, REQUEST_CONNECT_DEVICE);
Fig. 5.11 Fereastră de afișare a
dispozitivelor descoperite
56
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
5.6.Instalarea și testarea aplicației pe telefon
Dupa finalizarea implementării programului, acesta trebuie compilat, urmând a se construi automat un fișier cu extensia .apk. Acest fișier conține toate informațiile necesare pentru a rula aplicația pe un dispozitiv fizic sau emulator.
Diagrama de mai jos descrie componentele implicate în construirea și rularea unei aplicații.
Fig. 5.12 Diagrama de compilare și rulare a unei aplicații
Înainte de a instala aplicația pe telefonul mobil acesta trebuie configurat pentru modul Android Debugging Mode. Funcția principală a acestui mod este de a facilita o conexiune între un dispozitiv Android și un calculator ce rulează Android SDK.
Pentru a activa modul de debugging se intră în meniu de setări al telefonului Settings
> Developer options > se bifează USB debugging.
Fig. 5.14 Meniul de setări al telefonului Fig. 5.13 Submeniul "Opțiuni
dezvoltatator"
57
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
După configurare se conectează telefonul la calculator prin cablul USB.
În Eclipse se apasă butonul Run sau combinația de taste CTRL+F11, după care se va afișa o căsuța de dialog în care se selectează telefonul din listă și se apasă tasta OK.
În urma acestei acțiuni aplicația va rula automat după finalizarea instalării.
Fig. 5.15 Instalarea aplicației pe telefon
După instalare aplicația se va găsi în listă cu numele de “ARdroid Remote”:
Fig. 5.16 Butonul de accesare a aplicației
58
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Concluzii
Proiectul a fost dezvoltat pentru a demonstra că pot realiza cu costuri reduse un sistem mobil pentru detectarea gazului.
Sistemul poate fi utilizat în aplicații de monitorizare a zonelor cu risc exploziv, pentru a
măsura concentrația de gaz fiind ghidat de un operator uman care stă la distanță.
Capabilitățile sistemului pot fi extinse prin adăugarea de senzori și noi elemente de
execuție, astfel el putând fi adaptat foarte ușor pentru a îndeplini orice tip de sarcină.
Alimentarea cu un acumulator de 6V reprezintă cel mai mare deficit al sistemului, consumul de energie fiind imposibil de redus datorită numărului mare de consumatori prezenți pe acesta.
Un alt dezavantaj al sistemului îl reprezintă modulul de comunicație cu telefonul,
adaptorul Bluetooth având o rază de acțiune limitată la maxim 15 metri.
Pentru dezvoltări ulterioare sistemul poate fi îmbunătățit prin modificarea/adăugarea unor
componente cum ar fi:
Folosirea unor motoare de curent continuu dee putere mai mare pentru a putea rula
pe orice suprafețe de teren accidentat
Utilizarea unei baterii de putere mai mare ( de amperaj mare);
Utilizarea unui modul de comunicație fără fir cu o rază de acțiune mai mare
Instalarea unei camere video pentru a putea vizualiza imagini direct pe telefonul mobil
59
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Bibliografie
[1] – Dumitriu Adrian – BAZELE SISTEMELOR MECATRONICE, Editura Universității
Transilvania din Brașov, 2006
[2] – http://telecom.etc.tuiasi.ro/telecom/staff/ccomsa/Lucru/_Introducere_in_Bluetooth.pdf
[3] – http://users.utcluj.ro/~mbirlea/z/01z.htm (Senzori)
[4] – http://arduino.cc/en/Guide/Introduction
[5] – http://arduino.cc/en/Main/arduinoBoardUno
[6] – L293 and L293D Products Now From Texas Instruments Datasheet
[7] – MQ-6 Gas Sensor Datasheet
[8] – https://www.sparkfun.com/products/10393 (Bluetooth Mate Silver)
[9] – http://cs.curs.pub.ro/wiki/si/lab/2012/android1 (Introducere în Android)
[10] – Mogan, L. Gh., Roboți industriali, Editura Universității Transilvania, Brașov, 2003
[11] – Steven F. Barrett, Arduino microcontroller : processing for everyone!, Morgan & Claypool, cop. 2012
[12] – http://ctrl-d.ro/development/resurse-development/hello-android-elementele-ce-dau- viata-unei-aplicatii/
[13] – http://developer.android.com/guide/components/index.html
[14] – Greu-Adrian Victor, "Transmiterea datelor achiziționate de la senzorii robotului NXT la
un PC prin conexiune Bluetooth" UNIVERSITATEA POLITEHNICĂ DIN BUCUREȘTI , FACULTATEA DE INGINERIE ELECTRICĂ, BUCUREȘTI, Lucrare de licență.
60
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
Anexe
1.Cod pentru Arduino
// Cod pentru comandarea robotului mobil
// LICENTA 2013
//SARIVAN IONUT
//Facultatea de Inginerie Electrica si Stiinta Calculatoarelor
int EnableDir = 9; // pin de validare directie int EnableMotor = 3; // pin de validare deplasare
int DirPin1 = 10; // pinii de comanda pentru directie int DirPin2 = 12; //
int MotorPin1 = 4; // pinii de comanda pentru deplasare
int MotorPin2 = 5; //
int EnableDriver = 6; //pin de activare driver L293D
int senzorPin = A0; // pinul de intrare analogica pentru senzorul de gaz int ledPin = 13; // led de avertizare
int buzzerPin = 8; //pin pentru difuzor piezoelectric
char val; // se stocheaza datele primite pe serial int senzorVal =0; // valoarea citita de senzor
char stareSenzor; //
int stareLed = 0;
int nr_conversii = 3; // variabila care seteaza numarul de conversii efectuate de ADC
int limit = 500; // valoare limita pentru avertizare sonora int interval = 100;
long previousMillis = 0;
//initializarea pinilor si setarea Baud rate-ului la 9600bps void setup() {
pinMode(EnableDir, OUTPUT); pinMode(EnableMotor, OUTPUT); pinMode(DirPin1, OUTPUT);
61
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
pinMode(DirPin2, OUTPUT); pinMode(MotorPin1, OUTPUT); pinMode(MotorPin2, OUTPUT); pinMode(EnableDriver, OUTPUT); pinMode(senzorPin,INPUT); pinMode(ledPin,OUTPUT); Serial.begin(9600);
}
void porneste_senzor(){
senzorVal = readSensor(senzorPin, nr_conversii);
//afiseaza valorile pe seriala
Serial.println(senzorVal);
//daca valoarea de la senzor este mai mare decat limita stabilita
//incepe avertizarea sonora if (senzorVal > limit){
aprindeLED();
}
else
{
stopLED();
}
}
//citirea valorilor senzorului si returnarea unei valori medii int readSensor(int PIN, int nr_conversii) {
int val_medie;
int val[nr_conversii];
int suma_val = 0;
for(int x = 0; x < nr_conversii; x++){
val[x] = analogRead(PIN);
suma_val = suma_val + val[x];
delay(1000);
62
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
}
val_medie = suma_val/nr_conversii;
return val_medie;
}
void aprindeLED(){
unsigned long currentMillis = millis(); //functia milis(); din libraria
Arduino returneaza
pornita
//nr de milisencunde de cand placa a fost
if(currentMillis – previousMillis > interval) {
// salveaza timpul la care s-a aprins LED-ul previousMillis = currentMillis;
// daca led-ul este oprit il aprinde si invers:
if (stareLed == 0)
stareLed = 1;
else
stareLed = 0;
// seteaza starea led-ului pentru functia setLED();
setLED(stareLed);
}
}
void stopLED(){
digitalWrite(ledPin, LOW);
}
void setLED(int stare_LED){
//daca starea ledului este 1 opreste led-ul si activeaza avertizarea sonora if (stare_LED==1){
digitalWrite(ledPin, LOW);
tone(buzzerPin,2500,interval);
63
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
} //altfel aprinde led-ul else{
digitalWrite(ledPin, HIGH);
}
}
//functia pentru deplasare inainte void inainte() {
digitalWrite(MotorPin1, HIGH); digitalWrite(MotorPin2, LOW); digitalWrite(EnableMotor, HIGH);
}
// functia pentru oprirea deplasarii inainte void stop_inainte() {
digitalWrite(EnableMotor, LOW);
}
// functia pentru deplasarea inapoi void inapoi() {
digitalWrite(MotorPin1, LOW); digitalWrite(MotorPin2, HIGH); digitalWrite(EnableMotor, HIGH);
}
//functia pentru oprirea deplasarii inapoi void stop_inapoi() {
digitalWrite(EnableMotor, LOW);
}
//functia pentru virarea la stanga void stanga() {
digitalWrite(DirPin1, HIGH);
digitalWrite(DirPin2, LOW);
digitalWrite(EnableDir, HIGH);
}
64
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
//functia pentru virarea la dreapta void dreapta() {
digitalWrite(DirPin1, LOW);
digitalWrite(DirPin2, HIGH);
digitalWrite(EnableDir, HIGH);
}
//functia pentru oprirea directiei void stop_directie() {
digitalWrite(EnableDir, LOW);
}
//functie ce se executa in loop(); care verifica valoarea primita pe seriala
//si in functie de acea valoare executa una din comenzile motoarelor void executaComanda() {
digitalWrite(EnableDriver, HIGH);
if (Serial.available()) {
val = Serial.read();
}
if (val == 'f') { // daca valoarea primita pe interfata seriala inainte(); // este egala cu "f" executa comanda inainte();
} else if (val == 'z') { // daca valoarea primita pe interfata seriala
stop_inainte(); // este egala cu "z" executa comanda stop_inainte();
} else if (val == 'b') { // daca valoarea primita pe interfata seriala inapoi(); // este egala cu "b" executa comanda
inapoi();
} else if (val == 'y') { // daca valoarea primita pe interfata seriala stop_inapoi(); // este egala cu "y" executa comanda
stop_inapoi();
} else if (val == 'r') { // daca valoarea primita pe interfata seriala dreapta(); // este egala cu "r" executa comanda
dreapta();
} else if (val == 'l') { // daca valoarea primita pe interfata seriala
65
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
stanga(); // este egala cu "l" executa comanda stanga();
} else if (val == 'v') { // daca valoarea primita pe interfata seriala stop_directie(); // este egala cu "v" executa comanda
stop_directie();
} else if (val == 'g') {// daca valoarea primita pe interfata seriala porneste_senzor(); // este egala cu "g" executa comanda
porneste_senzor();
}
}
void loop() {
executaComanda();
}
2. MainActivity.java
package com.example.test2;
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Set;
import java.util.UUID;
import android.app.Activity;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Intent;
import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast;
public class MainActivity extends Activity implements Runnable {
protected static final String TAG = "ArduinoCar";
66
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
private static final int REQUEST_CONNECT_DEVICE = 1; private static final int REQUEST_ENABLE_BT = 2; BluetoothAdapter mBluetoothAdapter;
private UUID applicationUUID = UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB");
private ProgressDialog mBluetoothConnectProgressDialog; private BluetoothSocket mBluetoothSocket; BluetoothDevice mBluetoothDevice;
Button exit;
Button forward; Button reverse; Button left; Button right; Button connect; Button senzor; ImageView led;
TextView txtArduino; Handler h;
private InputStream mmInStream;
private OutputStream mmOutStream;
int val = 0;
final int RECIEVE_MESSAGE = 1; // Status pentru Handler
private StringBuilder sb = new StringBuilder();
@Override
public void onCreate(Bundle mSavedInstanceState) {
super.onCreate(mSavedInstanceState);
setContentView(R.layout.activity_main);
setupButtons(); ScanDevice(); ListaRecente();
// forward();
// reverse();
// left();
// right();
// senzor();
led.setBackgroundResource(R.drawable.button_green);
}
public void comandaMasina() {
forward(); reverse(); left(); right(); senzor();
}
public void setupButtons() {
connect = (Button) findViewById(R.id.scan_button);
exit = (Button) findViewById(R.id.connect_button); forward = (Button) findViewById(R.id.forwardButton); reverse = (Button) findViewById(R.id.reverseButton); left = (Button) findViewById(R.id.leftButton);
right = (Button) findViewById(R.id.rightButton);
67
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
txtArduino = (TextView) findViewById(R.id.txtArduino);
senzor = (Button) findViewById(R.id.senzor);
led = (ImageView) findViewById(R.id.imageView1);
}
public void readFromSerial() {
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE:
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0,
msg.arg1);
endOfLineIndex);
sbprint
sb.append(strIncom);
int endOfLineIndex = sb.indexOf("\r\n");
if (endOfLineIndex > 0) {
String sbprint = sb.substring(0,
sb.delete(0, sb.length()); txtArduino.setTextColor(Color.RED); txtArduino.setText("Valoare Senzor: " +
+ " ppm ");
val = Integer.parseInt(sbprint.toString());
if (val > 400)
alert();
else {
led.setBackgroundResource(R.drawable.button_green);
}
}
break;
}
}
};
}
public void alert() {
led.setBackgroundResource(R.drawable.button_red);
}
public void forward() {
forward.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
write("z");
}
});
forward.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
write("f");
return false;
}
});}
68
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
public void reverse() {
reverse.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
write("y");
}
});
reverse.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
write("b");
return false;
}
});
}
public void left() {
left.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
write("v");
}
});
left.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
write("l");
return false;
}
});
}
public void right() {
right.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
write("v");
}
});
right.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
write("v");
return false;
}
});
}
public void senzor() {
senzor.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
write("g");
readFromSerial();
}
});
}
69
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
@Override
public boolean onCreateOptionsMenu(Menu menu) { MenuInflater menuInflater = getMenuInflater(); menuInflater.inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.lista_recente:
listaRec();
break;
case R.id.scan_settings:
scan();
break;
case R.id.exit_settings: android.os.Process.killProcess(android.os.Process.myPid()); break;
}
return super.onOptionsItemSelected(item);
}
public void ScanDevice() {
connect.setOnClickListener(new View.OnClickListener() {
public void onClick(View mView) {
scan();
}
});
}
private void scan() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
Toast.makeText(MainActivity.this, "Message1", 2000).show();
} else {
if (!mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent,
REQUEST_ENABLE_BT);
} else {
REQUEST_CONNECT_DEVICE);
ListPairedDevices();
Intent connectIntent = new Intent(MainActivity.this,
DeviceListActivity.class);
startActivityForResult(connectIntent,
}
}
}
public void ListaRecente() {
exit.setOnClickListener(new View.OnClickListener() {
70
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
public void onClick(View mView) {
android.os.Process.killProcess(android.os.Process.myPid());
}
});
}
private void listaRec() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
Toast.makeText(MainActivity.this, "Message2", 2000).show();
} else {
if (!mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent,
REQUEST_ENABLE_BT);
} else { ListPairedDevices();
Intent connectIntent = new Intent(MainActivity.this, DeviceListActivity.class);
startActivityForResult(connectIntent,
REQUEST_CONNECT_DEVICE);
}
}
}
public void onActivityResult(int mRequestCode, int mResultCode, Intent mDataIntent) {
super.onActivityResult(mRequestCode, mResultCode, mDataIntent);
switch (mRequestCode) {
case REQUEST_CONNECT_DEVICE:
if (mResultCode == Activity.RESULT_OK) {
Bundle mExtra = mDataIntent.getExtras();
String mDeviceAddress =
mExtra.getString("DeviceAddress");
Log.v(TAG, "Coming incoming address " + mDeviceAddress);
mBluetoothDevice = mBluetoothAdapter
.getRemoteDevice(mDeviceAddress);
ProgressDialog.show(this,
+ " : "
mBluetoothConnectProgressDialog =
"Connecting…", mBluetoothDevice.getName()
+
mBluetoothDevice.getAddress(), true, false);
Thread mBlutoothConnectThread = new Thread(this);
mBlutoothConnectThread.start();
Runnable task = new Runnable() {
public void run() {
mBluetoothConnectProgressDialog.dismiss();
}
};
Handler timer = new Handler();
timer.postDelayed(task, 10000);
71
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
}
break;
case REQUEST_ENABLE_BT:
if (mResultCode == Activity.RESULT_OK) { ListPairedDevices();
Intent connectIntent = new Intent(MainActivity.this, DeviceListActivity.class);
startActivityForResult(connectIntent,
REQUEST_CONNECT_DEVICE);
} else {
Toast.makeText(MainActivity.this, "Message",
2000).show();
}
}
}
break;
private void ListPairedDevices() {
Set<BluetoothDevice> mPairedDevices = mBluetoothAdapter
.getBondedDevices();
if (mPairedDevices.size() > 0) {
for (BluetoothDevice mDevice : mPairedDevices) {
Log.v(TAG, "PairedDevices: " + mDevice.getName() + " "
+ mDevice.getAddress());
}
}
}
public void run() {
InputStream tmpIn = null; OutputStream tmpOut = null; try {
mBluetoothSocket = mBluetoothDevice
.createRfcommSocketToServiceRecord(applicationUUID); mBluetoothAdapter.cancelDiscovery(); mBluetoothSocket.connect(); mHandler.sendEmptyMessage(0);
tmpIn = mBluetoothSocket.getInputStream();
tmpOut = mBluetoothSocket.getOutputStream();
if (mBluetoothSocket.isConnected()) {
comandaMasina();
}
} catch (IOException eConnectException) {
Log.d(TAG, "CouldNotConnectToSocket", eConnectException);
closeSocket(mBluetoothSocket);
return;
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
byte[] buffer = new byte[256];
72
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
int bytes;
while (true) {
try {
bytes = mmInStream.read(buffer);
h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
public void write(String message) {
Log.d(TAG, "…Data to send: " + message + "…");
byte[] msgBuffer = message.getBytes();
try {
mmOutStream.write(msgBuffer);
} catch (IOException e) {
Log.d(TAG, "…Error data send: " + e.getMessage() + "…");
}
}
private void closeSocket(BluetoothSocket nOpenSocket) {
try {
nOpenSocket.close();
Log.d(TAG, "SocketClosed");
} catch (IOException ex) {
Log.d(TAG, "CouldNotCloseSocket");
}
}
5000)
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) { mBluetoothConnectProgressDialog.dismiss(); Toast.makeText(MainActivity.this, "Dispozitiv conectat !",
.show();
}
};
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == event.KEYCODE_HOME)
android.os.Process.killProcess(android.os.Process.myPid());
return super.onKeyDown(keyCode, event);
}
}
73
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
3.DeviceListActivity.java package com.example.test2; import java.util.Set;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log; import android.view.View; import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
/**
* Aceasta activitate apare ca o fereastra de dialog. Listeaza dispozitivele
* asociate si descoperite.
*/
public class DeviceListActivity extends Activity {
// Debugging
private static final String TAG = "DeviceListActivity";
private static final boolean D = true;
// declararea variabilelor
private BluetoothAdapter mBluetoothAdapter;
private ArrayAdapter<String> mPairedDevicesArrayAdapter; private ArrayAdapter<String> mNewDevicesArrayAdapter; Button scan;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// configurarea ferestrei requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.device_list);
setResult(Activity.RESULT_CANCELED);
// initializarea butonului scan pentru descoperire Button scan = (Button) findViewById(R.id.button_scan); scan.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
doDiscovery();
v.setVisibility(View.GONE);
}
74
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
});
// initializarea matricilor in care se salveaza dispozitivele mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this,
R.layout.device_name);
mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
// initializarea ListView-ului pentru dispozitivele asociate
ListView pairedListView = (ListView)
findViewById(R.id.paired_devices); pairedListView.setAdapter(mPairedDevicesArrayAdapter); pairedListView.setOnItemClickListener(mDeviceClickListener);
// initializarea ListView-ului pentru dispozitivele descoperite
ListView newDevicesListView = (ListView)
findViewById(R.id.new_devices); newDevicesListView.setAdapter(mNewDevicesArrayAdapter); newDevicesListView.setOnItemClickListener(mDeviceClickListener);
descoperite
descoperirii
// inregistrarea unui receptor de mesaje petru dispozitivele
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver, filter);
// inregistrarea unui receptor de mesaje pentru finalizarea filter = new
IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, filter);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// se obtine un set de dispozitive asociate
Set<BluetoothDevice> mPairedDevices = mBluetoothAdapter
.getBondedDevices();
// daca sunt dispozitive asociate se adauga cate unul in matrice
if (mPairedDevices.size() > 0) {
for (BluetoothDevice device : mPairedDevices) {
mPairedDevicesArrayAdapter.add(device.getName() + "\n"
+ device.getAddress());
}
} else {
String noDevices =
getResources().getText(R.string.none_paired)
.toString();
mPairedDevicesArrayAdapter.add(noDevices);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// se verifica daca procesul de descoperire este terminat
if (mBluetoothAdapter != null) {
mBluetoothAdapter.cancelDiscovery();
}
75
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
this.unregisterReceiver(mReceiver);
}
/**
* procesul de descoperire
*/
private void doDiscovery() {
if (D)
Log.d(TAG, "doDiscovery()");
// indica pe ecran "scanare…" setProgressBarIndeterminateVisibility(true); setTitle(R.string.scanning);
// se deschide lista pentru dispozitivele descoperite findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
// incepe procesul de descoperire mBluetoothAdapter.startDiscovery();
}
// selectarea unui dispozitiv din lista
private OnItemClickListener mDeviceClickListener = new
OnItemClickListener() {
public void onItemClick(AdapterView<?> mAdapterView, View mView,
int mPosition, long mLong) {
// se opreste procesul de descoperire
mBluetoothAdapter.cancelDiscovery();
// se extrage MAC-ul dispozitivului care reprezinta ultimele
17
// caractere din lista
String mDeviceInfo = ((TextView) mView).getText().toString(); String mDeviceAddress = mDeviceInfo
.substring(mDeviceInfo.length() – 17); Log.v(TAG, "Device_Address " + mDeviceAddress);
Bundle mBundle = new Bundle(); mBundle.putString("DeviceAddress", mDeviceAddress); Intent mBackIntent = new Intent(); mBackIntent.putExtras(mBundle); setResult(Activity.RESULT_OK, mBackIntent); finish();
}
};
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) { String action = intent.getAction();
// cand procesul de descoperire gaseste un dispozitiv
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
76
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
// se preia obiectul din Intent
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// daca este deja asociat, se trece la urmatorul
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
"\n"
mNewDevicesArrayAdapter.add(device.getName() +
+ device.getAddress());
}
titlul
// cand procesul de descoperire se termina, se schimba
// listei
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
.equals(action)) {
setProgressBarIndeterminateVisibility(false);
setTitle(R.string.select_device);
if (mNewDevicesArrayAdapter.getCount() == 0) {
String noDevices = getResources().getText( R.string.none_found).toString();
mNewDevicesArrayAdapter.add(noDevices);
}
}
}
};
}
77
Anexe
1.Cod pentru Arduino
// Cod pentru comandarea robotului mobil
// LICENTA 2013
//SARIVAN IONUT
//Facultatea de Inginerie Electrica si Stiinta Calculatoarelor
int EnableDir = 9; // pin de validare directie int EnableMotor = 3; // pin de validare deplasare
int DirPin1 = 10; // pinii de comanda pentru directie int DirPin2 = 12; //
int MotorPin1 = 4; // pinii de comanda pentru deplasare
int MotorPin2 = 5; //
int EnableDriver = 6; //pin de activare driver L293D
int senzorPin = A0; // pinul de intrare analogica pentru senzorul de gaz int ledPin = 13; // led de avertizare
int buzzerPin = 8; //pin pentru difuzor piezoelectric
char val; // se stocheaza datele primite pe serial int senzorVal =0; // valoarea citita de senzor
char stareSenzor; //
int stareLed = 0;
int nr_conversii = 3; // variabila care seteaza numarul de conversii efectuate de ADC
int limit = 500; // valoare limita pentru avertizare sonora int interval = 100;
long previousMillis = 0;
//initializarea pinilor si setarea Baud rate-ului la 9600bps void setup() {
pinMode(EnableDir, OUTPUT); pinMode(EnableMotor, OUTPUT); pinMode(DirPin1, OUTPUT);
61
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
pinMode(DirPin2, OUTPUT); pinMode(MotorPin1, OUTPUT); pinMode(MotorPin2, OUTPUT); pinMode(EnableDriver, OUTPUT); pinMode(senzorPin,INPUT); pinMode(ledPin,OUTPUT); Serial.begin(9600);
}
void porneste_senzor(){
senzorVal = readSensor(senzorPin, nr_conversii);
//afiseaza valorile pe seriala
Serial.println(senzorVal);
//daca valoarea de la senzor este mai mare decat limita stabilita
//incepe avertizarea sonora if (senzorVal > limit){
aprindeLED();
}
else
{
stopLED();
}
}
//citirea valorilor senzorului si returnarea unei valori medii int readSensor(int PIN, int nr_conversii) {
int val_medie;
int val[nr_conversii];
int suma_val = 0;
for(int x = 0; x < nr_conversii; x++){
val[x] = analogRead(PIN);
suma_val = suma_val + val[x];
delay(1000);
62
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
}
val_medie = suma_val/nr_conversii;
return val_medie;
}
void aprindeLED(){
unsigned long currentMillis = millis(); //functia milis(); din libraria
Arduino returneaza
pornita
//nr de milisencunde de cand placa a fost
if(currentMillis – previousMillis > interval) {
// salveaza timpul la care s-a aprins LED-ul previousMillis = currentMillis;
// daca led-ul este oprit il aprinde si invers:
if (stareLed == 0)
stareLed = 1;
else
stareLed = 0;
// seteaza starea led-ului pentru functia setLED();
setLED(stareLed);
}
}
void stopLED(){
digitalWrite(ledPin, LOW);
}
void setLED(int stare_LED){
//daca starea ledului este 1 opreste led-ul si activeaza avertizarea sonora if (stare_LED==1){
digitalWrite(ledPin, LOW);
tone(buzzerPin,2500,interval);
63
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
} //altfel aprinde led-ul else{
digitalWrite(ledPin, HIGH);
}
}
//functia pentru deplasare inainte void inainte() {
digitalWrite(MotorPin1, HIGH); digitalWrite(MotorPin2, LOW); digitalWrite(EnableMotor, HIGH);
}
// functia pentru oprirea deplasarii inainte void stop_inainte() {
digitalWrite(EnableMotor, LOW);
}
// functia pentru deplasarea inapoi void inapoi() {
digitalWrite(MotorPin1, LOW); digitalWrite(MotorPin2, HIGH); digitalWrite(EnableMotor, HIGH);
}
//functia pentru oprirea deplasarii inapoi void stop_inapoi() {
digitalWrite(EnableMotor, LOW);
}
//functia pentru virarea la stanga void stanga() {
digitalWrite(DirPin1, HIGH);
digitalWrite(DirPin2, LOW);
digitalWrite(EnableDir, HIGH);
}
64
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
//functia pentru virarea la dreapta void dreapta() {
digitalWrite(DirPin1, LOW);
digitalWrite(DirPin2, HIGH);
digitalWrite(EnableDir, HIGH);
}
//functia pentru oprirea directiei void stop_directie() {
digitalWrite(EnableDir, LOW);
}
//functie ce se executa in loop(); care verifica valoarea primita pe seriala
//si in functie de acea valoare executa una din comenzile motoarelor void executaComanda() {
digitalWrite(EnableDriver, HIGH);
if (Serial.available()) {
val = Serial.read();
}
if (val == 'f') { // daca valoarea primita pe interfata seriala inainte(); // este egala cu "f" executa comanda inainte();
} else if (val == 'z') { // daca valoarea primita pe interfata seriala
stop_inainte(); // este egala cu "z" executa comanda stop_inainte();
} else if (val == 'b') { // daca valoarea primita pe interfata seriala inapoi(); // este egala cu "b" executa comanda
inapoi();
} else if (val == 'y') { // daca valoarea primita pe interfata seriala stop_inapoi(); // este egala cu "y" executa comanda
stop_inapoi();
} else if (val == 'r') { // daca valoarea primita pe interfata seriala dreapta(); // este egala cu "r" executa comanda
dreapta();
} else if (val == 'l') { // daca valoarea primita pe interfata seriala
65
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
stanga(); // este egala cu "l" executa comanda stanga();
} else if (val == 'v') { // daca valoarea primita pe interfata seriala stop_directie(); // este egala cu "v" executa comanda
stop_directie();
} else if (val == 'g') {// daca valoarea primita pe interfata seriala porneste_senzor(); // este egala cu "g" executa comanda
porneste_senzor();
}
}
void loop() {
executaComanda();
}
2. MainActivity.java
package com.example.test2;
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Set;
import java.util.UUID;
import android.app.Activity;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Intent;
import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast;
public class MainActivity extends Activity implements Runnable {
protected static final String TAG = "ArduinoCar";
66
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
private static final int REQUEST_CONNECT_DEVICE = 1; private static final int REQUEST_ENABLE_BT = 2; BluetoothAdapter mBluetoothAdapter;
private UUID applicationUUID = UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB");
private ProgressDialog mBluetoothConnectProgressDialog; private BluetoothSocket mBluetoothSocket; BluetoothDevice mBluetoothDevice;
Button exit;
Button forward; Button reverse; Button left; Button right; Button connect; Button senzor; ImageView led;
TextView txtArduino; Handler h;
private InputStream mmInStream;
private OutputStream mmOutStream;
int val = 0;
final int RECIEVE_MESSAGE = 1; // Status pentru Handler
private StringBuilder sb = new StringBuilder();
@Override
public void onCreate(Bundle mSavedInstanceState) {
super.onCreate(mSavedInstanceState);
setContentView(R.layout.activity_main);
setupButtons(); ScanDevice(); ListaRecente();
// forward();
// reverse();
// left();
// right();
// senzor();
led.setBackgroundResource(R.drawable.button_green);
}
public void comandaMasina() {
forward(); reverse(); left(); right(); senzor();
}
public void setupButtons() {
connect = (Button) findViewById(R.id.scan_button);
exit = (Button) findViewById(R.id.connect_button); forward = (Button) findViewById(R.id.forwardButton); reverse = (Button) findViewById(R.id.reverseButton); left = (Button) findViewById(R.id.leftButton);
right = (Button) findViewById(R.id.rightButton);
67
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
txtArduino = (TextView) findViewById(R.id.txtArduino);
senzor = (Button) findViewById(R.id.senzor);
led = (ImageView) findViewById(R.id.imageView1);
}
public void readFromSerial() {
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case RECIEVE_MESSAGE:
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0,
msg.arg1);
endOfLineIndex);
sbprint
sb.append(strIncom);
int endOfLineIndex = sb.indexOf("\r\n");
if (endOfLineIndex > 0) {
String sbprint = sb.substring(0,
sb.delete(0, sb.length()); txtArduino.setTextColor(Color.RED); txtArduino.setText("Valoare Senzor: " +
+ " ppm ");
val = Integer.parseInt(sbprint.toString());
if (val > 400)
alert();
else {
led.setBackgroundResource(R.drawable.button_green);
}
}
break;
}
}
};
}
public void alert() {
led.setBackgroundResource(R.drawable.button_red);
}
public void forward() {
forward.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
write("z");
}
});
forward.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
write("f");
return false;
}
});}
68
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
public void reverse() {
reverse.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
write("y");
}
});
reverse.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
write("b");
return false;
}
});
}
public void left() {
left.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
write("v");
}
});
left.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
write("l");
return false;
}
});
}
public void right() {
right.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
write("v");
}
});
right.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
write("v");
return false;
}
});
}
public void senzor() {
senzor.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
write("g");
readFromSerial();
}
});
}
69
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
@Override
public boolean onCreateOptionsMenu(Menu menu) { MenuInflater menuInflater = getMenuInflater(); menuInflater.inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.lista_recente:
listaRec();
break;
case R.id.scan_settings:
scan();
break;
case R.id.exit_settings: android.os.Process.killProcess(android.os.Process.myPid()); break;
}
return super.onOptionsItemSelected(item);
}
public void ScanDevice() {
connect.setOnClickListener(new View.OnClickListener() {
public void onClick(View mView) {
scan();
}
});
}
private void scan() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
Toast.makeText(MainActivity.this, "Message1", 2000).show();
} else {
if (!mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent,
REQUEST_ENABLE_BT);
} else {
REQUEST_CONNECT_DEVICE);
ListPairedDevices();
Intent connectIntent = new Intent(MainActivity.this,
DeviceListActivity.class);
startActivityForResult(connectIntent,
}
}
}
public void ListaRecente() {
exit.setOnClickListener(new View.OnClickListener() {
70
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
public void onClick(View mView) {
android.os.Process.killProcess(android.os.Process.myPid());
}
});
}
private void listaRec() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
Toast.makeText(MainActivity.this, "Message2", 2000).show();
} else {
if (!mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent,
REQUEST_ENABLE_BT);
} else { ListPairedDevices();
Intent connectIntent = new Intent(MainActivity.this, DeviceListActivity.class);
startActivityForResult(connectIntent,
REQUEST_CONNECT_DEVICE);
}
}
}
public void onActivityResult(int mRequestCode, int mResultCode, Intent mDataIntent) {
super.onActivityResult(mRequestCode, mResultCode, mDataIntent);
switch (mRequestCode) {
case REQUEST_CONNECT_DEVICE:
if (mResultCode == Activity.RESULT_OK) {
Bundle mExtra = mDataIntent.getExtras();
String mDeviceAddress =
mExtra.getString("DeviceAddress");
Log.v(TAG, "Coming incoming address " + mDeviceAddress);
mBluetoothDevice = mBluetoothAdapter
.getRemoteDevice(mDeviceAddress);
ProgressDialog.show(this,
+ " : "
mBluetoothConnectProgressDialog =
"Connecting…", mBluetoothDevice.getName()
+
mBluetoothDevice.getAddress(), true, false);
Thread mBlutoothConnectThread = new Thread(this);
mBlutoothConnectThread.start();
Runnable task = new Runnable() {
public void run() {
mBluetoothConnectProgressDialog.dismiss();
}
};
Handler timer = new Handler();
timer.postDelayed(task, 10000);
71
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
}
break;
case REQUEST_ENABLE_BT:
if (mResultCode == Activity.RESULT_OK) { ListPairedDevices();
Intent connectIntent = new Intent(MainActivity.this, DeviceListActivity.class);
startActivityForResult(connectIntent,
REQUEST_CONNECT_DEVICE);
} else {
Toast.makeText(MainActivity.this, "Message",
2000).show();
}
}
}
break;
private void ListPairedDevices() {
Set<BluetoothDevice> mPairedDevices = mBluetoothAdapter
.getBondedDevices();
if (mPairedDevices.size() > 0) {
for (BluetoothDevice mDevice : mPairedDevices) {
Log.v(TAG, "PairedDevices: " + mDevice.getName() + " "
+ mDevice.getAddress());
}
}
}
public void run() {
InputStream tmpIn = null; OutputStream tmpOut = null; try {
mBluetoothSocket = mBluetoothDevice
.createRfcommSocketToServiceRecord(applicationUUID); mBluetoothAdapter.cancelDiscovery(); mBluetoothSocket.connect(); mHandler.sendEmptyMessage(0);
tmpIn = mBluetoothSocket.getInputStream();
tmpOut = mBluetoothSocket.getOutputStream();
if (mBluetoothSocket.isConnected()) {
comandaMasina();
}
} catch (IOException eConnectException) {
Log.d(TAG, "CouldNotConnectToSocket", eConnectException);
closeSocket(mBluetoothSocket);
return;
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
byte[] buffer = new byte[256];
72
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
int bytes;
while (true) {
try {
bytes = mmInStream.read(buffer);
h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
public void write(String message) {
Log.d(TAG, "…Data to send: " + message + "…");
byte[] msgBuffer = message.getBytes();
try {
mmOutStream.write(msgBuffer);
} catch (IOException e) {
Log.d(TAG, "…Error data send: " + e.getMessage() + "…");
}
}
private void closeSocket(BluetoothSocket nOpenSocket) {
try {
nOpenSocket.close();
Log.d(TAG, "SocketClosed");
} catch (IOException ex) {
Log.d(TAG, "CouldNotCloseSocket");
}
}
5000)
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) { mBluetoothConnectProgressDialog.dismiss(); Toast.makeText(MainActivity.this, "Dispozitiv conectat !",
.show();
}
};
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == event.KEYCODE_HOME)
android.os.Process.killProcess(android.os.Process.myPid());
return super.onKeyDown(keyCode, event);
}
}
73
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
3.DeviceListActivity.java package com.example.test2; import java.util.Set;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log; import android.view.View; import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
/**
* Aceasta activitate apare ca o fereastra de dialog. Listeaza dispozitivele
* asociate si descoperite.
*/
public class DeviceListActivity extends Activity {
// Debugging
private static final String TAG = "DeviceListActivity";
private static final boolean D = true;
// declararea variabilelor
private BluetoothAdapter mBluetoothAdapter;
private ArrayAdapter<String> mPairedDevicesArrayAdapter; private ArrayAdapter<String> mNewDevicesArrayAdapter; Button scan;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// configurarea ferestrei requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.device_list);
setResult(Activity.RESULT_CANCELED);
// initializarea butonului scan pentru descoperire Button scan = (Button) findViewById(R.id.button_scan); scan.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
doDiscovery();
v.setVisibility(View.GONE);
}
74
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
});
// initializarea matricilor in care se salveaza dispozitivele mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this,
R.layout.device_name);
mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
// initializarea ListView-ului pentru dispozitivele asociate
ListView pairedListView = (ListView)
findViewById(R.id.paired_devices); pairedListView.setAdapter(mPairedDevicesArrayAdapter); pairedListView.setOnItemClickListener(mDeviceClickListener);
// initializarea ListView-ului pentru dispozitivele descoperite
ListView newDevicesListView = (ListView)
findViewById(R.id.new_devices); newDevicesListView.setAdapter(mNewDevicesArrayAdapter); newDevicesListView.setOnItemClickListener(mDeviceClickListener);
descoperite
descoperirii
// inregistrarea unui receptor de mesaje petru dispozitivele
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver, filter);
// inregistrarea unui receptor de mesaje pentru finalizarea filter = new
IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, filter);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// se obtine un set de dispozitive asociate
Set<BluetoothDevice> mPairedDevices = mBluetoothAdapter
.getBondedDevices();
// daca sunt dispozitive asociate se adauga cate unul in matrice
if (mPairedDevices.size() > 0) {
for (BluetoothDevice device : mPairedDevices) {
mPairedDevicesArrayAdapter.add(device.getName() + "\n"
+ device.getAddress());
}
} else {
String noDevices =
getResources().getText(R.string.none_paired)
.toString();
mPairedDevicesArrayAdapter.add(noDevices);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// se verifica daca procesul de descoperire este terminat
if (mBluetoothAdapter != null) {
mBluetoothAdapter.cancelDiscovery();
}
75
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
this.unregisterReceiver(mReceiver);
}
/**
* procesul de descoperire
*/
private void doDiscovery() {
if (D)
Log.d(TAG, "doDiscovery()");
// indica pe ecran "scanare…" setProgressBarIndeterminateVisibility(true); setTitle(R.string.scanning);
// se deschide lista pentru dispozitivele descoperite findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
// incepe procesul de descoperire mBluetoothAdapter.startDiscovery();
}
// selectarea unui dispozitiv din lista
private OnItemClickListener mDeviceClickListener = new
OnItemClickListener() {
public void onItemClick(AdapterView<?> mAdapterView, View mView,
int mPosition, long mLong) {
// se opreste procesul de descoperire
mBluetoothAdapter.cancelDiscovery();
// se extrage MAC-ul dispozitivului care reprezinta ultimele
17
// caractere din lista
String mDeviceInfo = ((TextView) mView).getText().toString(); String mDeviceAddress = mDeviceInfo
.substring(mDeviceInfo.length() – 17); Log.v(TAG, "Device_Address " + mDeviceAddress);
Bundle mBundle = new Bundle(); mBundle.putString("DeviceAddress", mDeviceAddress); Intent mBackIntent = new Intent(); mBackIntent.putExtras(mBundle); setResult(Activity.RESULT_OK, mBackIntent); finish();
}
};
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) { String action = intent.getAction();
// cand procesul de descoperire gaseste un dispozitiv
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
76
Universitatea Transilvania din Brașov Calculatoare
Facultatea de Inginerie Electrică și Știința Calculatoarelor 2013
// se preia obiectul din Intent
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// daca este deja asociat, se trece la urmatorul
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
"\n"
mNewDevicesArrayAdapter.add(device.getName() +
+ device.getAddress());
}
titlul
// cand procesul de descoperire se termina, se schimba
// listei
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
.equals(action)) {
setProgressBarIndeterminateVisibility(false);
setTitle(R.string.select_device);
if (mNewDevicesArrayAdapter.getCount() == 0) {
String noDevices = getResources().getText( R.string.none_found).toString();
mNewDevicesArrayAdapter.add(noDevices);
}
}
}
};
}
77
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Calculatoare (ID: 149597)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
