miercuri, 17 octombrie 2012

Mini-Instalaţie de picurare pentru plante (DIY)

Motivaţia
Anul acesta am avut o surpriză neplăcută la întoarcerea din concediu când mi-am găsit plantele fie uscate, fie foarte ofilite. Doar cactusul meu stătea semeţ, de parcă n-aş fi lipsit deloc. În ciuda încercărilor mele de a uda foarte bine (aproape îneca) plantele înainte de plecarea în concediu, fără ca cineva să le ude tot la câteva zile, plantele au avut de suferit.
Ideea
Un coleg de muncă mi-a povestit cum a rezolvat el problema udării florilor. Era vorba de o instalaţie ce presupunea un microcontroller, o pompă şi câţiva senzori. Am stat puţin pe gânduri şi apoi am decis să încerc ceva mai simplu. Ca de obicei am căutat muza pe internet, şi am găsit o mulţime de soluţii. Am ales ce mi s-a părut mai simplu de făcut şi mai ieftin, şi anume o micro-instalaţie cu picurare pentru plante.
Cele trebuincioase
  • 3 metri de furtun
  • 12 Te-uri
  • 17 coturi
  • o sticlă de 5 litri
Am găsit de vânzareun kit de irigaţie pentru plante de apartament, dar m-i s-a părut cam scump aşa că am improvizat. Am mers la un magazin cu produse pentru animale, care vindea şi accesorii pentru acvarii, şi am luat câţiva metri de furtun, împreună cu câteva fiting-uri de plastic. Partea bună la toate astea e că am ieşit în final ceva mai ieftin decât dacă aş fi cumpărat setul de irigare pentru apartament.
Pe lângă asta am putut să reglez debitul de apă ce merge la fiecare plantă individual, folosindu-mă de robinetele cu care erau dotate coturile de plastic.
Realizare
Mai întâi am grupat florile pe care vroiam să le ud cât mai aproape unele de altele. Apoi am tăiat furtunul  şi am început să conectez fitingurile de plastic.
După ce întreaga "ţevăraie" a fost gata, am luat capătul furtunului şi l-am introdus în sticla de 5 litri umplută cu apă.
Sticla am aşezat-o ceva mai sus decât ghivecele cu flori, pentru a mă putea folosi de principiul vaselor comunicante.
Principiul vaselor comunicante
Pe scurt, acest principiu spune că dacă avem două (sau mai multe) vase legate între ele de un canal, prin care lichidul poate circula în ambele direcţii, atunci nivelul din cele două vase va fi aceelaşi faţă de un reper extern. Deci, dacă nivelul apei din recipientul B e mai mare decât cel din recipientul A, atunci apa va circula din recipientul B în A, până când apa din cele două recipiente va avea aceelaşi nivel.
Astfel, dacă vasul în care ese apa se află deasupra ghivecelor, apa va curge în continuu, dinspre vasul cu apă spre ghivece, "încercând" să egalizeze nivelul de apă. Asta nu o să se întample, aşa că până aici am rezolvat partea cu obţinerea unui debit constant de apă.
În continuare, a trebuit să montez în dreptul fiecărui ghiveci câte un robinet pentru reglarea debitului de apă. Fiecare plantă are nevoide de o anumită cantitate de apă, astfel debitul de apă trebuie "personalizat". Unele plante, cum ar fi busuiocul, au nevoie de mai multă apă, iar altele de mai puţină. Pentru asta e montat în dreptul fiecărui furtun ce ajunge la ghivece câte un robinet. După mai multe încercări am ales să reglez robinetele astfel încât o picătură de apă să cadă tot la 4-5 secunde pentru busuioc, iar pentru flori ceva mai rar.
Am într-un ghiveci dreptunghiular (jardinieră) mai multe fire de busuioc, iar pentru a reuşi să ud o suprafaţă mai mare am folosit trei puncte de picurare. Din păcate nu se văd toate robinetele din poză.
Avantaje
  • plantele nu mai suferă de sete când eşti plecat mai multe zile
  • nu trebuie să le uzi zilnic
  • poţi regla debitul de apă pentru fiecar plantă în parte
  • poţi dizolva în rezervorul de apă eventualul îngraşamânt pentru plante
  • poţi conecta mai multe rezervoare laolaltă, astfel ca plantele să fie independente mai mult timp
Dezavantaje
  • instalaţia va picura în continuu, astfel că unele plante pot avea de suferit din cauza asta dacă nu reglezi atent debitul de apă
  • toate ghivecele care sunt irigate trebuie să fie apropiate unele de altele
Din punctul meu de vedere, dacă nu-ţi face plăcere să uzi florile în fiecare dimineaţă atunci o astfel de instalaţie te poate ajuta foarte mult. În rest, e foarte utilă dacă pleci în concediu pe mai mult de 10 zile.

duminică, 22 aprilie 2012

Panou Termic Solar DIY - Partea III (Software)

Comanda pompei - partea software

În acest articol voi prezenta în detaliu algoritmul din spatele circuitului de comandă şi realizarea programului software.
O să încep prin a enumera cerinţele iniţiale:
  • Să măsoare şi să afişeze temperaturile din panou şi din bazin.
  • Să ofere posibilitatea reglării temperaturii de prag pentru panou şi a diferenţei de temperatură dintre panou şi bazin.
  • Să comande releul ce alimentează pompa atunci când temperatura din panou e mai mare decât temperatura de prag şi mai mare decât temperatura din bazin.
  • Să permită controlul atât automat cât şi manual al pompei.
Pe lângă aceste cerinţe iniţiale s-au mai adăugat:
  • Afişarea orei în format [oră : minute].
  • Afişarea datei în format [zi / lună / an].
  • Reglarea orei şi a datei.
  • Salvarea temperaturii minime şi maxime din panou, alături de oră şi dată.
  • Salvarea datelor şi a setărilor în cazul penelor de curent.
  • Indicator  luminos pentru avarie şi afişarea unui mesaj de eroare.
  • Controlul pompei cu histereză.
În ochii unui programator cerinţele astea se transformă în următoarele funcţionalităţi:
  1. Controlul ecranului cu actualizarea ciclică a datelor afişate.
  2. Maşină de stări internă pentru meniul afişat. 
  3. Scanarea ciclică a tastaturii.
  4. Monitorizarea temperaturii şi comunicarea prin OWP cu senzorii. 
  5. Actualizarea ore şi a datei.
  6. Monitorizarea tensiunii de 12V şi detectarea unei căderi de tensiune
  7. Scrierea şi citirea datelor în şi din EEPROM, cu validare prin CRC.
  8. Detectarea şi administrarea erorilor.
  9. Controlul releului pentru pompă.
Cu alte cuvinte programul trebuie să permită citirea şi procesarea informaţiilor de la senzori în timp ce ceasul merge şi utilizatorul manipulează tastatura, respectiv manipulează datele afişate pe ecran. Ar trebui ca microcontroller-ul să facă aparent mai multe lucruri în paralel. Microprocesorul folosit de mine poate executa instrucţiuni doar secvenţial. Asta înseamnă că a trebuit să găsesc o metodă de a împărţi şi de a amesteca operaţiile pe care trebuie să le execute controller-ul astfel încât să dea impresia că face mai multe lucruri în paralel.
Ce înseamnă execuţia de operaţii în paralel?
O să încep cu un exemplu. Să zicem că avem un senzor de temperatură DS18S20 şi vrem să afişăm temperatura pe un LCD, dar vrem ca temperatura afişată să pâlpâie de 2 ori pe secundă. Pentru a putea face asta trebuie să reactualizăm textul afişat pe ecran tot la 250 ms. Mai exact, va trebui făcută secvenţa următoare:
  1. Afişez textul (ce conţine temperatura)
  2. Aştept 250 ms
  3. Şterg textul (afişez " " pe tot ecranul)
  4. Aştept 250 ms
  5. Afişez din nou textul
  6. Aştept 250 ms
  7. Şterg din nou textul
  8. Aştept 250 ms
  9. Sar înapoi la pasul 1
Dacă adunăm timpul de aşteptare vom obţine exact o secundă (250 ms + 250 ms + 250 ms + 250 ms = 1 sec), iar în acea secundă textul a fost afişat de două ori, exact cum am vrut.
Comunicarea cu senzorul DS18S20 se face prin protocolul 1Wire, şi presupune transmiterea, respectiv recepţia unui număr de biţi, iar timpul de conversie pentru senzorul DS18S20 e de aproximativ 700 ms. Astfel vom avea temperatura actualizată tot la 700 ms şi ceva. Problem care trebuie rezolvată în acest moment e cum putem face transmiterea comenzilor pentru ecran, în aceelaşi timp cu transmiterea comenzilor pentru senzor şi respectiv recepţia datelor de la senzor? Una din soluţii e aceea de a folosi o maşină de stări.
Ce este o maşină de stări?
Eu aş zice că e un mecanism care controlează ordinea în care se execută o colecţie de stări. Folosirea într-o funcţie a unei maşini de stări presupune structurarea funcţiei respective în stări. Fiecare stare trebuie să reprezinte o anumită secvenţă de cod din acea funcţie. La fiecare apel al funcţiei, se va executa secvenţa de cod coresunzătoare stării active. Astfel, pentru a finaliza execuţia întregii funcţii, e nevoie de apelarea repetată a acelei funcţii.  După ce maşina de stări a terminat de executat toate stările, orice alt apel către funcţia respectivă va fi ignorat, până la resetarea maşinii de stări. Resetarea maşinii de stări presupune înlocuirea stării curente cu starea iniţială. Ideal ar fi ca fiecare secvenţă de cod ataşată unei stări să fie scurtă şi utilă.
Ei, dacă funcţia care desenează întreg ecranul ar conţine o astfel de maşină de stări, atunci funcţia ar putea afişa câte un caracter pe ecran la fiecare apel. Pentru a desena întreg ecranul LCD 2x16, va fi nevoie de 32 de apeluri.
În mod similar putem avea o maşină de stări pentru controlul senzorului. Astfel la fiecare apel al acelei funcţiei se transmite sau se recepţionează câte un bit pe protocolul 1Wire.
Dacă vom apela cele două funcţii odată la o milisecundă, atunci, după aproximativ 32 ms vom avea întreg ecranul scris, iar pe protocolul 1Wire vor fi 4 bytes transmişi sau recepţionaţi (32 biţi / 8 = 4 bytes).
În cazul citirii senzorului putem verifica la fiecare apel al funcţiei dacă s-au recepţionat toate datele, caz în care putem introduce noua temperatură obţinută în textul ce urmează să fie afişat. Tot atunci putem reseta maşina de stări astfel ca să se înceapă o nouă conversie.
În continuare, putem ca tot la 250 ms să actualizam textul ce urmează să fie afişat pe ecran. Fie folosim textul curent, fie folosim caracterul " " pentru a şterge întreg ercanul. Tot atunci putem reseta maşina de stări a funcţiei ce scrie ecranul. Obţinem astfel actualizarea ecranului tot la 250 ms (pâlpâitul) şi citirea temperaturii.
TEOS
Pentru a realiza toate astea cât mai simpu, şi pentru a şi învăţa câte ceva, mi-am propus să fac un pseudo sistem de operare. Nu e un sistem de operare în adevăratul sens al cuvântului, ci e mai degrabă un planificator de operaţii. Oricum, eu l-am numit TEOS, adică Triggered Event Operating System. În traducere asta înseamnă Sistem de operare bazat pe evenimente declanşate.
Ce înseamnă un event (eveniment)?
Termenul l-am preluat din programarea orientată pe obiecte, unde un eveniment reprezintă, printre altele şi o schimbare a stării sistemului. De exemplu, mişcarea mouse-ului, apăsarea unei taste, selectarea unei ferestre, etc.
În cazul de faţă, sistemul de operare TEOS va oferi posibilitatea creării unui set de evenimente cu diferite moduri de declanşare (triggers). Ca să dau câteva exemple:
Evenimentul 1 va avea ca şi declanşator expirarea timer-ului de 10 ms. Asta înseamnă că la fiecare 10 ms acest eveniment va deveni activ.
Evenimentul 2 va deveni activ când se va apăsa o tastă.
Evenimentul 3 va deveni activ dacă timp de 1 minut nici o tastă nu s-a apăsat.
Şi aşa mai departe...
Ce înseamnă că un eveniment e activ?
Pe lângă posibilitatea de a executa o operaţie (sau funcţie) printr-un apel către ea, acest sistem de operare oferă posibilitatea de a ataşa funcţiei dorite un eveniment, legând astfel execuţia funcţiei respective de activarea evenimentului ales. Mergând pe aceeaşi idee, putem avea mai multe funcţii care să fie legate de aceelaşi eveniment. Astfel, de fiecare dată când acel eveniment se va activa, se vor executa toate funcţile care sunt ataşate evenimentului respectiv.
Ce evenimente am ales să folosesc?
Deocamdată le voi enumera doar, urmând ca în continuare să vin cu explicaţii mai amănunţite legate de alegerea acestor evenimente.
Pentru programul care face controlul pompei şi monitorizarea temperaturilor am folosit 6 evenimente:
  1. Event1ms - eveniment care devine activ o dată o milisecundă
  2. Event10ms - eveniment care devine activ o dată la 10 milisecunde
  3. Event200ms - eveniment care devine activ o dată la 200 milisecunde
  4. Event1min - eveniment care devine activ o dată la un minut
  5. EventKeyPressed - eveniment care devine activ când s-a apăsat orice tastă
  6. EventKeyTimeout - eveniment care devine activ dacă timp aproximativ de 1 minut nu s-a apăsat nici o tastă
Fiecare din evenimentele de mai sus va avea una sau mai multe funcţii ataşate. Fiecare funcţie face parte din câte un modul cu un rol anume în funcţionarea programului.

O parte din evenimentele alese sunt ciclice pentru că se activează cu regularitate tot la 1 ms, sau 10 ms, etc. Activarea unui eveniment se face de către declanşatorul ataşat evenimentului (Trigger). De exemplu, pentru evenimentul de 200 ms, trigger-ul este un timer ce expiră tot la 200ms. Tot atunci timer-ul reporneşte, realizând astfel repetarea activării evenimentului după încă 200 ms. În mod similar se activează celelalte evenimente ciclice. În imaginea de mai jos se poate observa felul în care evenimentele ciclice (1 ms, 10 ms, 200 ms şi 1 min) se activează:

Evenimentul "Any key" este aciclic, deoarece trigger-ul lui depinde de momentul în care o tastă a fost apăsată.
Evenimentul "Key timeout" este ciclic, dar nu se activează întotdeauna cu regularitate. În mod normal evenimentul devine activ dacă timp de aproximativ 1 minut nu s-a apăsat nici o tastă. Astfel, în cazul în care nici o tastă nu este apăsată, evenimentul va fi activat tot la 1 minut, deci trigger-ul lui este un timer ce expiră la 1 minut. În schimb de fiecare dată când o tastă a fost apăsată, timerul va fi repornit, întârziind astfel expirarea lui, şi deci activarea evenimentului. Cu alte cuvinte, dacă tot la 59 de secunde apăsăm o tastă, evenimentul nu se va activa niciodată.
Modulele folosite
Următoarele module au fost necesare pentru realizarea acestui program:
  • CRC - Calculează un CRC pe 8 biţi bazat pe "SAU Exclusiv"
  • DELAY - Permite crearea de pauze şi permite întârzieri scurte în execuţia unei funcţii
  • DISPLAY - Permite manipularea datelor ce urmează să fie afişate pe ecran
  • ERROR - Gestionează erorile care pot apărea
  • HMDY - controleaza ora şi data
  • IEP - Permite accesul EEPROM-ului intern
  • KEYB - Scanează tastatura şi reţine starea fiecărei taste
  • LCD - Permite controlul ecranului
  • MAIN - modulul central, unde vine făcut primul apel de funcţie
  • OWP - Permite transmisia şi recepţia datelor prin protocolul 1-Wire
  • PUMP - Controlează şi reţine starea releului
  • SSM - Gestionează maşina de stări sistemului
  • STRING - Manipulează şiruri de caractere
  • TEOS - Controlează activarea evenimentelor
  • TEXT - Conţine o parte din textele afişate pe ecran
  • TIM - Manipulează timerele software
  • TMON - Monitorizează temperaturile şi decide pornirea sau oprirea pompei
  • TSENS - Controlează senzorul de temperatură
  • VMON - Monitorizează tensiunea de 12V
Toate aceste module au fost concepute şi scrise de mine de la zero pentru a mă asigura că vor fi compatibile cu pseudo-sistemul de operare TEOS.
O parte din modulele enumerate mai sus sunt scrise intenţionat înclinat, pentru a marca modulele care au implementate maşini de stări. Cu ajutorul acestor module am realizat toate funcţionalităţile cerute.
Dar să începem cu prima funcţionalitate.
1. Controlul ecranului cu actualizarea ciclică a datelor afişate
Ecranul folosit e un LCD (Liquid Crystal Display = Ecran cu cristale lichide) RC1602D, cu 2 linii şi 16 coloane. Poate fi controlat prin 4 linii de comandă şi 8 sau 4 linii de date. Cele 4 linii de comandă sunt:
  • Vo - Reglajul contrastului (semnal analogic)
  • RS - linia Register select (semnal digital)
  • R/W - linia de Read/Write (semnal digital)
  • E - linia de Enable (semnal digital)
Controlând aceste 4 linii putem comunica cu microcontroler-ul intern al LCD-ului şi putem afişa textul dorit pe ecran. Modulul LCD se ocupă cu iniţializarea şi afişarea datelor pe ecran. Tot ceea ce face acest modul e să ia datele ce trebuie afişate de la o anumită adresă din memorie şi să le afişeze pe ecran. Maşina de stări a modulului LCD e legată de evnimentul de 1 ms, putând astfel afişa pe ecran câte un nou caracter aproximativ o data la fiecare o milisecundă. După aproximativ 32 de milisecunde, modulul a rescris întreg ecranul şi poate intra în stare de aşteptare. Din această stare de aşteptare va ieşi în cazul în care un alt modul va cere rescrierea ecranului.
Modulul TEOS va cere o dată la 200 ms reactualizarea (refresh-ul) ecranului. Astfel, ecranul va fi redesenat de aproximativ 5 ori pe secundă. Motivul pentru care am ales frecvenţa asta de rescriere a ecranului e pentru a putea realiza pâlpâitul textului afişat, în cazul în care o anumită valoare trebuie modificată de către utilizator.
2. Maşină de stări internă pentru meniul afişat
Conţinutul ecranului este compus dintr-o parte statică (ce nu se schimbă) şi o parte dinamică (care se poate schimba). Partea statică depinde de starea în care se află modului SSM, iar partea dinamică este controlată de modulul DISPLAY.
Starea modului SSM se poate schimba la apăsarea unei taste, lucru care poate determina schimbarea conţinutului ecranului, adică schimbarea adresei de la care modulul LCD preia datele ce vor fi trimise la ecran.
Pe de altă parte, conţinutul dinamic al ecranului e controlat de funcţia care face reactualizarea ecranului o dată la 200ms. Această funcţie va apela modulul DISPLAY pentru a modifica anumite porţiuni ale ecranului. De exemplu, în cazul afişării temperaturilor sau a orei, aceste valori vor trebui reactualizate pentru că se pot modifica oricând.
 În imaginea de mai sus se pot vedea o parte din stările modului SSM alături de conţinutul ecranului asociat fiecărei stări. Toate locurile ocupate de caracterul "-" reprezintă conţinutul dinamic al ecranului, care va fi modificat la apelul funcţiei de refresh cu ajutorul modului DISPLAY.
3. Scanarea ciclică a tastaturii.
Tastatura este citită de către KEYB. Acest modul scanează tot la 10 ms fiecare tastă şi reţine starea ei. Astfel o tastă poate trece prin următoarele stări:
Trecerea de la o stare la alta în funcţie de următoarele tranziţii:
T1 - la prima citire pinul este "0" logic
T2 - la a doua citire pinul este "1" logic (eroare de citire)
T3 - la a doua citire pinul este "0" logic (butonul a fost apăsat)
T4 - pinul este citit ca "1" logic
T5 - repetând citirea, pinul este "0" logic (eroare de citire)
T6 - repetând citirea, pinul este "1" logic (btonul a fost lăsat)
T7 - funcţia butonului a fost procesată, stare se resetează
Cele două stări "aparent lăsată" şi "aparent apăsată" au fost introduse pentru a filtra eventualele semnale parazite ce pot apărea. Trecerea de la starea "lăsată" la starea "neapăsată" se face doar după procesarea tastei, respectiv activarea evenimentului care depinde de apăsarea unei taste.
De fiecare dată când o tastă trece în starea "Lăsată", evenimentul AnyKey devine activ. De activarea acestui eveniment este legată maşina de stări a modului SSM, respectiv conţinutul textului afişat.
În cazul în care SSM se află în starea S0, el poate trece în starea S1 dacă tasta "Enter" a fost apăsată. Din S1 poate trece în S2 dacă fie tasta "+" sau "-" a fost apăsată. Apăsând tasta "Escape" se revine în starea S0.
Din starea S1 se poate trece în următoarele stări apăsând tasta "Enter":
Pentru starea S11, următoarele tranziţii sunt posible:
Din starea S12 se poate ajunge în următoarele stări:
S2 poate trece în una din următoarele stări:
Din starea S21 se poate ajnge următoarele stări:

În reprezentările de mai sus am omis să menţionez o serie de stări folosite pentru modificarea unor parametri interni ai sistemului, cum ar fi:
S1111 - stare folosită pentru modificarea Temperaturii de prag a panoului (Tp)
S1121 - modificarea Diferenţei de temperatură dintre Tp şi Tb (DeltaT)
S1131 - modificarea numărului de conversii înainte de comanda pompei
S1211 - modificarea orei
S1212 - modificarea minutului
S1221 - modificarea zilei
S1222 - modificarea lunii
S1223 - modificarea anului
S131 - controlul pompei
La aceste stări se ajunge cu ajutorul tastei "Enter", iar folosindu-se tastele "+" şi "-" se pot modifica valorile pe care le reprezintă.
 4. Monitorizarea temperaturii şi comunicarea prin OWP cu senzorii. 
Partea de citire şi monitorizare a temperaturilor este realizată de mai multe module structurate pe nivele.
4.1 OWP şi DELAY
Nivelul cel mai de jos e reprezentat de modulul OWP, care transmite şi recepţionează date date prin protocolul 1-Wire. Dat fiind că protocolul 1-Wire are o serie de cerinţe stricte legate de durata impulsurilor, momentul când portul de comunicare devine intrare sau ieşire, etc, m-am folosit şi de modulul DELAY. Acest modul permite crearea de pauze de lungime precisă de ordinul microsecundelor. Mai mult, acest modul permite şi întârzierea execuţiei unei funcţii cu un anumit număr de microsecunde. Asta este realizat prin salvarea pointer-ului către funcţia ce trebuie executată şi chemarea acelei funcţii în interiorul intreruperii generate la expirarea perioadei de pauză. Astfel funcţia ce trebuie întârziată se va executa cu întârzierea dorită, iar în timpul acelei întârzieri, microcontroller-ul poate executa altceva.
O funcţionalitate importantă a modului OWP este aceea că permite calcularea unui CRC pe toate datele primite, conform cu polinomul: CRC = X^8 + X^5 + X^4 + 1.
Dat fiind că partea de iniţializare a comunicării presupune recepţionarea unui impuls de prezenţă de la senzor, modulul OWP poate determina cu aproximaţie o serie de probleme care pot să apară:
  • dacă linia de comunicare rămâne în "1" logic, fără să apară impulsul de prezenţă, atunci fie cablul este rupt, fie senzorul lipseşte, fie avem un scurt la plus.
  • dacă linia de comunicare rămâne pe "0" logic, după iniţializare, atunci avem un scurt la masă.
4.2 TSENS
Nivelul de deasupra modului OWP este TSENS. Acest modul ştie să comunice cu senzorul. Cu alte cuvinte poate să trimită aproape toate comenzile recunoscute de către senzorul DS18B20 şi ştie să citească întreaga memorie a senzorului (cei 9 bytes din Scratchpad). Modulul verifică starea modului OWP, decide ce trebuie făcut şi pasează eventuala eroare nivelului superior. Asta înseamnă că, în cazul unei erori, el va încerca să restabilească comunicarea cu acel senzor de fiecare dată când acel senzor va fi accesat. În plus modulul TSENS verifică dacă datele primite sunt corecte cu ajutorul CRC-ului oferit de OWP şi alertează modulul superior dacă o nouă temperatură este disponiblă.
4.3 TMON şi ERROR
Nivelul cel mai de sus este TMON. Acest modul are un rol foarte important pentru că el decide pornirea sau oprirea pompei, în funcţie de datele primite. Modul în care funcţionează este următorul:
  • citeşte alternativ temperaturile celor doi senzori (Tpanou şi Tbazin).
  • în momentul în care s-a făcut numărul de conversii dorit, realizează o medie a temperaturilor pentru Tpanou şi Tbazin.
  • valorile medii ale temperaturilor sunt comparate cu valorile setate de către utilizator, iar în cazul în care se respectă condiţia de pornire a pompei, pompa este pornită, altfel pompa este oprită.
  • în cazul în care unul din senzori (sau ambii) e marcat de către TSENS ca fiind în starea de eroare, acel senzor va fi ignorat până ce starea lui nu se schimbă.
În cazul apariţei oricărei erori, modulul ERROR va fi chemat. Acest modul ţine evidenţa tuturor erorilor ce au apărut în sistem. Dacă numărul erorilor e mai mare de 0 atunci LED-ul de avarie va fi aprins.
Dacă unul din senzori e în starea de eroare atunci numărul de conversii nu va ajunge niciodată la valoarea dorită, deci pompa nu va fi comandată.
Modulul OWP este legat de evenimentul de 1 ms, asta înseamnă că un bit va fi transmis, sau recepţionat la fiecare o milisecundă.
Modulul TSENS e legat de evenimentul de 10 ms, adică tot la 10 milisecunde va trimite o nouă comandă (un byte), sau va recepţiona un nou byte de date.
Modulul TMON e legat de evenimentul de 200 ms, adică tot la 200 ms verifică dacă există o nouă valoare disponibilă a temperaturii pe oricare din canalele folosite (Tpanou sau Tbazin), iar dacă există o procesează.
 5. Actualizarea ore şi a datei.
Modulul HMDY (Hour Minute Day Year = oră minut zi an) realizează gestionarea timpului. Acest modul e chemat o dată la un minut, datorită evenimentului 1min. De fiecare dată când acest modul se execută el va face următoarele operaţii:
Astfel la fiecare apel al modulului HMDY se va incrementa valoarea minutelor. În funcţie de această valoare se verifică dacă valoarea orei curente nu trebuie incrementată. La rândul ei ora curentă poate determina incrementarea zilei, ziua poate determina valoarea lunii şi tot aşa până la an. Determinarea anilor bisecţi (când luna Februarie are 29 zile) se face prin verificarea dacă anul curent este multiplu de 4 sau nu. Nu e o metodă foarte exactă, dar acoperă aproape toate situaţiile în care avem ani bisecţi.
 6. Monitorizarea tensiunii de 12V şi detectarea unei căderi de tensiune.
Detectarea unei căderea de tensiune poartă numele de BOD (Brown Out Detection). Atmega8 are posibilitatea de a fixa nivelul de detectie la 4V sau 2.7V. În cazul programului meu, nivelul de detecţie e setat la 2.7V. Asta înseamnă că în momentul în care tensiunea de alimentare a ajuns la valoarea de 2.7V, microcontroler-ul se va reseta.
Pe lângă această măsură de precauţie, am folosit intrările comparatorului analogic AIN0 şi AIN1 , prin intermediu modului VMON, pentru a determina din timp dacă apare o pană de curent. Astfel, tensiunea de 12V de la 7812, trece printr-un divizor de tensiune şi intră în AIN1 (intrarea inversoare a comparatorului) sub forma unei tensiuni de 5.3V. Tensiunea de 5V de la 7805 intră direct în AIN0 (intrarea neinversoare a comparatorului). De fiecare dată când nivelul tensiunii de pe pinul AIN1 devine mai mic decât nivelul tensiunii de pe pinul AIN0, ieşirea comparatorului va trece din "0" în "1" şi va genera o întrerupere. În această întrerupere se salvează toate configuraţiile făcute şi istoricul de temperaturi, împreună cu un CRC care va fi folosit pentru validarea datelor citite din EEPROM. Prin natura circuitului electronic de alimentare, este posibilă întârzierea căderii de tensiune sub pragul de 2.7V, astfel încât să putem salva toate datele.
 7. Scrierea şi citirea datelor în şi din EEPROM, cu validare prin CRC.
Datele sistemului se salvează în memoria EEPROM internă doar când este detectată o cădere de tensiune. Împreună cu datele salvate, se salvează şi CRC-ul calculat pentru datele scrise.
La pornirea sistemului, se vor citi toate datele din EEPROM cu ajutorul modulului IEP şi se va verifica dacă CRC-ul calculat la citire coincide cu CRC-ul scris în EEPROM. În cazul în care cele două valori ale CRC-ului sunt identice, datele din EEPROM sunt valide şi se pot folosi pentru iniţializarea variabilelor globale ale sistemului. În cazul în care CRC-ul este diferit, datele din EEPROM nu sunt valide, aşa că se vor folosi nişte date împlicite (salvate în memoria Flash) pentru iniţializarea vaiabilelor globale.
 8. Detectarea şi administrarea erorilor.
Modulul care se ocupă cu administrarea erorilor este modulul ERROR. Modulul este chemat de către fiecare alt modul capabil să detecteze o eroare: OWP, VMON şi PUMP.
Următoarele erori sunt detectable:
  1. cablu rupt pentru senzorul din panou
  2. scurt la masă pe cablul pentru senzorul din panou
  3. cablu rupt pentru senzorul din bazin
  4. scurt la masă pe cablul pentru senzorul din bazin
  5. tensiunea de 12V lipseşte
  6. cablu rupt pentru releul care comandă pompa
Modulul ERROR setează bitul corespunzător erorii apărute. În cazul apariţiei oricărei erori, led-ul de avarie se va aprinde. Acest led va rămâne aprins până când problema care a cauzat eroarea nu a fost remediată. pentru a vedea ce eroare a apărut, trebuie să navigăm prin meniu până în starea S23. Aici controller-ul va afişa toate erorile care au fost detectate în momentul respectiv:
De exemplu, în cazul în care avem 4 erori: cablu rupt pentru senzorul din panou, scurt la masă pe cablul de la senzorul din bazin, releul lipseşte şi tensiunea de alimentare este sub 12V, atunci vom vedea următoarele mesaje de eroare:
Trecerea de la un mesaj de eroare la altul se face apăsând tasta "Enter", în momentul în care suntem în starea S23.
 9. Controlul releului pentru pompă.
Controlul releului care alimentează pompa se face din starea 1.3 (Control Pompă). Din acest meniu putem pune pompa în trei stări diferite:
  • Off - Comanda maunală de oprire a pompei
  • On - Comandă manuală de pornire a pompei
  • Auto - Mod automat
Dacă primele două setări sunt clare, Modul Auto e puţin mai complicat. În acest mod, controlul pompei este preluat de către microcontroller. Acesta va decide când trebuie să pornească pompa şi când să se oprească, pe baza temperaturii măsurate de către cei doi senzori, după cum urmează:
Pentru ca pompa să poată porni trebuie îndeplinite trei condiţii:
  • Temperatura din panou este mai mare decât temperatura setată (Tp)
  • Diferenţa de temperatură dintre temperatura din panou şi cea din bazinul de stocare este mai mare decât cea setată (Delta.T)
  • S-au făcut un număr de măsurători egal cu cel setat (Nr.Conv.)
Pornirea pompei e restricţionată pentru a nu permite răcirea bazinului de stocare, în cazul în care temperatura din bazin e mai mare decât temperatura din panou şi decât temperatura setată (Tp). Valoarea Delta.T reprezintă acea diferenţă de temperatură care permite un transfer util de căldură. Agentul termic ce vine de la panou trebuie să aibă o temperatură cu câteva grade mai mare decât cel din bazin pentru a permite transferul termic.
Pentru a nu avea situaţia în care releul cuplează şi apoi decuplează succesiv, la interval foarte scurt, s-a introdus trimiterea comenzii pentru pompă doar după un număr configurabil de măsurători. Dacă Nr.Conv e setat la valoarea 1 atunci, cum fiecare măsurătoare a temperaturii durează aproximativ o secundă, iar cum avem doi senzori, timpul cel mai scurt de transmiterea al unei comenzi va fi de aprox. 2 secumde. Pentru Nr.Conv egal cu 30, transmiterea comenzii se va face tot la un minut.
Cam în asta constă partea de logică a controllerului...
10. Surse
Codul se poate copia de aici...
Fişierul hex cu programul pentru ATmega8 se poate copia de aici...
Datele pentru EEPROM se pot copia de aici...

11. Fuse bits Atmega8 [update 02.01.2018]

duminică, 19 februarie 2012

Panou Termic Solar DIY - Partea II (Electronica)

Comanda pompei - partea electronică
Având în vedere că e iarnă şi construirea instalaşiei e mai dificil de făcut, m-am gândit că cel mai simplu ar fi să mă ocup de partea electronică şi de partea sofware a instalaţiei. Astfel m-am pus pe treabă şi mi-am făcut o listă cu funcţionalităţile care trebuie să le aibă circuitul electronic. Am început prin a face o schiţă generală a montajului (schema bloc).
1. Schema bloc
Circuitul electronic controlează funcţionarea instalaţiei este compusă dintr-o parte de comandă şi una de control a pompei. Partea de comandă are rolul de a permite utilizatorului să modifice sau să verifice anumiţi parametri ai circuitului. Pe lângă asta, partea de comandă are şi rolul de a decide pornirea sau oprirea pompei, pe baza temperaturilor măsurate cu ajutorul celor doi senzori amplasaţi în panou, respectiv în bazinul de stocare.

M-am gândit că o să-mi fie mai uşor de realizat schema electrocnică dacă împart circuitul îm mai multe blocuri specializate: controlul pompei, afişarea datelor pe ecran, tastatura, citirea temperaturii etc. Toate aceste blocuri funcţionale vor avea ca punct central microcontroller-ul ATmega8, care va controla întregul montaj.
2. Schema electronică
Mai jos se poate vedea schema detaliată:


2.1 Partea de alimentare
Partea de alimentare e compusă din două stabilizatoare de tensiune (IC1 şi IC2), pentru tensiunile de 12V şi 5V folosite în motaj. Pe lângă stabilizatoare mai sunt şi o serie de condensatori folosiţi în mare parte pentru filtrarea zgomotului ce poate să apară.
Între cele două stabilizatoare am montat o diodă urmată de doi condensatori de capacitate mai mare. Din cauze ce ţin de aranjarea pieselor pe placă, unul din condensatori a fost montat după 7805. Rolul acestor condensatori împreună cu dioda e de a acumula energie, care poate fi folosită în cazul unei căderi a tensiunii de alimentare.
Astfel, în momentul în care tensiunea de alimentare scade suficient de mult, dioda se va bloca, iar energia stocată în condensatori va menţine montajul alimentat o perioadă scurtă de timp. Această perioadă e proporţională cu capacitatea condensatorilor folosiţi. Am folosit doi condensatori de 1000uF şi 3300uF, care în total însumează peste 4000uF. În cazul montajului de faţă, această capacitate permite menţinerea tensiunii de 5V aproximativ o jumătate de secundă după ce tensiunea de alimentare a fost oprită. Această perioadă e suficient de mare pentru a permite microcontroller-ului să salveze starea curentă a sistemului în memoria EEPROM internă.
2.2 Monitorizarea tensiunii de alimentare
Nivelul tensiunii de alimentare e monitorizat permanent de către microcontroller prin cele două intrări ale comparatorului său analogic (AIN0 şi AIN1). AIN0 este intrarea neinversoare a comparatorului, iar AIN1 este cea inversoare. Pe pinul AIN0 va cădea o tensiune ce e obţinută din cea de 5V printr-un divizor de tensiune. Rezistenţele din divizorul de tensiune (R5 şi R6) au fost alese în aşa fel încât să obţin 4.5V la AIN0. Aceasta va fi tensiunea de referinţă. Pe pinul AIN1 va ajunge o tensiune obţinută din tensiunea de 12V. Rezistenţele R7 şi R8 fac ca din celălalt divizor de tensiune să ajungă, pe AIN1, aproximativ 5.5V.
În momentul în care tensiunea de alimentarea începe să scadă (din cauza unei pene de curent), tensiunea de 12V va fi prima afectată, şi va începe să scadă. Astfel tensiunea  pe pinul AIN1 va coborî sub valoarea tensiunii de pe pinul AIN0. În acel moment comparatorul analogic va declanşa o întrerupere (Analog Comparator IRQ) care va scrie în EEPROM-ul intern toate configuraţiile sistemului, data, ora, etc. Datorită circuitului descris în paragraful precedent (2.1), tensiunea de 5V va fi menţinută suficient de mult timp pentru a permite microcontroller-ului să stocheze toate datele în EEPROM.
2.3 Comunicarea cu senzorii de temperatură
De microcontroller-ul sunt legaţi doi senzori de temperatură (DS18B20) ce pot comunica prin protocolul 1-Wire. Acest protocol permite transmiterea bidirecţională a datelor pe un singur cablu pe distanţe foarte lungi (peste o sută de metri). Eu am folosit un cablu lung de aproximativ 20 metri. Distanţa la care se pot transmite date depinde foarte mult de tipul cablului, şi poate varia de la câţiva centrimetri, până la zeci de metri. După mai multe teste cu diferite cabluri am ales să folosesc cablu panglică (asemănător cu cel de la Hard-disk-urile pe IDE).
Viteza protocolului 1-Wire nu e foarte mare. Transmisia unui bit prin protocolul 1-Wire se face în 60us, ceea ce înseamnă că viteza de transmisie a datelor e de aproximativ 16k Baudrate (adică 16 kilo-biţi de date pe secundă sau 2 kilo-octeţi pe secundă).
Linia de date a protocolului are nevoie de o rezistenţă la plus externă (pull-up extern) de 4.7k ohmi (poate să difere cu distanţa).
Deşi protocolul suportă mai mulţi senzori pe aceelaşi cablu de date, am ales să folosesc câte un cablu separat pentru fiecare cablu. Motivul e coplexitatea ridicată a algoritmului folosit pentru identificarea senzorilor de pe magistrala de date.
2.4 Tastatura
Tastatura e formată din patru butoane: Enter, Escape, Plus şi Minus. Cu ajutorul lor se poate naviga prin meniu şi se pot face toate setările necesare instalaţiei. Circuitul pentru fiecare buton e foarte simplu. Fiecare pin al microcontroller-ului e configurat în aşa fel încât să aibă o rezistenţă internă la plus ("internal pull-up resistor" de 20k ohmi). Pe partea celalată, butonul, odată închis va lega la masă pinul. Astfel, de fiecare dată când butonul va fi apăsat, pe pin vor fi 0V, iar în rest 5V.
2.5 Afişarea datelor pe ecran
Am folosit un ecran alfa-numeric cu două rânduri şi 16 coloane RC1202D. Ecranul se alimentează de la 5V, poate fi comandat prin 4 linii de control şi 8 (respectiv 4) linii de date. Liniile de control ale ecranului sunt digitale, cu excepţia pinului VO, care e analogic şi prin care se poate regla contrastul display-ului. Pentru aceasta am folosit un semi-reglabil de 4.7k (P1).
Linia de control R/W a fost conectată la masă deoarece, pentru aplicaţia asta e nevoie doar de transmisia datelor de la microcontroler la ecran şi nu viceversa.
Display-ul mai are doi pini (LED+ şi LED-) pentru alimentarea led-urilor care luminează ecranul. Am vrut ca iluminarea ecranului să poată fi controlată de microcontroller, aşa că am legat pinul LED+ la portul PD5 al microcontroller-ului.
Toţi pinii de date ai display-ului (DBx) sunt legaţi la portul PBx (x = 0 .. 7).
2.6 Controlul pompei prin releu
Circuitul de comandă al pompei este realizat prin comanda unui releu de 220Vac. Aceasta este şi partea de putere a montajului. Comanda releului se face printr-un optocuplor (IC6) care deschide tranzistorul T1, care comandă, la rândul lui bobina releului K5.
La cuplarea, respectiv decuplarea, bobinei releului vor apărea vârfuri scurte de tensiune care pot afecta restul circuitului. Aceste impulsuri sunt aşa de scurte încât ele pot trece prin circuitul de alimentare, şi pot ajunge la microcontroller, cauzând un Reset. Pentru a filtra aceste impulsuri, am adăugat de o parte şi de alta a releului câte un condensator de 100pF (C9 şi C10).
Pentru protejarea tranzistorului T1 am legat dioda (D8) paralel cu bobin releului, în sens invers de conducţie. Această diodă are rolul de a descărca bobina cât mai repede, în momentul în care T1 este blocat. Fără această diodă, energia acumulată în bobina releului, ar putea străpunge tranzistorul.

Comanda începe prin punerea pinului PD4 pe "1" logic, adică o tensiune de aproximativ 5V. Asta va face ca optocuplorul IC6 să se deschidă şi să deschidă, la rândul lui tranzistorul T1. În momentul în care T1 s-a deschis, bobina releului este alimentată, iar releul va cupla, alimentând astfel pompa.
Rolul optoculplorului e de a izola cât mai bine parte de putere de partea de comandă. În cazul în care T1 este străpuns (din orice motiv), tensiunea de 12V nu poate ajunge la pinii microcontroller-ului, datorită optocuplorului.
2.7 Detectarea prezenţei releului
E foarte important ca atunci când apare o defecţiune, aparatul cu care lucrezi să îţi poată da cât mai mute informaţii legate de problema apărută. Din acest motiv am încercat să fac montajul să detecteze cât mai multe defecţiuni. M-am gândit că partea de comandă a releului e foarte împortantă aşa că am vrut să am o confirmare (feedback) că releul e conectat la regulator şi că funcţionează.
Pentru a face lucrul ăsta m-am folosit de un amplificator operaţional, care compară tensiunea ce cade pe rezistenţa R10, cu tensiunea de alimentare de 12V. În cazul în care releul lipseşte (sau cablul de comandă e întrerupt), pe R10 nu va fi nici o cădere de tensiunea (nu circulă curent prin rezistenţă). În situaţia asta amplificatorul va semnaliza microcontroller-ului lipsa releului prin intermediul pinului PD4 (pompă feedback).

În cazul în care releul e prezent în circuit, la comanda de pornire a pompei, prin R10 va trece curent. Asta va duce la apariţia unei căderi de tensiune pe R10, care va face ca amplificatorul să nu comute din 0V în 12V.
Desigur partea asta de circuit nu e esenţială, ea poate lipsi. Pentru mine a fost o provocare să găsesc o metodă de a face detecţia releului, folosindu-mă de ce am avut la dispoziţie prin casă.
3. Programarea
În schemă nu apare şi interaţa pentru AVR Prog, prin care am programat microcontroller-ul.
În asta constă circuitul electronic al regulatorului. Nu am experienţă în electronică aşa că schema are cu siguranţă multe greşeli de proiectare, aşa că orice sfat sau observaţie e binevenită! :-)