Hola amigos, en especial mis agradecimientos a juaperser1 y elgarber:
Les agradezco sus recomendaciones y consejos, les aseguro que ya he rediseñado la “hoja de ruta” de mi proyecto para hacer exactamente lo que ustedes me recomiendan: ir más paso a paso e ir probando las cosas una tras otra.
Bueno, inicialmente probé algunos módulos de software individualmente, pero al integrar todo empezaron los dolores de cabeza mayores…
Bueno, les voy a describir el circuito para que lo comprendan, de cualquier manera voy a adjuntar el código en .c (uso CCS 5.007 y proteus 7.8 sp2) y una imagen de la simulación en proteus, pero con la descripción pienso que se puede entender al menos la idea.
De manera general quiero hacer un reloj POV con 11 leds, que se alimente con un transformador rotatorio, es decir, sin contacto. Además, me gustaría implementar la posibilidad de que se alimente con una batería (en el propio reloj) que permita seguir contando el tiempo si falla la alimentación o si se desconecta por cualquier razón. Por último quisiera implementarle la configuración por infrarrojos, usando un control remoto de un televisor o cualquier otro. Creo que aunque se ve un poco “amplio” (por no decir ambicioso) es perfectamente posible implementarlo.
Tengo en mis manos un par de 16f628a y un 16f887, aunque ahora lo estoy simulando con un 16f648a (empecé con un 628a pero por falta de memoria ROM emigré temporalmente a un 648a para probar los módulos básicos hasta que grafique adecuadamente, y luego emigrar al 887 donde quiero hacer la implementación final). Un detalle es que estoy usando una velocidad de 8MHz, que es lo que brinda el 887 internamente sin necesidad de cuarzo. Para el control del reloj tengo pensado usar un cuarzo externo de 32768 Hz que también tengo a mano.
Los leds que uso son en general 11 de ellos uso los primeros 5 para el horario, hasta el #9 el minutero, el led #10 es el segundero (el segundero enciende solo un led) y en la posición 11 pudiera ir uno o dos leds controlados por el mismo pin, cuya función sería dibujar un círculo alrededor del reloj.
Uso básicamente los 3 timers del PIC, el timer0 inicialmente quería usarlo con el watchdog, pero estoy pensando en cambiar su uso para controlar la señal del control remoto que configuraría el reloj (cambiar la hora, etc), pero verdaderamente la idea del control remoto llegó después que ya tenía el diseño un poco avanzado y aún no tengo muy clara la idea de cómo controlarlo ni que pin o mecanismo usar.
El timer1 lo uso básicamente como contador del cuarzo externo de 32768Hz para contar el tiempo y de esta manera controlar el tiempo, este timer de momento lo tengo configurado para que funcione como contador síncrono, pero en la versión final debería funcionar como contador asíncrono para que pueda seguir contando en modo sleep, en el caso en el que se desconecte la alimentación. Este timer también la uso como base de tiempo para calcular el tiempo que demora en dar una vuelta el motor del reloj –la velocidad- que es la base para calcular el tiempo de encendido/apagado de los leds en su recorrido circular.
El timer2 es el que uso para controlar el tiempo de encendido y apagado de los leds, además del tiempo de estabilización del reloj cuando se enciende el equipo y aún el motor no ha llegado a una velocidad que permita graficar.
La programación la desarrollé por modos de funcionamiento, el modo 1 sería el modo de arranque, el 2 el de funcionamiento “normal”, es decir, graficado automático y continuo del tiempo. Hasta ahora he llegado hasta el modo 2, pero tengo pensado implementar de esta manera otros modos que sean el de configuración, el modo sleep (cuando funciona con baterías, solo contando el tiempo), entre otros.
La idea que he implementado para el algoritmo es: usar la interrupción por RB0 para detectar el cruce por el valor de referencia (usando un sensor infrarrojo) este sensor se mediría al menos 2 veces –la primera vez, luego con una sola medición sería suficiente, ya que se compararía con el penúltimo valor medido- y a partir de ahí se desarrollan todos los cálculos que permitirían obtener al final el tiempo que deben estar encendidos los leds (el equivalente al diámetro de los leds), y el tiempo que deben estar apagados (que sería el tiempo de 1 segmento –el reloj contiene 60 segmentos y son por lo general mayores que 3 ó 5mm que es el diámetro del los leds que pienso emplear-).
Las fórmulas para el graficado que empleo son:
• Perímetro: 2 * pi * radio en micrómetros
• Tiempo de una vuelta (Tv): medición directa que hago usando el timer1
• Tiempo de 1 segmento (Ts): Tv/60
• Velocidad del motor (v): perímetro/Tv
• Tiempo de encendido de leds: diámetro de leds en micrómetros –equivalente a la distancia que debe recorrer dicho led-/velocidad (en microsegundos)
• Tiempo de apagado de leds (Toff): Ts-Ton
El tiempo de una vuelta lo hago leyendo y guardando el valor del timer1 y comparándolo con el valor del próximo pulso de RB0 y multiplicándolo por 30 (tiempo aproximado en microsegundos que tarda entre un valor y el siguiente del cuarzo externo a 32768 Hz).
En el algoritmo, el timer1 “correría libremente” y lo leería “eventualmente al menos una vez por vuelta para revisar si ha transcurrido o no un segundo (de 0 a 32767 sería un segundo, y de 32768 a 35563 el otro segundo). Según los cálculos, 1 segundo transcurriría cada varias vueltas.
Para optimizar al máximo la velocidad de la cpu (que sería 8 MHz) estoy implementando un algoritmo en el cual el pic está calculando el valor de Ton y Toff desde que se obtiene el último valor medido por el sensor de posición de referencia (sensor infrarrojo) y este cálculo es interrumpido por el timer2, el cual en cada interrupción primero enciende los leds –si debe encender alguno- y en su propia interrupción cambia el valor de carga del timer 2 (registro PR2) para que interrumpa ahora durante el tiempo Toff. Luego interrumpe en el nuevo valor cargado (Toff) y la función apaga los leds y carga el registro PR2 con el valor Ton y así sucesivamente. De este modo el cálculo de los valores Ton y Toff estaría en “segundo plano” y la interrupción del graficado de los leds estaría en “primer plano” ejecutándose cada cierto tiempo.
De esta manera, cuando se termina de hacer el cálculo del nuevo Ton y Toff correspondiente a la última lectura se guardan los valores en variables temporales hasta que se active la interrupción por Rb0 nuevamente. Una vez activa la interrupción por RB0 se asignan los valores temporales de Ton y Toff a sus variables definitivas, y comienza un nuevo ciclo –correspondiente a una nueva vuelta-. Todo lo anterior sería lo que debe hacer el PIC en 1 vuelta, en el modo “normal” de trabajo.
El cálculo incluye “filtrar” los pulsos para verificar si el motor está girando dentro de las velocidades precalculadas que debería permitir graficar adecuadamente. La idea es que los leds no enciendan si el motor está por debajo de 12 fps o por encima de 70 fps, aunque la velocidad máxima del motor que el sistema pueda graficar habría que medirla en la práctica y depende de la velocidad a la que esté corriendo el pic, con 8MHz estoy simulando unos 41.6667 fps, lo que serían unas 2500 RPM del motor y creo que alcanza perfectamente.
Voy a adjuntar el código y una imagen del proteus junto a la simulación. Cabe notar que use un generador de señales para simular el cuarzo externo de 32768 Hz (puse un cuarzo y no funcionó), y lo mismo hice para simular la interrupción por RB0, en este segundo caso la frecuencia es la misma que debería interrumpir si el motor gira a una velocidad de 2500 RPm ó 41.667 Hz.
Espero sus sugerencias.