ratza Postat Iulie 26, 2011 Partajează Postat Iulie 26, 2011 Microcontrollerele (uC) permit realizarea unor aplicaţii extrem de complexe, totul depinzînd de limitele celui/celei care dezvoltă aplicaţia. Poate v-aţi gîndit la o aplicaţie personalizată după propriile cerinţe şi nu ştiţi cum să începeţi. Prezint mai jos o aplicaţie de termometru de exterior cu acurateţe de 1 grad, relizată cu ATmega8, LM335Z şi un display cu 4 digiţi şi anod comun, explicînd modul în care se execută un proiect. Teoretic, orice proiect nou care foloseşte un uC trebuie să respecte cîţiva paşi: 1 Adunarea cerinţelor; 2 Identificarea pieselor necesare; 3 Alegerea limbajului de programare; 4 Definirea blocurilor funcţionale; 5 Implementarea codului; 6 Tesatarea sistemului; 7 Documentaţia ulterioară. 1. Adunarea cerinţelor Avem nevoie de un sistem care să măsoare temperatura din exterior de la -40°C la +60°C şi s-o afişeze cu o acurateţe de un grad Celsius pe un afişaj cu 7 segmente. Frecvenţa de măsurare va fi de 5Hz. Alimentarea trebuie să poată fi făcută de la o baterie de 9V. Evident, toate să coste cît mai puţin. 2. Identificarea pieselor necesare Folosim un senzor analogic, LM335Z. Ne trebuie un controller care să aibe un număr suficient de pini pentru conectarea afişajului şi un ADC (convertor analog-digital) cu o rezoluţie suficientă pentru acurateţea cerută, de un grad. Senzorul are ieşire proporţională în tensiune, fiecărui grad Kelvin corespunzîndu-i 10mV. Gama de temperaturi aleasă se încadrează fără probleme în specificaţiile senzorului. Tensiunea de măsurat va fi deci între 2,330...3,330V – o variaţie de 1V. Avem posibilitatea a două metode de măsură: - Extragerea unui offset de 2,33V şi măsurarea diferenţei de 1V (cu referinţă externă de 1V); - Măsurarea întregii game (cu referinţa externă de 5V). Avantajul primei variante este aceea că pentru un pas de 10mV este necesar un ADC pe: 1V/10mV = 100 biţi Cel mai apropiat ar fi un ADC pe 8 biţi, 2^8 = 256, dezavantajele fiind necesitatea unui operaţional care să ne scape de offset şi a unei referinţe de fix 1V. A doua variantă ne scapă de operaţional, circuitul fiind mult mai simplu, însă pentru a putea avea acurateţea necesară, va fi nevoie de o rezoluţie a ADC-ului pe: 5V/10mV = 500 biţi. Cel mai apropiat ar fi 2^9 = 512, adică 9 biţi, dar aceasă rezoluţie nu există. Se foloseşte deci un ADC cu rezoluţie de 10 biţi. Acurateţea va fi în acest caz de 5V/2^10 = 5000mV / 1024 = 4,883mV şi se încadrează în cerinţe. Un controller ieftin şi care îndeplineşte toate cerinţele de mai sus este ATmega8. Afişarea va necesita maxim două cifre şi semnul, în caz că temperatura este negativă. Drept urmare, un număr de 3 digiţi ar fi suficient. Folosim un afişaj cu 4 digiţi, fiind mai elegant să afişăm şi simbolul de grade. Pentru simplificarea circuitului, alegem varianta a doua. 3. Alegerea limbajului de programare Limbajul de programare se alege în funcţie de ceea ce ştiţi. Personal, prefer C; este un limbaj extrem de puternic şi uşor de stăpînit, permiţînd accesul la nivel de bit. Cei care vor să optimizeze totul la sînge vor alege assembler, tăticul tăticilor în progamare. Cum ziceam, prefer C, deci codul este scris în întregime în acest limbaj. Compilatorul folosit este CodeVision AVR, unul dintre cele mai bune compilatoare pe care le-am folosit. Are şi un generator de cod, însă nu vă recomand să vă bazaţi prea mult pe el. 4. Definirea blocurilor funcţionale Acum că ştim cu ce lucrăm, trebuie să alegem cum va funcţiona codul. Este bine ca acesta să fie spart în funcţii, fiecare ocupîndu-se de ceva anume. Pentru termometrul nostru, codul va avea nevoie de funcţii care să iniţializeze regiştrii, să execute conversia AD, să convertească rezultatul în grade Celsius, să convertească cifrele in segmente şi să afişeze valorile. 4.1 Iniţializarea regiştrilor se face ţinînd cont de foaia de catalog a controlerului şi de schemă. Din păcate este necesară cunoaşterea limbii engleze. Fără ea nu aveţi ce face. Noi folosim opt pini pentru segmente (port D [7]), 4 pini pentru anozi (port C [3]) şi un pin pentru ADC (port C [0]). Mai folosim un timer pentru frecvenţa de măsurare şi o întrerupere pentru acesta. Frecvenţa de ceas a uC se face din fuse bytes şi o stabilim la 1MHz (oscilator intern RC de 8MHz, divizat cu 8). Pentru timer folosim un prescaler de 1024, deci o frecvenţă de 1MHz/1024 = 976,6Hz. Pentru a obţine 5Hz, este necesar ca timerul să numere: 976,6/5 = 195 paşi. Cum limita de overflow este 255, timerul va porni de la: 255 – 195 = 60. 4.2 Conversia AD se face simplu în cazul nostru, prin setarea unui bit într-un registru, apoi se aşteaptă pînă e gata rezultatul. Acesta va fi dat mai departe, în funcţia de conversie a temperaturii. 4.3 Conversia temperaturii are loc în întreruperea de overflow, după ce s-a făcut conversia AD. Tot aici se stabileşte şi semnul pentru temperaturile negative. 4.4 Conversia în segmente se face ţinînd cont de valoarea temperaturii. Avînd 4 digiţi, fiecare va conţine cîte ceva. Primul este semnul „-” în caz de temperaturi negative. Dacă temperatura este pozitivă, nu se pune niciun fel de semn, digitul fiind ţinut stins. După semn se pune valoarea în grade (1 sau 2 digiţi), ultimul digit conţinînd semnul de grad. 4.5 Afişarea se face multiplexînd cei patru digiţi. Avem nevoie de un index care baleiază digiţii, afişîndu-le conţinutul pe rînd. În funcţie de valoarea conţinută de digiţi se aprind segmentele corespunzătoare. Toate segmentele sînt stinse la începutul funcţiei pentru a evita afişări eronate. 4.6 Funcţia main este obligatorie în orice cod scris în C. În aceasta se apelează iniţializarea regiştirilor, apoi se intră într-o buclă infinită în care se face conversia şi se afizează valorile. Bucla trebuie să fie repetată la nesfîrşit deoarece dacă programul iese din ea nu se mai execută nimic pînă la următorul reset. 5. Implementarea codului Codul va fi scris respectînd în mare cele de mai sus. Bineînţeles că sînt şanse mari să nu meargă din prima şi să apară probleme sau ca, pe parcurs, să fie găsită o modalitate mai eficientă de implementare. De asemenea, nu de puţine ori cerinţele sînt imposibil de atins şi e necesară revizuirea lor. Comentaţi-vă codul cît mai bine pentru că va fi de ajutor peste ani, cînd nu veţi mai avea idee ce dracu’ trebuia să facă linia cutare. Chiar dacă acum pare clar, în viitor nu va mai fi chiar la fel. E preferabil ca în locul valorilor scrise în clar să folosiţi macro. Acestea nu ocupă loc în flash şi fac codul mult mai uşor de înţeles. Un mic exemplu. - una e să scrii: PORTA = 0x11;- alta e să scrii: #define BIT0 0x01...#define BIT3 0x08...PORTA = BIT3 | BIT0;- şi cu totul altceva e să scrii: #define BIT0 0x01...#define BIT3 0x08...#define LED_MARTOR BIT0#define IESIRE BIT3...PORTA = LED_MARTOR | IESIRE; 6. Tesatarea sistemuluiCînd codul este presupus a fi funcţional cel puţin parţial, se trece la testarea acestuia. Eu prefer să testez fiecare funcţie în parte, apoi bucăţi împreună, adugînd din ce în ce mai multe funcţionalităţi. După rezolvarea problemelor, cînd totul funcţionează conform celor propuse, se trece la penultimul pas: o bere rece şi satisfacţia că merge. 7. Documentaţia ulterioară Cînd schema, PCB-ul, codul şi montajul sînt complet realizate ar fi bine să vă notaţi undeva care au fost problemele în fiecare etapă de proiectare, cum le-aţi rezolvat, cum aţi implementat funcţionalitatea etc. Acesta este un pas peste care foarte multă lume sare şi care este extrem de necesar. Proiectul de faţă este extrem de simplu, însă în cazul modulelor mari, de zeci de mii de linii de cod, implementarea este împărţită între mai multe persoane şi e foarte dificil să înţelegi ce a vrut să facă altcineva. De aceea documentaţia este foarte necesară, deşi e detestată de toată lumea pentru că ia mai mult timp decît implementarea propriu zisă. Aştept întrebări de genul „de ce e aia aşa”, „cum merge asta”, „nu mergea făcută şi aşa” etc. Din punctul meu de vedere, nu există întrebări tîmpite, ci doar răspunsuri idioate. Codul complet în ataşament. Link spre comentariu
francezu Postat Iulie 26, 2011 Partajează Postat Iulie 26, 2011 O observatie:aici: 1V/10mV = 100 biţisi aici:5V/10mV = 500 biţicorect ar fi 100 respectiv 500 nivele discrete (baza de numeratie zecimala), altfel nu are sens ce ai scris mai jos, ca se foloseste ADC pe 8 respectiv 9 biti. Link spre comentariu
ratza Postat Iulie 27, 2011 Autor Partajează Postat Iulie 27, 2011 Ai dreptate, era vorba de LSB (least signifiant bit). Obişnuinţa cu termenii în engleză Link spre comentariu
picolo Postat Iulie 27, 2011 Partajează Postat Iulie 27, 2011 Daca ai pus conditia ca trebuie sa mearga cu o baterie de 9V, cred ca trebuie sa te gandesti si la consum:1. masuratoare la 5Hz cred ca este mult. ( ce inertie termica are senzorul tau?)2. afisorul poate sa fie aprins si la 50hz, ca oricum ochiul uman nu sesizeaza.Poate este bine sa pui uC in sleep ca nu prea are ce face.Si nu inteleg care este rolul unei intreruperi intr-o aplicatie ca aceasta.Poate doar didactic. Link spre comentariu
ratza Postat Iulie 28, 2011 Autor Partajează Postat Iulie 28, 2011 1. Inerţia termică e destul de mare, ăia 5Hz sînt puşi la întîmplare.2. Fiecare e liber să-şi aleagă metoda. Eu am preferat afişarea în main().Nu l-am pus în sleep pentru că nu vreau să afişeze temperatura tot timpul. Cînd am chef să văd cum e afară apăs un buton şi-l alimentez.Rolul întreruperii? De distracţie. Prefer întreruperile în locul delay-urilor.Proiectul zace la mine pe geam. Codul l-am scris la repezeală, nu e chiar cel mai ordonat Link spre comentariu
godFather89 Postat Iulie 28, 2011 Partajează Postat Iulie 28, 2011 Felicitari pentru tutorial Cateva mici observatii: #define BIT0 0x01#define BIT3 0x10 Daca prin BITn te referi la al n-lea BIT dintr-o grupare de biti si numarul reprezinta masca acelui bit, atunci BIT3 este 0x08.Ai dreptate, era vorba de LSB (least signifiant bit). Obişnuinţa cu termenii în englezăLSB reprezinta un nivel de tensiune si anume nivelul de tensiune minim, necesar pentru schimbarea valorii returnate de ADC. Practic reprezinta sensibilitatea unui convertor analog digital LSB = Vref/2^N [V]. Unde N reprezinta rezolutia convertorului (exprimata in biti).Probabil te refereai la rezolutia convertorului exprimata in cuante (2^N).LE: Perosnal, recomand GCC ca si compilator si Avr Studio 5 (vine cu GCC toolchain pentru platformele pe 8 si 32 de biti) deoarece sunt foarte puternice si GRATIS. Link spre comentariu
ratza Postat Iulie 28, 2011 Autor Partajează Postat Iulie 28, 2011 Încă o dată corect, BIT3 = 0x08, ce-am scris eu e BIT4 În legătură cu LSB, mi-e greu să adaptez în română. Link spre comentariu
Postări Recomandate
Creează un cont sau autentifică-te pentru a adăuga comentariu
Trebuie să fi un membru pentru a putea lăsa un comentariu.
Creează un cont
Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!
Înregistrează un nou contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum