#include <proyecto_0.h>
#include <lcd3.c>
#include <stdlib.h> //librerias para trabajar con el protocolo RS232
#include <input.c>
#include <string.h>
int16 a=0,b=0;
#INT_TIMER2
void TIMER2_isr(void)
{
a=get_timer0();
printf(lcd_putc,"\fT1= %lu",a);
b=get_timer1();
printf(lcd_putc,"\nT2= %lu",b);
set_timer0(0);
set_timer1(0);
set_TIMER2(0);
}
void main()
{
setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_1);
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DIV_BY_16,255,16);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
lcd_init();
lcd_putc("\fReady...\n");
while(TRUE)
{
}
}void TIMER2_isr(void)
{
delay_ms(30);
a=get_timer0();
a=a*4;
b=get_timer1(); //CONT Pulsos
b=b*4;
set_timer0(0);
set_timer1(0);
set_TIMER2(0);
}
void TIMER2_isr(void)
{
delay_ms(30);
a=get_timer0();
b=get_timer1(); //CONT Pulsos
set_timer0(0);
set_timer1(0);
}
void main()
{
// Configuracioin de los temporizadores y contadores
setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_1|RTCC_8_bit); //65,5 ms overflow
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1); //65,5 ms overflow
setup_timer_2(T2_DIV_BY_16,195,16); //50,0 ms overflow
....
.....
2 problemas.
Si usas el CCP que usa el Timer2, vos NO debes ponerlo a 0, lo hace solo el CCP.
Si usas funciones como printf, divisiones que ocupan demasiado tiempo, cuando estas en una interrupcion hace que no pueda entrar de nuevo si es que ocurre una nueva interrupcion.
Entonces si usas el tiempo del Timer2 para tener una referencia de cuantos pulsos entraron, ya cuando entre de nuevo puede que pasen 2, 3 o mas veces la interrupcion del Timer2.
De esa forma es imposible tener una lectura correcta. Ya que vos esperas que tome la lectura del timer cada interrupcion del Timer2, pero lo que en realidad ocurre es que seguramente gracias a los printf y divisiones termine pasando 2 o mas interrupcioens del Timer2.
Si la PC es quien va a hacer de PID entonces tampoco multipliques por 3 o dividas por 10 en el micro, dejalo que lo haga la PC.
Te voy a dar un ejemplo espero que mas sencillo de entender.
-------------------------------------------------
Ahora vamos a los tiempos que posee tu programa
Timer2 tiene un OV cada 50ms
Y encima necesitas 30ms mas para poder obtener buenos valores en los demas Timers.
Por que no directamente implementas un contador y que cada 100ms proceda a tomar los valores de los Timers 0 y 1.
El Timer0 podes contar hasta 511 ( si pensas en el flag de interrupcion como un noveno bit ) Y te aseguras de que nunca supere este valor con los preescalers.
El Timer1 no vas a tener problemas.
Que velocidades va a tener y cuantos pulsos por revolucion van a entrar en cada caso ?
La duda que me queda, es que haciendo la conversión directa de de RPM a Frecuencia, la frecuencia me da con decimales y el pic en las pruebas solo mide frecuencias enteras entonces no se si al implementar esto sea una traba o deba hacer algún ajuste a la lectura.
CitarLa duda que me queda, es que haciendo la conversión directa de de RPM a Frecuencia, la frecuencia me da con decimales y el pic en las pruebas solo mide frecuencias enteras entonces no se si al implementar esto sea una traba o deba hacer algún ajuste a la lectura.
Y cual es el problema?
Vos estarias tomando lecturas cada 100ms.. Eso te va a dar RPM/20. Enviale eso a la PC y que la PC se encargue. Vos dijiste que la PC deberia hacer el control de velocidad, entonces que sea la PC que se encargue de hacer los calculos completos.
Es decir en tu PIC solo tomarias esos datos y lo enviarias y listo. Se termino el trabajo del PIC.
#INT_RDA
void RDA_isr(void)
{
k = getc();
if(k!=0)
if(k=='1')
{
set_pwm1_duty(10);
#INT_RDA
void RDA_isr(void)
{
k = getc();
x = atol(k);
set_pwm1_duty(x);
Lo que digo del Timer0 es que tenes 8 bits, pero tambien tenes un flag de interrupcion que se pone a 1 cuando la cuenta supera los 255.
Cuando se produce el overflow se activa el flag, no va a entrar a la interrupcion si es que esta desactivada la interrupcion. Pero el flag sigue activandose en ese caso.
Supongamos que comenzas con estos valores:
TMR0 = 0
TMR0IF = 0
Contas hasta llegar a 255 y te queda asi:
TMR0 = 0xFF
TMR0IF = 0
Al pasar a 0x00 se activa el flag, podrias pensar que en realidad el valor es de 0x100
TMR0 = 0x00
TMR0IF = 1
Asi hasta llegar a 0xFF nuevamente, que tendrias el valor 0x1FF ( 511 ) si tomas el bit del flag como el bit numero 9..
Te decia que tenes que preocuparte de que JAMAS pase de del valor 0x1FF ya que volveria a 0x100, es decir no podes saber cuantas veces entro.
---------------------
La otra si queres complicartela un poco mas o tal ves simplificartela es activar la interrupcion del TMR0.
Y en la interrupcion del Timer0 poner un contador. Entonces cuando vayas a tomar los valores el contador serian tus 8 bits de mayor peso y los 8 del TMR0 los de menor peso. Como si fuera uno de 16bits. Precauciones extras debes tener con esto obviamente.
---------------------
De ultima no te compliques y asegurate de que no se active el flag del TMR0.
solo que los valores que envia el PC pueden ser desde -255 hasta 255
void RDA_isr(void)
{
k = getc();
if(k == 'i') // Aqui verifico si es motor izquierdo
{
if(k != 0x0D)
{
// Aca todavia no esta completo y siguen llegando valores
RX_Buffer[i] = k;
i++;
// Proteccion de que no supere los 10 lugares que posee el array RX_Buffer (Recordando de dejar uno al ultimo siempre, por eso 4)
if(i >= 9)
{
.............
if(k == 'd') // Aqui verifico si es motor derecho
{
if(k != 0x0D)
{
if(k != 0x0D)
{
if(k=='i')
{
// Aca todavia no esta completo y siguen llegando valores
RX_Buffer[i] = k;
i++;
// Proteccion de que no supere los 10 lugares que posee el array RX_Buffer (Recordando de dejar uno al ultimo siempre, por eso 9)
if(i >= 9)
....................
Citarsolo que los valores que envia el PC pueden ser desde -255 hasta 255
No entiendo ya que la carga del duty si o si es sin signo. A no ser que esa sea la diferencia de lo que esta puesto. Bueno eso lo vas a ver vos.
Primero que nada no uso mucho CCS asi que tomalo entre comillas al codigo (funciones,preprocesadores,etc) que escriba.
Vamos al ejemplo... Supongamos que la computadora envia en ASCII el valor.
"250"
"100"
"10"
"-10"
"-125"
Primero que nada uno debe saber cuando es que termina lo que se esta enviando, asi que por ahi es bueno que se envie otro caracter mas. Podria ser un 0x00 para indicar que termino.
Entonces tu PC deebria enviar todo esto:
'2','5','0',0x00
'-','1','2','5',0x00
Esto deberias ponerlo en un array. Y recien cuando esta completo ( recibimos ese ultimo caracter) procedemos a convertirlo.Código: C
#include <stdlib.h> char RX_Buffer[10]; char i = 0; signed int16 numero; #INT_RDA void RDA_isr(void) { if(k != 0){ // Aca todavia no esta completo y siguen llegando valores RX_Buffer[i] = k; i++; // Proteccion de que no supere los 10 lugares que posee el array RX_Buffer (Recordando de dejar uno al ultimo siempre, por eso 9) if(i >= 9) { i=0; } } else { // Aca se completo, por que recibimos el 0x00 RX_Buffer[i] = '\0'; //Termino el string ya se habia pre-incrementado antes la i // Aca convierto a entero // Termino de hacer lo que necesite set_pwm_duty(numero); }
char RX_Buffer[5];
RDA_isr()//void RDA_isr(void)
{
k = getc();
if(k != 0x0D)
{
// Aca todavia no esta completo y siguen llegando valores
RX_Buffer[i] = k;
i++;
// Proteccion de que no supere los 6 lugares que posee el array RX_Buffer (Recordando de dejar uno al ultimo siempre, por eso 5)
if(i >= 4)
{
i=0;
}
}
else
{
// Aca se completo, por que recibimos el 0x00
RX_Buffer[i] = '\0'; //Termino el string ya se habia pre-incrementado antes la i
// Aca convierto a entero
numero = atoi(RX_Buffer);
printf("\fnum: %lu",numero);
if(numero >=300)
{
// Termino de hacer lo que necesite
numero = 300-numero;
set_pwm1_duty(numero);
}
else
// Termino de hacer lo que necesite
set_pwm2_duty(numero);
}
return numero;
}
#INT_RDA
void RDA_isr(void)
{
k = getc();
if(k != 0x0D)
{
// Aca todavia no esta completo y siguen llegando valores
RX_Buffer[i] = k;
i++;
// Proteccion de que no supere los 5 lugares que posee el array RX_Buffer (Recordando de dejar uno al ultimo siempre, por eso 4)
if(i >= 4)
{
i=0;
}
}
else
{
// Aca se completo, por que recibimos el 0x00
RX_Buffer[i] = '\0'; //Termino el string ya se habia pre-incrementado antes la i
// Aca convierto a entero
numero = atol(RX_Buffer);
if(numero >=255)
{
// Termino de hacer lo que necesite
//if(numero==255
numero = numero-255;
set_pwm1_duty(numero);
}
else
// Termino de hacer lo que necesite
set_pwm2_duty(numero);
}
}
#INT_TIMER2
void TIMER2_isr(void)
{
if (contador >=500)
{
a=get_timer0();
b=(get_timer1())/3; //CONT Pulsos
set_timer0(0);
set_timer1(0);
contador=0;
}
contador++;
}
void main()
{
// Configuracioin de los temporizadores y contadores
setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_1|RTCC_8_bit); //65,5 ms overflow
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1); //65,5 ms overflow
setup_timer_2(T2_DIV_BY_16,255,16); //50,0 ms overflow
//setup_timer_2(T2_DIV_BY_16,195,16); //50,0 ms overflow
// Inicializamos los timers en 0
set_timer0(0);
set_timer1(0);
set_TIMER2(0);
// Habilitamos las interrupciones
enable_interrupts(INT_RDA);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
// Habilitamos los PWM
setup_ccp1(CCP_PWM);
setup_ccp2(CCP_PWM);
set_pwm1_duty(pwm1);
set_pwm2_duty(pwm2);
lcd_init();
while(TRUE)
{
printf(lcd_putc,"\f%lu Hz Freq 1",a); //Muestra f
printf(lcd_putc,"\n%lu Hz Freq 2",b);
printf("\f%lu y %lu"a,b);
delay_ms(250);
}
}
Dim enviar As String
Dim port_a As String
Public Sub escribir()
'se declara este boton como public para poder acceder a él desde otros formularios.
If Button3.Enabled = True Then
enviar = TextBox1.Text
SerialPort1.Write(enviar)
TextBox1.Text = ""
Else
SerialPort1.Write(porta)
End If
End Sub
End Class