# Tutorial on how to build a sleeping environment monitor using an RPi Pico 2 W IoT device *Made by Simon Eriksson (se224ct)* ## Project Overview In this tutorial you will use a Raspberry Pi Pico 2 W to measure temperature, humidity, and light levels. The data is shown on an LCD screen and sent to an MQTT broker. The data can then be viewed in Node-RED with gauges and charts. The data is also persisted in an InfluxDB database. The finished project can be used to monitor the environment for example in your bedroom. ### Time needed to set up You will probably need about 2-5 hours depending on your previous experience. There is some wiring that needs to be done, and there are a few steps in setting up the software as well. ## Objective This project is a neat introduction to IoT and will aid you in understanding your sleeping environment by putting numbers on physical aspects of your environment, and being able to visualize this data over time. You might come to realize when you wake up dizzy after a bad nights sleep that it was because of abnormal levels of light, temperature or humidity. Because of this device, you now possess the tools to verify that. ## Material ### Full list of items needed | Quantity | Item | Image | Description | | -------- | --------------------- | ---------------------------------------------------------- | -------------- | | 1 | Raspberry Pi Pico 2 W | ![pico2w_small](https://hackmd.io/_uploads/r1_ZI84Sxg.png) |A microcontroller with WiFi capability. You could probably make do with a Pico W or WH as well.| | 1 | DHT11 | ![DHT11_new](https://hackmd.io/_uploads/SJZoSPEHel.png) | A digital sensor that measures humidity and temperature. Not very accurate or reliable, it can only measure about once every 2 seconds.| | 1 | NTC Thermistor | ![thermistor](https://hackmd.io/_uploads/SJwa8wEBee.png) | An analog resistor that decreases in resistance when the temperature rises. Since it is analog, it can be read at any time. | 1 | Photoresistor | ![photoresistor](https://hackmd.io/_uploads/B1HAYPNHel.png) | An analog resistor which decreases in resistance when the light level increases. Since it is analog, it can be read at any time. | | 3 | 10kΩ Resistor | ![10kresistor](https://hackmd.io/_uploads/rkeJ9wVrxg.png) | A fixed value resistor which we need for making voltage divider circuits to measure the variable analog resistors. One is also needed for the DHT11. | | 1 | 1602 LCD with I2C interface | ![lcd1602](https://hackmd.io/_uploads/rkSl5vNSxl.png) | A display which will be used to show the most recent measurements made by the device. It has an I2C module so we only need a few wires to connect and control it. | | 1 | Breadboard with at least 50 lanes | ![breadboard](https://hackmd.io/_uploads/HJJ-cPESge.png) | We need this to be able to build the device without having to solder. | | 5 | Red Male to Male Wires | ![wireanycolor](https://hackmd.io/_uploads/SJefqv4Sel.png) | While technically any color works, it is nice to keep to the convention of using red wires for voltage in. | | 5 | Black or Blue Male to Male Wires | ![wireanycolor](https://hackmd.io/_uploads/SJefqv4Sel.png) | The same goes here, we can use any color, but black or blue are traditionally used for connecting to ground, or the negative end of circuits. | | 3 | Any color Male to Male Wires | ![wireanycolor](https://hackmd.io/_uploads/SJefqv4Sel.png) | These will be used to connect our sensor circuits to GPIO and ADC inputs on the microcontroller | | 4 | Female to Male Wires of any color | ![fmwires](https://hackmd.io/_uploads/SyyEqwErxx.png) | Wires needed to connect the LCD to the breadboard without having to solder or awkwardly put the LCD directly into the breadboard | |1|MicroUSB Cable | ![microUSB](https://hackmd.io/_uploads/BysRuZrHel.png) | Needed to program your Pico device with your computer. | All items listed above and more is included in this kit I bought from Amazon: [Freenove Ultimate Starter Kit for Raspberry Pi Pico 2 W ](https://www.amazon.se/dp/B0DR2GDKJ4)(760 kr) The kit also includes tutorials and code to build and run various different projects so I recommend buying it if you are interested in more IoT projects even if it is a bit pricey. ## Computer Setup 1. For this project I used VS Code with the Pymakr plugin, this can be installed by [following this guide](https://hackmd.io/@lnu-iot/rkiTJj8O9). 2. You also need to update the firmware on the Pico board to run Micropython by [following this guide](https://hackmd.io/@lnu-iot/rkFw7gao_). 3. Connect the microcontroller and sensors as shown in the circuit diagram in [Putting Everything Together](#Putting-everything-together). 4. Download the project code. You can find the code here: [Github Repository](https://github.com/sier8161/IoT). 5. Add the code from the folder `MultiSensor` to your VS Code Pymakr project. 6. You will need to edit the file `Multisensor\lib\config.py` to include your specific details, you are going to set some of these up in the later steps in this guide. ```python # Wireless network WIFI_SSID = 'YOUR_WIFI_SSID' # replace with your WiFi SSID WIFI_PASS = 'YOUR_WIFI_PASSWORD' # replace with your WiFi password # MQTT server's configuration MQTT_SERVER = "YOUR_LOCAL_IP_ADDRESS" # replace with local IPv4 address of the machine running mosquitto MQTT_PORT = 1883 MQTT_USER = "YOUR_USER" # replace with your mosquitto username MQTT_KEY = "YOUR_PASSWORD" # replace with your mosquitto password MQTT_CLIENT_ID = "id-123" # can be set to anything starting with "id-" MQTT_TEMPERATURE_FEED = "devices/temp" MQTT_HUMIDITY_FEED = "devices/hum" MQTT_BRIGHTNESS_FEED = "devices/light" ``` 7. At this point you are ready to upload the code to your Pico device, but we also need to set up the data receiving end on your intended server machine. 8. Install Mosquitto MQTT broker on a machine on the same local network that you plan to connect the Pico to. This could for example be the computer you are using right now. [Instructions to download and install mosquitto](https://mosquitto.org/download/). Configure the mosquitto broker as follows: First you have to set up a password, this is done by typing into a terminal ```console mosquitto_passwd -c /etc/mosquitto/passwd <yourUserName> ``` This will prompt you to select a password for the mosquitto broker. Next we need to configure mosquitto to allow the persistance of data, user authentication and to allow incoming connections from the network. [Here are some general guidelines on how to do that](https://hackmd.io/@lnu-iot/rJr_nGyq5#Advanced-Configuration-and-Authentication). You can follow the guide linked above, but you must also add this line to your mosquitto config file: ``` listener 1883 0.0.0.0 #enables receiving data from other devices on the network. ``` At this point, you can add the selected mosquitto username and password into the file `config.py`. Then open a terminal window on the machine running mosquitto and type `ìp address` and you will find something like `192.168.xxx.xxx` -- This is what you should copy and paste as value of the variable `MQTT_SERVER` in `config.py` which concludes the last of the unknown values in it. 9. When the mosquitto installation is properly configured, simply restart it following the steps from the guide earlier, and then let it run in a terminal window on the server machine. Do not close this terminal as it will close the broker. 10. Install Node-RED. First you must install [Node.js](https://nodejs.org/en/download). Next simply type into a terminal: ```console sudo npm install -g --unsafe-perm node-red ``` This should install Node-RED, if it does not, then please check [this page](https://nodered.org/docs/getting-started/local). 11. Run Node-RED so it can be configured, simply type this into a terminal and keep the terminal open. Do not close this terminal as it is what keeps Node-RED running. ```console node-red ``` 12. Then go to your web browser and connect to your MQTT server on port 1880. If it is running on the machine you are using right now, that would be [127.0.0.1:1880](http://127.0.0.1:1880). Otherwise, [find your local IPv4 address](https://infinitydomainhosting.com/kb/what-is-my-local-ip-address/) on the machine that is running mosquitto and Node-RED and replace 127.0.0.1 with that IP. 13. Now we are inside Node-RED and to install the dashboard, simply click on the hamburger menu in the top right corner of the view, and go to **Manage Palette**, or by hotkey **Shift+Alt+P**. Then go to the install tab, search for "dashboard" and install `node-red-dashboard`. ![install_dashboard](https://hackmd.io/_uploads/Hy4K4fHHex.png) 14. While in the same view, search for "influx", and install the one named `node-red-contrib-influxdb` in the same manner as you did with the dashboard in the previous step. 15. Now it is time to install InfluxDB on the server machine by following [this link](https://www.influxdata.com/get-influxdb/). After it is installed, run it in a new terminal window by this command ```console influxd ``` and do not close this window, as doing so will shut down the database. Then go to http://localhost:8086 in a web browser and set up the bucket, in order for it to work with the settings I provide in this guide with the imported Node-RED flow, the bucket name must be "SleepingMonitor" and the organisation must be "LNU". You are free to pick whatever username and password you wish. If you are prompted for a username and password, it is by default "admin" and "admin", but once upon login you should be prompted to create your own unique login. Inside of InfluxDB in your web-browser, click on "Load Data" and go to the tab "API Tokens", there, generate a token for read and write access to the SleepingMonitor bucket by ticking the boxes, and very important: copy the token you get to a safe location, we will need it later! 16. After installing the dashboard and influxdb you are ready to import the flow related to the project. Again, go into the hamburger menu in the top right corner of Node-RED, and select **Import**, or by hotkey **Ctrl+I**. Then press "Select a file to import." and select the file **flows.json** which was included in the GitHub repository you downloaded earlier. Next press "Import".(the influxDB terminal is not shown in this picture) It should look like this: ![node-flow](https://hackmd.io/_uploads/BkIXUs0rgg.png) 17. Now the final step is to configure the MQTT broker and InfluxDB connections within Node-RED and we are ready to deploy! Press the cogwheel close to the top right corner of Node-RED, just below the hamburger menu. Then double click on **MQTTBroker**, now we can edit and update the details of the MQTT connection to NodeRED. Go into the **Security** tab and put in the credentials for the mosquitto server you set earlier with the `mosquitto_passwd` terminal command, and then click "Update". ![node-broker](https://hackmd.io/_uploads/BJ73dfrSxl.png) Then double click on **[v2.0] InfluxDB** and paste the API Token in the field "Token" which you generated in step 15 and click "Update". 16. You are now ready to deploy by clicking the **Deploy** button in the top right corner of Node-RED. The dashboard can now be viewed by accessing the server machine on the local network on port 1880, for example if running locally [127.0.0.1:1880/ui](http://127.0.0.1:1880/ui). ## Putting everything together Here is a circuit diagram showing how everything is connected: ![multisensor-schematic](https://hackmd.io/_uploads/HkTraBNrll.png) Or if you prefer to just follow what I did, here is how I connected everything on my breadboard (I modified it a tiny bit to be better able to visualize it): ![fritzing-breadboard-multisensor](https://hackmd.io/_uploads/HJnu6SVHle.png) ### NOTE: the breadboard rails have different voltages, <span style="color:red">be careful</span> to not mix them up. This was done because the LCD runs on 5V, but the other components use 3.3V. The data connections are as follows: - DHT11 sensor to GPIO 5 - NTC thermistor to ADC 26 - Photoresistor to ADC 27 - 1602 LCD using I2C on GPIO 14 (SDA) and GPIO 15 (SCL) ## Platform The platform Node-RED was chosen for its simplicity and flexibility. I tried using a TIG-stack at first but found it unnecessarily complex and instead settled on Node-RED as it felt like a perfect middle ground whilst still being a self-hosted solution requiring fewer steps. The platform is a local installation, and can be accessed from my local network by accessing the IP of the machine running Node-RED on port 1880. If I wanted to scale this further, a paid server in the cloud could be an option instead of running it locally. Node-RED is a flow-based development tool for wiring together hardware devices, APIs, and online services using a simple, visual interface. It lets you create logic by connecting nodes, making it easy to process data, control devices, and build IoT applications without heavy coding. InfluxDB is a time-series database designed to store and query data that changes over time, like sensor readings, and is used in this project for persisting the data received by Node-RED. ## The Code The code can be found in the [GitHub repository](https://github.com/sier8161/IoT) and is fairly simple, relying heavily on provided libraries that were gotten from the [Freenove tutorials](https://freenove.com/FNK0058) and [course tutorials](https://github.com/iot-lnu/pico-w/tree/main/network-examples/N5_WiFi_Mosquitto_Node-Red_Test), the included libraries are: `dht11.py`, `I2C_LCD.py`, `LCD_API.py` (from Freenove), and `mqtt.py` and `wifiConnection.py` (from the course). Sidenote on the code is that every 60 seconds, a garbage collector is run, because I had problems with the Pico device becoming unresponsive after a couple of minutes of runtime earlier, and ChatGPT suggested it might have to do with memory issues, so after including a garbage collector, it can now run for days without issues, possibly even longer, but that is the longest timespan I have verified it working for so far. ## Transmitting the Data The sensor data is transmitted every **10 seconds**. Between transmissions, the Pico updates the LCD display every second with new readings from the analog sensors but does not flood the network with unnecessary messages. The DHT11 sensor is read every 3 seconds in order to avoid errors from it, while the analog sensors are read every second, so the values displayed on the LCD are live updated for the analog sensors, but on a 3 second basis for the humidity value. The project uses **WiFi** (2.4GHz) for wireless local data communication. **MQTT** is used to efficiently publish sensor data to the local network broker. ### The data flow ![node-flow](https://hackmd.io/_uploads/BkIXUs0rgg.png) The flow is set up as follows: upon starting Node-RED, we fetch the last 24 hours of data in each topic and put it into its respective chart view. Upon receiving an MQTT message in any of the topics: 1. We display the value in the respective gauge. 2. We format the value so it can be stored into the database, and send it to the database. 3. We format the value so it can be sent to and displayed in its respective chart, and then send it to that chart. This makes sure we do not flood Node-RED or InfluxDB with unnecessarily large amounts of data processing by for example fetching all data from database on each update to the charts. And we both save the data to the database and make it show up in the graphs simultaneously. Here InfluxDB really shines as it is naturally made for keeping track of time, and minimal code was needed in the nodes themselves in Node-RED. Since the database has time-tagged all datapoints, and we just add the current time in the `Format for Chart` nodes, all data is displayed in the correct order in the charts. Also note that the MQTT messages are already formatted as JSON objects, so we can route them directly into the gauges with no parsing functions in between. ## Presenting the data This is what the dashboard looks like when everything is up and running: ![dashboard](https://hackmd.io/_uploads/Syxx8Y4Seg.png) Access it by connecting to your MQTT server on port 1880 and subdomain ui. If it is running on the machine you are using right now, that would be [127.0.0.1:1880/ui](http://127.0.0.1:1880/ui). Every 60 seconds, mosquitto will save the recently received data to a database file stored in /var/lib/mosquitto/ on the machine running mosquitto. Every time a new datapoint is received in MQTT by Node-RED, it saves the datapoint to the InfluxDB server, so it is saved in real-time. ## Final Notes Make sure the DHT11 sensor is not polled too often. I had problems with the device freezing after running for a little while, and by troubleshooting and researching online, I found the probable cause of this to be the DHT11, and that one should be careful with using it. Therefore, it is measured only once every 3 seconds, while the analog sensors are checked every second. Other than the problem I had with the DHT, I also had some problems with file ownership that was complicating the configuration process of mosquitto. But once the problems were overcome, I think the project was overall a great success and I will likely continue to improve the project, or make something else in a similar manner now that I know how simple it is to set up a nice little IoT flow like this! Future improvements would likely include some way of automatically reconnecting the device if network fails, and maybe install a button that can turn off the backlight of the LCD while sleeping, as it is kind of bright and might in itself reduce sleep quality. Another idea for improvement would be to add more sensors, for example something tracking how much you move during sleeping with some form of motion sensor, or tracking how loud the environment is by a decibel meter or microphone. We are currently utilizing 2 of the 3 analog inputs on the Pico, so we have hardware support for adding one more without it being too cumbersome. Lets finish this off with some pictures of the finished product! ### Pictures Here is what the setup running mosquitto in one terminal, Node-RED in another terminal, and connecting to the dashboard in a web browser looks like (the influxDB terminal is not shown in this picture). ![deployed](https://hackmd.io/_uploads/SJkqOuNHel.png) The graphs show the data over the last 24 hours. The gauges show the most recent measurement that was sent over MQTT. The vertical streaks in the humidity over time graph shows really how unreliable the DHT11 sensor is, as the code for error handling currently sets the humidity value to 0 when the DHT is unresponsive. The vertical streak at around 1AM for light level graph was me turning on the ceiling light in the bedroom. The "shakiness" of the light graph is due to natural variance in ambient light by clouds moving in the sky. Here is a closeup of the components and wiring during development: ![setup_dev](https://hackmd.io/_uploads/rJfTidErge.png) Here the device is seen in real action, *robustly* secured to my bedframe with clear tape: ![setup_bedside](https://hackmd.io/_uploads/Sk_6i_4rxg.png) ---