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

Similar Posts