2011-04-01 14 views
6

Lectura de la tensión de la batería en un dispositivo incorporado. Sin embargo, el voltaje real varía mucho dependiendo de la carga del sistema. Necesitamos un método para reducir la fluctuación de la tensión para mostrar el mejor valor.Función de suavizado para mostrar la tensión de la batería para reducir los picos en el sistema integrado

Actualmente, utilizamos un promedio variable/móvil. Sin embargo, en las últimas 15 lecturas, el resultado todavía fluctúa demasiado.

Al leer acerca de los algoritmos de suavizado, parece que las b-splines, los filtros de kernel o algunos otros algoritmos de suavizado serían ideales. Sin embargo, no puedo encontrar un ejemplo simple que no use numpy o funciones intrínsecas dentro de mathcad o algo así.

¿Alguien sabe de una función fácil de implementar que podría ayudar con esto? Este es un proyecto de C++ (usando Qt 4.5) con solo el mínimo de barras de bibliotecas. Prefiero quedarme en el dominio entero (que muestra el voltaje en milivoltios desde 3300-4200).

TIA Mike

Respuesta

6

Bueno, es un poco difícil de decir lo que necesita sin detalles sobre su situación. Por ejemplo, ¿cuál es la tasa de muestreo de su sensor y cómo se caracteriza la fluctuación del sensor y el ruido que intenta eliminar?

Sin embargo, si ya tiene implementada la media móvil, le recomiendo que pruebe una mediana móvil. (Mediana de las últimas n muestras, en lugar de la media.) Esto tenderá a reducir el impacto de las grandes aberraciones a corto plazo de la producción normal.

Si puede encontrar parámetros que funcionen, sería preferible que los requisitos de CPU y memoria utilicen algún tipo de filtro de paso bajo de tiempo discreto. Estos son bastante fáciles de implementar y solo requieren el conocimiento del valor de salida anterior y la entrada actual para calcular la salida actual. Por ejemplo:

Y = Y[n-1] + A * (X - Y[n-1]) 

(. Cuando Y es la salida de corriente, Y[n-1] es la última salida calculada, y X es su última lectura del sensor)

A es efectivamente la constante de tiempo del filtro de paso bajo, pero es un tiempo discreto, por lo que depende de la tasa de muestreo. Específicamente, A = dt/tau, donde dt es su período de muestreo en segundos, y tau es aproximadamente análoga a la constante de tiempo de tiempo continuo.

+0

Este era perfecta. Rápido, fácil de calcular. Tomó un poco para descubrir mi coeficiente, pero funciona muy bien. –

+0

@Mike: herramientas como Matlab (y sus clones gratuitos como FreeMat y Octave) tienen instalaciones para calcular coeficientes de filtro IIR para requisitos de ancho de banda específicos. Aunque en este caso con un solo coeficiente, probablemente sea suficiente un enfoque empírico (y probablemente más rápido que aprender Matlab). Su método de promedio móvil es un ejemplo simple de un filtro FIR (con todos los coeficientes iguales a 1). – Clifford

+0

gracias, exactamente lo que estaba buscando, este es mi función en base a este para Arduino: // COMPRESOR int compresor (int señal, int lastSignal) { int resultado = lastSignal + 0,2 * (señal - lastSignal) ; resultado de devolución; } – Macumbaomuerte

1

¿ha considerado la simple aplicación de un límite de inclinación para el ¿valor?

new_val = Read_From_HW(); 
diff = new_val - prev_val; 

if (diff > SKEW_LIMIT) 
    diff = SKEW_LIMIT; 
else if (diff < -SKEW_LIMIT) 
    diff = -SKEW_LIMIT; 

reported_val = prev_val + diff; 
prev_val = reported_val; 
0

Sé que esto no responde directamente a su pregunta, pero ayuda a bares promedio? En otras palabras, muestre min/max/mean/median en ventanas de 15 segundos en lugar de solo una media.

1

Sería posible profundizar en las técnicas de procesamiento de señales y las matemáticas complejas, pero debe preguntarse si es realmente necesario.

Si esta pantalla es una simple salida numérica instantánea, utilizada para "indicación solamente" en lugar de decir un gráfico continuo o registro de datos (es decir, no es necesario reconstruir la señal), entonces sería perfectamente aceptable, simplemente tome un promedio periódico en lugar de una media móvil. Como eso no requiere almacenamiento de historial, puede promediar tantas muestras como desee, y esto estaría determinado por la frecuencia requerida de actualización de la pantalla. No es inteligente, pero a menudo es adecuado para la tarea. Aquí hay un ejemplo y una simulación de prueba de su uso.

class cPeriodicMean 
{ 
    public : 
     cPeriodicMean(int period) : m_mean(0), 
             m_period(period), 
             m_count(0), 
             m_sum(0) 
     { 
      // empty 
     } 

     void addSample(int sample) 
     { 
      m_sum += sample ; 
      m_count++ ; 
      if(m_count == m_period) 
      { 
       m_mean = m_sum/m_period ; 
       m_count = 0 ; 
       m_sum = 0 ; 
      } 
     } 

     int getMean() 
     { 
      return m_mean ; 
     } 

    private : 
     int m_mean ; 
     int m_period ; 
     int m_count ; 
     int m_sum ; 
} ; 

// Test Simulation 
#include <cstdlib> 
#include <cstdio> 
#include <windows.h> // for Sleep to simulate sample rate 
int main() 
{ 
    // Average over 100 samples 
    cPeriodicMean voltage_monitor(100) ; 

    for(;;) 
    { 
     // Simulate 4000mV +/- 50mV input 
     int sample = 4000 + (std::rand() % 100) - 50 ; 
     voltage_monitor.addSample(sample) ; 

     // Simulate 100Hz sample rate 
     Sleep(10) ; 

     // Current output 
     int millivolts = voltage_monitor.getMean() ; 
     printf("\r%d millivolts ", millivolts) ; 
    } 
} 

Un refinamiento de esta técnica que producirá la salida aún más suave pero generan resultados a la misma frecuencia sería utilizar la salida media periódica como entrada para el filtro de media móvil. Si tuviera que usar mi ejemplo de 100 muestras por segundo con el período de 100 muestras y luego ponerlo en su promedio móvil de 15 muestras, habrá utilizado 15 segundos de datos de muestreo mientras sigue obteniendo un resultado cada segundo, con poca memoria adicional uso.

Obviamente, puede cambiar el período, la longitud promedio móvil y la frecuencia de muestreo para obtener los resultados que necesita con la frecuencia de actualización que necesita. Le sugiero que tome tantas muestras como pueda para el período para el que necesita una actualización, luego haga la media móvil todo el tiempo que desee.

0

Esto realmente me parece un problema de hardware. ¿Es una batería Li-Io o NiMH? ¿Cómo se ve la curva de descarga? ¿Qué componentes hay entre las celdas de la batería y su ADC? Usted necesita para saber estas cosas antes de ejecutar para implementar varios filtros digitales.

-1

Si no tiene su respuesta, esta es una buena manera de imprimir algo en un robot como un pololu 3pi.

{ 
    int bat = read_battery_millivolts(); 

    clear(); 
    print_long(bat); 
    print("mV"); 
    lcd_goto_xy(0,1); 
    print("Press B"); 

    delay_ms(100); 
} 

+0

Tenga cuidado al responder preguntas antiguas que tienen muchas respuestas, especialmente cuando una de ellas es aceptada. Debe explicar por qué su respuesta es mejor que cualquiera de las existentes. – APC

Cuestiones relacionadas