Assignment 3: Web-connected Environmental Monitor

The Idea

The project consists of developing a web-connected environmental monitor using a Raspberry PI  The device will send it’s data to a server via HTTPs every hour, whereas the RESTful API and it’s server will be provided to us. In this post I will go through several steps, starting at setting up our Raspberry Pi and later on setting up our environmental sensors and web client setup. You can find the code and circuit schematic at the end of the blog post.

The Process

Bill of Materials

Raspberry Pi 4 model B.
Raspberry Pi 4 model B.

Setting up the Pi

There are several approaches to setting up our pi, I followed Tom Igoe’s Setting up a Rasberry Pi guide in order to get it up and running. In a few words, we weill have to download the Rasbian OS into an SD card which we will insert into our Pi.Once we have our Pi with the SD card inside, we can look at the GPIO pins it has in order to identify it’s TXD and RXD pins. The TXD pin from our Serial to USB adapter will connect to the RXD pin on the Raspberry PI. The RXD pin in pur PI, consequently, will go to the TXD pin of our adapter. We also have to connect the GND pin in the adapter into a GND pin in the Pi. This will give our Pi and laptop a common GND.

GPIO Pin diagram
GPIO Pin diagram
GPIO pin detail.
GPIO pin detail.
Serial to USB adapter
Serial to USB adapter
Pi connections to UART to USB module.
Pi connections to UART to USB module.

There are tons of guides on how to talk through serial with you Pi through OSX. I used a windows OS with a Linux subsystem. To set this up I followed the following guide: Microsoft’s guide to setup Node with wsl in Windows. For the specific commands to talk to the Raspberry PI with a linux subsystem in windows I followed this guide made by Micheal Hirsch: Use USB-Serial adapters via Windows Subsystem for Linux. In any case, we need to check the COM port our computer recognizes connected with the PI. Once we have that, we can use our terminal to open the communication. 

COM port detected
COM port detected
Serial port command.
Serial port command.
Serial connection with Pi succesful
Serial connection with Pi successful

Now that we have our serial port open, let’s update our Pi so that it’s up to date with the latest updates from Raspbian. To do this we first need to access the Raspi-config menu to setup our network settings. With an internet connection available, it’s a matter of using apt-get as a super-user to update Raspbian. 

Raspi-config menu.
Raspi-config menu.
Distro-upgrade console log.
Distro-upgrade console log.

Getting the Data

SSH connection to the Pi

I did not want to have to have my serial connection up everytime I wanted to access my PI, so I decided to access it through SSH. the command is pretty straightforward, it’s just necessary to have a username, password, and the IP address of your device in the network you’re connected to. The IP address can be found with the  `ifconfig` command. This is demonstrated below. It is usually found after the “inet”.

IP address of your device.
IP address of your device.
SSH into PI.
SSH into PI.

DHT11 Temperature and Humidity Sensor

I decided to use a DHT11 temperature and humidity because it’s cheap, precise enough for a hobbyist project, and easy to find documentation. I also found an npm package called node-dht-sensor which would allow me to use the sensor directly with node, which seemed nice. Mainly I just grabbed the data given to me as an object by the node-dht-sensor package and separated it into Temperature and humidity. In the code you can identify this object called as ‘sensorReadings’. 

Log sensor data function.
Log sensor data function.

At this point I decided that logging the data was also my best option. So I wrote all of my logs into a ‘data.text file. This later served an unexpectedly to make my job of displaying the data much easier.

Log Success!
Log Success!
DHT11 temperature sensor.

The package website included a diagram for wiring the sensor. Even though the wiring is straightforward it was useful to see right away it didn’t involve a difficult setup. The sensor has a pin to 3.3V, another for GND, and one output pin to connect to the GPIO pin in the Raspberry PI. 

DHT11 Connection Diagram
DHT11 Connection Diagram

I wanted the sensor to be as precise as possible, so when I saw some examples with the library I wondered why there weren’t any float values. After looking around for a while, I foudn the following : “According to the data sheet, the accuracy of DHT11 is ±2℃. So reporting with decimals doesn’t make sense. If the sensor is reporting 22 degrees the temperature might be anywhere between 20 and 24.” (Taken from here). There is another model called the DHT22 which apparently has a lower variance of ±0.2℃, and I will use it next time. A degree or two of difference seems too unreliable for me.

SSD13106 OLED Monochrome screen

At first I thought I would use an ADC converter in order to get data on to the screen. However, after a couple of minutes google searching I was determined to find a way to do it with Node. I had a bunch of trouble using the rpi-oled package. However, the i2c package it required was almost impossible to install, and even then it would not work for me. So I decided to use oled-i2c-bus, which required a package called i2c-bus. It worked great since it was specifically made to avoid using the i2c package. At the end of this page I detail some issues I had working with the screen.

 In any case, I decided to use Moment.js to register the time which had passed since the last message was sent. IT would also read into

SSD1306 LED Monochrome screen.
SSD1306 LED Monochrome screen.
SSD1306 connected!
SSD1306 connected!
SSD1306 error
SSD1306 error. Grabbed from https://tinusaur.org/tag/ssd1306/.

I had this mistake several times while running my code, especially when cleaning the screen occurred right before I wanted to print a new message. I managed to solve this by creating an Asynchronous function out of the displaySensorData() function. In simple terms, I made the function wait for the screen to be cleaned and THEN print the new message. Sounds simple but solves everything.

Asynchronous function to clean the screen and make new message.

Sending the Data

Now came the fun part, sending the data. Fortunately, I had Tom Igoe’s Pi Recipes page, and his  NodeSensors Github repository with the project. One of the first things we had to do was obtain an authorization token from Tom in order to be able to push data into the server. To obtain the key we first needed to find our MAC Address. With the Raspberry PI there will be two MAC addresses: one called eth0 and another called wlan0. I quickly used a google search to find this “Eth0 and wlan0 are not assigned by your ip, eth0 and wlan0 are device names assigned by ubuntu. Eth0 is your ehternet connection and wlan0 is your wireless connection but sometimes wlan0 might be called eth1 instead it all depends on the driver your wireless card is using.” ( found here). In any case, we would be connecting through WiFi, so wlan0 is our address. 

With my MAC Address, the session key given to me, and my hostname I was ready to send the data as a json. This involved using the https npm package with requests. This can be seen in the Github repository.

mac Address Command.
Finding Mac Address
Finding Mac Address
Pre-case version

Cron Job

Response to my GET request.
Response to my GET request.

Making the case

I had thought about making a nice enclosure for the Pi, and had been thinking about 3D printing something for a while so I went with it. It had also been years since I’d opened a 3D modelling software so I decided to go with Blender. I found a Raspberry Pi case .stl file in Thingiverse (VERY recommended website for 3D models for printing.)which seemed cool, rigid, and easy to adapt to my sensor and screen.

3D case taken online.
3D case taken online.
Personalized case.
Personalized case.

To make the the case for my Pi I added two cube meshes that intersected the top face of the Raspberry Pi case .stl file. I later applied an object modifier unto the .stl imported mesh which deletes these two volumes. The result is shown above, and the process shown below.

Blender boolean operation.

I later exported this model in two different .stl files. One for the top half and another for the bottom. This was mainly due to time constraints. Below is the previsualization of the the model, the printing process,and the result.

Cura Ultimaker 3D Print
Cura Ultimaker 3D Print
3d printing model with Ultimaker 2+.
3d printing model with Ultimaker 2+.
Printed top half.
Printed top half.

Issues

Node and npm

At first, when I ran the node or the npm command nothing would appear. So I reinstalled npm and decided to uninstall that version of node and installed nodejs instead. 

Removing Node.
Removing Node.

Installing nodejs and npm correctly. Or at least in a way that it would work for me.

Install npm.
Install npm.
Install Nodejs.
Install Nodejs.

Code

Circuit Schematic

Circuit Schematic.
Circuit Schematic. Made with https://www.circuit-diagram.org/