Hola,
Estuve mirando formas de implementar "movimientos suaves" sin utilizar operaciones matemáticas complicadas y al final encontré una forma muy sencilla y discreta (digital) de hacerlo. Se trata de utilizar el
algoritmo de Bresenham para circunferencias. Hay como mínimo dos formas de implementar ese algoritmo y he utilizado el mismo que usé como ejemplo en la
pantalla Oled. Como decía, existen al menos dos algoritmos para circunferencias; una es por cuadrantes (como un pastel dividido en 4 partes iguales) y la otra es por octantes (como un pastel dividido en 8 partes iguales). Gráficamente usar el de octantes es más eficiente y rápido, porque hay que calcular menos y todo se repite. Pero para manejar motores me pareció más conveniente usar el de cuadrantes, y equivale a calcular un ángulo de 0 a 90 grados para un radio dado.
Nos olvidamos ahora de la parte gráfica y hagamos que un programa con este algoritmo nos muestre los números que salen para las coordenadas de los ejes X e Y. Veremos lo siguiente:

Al programa le doy como Radio el valor 16 (es arbitrario) y los valores de salida son los que se ven en la imagen donde la columna izquierda representa los valores del eje X y la de la derecha el eje Y. El programa está manipulado para que dé siempre números positivos usando la función ABS() para el eje X que es siempre negativo, y el Y no hay que hacer nada porque es siempre positivo.
Hemos de observar cómo en el eje X al comienzo se repiten valores, y lo mismo pasa en el eje Y pero hacia el final. Podemos comprobar que las sucesiones y repeticiones no son lineales, sino que se repite varias veces y cada vez se repite menos para que finalmente el resto de número (la mayoría) no se repitan.
El siguiente paso es tomar sólo los valores de salida del eje X y cuando termina, volvemos a ejecutar el programa pero sólo tomando los valores del eje Y; esto se puede hacer con un "for" que se ejecute dos veces y conmutar dicha salida (primero de X y luego de Y).

Para verificar que realmente estamos haciendo "smooth movement" vamos a graficar esta salida de datos haciendo unas artimañas (para que no vuelva hacia atrás, sino que prosiga):

Se ve un poco cutre pero es porque son sólo 29 puntos (14 del eje X y 15 del eje Y), pero se aprecia perfectamente que es una sigmoide.
Ahora vienen tres pasos cruciales, pero estas tres partes no son tan evidente. Si, como en el ejemplo, damos un valor de 14, nos saldrá 29 resultados cuando en realidad necesitamos 14.
Paso 1: Observamos si el valor de entrada (el radio) es par o impar para luego poner condiciones y así hacer corresponder, por ejemplo, si le doy una entrada de 14, me saque 14 pasos.
Paso 2: Hemos de dividir los dato de salida entre 2.
Paso 3: Cada paso mide un mismo tiempo. Si el número se repite se suman los tiempos de cada uno de ellos, pero sólo hay un paso (sin importar las veces que se repita). Es decir, que sólo cuando el número cambia de un paso al siguiente es cuando validamos ese paso.
Todo esto lo probé primero programando y una vez que conseguí que funcionase bien lo pasé a Verilog junto con otros módulos y me quedó así:

Este es el módulo principal, el cerebro que permite este tipo de movimiento. Tiene una entrada de 16 bits y siempre ha de ser números positivos.
El ICE que pongo como ejemplo es este:

Se trata de ver a través de los leds cómo va contando y lo hace de la siguiente manera: Comienza contando lento, se va incrementando, después ya toma una velocidad de contaje rápido la mayor parte del tiempo y cuando se acerca al final vuelve a relantizarse de la misma forma que empezó (pero al revés).
Si alguien le apetece probarlo, lo único que ha de hacer es subir el circuito y luego desde un terminal serie, ponerle un valor, recomiendo para empezar el valor 255, y luego el valor 511. Siempre va a contar de forma incremental, es decir, desde 0 al valor que le hayas puesto. Para números mayores de 255 simplemente vuelve a comenzar, así que si ponemos el valor 511 veremos que se repite dos veces, pero con la particularidad de que cuando comienza y cuando termina lo hace de forma progresiva.
Ya lo he probado con un motor de pasos (un Nema 17) y funciona como se espera, pero hay que añadir más cosas para que el tipo de movimiento sea perfecto. Lo que quiero decir es que se necesita una velocidad inicial mínima y de crucero máxima, para que el motor tenga un comportamiento "natural" y eso es lo que me falta por hacer. Espero no tardar mucho en lograrlo, será entonces cuando suba un vídeo de demostración.
Saludos.