IOT TUTORIAL: Esp8266 (NODEMCU): MICROPYTHON, DHT22, MQTT and INTERRUPT


I had a ESP8266 - NodeMCU - module laying around, so I decided to install inside an electrical panel, to gather also data from energy monitor. I used a DIN empty support to mount the ESP:

Flashing micropython to ESP8266

Micropython install on ESP8266 without pain: 
a. Download latest version from http://micropython.org/download#esp8266
b. Deploy the firmare, install with pip the esptool tool 
c. Erase flash with:
esptool.py --port /dev/ttyUSB0 erase_flash
d. Connect ESP8266
e. Check the connected serial port with
ls /dev
f. Change directory to the unzipped firmware directory
g. Flash the new firmware from bash with the following command.
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-20170108-v1.8.7.bin 
That's all, if not working, check USB port or reduce upload speed to 115200, or check micropython website tutorial.

Running a script

By default micropython at startup execute a main.py file. Write it in your favourite text editor and  upload it using WebREPL.

Connecting to ESP

There are two options to connect to ESP with micropython, serial REPL or WebREPL (OTA or On the air or via WIFI).

Serial prompt - REPL

If you connect to ESP via serial port, you'll be prompted with a python shell, import modules and execute commands. You can stop main.py from execution, and also you can soft or hard reset. This kind of interface is called REPL, and is always available.

Over the air - WebREPL

During startup, ESP will create an access point called MicroPython-xxxxxx to which you can connect directly. Download a local version of html file from Github and open the html inside the zip file. 
I prefer this way because with this interface you can upload main.py when needed.
You will be prompted to a web page like this.

On the bottom left corner the standard access point address, change after accordingly when the ESP is connected to your local network via WIFI.
Once uploaded a main.py file, after reset, inside WebREPL is possible to read output from print statements and stop main.py with CTRL-C if something went wrong.

ESP8266 + NODEMCU + MICROPYTHON PINOUT

Considering the following layout using micropython you have to refer to pin numbering used by GPIO naming. So for instance D0 pin is GPIO16, inside micropython is pin 16:

#import machine library
from machine import Pin

# create an output pin on pin #0
p0 = Pin(0, Pin.OUT)
# set the value to high
p0.value(1)

CONNECTING TO LOCAL WIFI NETWORK

To connect Nodemcu to Wifi:
#import libraryimport network 
#import sleep function from dedicated time libraryfrom utime import sleep
#defined function to check connection or reconnectdef do_connect():    sta_if = network.WLAN(network.STA_IF)    if not sta_if.isconnected():        print('Connecting to network Wireless...')        sta_if.active(True)        sta_if.connect('SSID', 'PASSWORD')        while not sta_if.isconnected():            pass
do_connect()
while True:
    #do your loop here
    ....
    do_connect()
    ...
    sleep(15) 
Once connected, every time you reset you have to change the IP number to the DHCP assigned one, without connecting to Access Point, or you can connect directly to access point and use the internal IP.
You can also disable AP on startup after do_connect() using:
ap_if.active(False)

SENDING MQTT MESSAGES TO BROKER

from umqtt.simple import MQTTClient
SERVER = b'192.168.1.xx' #put your broker addressCLIENT_ID = b'ESP_Epanel'TOPIC_T = b'HOME/EPANEL/TEMPERATURE'TOPIC_H = b'HOME/EPANEL/HUMIDITY'
#after connecting to WIFIclient = MQTTClient(CLIENT_ID, SERVER)client.connect()   #Connect to MQTT broker
while True:    client.publish(TOPIC_T, 22)    client.publish(TOPIC_H,45)

READING DHT22 SENSOR

DHT22 is an expensive and accurate sensor to monitor temperature and humidity. I used one with breakout board from Banggood.
Sometimes DHT22 fail to read and the simplest solution I found is to soft reset via code
from dht import DHT22
from machine import reset
sensor = DHT22(Pin(5))
while True:
    try:
        sensor.measure()
        t = sensor.temperature()
        h = sensor.humidity()
        if isinstance(t, float):
            msg = (b'{0:3.1f}'.format(t))
            client.publish(TOPIC_T, msg)
            print("Temperature: ", msg)
        if isinstance(h, float):
            msg = (b'{0:3.1f}'.format(h))
            client.publish(TOPIC_H, msg)
            print("Humidity: ", msg)
        else:
            print('Invalid sensor readings.')
    except OSError:
        print('Failed to read sensor.')
        reset()

PIN INTERRUPT HANDLING

Handling external interrupt in micropython is really simple:
from utime import time
from machine import reset  
#define a callback function where execute simple and short code 
def callback(pin_number):
    #refer to global variable
    global last_time
    last_lime = time()
 
#pin setup
p0 = Pin(12,mode=Pin.IN)
p1 = Pin(13,mode=Pin.IN)
 
#start interrupt
p0.irq(trigger=Pin.IRQ_FALLING, handler=callback)
p1.irq(trigger=Pin.IRQ_FALLING, handler=callback)

CONCLUSIONS

Put all together and you will have a connected MQTT node which read DHT22 sensor every 15 seconds, managing errors and as in my case count pulse input.

What I learned so far:
- Micropython is little tricky at the beginning, but stable, flexible and finally is Python.
- ESP8266 is not energy friendly, it produces a lot of heat, so is better to mount DHT22 far from ESP. In the near area surrounding the ESP the temperature reach a stable 26 degrees Celsius vs 20 degrees Celsius of surrounding.
- I hate pins, I would prefer to have screw connectors.


5 comments:

Popular posts