Функция сглаживания для отображения напряжения батареи, чтобы уменьшить пики во встроенной системе - PullRequest
7 голосов
/ 01 апреля 2011

Считывание напряжения батареи во встроенном устройстве. Однако фактическое напряжение сильно варьируется в зависимости от нагрузки системы. Нам нужен метод, чтобы уменьшить колебания напряжения для отображения наилучшего значения.

В настоящее время мы используем скользящее / скользящее среднее. Однако за последние 15 чтений результат все еще слишком сильно колеблется.

Читая об алгоритмах сглаживания, кажется, что b-сплайны, фильтры ядра или некоторые другие алгоритмы сглаживания были бы идеальными. Тем не менее, я не могу найти простой пример, который не использует пустые или встроенные функции в mathcad или что-то подобное.

Кто-нибудь знает простую в реализации функцию, которая может помочь с этим? Это проект C ++ (использующий Qt 4.5) с минимальным количеством библиотек. Я предпочел бы остаться в целочисленной области (показывая напряжение в милливольтах от 3300-4200).

ТИА Mike

Ответы [ 7 ]

7 голосов
/ 01 апреля 2011

Ну, сложно сказать, что вам нужно, без подробностей вашей ситуации. Например, какова частота дискретизации вашего датчика и как характеризуются флуктуация и шум датчика, который вы пытаетесь удалить?

Однако, если вы уже внедрили скользящее среднее, я мог бы рекомендовать вместо этого попробовать скользящую медиану. (Медиана последних n выборок, а не средняя.) Это будет иметь тенденцию уменьшать влияние больших кратковременных аберраций от нормы на ваш результат.

Если вы можете найти параметры, которые работают, было бы предпочтительным для требований ЦП и памяти использовать некоторую форму фильтра нижних частот с дискретным временем. Они довольно просты в реализации и требуют только знания предыдущего выходного значения и текущего ввода для вычисления текущего выхода. Например:

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

(где Y - токовый выход, Y[n-1] - последний вычисленный выход, а X - последнее показание датчика.)

A фактически постоянная времени фильтра нижних частот, но это дискретное время, поэтому оно зависит от частоты дискретизации. В частности, A = dt / tau, где dt - ваш период выборки в секундах, а tau примерно аналогичен постоянной времени непрерывного времени.

2 голосов
/ 01 апреля 2011

Вы можете найти объяснения и исходный код в классической книге NR: http://apps.nrbook.com/c/index.html,

, а именно глава 3: http://www.arcetri.astro.it/irlab/library/recipes/bookcpdf/c3-3.pdf

1 голос
/ 01 апреля 2011

Можно было бы углубиться в методы обработки сигналов и сложную математику, но вы должны спросить себя, действительно ли это необходимо?

Если этот дисплей представляет собой простой мгновенный числовой вывод, используемый для «только индикации», а не для непрерывного графика или журнала данных (т. Е. Вам не нужно восстанавливать сигнал), то он часто будет вполне приемлемым, просто взять периодическое среднее вместо скользящего среднего.Поскольку для этого не требуется хранения истории, вы можете усреднить столько сэмплов, сколько пожелаете, и это будет определяться требуемой частотой обновления дисплея.

Это не умный , но эточасто достаточно для этой задачи.Вот пример и тестовое моделирование его использования.

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 ) ;
    }
}

Уточнение этого метода, который будет производить еще более плавный выход, но генерировать результаты на той же частоте, будет использовать периодическое среднее значение.вывод в качестве входных данных для вашего фильтра скользящей средней.Если бы вы использовали мой пример 100 выборок в секунду с периодом 100 выборок, а затем пропустили его через скользящее среднее 15 выборок, вы будете использовать данные выборки за 15 секунд, в то же время получая результат каждую секунду с небольшим объемом дополнительной памяти.использование.

Очевидно, что вы можете изменить период, длину скользящей средней и частоту выборки, чтобы получить нужные вам результаты с необходимой частотой обновления.Я предлагаю вам взять как можно больше выборок за период, для которого вам нужно обновление, а затем сделать скользящую среднюю так долго, как вы хотите.

1 голос
/ 01 апреля 2011

Рассматривали ли вы просто применение предела перекоса к значению?

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 голосов
/ 26 декабря 2015

Если у вас нет ответа, это хороший способ напечатать что-нибудь на роботе типа пололу 3pi.

{
    int bat = read_battery_millivolts();

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

    delay_ms(100);
}

0 голосов
/ 02 апреля 2011

Это действительно звучит как аппаратная проблема для меня.Это литий-ионный или никель-металлогидридный аккумулятор?Как выглядит кривая разряда?Какие компоненты находятся между элементами аккумулятора и АЦП?Вам нужно знать эти вещи, прежде чем убегать для реализации различных цифровых фильтров.

0 голосов
/ 01 апреля 2011

Я знаю, что это не дает прямого ответа на ваш вопрос, но помогут ли средние бары?Другими словами, показывайте минимальное / максимальное / среднее / среднее значение, скажем, через 15 секунд, а не просто среднее значение.

...