Hola Francisco,
El razonamiento está perfecto, y el programa en principio también.
Con el Timer0, que es de solamente 8 bits, y prescaler x1024, el máximo tiempo que puede alcanzar entre interrupciones será de:
256 [cuentas] x 1024 [pulsos/cuenta] /(16000000 [pulsos/seg] ) = 0,016384 seg = 16,384 ms, menor que 100 ms.
Una solución a este problema de tener un timer tan corto puede ser elegir un submúltiplo de 100 ms, por ejemplo 10 ms , y cada 10 entradas a la interrupción TIMER0_OVF incrementar la velocidad en +50, como propone el ejercicio 5.5.
También se podría incrementar +5 cada 10 ms, lo que es similar a la que vos planteaste,con un incremento +1 cada 2ms para lograr +50 al cabo de 100 ms.
Con 2 ms la rampa de velocidad es más suave, aunque exige realizar cada 2 ms la operación de división
x=((16000000/8)/velocidad-1);
Este cálculo demora unos 40 microsegundos (tomado con el simulador y breakpoints antes y después de la operación), lo que es perfectamente viable (40us/2000us=2% de ocupación del micro).
El hecho de que la rampa en tu circuito no alcance los aproximadamente 4,72 del ejemplo visto en el video es que en el video la frecuencia generada llega a 5 kHz (ver figura y zoom, el período es de 200 us)
El circuito conversor Frecuencia-Tensión con el LM331 , que se hizo solamente para apreciar gráficamente el aumento de la frecuencia, está ajustado (mediante los componentes) para entregar aproximadamente 1 volt/kHz. Por eso en tu circuito, que llega a 1kHz como pide la consigna, el LM331 llega a unos 900 mV.
Tampoco el ripple asombroso es un problema del programa generador de pulsos, sino del conversor V-F. Que quede claro, este circuito es auxiliar y totalmente prescindible. Se podría ir apreciando también el aumento de frecuencia midiendo directamente los períodos de la onda generada (canal 1). De todos modos, si a alguien le interesa ver este clásico integrado de tiempos más analógicos, puede descargar la hoja de datos
aquí.
El único inconveniente que tiene el programa generador de rampa son estas extrañas discontinuidades
Estas discontinuidades o glitches tienen que ver con que, en el momento de actualizar el tope OCR1A, el TIMER1 puede quedar *por encima* del valor, por lo cual no encontrará el tope y continuará contando hasta desbordar y volver a alcanzar dicho tope desde 0. Esto es aproximadamente unos 65536 pulsos más tarde de lo previsto (se puede ver que son unos 31 us, esto es unas 62000 cuentas a 2MHz, que es 16MHz con prescaler x 8 en el Timer1)
Supuestamente (ver sección 16.7 del
datasheet del Atmega328) en todos los modos PWM del Timer1, el registro OCR1A está en modo doble buffer (no así en el modo CTC), lo cual evitaría este problema ya que el OCR1A no se actualizaría sino hasta que Timer1 vuelva a 0. Pero en el simulador al menos (no recuerdo en el circuito real) el
glitch se produce igual, tanto en modo CTC como en los modos PWM. Una forma de solucionarlo (con un parche de software) es forzar la espera mientras Timer1 esté por encima del valor que se quiere escribir en OCR1A, por ejemplo en tu programa, en la ISR, quedaría :
Donde el 2 de "(x-2)" es un margen para que TCNT1 no pase por encima mientras se realiza OCR1A=x;
Pero esto tiene el inconveniente de que dentro de la ISR podemos estar esperando varios milisegundos, especialmente al inicio de la rampa donde la frecuencia es baja.
Este podría ser un argumento a favor de realizar una actualización del OCR1A no tan frecuente.
De todos modos, existen otros métodos y algoritmos para realizar rampa de velocidad, por ejemplo
aquí y
aquí). También podemos pasar a otros otros uC con más timers de 16 bits para no tener las limitaciones vistas.
La dificultad estará en realizar las rampas de velocidad (aceleración y desaceleración) y al mismo tiempo satisfacer la llegada a la posición consigna, ya que pueden sobrar o faltar pulsos por errores acumulados.
Dejo el archivo de ejemplo visto en el video, hecho con una tabla en vez del algoritmo. En la carpeta debug está el circuito (EJ04b_PWM_Timer-rampa-Proteus.pdsprj)
Nota: He encapsulado el conversor F-V en el componente F_TO_V_LM331. Para ver o editar el circuito ir con el menú contextual a Child Sheet.
Luego pueden salir en el menú principal con Exit to parent Sheet.