12 votos

Eficiente inversa (1/x) para AVR

Estoy tratando de encontrar una manera eficaz de calcular una inversa en un AVR (o aproximación).

Estoy tratando de calcular el pulso período de un motor paso a paso para que yo pueda variar la velocidad lineal. El periodo es proporcional al inverso de la velocidad (p = K/v), pero no puedo pensar en una buena manera de calcular este sobre la marcha.

Mi fórmula es

p = 202/v + 298; // p in us; v varies from 1->100

Las pruebas en el Arduino, la división parece ser ignorado por completo dejando p fija en 298 (aunque tal vez esto sería diferente en avr-gcc). También he tratado de sintetizar v en un bucle hasta que se supera 202, y contar las vueltas, pero esto es bastante lento.

Yo podría generar una tabla de búsqueda y almacenarlo en flash, pero me preguntaba si no había otra manera.

Edit: puede que el título debería ser "eficiente dividir"...

Actualización: Como pingswept señala, mi fórmula para la asignación de período de velocidad es incorrecta. Pero el problema principal es la operación de división.

Edit 2: En la investigación posterior, división de trabajo en el arduino, el problema se debe tanto a la fórmula incorrecta arriba y un int de desbordamiento en otros lugares.

7voto

Christopher Galpin Puntos 598

Una cosa buena acerca de la división es que más o menos todo el mundo lo está haciendo. Es un bonito característica principal del lenguaje C, y los compiladores como el AVR-GCC (llamado por el Arduino IDE) va a elegir el mejor algoritmo de la división disponibles, incluso cuando el microcontrolador no tiene una división de hardware de la instrucción.

En otras palabras, usted no necesita preocuparse acerca de cómo la división se implementa a menos que tenga una muy extraño caso especial.


Si usted no se preocupe, entonces usted puede disfrutar de la lectura de Atmel oficial propuso la división de los algoritmos (uno optimizado para el tamaño del código, y uno optimizado para la velocidad de ejecución; ni tomar cualquier memoria de datos). Están en:

http://www.atmel.com/dyn/resources/prod_documents/doc0936.pdf

cual es la Nota de Aplicación "AVR200: Multiplicar y Dividir las Rutinas" que figura en el Atmel página para su (bastante grande) Atmega procesadores como el Atmega 168 y Atmega 328 utilizado en el estándar de los Arduinos. La lista de hojas de datos y las notas de aplicación es en:

http://www.atmel.com/dyn/products/product_card.asp?part_id=4720

4voto

JW. Puntos 145

a mí me parece que todo lo que usted necesita es un 100-entrada de la tabla de búsqueda. No consigue mucho más rápido que eso.

#define VALUE_FOR_V_EQUALS_ZERO 0
uint16_t formula_lookup[100] = {VALUE_FOR_V_EQUALS_ZERO, 500, 399, 365, 348, ..., 300};

...

//"calculate" formula
p = formula_lookup[v > 67 ? 67 : v];

EDICIÓN en realidad sólo un 68 valor de la tabla de búsqueda ya que los valores de v mayor que 67 evaluar siempre a 300.

3voto

mahler Puntos 161

Hay algunas muy buenas las técnicas que se mencionan en el libro "los Hackers Deleite por Henry Warren y en su sitio web hackersdelight.org. Una técnica que funciona bien con los más pequeños microcontroladores cuando se divide por las constantes de echar un vistazo a este archivo.

3voto

Su función no parece que daría el resultado que usted desea. Por ejemplo, el valor de 50 devuelve aproximadamente 302, mientras que 100 devuelve aproximadamente 300. Esos dos resultados hará que casi ningún cambio en la velocidad del motor.

Si lo entiendo correctamente, usted está realmente en busca de una manera rápida para asignar los números de 1 a 100 para el rango de 300 a 500 (aproximadamente), tal que 1 se asigna a 500 y 100 mapas a 300.

Tal vez probar: p = 500 - (2 * v)

Pero puede ser que sea un malentendido ... tratando de calcular el tiempo de una constante de la frecuencia de onda cuadrada? ¿Cuál es el 298?

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X