When you play with new microcontroller, first thing you usually do is driving an LED. That’s a classic “Hello World!” project for microcontrollers. That’s what I did when I was playing first time with ESP8266 and MicroPython. Let’s move on, and implement another classic project – measuring temperature and humidity with DHT22 sensor. But we don’t want to be quiet, so we are going to share this so important data on the Internet. ThingSpeak will help us with it. Let’s add a new warrior to the army of Internet of Shit!
For this project we’re going to use ESP-07 version of ESP8266. You can also use ESP-12 without any changes for the circuit below. But if you use other modifications of ESP8266, then you may need to modify a bit the circuit below.
Here is the circuit I used:
The circuit is similar to that one from my previous post. Here is what I added:
DHT22 sensor and a resistor R6.
A switch on GPIO5 which is used to turn on `configuration mode` which I’ll explain below.
A switch on GPIO4 which is not used. I added it just in case because I had a unit with two switches.
We use DHT22 sensor for measuring temperature and humidity. You can also use DHT11. That’s probably the most popular sensor for DIY projects, so MicroPython team kindly added a support for this sensor out-of-the-box. In case you have never seen this sensor, DHT22 looks like this:
Here is how the device looks like:
Starting a Wi-Fi access point on ESP8266
We’re done with hardware, let’s talk about software. I put sources to a repo on GitHub:
Since we’re going to send temperature and humidity to ThingSpeak, we need to connect our ESP8266 board to Wi-Fi. To do that, ESP8266 needs SSID and password. The most obvious way is to hardcode SSID and password. Here is how you can connect to Wi-Fi with MicroPython:
nic = network.WLAN(network.STA_IF)
But it’s not convenient to have hardcoded Wi-Fi settings. If SSID/password change, we’ll need to change sources and upload it to the board again. Instead of hardcoding SSID/password, we can do the following:
Add a `config mode` switch on GPIO5 (see on the circuit above) which turns on configuration mode.
When the board starts, it check if `config mode` switch is on (see `is_config_mode` function).
In case configuration mode is on, the board sets up a Wi-Fi access point, and starts a local web server (see `start_access_point` and `start_local_server` functions).
When a user connects to this Wi-Fi access point, the web server offers to set SSID and password for Wi-Fi network which should be used then.
When a user provides SSID/password, the web server stores it to a configuration file on ESP8266, and reboots the board (see `write_wifi_config` and `reboot` functions).
At this point, a user should also turn off `config mode`.
After reboot, the board connects to specified Wi-Fi network (see `connect_to_wifi` function).
In case of successful connection, it turns on LD1 (see `turn_on_wifi_led` function).
So, if we want to use the device in another Wi-Fi network, or we just changed Wi-Fi password, we don’t need to flash the device again.
After the device successfully connected to Wi-Fi, it starts measuring temperature and humidity with specified interval:
current_time = time.time()
if current_time - last_mesurement_time > MESUREMENT_INTERVAL:
last_mesurement_time = current_time
As I mentioned earlier, MicroPython supports both DHT11 and DHT22 sensors out-of-the-box. We just use `dht.DHT22` function, see `mesure_temperature_and_humidity`:
d = dht.DHT22(machine.Pin(DHT22_PIN))
t = d.temperature()
h = d.humidity()
print('temperature = %.2f' % t)
print('humidity = %.2f' % h)
That’s pretty simple. Then, we need to send data to the Internet. We’re going to use ThingSpeak which is a nice and free platform for gathering, analyzing, and visualizing data from IoT devices. ThingSpeak provides a RestFUL API for IoT devices. First, you need to create an account on ThingSpeak. Next, you’ll need to create a channel. After that, you’ll get an API key for posting data to your channel. This API key then should be used for sending data to ThingSpeak. Don’t forget to enable two fields in your channel: one for temperature, and another one for humidity.
Here is how we send data to ThingSpeak:
if not THINGSPEAK_WRITE_KEY:
print('not ThingSpeak key specified, skip sending data')
print('send data to ThingSpeak')
s = socket.socket()
ai = socket.getaddrinfo(API_THINGSPEAK_HOST, API_THINGSPEAK_PORT)
addr = ai[-1]
s = ssl.wrap_socket(s)
data = 'field1=%.2f&field2=%.2f' % (t, h)
http_data = THINGSPEAK_POST_TEMPLATE % (THINGSPEAK_WRITE_KEY, len(data), data)
We have the same problem here like we had with SSID/password – we need to provide API key, but we don’t want to hardcode it. The solution is the same – the device offers a user to specify API key in `config mode`.
As you might notice, we use TLS here – see `ssl.wrap_socket` call above which wraps a usual socket with an TLS socket. To be honest, I was surprised a bit when learned that MicroPython for ESP8266 supports TLS. But there is one thing about it. Even if TLS is used here, MicroPython for ESP8260 doesn’t support validation of server certificate (at least, v1.8.7 doesn’t support that). So, we’re relatively safe if an adversary can just eavesdrop the connection because all data will be encrypted. But if an adversary can modify the traffic, then we’re in a trouble because server certificate may be replaced with a malicious one, so that an adversary can decrypt and modify the data.
You might notice a number of `print` calls in the code. It’s just for debugging. You can connect to ESP8266 via USB-Serial adapter, and see those debug messages.
Visualizations on ThingSpeak
If everything went smoothly, the device will start sending data to ThingSpeak. Then, ThingSpeak allows you to visualize the data, and analyze it with MatLab. The simplest way is just to draw a chart like these ones:
These charts show temperature and humidity in my room. Here is a public channel for that: