3

I'm starting a test using Arduino to reproduce a set of temperature values in water each three hours and need some help with it.

I will use two ds18b20 sensors to control two thermostats connected to relays. The idea is that Arduino could access the data from a file in which there are simulated data for each day in the future. Something like this:

Date,Time,Temperature
01/01/2070,00:00:00,27.229211807251
30/12/2070,21:00:00,24.6133060455322
01/01/2070,06:00:00,22.1697025299072
01/01/2070,09:00:00,20.3209171295166
01/01/2070,12:00:00,27.7610721588135
01/01/2070,15:00:00,33.6277084350586
01/01/2070,18:00:00,34.5402450561523
01/01/2070,21:00:00,31.9973392486572
02/01/2070,00:00:00,26.2283573150635
02/01/2070,03:00:00,21.5823612213135
02/01/2070,06:00:00,18.6461429595947
02/01/2070,09:00:00,17.2126712799072
02/01/2070,12:00:00,24.8096561431885
02/01/2070,15:00:00,30.6440677642822
02/01/2070,18:00:00,33.8463973999023
02/01/2070,21:00:00,31.3529300689697
03/01/2070,00:00:00,25.2961673736572
03/01/2070,03:00:00,20.8135623931885

Based on this info the sensor will control the thermostat to decrease or increase the temperature within three hours (8 different temperatures by day). I'm going to start with 1 week (7 day x 8 temperatures = 56 simulations), but want to increment it till 3 months (720 simulations).

Considering the use of if/else if, it seems that would be a massive amount of conditionals.

Does anybody have a good solution to run this temperature simulation based on predefined data?

Thanks in upfront.

3
  • It is not clear to me, for what exactly you considered if/else if expressions. You have x data tuples with time and set temperature of the thermostat. So you could put these into an array, saving the current element index in a variable. Then you compare the time of the current element to the current time and set the setpoint of the thermostat accordingly. And you move on to the next element, if the time has come to do so. Is that, what you want?
    – chrisl
    Commented Mar 22, 2021 at 19:00
  • Thank you for the answer @chrisl. It seems quite reasonable what you suggest and exactly what I'm looking for! I've never worked with this approach so need to find out some documentation and reference about it.
    – s_tatus3
    Commented Mar 22, 2021 at 19:50
  • it makes no sense to store temperature using floating point values ... you are using 32 bits to store a 12 bit value
    – jsotola
    Commented Mar 23, 2021 at 0:49

1 Answer 1

2

You can use an array to go through the times.

Create a struct with the fields time and temperature (you should think about saving time as unix epoch, meaning seconds since 1970, so that you save memory).

struct SetPoint {
    unsigned long time;
    float temperature;
};

Then you can declare an array of type SetPoint to hold the tubles of time and temperature:

#define DATA_SIZE  720
SetPoint data[DATA_SIZE] = {
    {<time1>, <temp1>},
    {<time2>, <temp2>},
    ...
    };

In the above, you need to replace <timeX> and <tempX> by your data. Then declare a position variable, which the element index, which will be invoked next:

unsigned int pos = 0;

We are starting with the first element (index 0) and compare its time to the current time. If it is equal (or current time is after the elements time), we will set the thermostat to the elements temperature and increment the position variable. Something like this:

if(pos < DATA_SIZE && current_time >= data[pos].time){
    set_thermostat(data[pos].temperature);
    pos++;
}

Note: I used the variable current_time here as standin for your way of getting the current time, and the set_thermostat() function as a standin for your way of setting the thermostat. Also I inserted a check into the if statement, to prevent the code going further, when it reached the data array end.


That said, depending on the used board you can easily get into memory trouble here. An Arduino Uno does not have enough memory to save 720 of the data points above. float and unsigned long both take 4 bytes each, so 8 bytes per element, which makes 8*720 = 5760 bytes. The Uno only has 2048 bytes total in RAM. There are enough boards, which have more RAM. The ESP32 for example would have way enough (though there are many others; the ESP32 is just the first to get into my mind here).

Or you can add an SD card module to your build and save the data points in a file. That would also make it way easier to get the data in your project or change the data. It would just involving writing the corresponding file on your SD card.

Then the workflow would be a bit different. Lets assume you save one data point per line as text:

  • Open file and read one line. Close file.
  • Parse read text into 2 variables (time and temperature)
  • Use these variables for the if statement from above
  • if the time of the loaded data point was reached, open the file again, read the next line and parse it into the variables
  • The if statement now uses the next datapoint

and so on. If there is no line left to read, you could go into an infinite loop, stopping the code from running further than your data.

There are ready to use SD card modules to buy out there, and you can find many tutorials about how to use them online.


As Edgar Bonet correct stated in the comments, you can greatly reduce the needed RAM, when assuming regular intervals (3h in your case). Then you don't need to save the time for each data point. You only need the one start time for the series. Also above I used float for the temperature (as I assumed, that at this point it would be the easiest for you). But since temperature settings for thermostats are mostly working only down to the 1 digit after the decimal point, you can save memory space by using a different representation. For example you could save the temperature as a single byte signed integer with the unit of 0.1°C and a reasonable offset (for example 25°C being zero). So some example values would be:

Temp | value
------------
18°C | -70
20°C | -50
22°C | -30
25°C | 0
27°C | 20
35°C | 100

That would give you the precision of one digit after the decimal point and a range from 12.3°C to 37.8°C. When changing the factor of 0.1°C, you can also change the range (and precision with it) as you really need it.

So with the above you would only need 720 byte for the actual data, which is good for the Uno.

BUT: I would still suggest looking into the SD card reader. You will have more work building the project, but you won't have the same hassle with including or updating the data. That can come in especially handy, if you want to use to further use the device after the 3 months. Just loading new data on it (maybe even way more data, like for a full year) is easier with an SD card.

5
  • 2
    Note that if the times are regularly spaced (one setpoint every 3 hours), they do not need to be stored. The temperatures can be stored in 16-bits with a resolution of 0.001 °C, which is most likely already overkill. Commented Mar 22, 2021 at 20:47
  • 2
    @EdgarBonet Thanks, I added a paragraph about that in my answer.
    – chrisl
    Commented Mar 22, 2021 at 21:10
  • 1
    @s_tatus3 If you are going to connect the ESP32 to your wifi, you could also save the data in SPIFFS and write code, that lets you exchange the data over a website hosted on the ESP32. Might also be interesting for you.
    – chrisl
    Commented Mar 28, 2021 at 18:03
  • 1
    Fantastic! Yes, definitely will replace Arduino with ESP32 and use the data in a SD card. Already set epoch time (way better to work with). Just added the function set_thermostat() to control the relay and now will see the best way to set time to easily reuse it many times. void set_thermostat() { if (temperature < data[pos].temperature) { digitalWrite (relay, HIGH); } else if (temperature > data[pos].temperature) { digitalWrite (relay, LOW); } } Will back here to add whole code once is done. Thank you all the comments and support
    – s_tatus3
    Commented Mar 28, 2021 at 18:06
  • @chrisl just opened this question related to the sd file parsing. If you have some great insight about, they will be welcomed! :)
    – s_tatus3
    Commented Apr 21, 2021 at 22:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.