Wireless floor heating thermostat

We installed infrared floor heating film. It has not yet been connected, lacking a thermostat. My idea from the start was to use Arduino or compatible to build the thermostat myself. There were some reasons for that: it was cheaper than a ready built device, more flexible and an excellent reason to get started with Arduino.

So, to prevent any misunderstandings: although the floor is not wired yet, it is not wireless. The thermostat will be wireless on one end, the end to the user interface. From the thermostat to the floor it wires all the way down.

In the mean time the parts have arrived:

  • ESP32, the brains of each thermostat
  • Relays, to actually switch on or off the infra red film
  • 10k NTC’s are already under the floor, together with the film itself

The separate functions I need/want to integrate are easily found, and integrating them went quite quickly at first. The result was almost what I needed, lacking only the sensor for ambient temperature. And it only would work in the wrong order. Which functions are they and what went wrong in the first iteration?

  • Temperature measurement
  • Thermostat setting
    • On the one hand ambient temperature: the temperature we find comfortable in the room
    • On the other hand the floor temperature: the floor temperature is not allowed to raise above 29 degrees Celsius
  • Switching a relay based on measured temperature and thermostat setting
  • Accessible via WiFi on the internal domotica network

As stated, each separate function got its examples for Arduino as well as, fewer, for ESP32. I ended up with a loop that:

  • Connect to WiFi
  • Shows a web interface to turn on or off the relay
  • Measures the temperature on pushing the on or off button
  • Actually switching on or off based on measured floor temperature

So the thermostat would not interfere with the relay until a button was pressed. The loop should work in reverse order:

  • Check relay state
    • if off, measure ambient temperature and compare to thermostat value
    • if on, measure floor temperature and compare to set maximum temperature
  • Depending on above, switch the relay state or keep as is
  • Connect to WiFi for a minute
  • Show the web interface
  • Allow the thermostat to be set
  • Return to above

The next step is to have a domotica server serving the thermostat interface, and the ESP querying the domotica server every now and again for changes. That way, less time is spent broadcasting a web interface via WiFi, improving power efficiency and security. At first it will be a stand alone setup though.

Pins

What connections/pins do I need? Which pins are they on the board?

  • Ralay; the relay needs three pins:
    • Ground;
    • VCC, the relay needs 5V, but it sits on a PCB with additional logic to let it switch with 3.3V supplied;
    • Switching signal, 3.3V as well; that also drives the process towards the “floor is to hot”- or the “room is not warm enough”-branch.
    • I’m free to use any digital-out pin for this
  • Floor sensor; the floor sensor needs three pins as well:
    • Ground;
    • VCC, any, as long as it is known and constant. I’ll use 3.3V as supplied by the ESP32;
    • Sensor pin;
    • The sensor-pin; any analog-read pin will do. It will read the voltage ‘halfway’ the ground-NTC-sensor-resistor-VCC series. The read voltage is then converted to a temperature.
  • Ambient sensor; just like the floor sensor:
    • Ground;
    • VCC;
    • Sensor pin / analog read.

I have some trouble converting the pin-examples I find on the Net to the actual pins on my ESP32. The names of the pins in those pictures are just a few letters different from the names of the pins silkscreened on the PCB. The pins that are supposed to be called ‘sensor VP’ and ‘sensor VN’, are called ‘SP’ and ‘SN’, and are moved one pin because I got an extra 3.3V pin on one side and extra GND pin on the other side.

Most of the pins are called Gnn, with nn being a number ranging from 0 to 36, in seemingly random order. G0 is between G2 and G4, and then G17 and G16 come before G5. G could stand for GPIO, and sometimes they match the notation on the images I find online. Of course not all options for each pin can be silkscreened on the tiny PCB. With my currently limited knowledge of Arduino programming, it does not help understanding the code I find in the wild. How should I assign a name to an input or output? Lets just try it with simple programs, building and understanding from there instead of hacking something together and hoping for the best: there is no lack of basic tutorials, it just takes some time to apply them to my ESP32-board, test its behaviour and measure electric properties of pins.

Test with ‘touch’ pin

While reading up on the pins and how to interact with them, I come across an explanation of ‘touch’ pins. They presumably can be used as input by just touching them. I’ll make sure to test that and keep it in mind as another way of setting the temperature.

Actually writing a simple program myself has taught me more than reading five of them and then flinging together something complicated to see what sticks. Namely:

  • Arduino is touchy about casing. Be sure to write analogRead, not analogread or Analogread: it won’t be recognized.
  • Same goes for semicolons. Forget one, and the compiler complains that there is an unexpected } instead of a ;
  • Prototyping is fast once you got something you understand that is working.
  • Use the right function for the type of input you’re working with. In case of the touch pins:
    • My first guess was using analogRead. It ‘works’, giving 12 bit high values (4095) when licking the connected wire or touching either the 3.3V or the 5V pin, 0 when connecting with GND. Using my fingers, the most intuitive way to interact with touch interfaces, gives fluctuating readings. Above 2000 when I draw blood with the pin, slowly descending values when I let go of it. Conclusion so far: it might work, but only when using more than one button and reading all of them to infer which one actually has been touched (and educating users not to touch more than one button at a time).
    • Next up was digitalRead. That gave 1 instead of 4095, 0 just as analogRead, and random 1 or 0 in between.
    • The actual function to use for touch pins is touchRead. It gives quite low (10+/-10) readings when touching the pin, and around 60 when not touching. Surprisingly, it gives 1 when touching 3.3V and 0 for GND,
    • The wire tastes as if there is some current on the line, my multimeter gives 0.7V as the amount between ground and GPIO4/T0 on the one hand and 0.6V between GPIO4/T0 and 3.3V. From GPIO4/T0 to 5V gives 2.1V, so there is some more logic involved somewhere behind GPIO4/T0.
  • Pins can be assigned in the header, above ‘void setup()’, using four indicators:
    • Type, for example ‘int’;
    • Name of the variable for the pin, for example ‘touch_pin’
    • Assignment using the equal sign (=);
    • GPIO number, just ‘4’ in this case;
    • Don’t forget the semicolon!
    • The whole assignment looks like: int touch_pin = 4
    • While reading: touchRead (touch_pin)
  • Pins can be read inline without assigning a variable as well: just write the number of the GPIO on the spot where it is needed:
    • touchRead (4)
  • Arduino is not touchy about spaces between brackets and letters. A space “touchRead ( 4 )” gives the same result as no space “touchRead(4)”.

For future reference, the file with the code is attached.

Print this entry

Leave a Reply

Your email address will not be published. Required fields are marked *