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
}