Solo por el gusto de hacerlo, y para demostrar que se puede hacer, terminé una rutina de ensamblaje AVR para calcular los resultados de sin (x) en 24 bits (3 bytes) con un bit de error. El ángulo de entrada está en grados con un dígito decimal, de 000 a 900 (0 ~ 90.0) solo para el primer cuadrante. Utiliza menos de 210 instrucciones AVR y funciona con un promedio de 212 microsegundos, que varía de 211us (ángulo = 001) a 213us (ángulo = 899).
Tomó varios días hacerlo todo, más de 10 días (horas libres) simplemente pensando en el mejor algoritmo para el cálculo, considerando el microcontrolador AVR, sin punto flotante, eliminando todas las divisiones posibles. Lo que llevó más tiempo fue hacer los valores de incremento correctos para los enteros, para tener una buena precisión necesita aumentar los valores de 1e-8 a enteros binarios 2 ^ 28 o más. Una vez que se encontraron todos los errores culpables de precisión y redondeo, aumentaron su resolución de cálculo en 2 ^ 8 o 2 ^ 16 adicionales, se obtuvieron los mejores resultados. Primero simulé todos los cálculos en Excel teniendo cuidado de tener todos los valores como Int (x) o Round (x, 0) para representar exactamente el procesamiento central de AVR.
Por ejemplo, en el algoritmo el ángulo debe estar en radianes, la entrada está en grados para facilitar al usuario. Para convertir grados a radianes, la fórmula trivial es rad = grados * PI / 180, parece agradable y fácil, pero no lo es, PI es un número infinito: si se usan pocos dígitos creará errores en la salida, la división por 180 requiere La manipulación de bits AVR ya que no tiene instrucción de división, y más que eso, el resultado requeriría coma flotante ya que involucra números muy por debajo del entero 1. Por ejemplo, Radián de 1 ° (grado) es 0.017453293. Dado que PI y 180 son constantes, ¿por qué no invertir esta cosa para una multiplicación simple? PI / 180 = 0.017453293, multiplíquelo por 2 ^ 32 y resulta como una constante 74961320 (0x0477D1A8), multiplique este número por su ángulo en grados, digamos 900 para 90 ° y desplazarlo 4 bits a la derecha (÷ 16) para obtener 4216574250 (0xFB53D12A), es decir, los radianes de 90 ° con 2 ^ 28 de expansión, caben en 4 bytes, sin una sola división (excepto los 4 poco desplazamiento a la derecha). En cierto modo, el error incluido en dicho truco es menor que 2 ^ -27.
Por lo tanto, todos los cálculos adicionales deben recordar que es 2 ^ 28 más alto y que se ha solucionado. Debe dividir los resultados sobre la marcha por 16, 256 o incluso 65536 solo para evitar que use bytes de hambre innecesarios que no ayudarían a la resolución. Ese fue un trabajo minucioso, solo encontrar la cantidad mínima de bits en cada resultado de cálculo, manteniendo la precisión de los resultados alrededor de 24 bits. Cada uno de los varios cálculos se realizó en prueba / error con bits más altos o más bajos en el flujo de Excel, observando la cantidad general de bits de error en el resultado en un gráfico que muestra 0-90 ° con una macro que ejecuta el código 900 veces, una vez por décima de grado Ese enfoque "visual" de Excel fue una herramienta que creé, ayudó mucho a encontrar la mejor solución para cada parte del código.
Por ejemplo, al redondear este resultado de cálculo en particular 13248737.51 a 13248738 o simplemente perder los decimales "0.51", ¿cuánto afectará la precisión del resultado final para todas las 900 pruebas de ángulos de entrada (00.1 ~ 90.0)?
Pude mantener el animal contenido dentro de 32 bits (4 bytes) en cada cálculo, y terminé con la magia para obtener precisión dentro de los 23 bits del resultado. Al verificar los 3 bytes completos del resultado, el error es ± 1 LSB, pendiente.
El usuario puede obtener uno, dos o tres bytes del resultado para sus propios requisitos de precisión. Por supuesto, si solo un byte es suficiente, recomendaría usar una sola tabla sin 256 bytes y usar la instrucción AVR 'LPM' para obtenerla.
Una vez que tuve la secuencia de Excel funcionando sin problemas y ordenada, la traducción final del ensamblaje de Excel a AVR tomó menos de 2 horas, como de costumbre, debería pensar más primero, trabajar menos después.
En ese momento pude exprimir aún más y reducir el uso de registros. El código real (no final) utiliza alrededor de 205 instrucciones (~ 410 bytes), ejecuta un cálculo sin (x) en promedio de 212us, reloj a 16MHz. A esa velocidad puede calcular más de 4700 sen (x) por segundo. No es importante, pero puede ejecutar una onda sinusoidal precisa de hasta 4700Hz con 23 bits de precisión y resolución, sin ninguna tabla de búsqueda.
El algoritmo base se basa en la serie Taylor para sin (x), pero modificó mucho para adaptarse a mis intenciones con el microcontrolador AVR y la precisión en mente.
Incluso si usar una tabla de 2700 bytes (900 entradas * 3 bytes) sería atractivo para la velocidad, ¿cuál es la experiencia divertida o de aprendizaje en eso? Por supuesto, también se consideró el enfoque CORDIC, tal vez más tarde, el punto aquí es presionar a Taylor en el núcleo AVR y tomar agua de una roca seca.
Me pregunto si Arduino "sin (78.9 °)" puede ejecutar Processing (C ++) con 23 bits de precisión en menos de 212us y el código necesario más pequeño que 205 instrucciones. Puede ser si C ++ usa CORDIC. Los bocetos de Arduino pueden importar código de ensamblaje.
No tiene sentido publicar el código aquí, más tarde editaré esta publicación para incluir un enlace web, posiblemente en mi blog en esta url . El blog está principalmente en portugués.
Esta aventura de hobby sin dinero fue interesante, superando los límites del motor AVR de casi 16MIPS a 16MHz, sin instrucción de división, multiplicación solo en 8x8 bits. Permite calcular sin (x), cos (x) [= sin (900-x)] y tan (x) [= sin (x) / sin (900-x)].
Por encima de todo, esto ayudó a mantener mi cerebro de 63 años pulido y engrasado. Cuando los adolescentes dicen que las 'personas mayores' no saben nada sobre tecnología, yo respondo "piensa de nuevo, ¿quién crees que creó las bases para todo lo que disfrutas hoy?".
Salud