In Nordic countries the price of electricity is determined on the Nord Pool Spot exchange. Basically every day at 15.00 hourly prices for the next day are published. So in effect we have 24 separate tariffs for each day that are different on each day. When using electricity to heat a house and/or heat domestic hot water it would bring considerable savings to optimize heating system(s) so that electricity is mainly used when the price is low.
The house where this system is prototyped, developed and used is heated with underfloor water heating system. Heating water is heated with a simple electric boiler.
Before the installation of this new heating controller the heating system was controlled like this: In the heating season the circulation pump was always running and a simple adjustable capillary thermostat inside the boiler switched the 3-phase boiler heating element on and off by switching power to a 3-phase contactor. So basically the system worked on sensing the temperature of heating water pumped through the boiler. Very simple and effective solution.
The house has very well insulated walls, windows and roof. Inside the house has quite large thermal mass with the concrete floors and inside walls. So when heating system is turned off, in the middle of winter, the inside temperature dropping rate is quite slow. This makes it possible to turn off heating in the times when the electricity price is high and still be comfortable inside the house.
Electricity prices can be seen here: http://www.nordpoolspot.com
As before, when I built the initial heating system without a controller, I decided to use the KISS (Keep it simple, stupid) principle. Get something working and expand later on.
So, for the first iteration of "smart" heating control, the simplest way to extend the heating system was, to connect the IOT2020 with a relay module to the "external thermostat" connection contacts of the heating system. These contacts were just bridged for use without an external thermostat so far. I also had to rewire the circulation pump from always on to only on when heating element is switched on.
I adjusted the capillary thermostat to about 27C. So it is now a secondary failsafe switch-off. (There is also a third fixed temperature 90C failsafe thermo switch in series designed to prevent water boiling in the boiler)
The heating system diagram and electric circuit schematic can be seen on pages 5 and 6 in the original user manual for the heating system. I have attached the manual in PDF format to this project and made a diagram showing how I connected the IOT2020. See the schematics section below.
In this first iteration I decided to use only one temperature sensor located in the main living room. I had the temperature sensor working already before this project. The temperature sensor node publishes temperature with MQTT to my OpenHAB server which also runs the MQTT broker software Mosquitto.
On the IOT2020 I decided to use Node-Red. Because it was already available in the Siemens example image and I knew with Node-red it would be simple to interface the controller to my existing OpenHAB/MQTT system.
Basic IOT2020 setupFor basic setup I followed the documentation from Siemens and the tutorials here on hackser.io.
I installed the 2.1.3 image. Configured a USB wifi dongle. Set a fixed IP for the IOT2020 wifi adapter in my router. Enabled Node-red with the iot2000setup utility.
I did not enable and use Mosquitto on the IOT2020 because I already had Mosquitto running in my network on the Orange Pi board that runs OpenHAB. But for a stand alone controller Mosquitto on the IOT2020 can easily be enabled.
Time on the IOT2020The IOT2020 has no battery for RTC. Because my application requires Internet connectivity anyway, simply getting time from network is sufficient. The Siemens sample system image has no ntp client included. One solution would be a custom build with a ntp client included. But I saw that the rdate command from Busybox is available and used that. I created a script to get and set the time when the dhcp client gets and renews IP address. I used the nano editor:
nano /etc/udhcpc.d/99local
Contents of /etc/udhcpc.d/99local :
#!/bin/sh
case "$1" in
bound|renew)
rdate -s time.nist.gov
hwclock --utc --systohc
;;
esac
exit 0
And made the script executable:
chmod +x /etc/udhcpc.d/99local
I also needed to configure correct timezone on the IOT2020. For that I simply scp'd over the /etc/localtime file from my linux PC.
Price data from Nord Pool SpotI could not find any official documentation for a public API of NPS. The hourly prices can be seen on web at this link: www.nordpoolspot.com/Market-data1/Elspot/Area-Prices/ALL1/Hourly/?view=table. That page (and also every other script or library for the NPS prices) gets data as a massive json object from this URL: http://www.nordpoolspot.com/api/marketdata/page/10. By default you get latest data available. To get data for specific date one can add a get parameter endDate. For example endDate=30-03-2017
Looking at this massive json object I decided that instead processing it with javascript in Node-red I will get the data with curl and process it with the jq json processor in a shell script.
To install jq on the IOT2020 I downloaded the source tarball, unpacked and compiled with ./configure && make
. Then I copied the executable jq to /usr/local/bin folder.
After fiddling around with jq this is the final /usr/local/bin/getnps.sh
script:
curl -s http://www.nordpoolspot.com/api/marketdata/page/10?endDate=`date +%d-%m-%Y` | /usr/local/bin/jq '.data.Rows | .[0:24] | map({(.Name[0:2]|ltrimstr("0")|tonumber|.+1|.%24|tostring): .Columns[14].Value|split(",") | join(".")|tonumber}) | add'
First curl gets data for the current date and then the amazing jq utility does its thing. A little summary of whats happening there:
- Get rid of the min, max, avg etc prices at the end
- Output a simple json object with hours as key and price as value
- Add +1 to hours because I am in a timezone that is +0100 of NPS time
- 23 + 1 becomes 24, but needs to be 0, so I modulo every hour with 24
- Replace "," as decimal separator with "."
Output looks like this:
{
"1": 24.07,
"2": 23.69,
"3": 23.48,
"4": 22.94,
"5": 23.69,
"6": 25,
"7": 27.36,
"8": 33.97,
"9": 36.57,
"10": 35.6,
"11": 34,
"12": 33.08,
"13": 30.86,
"14": 28.32,
"15": 27.12,
"16": 27.53,
"17": 28.63,
"18": 32.05,
"19": 33.95,
"20": 33.16,
"21": 29.12,
"22": 29.34,
"23": 28.67,
"0": 26.72
}
If you do not need the time zone adjustment use this:
curl -s http://www.nordpoolspot.com/api/marketdata/page/10?endDate=`date +%d-%m-%Y` | /usr/local/bin/jq '.data.Rows | .[0:24] | map({(.Name[0:2]|ltrimstr("0")): .Columns[14].Value|split(",") | join(".")|tonumber}) | add'
You probably also want to adjust the script to the NPS price zone you are in. For that you need to change the number in this part: .Columns[14].Value
. 14 is for Estonia, 5 is for Finland and so on, see the original json for all possible values.
I could not use the relays on the otherwise excellent Arduino relay shield supplied with the IOT2020 contest package, because it has a maximum load voltage of 48V, but I needed to switch 230V. So I used a noname chinese relay module, that I had in my parts box.
I kept the relay shield on the IOT2020 to use its relays in possible future expansion project and because I could connect my external relay easily to the 3pin OUT6 connector.
There is however one issue with the relay module I currently use. It is a active low module and with the IOT2020 and Node-red this means the relay is switched on at IOT2020 boot time. In my application it is not a huge problem if the heating system is turned on at boot time for about 3 minutes. But it is best to use active high relay modules with the IOT2000 controllers. I will replace the module in the future with a active high version.
Temperature sensor nodeAs a mqtt publishing temperature sensor I use a ESP8266 based D1 mini clone with a SHT30 shield. SHT30 is a temperature and humidity sensor from Sensirion.
My temperature sensor software is based on the ESP8266 framework for Homie, a lightweight MQTT convention for the IoT. The full code is availible in the code section. Basically it just publishes the measured temperature and humidity to the mqtt broker on my network every 5 minutes.
I will not go too deep into the temperature sensor because this project is mainly about the IOT2020. Anything that can publish a temperature reading to mqtt can easily be used instead. For example you can use the very easy to use ESPEasy firmware with ESP8266. ESPEasy supports mqtt and many common temperature sensors.
Node-red flowsThe flows are available to import into your Node-red in the Code section further down on this page.
First flow: Getting NPS dataIt has two inject nodes. First one is configured to trigger everyday at 00:56 - that's 4 minutes before 01:00 at which time the new prices will come to effect for me (my time is +0100 of NPS time), the second one triggers once at startup.
Next is the exec node that runs the getnps.sh
script and gets its output which is then converted to javascript object by the json node. Now a custom function node sets the data as Node-red global object, so it is available to other flows. Finally data is also sent to the debug tab by the debug node.
Here the main node is the function node "Should we heat?". It is triggered by two possible ways, either a new temperature arrives per mqtt node "Temperature", which is also stored as a global. Or by a 5 min timer inject node.
Here is the code of "Should we heat?":
var maxprice = 35;
var settemp = 23;
var mintemp = 21;
var nps = global.get("nps");
var temp = global.get("temp");
var price = nps[new Date().getHours()];
var tempdiff = settemp - temp;
var pricediff = maxprice - price;
var state = {};
var statemsg = {};
var debug = {};
state.topic = 'devices/heatingcontrol/status';
statemsg.topic = 'devices/heatingcontrol/statusmsg';
debug.topic = 'devices/heatingcontrol/debug';
debug.payload = { 'temp': temp, 'price': price, 'tempdiff': tempdiff, 'pricediff': pricediff };
if (tempdiff <= 0) {
state.payload = 1;
statemsg.payload = "OFF temp higher than settemp";
} else {
if ((pricediff < 0) && (temp > mintemp)) {
state.payload = 1;
statemsg.payload = "OFF temp lower than settemp, but higher than mintemp, price higher than max price";
} else {
state.payload = 0;
statemsg.payload = "ON temp lower than settemp";
}
}
return [state,statemsg,debug];
Basically heater is turned on:
- always when temperature is less than 21C
- if price is less than 35€/MWh and when temperature is between 21C and 23C
First of the three outputs of this function controls the heater. Since my relay is active low, then 0 means heater will be on and 1 means it will be off. Second and third outputs are meant as debug info.
The first output is connected to mraa intel_gpio digital output node. The used pin number D6 corresponds to the 3pin header on the Arduino relay shield to which is the actual relay module connected. This output is also passed through another function node to invert the output and to turn on/off the (active high) user LED on the IOT2020 to indicate when the heater is switched on.
All three outputs are sent to the debug tab and also to the mqtt broker. The latter allows me to use the info in OpenHAB and display it on its UI and also log and graph when the heating system was turned on. Alternatively one can configure the 0/1 output to be also sent for example to Thingspeak so you can have nice graphs and check the latest status from anywhere.
I also have a "Test temperature" mqtt node to test the system with another mqtt topic than my real temperature sensor. For that I disconnect the real Temperature node and connect the test node. Then I use something to publish temperature on the testing channel. I used the MQTT Dash android app.
ConclusionThe system as described here in this project actually controls the heating in my house now. As of now the real world testing time has been quite short due to spring arriving and the heating season ending. Maybe next season some setpoints will need to be adjusted when the weather is really cold (lets say -25C).
I have to test and add code to deal with various error scenarios like internet connection going down - can't get NPS data, temperature sensor goes offline and stops sending data etc
Previously have been thinking about expanding the system by installing actuators on the floor heating collector, measuring the temperature in every room and in every section of floor heating system. This would enable precise zoned temperature control inside the house. The IOT2020 is an ideal platform for such expansion of my heating system. However having now lived some time with the basic heating system there has emerged a fact that somewhat hinders me going that route. Namely the simple system with only one temperature input from the large main living room works so well. So at least for now I will "Keep It Simple, Stupid" and "Not repair whats working".
I think however that I will look into controlling the domestic hot water heater and the ventilation system with the IOT2020 to also not use electricity at times when the price peaks.
Comments