//Autor: Luis Alberto Vargas Tijerino.
//Nicaragua, 15 de Junio de 2010.
//Seudónimo: Bigluis
#include <18f4550.h> //pic a utilizar
#DEVICE ADC=10
#include <Puertos.c>
#fuses XT,NOMCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,NOVREGEN,NOPBADEN // fuse con cristal 48Mhz
#use delay (clock=48M) //Fosc=48Mhz
#define LCD_DATA4 PIN_B0
#define LCD_DATA5 PIN_B1
#define LCD_DATA6 PIN_B2
#define LCD_DATA7 PIN_B3
#define LCD_ENABLE_PIN PIN_B4
#define LCD_RS_PIN PIN_B5
#define LCD_RW_PIN PIN_B6
#include <lcd.c> //libreria manejo lcd
int8 N=0; //N = Numero de muestras
int16 V=0,I=0; //Voltaje y Corriente instantaneos
int16 Vmax=0,Imax=0; //Voltaje y corriente Maxima.
int32 Vrms=0,Irms=0; //Voltaje y Corriente RMS.
#INT_TIMER0
void TIMER0_ISR(void){
delay_cycles(2);
set_timer0(73);
set_adc_channel(3); //Seleccionamos el Canal para medir voltaje
read_adc(ADC_START_ONLY); //Iniciamos la conversion AD del voltaje
Vrms+=_mul(V,V); //Realizamos la sumatoria de los cuadrados de V
if(Vmax<V)Vmax=V;
V=read_adc(ADC_READ_ONLY); //una vez terminada laconversion AD del voltaje lo guardamos
set_adc_channel(2); //Realizamos la sumatoria de los cuadrados de I
read_adc(ADC_START_ONLY); //Iniciamos la conversion AD de la corriente
Irms+=_mul(I,I); //Realizamos la sumatoria de los cuadrados de I
if(Imax<I)Imax=I; //obtenermos el valor de la corriente pico
I=read_adc(ADC_READ_ONLY); //Una vez terminada la conversion AD de la
//corriente lo guardamos
N++;
}
//Funcion para calcular la raiz cuadrada de un numero
int32 raiz(int32 x){
int32 r = x, t = 0;
if(!x)return 0;
if(x<4)return 1;
while (t != r){
t = r;
r = (x/r + r)/2;
}
return r;
}
void main(void){
PORTA=0;
PORTB=0;
PORTC=0;
PORTD=0;
PORTE=0;
TRISA=3; //Solo RA0 y RA1 como entrada los demas como salida
TRISC=0; //PORTC como salida.
TRISD=0; //PORTD como salida.
TRISE=0; //PORTE como salida
TRISB=0; //PORTB como salida
lcd_init(); //Iniciamos el LCD
lcd_putc("\fVe= Vp=\nIe= Ip="); //Escribimos los caracteres en el LCD
enable_interrupts(GLOBAL|INT_TIMER0); //Habilitamos Interrupciones Globales y TMR0
set_timer0(75); //ponemos TMR0=75 para que pasen 256-75 conteos
setup_timer_0(T0_8_BIT|T0_DIV_4); //Seteamos el TMR0 a 8 bits y relacion 4:1
//Para que transcurran 65.083us en cada desborde
setup_adc_ports( VSS_VDD|AN0_TO_AN3 );//Ponemos Vref+=Vss y Vref-=Vdd, y AN0 a AN3 como analogicas
ADCON2=0b10001000|ADC_CLOCK_DIV_64; //Seleccionamos Tad=64*Tosc y Tacqt=2Tad.
ADON=1; //Encendemos el ADC
setup_comparator(A0_A3_A1_A2_OUT_ON_A4_A5);
while(true){
if(N==255){ //Si se han tomado 255 muestras
disable_interrupts(INT_TIMER0); //Desabilitamos la Interrupcion del TMR0
Vrms=raiz(Vrms/256); //Sacarle raiz cuadrada a la sumatoria de las muestras de Voltaje
Irms=raiz(Irms/256); //y a las de Corriente
printf(lcd_putc,"%Lu",Irms); //Mostramos en pantalla la Corriente RMS
lcd_gotoxy(11,2); //Ubicamos el cursor en la posicion 11,2
printf(lcd_putc,"%Lu",Imax); //Mostramos en pantalla la Corriente Pico
lcd_gotoxy(4,1); //Ubicamos el cursor en la posicion 4,1
printf(lcd_putc,"%Lu",Vrms); //Mostramos en pantalla el Voltaje RMS
lcd_gotoxy(11,1); //Ubicamos el cursor en la posicion 11,1
printf(lcd_putc,"%Lu",Vmax); //Mostramos en pantalla el Voltaje Pico
lcd_gotoxy(4,2); //Ubicamos el cursor en la posicion 4,2
Vrms=0;Irms=0;Imax=0;Vmax=0; //Inciamos los valores para iniciar la medicion
enable_interrupts(INT_TIMER0); //Habilitamos la interrupcion del TMR0
}
}
}