FUNDAȚIA PENTRU CULTURĂ ȘI ÎNVĂȚĂMÂNT IOAN SLAVICI TIMIȘOARA [306613]
FUNDAȚIA PENTRU CULTURĂ ȘI ÎNVĂȚĂMÂNT “IOAN SLAVICI” TIMIȘOARA
UNIVERSITATEA “IOAN SLAVICI” [anonimizat]. Mircea Vlăduțiu
ABSOLVENT: [anonimizat] 2016 –
FUNDAȚIA PENTRU CULTURĂ ȘI ÎNVĂȚĂMÂNT “IOAN SLAVICI” TIMIȘOARA
UNIVERSITATEA “IOAN SLAVICI” [anonimizat]. Mircea Vlăduțiu
ABSOLVENT: [anonimizat]
2016
UNIVERSITATEA DIN ORADEA
FACULTATEA de Inginerie Electrică și Tehnologia Informației
DEPARTAMENTUL Calculatoare și tehnologia informației
TEMA _________________
Proiectul de Finalizare a studiilor a student: [anonimizat]: Ciont Liviu
1). Tema proiectului de finalizare a studiilor: MiniStațieMeteo
2). Termenul pentru predarea proiectului de diplomă:14.06.2016
3). Elemente inițiale pentru elaborarea proiectului de finalizare a studiilor: Placa de dezvoltare Arduino și senzor de temperatură și umiditate
4). Conținutul proiectului de finalizare a studiilor : [anonimizat] a unei stații meteo care măsoară temperatura și umiditatea prin intermediul plăcii de dezvoltare Arduino
5). Material grafic: [anonimizat]
6). Locul de documentare pentru elaborarea proiectului de diplomă: Biblioteca “Universității Politehnica” din Timișoara și Biblioteca “Universității de Vest” din Timișoara
7). Data emiterii temei: 20.10.2015
Coordonatori științifici
Prof. dr. ing. Mircea Vlăduțiu
REFERAT
PRIVIND PROIECTUL DE DIPLOMĂ
A
ABSOLVENT: [anonimizat] : Ciont Liviu
DOMENIUL Calculatoare și tehnologia informației
SPECIALIZAREA Tehnologia informației
PROMOȚIA 2016
Titlul proiectului: MiniStațieMeteo
Structura proiectului:
1.Introducere
2.Elemente constructive ale dispozitivului MiniStațieMeteo
3.Asamblarea dispozitivului MiniStațieMeteo
4.Construcție și tehnologie
5.Elemente de punere în funcțiune și depanare
6.Concluzii
Bibliografie
Anexe
Aprecieri asupra conținutului proiectului de DIPLOMĂ (finalizare a studiilor), [anonimizat], actualitate, deficiențe
Structura lucrării aparține absolvent: [anonimizat], acesta alocând o pondere de 25% [anonimizat]. [anonimizat].
[anonimizat] o bună coerență.
Lucrarea conține o parte aplicativă consistentă implicând soluții cu caracter de originalitate software și hardware.
Lucrarea tratează o problematică de strictă actualitate luând în considerație importanța domeniului calculului ambiental.
Aprecieri asupra proiectului (se va menționa: [anonimizat], calitatea și diversitatea surselor consultate; modul în care absolvent: [anonimizat], totuși investigația de literatură de specialitate este limitată.Sursele bibliografice sunt alese în mod corespuzător.
Considerăm tematica dată spre rezolvare ca fiind integral soluționată.
Materialul grafic este executat în mod îngrijit, fiind complementar părții redactate.
Redactarea lucrării este realizată într-o manieră concisă si clara.
(se va menționa: opțional locul de documentare și modul în care absolventul a realizat cercetarea menționându-se contribuția autorului)
Informațiile prelucrate din surse teoretice sunt citate în mod corespunzător, fiind inserate în lucrare doar pe măsură ce sunt utilizate pentru înlesnirea părții aplicative.
Concluzii (coordonatorul proiectului trebuie să aprecieze valoarea proiectului întocmit, relevanța studiului întreprins, competențele absolventului, rigurozitatea pe parcursul elaborării proiectului, consecvența și seriozitatea de care a dat dovadă absolventul pe parcurs)
În baza celor mai sus menționate, apreciez că lucrarea elaborată de absolvent este foarte valoroasă, absolventul dovedind reale competențe în domeniul calculului ambiental.
De asemenea, apreciez rigoare în activitatea de elaborare a lucrării de licență, absolventul dovedind consecvență și seriozitate.
Redactarea proiectului respectă ………………………………………………….cerințele academice de redactare (părți, capitole, subcapitole, note de subsol și bibliografie).
Consider că proiectul îndeplinește/ nu îndeplinește condițiile pentru susținere în sesiunea de Examen de LICENȚĂ (finalizare a studiilor) din IULIE 2016 și propun acordarea notei ………………
Oradea,
Data Conducător științific
20.06.2016 Prof. dr. ing. Mircea Vlăduțiu
Cuprins
Pagina
1. Introducere……………………………………………………………………………………………………………………7
Utilitate și construcție MiniStațieMeteo………………………………………………………………………7
Structura lucrării………………………………………………………………………………………………………7
2. Elemente constructive ale dispozitivului MiniStațieMeteo……………………………………………….8
2.1 Placa de dezvoltare Arduino UNO R3…………………………………………………………………………8
2.1.1 Microcontrolerul Atmega328…………………………………………………………………………………..9
2.1.2 Comunicația între placa Arduino și PC…………………………………………………………………….11
2.1.3 Limbaj de programare……………………………………………………………………………………………12
2.1.4 Senzor umiditate și temperatură AM2302………………………………………………………………..13
2.1.5 Modul ZS-042………………………………………………………………………………………………………15
2.1.6 Modulul MicroSD…………………………………………………………………………………………………16
2.1.7 Ecran cu cristale lichide 1602………………………………………………………………………………….18
2.1.8 Encoder Rotativ KY-040………………………………………………………………………………………..20
2.1.9 Protocolul de comunicare I2C…………………………………………………………………………………21
2.1.10 Protocolul de comunicare SPI……………………………………………………………………………..23
3. Asamblarea dispozitivului MiniStațieMeteo……………………………………………………………………24
3.1 Schema bloc…………………………………………………………………………………………………………….24
3.2 Programarea microcontrolerului…………………………………………………………………………………25
4. Construcție și tehnologie………………………………………………………………………………………………..33
4.1 Imprimare Cablaj……………………………………………………………………………………………………..33
5. Elemente de punere în funcțiune și depanare………………………………………………………………….34
5.1 Rezultate de implementare…………………………………………………………………………………………34
5.2 Probleme întâmpinate………………………………………………………………………………………………..36
6. Concluzii……………………………………………………………………………………………………………………….39
Bibliografie……………………………………………………………………………………………………………………….40
Anexe……………………………………………………………………………………………………………………………….41
1. INTRODUCERE
1.1 Utilitate și construcție MiniStațieMeteo.
Menținerea temperaturii și umidității unei încăperi în limite confortabile ne ajută în principal să avem o viață mai liniștită și mai plăcută. Pentru aceasta, avem nevoie in primul rând de un dispozitiv care permite măsurarea temperaturii și umidității în timp real și cu un grad de acuratețe relativ ridicat. Astfel pentru îndeplinirea acestei nevoi, au fost create ministații meteo pentru uz personal.
Lucrarea de față își propune implementarea la scară redusă a unei stații meteo care măsoară temperatura și umiditatea prin intermediul plăcii de dezvoltare Arduino.Voi denumi acest proiect MiniStațieMeteo și prin intermediul lui voi prezenta construcția unui sistem de monitorizare a temperaturii și umiditații dintr-o încăpere cu trei funcții majore: măsurarea temperaturii si umidității mediului ambiant, afișarea datelor cu ajutorul unui ecran LCD și salvarea acestor date pe un card MicroSD. Totodată cu temperatura și umiditatea vor fi afișate data și ora.
1.2 Structura lucrării
Documentul de față este structurat în șase capitole. Capitolul 1 conține introducerea, utilitatea și construcția MiniStațieMeteo, structura lucrării. Capitolul 2 conține informații despre elementele constructive ale dispozitivului. Capitolul 3 descrie asamblarea dispozitivului MiniStațieMeteo. Capitolul 4 prezintă construcția cablajului imprimat. În capitolul 5 am expus elementele de punere în funcțiune și depanarea, Capitolul 6 expune concluziile.
2. ELEMENTE CONSTRUCTIVE ALE DISPOZITIVULUI MiniStațieMeteo
2.1 Placa de dezvoltare Arduino UNO R3
Pentru realizarea acestui proiect am ales o platformă de mici dimensiuni (6.8 cm / 5.3 cm) produsă de Arduino, model Arduino UNO R3 deoarece este o platformă de procesare open-source, bazată pe software si hardware flexibil și simplu de folosit. Această platformă vine cu un microcontroler Atmega328 care este capabil să ruleze cod scris într-un limbaj de programare care este foarte similar cu limbajul C++ și are 14 pini configurabili pentru intrare/ieșire [2].
Placa de dezvoltare Arduino Uno prezentată în figura 1, având microcontrolerul încorporat se prezintă sub forma unei componente pregătită de interconectare, fără a-i adăuga funcții suplimentare (exceptând conversia serial-USB), ci doar facilitând utilizarea acestuia în cadrul unor aplicații diverse, fără a mai avea nevoie de proiectarea și implementarea componentelor suport de bază (alimentare, programator, mufe de interconectare). Conectorii de pe placa de dezvoltare asigură expunerea ordonată a porturilor I/O ai microcontrolerului într-o formă standardizată (conectorul de sus expune pinii porturilor digitale iar conectorul de jos pinii porturilor analogice și pinii de alimentare). Pe lângă toate aceste beneficii, se bucură și de suport software decent, având propriul IDE (Integrated Development Environment) [1].
Figura 1 Placa de dezvoltare Arduino UNO R3
(sursa http://www.explorelabs.com/arduino-uno-r3 )
Specificații [3]:
Specificațiile plăcii sunt date de componentele de pe aceasta:
Microcontroler: ATmega328
Tensiune de lucru: 5V
Tensiune de intrare (recomandat): 7-12V
Tensiune de intrare (limita): 6-20V
Pini digitali: 14 (dintre care 6 permit ieșire PWM Pulse Width Modulation)
Pini analogici: 6
Intensitate de iesire: 40 mA
Intensitate de iesire pe 3.3V: 50 mA
Flash Memory: 32 KB (ATmega328) 0.5 KB pentru bootloader
SRAM: 2 KB (ATmega328)
EEPROM: 1 KB (ATmega328)
Clock Speed: 16 MHz
Lungime: 68,6mm
Lățime: 53.4mm
Greutate: 25g
În figura de mai jos sunt prezentate principalele zone de interes de pe placă:
Figura 2 Cele mai importante zone de pe Ardunio Uno
(sursa https://www.flickr.com/photos/caseorganic/4503567354 )
1. Conector USB
2. Conector pentru alimentare
3. Stabilizator de tensiune
4. Pini digitali
5. Pini analogici
6. Pini pentru alimentare
7. Buton de reset
2.1.1 Microcontrolerul Atmega328
ATmega328 este un microcontroler pe 8 biți, ce consumă o cantitate redusă de energie, face parte din familia Atmel AVR având o arhitectură RISC – “Reduced instruction set computing” si atingând performanțe de 1 MIPS (milion instructions per second) per MHz. Rulează la frecvențe de până la 20 MHz și deține un număr de instrucțiuni de 131 și 132 de registre de uz general pe 8 biți. Capacitatea memoriei interne este de 32 KB memorie program de tip flash, 1 KB memorie utilizator de tip EEPROM și 2 KB memorie de date de tip SRAM [5].
Toate caracteristicile electrice și logice ale pinilor plăcii Arduino Uno sunt importate de la microcontrolerul incorporat Atmega328. Conectorii plăcii Arduino sunt conectați direct cu pinii microcontrolerului fără să aibe circuite auxiliare interconectate, iar in figura 3 este prezentată corespondența dintre ei [1].
Figura 3 Corespondența între pinii microcontrolerului si conectorii plăcii Arduino
Sursa (http://jobs.arduinoexperts.com/2013/03/02/arduino-atmega-pinout-diagrams/)
Specificații [4]:
Familia de microcontrolere: ATmega;
Tip interfața: I2C, SPI USART;
Dimensiune nucleu: 8 biti;
Tensiunea de intrare (limitare): 1.8V-5.5V;
Pini digitali I/O: 23 (din care 6 pot fi folositi ca PWM);
Număr intrări ADC: 6;
Oscilator de tip: intern, extern;
Număr de contoare: 3;
Forma capsulei: PDIP;
Temperatura de operare: -40°C la +85°C;
DC Curent pentru pinii de I/O: 40mA;
DC Curent pentru pinul de 3.3V: 50mA;
Memoria: 32 KB din care 8 KB utilizați de bootloader;
SRAM: 2KB;
EEPROM: 1KB;
Clock Speed: 20MHz;
Periferice: ADC, Comparator, RTC, Timer, PWM;
Set de instrucțiuni: Arhitectura RISC;
2.1.2 Comunicația între placa Arduino și PC
Conexiunea plăcii Arduino Uno cu PC-ul se face printr-un conector USB. Acest conector nu este conectat la un port USB integrat, motivul fiind că microcontrolerul Atmega 328, are doar un port de comunicație serială TTL (transistor-transistor logic) nu are un port USB integrat. Pentru programarea microcontrolerului prin intermediul portului USB, trebuie realizată o conversie între comunicația serială TTL si comunicația USB. Pentru aceasta Arduino Uno folosește un circuit bazat pe microcontrolerul ATmega16U2 care permite translatarea necesară precum și alimentarea plăcii prin intermediul portului USB [1]. În cazul în care un alimentator extern este conectat la mufa dedicată de pe placă, comutarea între alimentarea prin portul USB și alimentarea prin intermediul mufei dedicate se face automat. Conexiunea dintre placa Arduino si PC prin intermediul cablului USB va fi detectată de către sistemul de operare ca și o comunicație serială obișnuită datorită driver-ului instalat. Driver-ul pentru Arduino emulează prin intermediul comunicației USB o comunicație serială clasică. Figura 4 prezintă placa Arduino detectată de către sistemul de operare Windows ca și un dispozitiv cu conexiune serială după instalarea driver-ului.
Figura 4 Comunicația cu placa Arduino Uno detectată de OS
Pentru a programa microcontrolerul de pe placa Arduino Uno folosind sistemul de operare al PC-ului avem nevoie de două lucruri: aplicația software IDE Arduino și instalarea driver-ului de comunicație USB pentru a putea încărca programele scrise.
2.1.3 Limbaj de programare
Mediul de dezvoltare integrat pentru Arduino (Arduino IDE) conține un editor text pentru a scrie cod, o zonă dedicată consolei text și o serie de meniuri. În figura 5 este prezentat acest mediu de dezvoltare. Arduino IDE permite conectarea cu ușurință la hardware de tip Arduino pentru a încărca programe și pentru a comunica [7].
Acest mediu de dezvoltare folosește conceptul de schiță pentru programele concepute, deoarece, în cele mai multe cazuri, sunt programe de mici dimensiuni cu scopuri restrânse. Mediul conține și un monitor pentru serial menit să afișeze datele trimise de Ardunio calculatorului cât și să trimită date către Arduino [7].
După cum am precizat în capitolul 2.1 limbajul folosit în mediul Arduino IDE este similar cu limbajul C++. Conform regulilor ce trebuie respectate în mediul de dezvoltare IDE Arduino pentru a avea un program funcțional, programul folosit la asamblarea dispozitivului MiniStațieMeteo cuprinde două funcții importante: funcția setup în care se fac inițializările și funcția loop în care se scrie codul principal și care va rula într-o buclă infinită pe microcontroler. In afară de aceste două funcții programul mai conține o secvență de inițializare a variabilelor și de includere a unor biblioteci suplimentare, acestea fiind declarate la începutul programului.
Figura 5 Arduino IDE – mediul de dezvoltare
Fiecare program scris în IDE Arduino poartă denumirea de ”sketch” sau schiță [7]. După compilare sau după încărcarea cu succes a programului pe microcontroler în zona de mesaje va apărea un mesaj care va prezenta dimensiunea codului binar rezultat în urma compilării precum și dimensiunea maximă de memorie program . Acest mesaj se poate observa tot în figura 5.
2.1. 4 Senzor umiditate și temperatură AM2302
Umiditatea relativă este prescurtată RH, umiditatea relativă se referă la raportul exprimat in procente a conținutului în umiditate din aer în comparație cu umiditatea saturată la aceeași temperatură și presiune.Următoarea componentă a acestui proiect este senzorul de umiditate și temperatură. Am ales senzorul AM2302 produs de AOSONG Electronics deoarece are o acuratețe ridicată și include atât senzorul de temperatură cât și senzorul de umiditate. Acest senzor este cunoscut ca și DHT22 când este montat pe cablaj. Precizia la măsurarea temperaturii este de +-0.5 °C, la determinarea umidității de +-2% iar prețul de achiziție este unul redus. Acesta este un senzor digital si are integrat un termistor folosit la măsurarea temperaturii si un senzor capacitiv pentru determinarea umidității. Senzorul capacitiv integrat, este construit pe un substrat de silicon. Un strat dielectric format dintr-un film subțire de polimer este atașat între doi electrozi de metal protejați împotriva coroziunii. Suprafața unui electrod este poroasă astfel încât vaporii de apă din aer ating stratul dielectric iar filmul subțire de polimer absoarbe apa. În urma acestei acțiuni, se modifică treptat constanta dielectrică [9]. Prin schimbarea de capacitate, umiditatea relativă va fi măsurată. În figura 6 de mai jos este prezentat senzorul AM2302 și construcția senzorului capacitiv integrat.
Figura 6 Senzorul AM2302
(sursa http://machinedesign.com/news/sensor-sense-humidity-sensors)
Acest senzor are 4 pini numerotați de la stânga la dreapta .După cum este prezentat în figura 7 conexiunea se face în felul următor: pinul 1 VCC este pinul de alimentare conectat la pinul plăcii Arduino 5v, pinul 2 DATA este pinul de comunicație bidirecțională conectat la pinul A2 al plăcii Arduino, pinul 3 NC nu este conectat iar pinul 4 GND pin de masă conectat la pinul GND2 al plăcii Arduino. Între pinul 1 și pinul 2 este montată o rezistență de 4,7 kΩ care are rol de pull-up rezistor. Senzorul vine și cu o bibliotecă Arduino pentru a facilita utilizarea acestuia fară prea mari eforturi.
Figura 7 Conexiunea Senzorului AM2302 cu placaArduino
Protocolul de comunicație folosit este Single-Bus Communication.Comunicația Single –Bus fiind de tipul master – slave pe un singur fir, unde microcontrolerul ATMega328 este master iar AM2302 este slave, doar AM2302 va fi cel interogat. Comunicația prezentată în figura 8 se desfășoară în felul următor:
Când microprocesorul începe și trimite un semnal de start, AM2302 va trece din starea repaus în starea activ.Când microprocesorul termină de trimis semnalul de start, AM2302 va trimite ca și răspuns un semnal de date de 40 de biți care va reprezenta pentru microcontroler valoarea umidității relative și a temperaturii. Dacă ATMega328 nu trimite următorul semnal de start, AM2302 va trece în starea repaus și nu va trimite nici un alt semnal de date până la următoarea interogare. Intervalul dintre două semnale de start trimise senzorului AM2302 de către microprocesorul ATMega328 trebuie să fie mai mare de 2 secunde, in caz contrar AM2302 nu va avea timp să trimită răspuns primului semnal și comunicația nu va fi efectuată [9].
Figura 8 Comunicația Single – Bus dintre ATMega328 și senzorul AM2302
sursa(https://cdn-shop.adafruit.com/datasheets/Digital+humidity+and+temperature+sensor+AM2302.pdf.)
Exemplu [9]:
Microprocesorul ATMega328 primește de la senzorul AM2302 un semnal de 40 de biți după cum urmează:
00000010 10001111 00000001 00000010 10010100
16 biți umiditate relativă 16 biți temperatură 8 biți check-sum
Suma= 00000010 + 10001111 + 00000001 + 00000010 = 10010100
Se convertesc cei 16 biți reprezentând valoarea umidității relative din sistemul de numerație binar în cel hexazecimal după care în cel zecimal: 0000 0010 1000 1111 -> 028Fh -> 655 deci valoarea umidității relative va fi 655÷10=65,5%RH
Se convertesc cei 16 biți reprezentând valoarea temperaturii din sistemul de numerație binar în cel hexazecimal după care în cel zecimal: 0000 0001 0000 0010 -> 0102h -> 258 deci valoarea temperaturii va fi 258÷10=25,8 °C
Check-sum reprezintă ultimii 8 biți ai sumei.
Specificații:[9]
Tensiune de alimentare: 3.3-6V
Curent : 1-1.5mA
Curent standby: 40-50 µA
Umiditate măsurată: 0-100% RH
Temperatura măsurată: -40°C – +80°C
Acuratețe umiditate: +-2% RH
Acuratețe temperatură: +-0.5 C
2.1.5 Modulul ZS-042
Pentru a avea dată și oră am integrat în acest proiect modulul ZS-042 RTC (Real Time Clock) DS3231 prezentat în figura 9.Am ales acest modul pentru că are integrat cipul RTC DS3231, un preț de achiziție destul de mic, o acuratețe rezonabilă pentru dată / oră și un oscilator intern de tip TCXO (Temperature Compensated Crystal Oscillator (Xtal oscillator)) care nu este afectat de factori externi cum ar fi temperatura [10].
Figura 9 Modul RTC ZS-042
(sursa http://tronixlabs.com.au/breakout-boards/real-time-clock/ds3231-real-time-clock-module-australia/)
Totodată modulul are incorporată o baterie ca și sursă secundară de alimentare pentru a menține data și ora când alimentarea externă este întreruptă. Conexiunea cu placa Arduino prezentată în figura 10 se face în felul următor: pinul 3 SCL este conectat la pinul A5 al plăcii Arduino, pinul 4 SDA este conectat la pinul A4 al plăcii Arduino, pinul 5 VCC conectat la pinul 5V al plăcii Arduino iar pinul 6 GND conectat la pinul GND2 al plăcii Arduino. Comunicarea cu platforma Arduino se face prin protocolul I2C folosind pinii SDA și SCL.
Figura 10 Conexiunea dintre modulul ZS -042 și placa Arduino
Specificații [10]:
Tensiune de alimentare: 3,3 – 5V
Acuratețe foarte bună pentru dată și oră
Protocol de comunicare I2C.
Baterie CR2302 încorporată
2.1.6 Modulul MicroSD
Pentru a vedea variațiile de umiditate și temperatură într-un anumit interval de timp, valorile vor fi salvate intr-un fișier text pe un card microSD. Pentru aceasta am folosit un modul MicroSd cu funcții de citire/scriere. Motivul alegerii acestui modul este copatibilitatea deplină cu placa Arduino Uno. Acest modul este prezentat în figura 11.
Figura 11 Modul MicroSD
(sursa http://www.dx.com/p/diy-micro-sd-read-write-module-deep-blue-374196#.Vy75Y01f3IV )
Conexiunea cu platforma Arduino se face după cum urmează: pinul 1 GND conectat la pinul de masă GND al plăcii Arduino, pinul 2 VCC conectat la pinul de alimentare 5V al plăcii Arduino, pinul 3 MISO conectat la pinul D12 al plăcii Arduino, pinul 4 MOSI conectat la pinul D11 al plăcii, pinul 5 SCK conenctat la pinul D13 al plăcii iar pinul 6 CS (chip selection) conectat la pinul D10 al plăcii Aduino. Schema electrică a acestei conexiuni este prezentată in figura 12. Acest modul comunică cu platforma Arduino prin protocolul SPI (Serial Pheripheral Interface).
Figura 12 Conexiunea dintre modulul MicroSD si placa Arduino
Specificații [11]:
– Tensiune de alimentare: 3,3 – 5V
– Curent: 0,2 – 200mA
– suportă MicroSd card <= 2Gb sau Micro SDHC card <=32Gb
2.1.7 Ecran cu cristale lichide 1602
La afișarea informațiilor de la senzorul AM2302 și de la modulul RTC DS3231, am folosit un afișaj LCD (Liquid Crystal Display) 1602 de tip alfanumeric . Acest LCD prezentat în figura 13 are lumina de fundal galbenă iar caracterele negre. Modul de afișare este de 16X2, care poate afișa 16 caractere pe 2 linii. Fiecare caracter este afișat pe o matrice de 5X8 pixeli. Modulul LCD funcționează cu ajutorul a două registre: Command și Data [12].
Registrul Command înregistrează comenzile ce sunt trimise LCD-ului.Comenzile ce pot fi date sunt sarcini predefinite ce pot fi de inițializare, ștergere, setarea poziției cursorului etc.Registrul Data înregistrează datele ce vor fi afișate. Datele sunt înregistrate in cod ASCII [1].
Figura 13 LCD 1602
(sursa https://forum.arduino.cc/index.php?topic=157817.15)
Schema electrică a conectivității ecranului LCD cu placa Arduino este prezentată în figura 14. Această conectivitate se realizează după cum urmează [12]:
Pinul 1 VSS (ground) conectat la pinul de masă GND al plăcii Arduino.
Pinul 2 VDD (power connection) conectat la pinul +5V al plăcii Arduino.
Pinul 3 VE (contrast voltage) conectat la pinul de ieșire al potențiometrului folosit la reglarea luminozității.
Pinul 4 RS (register select) conectat la pinul digital D4 al plăcii Arduino și comandat de microcontrolerul ATMega328.
Pinul 5 RW (read/write) conectat la pinul de masă GND al plăcii Arduino deoarece in cazul de față nu este necesară preluarea de valori din registrele interne.
Pinul 6 E (enable) conectat la pinul digital D5 al plăcii Arduino. Prin acest pin se preia semnalul de activare a circuitului intern și este comandat de microcontrolerul ATMega328.
Pinul 11 DB4 (data port) conectat la pinul digital D6 al plăcii Arduino. Acest pin este folosit ca port pe care sunt scrise date și comenzi.
Pinul 12 DB5 (data port) conectat la pinul digital D7 al plăcii Arduino. Acest pin este folosit ca port pe care sunt scrise date și comenzi.
Pinul 13 DB6 (data port) conectat la pinul digital D8 al plăcii Arduino. Acest pin este folosit ca port pe care sunt scrise date și comenzi.
Pinul 14 DB7 (data port) conectat la pinul digital D9 al plăcii Arduino. Acest pin este folosit ca port pe care sunt scrise date și comenzi.
Pinul 15 A (backlight anode) conectat la pinul +5V al plăcii Arduino. Acest pin este folosit pentru a alimenta cu tensiune anodul luminii de fundal. Tensiunea de referință pentru LED-urile albe este de 3,3 V și un curent maxim de 20 mA iar circuitul nostru este alimentat cu 5 V și un curent mai mare de 20 mA. Pentru a evita arderea LED-urilor de iluminare fundal pe traseul dintre cei doi pini am adăugat o rezistență de 200ohm. Ca urmare avem: I = [ 5V-3,3V ] / 200ohm = 0,0085A = 8,5mA iar LED-urile de iluminare fundal funcționează fără probleme.
Pinul 16 K (backlight cathode) conectat la pinul GND al plăcii Arduino. Acest pin este folosit pentru a conecta la masă catodul luminii de fundal.
Figura 14 Conexiunea dintre ecranul LCD-1602 și placa Arduino
Specificații [12]:
Tensiune de alimentare: 5V
Curent: 1.1mA
Tensiune de alimentare backlight: 4.2V
Curent backlight: <120mA
Pentru a putea regla luminozitatea ecranului am folosit un potențiometru semireglabil multitură 3296 prezentat în figura de mai jos.
Figura 15 Potențiometru multitură 3096
(sursa http://www.chipdip.ru/product/3296w-1-102/ )
Specificații:
Rezistență: 20kΩ
Număr de rotații: 30
2.1.8 Encoder Rotativ KY-040
Figura 16 Encoder Rotativ KY-040
Pentru a putea regla ora și data am folosit un encoder rotativ cu funcția push-button model KY-040 prezentat în figura 16.Acest encoder (codificator) rotativ are un număr fix de poziții pe rotație . Aceste poziții se simt foarte ușor ca și un fel de mici " click-uri " când se învârte butonul . Modulul Keyes care l-am ales, are 30 de astfel de poziții . Funcția push-button o voi folosi atât la reglarea datei și orei cât și la afișarea unui mesaj [13].
Figura 17 Encoder rotativ Schema bloc și construcție internă
Sursa (http://henrysbench.capnfatz.com/henrys-bench/arduino-sensors-and-input/keyes-ky-040-arduino-rotary-encoder-user-manual/)
Encoder-ul are trei pini pe o parte și anume A, B, C prezentați în figura 17. În interiorul encoder-ului există două comutatoare . Un comutator conectează pinul A la pinul C când butonul se învârte în sensul acelor de ceas, iar celălalt conectează pinul B la C când butonul se învârte în sens opus acelor de ceas .
Figura 18 Conexiunea între Encoder-ul KY-040 și placa Arduino.
Conexiunea cu placa Arduino prezentată în figura 18 se face după cum urmează [13]:
Pinul 1 GND conectat la pinul de masă GND al plăcii Arduino.
Pinul 2 + conectat la pinul de alimentare 5V al plăcii Arduino.
Pinul 3 SW conectat la pinul A0 al plăcii Arduino.
Pinul 4 DT conectat la pinul digital D3 al plăcii Arduino.
Pinul 5 CLK conectat la pinul digital D2 al plăcii Arduino.
2.1.9 Protocolul de comunicare I2C (Inter-Integrated Circuit)
Cum aminteam în rândurile de mai sus, senzorul AM2302 comunică cu microcontrolerul prin intermediul protocolului de comunicație seriala I2C. Pentru a putea discuta despre I2C trebuiesc amintite anumite particularități ale comunicației seriale în general.
Interfețele seriale transmit datele câte un bit o dată. Folosesc cel puțin un fir, dar nu mai mult de patru.
Figura 19 Exemplu de comunicație serial sincronă prin două fire
După cum este prezentat în figura 19 de mai sus, între cele două dispositive este realizată o comunicare de tip serial, dispozitivul din stânga fiind master, iar cel din dreapta fiind slave. Transmisia de date se face cu ajutorul a nu mai mult de două fire. Fiecare bit de informație este transmis atunci cand semnalul de ceas (CLK) este pe front ascendent. Un mare avantaj al acestui tip de transfer este numarul mic de pini/fire necesare pentru implementare, de aici și costuri scăzute. Totodată ca dezavantaj putem aminti viteza relativ mică.
Comunicația serială se împarte în două mari categorii, diferența fiind făcută de necesitatea unui semnal de ceas și implicit a unui fir in plus. Astfel deosebim interfața sincron și interfața asincron.
Liniile unei comunicații seriale sincronizate sunt întotdeauna împerecheate cu un semnal de ceas, astfel toate dispozitivele de pe o magistrală serial sincronizată împart un semnal de tact comun. Această abordare e mai directă comparativ cu cea asincronă, însă necesita un fir în plus între dispozitive. Interfețele serial sincrone includ SPI (“Serial Peripheral Interface”) și I2C.
Pentru comunicația serială asincronă este necesară efectuarea câtorva setări inițiale care trebuie să fie stabilite pe ambele dispozitive ce participă la comunicare, altfel apar diferite probleme. Aceste setări sunt:
Baud rate reprezintă viteza cu care informațiile sunt transmise. Se exprimă in biți pe secundă (bps). Cele mai întâlnite valori ale acestui parametru sunt: 1200, 2400, 4800, 9600, 19200, 38400, 57600 și 115200. Dintre aceste valori, cea mai des întâlnită și suficientă este 9600.
Data bits reprezintă informația transmisă de fiecare pachet. Poate fi setat între 5 și 9 biți. Standard se folosesc 8 biți, însă și alte mărimi pot avea utilizările lor.
Biți de sincronizare sunt 2 sau 3 biți transferați cu fiecare pachet de date. Aceștia sunt bitul de start și bitul(biții) de stop. Ei marchează începutul și sfârșitul unui pachet.
Biți de paritate reprezintă o metodă simplă de verificare împotriva erorilor. Poate fi par sau impar. Biții de date sunt numărați și în funcție de numărul rezultat, bitul se setează fie pe 1, fie pe 0. Dispozitivul ce primește pachetul, face aceeași operație.
Magistrala I2C se poate realiza în tehnologiile NMOS, CMOS sau bipolară. Este o magistrală serială, cu două fire (linii) care transportă informația între dispozitivele conectate. Cele două linii sunt SDA (Serial Data) și SCL (Serial Clock). Fiecare dispozitiv care este conectat la magistrală este identificat printr-o adresă unică (fie că este microcontroler, driver LCD, memorie sau interfață pentru tastatură) și poate funcționa ca transmițător sau ca receptor. Trebuie făcută precizarea că un driver LCD poate îndeplini doar funcția de receptor, în timp de o memorie poate fi transmițător (transmite date pe magistrală) sau receptor (primește date de pe magistrală) [14].
Un transmițător este definit ca un dispozitiv care trimite date spre magistrală iar un receptor este orice dispozitiv care primește date de pe magistrală. În completarea funcției de transmițător și receptor, dispozitivele pot fi de asemenea considerate ca master sau slave atunci când se realizează transfer de date. Prin definiție, un master este un dispozitiv care inițiază un transfer de date pe magistrală, generează semnalele de clock pentru a face posibil acest transfer și tot el încheie transferul. În acel moment, orice dispozitiv adresat va fi considerat slave. Magistrala I2C are o structură de tip multi-master. Aceasta înseamnă că orice dispozitiv care este capabil să controleze magistrala poate fi conectat la aceasta, fără a produce alterarea datelor vehiculate.
Protocolul de transfer al datelor pe magistrala I2C prezentat în figura 20 presupune inițierea transferului prin aducerea magistralei într-o condiție de START, transferul propriu-zis și încheierea transferului prin aducerea magistralei într-o condiție de STOP.
Figura 20 Protocolul de transfer al datelor pe magistrala I2C
Condiția de START (S) este definită prin trecerea liniei SDA din 1 în 0, în timp ce linia SCL este menținută la nivel ridicat. Condiția de STOP (P) este definită prin trecerea liniei SDA din 0 în 1, în timp ce linia SCL este menținută la nivel ridicat. Ambele condiții sunt generate întotdeauna de către coordonator [14].
2.1.10 Protocolul de comunicare SPI (“Serial Peripheral Interface”)
SPI este o modalitate de a comunica cu dispozitive de tipul master-slave. Un dispozitiv este master (de obicei Arduino), si celelalte dispozitive sunt slave. În practică, se găsesc de obicei librării scrise de altcineva care încapsulează deja comunicarea dispozitivelor prin protocolul SPI. Voi prezenta mai jos câteva elemente ale SPI. Comunicarea SPI se face folosind patru canale (fire de conexiune) :
MISO – firul prin care dispozitivele slave trimit date catre master.
MOSI – firul prin care dispozitivul master trimite date catre slave.
SCK – firul prin catre este transmis clock-ul (ritmul de comunicatie)
SS (Slave Select) – acest canal este specific SPI, și este interesant. SPI permite conectarea pe aceeași magistrală a mai multor dispozitive, fiecare dispozitiv având atașat un canal Slave Select. Atunci când valoarea din acest canal este LOW, dispozitivul slave comunică cu master-ul. Când valoarea Slave Select este HIGH, atunci dispozitivul ignoră comunicarea SPI. În acest mod, se pot conecta pe același canal SPI oricât de multe dispozitive, cu condiția ca la fiecare dispozitiv să se atașeze un canal Slave Select. În cazul Arduino UNO, pinii Arduino SPI sunt MISO – pinul digital 12, MOSI – pinul digital 11, SCK – pinul digital 13. Pinul default SS este pinul digital 10. În cazul în care există mai mult de un dispozitiv SPI, se folosesc mai mulți pini Slave Select, nu doar pinul digital 10, fiecare dispozitiv fiind conectat cu cate un pin Slave Select distinct.
La modul concret, dacă există două dispozitive SPI, se începe prin a identifica pinii MOSI, MISO, SCK si SS pentru fiecare dispozitiv. Se conectează apoi împreună pinii MOSI ai celor două dispozitive, și împreună cu pinul Arduino MOSI, la fel și pentru MISO si SCK. Pentru pinii SS, se conectează pinul primului dispozitiv la un pin digital Arduino, iar pinul celui de-al doilea dispozitiv la un alt pin digital Arduino [15].
3. ASAMBLAREA DISPOZITIVULUI MiniStațieMeteo
3.1 Schema Bloc.
Având baza protipului formată din placa de dezvoltare Arduino Uno, senzorul de temperatură și umiditate AM2302, modulul SD, modulul ZS-042, ecranul LCD 1602 și encoderul, am trecut la asamblarea dispozitivului. Ca să am o imagine clară a dispozitivului MiniStațieMeteo ce urma să-l asamblez am creat Schema Bloc prezentată in figura 21 cu ajutorul programului EAGLE Professional.
Figura 21 Schema Bloc a dispozitivului MiniStațiMeteo
Inițial am vrut să folosesc la asamblarea dispozitivului o placă breadboard dar am renunțat la idee din motive practice și estetice. Ca urmare am trecut la imprimarea unui cablaj care să interconecteze toate componentele dispozitivului MiniStațieMeteo. Construcția acestui cablaj va fi descrisă in capitolul 4. După ce am interconectat toate componentele cu cablajul imprimat a fost nevoie de alimentarea dispozitivului. Curentul maxim furnizat de portul USB al calculatorului fiind de 500 mA,un pic prea puțin pentru necesitățile dispozitivului ținând cont de faptul că numai ecranul LCD care este iluminat tot timpul are nevoie de 160 mA și de faptul că dispozitivul în timpul testelor se reseta frecvent . Din aceste motive a fost nevoie de un alimentator extern. Acest alimentator extern are o tensiune de ieșire reglabilă între 3 si 12 V si oferă un curent de 1500 mA .
3.2 Programarea microcontrolerului
După cum am precizat în capitolul 2.1.3 pentru programarea microcontrolerului AtMega328 folosim mediul de dezvoltare Ardino IDE. În prezent există foarte mulți producători de componente compatibile cu placa Arduino Uno iar mediul de dezvoltare Arduino IDE nu conține atât de multe biblioteci. Datorită acestui fapt și pentru a putea implementa diferite funcții de utilizare a senzorilor dispozitivului MiniStațieMeteo am inclus următoarele biblioteci:
DHT [16]
Encoder [17]
LiquidCrystal [18]
RTClib [19]
SD [20]
SPI [21]
Wire [22]
Programul pe care îl voi încărca pe microcontroler și care preia informațiile de la senzori, le afișează pe LCD și le scrie pe MicroSD card este detaliat în cele ce urmează .
Programul începe cu partea de declarații care include mai multe biblioteci, partea de definiri a pinilor de conectare și inițializarea constantei chip select și a pinului de conectare a modulului MicroSD.
// se folosesc urmatoarele librarii
#include <Wire.h> // pentru interfata i2c
#include "RTClib.h" // pentru ceas
#include <LiquidCrystal.h> // pentru afisajul alfanumeric
#include <Encoder.h> // pentru encoder
#include <SD.h> // pentru card
#include <SPI.h> // pentru interfata seriala a perifericelor
#include <DHT.h> // se foloseste libraria DHT
RTC_DS1307 RTC; // tip ceas de timp real compatibil cu DS3231
Encoder knob(3, 2); // conectare encoder (DT si CLK)
LiquidCrystal lcd(4, 5, 6, 7, 8, 9); // conectare afisaj la placa Arduino
const int chipSelect = 10; // pin ChipSelection al modulului SD
Instanțierea obiectelor de lucru cu senzorul de temperatură și umiditate AM2302 necesită următoarele declarații:
#define DHTPIN A2 // se defineste pinul la care se conecteaza senzorul de tip AM2302
#define DHTTYPE DHT22 // AM2302 este identic cu senzorul DHT 22
DHT dht(DHTPIN, DHTTYPE); // se defineste elementul dht (pin si tip)
Programul mai utilizează și următoarele variabile globale:
// variabile pentru retinere valori provizorii an, luna, zi, ora si minute
// pentru modificare din meniu
int setyeartemp;
int setmonthtemp;
int setdaytemp;
int sethourstemp;
int setminstemp;
int setsecs = 0;
int maxday; // numar maxim de zile intr-o anumita luna
// pentru scriere pe card
int yeartemp; // variabila ia valoarea anului
int monthtemp; // variabila ia valoarea lunii
int daytemp; // variabila ia valoarea zilei
int hourstemp; // variabila ia valoarea orei
int minstemp; // variabila ia valoarea minutelor
int sectemp; // variabila ia valoarea secundelor
int buttonstate = 0; // variabila pentru a sti daca un buton a fost apasat sau nu si scrise datele
int pushlengthset = 2000; // timp de apasare "lunga" in ms
int pushlength = pushlengthset; // variabila ia valoarea timpului de apasare "lung"
int pushstart = 0; // timpul de cand a fost apasat butonul
int pushstop = 0; // timpul cand a fost eliberat butonul
int knobval; // valoarea pentru determinare sens rotire encoder
boolean buttonflag = false; // valoare intiala a apasarii butonului
// de defineste un caracter personalizat pentru simbolul de "grad"
// dupa cum este prezentat la http://arduino.cc/en/Reference/LiquidCrystalCreateChar
byte grad[8] = {
B01100,
B10010,
B10010,
B01100,
B00000,
B00000,
B00000,
};
int h; // variabila intreaga pentru umiditate
float t; // variabila reala pentru temperatura
float t1; // variabila reala pozitiva pentru valoare temperatura
int ft; // variabila pentru a scrie header-ul in fisierul de pe card
int qiu=1; // variabila pentru a salva periodic pe card datele
int qium = 555; // valoare maxima a iteratiilor inainte de a scrie pe card
// pentru valoarea de 3333 se scrie din minut in minut
În cadrul secțiunii setup se inițializează:
comunicația serială la viteza de 9600 de biți pe secundă,
comunicația I2C,
modulul RTC DS3231,
senzorul AM2302,
ecranul LCD cu specificația numărului de 16 linii și 2 coloane,
modulul MicroSD
encoderul
void setup () { // incepe partea de setari
Serial.begin(9600); // se initializeaza ecranul de monitorizare seriala
Wire.begin(); // se initializeaza comunicatia i2c
RTC.begin(); // se initializeaza modulul de ceas
dht.begin(); // initializare senzor DHT
lcd.begin(16,2); // se initializeaza afisajul LCD cu 16 coloane si 2 randuri
lcd.createChar(0, grad); // se creaza simbolul "grad"
lcd.clear(); // se sterge ecranul
pinMode(A0,INPUT); // butonul encoderului se conecteaza la pinul A0
digitalWrite(A0,HIGH); // pinul A0 se conecteaza intern prin rezistenta la +5V
if (! RTC.isrunning()) { // daca ceasul nu este functional
RTC.adjust(DateTime(__DATE__, __TIME__)); // ia data si ora de la calculator
}
Totodată la inițializarea programului pe ecranul LCD apare mesajul “Proiect realizat de Liviu Ciont MiniStatieMeteo data logger v.06F ”. După acest mesaj apare următorul legat de inițializarea cardului microSD “Se inițializează cardul.. card ok” sau dacă, cardul este defect ori nu este prezent “Se inițializează cardul.. card defect sau lipsă”.
// afisare mesaje de intampinare
lcd.setCursor(0, 0); // pozitionare cursor in coltul din stanga, sus
lcd.print("proiect realizat"); // se scrie textul dintre ghilimele
lcd.setCursor(1, 1); // pozitionare cursor pe coloana 1 si randul 1 (a doua coloana de jos)
lcd.print("de Liviu Ciont"); // se scrie textul dintre ghilimele
delay (4500); // se asteapta 2,5 secunde
lcd.clear(); // se sterge ecranul
lcd.setCursor(0, 0);
lcd.print("MiniStatieMeteo");
lcd.setCursor(0, 1);
lcd.print("versiunea 0.6F");
delay (4500);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("scriere date pe");
lcd.setCursor(2, 1);
lcd.print("card microSD");
delay (4500);
lcd.clear();
// initializare card
Serial.println("Se initializeaza cardul…"); // se afiseaza pe ecranul de monitorizare un text
pinMode(10, OUTPUT); // se defineste pinul chipSelect ca iesire
if (!SD.begin(10)) { // se verifica daca este card SD in inscriptor
Serial.println("Card defect sau nu exista..");
lcd.setCursor(2, 0);
lcd.print("card defect");
lcd.setCursor(2, 1);
lcd.print("sau lipsa..");
delay(1000);
return;
}
Serial.println("Card initializat.."); // daca e totul in regula confirma printr-un mesaj
lcd.setCursor(2, 0);
lcd.print("card ok !");
delay(1000);
lcd.clear();
ft=1; //variabila pt header-ul din fisier
} // aici se termina partea de testare
În secțiunea loop se realizează citirea senzorilor, afișarea valorilor citite pe ecranul LCD și salvarea acestora pe cardul microSD.
void loop () { // incepe programul principal
qiu = qiu + 1; // se incrementreaza variabila pentru scriere date pe card
t = dht.readTemperature(); // se citeste valoarea temperaturii
lcd.setCursor(9, 0); // cursorul se pozitioneaza pe coloana a 9-a pe randul de sus
if (t < 0) // daca temperatura este negativa
{t1=-t;} // se schimba semnul
else t1=t; // se foloseste o alta variabila, doar pentru valoarea efectiva, fara semn
if ( t1 < 10) // daca valoarea temperaturii este unitara
{
lcd.print(" "); // pun un spatiu in loc de cifra zecilor
}
if (t>0) lcd.print("+"); // daca temperatura este pozitiva, scrie semnul +
if (t==0) lcd.print(" "); // daca temperatura este exact 0 gr. Celsius, nu pune niciun semn
if (t<0) lcd.print("-"); // daca temperatura este negativa, scrie semnul –
lcd.print(t1,1); // afiseaza valoarea temperaturii cu o cifra dupa virgula
lcd.write(byte(0)); // afiseaza semnul de "grad"
lcd.print("C"); // scrie litera "C"
h = dht.readHumidity(); // se citeste valoarea umiditatii
lcd.setCursor(11, 1); // se pozitioneaza cursorul pe coloana a 11-a si randul de jos
if (h < 10) // daca valoarea umiditatii este unitara
{
lcd.print(" "); // pun eun spatiu in loc de cifra zecilor
}
lcd.print(h); // se afiseaza valoarea intreaga a umiditatii
lcd.print("%um"); // se afiseaza unitatea de masura
DateTime now = RTC.now(); // se citeste data de la ceas
lcd.setCursor (0,1); // se pozitioneaza cursorul in coltul din stanga, jos
lcd.print(now.day(), DEC); // se afiseaza ziua
lcd.print('.'); // se afiseaza "/"
lcd.print(now.month()); // se afiseaza luna
lcd.print('.'); // se afiseaza "/"
lcd.print(now.year(), DEC); // se afiseaza anul
lcd.print(" "); // se pun un spatiu liber
lcd.setCursor (0,0); // se pozitioneaza cursorul in coltul din stanga, jos
lcd.print(now.hour(), DEC); // se afiseaza ora
lcd.print(':'); // se afiseaza ":"
if (now.minute() <10) // daca minutele sunt unitare (doar dintr-o cifra)
{
lcd.print("0"); // se afiseaza un "0"
}
lcd.print(now.minute(), DEC); // se afiseaza minutele
lcd.print(':'); // se afiseaza ":"
if (now.second() <10) // daca secundele sunt unitare
{
lcd.print("0"); // se afiseaza un "0"
}
lcd.print(now.second()); // se afiseaza secundele
lcd.print(" "); // afisez un spatiu, pentru stergere eventuale date eronate
pushlength = pushlengthset; // variabila ia valoarea reglata
pushlength = getpushlength (); // se citeste timpul de apasare
delay (10); // scurta intarziere de 10ms
if (pushlength < pushlengthset) // daca butonul se apasa scurt
{
ShortPush (); // se apeleaza subrutina
}
if (pushlength > pushlengthset) // daca se apasa lung butonul
{
lcd.clear(); // se sterge ecranul
DateTime now = RTC.now(); // se citeste data si ora din ceas
setyeartemp=now.year(),DEC; // variabila ia valoarea anului
setmonthtemp=now.month(),DEC; // variabila ia valoarea lunii
setdaytemp=now.day(),DEC; // variabila ia valoarea zilei
sethourstemp=now.hour(),DEC; // variabila ia valoarea orei
setminstemp=now.minute(),DEC; // variabila ia valoarea minutelor
setclock(); // se apeleaza subrutina de reglaj
pushlength = pushlengthset; // variabila ia valoarea programata
};
Datele vor fi salvate pe cardul de memorie într-un fișier de tip .txt sub forma “data,ora,temperatura,umiditatea”. Datele stocate sunt suficient de mici ca dimensiune astfel încât pe un card de memorie de 2GB se pot stoca informațiile pentru perioade de câțiva ani.
// partea de scriere pe card in fisier txt
if (qiu > qium) // daca numarul iteratiilor este mai mare decat valoarea impusa
{
if (SD.exists("liviu.txt")) { //daca fisierul exista pe card
ft = 0; //comuta variabila ft pe 0
}
else {
ft=1;
}
DateTime now = RTC.now(); // se citeste data si ora din ceas
yeartemp=now.year(),DEC; // variabila ia valoarea anului
monthtemp=now.month(),DEC; // variabila ia valoarea lunii
daytemp=now.day(),DEC; // variabila ia valoarea zilei
hourstemp=now.hour(),DEC; // variabila ia valoarea orei
minstemp=now.minute(),DEC; // variabila ia valoarea minutelor
sectemp=now.second(),DEC;
File dataFile = SD.open("liviu.txt", FILE_WRITE); // pregatesc de scriere fisierul
if (ft == 1) { //daca ft=1
dataFile.print("DATE,HOUR,TEMP_C,HUMIDITY"); //scriu in fisier heade-rul
dataFile.println(); //sar la urmatorul rand
ft = 0; //opresc scrierea header-ului
}
if (dataFile) { // daca fisierul se deschide
lcd.setCursor(10, 1); // mut cursorul pe coloana nr.10 si randul de jos
lcd.print("*"); // afisez caracterul "*", pentru a stii cand se scrie pe card
Serial.print(String(daytemp)); // scrie pe ecranul serial ziua
dataFile.print(String(daytemp)); // scrie pe card ziua
delay(30); // mica pauza
Serial.print("/"); // pune pe ecranul de monitorizare seriala "/"
dataFile.print("/"); // scrie pe card "/"
Serial.print(String(monthtemp)); // scrie pe ecranul serial luna
dataFile.print(String(monthtemp)); // scrie pe card luna
delay(30); // asteapta putin, 30ms
Serial.print("/"); // scrie pe ecranul serial "/"
dataFile.print("/"); // scrie pe card "/"
Serial.print(String(yeartemp)); // scrie pe ecranul de monitorizare seriala anul, ca sir de caracter, la fel ca pe card
dataFile.print(String(yeartemp)); // scrie in fisier-ul txt anul
delay(30); // se "odihneste" putin (30ms)
Serial.print(" – "); // scrie pe ecranul serial " – " pentru delimitare data de ora
dataFile.print(","); // scrie pe card "," pentru delimitare data de ora
Serial.print(String(hourstemp)); // scrie pe ecranul serial ora
dataFile.print(String(hourstemp)); // scrie pe card ora
delay(30); // mica pauza
Serial.print(":"); // pune pe ecranul serial ":"
dataFile.print(":"); // pune pe card ":" dupa valoare ora
if (minstemp <10) Serial.print("0"); // daca minutele sunt mai mici de 10 (doar dintr-o cifra) pune pe ecranul serial un "0"
if (minstemp <10) dataFile.print("0"); // daca minutelor sunt mai mici de 10 (doar dintr-o cifra) pune in fisier un "0"
Serial.print(String(minstemp)); // scrie minutele pe ecranul serial
dataFile.print(String(minstemp)); // scrie minutele in fisier
delay(30); // mica pauza
Serial.print(":"); // scrie in ecranul serial ":"
dataFile.print(":"); // scrie in fisier ":"
if (sectemp <10) Serial.print("0"); // daca secundele sunt mai mici de 10 (doar dintr-o cifra) pune pe ecranul serial un "0"
if (sectemp <10) dataFile.print("0"); // daca secundele sunt mai mici de 10 (doar dintr-o cifra) pune in fisier un "0"
Serial.print(String(sectemp)); // scrie secundele in ecranul serial
dataFile.print(String(sectemp)); // scrie secundele in fisier
delay(30); // mica pauza
Serial.print(","); // lasa un spatiu pe ecranul serial, pentru delimitare ora de temperatura
dataFile.print(","); // lasa un spatiu in fisier, pentru delimitare ora de temperatura
Serial.print("t="); // scrie pe ecranul serial "t="
if (t>0) dataFile.print("+"); // daca temperatura este pozitiva, scrie in fisier semnul +
if (t<0) dataFile.print("-"); // daca temperatura este negativa, scrie in fisier semnul –
if (t < 0) {t1=-t;} // daca temperatura este negativa, schimba semnul, pentru a lucra doar cu valori pozitive
if (t<0) Serial.print("-"); // daca temperatura este negativa scrie pe ecranul serial semnul –
int t21 = t1; // se extrage valoarea intreaga
int t22 = 10*t1 – 10*t21; // se extrage valoarea de dupa virgula
Serial.print(String(t21)); // scrie valoarea intreaga pe ecranul serial
dataFile.print(String(t21)); // scrie valoarea intreaga in fisier
delay(30); // asteapta putin
Serial.print("."); // scrie in ecranul serial punct
dataFile.print("."); // scrie in fisier punct
Serial.print(String(t21)); // scrie pe ecranul serial valoarea dupa virgula
dataFile.print(String(t21)); // scrie in fisier valoarea dupa virgula a temperaturii
delay(30); // asteapta putin
Serial.print("^C h="); // scrie pe ecranul serial unitatea de masura temperatura si simbol umiditate
dataFile.print(","); // scrie in fisier unitatea de masura temperatura si simbol umiditate
Serial.print(String(h)); // scrie pe ecranul serial umiditatea
dataFile.print(String(h)); // scrie in fisier valoarea umiditatii
delay(30); // asteapta putin
Serial.println("%"); // scrie pe ecran simbolul "%"
dataFile.print("%"); // scrie in fisier simbolul "%"
dataFile.println();
delay(30); // asteapta putin
dataFile.close(); // inchid fisierul txt
delay(30); // asteapta putin
lcd.setCursor(10, 1); // pozitioneaza cursorul pe coloana 10 si randul de jos
lcd.print(" "); // sterge caracterul ce indica scrierea
} // se inchide fisierul
else { // daca nu se poate deschide fisierul
Serial.println("error opening fisier.txt");
lcd.setCursor(10, 1);
lcd.print("!");
delay(200);
lcd.setCursor(10, 1);
lcd.print(" ");
}
qiu = 0; // se reinitializeaza variabila pentru iteratii
} // aici se termina bucla pentru scriere pe card
} // aici se termina programul principal
// reglaj ceas
void setclock (){
setyear (); // se apeleaza subrutina de reglaj an
lcd.clear (); // se sterge ecranul
setmonth (); // se apeleaza subrutina de reglaj luni
lcd.clear (); // se sterge ecranul
setday (); // se apeleaza subrutina de reglaj ziua
lcd.clear (); // se sterge ecranul
sethours (); // se apeleaza subrutina de reglaj ora
lcd.clear (); // se sterge ecranul
setmins (); // se apeleaza subrutina de reglaj minute
lcd.clear(); // se sterge ecranul
// se actualizeaza data si ora
RTC.adjust(DateTime(setyeartemp,setmonthtemp,setdaytemp,sethourstemp,setminstemp,setsecs));
delay (1000);
}
// subrutina pentru a afla cat de lung se apasa butonul encoderului
int getpushlength () {
buttonstate = digitalRead(A0); // se citeste starea intrarii
if(buttonstate == LOW && buttonflag==false) // daca butonul este apasat si nu a mai fost verificat
{
pushstart = millis(); // se retine valoarea timpului cand se apasa
buttonflag = true; // se retine ca s-a verificat
};
if (buttonstate == HIGH && buttonflag==true)
{
pushstop = millis (); // se retine valoarea timpului cand se elibereaza butonul
pushlength = pushstop – pushstart; // se calculeaza timpul cat butonul a fost apasat
buttonflag = false; // se initializeaza verificarea ca nefacuta
};
return pushlength; // se returneaza valoarea timpului de apasare a butonului
}
int setyear () { // subrutina pentru reglaj an
lcd.setCursor (0,0); // se pozitioneaza cursorul in stanga, sus
lcd.print ("Reglaj an.."); // se afiseaza mesaj
pushlength = pushlengthset; // variabila ia valoarea programata
pushlength = getpushlength (); // se citeste timpul cat se apasa butonul
if (pushlength != pushlengthset) // daca s-a apasat butonul
{
return setyeartemp; // se returneaza valoarea anului
}
lcd.setCursor (0,1); // se pozitioneaza cursorul in stanga, jos
knob.write(0); // se considera cursorul in repaus
delay (50); // se asteapta putin
knobval=knob.read(); // se citeste starea encoderului
if (knobval < -1) // daca a fost rotit in sens trigonometric
{
knobval = – 1; // variabila knobval ia valoarea -1
}
if (knobval > 1) // daca a fost rotit in sensul acelor de ceasornic
{
knobval = 1; // variabila knobval ia valoarea +1
}
setyeartemp=setyeartemp + knobval; // variabila temporara pentru an scade sau creste, functie de sensul de rotire
if (setyeartemp < 2015) // daca variabila este mai mica decat 2015 (anul curent)
{
setyeartemp = 2015; // se impune ca valoare minima anul curent
}
lcd.print (setyeartemp); // se afiseaza valoarea temporara a anului
lcd.print(" "); // se pun 2 spatii libere
setyear(); // se revine in subrutina
} // se termina bucla subrutinei de reglaj an
int setmonth () { // subrutina pentru reglaj luna
lcd.setCursor (0,0); // se pozitioneaza cursorul in stanga, sus
lcd.print ("Reglaj luna.."); // se afiseaza un mesaj
pushlength = pushlengthset; //
pushlength = getpushlength (); // se masoara timpii de apasare sau eliberare
if (pushlength != pushlengthset) // se determina daca a fost sau nu apasat butonul
{
return setmonthtemp; // daca a fost apasat butonul, se iese din subrutina si se transmite si valoarea lunii
}
lcd.setCursor (0,1);
knob.write(0); // se considera ca encoderul este in repaus
delay (50); // se astepta un pic
knobval=knob.read(); // se determina sensul de rotire al encoderului
if (knobval < -1) // daca se roteste in sens trigonometric
{
knobval = -1; // variabila ia valoarea -1
}
if (knobval > 1) // daca se roteste in sensul acelor de ceasorinic
{
knobval = 1; // variabila ia valoarea +1
}
setmonthtemp=setmonthtemp + knobval; // variabila lunii screste sau scade functie de rotirea encoderului
if (setmonthtemp < 1) { // daca numarul lunii e mai mic de 1
setmonthtemp = 1; // se impune valoare minima 1
}
if (setmonthtemp > 12) { // daca numarul lunii e mai mare de 12
setmonthtemp=12; // se impune valoare maxima 12
}
lcd.print (setmonthtemp); // se afiseaza pe ecran lcd numarul lunii
lcd.print(" ");
setmonth(); // se revine in subrutina, pentru a afla daca encoderul se roteste
} // se termina bucla subrutinei de reglaj luna
int setday () { // subrutina pentru reglaj zi
if (setmonthtemp == 4 || setmonthtemp == 5 || setmonthtemp == 9 || setmonthtemp == 11) {
maxday = 30; // aprilie, iunie, septembrie si noiembrie au 30 zile
}
else {
maxday = 31; //… celelalte luni au 30 zile
}
if (setmonthtemp ==2 && setyeartemp % 4 ==0) { //… cu exceptia lunii februarie, care are 28 zile sau 29 zile, in anii bisecti
maxday = 29; // an bisesct (se imparte fara rest la 4)
}
if (setmonthtemp ==2 && setyeartemp % 4 !=0) { // ani nebisescti
maxday = 28;
}
lcd.setCursor (0,0); // se pozitioneaza cursorul in coltul din stanga, sus
lcd.print ("Reglaj zi.."); // se afiseaza un mesaj ca e reglajul zilelor
pushlength = pushlengthset; // i se da variabilei valoarea initiala
pushlength = getpushlength (); // se determina daca a fost apasat butonul
if (pushlength != pushlengthset) { // daca a fost apasat butonul de pe encoder
return setdaytemp; // se revine in programul principal, retinand valoarea zilelor
}
lcd.setCursor (0,1); // se pozitioneaza cursorul in coltul din stanga, jos
knob.write(0); // se considera ca encoderul este in repaus
delay (50); // se asteapta putin
knobval=knob.read(); // se citeste encoderul
if (knobval < -1) { // daca se roteste in sens trigonometric
knobval = -1; // variabila ia valoarea -1
}
if (knobval > 1) { // daca encoderul se roteste in sensul acelor de ceasornic
knobval = 1; // variabila ia valoarea +1
}
setdaytemp=setdaytemp+ knobval; // variabila scade sau creste functie de sensul de rotire al encoder-ului
if (setdaytemp < 1) { // daca ziua e mai mica ca 1
setdaytemp = 1; // se impune sa fie +1
}
if (setdaytemp > maxday) { // daca ziua e mai mare ca numarul maxim din luna respectiva
setdaytemp = maxday; // se impune valoarea corecta
}
lcd.print (setdaytemp); // se scrie pe ecran ziua reglata
lcd.print(" ");
setday(); // se revine in subrutina pentru reglaj zi, pana se apasa butonul
} // se termina bucla subrutinei de reglaj zi
int sethours () { // subrutina de reglaj ore
lcd.setCursor (0,0); // se pozitioneaza cursorul in coltul din stanga, sus
lcd.print ("Reglaj ora.."); // se scrie pe ecran un mesaj ca se regleaza ora
pushlength = pushlengthset; // variabila ia valoarea reglata initial
pushlength = getpushlength (); // se determina daca butonul a fost apasat
if (pushlength != pushlengthset) { // daca butonul a fost apasat
return sethourstemp; // se intoarce in programul principal, retinand valoarea orei
}
lcd.setCursor (0,1); // se pozitioneaza cursorul in coltul din stanga, jos
knob.write(0); // se condiera ca encoderul e in repaus
delay (50); // se asteapta putin
knobval=knob.read(); // se citeste pozitia encoderului
if (knobval < -1) { // daca se roteste in sens trigonometric
knobval = -1; // variabila ia valoarea -1
}
if (knobval > 1) { // daca encoderul se roteste in sensul acelor de ceasornic
knobval = 1; // variabila ia valoarea +1
}
sethourstemp=sethourstemp + knobval; // variabila orei scade sau creste functie de sensul de rotire al encoderului
if (sethourstemp < 0) { // daca variabila orei e mai mica de 0
sethourstemp = 0; // se regleaza la minimul de 0
}
if (sethourstemp > 23) { // daca variabila orei e mai mare de 23
sethourstemp=23; // se impune ca maxim valoarea 23
}
lcd.print (sethourstemp); // se scrie pe ecran ora reglata
lcd.print(" ");
sethours(); // daca butonul nu a fost apasat, se reintoarce la reglaj ore
} // se termina bucla subrutinei de reglaj
int setmins () { // subrutina de reglaj ore
lcd.setCursor (0,0); // se pozitioneaza cursorul in stanga, sus
lcd.print ("Reglaj minute.."); // se scrie mesaj ca se regleaza minutele
pushlength = pushlengthset; // variabilei i se da valoarea impusa initial
pushlength = getpushlength (); // se determina daca butonul a fost apasat
if (pushlength != pushlengthset) { // daca butonul a fost apasat
return setminstemp; // se revine in programul initial, retinand valoarea reglata pentru minute
}
lcd.setCursor (0,1); // se pozitioneaza cursorul in coltul din stanga, jos
knob.write(0); // se considera ca encoderul e in repaus
delay (50); // se asteapta putin
knobval=knob.read(); // se determina daca encoderul este rotit
if (knobval < -1) { // daca se roteste in sens trigonometric
knobval = -1; // variabila ia valoarea -1
}
if (knobval > 1) { // daca encoderul se roteste in sensul acelor de ceasornic
knobval = 1; // variabila ia valoarea +1
}
setminstemp=setminstemp + knobval; // variabila minutelor scade sau creste functie de sensul de rotire
if (setminstemp < 0) { // daca variabila minutelor este mai mica de 0
setminstemp = 0; // se impune ca valoare minima 0
}
if (setminstemp > 59) { // daca variabila minutelor ia valoare mai mare de 59
setminstemp=59; // se impune sa fie maxim 59 minute
}
lcd.print (setminstemp); // se scrie pe ecran valoarea reglata
lcd.print(" ");
setmins(); // se reintoarce la reglajul minutelor, daca nu s-a apasat butonul
} // se termina bucla subrutinei de reglaj
// subrutina pentru apasare scurta a butonului
void ShortPush () {
lcd.clear(); // se sterge ecranul
lcd.setCursor (0,0); // se pozitioneaza cursorul in coltul din stanga, sus
lcd.print ("proiect realizat"); // se afiseaza un mesaj
lcd.setCursor (1,1); // se pozitioneaza cursorul pe coloana 1, de jos
lcd.print ("de Liviu Ciont"); // se afiseaza un mesaj
delay(2000); // timp de 2 secunde nu face nimic
lcd.clear(); // sterge ecranul
}
4. CONSTRUCȚIE ȘI TEHNOLOGIE
4.1 Imprimare cablaj
După cum am specificat în capitolul 3.1 din motive practice si estetice am trecut la imprimarea unui cablaj care să interconecteze toate componentele dispozitivului MiniStațieMeteo. Primul pas a fost crearea desenului cablajului. Deoarece schema bloc a fost creată cu programul Eagle Professional am folosit acest program în continuare la crearea cablajului. Mulțumită opțiunilor multiple pe care le oferă programul Eagle Professional, odată creată schema bloc, desenarea cablajului se face automat folosind opțiunea “Switch to board”. După ce s-a desenat cablajul l-am ”aranjat” pentru a se potrivi interconectarea pinilor cu placa Arduino. La sfârșitul acestor operațiuni am exportat fișierul în format .png “Portable Network Graphics”. Versiunea pregătită pentru a fi trimisă la imprimantă este prezentată în figura 22.
Figura 22 Cablaj-versiunea pentru tipărit
Fișierul l-am tipărit pe o hârtie cretată cu o densitate de 60-80g/mp.Tipărirea s-a făcut cu o imprimantă laser cu toner. Următorul pas a fost achiziționarea unui cablaj simplu placat cu cupru pe suport textolit. Am curățat și degresat acest cablaj simplu, am aplicat hârtia cretată tipărită și am presat-o cu fierul de călcat incălzit la o temperatură mai mare de 200 °C aproximativ 2 minute. Am lăsat-o să se răcească și am introdus-o în apă. După ce am curățat hârtia a rămas tonerul lipit de cupru. Am introdus cablajul imprimat în clorură ferică pentru corodare, l-am curățat și găurit cu un burghiu de mici dimensiuni în locurile unde vor fi introduși pinii. La sfârșit am aplicat pe traseu o soluție de sacâz dizolvat în alcool pentru a nu se oxida cuprul și astfel lipiturile se pot face și după mult timp.
Figura 23 Cablajul imprimat finalizat
Ultima parte a fost lipirea baretei de pini tată în locurile găurite pentru conectarea cu placa Arduino și pini mamă în locurile de conexiune a componentelor prezentate în Schema Bloc din figura 21. În figura 23 este prezentat cablajul imprimat folosit în acest proiect.
5. ELEMENTE DE PUNERE ÎN FUNCȚIUNE ȘI DEPANARE
5.1 Rezultate de implementare
În urma implementării hardware a tuturor componentelor a rezultat prototipul MiniStațieMeteo prezentat în figura de mai jos:
Figura 24 MiniStațieMeteo
Prototipul conține următoarele componente: 1 Arduino Uno, 2 Senzor AM2302, 3 Modul MicroSD, 4 Circuit imprimat, 5 Modul ZS-042 RTC, 6 Potențiometru multitură 3096, 7 Encoder, 8 Ecran LCD.
Partea software a proiectului a fost realizată înaintea celei hardware. Acest lucru a fost posibil datorită mediului de dezvoltare ArduinoIDE.
Odată cu finalizarea parții hardware, am finalizat și prototipul MiniStațieMeteo, care are următoarele caracteristici:
Raportează umiditatea și temperatura mediului ambiant
Raportează data și ora
Datele raportate sunt salvate pe un mediu de stocare de tip microSD card
Datorită implementării software de salvare periodică a datelor pe microSD într-un fișier cu extensia txt, am posibilitatea vizulizării variațiilor de temperatură și umiditate pe calculatorul personal cu ajutorul programului Microsoft Office Excel. Multumită functionalităților acestui program am creat un șablon (template) cu care creez grafice de vizualizare a datelor ori de câte ori este necesar. În continuare voi prezenta un grafic cu variațiile de temperatură și unul cu modificările gradului de umiditate.
Figura 25 Grafic variații tempeatură
Graficul din figura 25 precum și cel din figura 26 l-am realizat cu datele obținute pe parcursul testelor de fiabilitate a prototipului. După cum se observă în cele două grafice în data de 08.06.2016 la ora 07:32:54 există o scădere bruscă până la valoarea 0 a umidității și temperaturii iar după aproximativ un minut revenirea la valorile reale. Acest lucru se datorează testului negativ făcut cu senzorul AM2302. Mai exact, am deconectat senzorul de la prototip în timpul funcționării iar după un minut l-am reconectat.
Figura 26 Grafic grad umiditate
Cu acest test am verificat funcționalitatea programului în cazul defectării senzorului AM2302. Rezultatul este pozitiv.
5.2 Probleme întâmpinate
Hardware
La punerea în funcțiune am întalnit o problemă majoră. Ecranul LCD s-a aprins dar datele nu puteau fi afișate. După mici investigații am găsit in fișierul cu specificații al ecranului informații despre pinul DB0 (pinul 7). Conform acestor informații pe pinul DB0 LCD-ul nu primește instrucțiuni de cod gen ”funcții setare”, ”mutare cursor” etc.
Cablajul este proiectat ca pinul 7 (DB0) al LCD-ului să se conecteze la pinul D6 al plăcii Arduino. În general un cablaj imprimat greșit este considerat rebut iar imprimarea altuia nou presupune costuri suplimentare. Din acest motiv am preferat adaptarea actualului cablaj. Am observat că cel mai aproape pin care primește toate instrucțiunile de cod este pinul 11 DB4.
Așadar conform figurii 27 am anulat conexiunea pinului DB0 întrerupând traseul de cupru si am creat o conexiune noua intre pinul DB4 de la LCD cu placa Arduino, folosind un conductor de cupru cositorit.
Figura 27 Anulare conectare pin DB0 și conectare pin DB4
Software
O problemă majoră întâmpinată a fost accea a scrierii datelor în fișierul txt într-un format care să poată fi recunoscut de către programul Microsoft Office Excel. Voi prezenta doar secțiunea cu modificările. Implementarea la momentul respectiv era:
void loop () { // incepe programul principal
qiu = qiu + 1; // se incrementeaza variabila pentru scriere date pe card
if (qiu > qium) // daca numarul iteratiilor este mai mare decat valoarea impusa
{
DateTime now = RTC.now(); // se citeste data si ora din ceas
yeartemp=now.year(),DEC; // variabila ia valoarea anului
monthtemp=now.month(),DEC; // variabila ia valoarea lunii
daytemp=now.day(),DEC; // variabila ia valoarea zilei
hourstemp=now.hour(),DEC; // variabila ia valoarea orei
minstemp=now.minute(),DEC; // variabila ia valoarea minutelor
sectemp=now.second(),DEC;
File dataFile = SD.open("liviu.txt", FILE_WRITE); // pregatesc de scriere fisierul
if (dataFile) { // daca fisierul se deschide
Serial.print(String(yeartemp)); // scrie pe ecranul de monitorizare seriala anul, ca sir de caractere, la fel ca pe card
dataFile.print(String(yeartemp)); // scrie in fisier-ul txt anul
delay(30); // asteapta putin (30ms)
Serial.print("/"); // pune pe ecranul de monitorizare seriala "/"
dataFile.print("/"); // scrie pe card "/"
Serial.print(String(monthtemp)); // scrie pe ecranul serial luna
dataFile.print(String(monthtemp)); // scrie pe card luna
delay(30); // astepta putin, 30ms
Serial.print("/"); // scrie pe ecranul serial "/"
dataFile.print("/"); // scrie pe card "/"
Serial.print(String(daytemp)); // scrie pe ecranul serial ziua
dataFile.print(String(daytemp)); // scrie pe card ziua
delay(30); // mica pauza
Serial.print(" – "); // scrie pe ecranul serial " – " pentru delimitare data de ora
dataFile.print(" – "); // scrie pe card " – " pentru delimitare data de ora
Serial.print(String(hourstemp)); // scrie pe ecranul serial ora
dataFile.print(String(hourstemp)); // scrie pe card ora
delay(30); // mica pauza
Serial.print(":"); // pune pe ecranul serial ":"
dataFile.print(":"); // pune pe card ":" dupa valoare ora
if (minstemp <10) Serial.print("0"); // daca minutele sunt mai mici de 10 (doar dintr-o cifra) pune pe ecranul serial un "0"
if (minstemp <10) dataFile.print("0"); // daca minutelor sunt mai mici de 10 (doar dintr-o cifra) pune in fisier un "0"
Serial.print(String(minstemp)); // scrie minutele pe ecranul serial
dataFile.print(String(minstemp)); // scrie minutele in fisier
delay(30); // mica pauza
Serial.print(":"); // scrie in ecranul serial ":"
dataFile.print(":"); // scrie in fisier ":"
if (sectemp <10) Serial.print("0"); // daca secundele sunt mai mici de 10 (doar dintr-o cifra) pune pe ecranul serial un "0"
if (sectemp <10) dataFile.print("0"); // daca secundele sunt mai mici de 10 (doar dintr-o cifra) pune in fisier un "0"
Serial.print(String(sectemp)); // scrie secundele in ecranul serial
dataFile.print(String(sectemp)); // scrie secundele in fisier
delay(30); // mica pauza
Serial.print(" "); // lasa un spatiu pe ecranul serial, pentru delimitare ora de temperatura
dataFile.print(" "); // lasa un spatiu in fisier, pentru delimitare ora de temperatura
Serial.print("t="); // scrie pe ecranul serial "t="
dataFile.print("t="); // scrie in fisier "t="
if (t>0) dataFile.print("+"); // daca temperatura este pozitiva, scrie in fieiser semnul +
if (t<0) dataFile.print("-"); // daca temperatura este negativa, scrie in fisier semnul –
if (t < 0) {t1=-t;} // daca temperatura este negativa, schimba semnul, pentru a lucra doar cu valori pozitive
if (t<0) Serial.print("-"); // daca temperatura este negativa scrie pe ecranul serial semnul –
int t21 = t1; // se extrage valoarea intreaga
int t22 = 10*t1 – 10*t21; // se extrage valoare de dupa virgula
Serial.print(String(t21)); // scrie valoarea intreaga pe ecranul serial
dataFile.print(String(t21)); // scrie valoarea intreaga in fisier
delay(30); // asteapta putin
Serial.print(","); // scrie in ecranul serial virgula
dataFile.print(","); // scrie in fisier virgula
Serial.print(String(t21)); // scrie pe ecranul serial valoarea dupa virgula
dataFile.print(String(t21)); // scrie in fisier valoarea dupa virgula a temperaturii
delay(30); // asteapta putin
Serial.print("^C h="); // scrie pe ecranul serial unitatea de masura temperatura si simbol umiditate
dataFile.print("^C h="); // scrie in fisier unitatea de masura temperatura si simbol umiditate
Serial.print(String(h)); // scrie pe ecranul serial umiditatea
dataFile.print(String(h)); // scrie in fisier valoarea umiditatii
delay(30); // asteapta putin
Serial.println("%"); // scrie pe ecran simbolul "%"
dataFile.print("%"); // scrie in fisier simbolul "%"
delay(30); // asteapta putin
dataFile.close(); // inchid fisierul txt
delay(30); // asteapta putin
lcd.setCursor(10, 1); // pozitioneaza cursorul pe coloana 10 si randul de jos
lcd.print(" "); // sterge caracterul de indica scrierea
} // se inchide fisierul
else { // daca nu se poate deschide fisierul
Serial.println("error opening fisier.txt");
lcd.setCursor(10, 1);
lcd.print("!");
delay(200);
lcd.setCursor(10, 1);
lcd.print(" ");
}
qiu = 0; // se reinitializeaza variabila pentru iteratii
} // aici se termina bucla pentru scriere pe card
Problema implementării de mai sus era că date erau salvate pe un singur rând unele după altele sub forma: 2016/01/11 – 13:54:32 t=24,45^C h=41% 2016/01/11 – 13:54:32 t=24,45^C h=41%. Acesta fiind un inconvenient major deoarece la crearea graficelor cu programul Excel aș fi fost nevoit ca de fiecare dată când aș fi deschis fișierul txt cu programul Office Exel ar fi trebuit să-l formatez. După mai multe încercări am ajuns la concluzia că pentru a putea crea un grafic fără moficări ulterioare ale datelor din fișierul txt, trebuie în primul rând să am un cap de tabel, în al doilea rând ca după fiecare secvență de scriere să ”sar” la rândul următor. Partea în care se trece la rândul următor a fost simplu de implementat, apelând funcția dataFile.println()chiar înainte de închiderea buclei care conține secvența de scriere. Partea de introducere a capului de tabel a presupus următoarele: în partea de început a programului am declarat o variabilă ft (first time), în partea de inițializări se activează această variabilă, în programul principal se verifică dacă fișierul există pe microSD card iar variabila se dezactivează și continuă secvența de scriere, dacă nu, variabila fiind activă se crează fișierul, se introduce capul de tabel după care se dezactivează variabila și continuă secvența de scriere. Versiunea finală cu modificările făcute arată în felul următor:
#include <SD.h> // pentru card
int ft; // variabila folosita pentru a scrie header-ul in fisierul de pe card
void setup () { // incepe partea de setari
ft=1; //variabila pt header-ul din fisier
} // aici se termina partea de setari
void loop () { // incepe programul principal
if (SD.exists("liviu.txt")) { //daca fisierul exista pe card
ft = 0; //comuta variabila ft pe 0
}
else {
ft=1; //daca nu ramane activa
}
File dataFile = SD.open("liviu.txt", FILE_WRITE); // pregatesc de scriere fisierul
if (ft == 1) { //daca ft=1
dataFile.print("DATE,HOUR,TEMP_C,HUMIDITY"); //scriu in fisier header-ul
dataFile.println(); //sar la urmatorul rand
ft = 0; //opresc scrierea header-ului
}
if (dataFile) { // daca fisierul se deschide
|
|
|
dataFile.println(); // trece la randul urmator
delay(30); // asteapta putin
dataFile.close(); // inchid fisierul txt
} // se inchide fisierul
6. CONCLUZII
Lucrarea aplicată se referă la domeniul calculului ambiental. Pe parcursul lucrării am proiectat aplicația realizând cablajul imprimat, respectiv am dezvoltat partea de programare necesară aplicației. Am inserat în lucrare elemente de depanare și rezultate experimentale.
Aș mai putea adăuga că asamblarea și punerea în funcțiune a dispozitivului MiniStațieMeteo a fost dificilă dată fiind natura prototipului și lipsa mea de experiență.
Referitor la partea de software, lucrul cu Arduino s-a dovedit destul de ușor până la întâmpinarea unor probleme, care au fost depășite prin implementarea unor soluții alternative. În final, combinând atât partea de software cât și partea hardware, a rezultat un sistem capabil să monitorizeze în timp real umiditatea și temperatura dintr-un spațiu închis. Cu toate că este realizat la scară redusă, prototipul ar putea, cu mici modificări să conducă procese într-un spațiu extins.
Cu toate că este un sistem funcțional, ar putea suferi cel puțin câteva îmbunătățiri. Acestea ar putea fi:
Implementarea unui element de interconectare cu un aparat de control al temperaturii si umidității
Controlul de la distanță a dispozitivului prin internet
Crearea unei aplicații pentru dispozitive mobile, in vederea controlării de la distanță a sistemului
BIBLIOGRAFIE
[1] Radu PIETRARU, Alexandru VELICU:”Elemente practice de bază în dezvoltarea sistemelor cu microprocesoare integrate” Editura Techno Media, Sibiu , 2014
[2] Robofun.(2015). [Online]. http://www.robofun.ro/arduino/arduino_uno_v3
[3] Arduino. www.arduino.cc. [Online]. http://www.arduino.cc/en/Main/ArduinoBoardUno
[4] ATMEL. (2009) ATmega datasheet. PDF.
[5] ATMEL.(2009)www.atmel.com.[Online]. http://www.atmel.com/devices/atmega328p.aspx
[6] Sparkfun.[Online]. https://learn.sparkfun.com/tutorials/what-is-an-arduino
[7] Arduino.[Online].https://www.arduino.cc/en/Guide/Environment
[8] DHT22.(2006)[Online].http://machinedesign.com/news/sensor-sense-humidity-sensors
[9] AM2302. (2012)Digital+humidity+and+temperature+sensor+AM2302.pdf
[10] DS3231.(2014)DS3231 datasheet.pdf
[11] Modul MicroSD.[Online].http://www.arduitronics.com/product/210/microsd-card-adapter-v1-1-catalex
[12] LCD.(2009)1602 Datasheet.pdf
[13] Encoder.[Online].http://henrysbench.capnfatz.com/henrys-bench/arduino-sensors-and-input/keyes-ky-040-arduino-rotary-encoder-user-manual/
[14] I2C.[Online]. http://www.meo.etc.upt.ro/materii/cursuri/ISMT/5.pdf
[15] SPI.[Online]. http://andrei.clubcisco.ro/cursuri/3pm/lab6.pdf.
[16] Biblioteca.DHT.[Online]. https://github.com/adafruit/DHT-sensor-library
[17] Biblioteca.Encoder.[Online].https://www.pjrc.com/teensy/td_libs_Encoder.html
[18] Biblioteca.LiquidCrystal.[Online].https://github.com/adafruit/Adafruit_LiquidCrystal
[19] Biblioteca.RTClib.[Online] https://github.com/adafruit/RTClib
[20] Biblioteca.SD.[Online]. https://github.com/adafruit/SD
[21] Biblioteca.SPI.[Online]. https://github.com/PaulStoffregen/SPI
[22] Biblioteca.Wire.[Online]. https://github.com/codebendercc/arduino-library-files/tree/master/libraries/Wire
ANEXE
Foaie de catalog ATMEL ATMega 328P
Foaie de catalog AM2302
Foaie de catalog Am2302
Foaie de catalog AM2302
Foaie de catalog AM2302
Foaie de catalog AM2302
Foaie de catalog DS3231
Foaie de catalog LCD 1602
Foaie de catalog LCD 1602
Foaie de catalog LCD 1602
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: FUNDAȚIA PENTRU CULTURĂ ȘI ÎNVĂȚĂMÂNT IOAN SLAVICI TIMIȘOARA [306613] (ID: 306613)
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.
