14. Networking and communications¶
This week assignment we should design, build, and connect wired or wireless node(s) that communicate with each other via network or bus (addresses). The purpose is to know how integrate components in a network and how to make them interact with each other via the network. Previously I have designed a board that reads the value from a distance sensor and shows it in a OLED screen. This week I decided to add these components in a wireless node and exchange the information via WiFi. The sensor will send the distance read and the OLED will show it in a way that they can be located in different locations and still communicate with each other.
Up to now, I was using ATtiny in the assignments, however this week this was not possible. ATtiny does not have enough memory available to load all the code necessary to enable the node to communicate with each other. So, I decided to use Wemos that is a WiFi development board base on ESP8266 (standard board for WiFi communication). The functioning of this board is similar to a NodeMCU, except that the hardware resembling Arduino UNO. It is a powerful board and I will fit perfectly to design the solution of the assignment of this week. For more info, visit their website WEMOS Home
I have designed a very simple circuit for this assignment. I have used the sensor VL53L0X (also used in the 11. Input devices assignment) with Wemos. Wemos will be configurated to read the sensor value and send via MQTT using the ESP8266 board (WiFi) to another node that will be listening for the sensor value. The pins SCL and SDA from VL53L0X were connected to D1 and D2 from Wemos. VCC from the sensor were connected to 3.3V Wemos pin.
As I have made a couple of boards in previous assignments, I decided this week to focus in the communication between the nodes I designed. 11. Input devices assignment provides the detailed steps on how to design, mill, and sold customized PCBs. Bellow there is the gerber files generated from the designed PCB which you can mill the board using the mentioned steps in previous assignment.
Again, I have designed a very simple circuit. I have used the OLED 128x32 I2C (also used in the 13. Output devices assignment) with Wemos. Wemos will be configurated to get data from the sensor via MQTT using the ESP8266 board (WiFi) and update the distance value in the OLED screen. The pins SCL and SDA from OLED were connected to D1 and D2 from Wemos. VCC from the sensor were connected to 3.3V Wemos pin.
I follow the strategy explained in the previous section, and I provide the gerber file to mill the board.
The Message Queuing Telemetry Transport (MQTT) is a standard messaging protocol for Internet of Things (IoT). It is designed as an extremely lightweight publish/subscribe messaging transport that is ideal for connecting remote devices with a small code footprint and minimal network bandwidth. Using MQTT, one node A can subcribe one topic X and another node B can publish messages to this topic that will be received by the node A. Many nodes can subscribe the same topic as well as many nodes can publish messages to the same topic. This easily create a N to N communication between different devices, not just IoT. Bellow the esquematic of how the communication happens between the devices when using MQTT (more info).
The communication requires a server and I decided to use a Raspberry Pi to create the WiFi network and also to host the MQTT Broker. The configuration will be present bellow.
The setup for the assignment requires the following steps:
- Prepare Raspberry Pi
- Configurate Raspberry Pi as AP
- Install MQTT
- Install libraries in the ArduinoIDE
I followed up the steps described at Raspberry Pi setting up to install the Operation System Raspberry Pi. It also gives some details about the device and its capability. First I installed the Raspberry Pi Imager. Then I wrote the operation system RASPBERRY PI OS (32-BIT) files in a SDHC CARD. The device was ready to be configurated.
Access Point (AP)¶
In order to have a dedicate network, I have setup the Raspberry Pi as Access Point (AP) following the steps in Access point routed. I did not execute the step Enable routing and IP masquerading because it was not necessary for the purpose of this assignment.
Here are the steps taken to prepare the environment to setup the AP.
sudo apt install hostapd
Enable wireless access point service and set it to start during boot
sudo systemctl unmask hostapd sudo systemctl enable hostapd
sudo apt install dnsmasq
Finally, install netfilter-persistent and its plugin iptables-persistent. This utilty helps by saving firewall rules and restoring them when the Raspberry Pi boots
sudo DEBIAN_FRONTEND=noninteractive apt install -y netfilter-persistent iptables-persistent
Here are the steps taken to setup the network router.
Change the IP address for DHCP server in the raspberry pi (file /etc/dhcpcd.conf). It is important to have an static IP address to avoid the need of updating the nodes every time the raspberry pi reboot and change the IP address. Initially I used the interface name wlan1 to avoid name problem current configuration of raspberry pi that has wlan0. I learned that the interface name is associated to the network board in the raspberry pi and should match it. So I used the name wlan0. The IP address can have different numbers as long it uses the same format (10.20.30.40 would be a valid value as well). I followed the standard numbers for IP address, just changing the last two digits.
interface wlan0 static ip_address=192.168.4.1/24 nohook wpa_supplicant
Configure the DHCP and DNS services for the wireless network
Save previous file to have a backup if I needed undo some configuration.
sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
Create a new one with the same name in the same location
sudo nano /etc/dnsmasq.conf
Add the following content:
interface=wlan0 # Listening interface dhcp-range=192.168.4.2,192.168.4.20,255.255.255.0,24h # Pool of IP addresses served via DHCP domain=wlan # Local wireless DNS domain address=/gw.wlan/192.168.4.1 # Alias for this router #raspberry pi can be reached by gw.wlan from wireless client.
Ensure wireless operation. To ensure WiFi radio is not blocked on your Raspberry Pi, execute the following command:
sudo rfkill unblock wlan
Configure the access point software. Create the file sudo nano /etc/hostapd/hostapd.conf and add the following content. You can choose the ssid of your interest and a better password (wpa_passphrase).
country_code=GB interface=wlan0 ssid=FabAcademy hw_mode=g channel=7 macaddr_acl=0 auth_algs=1 ignore_broadcast_ssid=0 wpa=2 wpa_passphrase=fabacademy wpa_key_mgmt=WPA-PSK wpa_pairwise=TKIP rsn_pairwise=CCMP
Run your new wireless Access Point.
sudo systemctl reboot
Devices able to connect to WiFi can now see a new connection called FabAcademy (if you choose the same name above). Check which devices are connected in your AP.
arp -a -n
Continuing the installation still in the raspberry pi, install mosquitto and mosquitto-clients softwares. They will serve as MQTT Broker to enable the communication between the devices.
sudo apt-get install mosquitto sudo apt-get install mosquitto-clients
Check if the MQTT broker is running (after reboot). Open two terminals and execute:
mosquitto_sub -h localhost -t intellettoTest
mosquitto_pub -h localhost -t intellettoTest -m "Testing1" mosquitto_pub -h 192.168.4.1 -t intellettoTest -m "Testing2"
The messages Testing1 and Testing2 should be printed in the Terminal One.
You can install mosquitto for windows here and exchange messages with the MQTT Broker. Do not forget to connect in the same network FabAcademy. Executing the following command, it should appear in the Terminal One the message Testing3.
mosquitto_pub -h 192.168.4.1 -t intellettoTest -m "Testing3"
Install libraries in the ArduinoIDE¶
In my work PC, it was necessary to install the board Esp8266 to enable configurate the WiFi board (includes also the library ESP8266Wifi) and PubSubClient to enable exchange message via MQTT Broker. Previously I have installed VL53L0X to be able to read the distance sensor and Tiny4OLED to show content in the OLED. I was able to reuse the library to read the distance sensor, but I needed to install the library U8g2 to show the content in the OLED. The libraries can be installed in the menu Sketch > Include Library > Manage Libraries….
To install the board and library Esp8266, follow the steps (also here):
- Add the link http://arduino.esp8266.com/stable/package_esp8266com_index.json in the Additional Boards Manager URL (menu: File > Preferences)
- Install board Esp8266 (menu: Tools > Board > Board Manager)
- Select the correct board type for the Wemos.
Initially I have installed the most recent version of the board Esp8266. However this version re-implements some standard libraries from ArduinoIDE and I had difficulties to work with these libraries, since it changed or did not implement the methods I needed to use. I have decided to install the version 2.3.0 which a specialist told me to be a stable version that provides the methods I need to use. The environment is ready to move to the implementation.
I studied the project Intel.letto to understand how I could implement the solution in my assignment. I will need two programs: (i) for the distance sensor and (ii) for the OLED screen. Trying to centrilize the common code that both programs would have, I create a module week14functions declaring the variables and functions in the header file (.h) and implementing them in the definition file (.c). ArduinoIDE was not able to compile the .c file, so I copied the definitions inside the header file (similar to what was done in the Intel.letto project). The code was working fine, until I face some errors and needed to change the version of the board Esp8266. Then the wemos could not connect in the WiFi anymore.
The library PubSubClient provides some code example, I checked if the wemos was working by adapting the example file mqtt_esp8266 to connect in the WiFi i have configurated for this assignment (mqtt_esp8266_example). Then, Wemos was able to connect in the WiFi again. I tried to check what was the problem of the previous code, comparing line by line with the code example, but I could not find the reason. So, to implement the solution for the assignment, I used the code example integrating the necessary code to read the distance sensor and to show it in the OLED (using the MQTT communication).
I have extended the example mqtt_esp8266 to work with the distance sensor VL53L0X. I have created the file mqtt_esp8266_sensor.ino including the library VL53L0X that enables to get the sensor measurement. I also added the library Wire.h to setup the I2C communication between the Wemos and the sensor. I used the pins D1 and D2 from wemos to work with the SDA and SCL, respectively, of the distance sensor. Following the code of the sensor.
Include libraries and declare variables that will be used in the program.
Function that connects to the Wifi configurated in the Raspberry Pi. The variables ssid and password should match the ones configurated in the raspberry pi.
These are the functions that perform MQTT operations. The function mqttMessageCallback is called when the node receives a message via a topic that previously subscribed. The second one, setupMqttClient, initialize a client for the MQTT. mqttSubscribeTopic executes the library call to subscribe a topic in the MQTT Broker and mqttPublishMessage sends a message for a topic registered in the MQTT Broker. The function mqttReconnect reconnect the node in the MQTT Broker. And the last one handleMQTTClient check if the node has received any message, which triggers the function mqttMessageCallback.
The setup function stablishes the connection with the WiFi and the MQTT Broker, but also setup the sensor to work with the wemos in the defined pins mentioned before. The loop function will simply checks if the node received message (only for test purpose since this node is not configurated to process received messages) and reads and sends the sensor measurement to the topic mqttOLEDListener that is registered to the wemos OLED (explained bellow).
I have also create an extension of the code example, named mqtt_esp8266_OLED. I have included the library u8g2lib that shows messages in the OLED screen. I have also added the library Wire.h to setup the I2C communication between the Wemos and the OLED. I also used the pins D1 and D2 from wemos to work as the SDA and SCL, respectivelly, of the OLED. Following the code of the OLED.
The list of libraries and variables are similar, differing in the library u8g2lib for the OLED and the variables used to manage the OLED.
Here it was used the same function to connect in the WiFi (showed before).
The functions to perform MQTT operations are very similar to the ones showed before, except for the function mqttMessageCallback, that update the OLED screen with the message received.
These two functions are to support updating content in the OLED screen. initial_display only shows an initial message to confirm the OLED is setup correctly. update_oled print the message received via MQTT Broker in the OLED.
The setup function is very similar, except that setup the OLED screen in the last step. The function loop only check if the node received message via MQTT Broker, triggering the callback function that update the OLED screen.