# **Tutorial for temperature and humidity monitoring by Rasp Pi Pico W using DHT11 sensor** *by Anna Safonova, as228ek* # Introduction Like if you notice from the rubric my IoT project speaks about the usage of a humidity and temperature sensor, the connection it to Raspberry pi pico w, and also the control it with Blynk so it reveals changes of temperature and humidity. The realization of the project will take a few hours. It could be used for example in a room, basement or in greenhouse to supervise the temperature and humidity. # Objective The objective of this IoT project is actually to simplify peoples lives in different spheres of live like for example job, agriculture, science and also just for a better environment for the people and the planet. # Materials | components | used for | | ---------------------------------------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | M2M jumper wires x3 | Allows us to connect components our with each other | | Raspberry Pi Pico W (board) x1 | Microcontroller with WiFi access to enable wireless communication and also the "brain" of our comunication system | | micro USB (Cable) x1 | allows us to connect rpi pi w (microcontroller) to our computer (microsoft, MAC,...) | | DHT11 (Humidity & temperature sensor) x1 |Sensor to gather data about the temperature and humidity (temperature in celcius, Humidity in procent %) | | breadboard x1 | Allows components to easily be removed and replaced, and also it allows us to connect everything together on one board. It makes also really easy to understand the circuit ![](https://hackmd.io/_uploads/BJGmo3Gon.gif =150x150) DHT11 temperature & humidity sensor ![](https://hackmd.io/_uploads/ry-Y1aMin.gif =150x250) RPI PI PICO W board The material was bought at [elektrokit.com](https://) # Computer set-up The chosen IDE for this project was Thonny because it supports MicroPython, has a simple, one step installation that provides both the interpreter and runtime and an IDE configured to use it. In addition, the Thonny has debugger. So firstly you need to download thonny and wait before it would be done. After the download your next step should be to download the micropython firmware from thonny IDE for connecting your microcontroller. After, when uf2 file has been downloaded, it can be uploaded to the microcontroller by connecting our micro USB cable from the host computer to the microcontroller. Before connecting the computer and microcontroller you should hold down the BOOTSEL key on the microcontroller and then connect it to the computer. After you have connected the microcontroller to the computer, a new drive should open on your computer containing the microcontrollers files where the uf2 file can be uploaded to. For visualizing and control the collected data the Blynk could be used as an low code IoT solution. # Circuit To connect a DHT11 sensor to a Raspberry Pi Pico, you need to wire the sensor’s VCC pin to the Pico’s 3.3V pin, the sensor’s GND pin to the Pico’s GND pin, and the sensor’s DATA pin to any of the Pico’s GPIO pin. In my case for this project I chose and used the GPIO 28 "DATA" pin. GPIO (General Purpose Input Output) is a set of pins in the microcontroller, which functions by passing data into and out of the board. They serve as a bidirectional pin. When serving as input, it brings information into the board from an input device to the processor on the micro-controller board. When serving as an output pin, the data from the board is transferred to an output device from the processor. Here is a diagram showing the pins of the DHT11 sensor: ![](https://hackmd.io/_uploads/B1MgOcXj2.gif =350x150) and this is a simplified circuit diagram of how we need to wire the components: ![](https://hackmd.io/_uploads/BkstTq7i2.jpg =300x300) This setup/circuit allows analog data to be sent from the DHT11 to the microcontroller, as well sending electricity to the DHT11 sensor through the microcontroller. So, after you have wired the circuit correctly then it would become something like this: ![](https://hackmd.io/_uploads/SyDVGsXi2.jpg =300x250) # Platform The platform that I would like to suggest to use is Blynk. I also tried Adafruit and Ubidots but I found them quite complicated. Blynk allows to build own apps to control any devices over the Internet. This tool permit to initiate actions and notifications in response to the data, and facilitates its visualization. This platform is free to download. Simple projects for individuals are also free of charge but building a relatively complicated app with many widgets will cost a little money. To get started with Blynk it is necessary to download the Blynk iOS or Android app, install a Blynk library, generate an Authentication Token from Blynk app to connect Raspberry pi pico w, and then it is possible to get started building the app and to add widgets (buttons, sliders etc.). # The Code ``` #define BLYNK_TEMPLATE_ID "TMPL4PVr6UwbC" #define BLYNK_TEMPLATE_NAME "DHT11" #define BLYNK_AUTH_TOKEN "1YJckdxKZEmxOpgm8pmMF_xRvgXSsBBM" from machine import Pin, I2C #importing relevant modules & classes import time import utime as time from dht11 import DHT11 , InvalidChecksum import BlynkLib import network # i2c=I2C(0,sda=Pin(0), scl=Pin(1), freq=400000) #initializing the I2C method led=machine.Pin('LED', machine.Pin.OUT) wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect("Pro","1234567890") #SSID: Pro , PASS: 1234567890 BLYNK_AUTH = '1YJckdxKZEmxOpgm8pmMF_xRvgXSsBBM' # connect the network wait = 30 while wait > 0: if wlan.status() < 0 or wlan.status() >= 3: break wait -= 1 print('waiting for connection...') time.sleep(1) # Handle connection error if wlan.status() != 3: #raise RuntimeError('network connection failed') led.value(0) #turn the led off else: print('connected') ip=wlan.ifconfig()[0] print('IP: ', ip) led.value(1) #turn the led on # Initialize Blynk Blynk = BlynkLib.Blynk(BLYNK_AUTH) while True: time.sleep(5) pin = Pin(28, Pin.OUT, Pin.PULL_DOWN) sensor = DHT11(pin) t = (sensor.temperature) h = (sensor.humidity) print("Temperature: {}".format(sensor.temperature)) print("Humidity: {}".format(sensor.humidity)) # Print sensor data to console print('Temperature: {:.1f} C'.format(sensor.temperature)) print('Humidity: {:.1f} %'.format(sensor.humidity)) # Send sensor data to Blynk Blynk.virtual_write(0, t/1) # virtual pin 0 for temperature Blynk.virtual_write(1, h/1) # virtual pin 1 for humidity # Run Blynk blynk.run() # Delay for 10 seconds time.sleep(10) ``` you can call it as dht11.py (such as i call it), and save it on your RPI PICO W board. but do not forget that we need the library for blynkLib.py so it could connect to blynk safely. so, here is the code: ``` import struct import time import sys import os try: import machine gettime = lambda: time.ticks_ms() SOCK_TIMEOUT = 0 except ImportError: const = lambda x: x gettime = lambda: int(time.time() * 1000) SOCK_TIMEOUT = 0.05 def dummy(*args): pass MSG_RSP = const(0) MSG_LOGIN = const(2) MSG_PING = const(6) MSG_TWEET = const(12) MSG_NOTIFY = const(14) MSG_BRIDGE = const(15) MSG_HW_SYNC = const(16) MSG_INTERNAL = const(17) MSG_PROPERTY = const(19) MSG_HW = const(20) MSG_HW_LOGIN = const(29) MSG_EVENT_LOG = const(64) MSG_REDIRECT = const(41) # TODO: not implemented MSG_DBG_PRINT = const(55) # TODO: not implemented STA_SUCCESS = const(200) STA_INVALID_TOKEN = const(9) DISCONNECTED = const(0) CONNECTING = const(1) CONNECTED = const(2) print(""" ___ __ __ / _ )/ /_ _____ / /__ / _ / / // / _ \\/ '_/ /____/_/\\_, /_//_/_/\\_\\ /___/ for Python v""" + __version__ + " (" + sys.platform + ")\n") class EventEmitter: def __init__(self): self._cbks = {} def on(self, evt, f=None): if f: self._cbks[evt] = f else: def D(f): self._cbks[evt] = f return f return D def emit(self, evt, *a, **kv): if evt in self._cbks: self._cbks[evt](*a, **kv) class BlynkProtocol(EventEmitter): def __init__(self, auth, tmpl_id=None, fw_ver=None, heartbeat=50, buffin=1024, log=None): EventEmitter.__init__(self) self.heartbeat = heartbeat*1000 self.buffin = buffin self.log = log or dummy self.auth = auth self.tmpl_id = tmpl_id self.fw_ver = fw_ver self.state = DISCONNECTED self.connect() def virtual_write(self, pin, *val): self._send(MSG_HW, 'vw', pin, *val) def send_internal(self, pin, *val): self._send(MSG_INTERNAL, pin, *val) def set_property(self, pin, prop, *val): self._send(MSG_PROPERTY, pin, prop, *val) def sync_virtual(self, *pins): self._send(MSG_HW_SYNC, 'vr', *pins) def log_event(self, *val): self._send(MSG_EVENT_LOG, *val) def _send(self, cmd, *args, **kwargs): if 'id' in kwargs: id = kwargs.get('id') else: id = self.msg_id self.msg_id += 1 if self.msg_id > 0xFFFF: self.msg_id = 1 if cmd == MSG_RSP: data = b'' dlen = args[0] else: data = ('\0'.join(map(str, args))).encode('utf8') dlen = len(data) self.log('<', cmd, id, '|', *args) msg = struct.pack("!BHH", cmd, id, dlen) + data self.lastSend = gettime() self._write(msg) def connect(self): if self.state != DISCONNECTED: return self.msg_id = 1 (self.lastRecv, self.lastSend, self.lastPing) = (gettime(), 0, 0) self.bin = b"" self.state = CONNECTING self._send(MSG_HW_LOGIN, self.auth) def disconnect(self): if self.state == DISCONNECTED: return self.bin = b"" self.state = DISCONNECTED self.emit('disconnected') def process(self, data=None): if not (self.state == CONNECTING or self.state == CONNECTED): return now = gettime() if now - self.lastRecv > self.heartbeat+(self.heartbeat//2): return self.disconnect() if (now - self.lastPing > self.heartbeat//10 and (now - self.lastSend > self.heartbeat or now - self.lastRecv > self.heartbeat)): self._send(MSG_PING) self.lastPing = now if data != None and len(data): self.bin += data while True: if len(self.bin) < 5: break cmd, i, dlen = struct.unpack("!BHH", self.bin[:5]) if i == 0: return self.disconnect() self.lastRecv = now if cmd == MSG_RSP: self.bin = self.bin[5:] self.log('>', cmd, i, '|', dlen) if self.state == CONNECTING and i == 1: if dlen == STA_SUCCESS: self.state = CONNECTED dt = now - self.lastSend info = ['ver', __version__, 'h-beat', self.heartbeat//1000, 'buff-in', self.buffin, 'dev', sys.platform+'-py'] if self.tmpl_id: info.extend(['tmpl', self.tmpl_id]) info.extend(['fw-type', self.tmpl_id]) if self.fw_ver: info.extend(['fw', self.fw_ver]) self._send(MSG_INTERNAL, *info) try: self.emit('connected', ping=dt) except TypeError: self.emit('connected') else: if dlen == STA_INVALID_TOKEN: self.emit("invalid_auth") print("Invalid auth token") return self.disconnect() else: if dlen >= self.buffin: print("Cmd too big: ", dlen) return self.disconnect() if len(self.bin) < 5+dlen: break data = self.bin[5:5+dlen] self.bin = self.bin[5+dlen:] args = list(map(lambda x: x.decode('utf8'), data.split(b'\0'))) self.log('>', cmd, i, '|', ','.join(args)) if cmd == MSG_PING: self._send(MSG_RSP, STA_SUCCESS, id=i) elif cmd == MSG_HW or cmd == MSG_BRIDGE: if args[0] == 'vw': self.emit("V"+args[1], args[2:]) self.emit("V*", args[1], args[2:]) elif cmd == MSG_INTERNAL: self.emit("internal:"+args[0], args[1:]) elif cmd == MSG_REDIRECT: self.emit("redirect", args[0], int(args[1])) else: print("Unexpected command: ", cmd) return self.disconnect() import socket class Blynk(BlynkProtocol): def __init__(self, auth, **kwargs): self.insecure = kwargs.pop('insecure', False) self.server = kwargs.pop('server', 'blynk.cloud') self.port = kwargs.pop('port', 80 if self.insecure else 443) BlynkProtocol.__init__(self, auth, **kwargs) self.on('redirect', self.redirect) def redirect(self, server, port): self.server = server self.port = port self.disconnect() self.connect() def connect(self): print('Connecting to %s:%d...' % (self.server, self.port)) s = socket.socket() s.connect(socket.getaddrinfo(self.server, self.port)[0][-1]) try: s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) except: pass if self.insecure: self.conn = s else: try: import ussl ssl_context = ussl except ImportError: import ssl ssl_context = ssl.create_default_context() self.conn = ssl_context.wrap_socket(s, server_hostname=self.server) try: self.conn.settimeout(SOCK_TIMEOUT) except: s.settimeout(SOCK_TIMEOUT) BlynkProtocol.connect(self) def _write(self, data): #print('<', data) self.conn.write(data) # TODO: handle disconnect def run(self): data = b'' try: data = self.conn.read(self.buffin) #print('>', data) except KeyboardInterrupt: raise except socket.timeout: # No data received, call process to send ping messages when needed pass except: # TODO: handle disconnect return self.process(data) ``` So, now we have all the codes that we need. # Connectivity The data is sent every 10 seconds, but can be adjusted in the code to fit different use-cases where on might want to gather the data more often or less often. The wireless protocol used is Wi-Fi, by connecting the microcontroller to a Wi-fi source (generally a router) via HTTPS to send requests to blynk and also send data to the gauche so it could show us the valor of temperature and humidity. # Running the code Now after that we have typed the code we need to run it, and also do not forget that when you run the code it needs to be smooth and fast, then you know that you made everything correct. The results in the shell should be like this: ![](https://hackmd.io/_uploads/r1tBu_Zph.png) # Presenting the data So when you have install Blynk then make a template and inserted some gadgets so you could see all the data about temperature and humidity, but only if you typed the code correctly. The results in the app could be like this: ![](https://hackmd.io/_uploads/SyeTM8Z6n.png =370x170) After that we could finalize the design. It could be done on the computer and also in the phone. ![](https://hackmd.io/_uploads/ByeNZIbT2.png =500x350)