Hola a todos.
Tengo dos sensores que me mandan un pulso a nivel alto cuando se activan. Quiero medir el tiempo que pasa entre la activación del primero y la activación del segundo:
Sensor 1: _____|**********|______
Sensor 2: ________|**********|______
Uso los dos módulos de captura de un PIC18F4550 (12 MIPS). Los dos módulos están asociados al Timer 3 (16 bits, 1:1). Cuando se activa el primer sensor, leo en la interrupción el valor del CCPR1. Cuando se activa el segundo, leo el valor del CCPR2 y:
- Si el 2º valor es mayor que el primero, el tiempo es la resta
- Si el 2º valor es menor que el primero, el timer se ha desbordado, el tiempo será: 65535-2ºvalor + 1ºvalor
- Mando los valores al PC.
El PC recibe los valores, pero existe mucha variacion entre ellos (por encima y por debajo del valor teorico).
¿Alguna sugerencia?
Gracias por vuestro tiempo.
1. ¿Qué ancho pueden tener los pulsos?El sistema tiene que ser independiente del ancho del pulso. Entre los pulsos puede haber una separación entre 10 msec y 1 segundo. El PIC tiene suficiente tiempo para procesar los resultados entre las diferentes activaciones. El orden de los pulsos siempre es el mismo.
2. ¿Que diferencia puede haber entre pulsos?
3. ¿Con qué frecuencia ocurre el alto y el bajo?
4. ¿El pulso que viene primero, es siempre el mismo?
uiNumeroCuentas = 65535 - (uiCuentaInicial + uiCuentaFinal);poruiNumeroCuentas = (1<<16) - 1 - (uiCuentaInicial + uiCuentaFinal);Pero al PIC no le gusta el desplazamiento de 16 bits. De esa forma genera menos intrucciones, pero no opera como toca.Porque no usas el evento especial con la interrupción del CCP1 y directamente haces que resetee el timer? Con esto te alivias de muchos dolores de cabeza! El flag del CCP1 lo puedes conservar hasta el cálculo en el bucle principal para saber que ese flanco ya lo tienesYa tengo el firmware configurado con 2 módulos de captura y haciendo la resta y no puedo cambiarlo ahora :p
ulNumeroCuentas = T3Overflow * (65535-1) + uiCuentaFinal + 65535 - uiCuentaInicial;Esa línea es redundante y se podría simplificar:
// Incluimos el numero de 'Overflo' en los calculos
ulNumeroCuentas = 0;
ulNumeroCuentas = (T3Overflow<< 16) + uiNumeroCuentas ;
En T3Overflow tengo el numero de "desbordamientos". Supongamos que tengo 3, (T3Overflow<< 16) lo desplazaria para ocupar los bits superiores al 16 y asi completar la operación. Siempre será menos costoso un desplazamiento que un producto, pero no funciona :-)Si uso 16 bits, las cuentas van desde 0 hasta 65535. Quiero cambiar el códigoCódigo: [Seleccionar]uiNumeroCuentas = 65535 - (uiCuentaInicial + uiCuentaFinal);porCódigo: [Seleccionar]uiNumeroCuentas = (1<<16) - 1 - (uiCuentaInicial + uiCuentaFinal);Pero al PIC no le gusta el desplazamiento de 16 bits. De esa forma genera menos intrucciones, pero no opera como toca.
Porque no usas el evento especial con la interrupción del CCP1 y directamente haces que resetee el timer? Con esto te alivias de muchos dolores de cabeza! El flag del CCP1 lo puedes conservar hasta el cálculo en el bucle principal para saber que ese flanco ya lo tienesYa tengo el firmware configurado con 2 módulos de captura y haciendo la resta y no puedo cambiarlo ahora :p
Jeje, pensé que tu mismo lo estabas programado... que problema hay en reprogramarlo ? ;) ;) :lol:ulNumeroCuentas = T3Overflow * (65535-1) + uiCuentaFinal + 65535 - uiCuentaInicial;Esa línea es redundante y se podría simplificar:Código: [Seleccionar]En T3Overflow tengo el numero de "desbordamientos". Supongamos que tengo 3, (T3Overflow<< 16) lo desplazaria para ocupar los bits superiores al 16 y asi completar la operación. Siempre será menos costoso un desplazamiento que un producto, pero no funciona :-)
// Incluimos el numero de 'Overflo' en los calculos
ulNumeroCuentas = 0;
ulNumeroCuentas = (T3Overflow<< 16) + uiNumeroCuentas ;
ulNumeroCuentas = (65536 - uiCuentaInicial) + uiCuentaFinal ;
ulNumeroCuentas = ulNumeroCuentas + (T3Overflow-1)*65536;
Esas dos instrucciones hacen que el programa funcione a costa de estar 171 ciclos del PIC (un PIC funcionando a 12 MIPS).typedef union
{
unsigned char bytes[4];
unsigned long valor;
} uMedidaCuentas;
aux = uMedida21bits.bytes[2];
uMedida21bits.valor = (65536 - uiCuentaInicial) + uiCuentaFinal;
uMedida21bits.bytes[2] = aux;
EL nuevo tiempo pasa a ser solo de 30 ciclos :o. Solo un 21% del valor antiguo. Parece que el C18 trabaja mejor si le usas uniones que si trabaja a mas alto nivel.
Una pregunta mas :-/
Las interrupciones del modulo de captura son seguidas, es decir, primero se activa un sensor y despues el otro.¿Valela pena salvar los valores al entrar en la interrupcion? Si no los guardo (quedan almacenados en un registro hardware) ahorro 8 ciclos en la interrupcion.