Skip to main content
added 1570 characters in body
Source Link
chrisl
  • 16.5k
  • 2
  • 17
  • 27

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.


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.

Source Link
chrisl
  • 16.5k
  • 2
  • 17
  • 27

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.