Rolling 24 hour window for temperature and humidity

Hi,

I've never used an Arduino before, but was thinking this might be a suitable use case for one?
The idea is that there would be a sensor that would measure the current room temperature and humidity every minute, and display it on a screen. The screen would also display the highest and lowest readings over the past 24 hours.
Is this a suitable use case for an Arduino, and if so, what board would you recommend, and any particular sensors and displays?

Thanks!

That is a fine example of an Arduino application, and any Arduino can handle it.

An Adafruit TFT Feather would be an option with a small built-in display. The smaller Arduinos generally don't have enough memory to handle a large display.

The search phrase "arduino temperature humidity" will turn up many examples and tutorials.

1 Like

Something like a TTGO Display, and add a BME280 for the sensor, and you get barometric pressure too.
You could even host a web server on it.

A reading every minute for 24hrs is 1,440 readings. Many of the most common and basic types of Arduino have only 2,048 bytes of memory, and you can't even use all of that because some is reserved and some is needed for your other program variables. So with these types of arduino you can only afford to use 1 byte to record each reading. So long as you only want to record the temperature to the nearest 1C, that's enough. But if you want to record temperature to the nearest 0.1C it would be difficult. If you want to store 1,440 humidity readings as well, then some additional memory will be needed with these types of Arduino.

To record both temperature and humidity, including decimal places, is most easily done using the float data type. But that requires 4 bytes each for temp and humidity, x1440 = 11.5KB of memory. Even an Arduino Mega does that have that much. But many more modern, 32-bit Arduino have more than enough.

The type of display you want to use can also need quite a lot of memory. Character LCD (16x2 or 20x4) need very little, but graphic LCD, TFT and OLED displays require much more and this, and this can also be tricky on those Arduino with smaller memories.

Just to get you off the ground, take a look at the Smoothing Example. It takes a reading every millisecond and saves the readings in a 10-element array, which is used as a "circular buffer". It always holds the 10 most recent readings and it takes an average.

Note that you don't have to "shift" or "move" the data... You just overwrite the oldest reading with the newest. (And when you get to the end of the array, reset the "pointer" and start-over at element zero.)

I have an application where I do something similar but I save a reading once per second in a 20-element array. So every second I update the array with a new reading and I find the new average and maximum values (for the last 20 seconds).

Thanks everyone for the replies so far!

jremington, is an Adafruit TFT Feather an Arduino, or a similar/rival product?

SemperIdem, is the TTGO (this?) just a display, or does it also contain an Arduino too? If I'm understanding correct, it's an Arduino with an display built in?

PaulRB, I don't think I'd actually need to store all 1,440 readings, if I can use something like C++'s deque. I could just store a monotonically decreasing queue of temperatures, removing items from the beginning/end as appropriate. It would be enough for me to measure to the nearest 1C too. I also imagine a simple Character LCD should be enough too, as I just need to be display basic text and numbers. No need for colours or graphics.

Purists would say it's not an Arduino, but it has extensions available to the Arduino IDE that make it programmable using the Arduino C++ dialect.
It's an ESP32, with WiFi, Bluetooth and display.

So, a 2x16 LCD, and a button to cycle through Current, Max, Min sort of thing, for the two or three values a BMP280 presents? Sounds simple and easy. Displays like:

CurT CurH CurP
val val val

MaxT MaxH MaxP
val val val

MinT MinH MinP
val val val
Apologies, proportional fonts are a mess, but you get the idea.

It is a microcontroller with display that can be programmed using the Arduino IDE. There are many such, not designed or produced by the Arduino company.

Assuming a reasonably narrow temperature range, you could consider using an array to store the last time a certain temperature has been measured using the temperature as the index (possibly with some offset correction). The minimum is the index of the first value in the array set less than 24 hours ago. By iterating over the array backwards the maximum can be found.

[edit]

Here is a possible implementation.

long readTemperature() {
  return random(-20, 30);
}


unsigned long pMillis() {
  unsigned long const now {millis()};
  return now ? now : 1;  // Timestamp 0 is reserved.
}

template <size_t n> size_t findMinimum(unsigned long const (& measurements)[n], unsigned long const timespan) {
  unsigned long const now {pMillis()};
  for (size_t i {0}; i < n; ++i) {
    if (measurements[i] and now - measurements[i] < timespan) {
      return i;
    }
  }
  return n;  // Should be unreachable.
}

template <size_t n> size_t findMaximum(unsigned long const (& measurements)[n], unsigned long const timespan) {
  unsigned long const now {pMillis()};
  for (size_t i {n}; i--;) {
    if (measurements[i] and now - measurements[i] < timespan) {
      return i;
    }
  }
  return n;  // Should be unreachable.
}


void setup() {
  Serial.begin(9600);
}

void loop() {
  static unsigned long measurements[50] {};
  long const offset {20};  // Temperature is between -20°C and 30°C.

  long const temperature {readTemperature()};
  measurements[temperature + offset] = pMillis();

  Serial.print("Current: ");
  Serial.print(temperature);

  Serial.print(",  Minima (3s, 6s): ");
  Serial.print(findMinimum(measurements, 3000) - offset);    // Minimum over the last 3s.
  Serial.print(", ");
  Serial.print(findMinimum(measurements, 6000) - offset);    // Minimum over the last 6s.

  Serial.print(",  Maxima (3s, 6s): ");
  Serial.print(findMaximum(measurements, 3000) - offset);    // Maximum over the last 3s.
  Serial.print(", ");
  Serial.println(findMaximum(measurements, 6000) - offset);  // Maximum over the last 6s.

  delay(1000);
}

On a (simulated) Mega2560, this is the output.

Current: -13,  Minima (3s, 6s): -13, -13,  Maxima (3s, 6s): -13, -13
Current: 29,  Minima (3s, 6s): -13, -13,  Maxima (3s, 6s): 29, 29
Current: 3,  Minima (3s, 6s): -13, -13,  Maxima (3s, 6s): 29, 29
Current: -12,  Minima (3s, 6s): -12, -13,  Maxima (3s, 6s): 29, 29
Current: 10,  Minima (3s, 6s): -12, -13,  Maxima (3s, 6s): 10, 29
Current: 2,  Minima (3s, 6s): -12, -13,  Maxima (3s, 6s): 10, 29
Current: 24,  Minima (3s, 6s): 2, -12,  Maxima (3s, 6s): 24, 29
Current: 8,  Minima (3s, 6s): 2, -12,  Maxima (3s, 6s): 24, 24
Current: 3,  Minima (3s, 6s): 3, -12,  Maxima (3s, 6s): 24, 24
Current: -11,  Minima (3s, 6s): -11, -11,  Maxima (3s, 6s): 8, 24
Current: 20,  Minima (3s, 6s): -11, -11,  Maxima (3s, 6s): 20, 24
Current: -5,  Minima (3s, 6s): -11, -11,  Maxima (3s, 6s): 20, 24
...

You can add as many periods (last hour, last day, last week, etc.) as you like. The maximum time span can be extended by storing seconds or minutes instead of milliseconds (e.g., store pMillis() / 1000, this can also be used to cut down on memory requirements instead (e.g., change the type of measurements to uint16_t[]).

1 Like
// This records the low value over the last 24 hrs

float outTemp;                                            //outdoor temp
float outMin = 0;                                         //outdoor min temp in time interval

unsigned long previousMillis = millis();                  // Last time the counter was reset (initialize to present time).
//const long    interval24 = 86400000;                    // 24 hour interval in milliseconds.
const long    interval24 = 60000;                         // 1 minute test interval in milliseconds.
unsigned long soFar;                                      // Time since the last low reading.

void setup() {                                            // Setup temperature readings here
  Serial.begin(115200);                                   // Start Com port
}

void loop() {                                             // Add real code to read temperature here
outTemp = random(0, 100);                                 // Random temperature generator, used for testing.
unsigned long currentMillis = millis();                   // Record time now.
  if (currentMillis - previousMillis >= interval24 ||     // Has 24 hours gone by...
     outTemp <= outMin ) {                                // ...or has a new low temperature occurred?
    outMin = outTemp;                                     // If so, record the new low temperature and...
    previousMillis = currentMillis; }                     // ...start the 24 hour counter over.
soFar = currentMillis - previousMillis;                   // Calculate the time since the last low reading, in milliseconds.
Serial.print("Temperature: "); Serial.print(outTemp);     // Print test values to serial port.
Serial.print(", 24 hr minimum: "); Serial.print(outMin);
Serial.print(", Time since last min "); Serial.println(soFar);
delay(1000);                                              // Wait 1 second between readings.
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.