I’ve been working through the examples in the WebServer course and decided to tweak the weather sensor example by changing the direction of the arrows on the atmospheric pressure reading to indicate whether the pressure is rising or falling. To do this I look at the current pressure reading and the moving average of the past 24 readings to determine the status. In doing so I came up with a quick, easy, and efficient way to store recent sensor data that others might find useful as well. I hope this is helpful!
Problem: I want to store the most recent N sensor readings to be able to access them for analysis and also to obtain a moving average. Readings older than N are removed so the data doesn’t grow over time.
Approach: Use a double ended queue (deque) from the c ++ standard library. Load it initially with impossible sensor values. As each new reading comes in push it into the front of the deque and pop the oldest item from the back. Check to see if the last item is the same as the initial value. If not, then enough readings have been entered to fill the deque and valid calculations can be made. The c++ standard accumulator is used to calculate the moving average. This approach is very memory efficient.
Example: In the example below, the last 24 readings are stored. Each pass through the loop adds a new value and prints out a summary of the current values. This was tested on an ESP32 device using the Platformio IDE
https://pastebin.com/DEiwN95C
#include <Arduino.h>
#include <deque>
#include <iostream>
#include <numeric>
//initialize the double ended queue to length 24 and values 999.0 (impossible reading)
std::deque <float> seq1(24,999.00);
std::deque <int>::size_type i; //set data type for deque size descriptor
float listindex = 0.0; //initialize data to be stored
bool datavalid = false; //are there 24 valid items in the deque?
void setup() {
// put your setup code here, to run once:
// no code here
}
void loop() {
// put your main code here, to run repeatedly:
delay(3000);
Serial.println(“opening code”);
listindex += 1.5; //set value to add to queue
seq1.push_front(listindex); //add newest value to front of queue
seq1.pop_back(); // remove oldest value from back of queue
//calculate the moving average of the queued values
float mavg = std::accumulate(seq1.begin(),seq1.end(),0.0)/seq1.size();
//see if data is valid yet
if (seq1.back() < 999.0 ){datavalid = true;}
//print summary
Serial.print(“Is data valid? “);
Serial.println(datavalid);
Serial.print(“The third element is “);
Serial.println(seq1.at(2));
Serial.print(“The last element is “);
Serial.println(seq1.back());
Serial.print(“The queue length is “);
Serial.println(seq1.size());
Serial.print(“The moving average is “);
Serial.println(mavg);
}