Micropython ESP8266 and DS18B20 “Open the Windows” DIY Sensor

Nathan Wells
10 min readAug 23, 2019

--

During the summer I like to open our windows in the morning to let the cool air in, but the problem is sometimes I forget to close them, or even when I do remember, I’m not sure if I should close them yet or keep them open a little longer (based on the outside temperature and inside temperature difference). Enter a DIY project with my newly learned Micropython skills.

I wanted to create something that would send a push notification to my phone letting me know that I should close my windows in the morning because the temperature outside was almost equal to the temperature in my house and also let me know when to open my windows in the evening to maximize my use of God’s free air-conditioning.

And since I had to scour the Internet to figure out how to do this (especially for the push notifications), I thought I would post a tutorial here to make it easier for everyone else.

You can view my completed Micropython code on Github here.

So we start with an ESP8266 board, a DS18B20 temperature sensor, a SSD1306 I2C OLED 128x64 display, breadboard, and some wires. Here’s a list of parts if you want to buy them:

First, you’ll need to load Micropython on to your ESP8266 board. You can read how to do that here: https://docs.micropython.org/en/latest/esp8266/tutorial/intro.html

Hooking Up the DS18B20 Temperature Sensor

It took me a while to figure out how to do this. Mainly because the pin labels on the ESP8266 don’t have the raw pins you use in Micropython. But here’s a diagram I found that will help you hook it up correctly (if your DS18B20 is already mounted on a board with resistors, connect GND on the sensor to a GND on the board, VCC to a 3V3 on the board and then the DQ to an open pin on the ESP8266— I chose D1 which is actually raw pin number 5). If your DS18B20 is just the plain sensor, you can see how to hook up the needed 4.7k Ohm Resistor and the sensor to your ESP8266 here: https://learn.adafruit.com/assets/3781
or https://randomnerdtutorials.com/esp8266-ds18b20-temperature-sensor-web-server-with-arduino-ide/

Image Credit: http://www.thesmarthomehookup.com/post-320/

Let’s test the sensor and make sure it’s working:

import machine, onewire, ds18x20, time#Make sure you change this to the pin you chose.
ds_pin = machine.Pin(5)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))
roms = ds_sensor.scan()
print('Found DS devices: ', roms)
#Loops every 5 seconds forever
while True:
ds_sensor.convert_temp()
#It's important to wait so the conversion can take place
time.sleep_ms(750)
for rom in roms:
print(rom)
print(ds_sensor.read_temp(rom))
time.sleep(5)

Use Ctrl-C to stop the script once everything is working correctly. I found my temperature sensor was a little off (and I ended up ordering a new one because I think my first one was a fake) so keep that in mind as we proceed to the next sections.

Connect the SSD1306 I2C OLED 128x64 Display

Attach the display to the ESP8266 with the bread board jumper wires (I didn’t connect the OLED to the bread board so I could mount it in the box. GND to GND, VCC to 3V3, SCL to D4 and SDA to D3.

Image Credit: https://blog.squix.org/weatherstation-wiring-and-first-run

Test to make sure you have everything connected correctly by running this code in Micropython.

from machine import *
import ssd1306
iic = I2C(scl = Pin(2), sda = Pin(0))
oled = ssd1306.SSD1306_I2C(128, 64, iic)
oled.text('Hello', 20, 10)
oled.text('World!', 30, 20)
oled.show()

Setting up Pushbullet and IFTTT

Next let’s setup push notifications on Pushbullet with IFTTT. So first, go to pushbullet.com and setup a free account (and setup a device, like your iPhone or Android by downloading the app).

Next, head over to ifttt.com and open a free account. Once logged in, you’ll want to click the user menu and choose “create” (my account is already setup, so it might look a little different for you).

Then click on the IFTTT Platform link.

Once you are in the IFTTT Platform (just sign up for the free teir), click on “Applets”

Then click “New Applet”

You’ll create two new Applets. One for opening the windows and one for closing them. So first choose “Webhooks” as the trigger.

And then select “receive a web request” from the drop-down menu.

Then name the “Field label” and “Default value” (they can be whatever you want, just remember what you named the “Default value” because we will use that to trigger the push notification).

Then click “Add action”.

And find “Pushbullet” and select it (you’ll need to give IFTTT permission to access your Pushbullet account — just follow the prompts).

Then give your Applet a title and description and click “Save”. And then create another identical Applet but this time for the “Close Door” notification.

Once you have both Applets created, go to the Applets tab and click on the title of one of your Applets.

Then click on the title again.

Then click to connect your Applet.

And repeat for the other Applet.

While you are here, click on the Webhooks icon as well.

And then click on “Documentation”.

You’ll be taken to a page that gives you the url you will use to send push notifications to your device from our Micropython code. Populate the “{event}” with the default value in your applet (like “open_windows” or whatever you chose) and test it out! You can also pass additional values in the url (like the current temperature inside and outside), but I found it made my code unstable on my board (I’ve found the ESP8266 to be pretty unstable personally). Take note of the url and copy it down so you can use it later in our Micropython code.

But if you want to try, here is how you would do that: https://maker.ifttt.com/trigger/window_close/with/key/YOUR_KEY?value1=12&value2=44

Get an Openweathermap.org API Key

Alright! We’re getting close to being able to code something in Micropython! But first we need to be able to get the outside temperature, and we’ll do that with the OpenWeather API. Go to https://openweathermap.org and create an account. Once you are signed in, go to your user profile and click the “API” tab and generate an API code. Copy the code so you can use it in the Micropython code.

Next, find the City ID for the city you live in and copy the city ID from the url so you can use it in the Micropython code.

Micropython Code Walkthrough

You can grab the completed code from Github here but I thought it would help if I walked through some sections of the code and explained what it was doing so you can easily modify it for your own use.

We’ll start at line 17 in the code.

First, you’ll need to add your own openweathermap.org API key in weather_api_key, change the city ID in city_id, choose your units in weather_units, and add your IFTT urls in iftt_close_window_url and ifttt_open_window_url.

If you want the ability to easily connect to multiple WiFi networks (so you can use the code in multiple locations), you can add those SSIDs and passwords (if not, just delete the other entries and the trailing comma) in dict_of_wifi.

Also, if your temperature sensor isn’t calibrated correctly, you can add an offset with temp_offset.

Then set your time-zone using the time_zone variable. This enables us specify when the program should send notifications.

And finally, specify what pin DQ the pin on the DS18B20 sensor is attached to on the ESP8622 board using temperature_pin (in my case it was attached to pin 5).

Next, we’ll jump to line 140 in the main code.

I found that my ESP8622 was rather unstable and I wasn’t able to create many functions without getting memory errors, so pretty much all the code is in-line and in a try statement so we can reboot the device if there are any errors thrown.

Here we are using the file_exists() function to check whether or not we have created a text file that holds the state of our open_windows and close_windows variables (this is so we don’t keep sending push notifications, but just send it one time each period). I ended up loading the states into a file so that if the device errors, the states are still remembered and I don’t keep getting the same push notification over and over).

Now we’ll look at line 154 (and the called function at line 72) which deals with connecting to WiFi.

I had issues connecting to WiFi in my boot.py (because I didn’t want to start my code until there was a connection — and I wanted to re-connect if the connection was ever dropped) and so I decided to deal with it directly in my script and make it robust with ten retries, as well as checking on the available SSIDs and connecting to a known one (on the fifth try) so we don’t just rely on the devices internal memory for previous WiFi connections.

Next starting on line 162, we grab the current time from the internet using ntptime.

There were some issues with errors, so I have this retry ten times if needed with a second pause in between each try. We then grab the hour (in 24 hour format) so we can use that to prevent push notifications when it wouldn’t be appropriate (like I don’t need a notification at 2am to open my windows).

Now on to line 170 where we do our openweathermap.org API call.

This is pretty self-explainatory. And of course you could grab some other values if you wanted to use them in your own project as well. I left the pressure and humidity there, but commented them out since I didn’t use them.

Then starting on line 212 we have the logic for sending push notifications.

I’ll walk through the if statement for closing the windows.
If the current temperature outside (from the API) plus two degrees is greater than the inside temperature (I wanted to close the windows a little before the temperatures were equal) AND
If the outside temperature is less than the inside temperature plus five degrees (this is so if it is 90 degrees outside and 75 inside the code won’t send me a push notification, because I don’t feel I needed one at that point) AND
If it is after 3PM AND
If a push notification has not already been sent telling me to close my windows (the close_windows variable is reset when the script sends a push notification telling me to open my windows).

When we send a push notification, the text file that stores our states is updated. For whatever reason I ran into a lot more errors if I loaded the file into memory and re-wrote each json variable, so I just re-write the whole file each time.

And on line 230 I added an animation (a sun icon) so I could make sure the code was running and not frozen.

The code loops through 50 times and the animation plays every 9 seconds which means my main loop will run every 15 minuites.

That’s All Folks!

And that’s it! Grap the code from my Github page here and enjoy! If you want to run the code when you boot your ESP8266 rename the file open_windows.py to main.py

I’d love to get your feedback — let me know your thoughts in the comments section!

--

--