Sari la conținut
ELFORUM - Forumul electronistilor

voltampermetru cu pic 16f876


winston

Postări Recomandate

Acea schema era un experiment, cautam o solutie sa monitorizez curentul pe ramura pozitiva pentru a putea avea masa comuna la sursa unde urma sa fie pusa, initial mersesem pe ideea unui amplificator diferential cu amplificare 1x, urmat de un amplificator neinversor dar configuratia nu era una stralucita si pana la urma am ales ceva sugerat de Smilex, un generator de curent constant cu AO, asta este schema finala pe care am facut-o si care functioneaza ok pe sursa mea:

Posted Image

 

Acum ca stim ce senzor de temperatura folosesti oputem merge mai departe cu codul, si referitor la temperatura intre ce limite vrei sa fie afisata pe display? adica spre exemplu 0-100*C sau 0-150*C, sau orice alt prag maxim preferi tu.

Link spre comentariu
Vizitator nmihaic

merci mult imi dai si codul folosit(sursa) ca o modific eu pentru ce am nevoie, voi folosi ca senzor de temp un lm35 urmat de un AO cu o amplificare de 4 cred(pentru a masura pana la 125 grade celsius si adug la intrarea picului diode xener de 5v1 pentru toate cele 3 intrari analogice,

Multumesc inca o data.

Link spre comentariu
Vizitator nmihaic

mai am o intrebare :)

ai facut 2 dubloare de tensiune(nu sunt sigur daca asa se numesc poate spun prosti :) da aia fac ) de 9.1V*2 pentru a alimenta cele 2 AO dece nu ai facut unu?

adica 2 diode zener nu 4 2 condesatoare de 1000u pe 20v(mai mare de 9 bineinteles) nu sunt zgarcit da incerc sa reduc shema :)

si daca as pune LM ala direct la PIC as avea o sensibilitate buna pentru ca picu are 5v/1023 adica aproape 5mv/pe diviziune iar LM are 10mv/grad celsius, n ar fi ok?

imi cer scuze daca pun intrebari de noob da vreau si eu sa invat :)

O zi buna si multumesc inca o data :)

Editat de nmihaic
Link spre comentariu

Hai sa lamurim o chestie, schema mea a fost dezvoltata dupa niste cerinte clare ale mele, atat partea de monitorizare curent cat si de temperatura ii apartin lui Smilex, la partea de monuitorizare curent shuntul este pus pe plus si nu pe masa asa cum se face de obicei, eu aveam nevoie de masa comuna, solutia asta a fost una cea mai accesibila mie si destul de precisa, masa alimentarii AO este raportata la plusul pe care curentul se monitorizeaza, configuratia ceerea asta, din acest motiv trebuia ca alimentarea partii de monutorizare temperatura sa fie izolata galvanic de aceasta de la curent, si asta nu se putea obtine decat de la un alt secundar separat, de aici si 2 redresari cu dublare de tensiune separate.

 

Tu ceri altceva, sunt cateva chestii usor diferite deci haide sa continuam ce am inceput pentru tine, codul este in proportie de 70-80% scris, nu mai trebuie decat cateva randuri adaugate la el, apoi iti voidesena eu schema potrivita pentru tine ( la senzor este nevoie de AO, nu se poate fara ). Revin sper eu dupa-amiaza cu codul complet si schema.

Link spre comentariu

Codul completat conform cerintelor ( tarziu stiu, dar am avut o zi aglomerata, si maine va fi si mai rau ):

/* Volt-Amper metru @nmihaic * Tensiune afisata 0-20Vcc * Curent afisat 0-5Acc * Microcontroller PIC16F876A * Oscilator Cristal 4Mhz * LCD 2x16 * Autor Marian@Elforum *///Conexiuni LCDsbit LCD_RS at RB1_bit;sbit LCD_EN at RB3_bit;sbit LCD_D4 at RB4_bit;sbit LCD_D5 at RB5_bit;sbit LCD_D6 at RB6_bit;sbit LCD_D7 at RB7_bit;sbit LCD_RS_Direction at TRISB1_bit;sbit LCD_EN_Direction at TRISB3_bit;sbit LCD_D4_Direction at TRISB4_bit;sbit LCD_D5_Direction at TRISB5_bit;sbit LCD_D6_Direction at TRISB6_bit;sbit LCD_D7_Direction at TRISB7_bit;//Declarare variabileunsigned char ch, ADCx;unsigned int Tensiune, Curent, Temp, Putere, ProtT;unsigned long V, A, T, Pw;//Functie principalavoid main() {     INTCON = 0;     TRISA = 0x07;     TRISC = 0;     PORTC = 0;     Lcd_Init();     Lcd_Cmd(_LCD_CURSOR_OFF);     Lcd_Cmd(_LCD_CLEAR);     Lcd_Out(1,1,"VoltAmper-metru");     Lcd_Out(2,3,"***Mihai***");     Delay_ms(2000);     Lcd_Cmd(_LCD_CLEAR);     Lcd_Out(1,1,"U:");     Lcd_Out(1,9,"T:");     Lcd_Out(1,16,"C");     Lcd_Out(2,1,"I:");     Lcd_Out(2,9,"P:");     while (1) {         //Achizitie ADC         Tensiune = 0;         Curent = 0;         Temp = 0;         for (ADCx=0; ADCx<10; ADCx++) {         Tensiune += ADC_Read(0);                               // Achizitie Tensiune         Curent += ADC_Read(1);                                 // Achizitie curent         Temp += ADC_Read(2);                                   // Achizitie Temperatura         Delay_ms(50);         }         //Tensiune            Tensiune = Tensiune/ADCx;                           // Alocare valoare tensiune            V = (long)Tensiune*200;                             // Converteste rezultat in milivolti            V = V/1023;                                         // 0...1023 => 0...200mV            ch = V/100;                                         // Extrage zeci            if (ch==0) {                Lcd_Chr(1,3,32);                                // Daca rezultatul este 0, afiseaza spatiu liber                }            else {                Lcd_Chr(1,3,48+ch);                             // Afisare rezultat in format ASCII, linia 1, coloana 3                }            ch = (V/10) % 10;                                   // Extrage unitati            Lcd_Chr_CP(48+ch);                                  // Afisare rezultat            Lcd_Chr_CP('.');                                    // Afiseaza caracter ","            ch = (V/1) % 10;                                    // Extrage zecimi            Lcd_Chr_CP(48+ch);                                  // Afisare rezultat            LCD_Chr_CP('V');                                    // Afisare "V" la final            Delay_ms(10);            //Curent            Curent = Curent/ADCx;                               // Alocare valoare curent            A = (long)Curent*500;                               // Converteste rezultat in milivolti            A = A/1023;                                         // 0...1023 => 0...500mV            ch = A/100;                                         // Extrage unitati            LCD_Chr(2,3,48+ch);                                 // Afisare rezultat in format ASCII linia 2, coloana 3            Lcd_Chr_CP('.');                                    // Afisare caracter ","            ch = (A/10) % 10;                                   // Extrage zecimi            Lcd_Chr_CP(48+ch);                                  // Afisare rezultat            ch = (A/1) % 10;                                    // Extrage sutimi            Lcd_Chr_CP(48+ch);                                  // Afisare rezultat            Lcd_Chr_CP('A');                                    // Afiseaza "A" la final            Delay_ms(10);                        //Temperatura            Temp = Temp/ADCx;                                   // Alocare valoare temperatura            T = (long)Temp*990;                                 // Converteste rezultatul in mV            T = T/1023;                                         // 0...1023 => 0...990mV            ch = T/100;                                         // Extrage zeci            if (ch==0) {                Lcd_Chr(1,11,32);                               // Daca rezultatul este 0 afiseaza spatiu liber                }            else {                Lcd_Chr(1,11,48+ch);                            // Afiseaza rezultat in format ASCII, linia 1, coloana 11                }            ch = (T/10) % 10;                                   // Extrage unitati            Lcd_Chr_CP(48+ch);                                  // Afisare rezultat            Lcd_Chr_CP('.');                                    // Afisare caracter ","            ch = (T/1) % 10;                                    // Extrage zecimi            Lcd_Chr_CP(48+ch);                                  // Afiseaza rezultatul            LCD_Chr_CP(223);                                    // Afiseaza caracter "grad"            Delay_ms(10);                        //Putere            Pw = V*A/100;                                       // Aloca valoare putere            ch = Pw/1000;                                       // Extrage sute            Lcd_Chr(2,11,48+ch);                                // Afisare rezultat in format ASCII, linia 2, coloana 11            ch = (Pw/100) % 10;                                 // Extrage zeci            Lcd_Chr_CP(48+ch);                                  // Afisare rezultat            ch = (Pw/10) %10;                                   // Extrage unitati            Lcd_Chr_CP(48+ch);                                  // Afisare rezultat            Lcd_Chr_CP('.');                                    // Afisare ","            ch = Pw %10;                                        // Extrage zecimi            Lcd_Chr_CP(48+ch);                                  // Afisare rezultat            Lcd_Chr_CP('W');                                    // Afisare "W"            Delay_ms(10);                        //Protectie temperatura            ProtT = ADC_Read(2);                                // Aloca valoare protectie temperatura            if (ProtT > 413) {            PORTC.F2 = 1;                                       // Daca temperatura este mai mare de 40*C activeaza portul RC2            }            else if (ProtT < 310) {            PORTC.F2 = 0;                                       // Daca temperatura este mai mica de 30*C dezactiveaza portul RC2            }                  }}

Am comentat cat mai multe linii pentru a se intelege ce face fiecare. Iata si cateva imagini ilustrative cu diferite stagii ale afisarii:

Posted Image

Posted Image

Posted Image

Posted Image

Posted Image

 

Aici ilustrarea pragurilor de comutare a portului RC2 ( a se vedea ledul ) si histeresisul cerut, in speta ON la 40*C si off la 30*C:

Posted Image

Posted Image

Posted Image

Posted Image

 

Atasez si arhive cu hex-ul si proiectul in proteus:

Volt-Ampermetru @nmihaic.rar

Proteus.rar

 

Maine promit sa incerc sa-mi fac timp si pentru schema potrivita.

Spor.

Link spre comentariu
Vizitator nmihaic

Mulțumesc mult când ajung acasă o sa incerc sa îl fac și eu și Mas apuca de cablaj pana duminica, mulțumesc mult pentru timpul acordat, apropo de unde ești? Sa dau o bere sau ceva când trec pe aproape :).

Link spre comentariu

Nu-mi datorezi absolut nimic, ce fac, o fac cu placere.

 

LE: Cam asta ar fi schema gandita de mine:

post-176915-0-38172300-1402061494_thumb.png

 

Toate semireglabilele multitura, toate intrarile protejate cu zenner 5V1, si recomand BZX55C5V1, am lucrat cu ele si mi-au placut, apoi ideea este simpla, la tensiune un simplu semireglabil precedat de o rezistenta pentru limitare curent in eventualitatea scurtcircuitarii semireglabilului sau a unui reglaj "prea sus"; la curent un amplificator neinversor cu shuntul pe traseul de masa, amplificarea ajustabila din semireglabil, teoretic trebuie sa fie de 10x la shunt de 0,1, practic reglezi si calibrezi pentru shuntul tau tinand cont de toleranta acestuia; la temperatura un alt AO neinversor, deasemenea amplificare ajustabila pentru reglaj de precizie al afisarii. La iesirea pentru comutarea ventilatorului am inclus si un led care sa indice faptul ca ventilatorul a pornit ( mi s-a parut mie o chestie interesanta ), restul se poate lesne vedea in schema.

 

Bafta.

Link spre comentariu
Vizitator nmihaic

merci mult qam cateva intrebari la cum functioneaza adc de fapt codu 

1. )

A = (long)Curent*500; // Converteste rezultat in milivolti
A = A/1023; // 0...1023 => 0...500mV

ce fac mai exact linile astea :)

inteleg ca inparte scara tensiuni de la 0 la 5V in 2^10 diviziuni adica 1024(1023+1(care e 0)) dar de ce inparti A la 500? banuiesc ca e pentru sntul de 0.1dar nu prea inteleg :)

2 si la temp am o intrebare

//Protectie temperatura
ProtT = ADC_Read(2); // Aloca valoare protectie temperatura
if (ProtT > 413)

PORTC.F2 = 1; // Daca temperatura este mai mare de 40*C activeaza portul RC2

}
else if (ProtT < 310) {
PORTC.F2 = 0; // Daca temperatura este mai mica de 30*C dezactiveaza portul RC2

 

inteleg de aici ca eu va trebui sa reglez amplificarea sa fie de 5*(cand voi avea la 99grade sa am acel 5v la intrarea picului nu ca acea comparatie intre variabila ProT si o vla 413(banuiesc ca 413 diviziuni sun cele 40 grade) 

fac acest proiect pentru a invata si eu cum lucreaza si cum se progreameaza un PIC si sper sa am timp sa fac mai multe lucruri cu PIC :)

ms mult inca o data pentru timpul acorda, poate par intrebari banale dar vreau sa invat :).

Link spre comentariu

A = (long)Curent*500; // Converteste rezultat in milivolti

A = A/1023; // 0...1023 => 0...500mV

ce fac mai exact linile astea :)

inteleg ca inparte scara tensiuni de la 0 la 5V in 2^10 diviziuni adica 1024(1023+1(care e 0)) dar de ce inparti A la 500? banuiesc ca e pentru sntul de 0.1dar nu prea inteleg :)

Nu imparte la 500 ci inmulteste cu cu 500.

Adica la cap de scara are 500 mV => ca pentru fiecare LSB al ADC-ului are 500 mV / 1023.

In conditiile astea, valoarea convertita va fi valoarea ADC in LSB, inmultita cu valoarea unui LSB. Adica Val_Conv = ADC * 500 / 1023

 

2 si la temp am o intrebare

inteleg de aici ca eu va trebui sa reglez amplificarea sa fie de 5*(cand voi avea la 99grade sa am acel 5v la intrarea picului nu ca acea comparatie intre variabila ProT si o vla 413(banuiesc ca 413 diviziuni sun cele 40 grade) 

fac acest proiect pentru a invata si eu cum lucreaza si cum se progreameaza un PIC si sper sa am timp sa fac mai multe lucruri cu PIC :)

ms mult inca o data pentru timpul acorda, poate par intrebari banale dar vreau sa invat :).

Si aici e in principiu acelasi lucru - corespondenta marime fizica - valoare ADC.

Marian stie valorile ADC (in LSB) pentru 40°, respectiv 30° (pragurile de activare, respectiv dezactivare ventilator) si compara valoarea citita de ADC de la senzorul de temperatura cu valorile prag. In functie de rezultatul comparatiei, porneste/opreste ventilatorul.

 

PS In limba romana, inainte de b si pe se foloseste intotdeauna m, niciodata n (cu exceptia orasului Istanbul, da' ala e nume, nu se pune).

Editat de Liviu M
Link spre comentariu
Vizitator nmihaic

a deci sinsibilitatea e de fapt 500/1024? (mv/div) atuci cum naiba am vazut scheme in care un LM35 era conectat direct la microcontroler fara nici un zener macar pentru protectie asta insemna ca daca trecea peste 50 grade nu mai convertea nimic? sccuze pt limba romana scriu de pe tel si mai manc litere sau pun in plus :)

V = (long)Tensiune*200; // Converteste rezultat in milivolti
V = V/1023; // 0...1023 => 0...200mV

aici de ce e *200?

is cam prostut de fel recunosc:)

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