EJ 5.5 Rampa

EJ 5.5 Rampa

de Francisco Andres Dalessandro Figueroa -
Número de respuestas: 2

Hola profe, estaba haciendo este ejercicio de la guía y me encuentro con una inquietud.

Primero, como lo razoné: utilizo 2 Timers

-Timer 1 en modo FAST PWM OCR1A TOGGLE, en el cual OCR1A cambia a lo largo de la ejecución del programa. Prescaler en 8

-Timer 0 en modo CTC OCR0A. Prescaler en 1024

Yo sé que aumento 50 pulsos/segundo cada 100ms = una aceleración de 500pulsos/segundo^2. Esto quiere decir que para tener un deltaVel = 1 pulso/segundo, necesito 1/500 = 2ms. Entonces, podría hacer que Timer0 cuente hasta el equivalente a 2ms (osea, hasta 30 o 31) y que cada 2ms se habilite una interrupción que le sume 1 a la velocidad actual. Asi, OCR1A, quien controla la velocidad, seria calculado como 1/velocidad*F_CPU/prescaler-1. ¿Por qué no tomar directamente un deltat=100ms? Porque no encuentro la forma de meterlo adentro de un Timer de 8 bits.

Mi pregunta es: esto parece funcionar (no me suele pasar) pero la rampa azul llega hasta 900mV, en vez de 5V como muestra en uno de sus videos. Quizás tenga la culpa algún valor de resistencia/capacitancia asociado al LM331, pero aun así, el que sea tan poquito voltaje y el que tenga un ripple asombroso me da duda de si lo estoy haciendo bien realmente. Por las dudas comparto código y simulación.


En respuesta a Francisco Andres Dalessandro Figueroa

Re: EJ 5.5 Rampa

de Eduardo Iriarte -
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.