Buenas gente, haber si podeis ayudarme!!
Deseo generar un duty cycle dependiendo de la velocidad que queremos que gire, es decir, se introduce la velocidad en r.p.m. y se transmite via serie, entonces el PIC generara un PWM dependiendo de esta velocidad, la regla de tres es la siguiente
(velocidad*100)/3900.0=el resultado es el duty cycle que queremos; luego logicamente nos daria una velocidad, que muy dificilmente coincidiria con la deseada, entonces habria que sacar el error y multiplicarlo por una constante y enviar de nuevo otro duty, en funcion del error y la constante (en resumen un lazo Proporcional)!!!
Pero mi primera duda es la primera, la segunda ya se intentaria solucionr mas adelante!!
Aqui os mando lo que he hecho, pero no funciona correctamente!!!
Creo que es por alguna definicion de variables, pero si mem pudierais ayudar mejor!!
codigo:
#include <16f873.h>
#device adc=10
#include <stdlib.h>
#fuses XT, NOPROTECT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=N, bits=8)
#zero_ram
int opcion;
int i;
int16 duty;
int16 pulsos;
int16 interrupcion;
int16 velocidad;
int16 recibido;
int reset;
float dato;
//float const resolucion=5.0/1024.0;
int16 value;
char string[10];
//float corriente;
//float sumacorriente;
//float corrientemedia;
int habilitacion;
//int convertidor;
int32 tiempoReal;
int32 Tiempo;
#int_RTCC //se determina la funcion de la interrupcion
RTCC_isr()
{
if(habilitacion==1)
{
tiempoReal++; //se suma a una variable que computa el tiempo transcurrido
pulsos=get_timer1(); //se obtiene el valor del contador timer1
interrupcion++; //se suma en uno el flag de interrupcion
if(interrupcion==100) //cuando se llega a 100, es decir, 1 segundo, 100*10ms=1000ms=1seg; se introduce en la funcion
{
velocidad=pulsos*15; //sacamos la velocidad con una regla de tres
printf("%lu r.p.m.
",velocidad); //tambien puerto serie
/* ************ convertidor analógico *****************
for(i=0;i<10;i++)
{
set_adc_channel( 0 ); //el canal 0, entrada AN0
delay_us(160); //delay 1us
value = read_adc();
dato = value*resolucion;
corriente=dato; //una R=0,005 --> V=IR; I=V/R; corriente=dato/R=dato/0.005=corriente
sumacorriente=sumacorriente+corriente;
corrientemedia=sumacorriente/10.0;
}
printf("%1.3f A
",corrientemedia);*/
printf("%lu duty",duty);
Tiempo=tiempoReal*0.01;
printf("%lu segundos", Tiempo);
//corrientemedia=0;
//sumacorriente=0;
interrupcion=0; //se inicializa de nuevo el flag de interrupcion para que vuelva a contar 100 interrupciones
set_timer1(0); //se inicializa tambien el contador
set_rtcc(178); //se introduce de nuevo el valor del temporizador de interrupcion
}
else
{
set_rtcc(178);
set_timer1(pulsos);
}
}
}
main()
{
//set_tris_b(0x00); //si se habilita no se puede sacar el PWM 1
enable_interrupts(GLOBAL); //se habilitan interrupcion general
enable_interrupts(INT_RTCC); //habilita int. del timer0
setup_timer_0 ( RTCC_INTERNAL | RTCC_DIV_128); //se configura el timer0 como temporizador y una báscula de 128
set_rtcc(178); //10ms -> 10000us -> 10000/128=78 -> 255-78=177 se le inserta el tiempo a contar, se suma uno
duty = 0; //se inicializa el duty en cero
setup_ccp1(CCP_PWM); //Se habilita el pwm 1
setup_timer_2(T2_DIV_BY_16, 99, 1); //Se establece el valor de la frecuencia de 620Hz(1,6 ms el periodo) para el PWM
set_pwm1_duty(duty); //se manda el duty al PWM
//setup_adc_ports( ALL_ANALOG ); //todo el puerto analogico
//setup_adc( ADC_CLOCK_INTERNAL ); //convertidor con clock interno
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1); //se configura el timer1 como contador, de pulsos externos y de báscula 1
set_timer1(0); //se inicializa el contador en cero
interrupcion=0; //se inicializan los flags
habilitacion=0;
//convertidor=0;
tiempoReal=0;
Tiempo=0;
while(true)
{
//el programa principal que estaria haciendo, esperando a la interrupcion del timer0
//while(!kbhit());
gets(string); //Guarda el Duty (0-255) en la variable string aunque solo necesitamos hasta 100
//y espera un RETURN (Ctrl 13)
opcion=atoi(string); //Usa la función ATOI para pasarlo a entero
switch (opcion) {
case 3: //recibido duty cycle
while(true)
{
gets(string);
recibido=atol(string);
if(recibido==200 || recibido==201);
reset_cpu();
else
duty=recibido;
set_pwm1_duty(duty); //El caracter ascii recibido pasado a entero
//establecido como ciclo de trabajo
habilitacion=1; //flag pata habilitar el contaje de los pulsos de velocidad del optoacoplador
}
break;
case 4: //recibido velocidad
while(true)
{
gets(string);
recibido=atol(string);
if(recibido==200 || recibido==201)
reset_cpu();
else
duty=(recibido*100.0)/3900.0;
set_pwm1_duty(duty);
habilitacion=1;
}
break; }
}
}
PD: en el codigo estoy intentando tambien tener la opcion de poder controlar con la velocidad o con el duty cycle; por eso la sentencia CASE!! Dpendiendo de lo que le llegue por el puerto serie (un 3 o un 4)!!
Muchas gracias y saludos!!!