Buenas,
Me presento, soy nuevo en el foro, y aunque llevo un par de meses que os visito nunca había escrito ningún post. Tengo un problema: a principios de la semana que viene tengo que entregar el proyecto final de carrera y no consigo programar el PIC16F877-20/p (el de 40 pines).
A continuación descrivo los problemas y adjunto el código que he hecho. Por cierto, los comentarios no estan muy bien hechos...
1. ADCs. Necesito leer 3 señales analógicas, y diría que lo consigo pero creo que tarda mucho, ya que para realizar el programa después de leer estas señales me tarda unos 40 segundos... Creo que el ADC está mal configurado.
#include <16f877A.h>
#device ADC=8 // ADC devuelven 8 bits
#fuses NOPROTECT,NOCPD,NOLVP,NOWDT,XT,PUT //Configuracion de timers, reloj, proteccion de datos...
#use fast_io (A) //Input y output sin reprogramar los pines, como lo haria el #use standard_io
#use fast_io (B)
#use delay(clock=20000000) //Reloj de 4MHz
#use standard_io(A)
#use standard_io(B)
#use standard_io(C)
#use standard_io(D)
#use standard_io(E)
#int_rtcc //rutina que até a interrupció
int8 sensor1, sensor2, consigna, sortida; //Variables para el resultado de la conversión AD
float sens1d, sens2d, consd;
float K1, K2, K3, vh1pt, vh2pt, conspt, vpt;
float incvh1, incvh2, incvcons, incK1, incK2, incK3, invconsfinal, out1, inputact=0, integrador;
float inputant=0, integant=0, out2, outfinal;
void main()
{
//Se activa el ADC y se selecciona el canal RA0/AN0. Frecuencia de trabajo Fosc/32
set_tris_b(0x00); //portb como salida(RB0,las demas desactivadas)
set_tris_e(0x07);
set_tris_d(0x00);
disable_interrupts(GLOBAL); //todas las interrupciones desactivadas
output_b(0x00);
output_d(0x00);
setup_adc(ADC_CLOCK_DIV_16); //Ajusta frecuencia de muestreo del ADC
setup_adc_ports(AN0);
K1=-0.443;
K2=-2.129;
K3=-22.76;
vh1pt=3.06;
vh2pt=3.95;
conspt=vh2pt;
vpt=7.8;
//PROGRAMA PRINCIPAL
while(1)
{
set_adc_channel(0); //Selección del canal 0 (RA0)
delay_us(10); //Temporiza 10uS
sensor1=read_adc(); //Inicia la conversión y lee el resultado
sens1d=sensor1;
set_adc_channel(1); //Selección del canal 0 (RA0)
delay_us(10); //Temporiza 10uS
sensor2=read_adc(); //Inicia la conversión y lee el resultado
sens2d=sensor2;
set_adc_channel(2); //Selección del canal 0 (RA0)
delay_us(10); //Temporiza 10uS
consigna=read_adc(); //Inicia la conversión y lee el resultado
consd=consigna;
incvh1=sens1d-vh1pt;
incvh2=sens2d-vh2pt;
incvcons=consd-conspt;
invconsfinal=incvh2-incvcons;
incK2=K2*incvh1;
incK3=K3*incvh2;
out1=incK1+incK2;
inputact=invconsfinal;
integrador=integant+((inputact+inputant)*(1/2));//1=3.138 si interrupció
inputant=inputact;
integant=integrador;
out2=invconsfinal*K1*integrador;
outfinal=out2+out1+vpt;
sortida=outfinal*256/10;
output_b(sortida);
}
}
De esta manera cre que hacen algo. Si los configuro como he visto en numerosos ejemplos me dice que no reconoce AN1 y AN2:
setup_adc_ports(AN0); //RA0 entrada analógica
set_adc_channel(0); //Selección del canal 0 (RA0)
delay_us(10); //Temporiza 10uS
sensor1=read_adc(); //Inicia la conversión y lee el resultado
sens1d=sensor1;
setup_adc_ports(AN1); //RA1 entrada analógica
set_adc_channel(1); //Selección del canal 1 (RA1)
delay_us(10); //Temporiza 10uS
sensor2=read_adc(); //Inicia la conversión y lee el resultado
sens2d=sensor2;
setup_adc_ports(AN2); //RA2 entrada analógica
set_adc_channel(2); //Selección del canal 2 (RA2)
delay_us(10); //Temporiza 10uS
consigna=read_adc(); //Inicia la conversión y lee el resultado
consd=consigna;
2. Interrupción: Todo mi porograma debería estar dentro de una interrupción, ya que lo quiero "ejecutar" cada 5 segundos:
Con el código que pongo a continuación obtengo una interrupción cada 3,138 segundos aproximadamente y lo que hago es cambiar de estado el puerto_b, cosa que veo imposible con un TIMER0 de 8 bits y el valor de preescaler que le doy:
#include <16f877.h>
#fuses NOPROTECT,NOCPD,NOLVP,NOWDT,XT,PUT //Configuracion de timers, reloj, proteccion de datos...
#use fast_io (A) //Input y output sin reprogramar los pines, como lo haria el #use standard_io
#use fast_io (B)
#use delay(clock=20000000) //Reloj de 4MHz
#use standard_io(A)
#use standard_io(B)
#use standard_io(C)
#use standard_io(D)
#use standard_io(E)
byte puerto_b;
#int_rtcc //rutina que até a interrupció
void interrupcion()
{
puerto_b=~puerto_b;
output_b(puerto_b);
set_RTCC(0);
}
void main()
{
set_tris_b(0x00);
puerto_b=0x00;
output_b(puerto_b);
setup_counters (RTCC_INTERNAL, RTCC_DIV_4); //programació timer0
set_RTCC(0);
enable_interrupts(INT_RTCC); // Habilita interrupcion timer0.
enable_interrupts(GLOBAL); // Habilita todas las interrupciones.
while(1)
{
}
}
Sé que hago algo mal, que no configuro bien el timer o lo que sea, lo he probado con el TIMER1 que es de 16 bits y tampoco consigo que funcione...
3. Integrador: Quien tenga conocimientos de regulación automàtica lo conocerà mejor. La fórmula bàsica del integrador es:
integrador=integant+((inputact+inputant)*(T/2));
donde:
integant=integrador anterior
inputact=entrada actual
inputant=entrada anterior
T=periodo que pasa entre que hace el cálculo hasta que lo vuelve a realizar.
El problema que tengo es que no sé como encontrar el valor de T... Si lo hiciera dentrro de una interrupción de 5 segundos pues T sería 5 segundos aproximadamente.
Alguien me puede ayudar?
Gracias de antemano.
Saludos!