ESP8266 IoT room thermometer – part 1

Impulsiveness is not always a good thing. So here’s a handy rule for you: first, prototype; then fabricate the PCBs. Doing it that way, things have a chance of going well. Reverse that order and … well, not so much.

Not that it was a disaster. In fact I had prototyped this little project – mostly. But we’re getting ahead of ourselves.

Wifi loveliness

There was a period when forums were constantly a-twitter with talk of the ESP8266, the miracle microcontroller with built-in wifi loveliness. And for a long time I mostly ignored it because I was busy elsewhere. Then I gave in and ordered a fewthe Adafruit Huzzah board, to be precise, because I trust Adafruit. I mucked about with MicroPython and thought, ‘this is rather nice’, then put it aside to concentrate on other stuff.

The prototype. The ESP8266 board is pushed into female headers soldered to a prototyping board. This also has tactile buttons mimicking the two buttons on the ESP8266 which I find very awkward to press. The whole thing is mounted alongside a breadboard on an acrylic base. This allows for easy experimentation.

But over winter I found myself with a need to know the temperature in my office. It wasn’t just a desire. I really needed this information.

As someone who suffers from osteoarthritis, I’m somewhat sensitive to temperature. If it drops too low, the pain in my joints increases notably.

Now, I could have just bought a digital thermometer (actually, I bought two) and set it up at my workstation. But where’s the fun in that? No, I wanted a thing – as in the Internet of Things (IoT).

So I dug out the ESP8266 boards and looked around for a suitable temperature sensor. I had a few lying around, but when I tried using them and compared the results with a digital thermometer I found they were somewhat inaccurate.

Eventually I settled on the DHT22. And then I learned a lesson. I bought a few, very cheap, from China via eBay. Not only didn’t they agree with the digital thermometer, they didn’t even agree with each other. It’s possible they were rejects. Then I bought a few more at slightly higher cost from reputable suppliers. These were consistent in readings, although still half a degree Celsius below the digital thermometer. I can live with that. And although it’s unlikely the error is linear across the full range of temperatures, within the limited range I’ll be experiencing in my office I should be able to just add a 0.5ºC compensation in the software if I want.

The sensor has four pins – VCC, GND, data out and one that isn’t used. You pull the data pin high with a resistor (I used a 10kΩ), attach it to a GPIO pin and then use the Adafruit library. Easy.

(BTW, I developed the code for this project in the Arduino IDE, in its usual dialect of C.)

As a display I opted for a 2.2in SPI-driven 240×320 TFT panel that I’ve used a lot with the Teensy with great success. I’m controlling this with the Bodmer TFT_eSPI library which provides for lots of nice fonts and easy text placement, once you get used to it.

The display shows the current temperature, rounded to the nearest integer (in Celsius, because I’m European and have forgotten why anyone bothers with Fahrenheit). Under that is the actual temperature to one decimal place, the minimum and maximum temperatures since the last reset (more on this in a moment) and the relative humidity.

Then come the time and date. Underneath those is a three-line area for various messages, including one just for errors. These messages disappear after a certain period (which is set in the code). Finally, there’s a line at the bottom showing the SSID of the wifi access point in use and the ESP8266’s IP address.

Time & date

I didn’t want to add a real-time clock. It was just too much complication and besides, the Huzzah board almost certainly wouldn’t have enough GPIO pins to accommodate it. To hell with that anyway because this is an Internet thing. If it wants to know the time it can just ask a server.

In terms of electronic components, then, there isn’t a lot more than the three main items – the ESP8266 board, the TFT LCD display and the temperature sensor. I needed a couple of resistors – one to pull the data line on the DHT sensor high and one to limit the current for the power supply to the screen’s backlighting. I also decided to add a reset button, so I added another resistor to pull that high too.

In spite of the simplicity, though, I decided to have a PCB made. It would save on a lot of wiring and would be smaller than, say, a stripboard solution. Besides, having started to get comfortable with KiCad I just like making PCBs now.

That’s when things got a little wobbly.

Mission creep

While drawing up the schematic I noticed I had three spare pins. Pin 0 on the Huzzah is a bit weird, being associated with the bootloader, so I decided to ignore that. But pins 15 and 16 were also unused.

This was about the same time I decided the display should show maximum high and minimum low temperatures. And I wanted a way of resetting that. No problem – I’ll add a second ‘reset’ button. Pin 15 seemed handy. I’ll pull that high with a resistor and then set up an interrupt to watch for it being pulled low, I thought.

Remember, this is after I’d built the breadboard prototype and while I was drawing the schematic. I was pretty confident it would work, so I went ahead and laid out the PCB and ordered 10 of them from a fab house (total cost $9 including shipping).

Then I added the new button to the breadboard prototype.

It didn’t work.

I’ll save you the agonies I went through. It turns out that pin 15 is also a bit weird on this board. According to Adafruit it is, “used to detect boot-mode. It has a pulldown resistor connected to it, make sure this pin isn’t pulled high on startup. You can always just use it as an output”. Damn. I couldn’t even upload new versions of the code to the ESP8266 board because I had this pulled high.

I switched to pin 16, but couldn’t get the interrupt to fire. So I tried pin 2. That worked with the interrupt, but on my board it’s tied up for use with the temperature sensor. I considered changing lots of pin assignments, but the thought was somewhat daunting.


In the end I redesigned the schematic and board layout and reworked the software to use pin 16 with simple polling, rather than using an interrupt. I still don’t know why the interrupt doesn’t work, but assume it’s somehow connected to the fact that the pin is used to wake the microcontroller from deep sleep.

I hadn’t considered polling before for one good reason – my original version of the code included a long delay (six seconds no less) in the main loop. This is because the device isn’t in any hurry to do anything. The main loop does the following:

  • Checks in with a server to update the time and date – once a minute is enough for this.
  • Checks in with a server to send the current temperature and humidity, so the server can log them and display the data on our intranet. A side-effect of this is checking the wifi connection is still good. Once every five or 10 minutes is good enough for this.
  • Checks and displays the current temperature and humidity – I figured five-minute intervals are good enough for this.

So I used a six-second delay in the loop and integer counters to decide when these actions should take place. That made polling for button pushes very haphazard because the processor was spending most of its time in a delay() function!

To sort that, I divided the delay time by 10 and multiplied the limits for the counters by the same factor to compensate. Now the delay time is 600 milliseconds – just over half a second. This works well because when you press the button to reset the min/max values there’s that slight delay before it happens. You have to be very deliberate about it, which I think is a good thing in a reset button. Also, the delay debounces the switch.

The PCBs I ordered should still work, I just won’t solder in the headers for the min/max reset button and the associated pullup resistor. If I want to reset the minimum and maximum values I’ll just reset the whole shebang with the main reset button.

In the next part I’ll talk about how it talks with the server.

» Read Part 2 »

2 thoughts on “ESP8266 IoT room thermometer – part 1

  1. Richard P

    Done a similar toy, but different mission requirement. The DHT11 is a dismal device and much like you, I went with the DHT22. I still didnt trust the DHT so I also added the DS18B20 1Wire temperature sensor as a belt-and-braces. Connectivity was via MQTT to a server, but I dont think its a good idea to keep a device running just to serve the temperature. My next version will have its own web server and dish out JAVASCRIPT to I can see the history. For power failure modes, a supercap and some code to detect the input voltage being unstable triggered a SPIFFS write of the history data before it shut itself down. All data was timestamped as the ESP8266 synced to a NTP clock.

    I wanted an outdoor sensor, so I built it all in to a PVC tube. As a radio amateur, I have a mast that has power points so getting power outdoors is an easy task.

    1. Machina Post author

      Hadn’t thought of using NTP for the clock – I think I’ll look into that.


Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.