Sari la conținut

Wattmetru cu PIC


pisica matache
 Share

Postări Recomandate

Am testat in dimineata asta;zerourile inutile au disparut.Umplerea pwm,se modifica de doua ori mai rapid ca inainte,ceea ce inseamna cresterea tensiunii de la zero la maxim,in cca 40s.Am filtrat rudimentar semnalul pwm,cu 820 ohmi si 10 micro.Semnalul as zice ca e suficient de curat.Pun si un filmulet,in care butonul de descrestere a umplerii e apasat.Se observa cum tensiunea continuua scade de la 5V,la zero.

http://www.youtube.com/watch?v=iTq2JZp3rrg

Ramane acum de implementat reglarea tensiunii si a curentului,pe sursa in comutatie.

Umplerea se regleaza in pasi de cca 0,8%,ceea ce are ca urmare,pasi de cca 36mV,dupa filtrare.

 

Multumesc Mihai!

Editat de pisica matache
Link spre post
Distribuie pe alte site-uri

RoadRunner nu pricep la ce te referi eu nu sunt programator sunt un electronist care a invatat ceva programare din nevoie. Pisica matache, vezi linkul ala care ti l-am dat . ma bucur ca merge totul cum trebuie pana acum. sa vedem mai departe.

Link spre post
Distribuie pe alte site-uri

Din nou, consider ca nu trebuie sa fie chiar asa de avansat functia asta, asa se poate face si cu encoder sau mai stiu eu ce. sau direct cu telecomanda in infrarosu(eu am facut asta), consider ca e destul de bine cum functioneaza acum. Pisica Matache, eu am folosit la pwm frecventa de 15khz, ca asa am gasit eu practic cu osciloscopul ca e mai stabila si mai curata tensiunea de la iesire, eu am mai gasit in documentatie de la microchip ca se calculeaza cumva cu integrale filtrul asta si ca frecventa de start e undeva la 19khz ca sa fie perfect, eu nu am avut rabdare, daca vrei sa schimb frecventa la pwm se poate.

Link spre post
Distribuie pe alte site-uri

Eu zic ca e bine,cum functioneaza acum.Ramane sa testez practic cum se va comporta sursa,primind ca referinta semnalul oferit de PIC.

Daca referinta se modifica cu pasi de 36mV,de la 0 la 5V,iar sursa va avea tensiunea maxima de 25V,de exemplu,tensiunea la iesire se va modifica cu pasi de 36mVx5,adica 180mV.Se poate ajusta tensiunea de referinta,obtinandu-se pasi de 200mV.Eu zic ca reglarea tensiunii cu pasi de 0,2V,e suficienta.Adica,nu vad ce sarcina asa pretentioasa as putea alimenta,care sa aibe nevoie,sa zicem,de 14,33V si care sa nu functioneze normal cu 14,20 sau 14,40V.

Daca curentul maxim va fi de 10A,pasii vor putea fi de 72mA,sau regland referinta,de 100mA.

Editat de pisica matache
Link spre post
Distribuie pe alte site-uri

O sa testez,in limita timpului.Ieri am modificat sursa in comutatie,careia ca tensiune de referinta,in locul celei originale de 2,5V i-am dat tensiunea de 0-2,5V,obtinuta dupa filtrarea pwm.Sursa functioneaza conform asteptarilor,adica foarte bine,modificarea tensiunii,facandu-se cu pasi de 100mV,pentru o tensiune de iesire de cca 2-16V.A trebuit sa alimentez placa cu PIC dintr-o sursa separata,altfel la pornire umplerea fiind zero,tensiunea de referinta e zero,cea de iesire idem.Va trebui sa alimentez separat si operationalul si optocuplorul intern sursei,sa pot scadea tensiunea de iesire pana la zero volti. Testele le-am facut in graba,din lipsa timpului.Urmeaza sa pun totul intr-o carcasa si revin cu rezultatele finale.

Link spre post
Distribuie pe alte site-uri

Am testat in seara asta,hex-ul pentru 62,5Khz.Frecventa chiar aceasta este,iar umplerea se modifica cu pasi de cca 1,3%.Varianta asta va echipa o sursa in comutatie,la care voi modifica manual umplerea.

post-25543-0-11464000-1385582156_thumb.jpg

Editat de pisica matache
Link spre post
Distribuie pe alte site-uri

Buna ziua, Matache am incercat sa fac un cod pentru cerintele tale, referitor la zerouri am pus inapoi cum eram ca ele dispar si cand valoarea e mai mare si trebuie comparata valoarea si dupa modificate zerourile, poate cineva mai experimentat ne ajutat, referitor la cele 2 citiri de curent eu am facut asta si am pus pe pinul 14 15 16 cate un led care se va aprinde daca valorile difera, simulatorul nu imi ofera nimic ramane sa testezi practic. pe pinul 14 am pus un led care indica cand cele 2 valori sunt egale,pe pinul 15 cand valoarea a 2-a este mai mare decat prima si pe pinul 16 cand valoarea a 2-a este mai mica decat prima citita.

//Conexiuni LCD
sbit LCD_RS at RB7_bit;
sbit LCD_EN at RB6_bit;
sbit LCD_D4 at RB5_bit;
sbit LCD_D5 at RB4_bit;
sbit LCD_D6 at RB3_bit;
sbit LCD_D7 at RB2_bit;
sbit LCD_RS_Direction at TRISB7_bit;
sbit LCD_EN_Direction at TRISB6_bit;
sbit LCD_D4_Direction at TRISB5_bit;
sbit LCD_D5_Direction at TRISB4_bit;
sbit LCD_D6_Direction at TRISB3_bit;
sbit LCD_D7_Direction at TRISB2_bit;
//Declarare variabile
unsigned char ch, ADCx;
unsigned int Tensiune, Curent, Curent1, Curent_medie;
unsigned long V, A, Pw;
unsigned short current_duty1,current_duty2;
//Functie principala
void main() {
	 INTCON = 0;													 // Dezactivare intreruperi
	 TRISA = 0x03;											 // RA0, RA1 setate ca intrari
	 TRISB.F0=1;
	 TRISB.F1=1;
	 TRISC.F7=1;					  //intrari pentru push-butoane
	 TRISC.F6=1;
	 TRISC.F4=0;
	 TRISC.F5=0;
	 TRISC.F3=0;
	 PORTC.F5=0;
	 PORTC.F4=0;
	 PORTC.F3=0;
   
	 Lcd_Init();													 // Initializare LCD
	 Lcd_Cmd(_LCD_CURSOR_OFF);						 // Dezactivare cursor
	 Lcd_Cmd(_LCD_CLEAR);								   // Stergere Ecran
	 Delay_ms(1000);												 // Delay 1 secunda
	 Lcd_Out(1,2,"Afisaj Digital");		   // Mesaj initial 1, prima linie
	 Lcd_Out(2,5,"Multiplu");							   // Mesaj initial 1 linia 2
	 Delay_ms(3000);
	 Lcd_Cmd(_LCD_CLEAR);								   // Stergere ecran
	 Lcd_Out(1,1,"100V; 50A; 5000W");			   // Mesaj initial 2, prima linie
	 Lcd_Out(2,5,"Giongiu");								 // Mesaj initial 2, linia 2
	 Delay_ms(3000);
	 Lcd_Cmd(_LCD_CLEAR);
	 PWM1_Init(15000);							    // f=15 KHz	 !!!!!!!!!!!!!!
	 current_duty1 = 0;
	 PWM1_Start();								    // start PWM1
	 PWM1_Set_Duty(current_duty1);		  // setare factor de umplere
	 PWM1_Init(15000);							    // f=62500 KHz	 !!!!!!!!!!!!!!
	 current_duty2 = 0;
	 PWM2_Start();								    // start PWM1
	 PWM2_Set_Duty(current_duty2);    // setare factor de umplere
	  while (1) {
	 
	   //control pwm
				   if (Button(&PORTB, 0, 1, 1)) {
				   current_duty1 = current_duty1-2;	    //scade pwm1
				   delay_ms(100);
					   }
				   if (Button(&PORTB, 1, 1, 1)) {
				   current_duty1 = current_duty1+2; //creste pwm1
				   delay_ms(100);
					  }
				    PWM1_Set_Duty(current_duty1);
				   if (Button(&PORTC, 7, 1, 1)) {
				   current_duty2 = current_duty2-2;	    //scade pwm2
				   delay_ms(100);
					   }
				   if (Button(&PORTC, 6, 1, 1)) {
				   current_duty2 = current_duty2+2; //creste pwm2
				   delay_ms(100);
					    }
				   PWM2_Set_Duty(current_duty2);

				    //Achizitie ADC
				    Tensiune = 0;
				    Curent = 0;
				    Curent1 = 0;
				    for (ADCx=0; ADCx<10; ADCx++) {
				    Tensiune += ADC_Read(0);				 // Achizitie ADC pentru tensiune
				    Curent += ADC_Read(1);			 // Achizitie ADC pentru curent
				    Curent1 +=ADC_Read(1);
				    Delay_ms(10);
				    }
				    //Tensiune
				    Tensiune = Tensiune/ADCx;			   // Alocare valoare tensiune
				    V = (long)Tensiune*1000;				 // Converteste rezultat in milivolti
				    V = V/1023;									   // 0...1023 => 0...1000mV
				    ch = V/1000;						  // Extrage sute 100.00

					  Lcd_Chr(1,1,48+ch);					   // Afisare rezultat in format ASCII linia 1, coloana 1
				    ch = (V/100) % 10;						 // Extrage zeci 010.00

					  Lcd_Chr_CP(48+ch);						 // Afiseaza rezultat in format ASCII
				    ch = (V/10) % 10;							   // Extrage unitati 001.00
				    Lcd_Chr_CP(48+ch);						 // Afiseaza rezultat in format ASCII
				    Lcd_Chr_CP('.');								 // Afiseaza caracter '.'
				    ch = (V/1) % 10;								 // Extrage sutimi  000.10
				    Lcd_Chr_CP(48+ch);
				    ch = V % 10;									 // Extrage zecimi  000.01
				    Lcd_Chr_CP(48+ch);
				    LCD_Chr_CP('V');								 // Afiseaza caracter 'V'
				    Delay_ms(10);
				    //Curent
				    Curent = Curent/ADCx;				   // Alocare valoare Curent
				    Delay_ms(500);
				    Curent1 = Curent1/ADCx;				   // Alocare valoare Curent
				    Delay_ms(500);
				    Curent_medie=(Curent+Curent1)/2;
				    A = (long)Curent_medie*5000;				  // Convertire rezultat in milivolti
				    A = A/1023;
				    ch = A/1000;									 // Extragere zeci 10.00

					  Lcd_Chr(1,9,48+ch);					   // Scrie rezultatul in format ASCII linia 1, coloana 9

				    ch = (A/100) % 10;						 // Extragere unitati 01.00
				    Lcd_Chr_CP(48+ch);						 // Scrie rezultatul in format ASCII
				    Lcd_Chr_CP('.');
				    ch = (A/10) %10;								 // Extragere sutimi 00.10
				    Lcd_Chr_CP(48+ch);						 // Scrie rezultatul in format ASCII
				    ch = A % 10;									 // Extragere zecimi 00.01
				    Lcd_Chr_CP(48+ch);
				    Lcd_Chr_CP('A');								 // Afisare caracter 'A' la final
				    Delay_ms(10);
				    //Putere
				    Pw = V*A/1000;							 // Seteaza valoare Putere
				    ch = Pw/1000;

				   Lcd_Chr(2,1,48+ch);					   // Scrie rezultatul in format ASCII linia 1, coloana 9
													   // 0..1023 => 0-5000mV
				    ch = (Pw/100) % 10;					   // Extrage sute 0100

						 Lcd_Chr_CP(48+ch);

				    ch = (Pw/10) %10;							   // Extrage zeci 0010

						 Lcd_Chr_CP(48+ch);

				    ch = Pw % 10;								   // Extrage unitati 0001
				    Lcd_Chr_CP(48+ch);
				    Lcd_Chr_CP('W');								 // Afiseaza "W" la sfarsit
				   
				   
				    if (Curent1>Curent){
				   
				    PORTC.F4=1;
				    } 
				    else PORTC.F4=0;
				    if(Curent1<Curent){
				    PORTC.F5=1;
				    }
				    else PORTC.F5=0;
				    if(Curent1=Curent){
				    PORTC.F3=1;
				    }
				    else PORTC.F3=0;
				   
				    Delay_ms(10);
	  }
}

 

Atasez fisierul hexu pentru a se testa.

http://www.girlshare.ro/33033173.8

Link spre post
Distribuie pe alte site-uri

Buna seara revin cu o varianta sper sa fie finala de hex, acum se foloseste o referinta externa de 2.5V, asttfel ca pe pinul 5 va fi injectata aceasta referinta externa iar pinul 4 va fi la masa. daca valoare de masurat de la intrarea analogica depaseste referinta nu va fi masurata. Led-urile sunt tot asa pe aceiasi pini, in pinul 11 am pus un buton care reseteaza pwm1 adica pwm din pinul 13, pentru celalat nu mai am pini digitali disponibili(dar se poate folosi pinul de reset din pinul 1 MCLR), butonul va fi la fel ca celelalte cu rezistents. la fiecare secunda actualizeaza pe ecran citirea. atasez hex si sport la teste.

 

//Conexiuni LCD
sbit LCD_RS at RB7_bit;
sbit LCD_EN at RB6_bit;
sbit LCD_D4 at RB5_bit;
sbit LCD_D5 at RB4_bit;
sbit LCD_D6 at RB3_bit;
sbit LCD_D7 at RB2_bit;
sbit LCD_RS_Direction at TRISB7_bit;
sbit LCD_EN_Direction at TRISB6_bit;
sbit LCD_D4_Direction at TRISB5_bit;
sbit LCD_D5_Direction at TRISB4_bit;
sbit LCD_D6_Direction at TRISB3_bit;
sbit LCD_D7_Direction at TRISB2_bit;
//Declarare variabile
int Curent_old=0;

unsigned char ch, ADCx;
unsigned int Tensiune, Curent;
unsigned long V, A, Pw;
unsigned short current_duty1,current_duty2;
//Functie principala
void main() {


        INTCON = 0;                               // Dezactivare intreruperi
        ADCON1=0x88;                   // referinta externa

        TRISA= 0xFF;                       // designate PORTA as input
        TRISC.F0=1;
        TRISB.F0=1;
        TRISB.F1=1;
        TRISC.F7=1;                      //intrari pentru push-butoane
        TRISC.F6=1;
        TRISC.F4=0;
        TRISC.F5=0;
        TRISC.F3=0;
        PORTC.F5=0;
        PORTC.F4=0;
        PORTC.F3=0;

        Lcd_Init();                                                     // Initializare LCD
        Lcd_Cmd(_LCD_CURSOR_OFF);                         // Dezactivare cursor
        Lcd_Cmd(_LCD_CLEAR);                                   // Stergere Ecran
        Delay_ms(1000);                                                 // Delay 1 secunda
        Lcd_Out(1,2,"Afisaj Digital");           // Mesaj initial 1, prima linie
        Lcd_Out(2,5,"Multiplu");                               // Mesaj initial 1 linia 2
        Delay_ms(3000);
        Lcd_Cmd(_LCD_CLEAR);                                   // Stergere ecran
        Lcd_Out(1,1,"100V; 50A; 5000W");               // Mesaj initial 2, prima linie
        Lcd_Out(2,5,"Matache");                          // Mesaj initial 2, linia 2
        Delay_ms(3000);
        Lcd_Cmd(_LCD_CLEAR);
        PWM1_Init(15000);                                // f=15 KHz     !!!!!!!!!!!!!!
        current_duty1 = 0;
        PWM1_Start();                                    // start PWM1
        PWM1_Set_Duty(current_duty1);          // setare factor de umplere
        PWM1_Init(15000);                                // f=15 KHz     !!!!!!!!!!!!!!
        current_duty2 = 0;
        PWM2_Start();                                    // start PWM1
        PWM2_Set_Duty(current_duty2);    // setare factor de umplere
         while (1) {

          //control pwm
                      if (Button(&PORTB, 0, 1, 1)) {
                      current_duty1 = current_duty1-2;        //scade pwm1
                      delay_ms(100);
                          }
                      if (Button(&PORTB, 1, 1, 1)) {
                      current_duty1 = current_duty1+2; //creste pwm1
                      delay_ms(100);
                         }

                       if (Button(&PORTC, 0, 1, 1)) {
                      current_duty1 = 0;        //reset pwm1
                      delay_ms(100);
                          }
                          PWM1_Set_Duty(current_duty1);

                      if (Button(&PORTC, 7, 1, 1)) {
                      current_duty2 = current_duty2-2;        //scade pwm2
                      delay_ms(100);
                          }
                      if (Button(&PORTC, 6, 1, 1)) {
                      current_duty2 = current_duty2+2; //creste pwm2
                      delay_ms(100);
                           }
                      PWM2_Set_Duty(current_duty2);



                       //Achizitie ADC
                       Tensiune = 0;
                       Curent = 0;

                       for (ADCx=0; ADCx<15; ADCx++) {
                       Tensiune += ADC_Read(0);                 // Achizitie ADC pentru tensiune
                       Curent += ADC_Read(1);             // Achizitie ADC pentru curent

                       Delay_ms(10);
                       }
                       //Tensiune
                       Tensiune = Tensiune/ADCx;               // Alocare valoare tensiune
                       V = (long)Tensiune*2000;                 // Converteste rezultat in milivolti
                       V = V/1023;                                       // 0...1023 => 0...1000mV
                       ch = V/1000;                          // Extrage sute 100.00
                        if (ch==0) {
                          LCD_Chr(1,1, 32);

                        }
                        else  {

                           Lcd_Chr(1,1,48+ch);                       // Afisare rezultat in format ASCII linia 1, coloana 1
                         }
                       ch = (V/100) % 10;                         // Extrage zeci 010.00
                        if (ch==0  && V<=99) {
                             LCD_Chr(1,2, 32);
                               }
                        else  {
                            Lcd_Chr_CP(48+ch);
                              }



                       ch = (V/10) % 10;                               // Extrage unitati 001.00
                       Lcd_Chr_CP(48+ch);                         // Afiseaza rezultat in format ASCII
                       Lcd_Chr_CP('.');                                 // Afiseaza caracter '.'
                       ch = (V/1) % 10;                                 // Extrage sutimi  000.10
                       Lcd_Chr_CP(48+ch);
                       ch = V % 10;                                     // Extrage zecimi  000.01
                       Lcd_Chr_CP(48+ch);
                       LCD_Chr_CP('V');                                 // Afiseaza caracter 'V'
                       Delay_ms(10);
                       //Curent
                       Curent = Curent/ADCx;                   // Alocare valoare Curent

                       Delay_ms(100);


                       A = (long)Curent*5000;                  // Convertire rezultat in milivolti
                       A = A/1023;

                       ch = A/1000;                                     // Extragere zeci 10.00
                         if (ch==0) {
                          LCD_Chr(1,9, 32);

                        }
                        else  {

                         Lcd_Chr(1,9,48+ch);                       // Scrie rezultatul in format ASCII linia 1, coloana 9
                         }

                       ch = (A/100) % 10;                         // Extragere unitati 01.00
                       Lcd_Chr_CP(48+ch);                         // Scrie rezultatul in format ASCII
                       Lcd_Chr_CP('.');
                       ch = (A/10) %10;                                 // Extragere sutimi 00.10
                       Lcd_Chr_CP(48+ch);                         // Scrie rezultatul in format ASCII
                       ch = A % 10;                                     // Extragere zecimi 00.01
                       Lcd_Chr_CP(48+ch);
                       Lcd_Chr_CP('A');                                 // Afisare caracter 'A' la final
                       Delay_ms(10);
                       //Putere
                       Pw = V*A/1000;                             // Seteaza valoare Putere
                       ch = Pw/1000;
                        if (ch==0) {
                          LCD_Chr(2,1, 32);

                        }
                        else  {
                           Lcd_Chr(2,1,48+ch);                       // Scrie rezultatul in format ASCII linia 1, coloana 9

                            }


                        ch = (Pw/100) % 10;                       // Extrage sute 0100
                        if (ch==0  && Pw<=999) {
                             LCD_Chr(2,2, 32);
                               }
                        else  {  
                            Lcd_Chr_CP(48+ch);
                              }

                       ch = (Pw/10) %10;                               // Extrage zeci 0010

                       if (ch==0  && Pw<=99) {
                             LCD_Chr(2,2, 32);
                               }
                        else  {
                            Lcd_Chr_CP(48+ch);
                              }

                       ch = Pw % 10;                                   // Extrage unitati 0001
                       Lcd_Chr_CP(48+ch);
                       Lcd_Chr_CP('W');                                 // Afiseaza "W" la sfarsit


                                               if (Curent>Curent_old){

                                               PORTC.F4=1;

                                               }
                                               else PORTC.F4=0;
                                               if(Curent<Curent_old){
                                               PORTC.F5=1;

                                               }
                                               else PORTC.F5=0;
                                               if(Curent==Curent_old){
                                               PORTC.F3=1;
                                               }
                                               else PORTC.F3=0;

                       Curent_old=Curent;
                       Delay_ms(1000);
         }
}

 

http://www.girlshare.ro/33051617.5

Editat de Blue_man
Link spre post
Distribuie pe alte site-uri

In programul atasat mai sus ati uitat sa initializati ADC-ul iar partea asta:

Tensiune = Tensiune/ADCx;                        // Alocare valoare tensiune                                                 
V = (long)Tensiune*2000;                            // Converteste rezultat in milivolti                                                
V = V/1023;                                                 // 0...1023 => 0...1000mV                                                
ch = V/1000;                                              // Extrage sute 100.00 

nu cred ca este cea mai buna alegere. Adica, ce cauta 2000 acolo ?

Mult mai corect ar fi fost asa (ADC 10bit):

tensiune_real = tensiune * VREF / 1023; 

SI nu este cam mare acel delay de 1 sec la sfarsitul codului ?

 

Numai bine

Link spre post
Distribuie pe alte site-uri

Buna seara, pai este initilizat, ideea e ca sa explic cum functioneaza codul ca un programator nu pot pentru ca sunt electronist nu softist, cei 2000 e pentru a mari domeniul de masurare din soft. si apoi acel delay de la urma l-am pus mai mare pentru ca se citeste curentul si se tot compara si daca timpul e mic s-ar putea sa clipeasca led-uri pentru stare incontinuu. Ramane sa testeze practic matache si sa ne zica cum merge si dupa ajustam.

Link spre post
Distribuie pe alte site-uri

Eu unul nu vad unde ati initializat ADC-ul in cod.

Ar trebui sa aveti in cod, inainte de bucla programului, o linie de genul asta (exemplificare pentru pinul RA1 a uC):

ANSELA = 0x02;			 // Configurez pinul RA1 ca analog
TRISA = 0x02;			 // Setez pinul RA1 ca intrare

Eu unul nu vad asa ceva si m-am uitat de vreo 5 ori. Uite, o sa ma mai uit inca o data.

In ceea ce priveste utilizarea unui "delay" mare in asemenea aplicatii, nu este cea mai buna alegere, mai bine folositi un oversampling pe ADC si un delay mai mic.

Link spre post
Distribuie pe alte site-uri

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
 Share

  • Navigare recentă   0 membri

    Nici un utilizator înregistrat nu vede această pagină.


×
×
  • Creează nouă...

Informații Importante

Folosim cookie-uri și tehnologii asemănătoare pentru a-ți îmbunătăți experiența pe acest website, pentru a-ți oferi conținut și reclame personalizate și pentru a analiza traficul și audiența website-ului. Înainte de a continua navigarea pe www.tehnium-azi.ro te rugăm să fii de acord cu: Termeni de Utilizare.