Autor Tema: Ayuda proyecto  (Leído 3258 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado NiponWar

  • PIC10
  • *
  • Mensajes: 13
Ayuda proyecto
« en: 16 de Diciembre de 2016, 17:21:25 »
Hola a todos.

Estoy realizando un proyecto con un ATmega 328p donde debo detectar que en una entrada se produce un cambio de 0 a 1 y que si se mantiene durante más de 10 us me encienda una alarma.

Para detectar el cambio he pensado en usar una de las interrupciones externas, INT0 o 1, y que ésta me active un TIMER para contar los 10 us. En el caso de que cuente dicho tiempo que salte una interrupción temporal y me active la alarma y me apague el TIMER.

Hasta aquí todo OK.

Mi problema viene a la hora de controlar que sucede si el cambio de 0 a 1 no llega a los 10 us por lo que se debería de parar el TIMER y continuar como si nada hasta el siguiente cambio.

Es para un experimento de mucha precisión de ahí que me haya decidido por el uso de interrupciones.

Pero para el apagado del TIMER y volver a como si no hubiese pasado nada sólo se me ocurre usar un

if (PIND.2) {
#código para apagar el TIMER
}

en el While(1) {}.

Y no sé si esto sería lo más apropiado, por lo que acepto sugerencias.

Saludos.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Ayuda proyecto
« Respuesta #1 en: 16 de Diciembre de 2016, 18:20:07 »
Creo que lo que decis es mas "exactitud" que precision, pero si es de tanta exactitud imagino que lo estas haciendo en Assembler. Ya que sino estarias agregando instrucciones que no sabes en el codigo y cada instruccion es tiempo. A 20Mhz tenes un ciclo cada 0.05us , son 4 ciclos hasta que la bandera se pone en 1 detectando el cambio. Luego tenes el salto del procesador al vector, los cuales son otros 4 ciclos, finalmente estos vectores son saltos, por lo cual tenes otros 3 ciclos. Suponiendo que se ejecutaba alguna instruccion simple ( de 1 ciclo ) sino se termina la instruccion y procede al salto, lo cual puede agregarse unos 2 o 3 ciclos mas, Luego tenes todas las instrucciones ejecutadas, y tenes otros 4 ciclos mas de vuelta.

Hace alguna otra cosa el micro ademas de conectar la alarma?

Si no hace nada.. entonces lo podes hacer en el while(1) tranquilamente:

Código: C
  1. //Espero el flanco:
  2. while(!PIND.2);
  3. while(PIND.2);
  4. // aca delay
  5. delay_us(10);
  6. // si esta en uno continuo aca
  7. if(PIND.2)
  8. {
  9.     //Activo alarma
  10. }

Esa es una de las formas. Pero no deberias hacer nada mas en el while.
La otra es ir por el timer, interrupcion externa si es que tenes mas cosas en el while.

¿Como hacerlo con el timer?

Suponiendo que tenes esos 1+4+4+3 ciclos asegurados ( el 1 es un promedio de las instrucciones que puede llegar a cortar), tenes que son 12 ciclos de entrada mas 4 de salida.
Luego dentro de la interrupcion externa (flanco ascendente detectado) tenes que:
- Borrar el flag
- Cambiar el flanco de la interrupcion externa.
- Activar el timer (es decir darle entrada de reloj al mismo )
- Salir de interrupcion

Ahora falta el flanco descendente cuando es que vamos a calcular el tiempo. De entrar tenes:
- Borrar el flag
- Cambiar el flanco a ascendente
- Desactivar el reloj del timer
- Borrar flag del timer
- Cargar valor al timer
- Salir de interrupcion

El anterior caso es si no llego a detectarse nada. O que llego el flanco primero antes que el timer a completar, ahora falta el del timer.
- Borrar flag
- Desactivar timer
- Activar alarma
- Salir de interrupcion


Si suponemos que cada operacion ocupa al menos 3 ciclos cada uno, tenemos lo siguiente:
Flanco ascendente: 9 ciclos hasta activar el timer, mas 12 ciclos de entrada. desde que se detecto el flanco
Flanco descendente: Hasta detectarse 4 ciclos

Entonces el timer que deberia cargarlo con un valor de
10us / 0.05us = 200

Pero desde que se activa el flanco hasta que se pone en marcha el timer pasan 21 ciclos. Pero luego para detectar el otro flanco se tarda 4 mas. Dejandolo en 17 ciclos a restarle a esos 200

Quedando en 183, o cargarle el valor 256 - 183 = 73 al timer.

El apagado de la alarma se hace desde el while..


En resumen, lo que busco es una "carrera".. El flanco ascendente me activa el timer, y me configura la int externa.
De ahi pasa a ser una carrera entre la int externa y el timer.
Quien termina primero significa que el pulso es menor o mayor a 10us.
Si termina el timer significa que es mayor a 10us, si ocurre el flanco primero, entonces quiere decir que fueron menos de 10us.

Mayor precision y exactitud se lograria con ASM.

Desconectado NiponWar

  • PIC10
  • *
  • Mensajes: 13
Re:Ayuda proyecto
« Respuesta #2 en: 17 de Diciembre de 2016, 15:55:09 »
Muchas gracias KILLERJC.

No había caído en eso de cambiar la configuración de la interrupcion externa para que después me detectase un flanco de bajada.

Me ha costado un poco el tema de activar y desactivar el TIMER por el tema de estar acostumbrado a otros micros que tienen un propio registro para ello y aquí hasta que me he dado cuenta que se hace con el escalado del TIMER me ha llevado su tiempo.

Sólo una cosa.

El vector de interrupción externa tanto para que salte con el flanco de subida como con el flanco de bajada es el mismo, ¿verdad? Es decir, que tendré que crearme dentro de la atención a la interrupción externa una bandera que me indique si estoy en un caso u otro,supongo.

Nuevamente gracias.

Saludos.
« Última modificación: 17 de Diciembre de 2016, 16:00:01 por NiponWar »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Ayuda proyecto
« Respuesta #3 en: 17 de Diciembre de 2016, 17:34:30 »
El vector de interrupción externa tanto para que salte con el flanco de subida como con el flanco de bajada es el mismo, ¿verdad? Es decir, que tendré que crearme dentro de la atención a la interrupción externa una bandera que me indique si estoy en un caso u otro,supongo.

Es correcto.

Desconectado NiponWar

  • PIC10
  • *
  • Mensajes: 13
Re:Ayuda proyecto
« Respuesta #4 en: 17 de Diciembre de 2016, 18:06:57 »
Creo que ya lo tengo, o eso espero.

Algunas veces me falla pero creo que es el efecto rebote ya que estoy simulando las entradas con.
« Última modificación: 17 de Diciembre de 2016, 19:10:48 por NiponWar »