Sari la conținut
ELFORUM - Forumul electronistilor

Termometru cu pic16f876A


Vlad Mihai

Postări Recomandate

Salut, vreau sa fac un termometru care sa afiseze temperatura in grade Celsius, fahrenheit, Kelvin si Rankine, am incerc eu sa fac un cod pe baza documentatiei dar nu cred ca merge ma ajuta cineva sa il termin? folosesc lm35 ca senzor care are 10mV pe grad celsius. De asemenea am cuart de 12Mhz si un 2x16 LCD.

 

Conversia temp...http://ro.wikipedia.org/wiki/Celsius

 

 

sbit LCD_RS at RB4_bit;sbit LCD_EN at RB5_bit;sbit LCD_D4 at RB0_bit;sbit LCD_D5 at RB1_bit;sbit LCD_D6 at RB2_bit;sbit LCD_D7 at RB3_bit;sbit LCD_RS_Direction at TRISB4_bit;sbit LCD_EN_Direction at TRISB5_bit;sbit LCD_D4_Direction at TRISB0_bit;sbit LCD_D5_Direction at TRISB1_bit;sbit LCD_D6_Direction at TRISB2_bit;sbit LCD_D7_Direction at TRISB3_bit;unsigned int val1,val2,val3,valm; unsigned int t,a, b;  unsigned long u;unsigned char ch;void main(){  //TRISA      = 0xFF;                       // designate PORTA as input  //INTCON = 0;                              // Disable all interrupts  //IRP_bit = 1 ;  Lcd_Init();                        // Initialize LCD  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off  Lcd_Cmd(_LCD_CLEAR);               // Clear display  Delay_ms(100);  LCD_Out(1,2,"Termometer");  LCD_Out(2,2,"EA 1341A");  Delay_ms(1500);  Lcd_Cmd(_LCD_CLEAR);               // Clear display  LCD_Out(1,2," Alexandru");  LCD_Out(2,2," Bujorean");  Delay_ms(1500);  Lcd_Cmd(_LCD_CLEAR);               // Clear display  LCD_Out(1,2,"Prof. Gaitan");  LCD_Out(2,2,"Cristina-MC");  Delay_ms(1500);   Lcd_Cmd(_LCD_CLEAR);    while (1)    {      for (b ; b < 2; b++) {       Lcd_Cmd(_LCD_CLEAR);      }      // Voltage      val1=ADC_read(0);                // get ADC value for U from channel 1      delay_ms(30);      val2=ADC_read(0);      delay_ms(30);      val3=ADC_read(0);      delay_ms(30);      valm=((val3+val2+val1)/3);      u=(long)valm*5000;               // covert adc reading to milivolts      u=u/1023;      t=(valm*0.48876);//Convert to Degree Celcius                               LCD_Chr_CP(t);  }}
Link spre comentariu
  • Răspunsuri 20
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • Vlad Mihai

    11

  • Liviu M

    7

  • francezu

    1

  • 10vid

    1

Top autori în acest subiect

Imagini postate

Am dat google dupa acel numar misterios: 0.48876. Si a aparut tot in proiecte similare cu pic si lm35. E un factor de conversie precalculat. Daca ai inceput cu val*5000 etc, care e acelasi lucru, doar scris labartat, e clar ca nu-l mai inmultesti inca o data cu acel factor.Si apropo, ADC are 1024 nivele, nu 1023. Stiu, multi fac greseala asta, sa inmultesca si sa imparta cu 1023, probabil si profesori. :bataieDeci, dupa calcularea mediei celor trei citiri, urmeaza:t=(valm*500)/1024

Link spre comentariu

la afisare nu prea stiu cum sa fac dupa ce o convertesc, nu stiu cum sa afisez pe prima linie prima coloana temperatura in grade urmat de a 2 coloana cea in Kelvin, iar pe linia a 2 coloana 1 in grade F iar pe linia2 coloana 2 grade R.

Link spre comentariu
  10vid a spus:

Si apropo, ADC are 1024 nivele, nu 1023. Stiu, multi fac greseala asta, sa inmultesca si sa imparta cu 1023, probabil si profesori. :bataie

Rezolutia , in volti, a unui adc este raportul dintre intervalul tensiunilor permise la intrare si numarul de intervale incadrate in scala adc-ului. Daca adc-ul este pe 10 biti, inseamna ca poate cuantifica 1024 nivele distincte , dar intre acestea sunt doar 1023 de intervale de tensiune. Stiu ca e mai greu sa imparti la 1023 decat la 1024, dar asa se face.http://ww1.microchip.com/downloads/en/A ... 01152A.pdfhttp://en.wikipedia.org/wiki/Analog-to- ... _converter
Link spre comentariu

Domnilor am modificat cum aţi spus mai departe cu afişarea nu înţeleg. ataşez ce ma făcut eu:

sbit LCD_RS at RB4_bit;sbit LCD_EN at RB5_bit;sbit LCD_D4 at RB0_bit;sbit LCD_D5 at RB1_bit;sbit LCD_D6 at RB2_bit;sbit LCD_D7 at RB3_bit;sbit LCD_RS_Direction at TRISB4_bit;sbit LCD_EN_Direction at TRISB5_bit;sbit LCD_D4_Direction at TRISB0_bit;sbit LCD_D5_Direction at TRISB1_bit;sbit LCD_D6_Direction at TRISB2_bit;sbit LCD_D7_Direction at TRISB3_bit;unsigned int val1,val2,val3,valm; unsigned int t,a, b;  unsigned long u;unsigned char ch;void main(){  //TRISA      = 0xFF;                       // designate PORTA as input  //INTCON = 0;                              // Disable all interrupts  //IRP_bit = 1 ;  Lcd_Init();                        // Initialize LCD  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off  Lcd_Cmd(_LCD_CLEAR);               // Clear display  Delay_ms(100);  LCD_Out(1,2,"Termometer");  LCD_Out(2,2,"EA 1341A");  Delay_ms(1500);  Lcd_Cmd(_LCD_CLEAR);               // Clear display  LCD_Out(1,2," Alexandru");  LCD_Out(2,2," Bujorean");  Delay_ms(1500);  Lcd_Cmd(_LCD_CLEAR);               // Clear display  LCD_Out(1,2,"Prof. Gaitan");  LCD_Out(2,2,"Cristina-MC");  Delay_ms(1500);   Lcd_Cmd(_LCD_CLEAR);   LCD_Out(1, 1,"Temp:");  LCD_Out(2, 1,"Temp:");    while (1)    {      for (b ; b < 2; b++) {      }      // Voltage      val1=ADC_read(0);                // get ADC value for U from channel 1      delay_ms(30);      val2=ADC_read(0);      delay_ms(30);      val3=ADC_read(0);      delay_ms(30);      valm=((val3+val2+val1)/3);      t=(valm*500)/1024;               // covert adc reading to milivolts     t=(valm*0.48876);//Convert to Degree Celcius       if (ch==0)        {          LCD_Chr(1,6, 32);                // write empty space if digit is 0        }      else        {          LCD_Chr(1,6,48+ch);              // write ASCII digit at 1st row, 2nd column        }      LCD_Chr_CP("C");  }}

Stiu ca am gresit dar daca imi arati odata codul, stiu dupa cum se face. :pandaci

Link spre comentariu
  Vlad Mihai a spus:

      for (b ; b < 2; b++) {      }

De unde stie compilatorul cat trebuie sa fie b la intrarea in for? La ce e buna secventa asta?

 

  Vlad Mihai a spus:

t=(valm*500)/1024;               // covert adc reading to milivolts     t=(valm*0.48876);//Convert to Degree Celcius

Cum ti-a zis si 10vid, 0.48876 pare a fi 500/1023, asa ca una din operatii pare in plus.

 

  Vlad Mihai a spus:

       if (ch==0)        {          LCD_Chr(1,6, 32);                // write empty space if digit is 0        }      else        {          LCD_Chr(1,6,48+ch);              // write ASCII digit at 1st row, 2nd column        }      LCD_Chr_CP("C");  }}

 

Cine e ch si de unde sa stie el ce vrei tu sa scrii? Inainte sa folosesti ch, trebuie sa-l "umpli". Drept pentru care trebuie sa transformi temperatura din numar in sir de caractere si sa afisezi caracterele respective.

 

Metoda pe care o folosesc eu e (cu variabilele tale ):

   if(t<0)     LCD_char(1,6,'-'); // semnul - pentru temperaturi negative   ch = t/100; //=> afisez sutele   if(ch)       LCD_char(1,7,'0'+ch); //eu prefer ca trasformarea din char in ascii s-o fac cu ajutorul lui '0', nu cu 48. E acelasi lucru, da' eu citesc mai usor codul astfel scris   else      LCD_char(1,7,' '); //aici e o pauza intre ' ' (caracterul pauza   )   ch = ...; //=> afisez zecile   if(ch)       LCD_char(1,8,'0'+ch);   else       LCD_char(1,8,' ');...
Sper ca am inteles bine ce-ti trebuie.
Link spre comentariu

multumesc de raspuns, dar tot nu am priceput.. poti modifica tu astfel incat sa apara temperatura in grade Celsius pe prima linie si prima colonă?? si eu după sa ma joc cu el, după ce e bun. Multumesc!

Link spre comentariu

N-am inteles ce n-ai inteles.

Cum se transforma "LSB in grade", cum afisezi ce ai obtinut, ambele?

La prima intrebare am asa o senzatie ca t (din t=(valm*500)/1024; sau t=(valm*0.48876)) e fix ce-ti trebuie.

La afisare ti-am scris mai sus "algoritmul", n-ai decat sa-l termini si sa-l corectezi - ce am scris eu afiseaza pornind din linia 1, coloana 6 (sper ca-ti e clar ca temperatura nu poate fi afisata "pe linia 1 coloana 1 decat daca e intre 0 .. 9 °C).

Mai departe incearca si singur, ca nu-i asa greu.

Link spre comentariu

am mai facut ceva acum dar apare tot timpul 0.0 grade celsius.. nu am idee ce trebuie sa fac.

sbit LCD_RS at RB4_bit;sbit LCD_EN at RB5_bit;sbit LCD_D4 at RB0_bit;sbit LCD_D5 at RB1_bit;sbit LCD_D6 at RB2_bit;sbit LCD_D7 at RB3_bit;sbit LCD_RS_Direction at TRISB4_bit;sbit LCD_EN_Direction at TRISB5_bit;sbit LCD_D4_Direction at TRISB0_bit;sbit LCD_D5_Direction at TRISB1_bit;sbit LCD_D6_Direction at TRISB2_bit;sbit LCD_D7_Direction at TRISB3_bit;unsigned int val1,val2,val3,valm; unsigned int t,a, b;  unsigned long u;unsigned char ch;void main(){  //TRISA      = 0xFF;                       // designate PORTA as input  //INTCON = 0;                              // Disable all interrupts  //IRP_bit = 1 ;  Lcd_Init();                        // Initialize LCD  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off  Lcd_Cmd(_LCD_CLEAR);               // Clear display  Delay_ms(100);  LCD_Out(1,2,"Termometer");  LCD_Out(2,2,"EA 1341A");  Delay_ms(1500);  Lcd_Cmd(_LCD_CLEAR);               // Clear display  LCD_Out(1,2," Alexandru");  LCD_Out(2,2," Bujorean");  Delay_ms(1500);  Lcd_Cmd(_LCD_CLEAR);               // Clear display  LCD_Out(1,2,"Prof. Gaitan");  LCD_Out(2,2,"Cristina-MC");  Delay_ms(1500);   Lcd_Cmd(_LCD_CLEAR);   LCD_Out(1, 1,"Temp:");  LCD_Out(2, 1,"Temp:");    while (1)    {      for (b ; b < 2; b++)     {      }      // Voltage      val1=ADC_read(0);                // get ADC value for U from channel 1      delay_ms(30);      val2=ADC_read(0);      delay_ms(30);      val3=ADC_read(0);      delay_ms(30);      valm=((val3+val2+val1)/3);     t=(valm*0.48876);//Convert to Degree Celcius    if (ch==0)        {          LCD_Chr(1,6, 32);                // write empty space if digit is 0        }      else        {          LCD_Chr(1,6,48+ch);              // write ASCII digit at 1st row, 2nd column        }      ch=(u/100) %10;                      // extract 01.00 U digit      LCD_Chr_CP(48+ch);                   // write ASCII digit at cursor point  LCD_Chr_CP('.');                     // write '.' at cursor point    ch=(u/10) %10;                       // extract 00.10 U digit     LCD_Chr_CP(48+ch);                   // write ASCII digit at cursor point      LCD_Chr_CP('C');  }}

post-65525-139829525757_thumb.jpg

Link spre comentariu

Cine-i u? Unde scrii ceva in u, a.i u sa nu fie 0?

Mie mi se parea clar exempul meu.

Temperatura ta sta in t.

In primul if din exemplul meu testez daca temperatura e negativa (la tine n-are de unde sa fie negativa, da' am tratat cazul general). Daca e, afisez semnul -, daca nu las o pauza.

Urmeaza afisarea fiecarei cifre din temperatura.

Am exagerat putin si am presupus ca temperatura ta poate fi peste 100°C,drept pentru care pot afisa si sutele de grade. Cu operatia ch = t/100 am extras sutele din valoarea temperaturii (t, la tine temperatura sta tot timpul in t). Cu LCD_char(1,7,'0'+ch); afisez caracterul corespunzator sutelor (am scris in comentartiu de ce folosesc '0').

Chiar nu vad ce e neclar.

 

PS Ca sa ai o "rezolutie" ceva mai buna, foloseste un tip "cu virgula" (single, double)pentru t, nu intreg ca pana acum.

In cazul asta o sa ai si ceva de afisat dupa virgula.

Link spre comentariu

Pai asta am facut in postul cu codul. :nebunrau:

Mai aveai sa scrii doua formule pentru extras zecile (ch=(t/10)%10), respectiv unitatile (ch=t%10) din t si sa le afisezi la locurile lor:

   if(t<0)       LCD_char(1,6,'-'); // semnul - pentru temperaturi negative   ch = t/100; //=> afisez sutele   if(ch)       LCD_char(1,7,'0'+ch);    else      LCD_char(1,7,' ');   ch = (t/10)%10;       LCD_char(1,8,'0'+ch);   ch = t%10;       LCD_char(1,9,'0'+ch);

Asa-i ca nu era chiar asa greu?.

Ce-i drept, codul de mai sus afiseaza 0 la zeci cand temperatura e mai mica de 10°C, da' te mai joci singur sa-l faci sa afiseze mai bine (trebuie sa testezi daca ai ceva la sute, daca ai afisezi 0, daca n-ai nu afisezi nici la zeci nimic).

 

LE Mai trebuie, desigur, sa afisezi °C dupa valoare.

Link spre comentariu

Sa nu-mi zici ca ai si acolo probleme. :nebunrau: Calculezi intai valoarea ca numar (fahr=f(t), unde f e functia de conversie din °C in fahrenheit) dupa care la afisare aplici acelasi "algoritm" inlocuind t cu fahr in formulele de calcul pentru ch si adaptand coordonatele de afisare.

Link spre comentariu

revin cu termomerul meu am scris softul în simulator merge perfect, dar in practica nu merge, Lm35z l-am pierdut dar am făcut rost de un Lm335 care conform datasheet are 10mv/grad kelvin, deci acolo unde trebuia să indice celsius trebuia să indice kelviu doar că senzorul pare defect la temperatura camerei circa 20 de grade C da la ieşire o tensiune de 2.3v iar pe Lcd afisează 230. deci bănuiesc senzorul defect, am văzut pe google că se inseria si un rezistor de 2k2 cu borna 5v la senzor , dacă fac asta scade la 1.4v la ieşire din senzor. Deci?

Posted Image

online photo storage

Link spre comentariu

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 cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări