Cómo asignar un valor de ADC de 10 bits a un rango con restricciones

2

Necesito asignar un ADC de 10 bits, es decir, [0-1023] a un rango [1-100]. La fórmula de mapeo en sí es la directa "y = (x-a) / (b-a) * (d-c) + c" para mapear x en [a-b] a y en [c-d].

La entrada x se calcula como el promedio de, por ejemplo, 1000 lecturas de ADC.

Mi problema es este. La entrada al ADC es un potenciómetro y necesito calcular x SOLAMENTE cuando el potenciómetro está parado. ¿Cómo detectas esto? La forma en que lo estoy haciendo actualmente es leer conjuntos de 1000 valores de ADC (en un temporizador), calcular su promedio y comparar el "promedio actual" con el "promedio anterior". Si "avg actual - avg anterior" es algo de "+ -delta" asumo que el potenciómetro es estacionario y realiza el cálculo.

¿Hay una mejor manera de hacer esto?

Editar: Para proporcionar algunos datos más;

  • Estoy usando un MCU C8051F850 de SiLabs que funciona a 24.5MHz
  • Las muestras de ADC se recolectan cada 100us
  • El promedio de 2500 muestras ~ 250 ms se calcula por conjunto. Por lo tanto, se comparan dos avgs cada 500 ms.
  • Mi "delta" es de 10 unidades (aproximadamente 1024/100)
  • Aritmética de enteros para redondear errores
pregunta RamanathanR

2 respuestas

2

Esto es 'prueba de hipótesis en presencia de ruido'.

Cuando estamos haciendo una prueba de hipótesis, definimos un par de condiciones entre las que queremos discriminar, luego definimos una prueba para hacerlo mejor.

Ha definido una condición 'es estacionaria' y una prueba | (current_avg - previous_avg) | < delta. Implícito en esa definición hay otras dos condiciones, subir y bajar.

Si bien la definición de 'es estacionario' no está bien definida, si aplicamos ingeniería inversa a la prueba que ha ideado para averiguar qué significa realmente, el cambio en la posición promedio tomada entre los primeros 1000 y los próximos 1000 Una muestra larga de posiciones de 2000, encontramos que es algo bastante razonable de hacer.

El promedio de 1000 muestras es la mejor manera de calcular una posición promedio, si asumimos que el ruido en cada muestra es independiente. También es rápido, usa pocos recursos, es fácil de entender y usa poca memoria (no necesita almacenar todas las entradas).

La diferencia entre el primer y el segundo conjunto te da la mejor estimación de la velocidad media del pozo durante ese tiempo.

Ahora considere este caso de prueba. Para las primeras 1000 muestras, el bote está girando rápidamente hacia arriba, para las siguientes 1000 está girando rápidamente hacia abajo. El movimiento medio durante ese período, calculado por su estimador, será cero.

¿Estás contento de que esta condición se detecte como estacionaria? Si no, entonces tenemos que cambiar nuestra definición de estacionario. Según tu comentario, no estás contento con algo. ¿Pero qué?

Como ve, el problema no está en la prueba en sí, sino en (a) su definición deficiente de lo que significa "estacionario" y (b) su definición deficiente de lo que considera insatisfactorio sobre el desempeño de la prueba actual.

La prueba que ha definido es la prueba más razonable que existe para detectar la velocidad promedio en presencia de ruido. Si esto funciona bien con la física del mundo real y el comportamiento del usuario es otra cuestión.

Si encuentra que realmente necesita detectar la aceleración, para mejorarla en su caso, es bastante fácil tomar tres muestras promediadas sucesivas, calcular ambos deltas y luego calcular el delta delta.

Si encuentra que un cambio de tamaño promedio, para cambiar la velocidad a la que puede detectar cambios, funciona mejor, entonces haga eso.

Hay otras alternativas que prueban diferentes hipótesis. El primero sería calcular dos medios de ejecución con diferentes constantes de tiempo. Este es un filtro común para usar como detector de bordes en el procesamiento de imágenes, pero también detectará "bordes" en datos unidimensionales. Como los filtros son recursivos, esto es bastante barato de implementar. Sin embargo, tendría que ajustar las dos constantes de tiempo a su situación, entonces, ¿cómo lo haría sintonizar mejor que la única constante de tiempo de su probador actual?

El segundo es hacer un FFT de tus muestras. A continuación, puede comparar la energía en el contenedor de CC (cantidad de estacionario) con la energía en los contenedores de baja frecuencia (cantidad de movimiento, aceleración, cambio de aceleración ...) mientras descarta la energía en los contenedores de alta frecuencia (ruido de lectura) . Pero eso necesita una gran capacidad de memoria y procesamiento, y parece una exageración.

Un tercero, basado en su comentario sobre el problema de la latencia, sería estimar simultáneamente la posición y la pendiente de la línea mediante regresión lineal. Hay una fórmula recursiva para esto, por lo que es relativamente eficiente para usted calcular en tiempo real sin más memoria. Esto le permitiría "corregir" el retraso en la recopilación de datos extrapolando ambas estimaciones hacia adelante para obtener la posición promedio "ahora". Tenga en cuenta que la regresión lineal puede tener problemas de rango dinámico si se realiza para grandes conjuntos de datos, y como está usando la aritmética de enteros, tendría que pensar detenidamente en la implementación. Una forma de mejorar las cosas sería diezmar y ejecutar la regresión lineal a una frecuencia de muestreo mucho más baja, más consistente con la velocidad a la que se está moviendo su pozo del mundo real y el tiempo de respuesta que desea que tenga el programa.

    
respondido por el Neil_UK
1

El promedio hace algunas cosas; y hay mejores maneras.

  1. Agrega latencia = n * intervalo de muestra
  2. Reduce las fluctuaciones aleatorias en Vpp / \ $ \ sqrt n \ $
  3. Actúa como un primer filtro de paso bajo, donde un filtro ponderado puede tener el mismo ruido BW con faldas más pronunciadas y menor retardo de grupo (latencia) al igual que los filtros activos.

  4. Puede causar errores de aliasing si las señales superan la frecuencia de Nyquist antes del promedio, por lo que se necesita algo de filtrado, pero un filtro de pared de ladrillo de quinto orden es mejor para la baja latencia, que es esencialmente un valor de ponderación para el promedio.

  5. Si espera inactivo y la olla tiene ruido de vibración, se agregará una latencia excesiva.

  6. Si diseña un promedio ponderado continuo diferente, puede optimizar la demora de grupo y el error de movimiento utilizando parámetros como un filtro de Kalman. Esto se utiliza en GPS y otros sensores de posición de movimiento, velocidad y aceleración.

6b. ... como @Neil_UK sugirió que puede hacer un FFT en los valores (o exportar y analizar), entonces podría usar un filtro coincidente en la señal fundamental (velocidad de respuesta 10 ~ 90% = tR = 0.35 / f-3dB) en orden para rechazar el ruido utilizando valores de ponderación en promedios itinerantes.

  1. Puede usar un peso de velocidad por la diferencia media en los valores para predecir la posición debido a la latencia y llegar al resultado suave con menos retraso. Luego, puede reducir el número de muestras necesarias para diezmar (reducir la resolución) a valores del 1% (0 ~ 99)

Dejo el algoritmo de diezmado para que otros lo resuman, que es un álgebra básica.

p.s. Yo usaría un codificador de cuadratura incremental con retenciones en lugar de un Pot, para esta aplicación como se usa en los sistemas modernos.

    
respondido por el Tony EE rocketscientist

Lea otras preguntas en las etiquetas