TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Xa2 en 24 de Junio de 2004, 06:12:00

Título: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: Xa2 en 24 de Junio de 2004, 06:12:00
Buenas  foreros, me vais a llamar pesado!!!!jeje!!
Tengo que obtener la velocidad en r.p.m. y tengo un encoder, entonces tendre que progrmar TMR0 como temporizador durante 1s (1000ms), y el TMR2 como contador para que cuente cuantos pulsos le llegan (no se que pata seria, es cuestion de mirar) del exterior, y ese numero multiplicarlo por 60 para obtener las r.p.m. y este dato mandarlo por el puerto serie(aunque serán caracteres, en visual basic ya se convertiran a numeros, no??)!!
Mi pregunta es como se configurarian los dos temporizadores??es decir, como son las secuencias??
Habria que habilitar las interrupciones generales y luego la interrupcion del timer 0, no??"
Muchas gracias de antemano y saludos a todos vosotros!!
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: pocher en 24 de Junio de 2004, 10:29:00
Sí claro tienes que habilitar las interrupciones GLOBAL y INT_RTCC.

Cuando finalice el tiempo preestablecido por tí, que no tiene porque ser 60s, dentro de la interrupción haces pulsos=get_timer1().

Haz el programa y lo corregimos, es sencillo.
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: Xa2 en 24 de Junio de 2004, 12:05:00
He conseguido hacer lo siguiente, me compila, pero no se si funciona ya que no se como simularlo!!!!
Si me pudieras ayudar muchas gracias, si algo falta o está mal respondeme por favor!
No espero a un segundo, cada 10ms desbordo el timer0, ya que es de 8 bits y si quiero hacer de 1s se me sale el valor a cargar del rango; luego cklaro, al ser cada 10ms, los pulsos los multiplico por 1000.

*****************************************************
#include <16f873.h>

#fuses XT, NOPROTECT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=4000000)

#int_RTCC

long int pulsos;

RTCC_isr()
{
   pulsos=get_timer1();
}

main()
{

   long int velocidad;

   while(true)
   {
      enable_interrupts(GLOBAL);
      enable_interrupts(INT_RTCC);
      setup_timer_0 ( RTCC_INTERNAL | RTCC_DIV_256);
      set_rtcc(21);  //60ms -> 60000us -> 60000/256=234 -> 255-234=21

      velocidad=pulsos*1000.0;

   }

}
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: pocher en 24 de Junio de 2004, 23:22:00
Si tomas pulsos cada 10ms por muy rápido que vaya el motor no le va a dar tiempo a dar ni una vuelta. Cada vez que entra en la interrupción debes de incrementar una variable y cuando esta variable llegue a un cierto valor, entonces tomas datos (pulsos=get_timer1()).

Todo esto: enable_interrupts(GLOBAL); enable_interrupts(INT_RTCC); setup_timer_0 ( RTCC_INTERNAL | RTCC_DIV_256); set_rtcc(21); //60ms -> 60000us -> 60000/256=234 -> 255-234=21 , mételo en el main, no en el while.

En la fórmula velocidad=pulsos*1000.0; no hace falta el .0, el 1000 claro, está mal y además, esta fórmula métela en la interrupción, detrás del  pulsos=get_timer1().

Vete haciendo y vamos corrigiendo.
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: Xa2 en 25 de Junio de 2004, 04:41:00
He hecho los cambios q me has aconsejado y sigue sin funcionar, no me coje los valores del contador y logicamente no me los manda por puerto serie. Te dejo el codigo por si me puedes ayudar, saludos y gracias de nuevo por ayudarme.


#include <16f873.h>

#fuses XT, NOPROTECT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#int_RTCC

long int pulsos;
int interrupcion;
int velocidad;

RTCC_isr()
{
   interrupcion=interrupcion+1;
   while(interrupcion=100)
      {
      pulsos=get_timer1();
      velocidad=pulsos*60;
      printf("%d",velocidad);
      interrupcion=0;
      }
}

main()
{

   
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_RTCC);
   setup_timer_0 ( RTCC_INTERNAL | RTCC_DIV_128);
   set_rtcc(177); //10ms -> 10000us -> 10000/128=78 -> 255-78=177

   interrupcion=0;

   while(true)
   {
   
         //el programa principal que estaria haciendo, esperando a la interrupcion
   }

}

Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: pocher en 25 de Junio de 2004, 11:18:00
Veo que estás ahí, te lo estoy mirando, pero hay alguna chorrada que no me salen los resultados. Sigo en ello.
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: pocher en 25 de Junio de 2004, 11:45:00
¡¡¡Ya está!!!

Codigo:
#include <16f873.h>

#fuses XT, NOPROTECT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

int16 pulsos;
int16 interrupcion;
int16 velocidad;

#int_RTCC

RTCC_isr()
{   
interrupcion++;
if(interrupcion==100)
{
   pulsos=get_timer1();
   velocidad=pulsos*60;
   printf("%lu   ",pulsos);
   printf("%lu   ",velocidad);
   delay_ms(2000);
   interrupcion=0;
   set_timer1(0);
   set_rtcc(177);
}
}

main()
{

set_tris_c(0x01);
enable_interrupts(GLOBAL);
enable_interrupts(INT_RTCC);
setup_timer_0 ( RTCC_INTERNAL | RTCC_DIV_128);
set_rtcc(177); //10ms -> 10000us -> 10000/128=78 -> 255-78=177

setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);
set_timer1(0);

interrupcion=0;

while(true)
{
//el programa principal que estaria haciendo, esperando a la interrupcion
}

}

Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: Xa2 en 25 de Junio de 2004, 12:02:00
Muchas garcias pocher, no se que haría son ti, jeje, no que es broma, pero muvhas gracias otra vez, no se cuantas van, pero si me pudieras decir en k falla???
gracias de nuevo y saludos!!
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: pocher en 25 de Junio de 2004, 12:08:00
El programa que te he puesto, creo que está bien. Pruébalo físicamente y ya me contarás.

Acuerdate que la entrada de pulsos va por RC0.
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: Xa2 en 25 de Junio de 2004, 12:14:00
 Simulando como tu dices funciona, pero me referia a si pudieras decirme en que fallaba mi programa, para poder aprender en que he fallado, gracias!!
Saludos!!
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: pikman en 25 de Junio de 2004, 12:46:00
Bueno, yo he usado para esto el CCP midiendo el ancho del pulso, con esto obtengo el periodo, luego  1/x y tienes la frecuencia, de ahi a las RPM estas a un paso, hay un ejemplo de medicion de velocidad del viento en este subforo de donde saque la idea publicado por lu6vg, espero te sirva.

saludos

ARIEL
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: Ginho_rj en 25 de Junio de 2004, 23:21:00
alguns erros:


#include <16f873.h>

#fuses XT, NOPROTECT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#int_RTCC //esta linha deve preceder a função

long int pulsos;
int interrupcion;
int velocidad;

RTCC_isr()
{
interrupcion=interrupcion+1;
while(interrupcion=100) //deve-se utilizar o operador   comparação "==" e não utilize whiles dentro de uma interrupção
{
pulsos=get_timer1();
velocidad=pulsos*60;
printf("%d",velocidad);
interrupcion=0;
}
}

main()
{


enable_interrupts(GLOBAL);
enable_interrupts(INT_RTCC);
setup_timer_0 ( RTCC_INTERNAL | RTCC_DIV_128);
set_rtcc(177); //10ms -> 10000us -> 10000/128=78 -> 255-78=177

interrupcion=0;

while(true)
{

//el programa principal que estaria haciendo, esperando a la interrupcion
}

}
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: pocher en 25 de Junio de 2004, 23:26:00
Pués el fallo más importante que había es que no habías programado el TMR1 en el main con setup_timer1(...) y claro no contaba pulsos.

Otras cosillas:

- Definías long pulsos y int velocidad ---> deben definirse al revés ya que pulsos es dificil que pase de 255 pulsos por segundo, sin embargo velocidad sí que pasa.

- Como consecuencia de esto en el printf el formato de la velocidad ha de ser %lu

Un saludo
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: pocher en 28 de Junio de 2004, 10:58:00
Un detalle más, sin el cual el programa no va a ir bien.

Al entrar en la interrupción se incrementa la variable y luego se pregunta el if. Todo esto repetido 100 veces va a dar lugar a que el TMR1 cuente más pulsos de los que son, con lo cual saldrá más velocidad de la que toca.

Para solucionar esto nada más entrar en la interrupción captura el valor del TMR1 y al salir se lo devuelves.

Un saludo
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: Xa2 en 28 de Junio de 2004, 13:20:00
Muchas gracias a todos!!
Entonces como quedaría la interrupcion??

De la siguiente manera??? Es que todavia ando pez en esto de CCS...ya me perdonareis

********************************
#int_RTCC

RTCC_isr()
{
   pulsos=get_timer1();
   interrupcion++;
   if(interrupcion==100)
   {
      pulsos=get_timer1();
      velocidad=pulsos*60;
      printf("%lu   ",pulsos);
      printf("%lu   ",velocidad);
      delay_ms(1000);
      interrupcion=0;
      set_timer1(0);
      set_rtcc(177);
   }
}
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: pocher en 28 de Junio de 2004, 13:50:00
No así:

#int_RTCC

RTCC_isr()
{
pulsos=get_timer1();
interrupcion++;
if(interrupcion==100)
{
//pulsos=get_timer1();
velocidad=pulsos*60;
printf("%lu ",pulsos);
printf("%lu ",velocidad);
//delay_ms(1000);
interrupcion=0;
set_timer1(0);
set_rtcc(178);
}
else
{
set_rtcc(178);
set_timer_1(pulsos)
}
}

El 178 es porque en la fórmula es 256, no 255.
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: pocher en 29 de Junio de 2004, 04:25:00
Pikman podrías publicar aquí como lo hiciste empleando el módulo CCP?

Empleando un cristal de 4MHz y un Preescaler=1, la diferencia más grande entre dos capturas del TMR1 con flancos ascendentes, es de 65535us que dá una frecuencia mínima de 15,25Hz

Empleando un cristal de 4MHz y un Preescaler=8, la diferencia más grande entre dos capturas del TMR1 con flancos ascendentes, es de 524ms que dá una frecuencia mínima de 1,9Hz


¿Como hiciste para medir frecuencias de 1Hz por ejemplo?

La única posibilidad que le veo es coger un cristal más pequeño (fosc menor)
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: pocher en 30 de Junio de 2004, 09:47:00
Ya he dado con la solución empleando el módulo CCP1.

Se me ha ocurrido otra forma de trabajar con frecuencias más bajas de 1,9Hz sin tener que reducir la frecuencia del cristal, y es empleando un encoder con más radios, por ejemplo 4.

Además es conveniente emplear 4 radios en lugar de uno ya que el error que se comete por pérdida de un pulso sería de +/- 15 r.p.m. en el caso de 4 radios y de +/- 60 r.p.m. en caso de dibujar un radio.
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: Xa2 en 01 de Julio de 2004, 06:58:00
Muy buena Pocher!! Ese metodo tb se puede realizar con la interrupcion del timer no???
Por curiosidad como seria con el modulo CCP???
bueno usando el metodo del timer0 y timer1, la multiplicación seria pulsos*15, ya que son 4 radios!!
Y ya está, no??"
Si pudieras resolverme las dudas que te he puesto te lo agradecería!!
PD: que sabes sobre resistencas shunt para sacar la corriente del motor??? cualquier cosa me valdria
Saludos y gracias soys la ostia, como ayudais
Título: RE: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: pocher en 02 de Julio de 2004, 00:29:00
Sí eso es Xa2, hay que multiplicar con 4 radios, la velocidad por 15 para obtenerla en r.p.m.

El programita con el TMR1 - TMR0 sí que es capaz de medir velocidades de 1rev/s sin necesidad de poner 4 radios, sin embargo para cuestión de mejor resolución por pérdida de un pulso sí que es conveniente hacerlo con 4 radios ó más.

Respecto a sacar por LCD la intensidad de consumo del motor empleando una resistencia shunt, este tema ya lo tienes tratado, tenía el título de "Amperímetro digital", más o menos y creo recordar que estaba en el subforo de ensamblador (todo sobre microcontroladores). Ayer y anteayer el buscador no funcionaba, es una lástima ya que con él te saldría enseguida.

Gracias Pikman, lo probaré.

Un saludo
Título: Re: TMR0 Y TMR1!!!!R.P.M.!!!!!
Publicado por: epogor en 02 de Septiembre de 2011, 13:01:40
hola soy nuevo en este tema de los pic, estaba viendo este contador de rpm, y queria preguntar por que configuran los timer de esta manera:

setup_timer_0 ( RTCC_INTERNAL | RTCC_DIV_128); //habilito interrupcion-prees 128
set_rtcc(177);          //10ms -> 10000us -> 10000/128=78 -> 255-78=177

setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);// habil interr. de pulsos
set_timer1(0);

 al poner set_rtcc(177);  que esta haciendo, habilita la interrupcion cada 10ms? y la segunda pregunta es: RTCC_DIV_128 es para configurar el preescalador.
desde ya gracias por compartir tan buena info. :o :o