Sari la conținut
ELFORUM - Forumul electronistilor

Volt/ampermetru trifazat cu PIC16F877A


Postări Recomandate

Salutare am o mica problema cu un program pentru PIC16F877A se reseteaza simularea in Proteus la citirea ultimului curent si nu stiu de ce. Daca scot citirea de curent pe ultima faza nu se mai reseteaza.In mikro C nu am nici o eroare.Daca aveti ceva ideii?

 

// LCD module connections

sbit LCD_RS at RB2_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 TRISB2_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;

// End LCD module connections

 

unsigned int Tensiune,curent1,curent2,curent_medie;

unsigned long u,i;

 

unsigned char ch;

 

void main()

 

 

{

TRISA = 0xFF; // designate PORTA as input

INTCON = 0; // Disable all interrupts

IRP_bit = 0 ;

 

 

 

Lcd_Init(); // Initialize LCD

Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off

Lcd_Cmd(_LCD_CLEAR); // Clear display

Delay_ms(100);

LCD_Out(1,3,"VOLT/AMPERMETRU");

LCD_Out(3,3,"**By CsOnGoRe**");

Delay_ms(1500);

 

Lcd_Cmd(_LCD_CLEAR);

LCD_Out(1, 8,"R=");

LCD_Out(2, 8,"R=");

LCD_Out(3, 1,"S=");

LCD_Out(4, 1,"S=");

LCD_Out(3, 14,"T=");

LCD_Out(4, 14,"T=");

 

 

while (1) {

 

 

// Citire Tensiune 1

Tensiune=ADC_read(0); // get ADC value for U from channel 1

u=(long)Tensiune*3500; // covert adc reading to milivolts

u=u/1023; // 0..1023 -> 0-3500mV

 

ch=u/1000; // extract 10.00 U digit

if (ch==0)

{

LCD_Chr(1,11, 32); // write empty space if digit is 0

}

else

{

LCD_Chr(1,11,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

 

ch=(u/10) %10; // extract 00.10 U digit

LCD_Chr_CP(48+ch); // write ASCII digit at cursor point

 

 

LCD_Chr_CP('V'); // write 'V' at cursor point

 

//Curent 1

curent1=ADC_read(1); // get ADC value for U from channel 1

Delay_ms(50);

curent2=ADC_read(1); // get ADC value for U from channel 1

Delay_ms(50);

curent_medie=(curent1+curent2)/2;

 

i=(long)curent_medie*2000; // covert adc reading to milivolts

i=i/1023; // 0..1023 -> 0-2000mV

ch=i/10000; // extract 10.00 U digit

if (ch==0)

{

LCD_Chr(2,10, 32); // write empty space if digit is 0

}

else

{

LCD_Chr(2,10,48+ch); // write ASCII digit at 1st row, 2nd column

}

 

ch=(i/1000) %10; // extract 01.00 U digit

LCD_Chr_CP(48+ch);

 

ch=(i/100) %10; // extract 00.10 U digit

LCD_Chr_CP(48+ch); // write ASCII digit at cursor point

ch=i %10; // extract 00.01 U digit

LCD_Chr_CP(48+ch); // write ASCII digit at cursor point

 

LCD_Chr_CP('A');

 

// Citire Tensiune 2

Tensiune=ADC_read(2); // get ADC value for U from channel 1

u=(long)Tensiune*3500; // covert adc reading to milivolts

u=u/1023; // 0..1023 -> 0-3500mV

 

ch=u/1000; // extract 10.00 U digit

if (ch==0)

{

LCD_Chr(3,4, 32); // write empty space if digit is 0

}

else

{

LCD_Chr(3,4,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

 

ch=(u/10) %10; // extract 00.10 U digit

LCD_Chr_CP(48+ch); // write ASCII digit at cursor point

 

 

LCD_Chr_CP('V'); // write 'V' at cursor point

 

//Curent 2

curent1=ADC_read(3); // get ADC value for U from channel 1

Delay_ms(50);

curent2=ADC_read(3); // get ADC value for U from channel 1

Delay_ms(50);

curent_medie=(curent1+curent2)/2;

 

i=(long)curent_medie*2000; // covert adc reading to milivolts

i=i/1023; // 0..1023 -> 0-2000mV

ch=i/10000; // extract 10.00 U digit

if (ch==0)

{

LCD_Chr(4,3, 32); // write empty space if digit is 0

}

else

{

LCD_Chr(4,3,48+ch); // write ASCII digit at 1st row, 2nd column

}

 

ch=(i/1000) %10; // extract 01.00 U digit

LCD_Chr_CP(48+ch);

 

ch=(i/100) %10; // extract 00.10 U digit

LCD_Chr_CP(48+ch); // write ASCII digit at cursor point

ch=i %10; // extract 00.01 U digit

LCD_Chr_CP(48+ch); // write ASCII digit at cursor point

 

LCD_Chr_CP('A');

 

// Citire Tensiune 3

Tensiune=ADC_read(4); // get ADC value for U from channel 1

u=(long)Tensiune*3500; // covert adc reading to milivolts

u=u/1023; // 0..1023 -> 0-3500mV

 

ch=u/1000; // extract 10.00 U digit

if (ch==0)

{

LCD_Chr(3,17, 32); // write empty space if digit is 0

}

else

{

LCD_Chr(3,17,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

 

ch=(u/10) %10; // extract 00.10 U digit

LCD_Chr_CP(48+ch); // write ASCII digit at cursor point

 

 

LCD_Chr_CP('V'); // write 'V' at cursor point

 

 

//Curent 3

curent1=ADC_read(5); // get ADC value for U from channel 1

Delay_ms(50);

curent2=ADC_read(5); // get ADC value for U from channel 1

Delay_ms(50);

curent_medie=(curent1+curent2)/2;

 

i=(long)curent_medie*2000; // covert adc reading to milivolts

i=i/1023; // 0..1023 -> 0-2000mV

ch=i/10000; // extract 10.00 U digit

if (ch==0)

{

LCD_Chr(4,16, 32); // write empty space if digit is 0

}

else

{

LCD_Chr(4,16,48+ch); // write ASCII digit at 1st row, 2nd column

}

 

ch=(i/1000) %10; // extract 01.00 U digit

LCD_Chr_CP(48+ch);

 

ch=(i/100) %10; // extract 00.10 U digit

LCD_Chr_CP(48+ch); // write ASCII digit at cursor point

ch=i %10; // extract 00.01 U digit

LCD_Chr_CP(48+ch); // write ASCII digit at cursor point

 

LCD_Chr_CP('A');

}}

Link spre comentariu
  • Răspunsuri 1
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

Zile populare

Top autori în acest subiect

Nu ai oferit toate detaliile cat sa fie clar ce si cum.

 

Dar,

1. Ce face watchdog-ul? Cum e setat? Daca pui asta face la fel?

LCD_Chr_CP('V'); // write 'V' at cursor point

  asm
    clrwdt
  end;

//Curent 3

2. Contrar credintei larg raspandite pe Internet ca sunt 1023 valori, de la 0 la 1023 sunt 1024 valori, e mai corect asa:

u=u/1024; // 0..1023 -> 0-3500mV

3. ADC_Read(x) este echivalentul lui:

ADC_Init()
ADC_Get_Sample(x)

De ce sa tot initializezi ADC-ul la fiecare citire? Stiu ca aici nu conteaza viteza de executie, dar poate alta data...

Deci, se scrie asa:

void main()
{
ADC_Init()

while (1) {
// Citire Tensiune 1
Tensiune=ADC_Get_Sample(0); // get ADC value for U from channel 1

4. Vad ca faci medieri de citiri cu intarzieri intre citiri. Felul cum o faci (si o afisezi) iti va rezulta in valori care clipesc pe ecran. Da, la cate sute de ms adunate ai acolo pentru o executie de ciclu complet, au sa clipeasca.

Ai putea opta pentru supraesantionare (eu nu te pot ajuta in MikroC, caci lucrez in Mikrobasic, dar Florin are aici codul https://forum.mikroe.com/viewtopic.php?t=20393).

Altfel, faci o bucla For si citesti n valori (sa zicem 50-100). Doar 2 valori la 50ms mi se pare prea intamplator.

 

In orice caz, ca sa eviti clipirea, va trebui sa citesti ADC-ul si sa vezi daca noua valoare difera de precedenta (alta variabila va fi buffer-ul precedentei). Daca ai aceeasi valoare nu mai scrii pe ecran. Astfel ai sa ai update de ecran doar daca valoarea variaza intradevar.

 

Foloseste butonul CODE (ala de arata <>) in editorul full. Se intelege mai bine codul.

 

Opinie personala: pune totul pe un breadboard, cine stie ce setari ai in simulator.

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