Gracias! Por lo que veo trabaja con el timer del micro.. quisiera saber el error y porque esa seria una mala manera de medir el tiempo de echo,
Es exactamente a lo que voy. Una instruccion en ASM generalmente se realiza en un ciclo, si quisiera saber bien el tiempo que paso deberia contar cada instruccion de ASM, sumarlas y eso me daria el tiempo.
Tu metodo a contar no cuenta exactamente eso... sino que esta contando una cierta cantidad de instrucciones
while(echo==1){
if (nNumero == 0){
tiempo++;
if(tiempo==0){
nNumero = 1;
tiempo = 10000;
}
Pasado a ASM seria y siendo generoso seria algo parecido a instrucciones:
loop:
MOVF nNumero
BTFSS STATUS,Z
INCF Tiempo ; Asumo que tiempo es de 8 bits maximo sino aca serian muchas mas instrucciones
BTFSS STATUS,Z
GOTO fin
MOVLW 0x01
MOVWF nNumero
MOVLW 0xFF ; Aca puede haber mas..... por si su pera los 8 bits
MOVWF Tiempo
fin:
MOVF echo
SUBLW 0x01
BTFSC STATUS,Z
GOTO loop
A lo que quiero llegar que lo que vos contas como "tiempo" es una cantidad aleatoria de instrucciones ( digo aleatoria por que el compilador es quien decide como se pasa a ASM ), y cada 1 de tiempo significa varios ciclos de maquina, con lo cual no podes estar seguro jamas que cuadno sume 1 paso realmente un tiempo exacto.
Ahora el codigo que te pase usa el modulo Capture/Compare/PWM, este modulo usa el timer.
Entonces como podemos medir el pulso?
Podemos usar una interrupcion por flanco ( como tiene el RB0 del 628 ), entonces activas la interrupcion en flanco de subida, entra a la interrupcion y pones a 0 el timer, cambias el flanco a bajada. Cuando entre nuevamente guardas el valor del timer en una variable. Entonces el contenido del timer SI tiene una relacion directa con los ciclos de reloj (Ej: Osc 20Mhz sin prescaler, el timer suma 1 cada 0.2us). Por ende podes saber exactamente el tiempo transcurrido (podes llegar a tener un pequeño error pero no es significante como lo que podes obtener con tu codigo).
En el link que te pase hace exactamente eso nomas que utiliza el modulo CCP para generar la interrupcion y no la interrupcion del puerto RB0. La unica diferencia entre usar la interrupcion por flanco o por el modulo CCP, es que al ocurrir el evento de bajada, el valor se termina copiando a un registro del modulo CCP, es por eso que ves que no se copia el valor del timer en la interrupcion.
Otra de las cosas a tener en cuenta es que si observas el codigo, la muestra (el valor del timer ) se limita.. en ese ejemplo a 3000, si es mayor se considera fuera de rango, el valor de "fuera de rango" se lo das vos para evitar algunos falsos positivos.
Solo 3 cosas mas:
- no es necesario que calcules la distancia en centimetros si no la vas a mostrar en un display/lcd o algo por el estilo, podes simplemente hacer la "comparacion" con el valor obtenido del timer de esa forma ahorras muchos ciclos que estaria intentando multiplicar por un numero con coma.
- tenes que tener en cuenta que el timer puede rebalsar, y puede que en algun momento esto te de un valor que es erroneo.
- podes hacerlo como lo hiciste, es decir sin interrupciones, aunque podrias tener al micro haciendo otra cosa y no esperando un evento. Es por eso el uso de las interrupciones, pero con lo que intentas hacer basta y sobra. Tene en cuenta el punto de arriba
Quiero trabajar con el oscilador interno del pic de 4MHZ, temo que algun fusible pueda estar mal declarado o mal usado el timer..
#fuses xt
Es para un cristal de 4Mhz o menos
#fuses INTRC_IO
Oscilador interno y OSC1/OSC2 como I/O
Con reloj a 4mhz
1 ciclo = 4/4Mhz = 1us
como el preescaler esta en 1(T1_DIV_BY_1) cada 1 que sume significa que transcurrio 1us
el timer1 es de 16 bits, por lo tanto lo maximo que puede contar con ese preescaler es de 65,5ms
Si ese tiempo (tendras que traducirlo a cm y ver si es suficiente) es poco podrias aumentar el preescaler disminuyendo la precision o usar un contador de cuantas veces el temporizador rebalsa.