movingAvg library tested with STM32

Working libraries, libraries being ported and related hardware
Post Reply
AndrewBCN
Posts: 105
Joined: Sun Apr 25, 2021 3:50 pm
Answers: 1
Location: Strasbourg, France

movingAvg library tested with STM32

Post by AndrewBCN »

Just wanted to note that the movingAvg Arduino library was marked as AVR only by the author, but has been successfully tested with SAMD, ESP and now STM32 (by me), so I forked it, edited the library.properties file, and sent a pull request to the author.

This is a neat little library that provides a moving average smoothing filter, for example for ADC readings.

https://github.com/JChristensen/movingAvg

I am using it in my STM32 GPSDO project to smooth out all the voltage readings, which are very noisy otherwise, and it works fine.

If you install it without the patch and try to compile it for any architecture except avr, it generates a warning during compilation. With the patch, no warning.
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: movingAvg library tested with STM32

Post by fpiSTM »

Thank you @AndrewBCN
mrburnette
Posts: 633
Joined: Thu Dec 19, 2019 1:23 am
Answers: 7

Re: movingAvg library tested with STM32

Post by mrburnette »

In my experience, sometimes Arduino libraries "abstract" just too much for simple programming; that is to say, writing one's own function gives one an appreciation for the process and avoids simply using a library as a "black box."

IMO: To move beyond the Arduino weekend coding mentality, it is necessary dig a bit into the libraries used and to understand the implication. Recreating simple functionality and comparing a test-case to the canned library results is a great way to learn and bridge gaps in knowledge and maybe make your programs a bit more lean at the same time.

For example, consider an engine monitor built around a variety of analog sensors, mostly thermistors. My requirements were 9 sensors with a rolling average as explained below:
The test matrix is 45 integer values, arranged in 9 rows of 5 columns.
[ROW] represents the function + specific analog input pin #
Example:
A0 is allocated to water temperature. WaterTemp_AnalogIn is the pin-name variable representing A0
Functions simply "set" ROW variable, call the analogAverage function with the analog pin name.
ROW must be specified because the pins are not contiguous... A0, A1, A2, A3, A4, A10, A12, A13, A15 == 9 pins alias names == [0 - 8]
The averaging matrix is hard-coded at the moment (easily expanded) to maintain 4 old values and the current analog input.
The total loop() cycle time is 750mS, so the OLED displays should come to read average values in under 4 seconds.

Mofified all analogRead statements to average across Average_Depth as AReadAvg[Y][Average_Depth] where Y ==
[0] = WaterTemp_AnalogIn X = [0], [1], [2], [3], [4]
[1] = OilTemp_AnalogIn X = [0], [1], [2], [3], [4]
[2] = OilPres_AnallgIn X = [0], [1], [2], [3], [4]
[3] = FrontCylTemp_AnalogIn X = [0], [1], [2], [3], [4]
[4] = RearCylTemp_AnalogIn X = [0], [1], [2], [3], [4]
[5] = Ampres_AnalogIn X = [0], [1], [2], [3], [4]
[6] = Voltage_AnalogIn X = [0], [1], [2], [3], [4]
[7] = FuelQty_AnalogIn X = [0], [1], [2], [3], [4]
[8] = FuelPres_AnalogIn X = [0], [1], [2], [3], [4]

Code: Select all

// Ray Burnette 2017
#include <Streaming.h>                       // library can be found here: http://arduiniana.org/libraries/streaming/
#define DIAG false // or true

const int Average_Depth = 5 ;                // can be changed at expense of loop{} total time
int AnalogAverageMatrix [9][Average_Depth];  // 9 is based on A0, A1, A2, A3, A4, A10, A12, A13, A15

int analogAverage ( int ROW, int ApinNo )
{
    int ReadVal = 0;
    // Rollup ... small matrix, just assign for testing, could be a for() if desired
    // Oldest value is [0], newest value [4]
    AnalogAverageMatrix [ROW][0] = AnalogAverageMatrix [ROW][1];
    AnalogAverageMatrix [ROW][1] = AnalogAverageMatrix [ROW][2];
    AnalogAverageMatrix [ROW][2] = AnalogAverageMatrix [ROW][3];
    AnalogAverageMatrix [ROW][3] = AnalogAverageMatrix [ROW][4];
    // do two reads ... as a test, but one should really be enough IMO
    ReadVal = analogRead( ApinNo ); // delayMicroseconds( 10 );
    AnalogAverageMatrix [ROW][4] = analogRead( ApinNo );
    if ( DIAG) Serial << ROW  << ": " << AnalogAverageMatrix [ROW][0] << ", " <<  AnalogAverageMatrix [ROW][1] << ", " << AnalogAverageMatrix [ROW][2] << ", " << AnalogAverageMatrix [ROW][3] << ", " << AnalogAverageMatrix [ROW][4] << endl ;
    // now perform an average [0] -> [4]
    /*ReadVal = 0;
    for (int x = 0; x < 5; x++) {
      ReadVal += AnalogAverageMatrix[ROW][x];
    } */
    // Yes, a bit more flexible solution would be to loop
    ReadVal = AnalogAverageMatrix [ROW][0] + 
              AnalogAverageMatrix [ROW][1] + 
              AnalogAverageMatrix [ROW][2] + 
              AnalogAverageMatrix [ROW][3] + 
              AnalogAverageMatrix [ROW][4] ;
    ReadVal = ReadVal / Average_Depth;
    if (DIAG) Serial << "Average for " << ROW << ": " << "is " << ReadVal << endl;
    return ReadVal;     // The average is returned to calling function
}

Post Reply

Return to “Libraries & Hardware”