You are on page 1of 131

Table of Contents

1. Versions .................................................................................................... 7
2. Preface ...................................................................................................... 8
3. Project Information ..................................................................................... 9
4. Introduction to the Remote Distant Laboratories............................................. 10
5. VREL #1 and #3: General Purpose IoT Laboratory, air receiving nodes 1 and 3 ..13
5.1. Introduction ......................................................................................... 13
5.2. Prerequisites ........................................................................................ 13
5.3. Sensors............................................................................................... 13
5.3.1. Technical details for the flap position monitor...................................... 13
5.4. Actuators............................................................................................. 15
5.5. Software, libraries and externals............................................................. 16
5.6. Communication .................................................................................... 16
5.7. Limits ................................................................................................. 17
5.8. Support............................................................................................... 17
6. VREL #2 and #4: General Purpose IoT Laboratory, air pushing nodes 2 and 4 ....18
6.1. Introduction ......................................................................................... 18
6.2. Prerequisites ........................................................................................ 18
6.3. Technical details ................................................................................... 18
6.4. Sensors............................................................................................... 19
6.5. Actuators............................................................................................. 19
6.6. Software, libraries and externals............................................................. 20
6.6.1. Support ......................................................................................... 22
7. VREL #6: Color Temperature and Brightness Compensation Laboratory .............23
7.1. Introduction ......................................................................................... 23
7.2. Prerequisites ........................................................................................ 24
7.3. Technical details ................................................................................... 24
7.4. Sensors............................................................................................... 26
7.5. Actuators............................................................................................. 27
7.6. Software, libraries and externals............................................................. 28
7.7. Communication .................................................................................... 28
7.8. Limits ................................................................................................. 29
7.9. Support............................................................................................... 29
8. VREL #8 through #11: General Purpose IoT Laboratory with air chamber for
pressure monitoring ....................................................................................... 30
8.1. Introduction ......................................................................................... 30

2
8.2. Prerequisites ........................................................................................ 30
8.3. Sensors............................................................................................... 30
8.3.1. Technical overview of the node and air pressure chamber overview .......31
8.4. Actuators............................................................................................. 32
8.5. Software, libraries and externals............................................................. 33
8.5.1. LCD Display.................................................................................... 33
8.5.2. Servo ............................................................................................ 33
8.3.1. Fan ............................................................................................... 31
8.6. Communication .................................................................................... 34
8.7. Limits ................................................................................................. 35
8.8. Support............................................................................................... 35
9. Hands-on lab scenarios for SUT VREL nodes .................................................. 36
9.0.1. B1: Basic operations on the 4x20 LCD screen .................................... 36
9.0.2. B2: Presenting temperature and humidity on the LCD ......................... 39
9.0.3. B3: Handling LED brightness using PWM via I2C controller................... 41
9.0.4. B4: E-paper display operations ........................................................ 44
9.0.5. B6: Presenting air pressure on the LCD ............................................. 45
9.0.6. B7: Controlling servo ...................................................................... 48
9.0.7. B8: Controlling fan using PWM ......................................................... 51
9.0.8. U1: Connecting to the network in STA mode ...................................... 53
9.0.9. U2: Exposing access point (AP) ........................................................ 56
9.0.10. U3: Sending MQTT messages ......................................................... 58
9.0.11. U4: Receiving and handling MQTT messages .................................... 63
9.0.12. U7: Controlling fan speed and servo angle via MQTT ......................... 68
9.0.13. U8: Visualising and sending flap state ............................................. 73
9.0.14. U9: A CoAP client ......................................................................... 76
10. ITT modular component laboratory ............................................................. 81
10.1. ITT Controller module basics ................................................................ 81
10.1.1. Introduction.................................................................................. 81
10.1.2. Prerequisites................................................................................. 81
10.1.3. Technical details............................................................................ 81
10.1.4. Specifications................................................................................ 82
10.1.5. Electrical connection ...................................................................... 82
10.1.6. Actuators ..................................................................................... 82
10.1.7. Software, libraries and externals ..................................................... 82
10.1.8. Communication ............................................................................. 83
10.1.9. Limits .......................................................................................... 83

3
10.2. ITT RGB LED module ........................................................................... 83
10.2.1. Introduction.................................................................................. 83
10.2.2. Prerequisites................................................................................. 84
10.2.3. Technical details............................................................................ 84
10.2.4. Hands-on labs............................................................................... 84
10.2.5. Support........................................................................................ 86
10.3. ITT Temperature and humidity sensor module ........................................ 86
10.3.1. Introduction.................................................................................. 86
10.3.2. Prerequisites................................................................................. 87
10.3.3. Technical details............................................................................ 87
10.3.4. Hands-on labs............................................................................... 87
10.3.5. Support........................................................................................ 88
10.4. ITT Servo module ............................................................................... 88
10.4.1. Introduction.................................................................................. 88
10.4.2. Prerequisites................................................................................. 89
10.4.3. Technical details............................................................................ 89
10.4.4. Hands-on labs............................................................................... 90
10.4.5. Support........................................................................................ 91
10.5. ITT Relay module................................................................................ 91
10.5.1. Introduction.................................................................................. 91
10.5.2. Prerequisites................................................................................. 92
10.5.3. Technical details............................................................................ 92
10.5.4. Hands-on labs............................................................................... 93
10.5.5. Support........................................................................................ 94
10.6. ITT OLED display module ..................................................................... 94
10.6.1. Introduction.................................................................................. 94
10.6.2. Prerequisites................................................................................. 94
10.6.3. Technical details............................................................................ 94
10.6.4. Hands-on labs............................................................................... 95
10.6.5. Support........................................................................................ 98
11. SmartMe Network Laboratory: Arduino Nodes 1-5......................................... 99
11.1. Introduction ....................................................................................... 99
11.2. Prerequisites ...................................................................................... 99
11.3. Technical details ................................................................................. 99
11.3.1. Node schematic........................................................................... 100
11.4. Sensors ........................................................................................... 102
11.5. Actuators ......................................................................................... 103

4
11.6. Software, libraries and externals ......................................................... 104
11.7. Communication ................................................................................ 105
11.8. Limits.............................................................................................. 106
11.9. Support ........................................................................................... 106
11.9.1. IB1: Basic operations on the 2x16 LCD screen................................. 106
11.9.2. IB2: Presenting temperature and humidity values on the LCD ........... 109
11.9.3. IB3: PWM mode (~) of digital pins, programming threshold values .... 113
11.9.4. IU1: Showing temperature, humidity and dust values on the 2x16 LCD
screen .................................................................................................. 116
11.9.5. IM1: MQTT to publish a message with a topic .................................. 121
11.9.6. IM2: MQTT to subscribe to a topic to receive messages .................... 126

5
Authors
IOT-OPEN.EU consortium selected partners collective monography. The full list of
contributors is juxtaposed below.

ITT Group
▪ Raivo Sell, Ph.D., ING-PAED IGIP
▪ Rim Puks, Eng.
▪ Mallor Kingsepp, Eng.

Silesian University of Technology


▪ Piotr Czekalski, Ph.D., Eng.
▪ Gabriel Drabik, Ph.D., Eng.
▪ Oleg Antemijczuk, M.Sc., Eng.
▪ Jarosław Paduch, M.Sc., Eng.

University of Messina
▪ Salvatore Distefano, Ph.D., Eng.
▪ Riccardo Di Pietro, Eng.
▪ Giovanni Merlino, Ph.D., Eng.
▪ Carlo Scaffidi, Eng.

Graphic design and images


▪ Blanka Czekalska, M.Sc., Eng., Arch.
▪ Małgorzata Wiktorczyk, B.Sc. Eng.

6
1. Versions

1. Versions
This page keeps track of the content reviews and versions done as a continuous
maintenance process

Table 1: Versions and Content Updates

Change
# Version Content updates summary Other comments
Date
1 v 0.1 01.01.2019 Preliminary content
Fixed pre publishing for
2 v 0.2 11.08.2019
limited number of labs
Reorganised chapters to fit
3 v 0.3 29.10.2019
ToC
4 v 0.4 29.10.2019 Layout correction
Images standardisation
5 v 0.5 29.10.2019
and code wrapping
VREL nodes 8-11
6 v 0.6 28.04.2020 (no scenarios yet)
description
VREL nodes 8-11 scenarios
7 v 0.7 05.05.2020 and reorganisation of the
ToC
VREL nodes 8-11
8 v 0.8 06.05.2020
platformio.ini update
VREL nodes 8-11
9 v 0.9 07.05.2020
platformio.ini update
VREL nodes 8-11 There is a problem with BMP280
10 v 0.91 12.05.2020 platformio.ini update, U9 library (still) unsolved in some
scenario added cases.
11 v 0.92 17.05.2020 U7 scenario updated

7
2. Preface

2. Preface
This book and its offshoots were prepared to provide an additional and practical add-on
for the main book on the Internet of Things. The primary goal of this book is to provide
a detailed description of the VREL - IoT laboratories with remote access for those who
interface our labs remotely. Its secondary goal is to give ideas on the IoT projects to the
bachelor students, master students, technology enthusiasts and engineers.

This book is also a good starting point for teachers, tutors and educators to start
preparing of other materials for their implementation of the practical course on IoT,
construct their laboratories, develop a module or even full curriculum related to the IoT.

We (authors) assume that persons willing to study this content are already familiar
with our “Introduction to the IoT book” or has equivalent knowledge and has at least
elementary skills on programming in C, Python and C#.

We believe this manual will help to seamlessly start your work with real IoT devices,
whether you have them on your desk or you access them remotely using our VREL
model.

Note: Practice makes a master, so enjoy programming IoT!

8
3. Project Information

3. Project Information
This Intellectual Output was implemented under the Erasmus+ KA2: Strategic
Partnerships in the Field of Education, Training, and Youth – Higher Education.
Project IOT-OPEN.EU – Innovative Open Education on IoT: Improving Higher Education
for European Digital Global Competitiveness.
Project number: 2016-1-PL01-KA203-026471.

Erasmus+ Disclaimer
This project has been funded with support from the European Commission.
This publication reflects the views only of the author, and the Commission cannot be held
responsible for any use which may be made of the information contained therein.

Copyright Notice
This content was created by the IOT-OPEN.EU consortium: 2016–2019.
The content is Copyrighted and distributed under CC BY-NC Creative Commons Licence,
free for Non-Commercial use.

In case of commercial use, please contact IOT-OPEN.EU consortium representative.

9
4. Introduction to the Remote Distant Laboratories

4. Introduction to the Remote Distant


Laboratories

Laboratories can be accessed via a single entry point, using web platform available
here: http://distance.roboticlab.eu/. Please note that there is a variety of hardware
specifications, and almost every node has different peripherals and physical properties.
Following chapters present a list of the laboratories and their documentation. Read it
carefully before jumping in into the programming it. To be able to connect to the labs
you need to create an account and book a device as all devices can be used in exclusive
mode only. You can book more than one at a time to create a fully-featured distributed
IoT solution, even across a few countries!

Note, even remotely, you're facing real, physical devices with actuators thus you always
must consider in your experiments physical phenomena like time, friction, pendulum,
and so on.

Each document has subchapters with hands-on labs to launch your experience with the
device. You can extend those scenarios yourself!

List of laboratories:

SUT The Silesian University of Technology, laboratories location: Gliwice,


Poland All nodes are using NodeMCU v.3 (ESP-12E) MCUs.

▪ Node 1 and Node 3 VREL #1 and #3: General Purpose IoT Laboratory, air receiving
nodes 1 and 3 - air RX
▪ Node 2 and Node 4 VREL #2 and #4: General Purpose IoT Laboratory, air pushing
nodes 2 and 4 - air TX
▪ Node 5 roboarm (under maintenance)
▪ Node 6 VREL #6: Color Temperature and Brightness Compensation Laboratory
▪ Node 7 rooftop (under maintenance)
▪ Node 8 through 11 VREL #8 through #11: General Purpose IoT Laboratory with air
chamber for pressure monitoring

10
4. Introduction to the Remote Distant Laboratories

Figure 2: SUT Physical location of the VREL nodes

Laboratory provides access to the uniform WiFi, private and separated network with
MQTT and NodeRED services able to relay and route application-level messages to and
from the Internet (devices remain separated, however). This way you can contact any of
the nodes as they present themselves in a single IPv4 “internal.IOT” WiFi network.
Nodes 1 through 4 are in a physical distance able to “see” one another, but separated
from other devices.
Nodes 8 through 11 are in a physical distance able to “see” one another, but separated
from other devices.
Node 6, node 7 and node 5 are in physically distant locations so there is no warranty
that setting up the device as AP enables to connect to them from any other node. If
you want to implement communication scenarios independent on the provided WiFi AP,
please note to use VRELs 1 through 4 or 8 through 11.

ITT Group, laboratories location: Tallinn, Estonia All nodes are using ESP8266 MCUs

▪ Node 1 Remote lights


▪ Node 2 Temperature/Humidity controlled rooms
UME University di Messina, laboratory location: Messina, Sicilia, Italy Nodes 1
through 5 use Arduino Uno with Ethernet Shield while Node 6 uses Arancino board.

11
4. Introduction to the Remote Distant Laboratories
▪ Node 1-5 SmartME Network Laboratory Arduino.
▪ Node 6 SmartME Network Laboratory Arancino.

12
5. VREL #1 and #3: General Purpose IoT Laboratory, air receiving
nodes 1 and 3

5. VREL #1 and #3: General Purpose IoT


Laboratory, air receiving nodes 1 and 3
The laboratory is located at Silesian University of Technology, Gliwice, Poland,
Akademicka 16, room 310. There are two nodes of this kind: Node 1 and 3, one per two
air ducts, constituting a pair of working devices along with Nodes 2 and 4 respectively.

5.1. Introduction
The lab consists of a mechanical airflow indicator going from the pipe (connected to a
neighbour, TX lab). The indicator is a vertical flap, which changes position depends on
airflow. The position of the flap is observable, using the camera and measurable using
a photoelectric proximity sensor. The signal from the sensor is sent to the AD converter
and additionally is displayed on needle gauge.

5.2. Prerequisites
The user needs to know:

▪ physical effect of the airflow,


▪ elementary rules od light propagation,
▪ work of the unbalanced bridge.

5.3. Sensors
The sensor of flap position is made which photoresistors. For reference, next to the flap
there is an immovable surface made with the same material like the flap. Like in case
of flaps, here is an identical photoresistor. Both of resistor make an unbalanced bridge,
with is balanced, if the flap is in the start position (without airflow). For balancing bridge
in the start position, two another resistors in the bridge, are build which potentiometer.

5.3.1. Technical details for the flap position monitor


End of the air duct is fitted to rectangle flap, The flap is hanging loosely and can be
pushed by the airflow. The flap is lighted by LED form the top, and at the opposite side
of the flap, there is the photoresistor, which measures light intensity, reflected from the
flap. The flap sensing system is connected to the analogue input A0.

13
5. VREL #1 and #3: General Purpose IoT Laboratory, air receiving
nodes 1 and 3

Independent, in the lab there is a sensor of temperature and humidity, DHT22, connected
to the D4/GPIO2.

14
5.4. Actuators

5.4. Actuators
There are no mechanical actuators in this laboratory.
LCD Display is 4×20 characters. LCD is controlled via I2C extender: LCM1602. The I2C
extender address is 0x3F and the I2C bus is connected to the pins D1/GPIO5 and D2/
GPIO4 (D1 is SCL and D2 is SDA).
As you do not have any access to the serial console, use LCD to visually trace the
progress of your program, connection status, etc. By the LCD display, there are two LEDs
that can be used to trace status. One LED is connected to the pin GPIO 16 while the
other one to the GPIO pin 2. The former one (GPIO 2) is connected to the Serial Port TX
as well so expect it flashing when communicating over serial protocol (i.e. flashing new
firmware that is beyond the control of your code).

Please note cameras are running only with some 5-10fps so do not implement quick
flashing light as you may not be able to observe it remotely. Same note applies to the

15
5. VREL #1 and #3: General Purpose IoT Laboratory, air receiving
nodes 1 and 3
quick changes of the LCD contents.

Build in LEDs (both) are active with signal LOW so setting HIGH on GPIO 16 or 4 switches
them off while setting LOW switches them on.

5.5. Software, libraries and externals


LCD display requires a dedicated library. Of course, you can control it on the low-level
programming, writing directly to the I2C registers, but we do suggest using a library
first. As there are many universal libraries, and many of them are incompatible with this
display, we strongly recommend using ''LiquidCrystal_I2C by Tony Kambourakis''. The
LCD I2C control library can be imported to the source code via:

#include <LiquidCrystal_I2C.h>

Then configure your LCD controller:

LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x3F


// for a 20 chars and 4 line display

Platformio.ini
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; http://docs.platformio.org/page/projectconf.html

[env:d1_mini]
platform = espressif8266
board = d1_mini
framework = arduino
lib_deps = Wire, EmonLib, Adafruit NeoPixel, Encoder,DHT sensor library,
Adafruit Unified Sensor,
LCD, PubSubClient, KS0108_PCF8574, 2120

5.6. Communication
You can connect your ESP8266 microcontroller via its integrated WiFi interface to the
separated IoT network. Then you can communicate with other nodes and players,
already connected devices and even provide some information to the cloud. In details,
there is a dedicated MQTT broker waiting for you. You can also set up your soft Access
Point and connect another node directly to yours.

The communication among the devices can be done using MQTT messages, exchanging
data among other nodes (M2M) and you can even push them to the Internet via MQTT
broker.

Using your Node, you can access it and publish/subscribe to the messages once you

16
5.7. Limits
connect your ESP to the existing wireless network (this network does not provide access
to the global internet and is separated but please note there are other developers and
IoT nodes connected to this access point:

▪ SSID: internal.IOT
▪ Passkey: IoTlab32768
▪ Setup your microcontroller for DHCP, to automatically obtain an IP address, your ESP
will obtain the address from the 192.168.90.X pool.
▪ MQTT server is available under the fixed address: 192.168.90.5, and the credentials
to publish/subscribe are:
▪ User: vrel
▪ Password: vrel2018
The same MQTT server/broker is visible under public IP: 157.158.56.54 port 1883 (non-
secure) and 8883 (secure) to let you exchange data with the world and control your
devices remotely.

5.7. Limits
At the same time, only one user can be programming the controller, although analysing
the signal by others (unlimited number) the user has sense. Model is provided to work
continuously, without service breaks. For more interesting experiments, the user should
be access to complementary Tx lab at the same time.

5.8. Support
gabriel.drabik@polsl.pl

17
6. VREL #2 and #4: General Purpose IoT Laboratory, air pushing
nodes 2 and 4

6. VREL #2 and #4: General Purpose IoT


Laboratory, air pushing nodes 2 and 4
The laboratory is located at Silesian Technical University, Poland, Gliwice Akademicka 16,
room 310.

6.1. Introduction
The node is an airflow generator, connected to the appropriate air receiving node. There
is an air duct that connects nodes (node 2 send air to node 1, while node 4 send air to
node 3). The lab consists of the fan which is a source of airflow going to the air duct. The
beam of the airflow can be regulated in two ways:

▪ by changing the rotation speed of the fan,


▪ by changing the position of the closing flap, mounted in front of the fan.
The voltage on the fan is visible on needle multimeter.

6.2. Prerequisites
The user needs to know:

▪ physical effect of the airflow,


▪ PWM control method,
▪ working od servo-motors and its control.

6.3. Technical details


End of the pipe is fitted to fan which is covered by rectangle flap. The flap is hanging on
servomotor lever. Both fan and servomotor, are connected to the PWM outputs (each has
its pin, enabling to control them independently) from the SoC. It is possible to change the
rotating speed of the fan, and also the position of the flap. Parallel, the voltage on the fan
(effective value), is displayed on analogue spindle voltage meter and can be observed
via camera.

18
6.4. Sensors

6.4. Sensors
There is a temperature and humidity sensor in the lab node: DHT22, connected to the
GPIO0 (D4).

6.5. Actuators
There are two actuators (fan, servo) and LCD display.

▪ The fan is a DC controlled one, where using PWM one can change rotation speed.
▪ the pin is GPIO 15/ D8
▪ The servo is an analogue servo, Emax ES08A II:
▪ min timing 1500us max timing 1900us
▪ the pin is GPIO 14 / D5
▪ LCD is I2C controlled, present under address 0x3F on the I2C bus
▪ I2C bus is connected to the:
▪ SDA GPIO5 / D1
▪ SCL GPIO4 / D2

19
6. VREL #2 and #4: General Purpose IoT Laboratory, air pushing
nodes 2 and 4

6.6. Software, libraries and externals


LCD display requires a dedicated library. Of course, you can control it on the low-level
programming, writing directly to the I2C registers, but we do suggest using a library
first. As there are many universal libraries, and many of them are incompatible with this
display, we strongly recommend using ''LiquidCrystal_I2C by Tony Kambourakis''. The
LCD I2C control library can be imported to the source code via:

#include <LiquidCrystal_I2C.h>

Then configure your LCD controller:

LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x3F


// for a 20 chars and 4 line display

Platformio.ini
; PlatformIO Project Configuration File
;

20
6.6. Software, libraries and externals
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; http://docs.platformio.org/page/projectconf.html

[env:d1_mini]
platform = espressif8266
board = d1_mini
framework = arduino
lib_deps = Wire, EmonLib, Adafruit NeoPixel, Encoder,DHT sensor library,
Adafruit Unified Sensor,
LCD, PubSubClient, KS0108_PCF8574, 2120

Communication
You can connect your ESP8266 microcontroller via its integrated WiFi interface to the
separated IoT network. Then you can communicate with other, already connected
devices and even provide some information to the cloud. In details, there is a dedicated
MQTT broker waiting for you. You can also set up your soft Access Point and connect
another node directly to yours.

The communication among the devices can be done using MQTT messages: exchanging
data among other nodes (M2M) and you can even push them to the Internet.

Reference data

Using your Node, you can access it and publish/subscribe to the messages once you
connect your ESP to the existing wireless network (this network does not provide access
to the global internet and is separated, but please note there are other developers and
IoT nodes connected to this access point:

▪ SSID: internal.IOT
▪ Passkey: IoTlab32768
▪ Setup your microcontroller for DHCP, to automatically obtain an IP address, your ESP
will obtain the address from the 192.168.90.X pool.
▪ MQTT server is available under the fixed address: 192.168.90.5, and the credentials
to publish/subscribe are:
▪ User: vrel
▪ Password: vrel2018

Limits
At the same time, only one user can program the controller, although analysing the
signal by others (unlimited number) the users is reasonable. Model is provided to work
continuously, without service breaks. For more interesting experiments, the user should
be access to complementary Rx lab at the same time (applies to the advanced lab
scenarios).

21
6. VREL #2 and #4: General Purpose IoT Laboratory, air pushing
nodes 2 and 4

6.6.1. Support
gabriel.drabik@polsl.pl

22
7. VREL #6: Color Temperature and Brightness Compensation
Laboratory

7. VREL #6: Color Temperature and Brightness


Compensation Laboratory
The laboratory is located at Silesian Technical University, Poland, Gliwice Akademicka 16,
room 319.

7.1. Introduction
The lab consists of two light sources placed on top of the pyramid-shaped tower (figure
##REF:Tower_diagram##). The tower is divided into two sections:

▪ Bright side - opened to ambient light and simultaneously illuminated by LEDs


▪ Dark side - only illuminated by LEDs
The user can experiment with controlling the brightness of LEDs and measuring the
intensity and colour of the light.

23
7. VREL #6: Color Temperature and Brightness Compensation
Laboratory
7.2. Prerequisites
The user needs to know:

Beginners:

▪ Basic knowledge of ESP8266 NodeMCU v2,


▪ ESP8266 Arduino programming,
▪ Basic knowledge of I2C Interface,
▪ Basic knowledge of I2C programming using Arduino I2C library,
▪ Knowledge of PWM controller chip PCA9685,
▪ Operation and method of PWM current control,
Undergraduates additionally:

▪ Knowledge of PWM controller chip PCA9685,


▪ Knowledge of I2C extender chip TCA9548A,
▪ Knowledge of light sensor chip TCS34725,
▪ Division of white light sources due to colour temperature,
▪ Measure of light intensity,
Masters additionally:

▪ Construction and operation of Cree Dynamic White LEDs,


▪ Knowledge of PWM controller chip PCA9685,
▪ Knowledge of I2C extender chip TCA9548A,
▪ Knowledge of light sensor chip TCS34725,
▪ Division of white light sources due to colour temperature,

7.3. Technical details


The main aim of the laboratory is to do different experiments with LED light. The user can
start with simple PWM controlling of LED. Next, try to keep a constant level of brightness
on a bright part of the model. The other aim is to keep the same level of lighting on a
dark part of the model, as is on the bright side. The diagram of the main part is shown
in figure 3, and diagram of LEDs connection is in figure 4

24
7.3. Technical details

Figure 3: Microcontroller with PWM and sensors.

25
7. VREL #6: Color Temperature and Brightness Compensation
Laboratory

Figure 4: LEDs connections

7.4. Sensors
A camera gives a general view on the bright side of the tower, and the second camera
at the bottom of the tower gives a view of how both parts of the ground are illuminated
(bright and dark) ambient light and RGB sensors are used as sensors for measuring
brightness and colour of light. The following devices are connected directly to the main
I2C controller:

I/O Device I2C address Description


PCA9685A 0x40h PWM LED controller
TCA9548A 0x70h I2C Extender

In the system, there are three TCS34725 light sensors. Sensors have the same I2C
addresses (0x29h) but are connected to different channels of I2C extender (TCA9548A).
I2C extender address is 0x70h.

Remember to always select the appropriate multiplexer channel before referring to the
correct light sensor

26
7.5. Actuators
TCA9548A I2C I2C Input/
Sensors Position Remarks
channel Address output

Channel Sensor TCS34725 RGB - Bottom of Main sensor of


0x29h Output
0 Main brightside mixed light
Channel Sensor TCS34725 RGB - Bottom of Sensor of only LED
0x29h Output
1 DarkSide darkside light
Channel Sensor TCS34725 RGB - Ambient light
0x29h Top of Tower Output
2 Ambient sensor
Channel
- - Output N/C
3
Channel
- - Output N/C
4
Channel
- - Output N/C
5
Channel
- - Output N/C
6
Channel
- - Output N/C
7

7.5. Actuators
In the system, there are two CREE dynamic LEDs. Each consists of four LED structures
with two cold-white and two warm-white lightning. First LED is placed on top of the
bright/openside of the tower and the second LED is placed on top of the dark/close
side. The each LEDs light intensity must be appropriately controlled using PWM current
controller which is separate for every white colour of each LED. ( Each PWM channel
controls two LED structures with identical light colour.) As PWM controller has been used
a 16-channel PWM chip - PCA9685 (Address - 0x40H). PCA9685 is connected directly to
the microcontroller's I2C master interface.

Actuator Position Input/output Remarks


Channel 0 On the board Input LED1/bright side warm-white
Channel 1 On the board Input LED1/bright side cold-white
Channel 2 On the board Input LED2/dark side warm-white
Channel 3 On the board Input LED2/dark side cold-white
Channel 4 On the board Input N/C
Channel 5 On the board Input N/C
Channel 6 On the board Input N/C
Channel 7 On the board Input N/C
Channel 8 On the board Input N/C

27
7. VREL #6: Color Temperature and Brightness Compensation
Laboratory
Actuator Position Input/output Remarks
Channel 9 On the board Input N/C
Channel 10 On the board Input N/C
Channel 11 On the board Input N/C
Channel 12 On the board Input N/C
Channel 13 On the board Input N/C
Channel 14 On the board Input N/C
Channel 15 On the board Input N/C

7.6. Software, libraries and externals


Platformio.ini
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; http://docs.platformio.org/page/projectconf.html

[env:d1_mini]
platform = espressif8266
board = d1_mini
framework = arduino
lib_deps = Wire, EmonLib, Adafruit NeoPixel, Encoder,DHT sensor library,
Adafruit Unified Sensor, LCD,
PubSubClient, KS0108_PCF8574, CoAP simple library

7.7. Communication
You can connect your ESP8266 microcontroller via its integrated WiFi interface to the
separated IoT network. Then you can communicate with other, already connected
devices and even provide some information to the cloud. In details, there is a dedicated
MQTT broker waiting for you. You can also set up your own soft Access Point and connect
another node directly to yours.

The communication among the devices can be done using MQTT messages, exchanging
data among other nodes (M2M) and you can even push them to the Internet.

Using your Node, you can access it and publish/subscribe to the messages once you
connect your ESP to the existing wireless network (this network does not provide access
to the global internet and is separated but please note there are other developers and
IoT nodes connected to this access point:

▪ SSID: internal.IOT
▪ Passkey: IoTlab32768

28
7.8. Limits
▪ Setup your microcontroller for DHCP, to automatically obtain an IP address, your ESP
will obtain the address from the 192.168.90.X pool.
▪ MQTT server is available under the fixed address: 192.168.90.5, and the credentials
to publish/subscribe are:
▪ User: vrel
▪ Password: vrel2018

7.8. Limits
At the same time, only one user can be programming the controller, although analysing
the signal by others (unlimited number) the user has sense. Model is provided to work
continuously, without service breaks.

7.9. Support
In case of problems contact: jaroslaw.paduch@polsl.pl

29
8. VREL #8 through #11: General Purpose IoT Laboratory with air
chamber for pressure monitoring

8. VREL #8 through #11: General Purpose IoT


Laboratory with air chamber for pressure
monitoring
The laboratory is located at Silesian University of Technology, Gliwice, Poland,
Akademicka 16, room 316 There are four nodes of this kind: Node 8,9,10 and 11. Nodes
may look different, in particular, nodes 8 and 10 are a mirror to the 9 and 11.

8.1. Introduction
The lab consists of a set of devices presenting various sensors and actuators. Each
laboratory is independent of the physical point of view, however, using a combination
of different devices connected via the network is advised. Note, you may also use other
nodes, 1 through 7, and external services. Each node contains a yellow air chamber with
a pressure sensor inside it and a DC fan, able to increase air pressure in the chamber,
when on. An airflow limiter located by the other side, opposite to the fan, limits airflow
running out of the chamber.

8.2. Prerequisites
The user needs to know:

▪ physical effect of the airflow and air pressure phenomena,


▪ PWM control principals.

8.3. Sensors
Each node contains the following set of sensors:

▪ DHT sensor measuring temperature and humidity (Blue is DHT11, White is DHT22)
connected to the D4/GPIO2.
▪ Bosch BMP280 air pressure sensor, reporting absolute air pressure measurements in
Pa, located inside of the yellow air chamber (operating of the fan changes pressure
reported by the sensor when the fan is off, it measures absolute air pressure - please
note, the laboratory is located at the 3rd floor + base floor, so it is not a ground-level
pressure). This sensor uses I2C protocol and is connected to the D1 and D2 GPIOs
(D2 is SDA, D1 is SCL). The sensor I2C address is 0x76.

30
8.3. Sensors

8.3.1. Technical overview of the node and air pressure chamber


overview

Figure 5: Air chamber

31
8. VREL #8 through #11: General Purpose IoT Laboratory with air
chamber for pressure monitoring

Figure 6: VREL #8-#11 components (circuit)

8.4. Actuators
There are two mechanical actuators in this laboratory:

▪ Classical servo (180 degrees) controlled via pin D5 with arrow presenting its position.
▪ DC fan, located in the inlet of the air chamber, controlled with pin D8.
LCD Display is 4×20 characters. LCD is controlled via I2C extender: LCM1602. The I2C
extender address is 0x3F for nodes 8 and 9 and 0x27 for nodes 10 and 11. The I2C bus

32
8.5. Software, libraries and externals
is connected to the pins D1/GPIO5 and D2/GPIO4 (D1 is SCL and D2 is SDA).
As you do not have any access to the serial console, use LCD to visually trace the
progress of your program, connection status, etc. By the LCD display, there are two LEDs
that can be used to trace status. One LED is connected to the pin GPIO 16 while the
other one to the GPIO pin 2. The former one (GPIO 2) is connected to the Serial Port TX
as well so expect it flashing when communicating over serial protocol (i.e. flashing new
firmware that is beyond the control of your code).

Please note cameras are running only with some 5-10fps so do not implement quick
flashing light as you may not be able to observe it remotely. Same note applies to the
quick changes of the LCD contents.

Build in LEDs (both) are active with signal LOW so setting HIGH on GPIO 16 or 4 switches
them off while setting LOW switches them on.

Even if 20×4 LCD displays look same in different nodes, nodes 8 and 9 use 0x3F address
while nodes 10 and 11 use 0x27. Using invalid I2C address in your code causes the
display to become inoperable.

8.5. Software, libraries and externals


LCD display requires a dedicated library. Of course, you can control it on the low-level
programming, writing directly to the I2C registers, but we do suggest using a library
first. As there are many universal libraries, and many of them are incompatible with this
display, we strongly recommend using ''LiquidCrystal_I2C by Tony Kambourakis''.

8.5.1. LCD Display


The LCD I2C control library can be imported to the source code via:

#include <LiquidCrystal_I2C.h>

Then configure your LCD controller for nodes 8 and 9:

LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x3F


// for a 20 chars and 4 line display
// Nodes 8 and 9

or for nodes 10 and 11

LiquidCrystal_I2C lcd(0x27F,20,4); // set the LCD address to 0x3F


// for a 20 chars and 4 line display
// Nodes 10 and 11

8.5.2. Servo
The easiest way to control a servo it is using a dedicated library. Still, low-level PWM
programming is possible.

#include <Servo.h>

33
8. VREL #8 through #11: General Purpose IoT Laboratory with air
chamber for pressure monitoring
...

#define servoPin D5

Servo servo;
servo.attach(servoPin);

8.5.3. Fan
Fan operation is controlled via classical PWM. We control fan using analogWrite.
Suggested PWM frequency is about 250 Hz:

#define PWMFanPin D8

...

pinMode(PWMFanPin,OUTPUT);
analogWriteFreq(250);
analogWrite(PWMFanPin,0); //stop FAN

Setting too high PWM frequency causes fan to operate binary (on/off) and limits
controlling range.

Platformio.ini
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; http://docs.platformio.org/page/projectconf.html

[env:d1_mini]
platform = espressif8266
board = d1_mini
framework = arduino
lib_deps = Wire, LCD, 528@1.0.6, 31@1.0.3, 2120

The library numbers and their enforced versions are necessary to compile your code. You
may get library errors if using other versions and referencing libraries by name, not by
ID.

8.6. Communication
You can connect your ESP8266 microcontroller via its integrated WiFi interface to the
separated IoT network. Then you can communicate with other nodes and players,
already connected devices and even provide some information to the cloud. In details,
there is a dedicated MQTT broker waiting for you. You can also set up your soft Access
Point and connect another node directly to yours.

34
8.7. Limits
The communication among the devices can be done using MQTT messages, exchanging
data among other nodes (M2M) and you can even push them to the Internet via MQTT
broker.

Using your Node, you can access it and publish/subscribe to the messages once you
connect your ESP to the existing wireless network (this network does not provide access
to the global internet and is separated but please note there are other developers and
IoT nodes connected to this access point:

▪ SSID: internal.IOT
▪ Passkey: IoTlab32768
▪ Setup your microcontroller for DHCP, to automatically obtain an IP address, your ESP
will obtain the address from the 192.168.90.X pool.
▪ MQTT server is available under the fixed address: 192.168.90.5, and the credentials
to publish/subscribe are:
▪ User: vrel
▪ Password: vrel2018
The same MQTT server/broker is visible under public IP: 157.158.56.54 port 1883 (non-
secure) and 8883 (secure) to let you exchange data with the world and control your
devices remotely.

8.7. Limits
At the same time, only one user can be programming the controller, although analysing
the signal by others (unlimited number) the user has sense. ode does not require
physical human interaction and is supposed to work continuously, without service breaks.

8.8. Support
piotr.czekalski@polsl.pl

35
9. Hands-on lab scenarios for SUT VREL nodes

9. Hands-on lab scenarios for SUT VREL nodes


A table below presents a relation between SUT's IOT VREL nodes and their capabilities to
handle presented hands-on-labs scenarios.

Please be aware that scenarios are strictly related to the hardware, thus using
an inappropriate scenario in the context of the VREL node that presents
incompatible hardware may lead to the inability to obtain desired results or
even to the hardware damage.

▪ B class scenarios present introductory level to the hardware handling,


▪ U class scenarios present more advanced levels, including networking, and their
implementation usually requires familiarity with B class ones.
Table 2: SUT's scenarios coverage matrix for VREL nodes

SUT's VREL laboratory node number


Group 1 Group 2
#1 #2 #3 #4 #5 #6 #7 #8 #9 #10 #11
B1 x x x x x x x x x
B2 x x x x x x x x x
B3 x
B4 x
B5
B6 x x x x
B7 x x x x
B8 x x x x

U1 x x x x x x x x x
U2 x x x x x x x x x
U3 x x x x x x x x x
U4 x x x x x x x x x
U5
U6
U7 x x
U8 x x

9.0.1. B1: Basic operations on the 4x20 LCD screen


Whatever you do, you expect to have some output of the system. Sometimes there is a

36
9. Hands-on lab scenarios for SUT VREL nodes
blinking LED, sometimes information about connected/disconnected network and some
other time simply trace algorithm progress. In laboratories where you have physically
connected MCU to your programming device (i.e. computer), you usually would choose
Serial port to report about what is going on. However here all you have is access via
the video stream. Perhaps those are reasons you will use this LCD display in your every
lab work.

Note, the video stream from the camera is limited in bandwidth and presents some
5-10fps maximum (usually around 1 fps) so you shouldn't change display content nor
LED state faster than once every 2 seconds, to let you notice any change!

Target group
This hands-on lab guide is intended for the Beginners but other target groups may
benefit from it, treating it as a tool for advanced projects.

Prerequisites
There are no other prerequisites than LCD I2C library. Mind, LCD is controlled via the I2C
bus. LCD Display is 4×20 characters. LCD is controlled via I2C extender: LCM1602. The
I2C extender address is 0x3F or 0x27 (depends on the laboratory node, please refer to
the documentation!) and the I2C bus is connected to the pins D1 and D2 (D1 is SCL and
D2 is SDA).

There are two types of I2C extenders differing their I2C address:

▪ Nodes 1 through 5, 8 and 9 use 0x3F


▪ Nodes 10 and 11 use 0x27

Scenario
Initialize LCD screen, clear it then write some fancy text on it, i.e. “Hello IOT!” in the
first line then your first name in the second line and the name of the city you're in, in
the third. In the fourth line, print right-aligned number of loop iterations (delay it for 1
second between updates - yes, 1, to observe video stream lag and delays). Note, delays
are provided in ms, not in s.

Result
You should see the texts and ticking counter in the video stream.

Start
There are no special steps to be performed.

Steps

Step 1
Include LCD driver library:

37
9. Hands-on lab scenarios for SUT VREL nodes
#include <LiquidCrystal_I2C.h>

Step 2
Instantiate software controler component for the LCD display:

LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x3F


// for a 20 chars and 4 line display

Step 3
Declare some variables: counter i, its length n and buffer for the into to string
conversion:

int i = 0;
char buffer [50];
int n;

We will use them in further part of the code.

Step 3
Initialize display - we suggest to do it in setup() function:

...
lcd.init(D2,D1); // initialize the lcd I2C
lcd.backlight(); // switch on the backlight
...

Step 4
Clear the contents, set cursor and draw static text - still in setup() function:

...
lcd.home();
lcd.print("Hello IOT!");
lcd.setCursor(0, 1);
lcd.print("James Bond here");
lcd.setCursor(0,2);
lcd.print("London");
...

Step 5
Implement loop() to draw number of loop executions:

...
i++;
n=sprintf(buffer,"%d",i);
lcd.setCursor(20-n,3);
lcd.print(i);
delay(1000);

38
9. Hands-on lab scenarios for SUT VREL nodes
...

sprintf uses number of wildcards that are rendered with data. Refer to the c/c++
documentation on sprintf. Here %d means: having integer number render it to string
and as we do not specify number of digits, it is up to the engine to convert it
properly.\\delay(time) is measured in milliseconds.

Result validation
Observe text, its position and counter ticking in lower, right corner.

9.0.2. B2: Presenting temperature and humidity on the LCD


In this scenario, you will present temperature and humidity as read by the attached
DHT22 sensor, on the LCD screen.

Target group
Beginners

Prerequisites
You need to know, how to print and position text on the LCD display. Use LCD I2C library
to control it:

#include <LiquidCrystal_I2C.h>

The temperature and humidity sensor is all-in-one, DHT22 sensor (white) or DHT11
(blue), connected to the pin D4. Observe your camera to check which sensor is equipped
with your lab and consult node documentation.
To read data you may use a dedicated library (libraries):

#include <Adafruit_Sensor.h>
#include <DHT.h>

Scenario
Once you initialise sensor and LCD display, read sensor data (temperature and humidity,
mind they're float values, not integers) and then display them in the loop. Give each loop
execution some 5-10s delay.

Do not try to read temperature and humidity too frequent. Once every 5s is quite
enough both for information and safe enough to not let your readings race with the
communication protocol. If you read too frequent, your sensor may not be able to deliver
data on time and you will obtain a 'nan' (not a number) instead of temperature and
humidity.

The first line of the LCD should display: “Temperature is:“


The second line should provide temperature within the ”NN.N C” form, in Celcius.
The third line should display: “Humidity is:“

39
9. Hands-on lab scenarios for SUT VREL nodes
Finally, the fourth should present relative humidity: ”NN.N%Rh“

You will use sprintf function to format string and convert from float to string.

Result
You should be able to see temperature and humidity readings on the LCD display using
the video stream.

Start
There are no special steps to be performed.

Steps

Step 1
Include LCD and DHT sensor driver libraries:

#include <LiquidCrystal_I2C.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>

Step 2
Instantiate software controler components for the LCD display and DHT sensor:

LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x3F for nodes 1 through 5, 8 a
//LiquidCrystal_I2C lcd(0x27,20,4); // for nodes 10 and 11 only!
// for a 20 chars and 4 line display
DHT dht(DHTpin,DHT22,50);

Step 3
Declare a buffer for sprintf function:

char buffer [10];

Step 4
Initialize LCD and DHT sensor:

...
lcd.init(D2,D1); // initialize the lcd
lcd.backlight();
lcd.home();
...
dht.begin();
delay(1000); // give it a second to let the sensor initialize
...

40
9. Hands-on lab scenarios for SUT VREL nodes

Step 5
Read in the loop:

...
float hum = dht.readHumidity();
float temp = dht.readTemperature();
...

To convert float into the string with formatting use sprintf function:

...
sprintf(buffer,"%2.1f C",temp);
...
sprintf(buffer,"%2.1f%%Rh",hum);
...
delay(5000);
...

sprintf uses number of wildcards that are rendered with data. Refer to the c/c++
documentation on sprintf. Here

%2.1f

means: having float number render it to string using two digits before decimal point and
one after. Temperature in our lab is always above 10C.

%%

is an escape character to print a

(percent) symbol.\\delay(time) is measured in milliseconds.

Result validation
Observe temperature and humidity readings on the LCD. Temperature ranges between
20-30C while humidity between 35-60%Rh.

9.0.3. B3: Handling LED brightness using PWM via I2C controller
This is the simple example of setting brightness of LED using PWM controller.

Target group
This hands-on lab guide is intended for the Beginners.

Prerequisites
The user needs to know: Basic knowledge of ESP8266 NodeMCU v.2. ESP8266 Arduino

41
9. Hands-on lab scenarios for SUT VREL nodes
programming, Basic knowledge of I2C Interface. Basic knowledge of I2C programming
using Arduino I2C library.

Scenario
All important information including the address of devices is enclosed in the description of
the laboratory. In that scenario, the user should write a program in the Arduino platform
which turns on and off LEDs for the specified time 15 seconds. The LEDs brightness can
be controlled by setting variable “level” from 0 to 4095.

Result
As a result user can control in cameras program execution.

Start
In the beginning, both cameras must show that all LEDs are off.

Steps

Step 1
First load an example project, include appropriate libraries and declare variable
ledDriver:

#include <Wire.h>
#include <PCA9685.h>

Step 2
Instantiate PWM controler component:

#define PCA9685_ADDRESS 0x40


PCA9685 ledDriver;

or

#define PCA9685_ADDRESS 0x40


PCA9685 ledDriver(PCA9685_ADDRESS);

Step 3
Initialize properly hardware, we suggest to do it in setup() function:

First initialize I2C controller and join i2c bus to correct pins of NodeMCU:

...
Wire.begin(D1, D2); /* join i2c bus with SDA=D5 and SCL=D4 of NodeMCU */
...

and then enable PWM controller ( pin /EN of PCA9685 is connected to pin D0 of

42
9. Hands-on lab scenarios for SUT VREL nodes
NodeMCU):

...
pinMode( D0, OUTPUT ); // define pin D0 as output
digitalWrite( D0, LOW); // enable PWM
...

Step 4
Turn the desired led to any PWM level from 0 to 4095:

The diodes are numbered from 0 to 3

PWM level 0 means that LED is off and level value 4095 means that diode is full-on.

...
ledDriver.setLEDDimmed( number , level);
...

Function setLEDDimmed cannot be used in a loop to give you a pleasant


"turning-up" of the LED. This is because each time you set a level for a LED
it will calculate random timing intervals for the PWM function in the chip
This is done in order to distribute current consumptions of the full-time period.

Step 5
Write a simple programme which:

▪ Turn LED0 placed on the bright side to warm-white fully on for 15 seconds
▪ Turn LED0 off
▪ Turn LED1 placed on the bright side to cold-white fully on for 15 seconds
▪ Turn lED1 off
▪ Turn LED2 placed on the dark side to warm-white fully on for 15 seconds
▪ Turn LED2 off
▪ Turn LED3 placed on the dark side to cold-white fully on for 15 seconds
▪ Turn lED3 off

Step 6
Repeat step 5 ten times.

Result validation
The only way for validation is to check display by the camera. Both cameras must show
that LEDs are changing brightness in given periods of time.

43
9. Hands-on lab scenarios for SUT VREL nodes

9.0.4. B4: E-paper display operations


In the example of B3, the only way to see the results was to preview the image in the
camera. Sometimes You need to have some other output of the system. So now, in our
example, we use e-paper display attached to the system.

Target group
This hands-on lab guide is intended for the Beginners, but other target groups may
benefit from it, treating it as a tool for advanced projects.

Prerequisites
There are no other prerequisites than knowledge of e-paper library. Mind, the display is
controlled by a specialised interface connected to selected GPIO ports of the system.

Scenario
Initialise e-paper screen, clear it then write some fancy text on it, i.e. “Hello IOT!” in the
first line.

Result
As a result, the user can check the text displayed on the screen in the camera.

Start
There are no special steps to be performed.

Steps

Step 1
Include LCD driver library:

#include <SPI.h>
#include <epd2in13.h>
#include <epdpaint.h>
#include "imagedata.h"

Step 2
Choose uncolored verison display:

#define COLORED 0
#define UNCOLORED 1

Step 3
Declare buffer for image and instantiate software controller component for the e-ink
display:

44
9. Hands-on lab scenarios for SUT VREL nodes
unsigned char image[1024];
Paint paint(image, 0, 0);
Epd epd;

Step4
Initialize display - we suggest to do it in setup() function:


if (epd.Init(lut_full_update) != 0) {
Serial.print("e-Paper init failed");
return;
}

Step 5
Clear the contents, set cursor and draw static text - still in setup() function:

...
epd.ClearFrameMemory(0xFF); // bit set = white, bit reset = black

paint.SetRotate(ROTATE_0);
paint.SetWidth(128); // width should be the multiple of 8
paint.SetHeight(24);
...

Step 6
Place text “Hello IOT!” in frame buffer:


/* For simplicity, the arguments are explicit numerical coordinates */
paint.Clear(UNCOLORED);
paint.DrawStringAt(30, 4, "Hello IOT!", &Font12, UNCOLORED);
epd.SetFrameMemory(paint.GetImage(), 0, 10, paint.GetWidth(), paint.GetHeight());

Step 7
Display buffer”

...
epd.DisplayFrame();
...

Result validation
The only way for validation is to check display by the camera.

9.0.5. B6: Presenting air pressure on the LCD


In this scenario, you will present absolute air pressure reading, on the LCD screen.

45
9. Hands-on lab scenarios for SUT VREL nodes

Target group
Beginners

Prerequisites
You need to know, how to print and position text on the LCD display. Use LCD I2C library
to control it:

#include <LiquidCrystal_I2C.h>

The air pressure sensor is Bosch BMP280 sensor, connected to the I2C bus, shared with
LCD display. To read data you may use a dedicated library (libraries):

#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>

Scenario
Once you initialise sensor and LCD display, read sensor data (air pressure) and then
display them in the loop. Give each loop execution some 5-10s delay.

Do not try to read air pressure too frequent. Once every 5s is quite enough both for
information and safe enough to not let your readings race with the communication
protocol.

The first line of the LCD should display: ”Air pressure is:“
The second line should provide temperature within the ”NNNN.NN hPa“ form, in hPa.

Note - your readings are in Pa (not hPa) so you're supposed to divide them by 100 before
presenting on the screen!

You will use sprintf function to format string and convert from float to string.

Result
You should be able to see air pressure readings on the LCD display using the video
stream. Some fluctuations are natural.

If the fan connected to the air chamber is on, air pressure measured may be higher than
the ambient air pressure observed and higher disturbances will be observed.

Start
There are no special steps to be performed.

Steps

Step 1
Include LCD and sensor driver libraries:

46
9. Hands-on lab scenarios for SUT VREL nodes
#include <LiquidCrystal_I2C.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>

Step 2
Instantiate software controler component for the LCD display:

LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x3F for nodes 1 through 5, 8
//LiquidCrystal_I2C lcd(0x27,20,4); // for nodes 10 and 11 only!

Adafruit_BMP280 bmp;

Step 3
Declare a buffer for sprintf function and floating point value (single precision is enough)
for storing last air pressure reading:

char buffer [11];


float pres;

Step 4
Initialize LCD and BMP sensors:

...
lcd.init(D2,D1); // initialize the lcd
lcd.backlight();
lcd.home();
...
if(!bmp.begin(0x76))
{
lcd.print("Bosch Sensor Error!");
delay(1000);
};
lcd.home();
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */
Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */
Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */
Adafruit_BMP280::FILTER_X16, /* Filtering. */
Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
...

The BMP sensor address is 0x76 and, if not initialised, display error on the LCD screen.

Step 5
Read in the loop:

...
pres = bmp.readPressure()/100;
...

47
9. Hands-on lab scenarios for SUT VREL nodes
bmp.readPressure() function returns air pressure in Pa. You must convert it hPa,
dividing by 100.

To convert float into the string with formatting use sprintf function:

...
sprintf(buffer,"%4.2f hPa",pres);
...
delay(5000);
...

sprintf uses number of wildcards that are rendered with data. Refer to the c/c++
documentation on sprintf. Here

%4.2f

means: having float number render it to string using four digits before decimal point and
two after it. Air pressure readings should be somewhere between 890 and 1060 hPa.
delay(time) is measured in milliseconds.

Result validation
Observe air pressure readings on the LCD. Note - small oscillations are natural - you
can implement moving average (i.e. of 10 subsequent reads, FIFO model) to “flatten”
readings.

9.0.6. B7: Controlling servo


In this scenario, you will control a servo to rotate it to the predefined positions.
Servo is under the red arrow you can see in the video stream, to let you easily observe
its position.
Servo is connected to the GPIO D5.

Target group
Beginners

Prerequisites
You need to understand how typical servomotor looks like and how it works.
The servo is controlled using predefined, precise PWM timing. Most servos share exactly
the same model (0-180 degree servos), regardless of their size and power voltage.
Classical, analogue servo frequency is 50Hz = 20ms period and duty cycle of the high
signal is 1ms for 0deg and 2ms for 180deg. So changing the PWM duty cycle from 1ms to
2ms (5% to 10%) rotates servo. There is no need, however, to implement manually (still
you can do) but you will use a predefined library instead of manually setting-up PWM.
This brings features like range mapping to control servo logical way (i.e. providing angle,
not duty cycle).
The library is Servo.h.

According to the algorithm of your choice to implement your code, you may hard code

48
9. Hands-on lab scenarios for SUT VREL nodes
rotations one by one or i.e. declare a table with rotation targets and then iterate over it,
so familiarity with array operations in C is essential in this case.

Scenario
In this scenario, you will rotate the servo to the 0 degrees, then 45, 90, 135 and 180
degrees counter wise, then 180, 90, 0, clockwise. Note - Arrow pointing left means servo
is set to 0, pointing right is 180 degrees, and when 90 degrees, arrow points down. We
use LCD to get feedback about requested servo angle and to compare it with the result,
but please note, it is just for information only and is not necessary to implement servo
rotation.

Please DO NOT use loop() to implement infinite servo rotation as it will wear out quickly
and can even burn. Servo is NOT INTENDED to rotate as a motor. Instead, implement
your code to run once or twice in the setup() function. You may reset the node to restart
your code without the need to recompile.

Result
You should see the red arrow rotating as predefined in the scenario.

Start
There are no special steps to be performed.

Steps

Step 1
Include servo driver library:

#include <Servo.h>

Step 2
Define a servo management class:

...
Servo servo;
...

If you intend to implement your solution with rotation targets array, here is a hint on
array declaration:

...
int angles[] = {0,45,90,135,180,90,0};
...

Step 3
Instantiate software controller component for the LCD display:

49
9. Hands-on lab scenarios for SUT VREL nodes
...
LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x3F for nodes 1 through 5, 8
//LiquidCrystal_I2C lcd(0x27,20,4); // for nodes 10 and 11 only!
...

Step 4
In the setup() function initialize LCD and attach servo, then implement your code:

...
lcd.init(D2,D1); // initialize the lcd
lcd.backlight();
lcd.home();
lcd.print("Starting");
...
servo.attach(servoPin);
servo.write(0); // rotate to 0 degrees.
...

Setting servo to desired angle is as simple as calling servo.write(angle);. Default


mapping is 0…180 degrees for micro servos we use here.

If you implement your solution using rotation targets array, here is a hint on how to
implement the for loop to iterate over an array:

...
for(int i=0; i<sizeof(angles); i++)
{
...

The sizeof operator above brings you automated evaluation of the array size during
compilation, thus if you add or remove an item(s) from the array in the declaration
section, loop will automatically change iteration scope, according to the new array size.

Give it at least 2s gap between setting subsequent rotation target for the servo.
Otherwise, you may be unable to reliably observe results via video stream.

Step 5
Keep loop() dummy, empty method not to overheat the servo or to wear out it's gears:

...
void loop()
{
}

Result validation
Observe the arrow rotating to the desired angle.

50
9. Hands-on lab scenarios for SUT VREL nodes

9.0.7. B8: Controlling fan using PWM


In this scenario, you will control a fan using PWM.
The fan pushes air into the air chamber so you may expect air pressure readings provided
via integrated BMP280 pressure sensor to increase a bit. Changes should reflect fan
rotation speed (non-linear way, as noted below).
Servo is connected to the GPIO D8.

Relation between rotation speed and PWM duty cycle is non-linear, thus i.e. switching
duty cycle from 200 to 400 does not bring you twice the rotation speed of the fan, as
well as won't generate twice as much airflow nor pressure inside air chamber.

Target group
Beginners

Prerequisites
Students should get familiar with BMP pressure readings and presenting their value on
the LCD display.

he fan is controlled raw PWM signal generated as “analogue” output. There is no need to
include any library to operate the fan.

Scenario
In this scenario, you will start rotating fan (0 means fan is stopped) and observe air
pressure change on the LCD display. Keep periodical changes of the fan rotation (i.e.
every 10s) and experiment with different speeds. The valid range is between 0 and 1023.

Result
You should see the fan rotating in the camera. Note, it will be hard to observe rotation
speed via camera, so you can observe result indirectly via observing pressure changes
on the LCD display.

Start
There are no special steps to be performed.

Steps

Step 1
Include LCD driver library as presented in scenarios B1 and B2. You need to include a
generic Arduino library to control PWM frequency. No other libraries are necessary but
for convenience and programming purity, you may define the pin that controls the fan:

#include <Arduino.h>
...
#define PWMFanPin D8

51
9. Hands-on lab scenarios for SUT VREL nodes

Step 2
In the setup() section of the code, define GPIO D8 as output and define PWM frequency.
It is also a good idea to stop the fan at the beginning of your code. Also, give some
time for the BMP sensor (once initialised) to let it relax in current pressure and stabilise
readings. At least 10s delay is suggested.

...
pinMode(PWMFanPin,OUTPUT);
analogWriteFreq(250);
...
analogWrite(PWMFanPin,0); //stop FAN
...
delay(10000);

Step 3
Change the fan rotation speed using analogWrite(pin, value) and keep delays
between consecutive changes to let the BMP280 sensor go along with new air pressure
in the air chamber:

...
analogWrite(PWMFanPin,500);
delay(5000);
...
//here read air pressure
delay(5000);
...
// next rotation speed

Step 4

Once you're done with your lab, please execute following code to stop the fan. Thank
you!

Once finished your experiments, please execute the following code, to stop fan:

#include <Arduino.h>
#define PWMFanPin D8

void setup()
{
pinMode(PWMFanPin,OUTPUT);
analogWriteFreq(250);
analogWrite(PWMFanPin,0); //stop FAN
}
void loop()
{
//This section was intentionally left blank
}

52
9. Hands-on lab scenarios for SUT VREL nodes

Result validation
Observe air pressure changes on the LCD. Try to evaluate minimum and maximum
values (related to the fan stopped and operating on max rpm.

Remeber to execute fan stopping code once all your experimentation is finished.

9.0.8. U1: Connecting to the network in STA mode


Most IoT (if not all of them) require your device to communicate via a network. Here we
connect to the existing WiFi network, 2.4GHz. All laboratory nodes can access common
access point and require credentials to connect to it (see laboratory description section
for the credentials and latest updates). ESP 8266 has a built-in WiFi interface, so you're
using it to connect to the network. Every ESP has an individual MAC address. An IP
address is assigned to the ESP via DHCP server, automatically, so you will present it on
the LCD screen

Target group
Undergraduate / Bachelor / Engineering Students

Prerequisites
You will need to know the credentials of the network - see node description for details.
Mind, those may be different than in the code chunks presented below. You need to know
how to handle 4×20 characters LCD screen. In case of doubt re-work on scenarios B1
and B2.

Scenario
In this scenario, you will create a WiFi client to connect to the AP then present connection
status (eventually the failure, with attempts) on the LCD screen. Then you will show on
the LCD given IP address and MAC address of your ESP8266.
While attempting to connect, the first line of the LCD should present information
“Connecting Wifi” and the second line should present the attempt number. When
connected, the first line of the LCD should present information “WiFi connected”,
following one your given IP address including “IP: XXX.XXX.XXX.XXX”. As MAC address
is pretty long (17 chars including separators, here we will use the fourth line to present
it, while “MAC: ” header should be present in the third line of the LCD. Note, there is a
ticker, showing that the device is alive, implemented the same way as in scenario B1, for
beginners.

We suggest putting connection and information code into the separate function that you
will call from the setup() one, just for cleaner code.

Result
The LCD screen should present the current situation and all the necessary information.
Once connected, observe the IP address assigned by the DHCP server and device's MAC.

53
9. Hands-on lab scenarios for SUT VREL nodes

Start
Define some identifiers to separate and update AP's SSID and passphrase easily. To
format lines for the LCD, we suggest using a char buffer of 20 characters (one full
line) and some 2-3 integers for iterators. Remember to declare the LCD control class in
your code. You do not need to instantiate WiFi communication class - as you have only
one interface here, it is singleton class you can refer directly using WiFi. Note - in this
scenario, you connect only once. If your connection breaks, you will have no information
about it here. To handle such situation, there are multiple solutions: you can check in
the loop() if the connection is OK and in case it is down, you can call your re-connecting
function, or you can use one of the asynchronous handlers, triggered automatically via
the WiFi manager. To use the latter approach, refer to the ESP8266 WiFi implementation
for Arduino documentation.

Steps
Following steps do not present full code - you need to supply missing parts on your own!

Step 1
Include all necessary libraries. The minimum set here is:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <LiquidCrystal_I2C.h>
...

Step 2
Give it some definitions as identifiers for cleaner code:

#define wifi_ssid "internal.IOT"


#define wifi_password "IoTlab32768"

Always refer to the node documentation to ensure you know current SSID and
passphrase. They may differ to those in the code above!

Step 3
Print some information about starting connecting to WiFi, configure network interface as
a WiFi client and give it a try to connect to the AP:

delay(10);
WiFi.mode(WIFI_STA);
WiFi.begin(wifi_ssid, wifi_password);
n=0;

delay(10) is necessary to give it a breath before you ask it to connect to the web - wifi
interface itself boots slower than rest of the ESP8266 because of radio physics.

n=0 is an iterator here - you will use it to show a number of attempts - you should usually
succeed in one or couple. If attempts start ticking up, look for the code mistakes and

54
9. Hands-on lab scenarios for SUT VREL nodes
check your SSID and passphrase.

Please, explicitly use interface mode setting: WiFi.mode(WIFI_STA);. See FAQ section
for details.

Step 4
Check if connected, if not, give it next attempt:

while (WiFi.status() != WL_CONNECTED) {


lcd.setCursor(0,1);
n++;
sprintf(buffer,"Attempt %d",n);
lcd.print(buffer);
delay(1000);

Step 5
When connected, show details to the camera:

lcd.clear();
lcd.home();
lcd.print("WiFi connected!");
//Print IP
String s = WiFi.localIP().toString();
sprintf(buffer,"IP: %s",s.c_str());
lcd.setCursor(0,1);
lcd.print(buffer);
//Print MAC
lcd.setCursor(0,2);
lcd.print("MAC:");
s = WiFi.macAddress();
lcd.setCursor(0,3);
lcd.print(s.c_str());

IP address returned by the WiFi.localIP() function of the WiFi manager returns IPAddress
structure so you need to convert it to String. Supprisingly, MAC address is an already
pre-formatted String object.

Step 6
In the loop() function present ticker in the 3rd line, right side of the LCD. The 4th line
is all occupied by the MAC address, if you followed 1:1 the guide. In case your UI looks
different, handle coordinates appropriatelly.

Result validation
Run your code and observe LCD presenting information on connection progress, IP and
MAC addresses.

FAQ
Does IP address change over time?: Yes. First of all, IP is given automatically by
the DHCP server. There is no strict rule saying, your IP is always going to be the same.

55
9. Hands-on lab scenarios for SUT VREL nodes
Second, IP address reservation is done for some period of time and then DHCP server
may assign you other IP so it may change over runtime, not necessarily between restarts
only.
Does MAC address change: No. It is a factory given one and should be unique
worldwide. Anyway, you can programmatically change it - this technique is commonly
used by hackers to mimic other devices.
Do I need to use WiFi.mode(WIFI_STA);?: Yes, please do. Theoretically, if consecutive
compilations use STA (client to AP) mode of the ESP8266 wifi interface, your code may
work without it. However, you never know if the previous user used STA or AP (or both).
Your code may fail then if not explicitly stated!

9.0.9. U2: Exposing access point (AP)


In this scenario, you set up your own access point. Please note, in this case, a number
of devices you can connect to the AP is really limited. VRELs 1, 2, 3 and 4 are physically
located together, while VREL 6 and VREL 7 are in two remote locations, thus you may
not be able to reach hosted AP.

Target group
Undergraduate / Bachelor / Engineering Students

Prerequisites
You need to know how to handle 4×20 characters LCD screen. In case of doubt re-work
on scenarios B1 and B2.
Warning: In no case should you give your AP the internal.IOT SSID name! You will
mess up the laboratory environment and block other users from accessing network
infrastructure. We consider this behaviour as hacking and it will be penalized under legal
jurisdiction!

In no case give your AP the internal.IOT SSID! You will mess up the laboratory
environment and block other users from accessing network infrastructure. We consider
this behaviour as hacking and it will be penalized under legal jurisdiction!

To fully experience this scenario, you need to book another node (one of 1,2,3 or 4), to
let the other node act as your networking client. You can use scenario U1 for this purpose
but mind to update network SSID and passphrase in your code, to let it connect to your
server.

Students physically present in the SUT IoT laboratory room 320 may use their own
devices like laptops or mobile phones to connect to your AP.

Scenario
In this scenario, you will set up an access point and present on the LCD screen number
of clients connected. The devices that connect to your AP obtain automatically an IP
address from your AP so actually it hosts a DHCP server out of the box! The IP range
is from the 192.168.4.x subnet, but you can configure it for another one if you only
wish via wifi.ap.shcp.config() function. if you use the default configuration, your AP
is 192.168.4.1.

56
9. Hands-on lab scenarios for SUT VREL nodes

Result
On the LCD you should present that AP is active, its name (SSID) and passphrase (select
one no longer than 20 characters, to fit single line). In the last line of the LCD, there
should be present a number of connected devices.

Start
Define some identifiers to separate and update AP's SSID and passphrase easily. To
format lines for the LCD, we suggest using a char buffer of 20 characters (one full
line) and some 2-3 integers for iterators. Remember to declare the LCD control class
in your code. You do not need to instantiate WiFi communication class - as you have
only one interface here, it is singleton class you can refer directly using WiFi. you
will use loop() to display a number of connected devices to your network. There do
exist asynchronous way (event-based) to do it, but here we use a simplified, blocking
approach. If you want to test the other one, refer to the ESP8266 WiFi implementation
for Arduino documentation.

Steps
Following steps do not present full code - you need to supply missing parts on your own!

Step 1
Include all necessary libraries. The minimum set here is:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <LiquidCrystal_I2C.h>
...

Step 2
Give it some definitions as identifiers for cleaner code, remember to change ssid name
to yours!

#define wifi_ssid_ap put_your_unique_id_here //give it some unique name-change here


#define wifi_password_ap "1234567890"

Never use internal.IOT as your SSID name wifi_ssid_ap - you will overlap existing
network infrastructure and we consider it as hacking that is subject to jurisdiction! Your
account will be imediatelly banned!

Step 3
Print some information about starting software WiFi AP, configure network interface as a
WiFi AP and give it a try to start:

...
delay(10);
...
WiFi.mode(WIFI_AP);

57
9. Hands-on lab scenarios for SUT VREL nodes
delay(100);
boolean result = WiFi.softAP(wifi_ssid_ap, wifi_password_ap);

if(result == true)
{
... //Announce success, print status, SSID and passphrase to the LCD
}
else
{
... //Announce failure. Print it on LCD
}
...

Step 4
Implement in the loop() an information about number of connected clients, i.e. like this:

...
void loop()
{
lcd.setCursor(0,3);
sprintf(buffer, "Stations: %d", WiFi.softAPgetStationNum());
lcd.print(buffer);
delay(3000);
}
...

Result validation
Check your AP is active on LCD eventually observe failure. If works OK, compile U1
scenario on another node(s), mind to update SSID and passphrase in the U1 source code
then observe if connected clients counter increases.

FAQ
Do I need to use WiFi.mode(WIFI_AP);?: Yes, please do. Theoretically, if consecutive
compilations use AP (software server) mode of the ESP8266 wifi interface, your code
may work without it. However, you never know if the previous user used STA or AP (or
both). Your code may fail then if not explicitly stated!

9.0.10. U3: Sending MQTT messages


In this scenario, you will send MQTT message exposing temperature and humidity to
the MQTT server available on the internal.IOT network. By sending sensor data, you
will learn, how to expose the device's state and how to inform others that your device
stopped working uncontrolled way.

Target group
Undergraduate / Bachelor / Engineering Students

58
9. Hands-on lab scenarios for SUT VREL nodes

Prerequisites
We assume you already know how to:

▪ handle DHT sensor to read temperature and humidity,


▪ handle LCD screen to present information,
▪ connect to the existing WiFi network: internal.IOT,
▪ additionally we will ask you to install and use an MQTT client of your choice. We
suggest using MQTT Spy, but any MQTT client that will let you subscribe to the MQTT
messages is OK. You connect it to the public IP of the MQTT broker (see below).
MQTT broker present in the internal.IOT network is also visible under public address.
So whenever you publish an MQTT message using VREL node that is connected to the
internal.IOT network, you may subscribe to it using other devices connected to the
internal.IOT, i.e. other VREL node or if you're physically present at SUT in the IOT
laboratory room 320, then you can connect your mobile and laptop to the internal.IOT
network and use “internal” IP address. However, if you're in a remote location, you
can access the same broker under public IP as stated in the node description. Same
messages published on the internal network are also visible on the public side. Mind,
to access MQTT broker you need to use IP, user and password (applies to both public
and private IPs of the MQTT Broker). Refer to the node documentation for the latest
information.

Note - information present in source code samples can be not up-to-date - remember
to refer to the VREL node documentation for the latest information on IPs, users and
passwords for both internal.IOT network access and for the MQTT Broker.

Scenario
In this scenario, you will connect to the infrastructure as a client (STA) and use the MQTT
server to publish information about temperature, humidity. Also, you will expose device
state using MQTT “last will” mechanism: on startup, you will configure MQTT broker to
send an MQTT message with payload automatically off when connection breaks (i.e. your
device goes down) and your starting code will send the same message with payload on
to notify subscribers that you're (back) on-line. Parallelly, you will present temperature
and humidity data on the LCD screen.

In this scenario, you do not subscribe your device to any messages, you only publish
them.

Result
You should be able to see connection status, temperature and humidity on the screen
while your MQTT subscriber should be able to present you readings delivered via MQTT.
It should be equal to the data presented in the LCD screen you observe locally, via video
stream.

Start
Define some identifiers to separate and update AP's SSID and passphrase easily. To
format lines for the LCD, we suggest using a char buffer of 20 characters (one full

59
9. Hands-on lab scenarios for SUT VREL nodes
line) and some 2-3 integers for iterators. Remember to declare the LCD control class in
your code. You do not need to instantiate WiFi communication class - as you have only
one interface here, it is singleton class you can refer directly using WiFi. Note - in this
scenario, you connect only once. If your connection breaks, you will have no information
about it here. To handle such situation, there are multiple solutions: you can check in
the loop() if the connection is OK and in case it is down, you can call your re-connecting
function, or you can use one of the asynchronous handlers, triggered automatically via
the WiFi manager. To use the latter approach, refer to the ESP8266 WiFi implementation
for Arduino documentation.

Steps
Following steps do not present full code - you need to supply missing parts on your own!
We do not present here how to connect to the WiFi AP. If you're in doubt, rever to the U1
scenario. We also do not present in details on how to organise and print DHT22 sensor
data on the LCD screen. Please refer to the scenario B2 if you need a recall.

Step 1
Include all necessary libraries. We use PubSubClient library to contact MQTT broker. The
minimum set here is:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
...

Declare some identifiers to let you easier handle necessary modifications and keep code
clear:

#define wifi_ssid "internal.IOT"


#define wifi_password "IoTlab32768"
#define mqtt_server "192.168.90.5"
#define mqtt_user "vrel"
#define mqtt_password "vrel2018"
...

Step 2
Declare some identifiers, here MQTT messages' topics, MQTT client ID and payloads for
the status notification (on / off).

Use unique names for topics and for the MQTT client, do some random, use your MAC
as part of it. It is important because MQTT broker identifies client using its name thus
if your device shares name with some other that is already working, you may not get
information about connection lost because another device with the same name is still
active on the network. Unique topics are also essential: if you accidentally overlap, you
may get an invalid reading with someone that is using the same topic but different
payload.

60
9. Hands-on lab scenarios for SUT VREL nodes
#define MQTTClientName ...<your client name>...
#define tempTopic ...<some topic for temperature>... // give it some unique topic
// i.e. including your name
#define humTopic ...<come topic for humidity>... // as above

//MQTT last will


#define lastWillTopic ...<some topic for exposing state and last will>...
// give it some unique topic
// i.e. including your name
#define lastWillMessage "off"
#define mqttWelcomeMessage "on"

Step 3
By the regular variables related to you WiFi Esp network client, DHT sensor, buffer for
string processing and so on, here you need to configure an object additionally to handle
communication with MQTT broker. As you may use many brokers in your app, you need
to instantiate it yourself. The constructor accepts WiFiClient as a parameter, so here
you need explicitly declare one:

// WiFi & MQTT


WiFiClient espClient;
PubSubClient client(espClient);

Configure your network client, remember to set ESP.mode(WIFI_SFA). Once you're done
with starting, initialise MQTT broker client. Once you're done with connecting to the WiFi,
configure your MQTT PubSubClient:

client.setServer(mqtt_server, 1883);

You can call it i.e. in the setup() function, after a successful connection to the WiFi AP
but before you execute step 4.

Step 4
If your WiFi client is working, your MQTT client is configured it is time to connect to the
MQTT broker. It is a good idea to have this procedure separated to call as needed if your
connection with MQTT broker goes down for any reason. Here we encapsulate it in the
reconnect() function:

void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
if (client.connect(MQTTClientName, mqtt_user, mqtt_password,
lastWillTopic, 0, true, lastWillMessage))
{
client.publish(lastWillTopic, mqttWelcomeMessage, true);
} else
{
// Wait 5 seconds before retrying
delay(5000);
}
}

61
9. Hands-on lab scenarios for SUT VREL nodes
lcd.setCursor(0,1);
lcd.print("MQTT Connected!");
}

Function retries every 5 seconds, in case it is unable to connect to the MQTT broker.
You can call it in the very beginning of the loop() function, checking in advance if your
client is connected or not, i.e. this way:

...
if (!client.connected()) {
reconnect(); //reconnect MQTT
}
...

Step 5
Prepare a code that publishes MQTT messages. You will call it periodically within loop()
section. Do not try to send data too frequently. Once every 10-20s is pretty enough
as nor humidity nor temperature will change rapidly. On the other hand, sending too
frequently causes network bottlenecks and heavy load on the MQTT broker.

Your publishing routine may look somehow like this:

void mqttPublish()
{
hum = dht.readHumidity();
temp = dht.readTemperature();
if(client.connected())
{
if (!(isnan(temp)||isnan(hum)))
{
client.publish(tempTopic, String(temp).c_str(), false); // Do not retain
// messages
client.publish(humTopic, String(hum).c_str(), false);
}
}
}

If you choose to implement this routine as a ticker/timer, you will experience ESP crash
every execution of this loop (you will observe it as your device may freeze or restart
every execution). The reason is if you use timer/ticker, those routines are not giving
extra time for the WiFi handling routine (while main loop() indeed does). reading from
the DHT sensor takes so much time, blocking here device to handle WiFi communication,
so hardware watchdog will trigger an exception and break your code execution!
To handle this issue you must read DHT sensor in the main loop() and insert them into
the variables then limit MQTT publish procedure just to only prepare and send data over
the network (this is legit). Anyway, we do not consider this kind of scenario here as we
call publishing code directly from within the loop() function so it is safe.

Finally your loop() may look like this:

void loop()

62
9. Hands-on lab scenarios for SUT VREL nodes
{
if (!client.connected()) {
reconnect();
}
client.loop();
sprintf(buffer,"Temp is %2.1f C",temp);
lcd.setCursor(0,2);
lcd.print(buffer);
sprintf(buffer,"Humidity is %2.1f%% Rh",hum);
lcd.setCursor(0,3);
lcd.print(buffer);
mqttPublish();
delay(5000);
}

the client.loop() is to handle incoming MQTT messages. There are none here but it is
good practice to have it in your code.

Result validation
Observe connection progress on the LCD via video stream. Once WiFi and MQTT are
connected you should be able to see temperature and humidity readings on the LCD and
additionally those should be sent over the MQTT messages to the MQTT broker. Connect
your MQTT client and subscribe to your messages (you may do it using a wildcard
character) i.e. with means of the MQTT spy application. Remember to connect MQTT spy
to public IP address unless you're a student physically present in our laboratory room and
you have direct access to the internal.IOT network. Observe data on the LCD screen
the same as over MQTT messages (note, there may be a delay because of the network
bottlenecks and MQTT broker load).

FAQ
What topic should I choose?: Up to you. Anyway, we suggest using non-trivial ones
just not to overlap with other users.
Why MQTT broker uses two IP addresses?: As programming ESP826 devices may
issue many hacking scenarios, we decided to use separated WiFi network. On the other
hand, it should be a way to exchange some data with the external world. Here comes
the solution: our MQTT broker is connected one leg to the separated internal.IOT
network while another interface connects to the public Internet. This way any message
you publish from within the private network is visible (you can subscribe to it) on both
sides: public and private one. This way you can send information to the i.e. IBM Watson
cloud or Microsoft Azure to store it and visualise. Opposide, you can drive the node
device connected to the internal.IOT solely from the Internet, i.e. implementing some
interface using dashboard. All you need is to publish to our MQTT broker on its public
interface and write a code that subscribes to those messages on the private side. Simple
and safe.

9.0.11. U4: Receiving and handling MQTT messages


In this scenario, you will subscribe to the MQTT broker for MQTT messages and handle
them. Most of the code yo will implement here is similar to the scenario U3, including
LCD handling and connecting to the MQTT broker.

63
9. Hands-on lab scenarios for SUT VREL nodes

Target group
Undergraduate / Bachelor / Engineering Students

Prerequisites
We assume you already know how to:

▪ handle DHT sensor to read temperature and humidity,


▪ handle LCD screen to present information,
▪ connect to the existing WiFi network: internal.IOT,
▪ additionally we will ask you to install and use an MQTT client of your choice. We
suggest using MQTT Spy, but any MQTT client that will let you subscribe to the MQTT
messages is OK. You connect it to the public IP of the MQTT broker (see below).
MQTT broker present in the internal.IOT network is also visible under public address.
So whenever you subscribe to the MQTT message using VREL node that is connected
to the internal.IOT network, you may publish to it using other devices connected to
the internal.IOT, i.e. other VREL node or if you're physically present at SUT in the IOT
laboratory room 320, then you can connect your mobile and laptop to the internal.IOT
network and use “internal” IP address. However, if you're in a remote location, you can
access the same broker under public IP as stated in the node description. When you
publish an MQTT message using public IP, it will be delivered to the subscribers in the
private internal.IOT network as well. Mind, to access MQTT broker you need to use IP,
user and password (applies to both public and private IPs of the MQTT Broker). Refer to
the node documentation for the latest information.

Note - information present in source code samples can be not up-to-date - remember
to refer to the VREL node documentation for the latest information on IPs, users and
passwords for both internal.IOT network access and for the MQTT Broker.

Scenario
In this scenario, you will connect to the infrastructure as a client (STA) and use the MQTT
server to subscribe to the messages sent by some publisher. You will present received
MQTT message on the LCD screen. We will implement a “remote display”, where you
handle remote requests to put contents on specific (one of four) LCD lines. MQTT payload
should be a string then. We assume that the last character of the topic determines line
number (between 0 and 3) so you need to construct MQTT topics as i.e. like /mydevice/
someuniqueID/LCDcontent/0 for the first line, /mydevice/someuniqueID/LCDcontent/
1 for the second one, and so on. Mind to update “someuniquieID” with your ID not to
overlap with other students as you share single MQTT broker!

Result
You should be able to visualise payload of the subscribed messages on the LCD screen.
Note, you handle only a limited number of messages that you subscribe to. When
subscribing, do not go “too wide” using wildcards cause you won't be able to present
all of them on the LCD display. Remember, you share MQTT broker with other users so
tailor your subscriptions to those that apply to your device.

64
9. Hands-on lab scenarios for SUT VREL nodes
Subscribing to # is a really bad idea in production, live system. You will get a flood of
messages!

Start
Define some identifiers to separate and update AP's SSID and passphrase easily. To
format lines for the LCD, we suggest using a char buffer of 20 characters (one full
line) and some 2-3 integers for iterators. Remember to declare the LCD control class in
your code. You do not need to instantiate WiFi communication class - as you have only
one interface here, it is singleton class you can refer directly using WiFi. Note - in this
scenario, you connect only once. If your connection breaks, you will have no information
about it here. To handle such situation, there are multiple solutions: you can check in
the loop() if the connection is OK and in case it is down, you can call your re-connecting
function, or you can use one of the asynchronous handlers, triggered automatically via
the WiFi manager. To use the latter approach, refer to the ESP8266 WiFi implementation
for Arduino documentation.

To handle incoming MQTT messages, you will need to implement a callback function that
will be triggered, whenever a new message comes. You will receive only those messages
that you've subscribed to. Note you need to check and decode message topics yourself.

Steps
Following steps do not present full code - you need to supply missing parts on your own!
We do not present here how to connect to the WiFi AP. If you're in doubt, rever to the U1
scenario. Please refer to scenario B1, if you need a recall on how to handle LCD screen.

Step 1
Include all necessary libraries. We use PubSubClient library to contact MQTT broker. The
minimum set here is:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
...

Declare some identifiers to let you easier handle necessary modifications and keep code
clear:

#define wifi_ssid "internal.IOT"


#define wifi_password "IoTlab32768"
#define mqtt_server "192.168.90.5"
#define mqtt_user "vrel"
#define mqtt_password "vrel2018"
...

Step 2
Declare some identifiers, here MQTT messages' topic (one with wildcard, for four LCD
lines) and MQTT client ID.

65
9. Hands-on lab scenarios for SUT VREL nodes
Use unique names for topics and for the MQTT client, do some random, use your MAC
as part of it. It is important because MQTT broker identifies the client using its name.
Also note, the set of MQTT topics that you use to send information to your LCD should
be unique, otherwise some other users may “inject” information to your display.

Use topics that their last character is a line number (0 till 3) to easily suit
lcd.setCursor(x,y) requirements, i.e. as below:

// MQTT messages
#define MQTTClientName "thisissomeuniqueclientname"
#define lcdTopicWithWildcard "/sut/mydevice/LCD/+"

Valid MQTT messages are:

▪ /sut/mydevice/LCD/0 - delivers payload for line 1 of the LCD screen,


▪ /sut/mydevice/LCD/1 - delivers payload for line 2 of the LCD screen, and so on.

Step 3
We will declare an MQTT handler callback function that is called whenever new MQTT
message comes. Mind - only those messages that you've subscribed to are triggering this
function, so you do not need to check the topic other than decoding its part to obtain,
which LCD line number comes (this is the last character of the MQTT topic):

void mqttCallback(char* topic, byte* payload, unsigned int length) {


char nLine = topic[strlen(topic)-1];
n = atoi(&nLine);
if (n>=0 && n<=3)
{
lcd.setCursor(0,n);
lcd.print(" "); //clear one line
for (int i = 0; i < length; i++)
{
lcd.setCursor(i, n);
lcd.write((char)payload[i]);
}
}
}

Note - header of the function is interface declared by the mqtt PubSubClient library.
topic is MQTT message topic, payload is a content and length is payload's length. As
payload is binary, length is essential to know, how to handle payload contents.

Step 4
By the regular variables related to your WiFi ESP network client and so on, here you
need to configure an object additionally to handle communication with MQTT broker. As
you may use many brokers in your code, you need to instantiate it yourself, there is no
singleton class as in case of the network interface. The constructor accepts WiFiClient
as a parameter, so here you need explicitly declare one, to gain access to it:

// WiFi & MQTT


WiFiClient espClient;

66
9. Hands-on lab scenarios for SUT VREL nodes
PubSubClient client(espClient);

Configure your network client, remember to set ESP.mode(WIFI_SFA). Once you're done
with starting, initialise MQTT broker client. Once you're done with connecting to the WiFi,
configure your MQTT PubSubClient and give it a handler function to let it be called,
whenever a new message comes (here mqttCallback:

client.setServer(mqtt_server, 1883);
client.setCallback(mqttCallback);

You can call it i.e. in the setup() function, after a successful connection to the WiFi AP
but before you execute step 4.

Step 5
If your WiFi client is working, your MQTT client is configured it is time to connect to the
MQTT broker. It is a good idea to have this procedure separated to call as needed if your
connection with MQTT broker goes down for any reason. Here we encapsulate it in the
reconnect() function where we also subscribe to the number of topics delivering LCD
content in the payload:

void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
if (client.connect(MQTTClientName, mqtt_user, mqtt_password)) {
client.subscribe(lcdTopicWithWildcard);
} else {
// Wait 5 seconds before retrying
delay(5000);
}
}
lcd.setCursor(0,1);
lcd.print("MQTT Connected!");
}

Step 6
Finally your loop() may look like this:

void loop()
{
if (!client.connected()) {
reconnect();
}
client.loop();
}

The client.loop() is to handle incoming MQTT messages.

Result validation
Compile and run your code then wait till it connects to the network and MQTT broker.

67
9. Hands-on lab scenarios for SUT VREL nodes
Once it is connected, use your favourite MQTT client to connect to the MQTT broker and
issue a number of MQTT messages that their topics are:

▪ /sut/mydevice/LCD/0
▪ /sut/mydevice/LCD/1
▪ /sut/mydevice/LCD/2
▪ /sut/mydevice/LCD/3
and the payload is a text you want to display on your LCD. Note, your display ix 20
characters each line only so keep your payload within those limits.

FAQ
This section is to be extended as new questions appear.
When using the printed version of this manual please refer to the latest online version of
this document to obtain the valid and up-to-date list of the FAQ. Provide some FAQs in
the following form:
Question?: Answer.

9.0.12. U7: Controlling fan speed and servo angle via MQTT
In this scenario, you will learn how to remotely control fan speed using PWM and how to
control servo angle using MQTT messages. This scenario is a practical extension to the
scenario U4 where you learned, how to receive and handle MQTT messages.

Target group
Undergraduate / Bachelor / Engineering Students

Prerequisites
We assume you already know how to:

▪ handle LCD screen to present information,


▪ connect to the existing WiFi network: internal.IOT,
▪ receive and handle MQTT messages using PubSubClient library
▪ additionally we will ask you to install and use an MQTT client of your choice. We
suggest using MQTT Spy, but any MQTT client that will let you subscribe to the MQTT
messages is OK. You connect it to the public IP of the MQTT broker (see below).
MQTT broker present in the internal.IOT network is also visible under public address.
So whenever you subscribe to the MQTT message using VREL node that is connected
to the internal.IOT network, you may publish to it using other devices connected to
the internal.IOT, i.e. other VREL node or if you're physically present at SUT in the IOT
laboratory room 320, then you can connect your mobile and laptop to the internal.IOT
network and use “internal” IP address. However, if you're in a remote location, you can
access the same broker under public IP as stated in the node description. When you
publish an MQTT message using public IP, it will be delivered to the subscribers in the
private internal.IOT network as well. Mind, to access MQTT broker you need to use IP,
user and password (applies to both public and private IPs of the MQTT Broker). Refer to

68
9. Hands-on lab scenarios for SUT VREL nodes
the node documentation for the latest information.

Note - information present in source code samples can be not up-to-date - remember
to refer to the VREL node documentation for the latest information on IPs, users and
passwords for both internal.IOT network access and for the MQTT Broker.

Warning - physical servo range is ONLY between 0 and 90 degrees! Going over 90
degrees may cause a break to the equipment and you may be charged for repair!

Scenario
In this scenario, you will handle incoming MQTT messages (one for controlling fan, other
for servo, opening and closing the flap. Parallelly you will present incoming messages on
the LCD screen.

Result
You should be able to remotely control fan rotation speed and flap angle (0..90 degrees),
observe connection status and incoming MQTT messages for your device on the LCD
screen.

Start
Define some identifiers to separate and update AP's SSID and passphrase easily. To
format lines for the LCD, we suggest using a char buffer of 20 characters (one full
line) and some 2-3 integers for iterators and storing current PWM for servo and fan.
Remember to declare the LCD control class in your code. You do not need to instantiate
WiFi communication class - as you have only one interface here, it is singleton class you
can refer directly using WiFi. Reading analogue input brings you an integer value.

Servo is controlled using GPIO pin D5 (GPIO14) while the fan is controlled using GPIO
pin D8 (GPIO15). As servo we use is a small one, it is powered and controlled directly
through the ESP8266 while in case of the FAN, it is controlled indirectly, using a
transistor.

Legal range for the servo is 0…90 degree! Exceeding over 90 degrees may break the
construction!

Valid range for controlling fan is 0 (stopped) till 4095 (full speed). Please note,
characteristics are non-linear, so setting output 2047 does not mean that rotation speed
nor airflow is half of the maximum.

Steps
Following steps do not present full code - you need to supply missing parts on your own!
We do not present here how to connect to the WiFi AP. If you're in doubt, rever to the U1
scenario. Please refer to scenario B1, if you need a recall on how to handle LCD screen.
In case you're in doubt how to handle MQTT messages communication (here publishing/
sending), please refer to the U4 scenario.

Step 1
Include all necessary libraries. We use PubSubClient library to contact MQTT broker. The

69
9. Hands-on lab scenarios for SUT VREL nodes
minimum set here is:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
...

Here we use Servo.h library to easily handle servomotor control for regular, modeller's
servos, mostly used in RC toys. Declare some identifiers to let you easier handle
necessary modifications and keep code clear:

#define wifi_ssid "internal.IOT"


#define wifi_password "IoTlab32768"
#define mqtt_server "192.168.90.5"
#define mqtt_user "vrel"
#define mqtt_password "vrel2018"
...

Step 2
Declare some identifiers, here MQTT messages' topics, MQTT client ID and payloads for
the status notification (on / off).

Use unique names for topics and for the MQTT client, do some random, use your MAC
as part of it. It is important because MQTT broker identifies client using its name thus
if your device shares name with some other that is already working, you may not get
information about connection lost because another device with the same name is still
active on the network. Unique topics are also essential: if you accidentally overlap, you
may get an invalid reading with someone that is using the same topic but different
payload.

// MQTT messages
#define MQTTClientName "myVREL2clientname"
#define servoTopic ...<some topic for servo>... // give it some unique topic
// i.e. including your name
#define fanTopic ...<some topic for fan>... // give it some unique topic
// i.e. including your name

//MQTT last will


#define lastWillTopic ..<some topic for exposing state and last will>...
// give it some unique topic
// i.e. including your name
#define lastWillMessage "off"
#define mqttWelcomeMessage "on"

Finally, declare GPIOs pin numbers connecting to the servo and fan:

//Hardware
#define PWMFanPin D8
#define servoPin D5

70
9. Hands-on lab scenarios for SUT VREL nodes

Step 3
Declare WiFiCilent, PubSubClient, initialise, instantiate and connect to the network. If
in doubt, refer to the scenario U4 on how to prepare networking code for your solution.
Additionally, instantiate a servo controlling the flap:

...
Servo servo;
...

Later, in your initialisation section (possibly in setup() function) bind your servo with
physical one using appropriate GPIO and set it to 0 degrees (close the flap, down). Also,
initialise fan's GPIO for output, to control PWM and set it to 0 (stop fan):

...
void setup()
{
...
// Servo and PWM fan
servo.attach(servoPin);
servo.write(0); //set servo down to 0 degrees
pinMode(PWMFanPin,OUTPUT);
analogWrite(PWMFanPin,0); //stop FAN
...

Note - here you see how to control servo and fan. In the case of the servo, we use
a Servo library, so function servo.write(deg) sets servo to the desired number of
degrees. While the fan is controlled using RAW values on 12bit resolution (in fact it is
PWM as well) from 0 to 4095, using analogWrite(pin, value). Word “analog” may
mislead you here: output on the digital pin is not a continuous analogue voltage value,
but its approximation using PWM anyway, it works perfectly for the fan and many other
devices.

Step 4
Implement MQTT callback - a function that is being called, whenever there comes an
MQTT message. You should have subscribed only to the selected MQTT messages (one
for the fan, other for the servo) so only those messages may trigger your callback
function. Anyway, it is a matter to distinguish, which one message comes. Your function
may look like this:

void mqttCallback(char* topic, byte* payload, unsigned int length) {


lcd.setCursor(0,2);
lcd.print("Servo:");
lcd.setCursor(0,3);
lcd.print("Fan:");
String sTopic(topic);
if(sTopic.startsWith(servoTopic))
{
//Handle servo message
for(int i=0; i< length; i++)
{
buffer[i] = (char)payload[i];

71
9. Hands-on lab scenarios for SUT VREL nodes
}
buffer[length]='\0';
srv = atoi(buffer);
servo.write(srv);
lcd.setCursor(9,2);
sprintf(buffer,"%2d deg",srv);
lcd.print(buffer);
}
if(sTopic.startsWith(fanTopic))
{
//Handle fan message
for(int i=0; i< length; i++)
{
buffer[i] = (char)payload[i];
}
buffer[length]='\0';
fan = atoi(buffer);
analogWrite(PWMFanPin,fan);
lcd.setCursor(7,3);
sprintf(buffer,"%4d PWM",fan);
lcd.print(buffer);
} // give it some unique topic i.e. including your name
}

As you see, we do not only receive the value but also drive LCD display to present it. Still
you may inject some validation code, particularly for the servo, i.e. check if incoming
MQTT payload for the servo message is more than 90 degres then truncate it not to
break the device physically.

Step 5
Remember to bind your MQTT callback function to the MQTT PubSubClient. Perhaps you
will do it in the setup() or in the reconnect() functions:

...
client.setCallback(mqttCallback);
...

Result validation
Observe flap moving out and in. As the fan is mounted perpendicular to the video
camera, you cannot observe rotation directly (video stream is too slow to present it on
the other hand). You can observe value on the analogue gauge to the right but also
indirectly through the flap mounted in the corresponding air receiving node (RX). Those
are VREL1 and VREL3 for sending nodes VREL2 and VREL4 respectively. You will see the
air stream pushing the flap thus you can monitor the airflow.

FAQ
What is the valid range for controlling the fan?: The fan is connected to the digital
pin and controlled via PWM (12-bit resolution). Thus valid range is from 0 (min) to
4095 (max). Note rotation speed and airflow do not have linear characteristic vs PWM
controlling value, So issuing 2047 on the GPIO pin controlling the fan won't make your
fan to rotate 50% nor the airflow will be 50% of the maximum one. You need to

72
9. Hands-on lab scenarios for SUT VREL nodes
experiment individually!
What is the valid range for controlling the servo?: The valid range is from 0 to 90
degrees. Exceeding 90 degrees can break the construction! Never go beyond 90 degrees!

9.0.13. U8: Visualising and sending flap state


In this scenario, you will use to monitor the voltage of the unbalanced resistance bridge
connected to the analogue input. Voltage level reflects the flap inclination via the light
level, reflected from the flap (compared to the reference one).

Target group
Undergraduate / Bachelor / Engineering Students

Prerequisites
We assume you already know how to:

▪ handle LCD screen to present information (refer to the scenarios B1 and B2 when in
doubt),
▪ connect to the existing WiFi network: internal.IOT,
▪ publish to the MQTT broker available in your network,
▪ additionally, we will ask you to install and use an MQTT client of your choice. We
suggest using MQTT Spy, but any MQTT client that will let you subscribe to the MQTT
messages is OK. You connect it to the public IP of the MQTT broker (see below).
MQTT broker present in the internal.IOT network is also visible under public address.
So whenever you publish an MQTT message using VREL node that is connected to the
internal.IOT network, you may subscribe to it using other devices connected to the
internal.IOT, i.e. other VREL node or if you're physically present at SUT in the IOT
laboratory room 320, then you can connect your mobile and laptop to the internal.IOT
network and use “internal” IP address. However, if you're in a remote location, you
can access the same broker under public IP as stated in the node description. Same
messages published on the internal network are also visible on the public side. Mind,
to access MQTT broker you need to use IP, user and password (applies to both public
and private IPs of the MQTT Broker). Refer to the node documentation for the latest
information.

Note - information present in source code samples can be not up-to-date - remember
to refer to the VREL node documentation for the latest information on IPs, users and
passwords for both internal.IOT network access and for the MQTT Broker.

Note - Analog input in ESP8266 measures voltage on the pin A0, ranging from 0 to 3.3V
(in reality somewhere from 0.1-0.2V to 3.2V) using 4096 distinguishable values - the A/
D converter resolution is then 12bit and return values you may expect, range from 0 to
4095 - in fact they're much more narrowed.

Scenario
I this scenario, once you get connected to the WiFi as AP and then to the MQTT server to
publish data, you will periodically read A0 (analogue) input of the ESP8266 and publish

73
9. Hands-on lab scenarios for SUT VREL nodes
its RAW value to the MQTT server. You will also visualise the RAW value of the A0 input
reading on the LCD screen.

Result
You should be able to read data stream via MQTT message, presenting flap position.
Parallel, data should be displayed on the LCD, along with connection status.

Note - flap position refers to the airflow: you may need to control it using VREL2 and
VREL4 for VREL1 and VREL3, respectively. Airflow in nodes 2 and 4 can be controlled
twofold: using PWM to control fan rotation speed and using the flap to open/close air
duct.

Start
Define some identifiers to separate and update AP's SSID and passphrase easily. To
format lines for the LCD, we suggest using a char buffer of 20 characters (one full line)
and some 2-3 integers for iterators. Remember to declare the LCD control class in your
code. You do not need to instantiate WiFi communication class - as you have only one
interface here, it is singleton class you can refer directly using WiFi. Reading analogue
input brings you an integer value.

Steps
Following steps do not present full code - you need to supply missing parts on your own!
We do not present here how to connect to the WiFi AP. If you're in doubt, rever to the U1
scenario. Please refer to scenario B1, if you need a recall on how to handle LCD screen.
In case you're in doubt how to handle MQTT messages communication (here publishing/
sending), please refer to the U3 scenario.

Step 1
Include all necessary libraries. We use PubSubClient library to contact MQTT broker. The
minimum set here is:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>
...

There is no need to use a special library to read analogue input representing relative flap
position here.
Declare some identifiers to let you easier handle necessary modifications and keep code
clear:

#define wifi_ssid "internal.IOT"


#define wifi_password "IoTlab32768"
#define mqtt_server "192.168.90.5"
#define mqtt_user "vrel"
#define mqtt_password "vrel2018"
...

74
9. Hands-on lab scenarios for SUT VREL nodes

Step 2
Declare some identifiers, here MQTT messages' topics, MQTT client ID and payloads for
the status notification (on / off).

Use unique names for topics and for the MQTT client, do some random, use your MAC
as part of it. It is important because MQTT broker identifies client using its name thus
if your device shares name with some other that is already working, you may not get
information about connection lost because another device with the same name is still
active on the network. Unique topics are also essential: if you accidentally overlap, you
may get an invalid reading with someone that is using the same topic but different
payload.

// MQTT messages
#define MQTTClientName ...<your client name>...
#define analogOutTopic ...<some topic for flap>... // give it some unique topic
// i.e. including your name

//MQTT last will


#define lastWillTopic ...<some topic for exposing state and last will>...
// give it some unique topic
// i.e. including your name
#define lastWillMessage "off"
#define mqttWelcomeMessage "on"

Step 3
Declare WiFiCilent, PubSubClient, initialise, instantiate and connect to the network. If in
doubt, refer to the scenario U3 on how to prepare networking code for your solution.

Step 4
Prepare MQTT publishing code, here we publish periodically one value (flap position,
relative), i.e. like this:

void mqttPublish()
{
flap = analogRead(A0);

if(client.connected())
{
client.publish(analogOutTopic, String(flap).c_str(), false); // Do not retain
// messages
}
}

Reading analogue input is pretty easy: all you need to do is to use analogRead(A0).
Note, ESP8266 has only one analogue input A0.

Step 5
Your loop() function should include call to the aforementioned mqttPublish and printing
on the LCD screen once every 5 seconds.

75
9. Hands-on lab scenarios for SUT VREL nodes
void loop()
{
if (!client.connected()) {
reconnect();
}
client.loop();
mqttPublish();
sprintf(buffer,"Flap is %d ",flap);
lcd.setCursor(0,2);
lcd.print(buffer);
delay(1000);
}

Mind to keep a delay(…), not to saturate MQTT broker and communication channel.
Minimum reasonable delay between issuing consecutive MQTT messages is about 200ms.

The flap variable is a global one, set in the mqttPublish using analogRead(A0). This
way you have it set for sprintf formating function.

Result validation
Observe connection progress on the LCD via video stream. Once WiFi and MQTT are
connected, you should be able to see analogue input readings on the LCD, and
additionally, those should be sent over the MQTT messages to the MQTT broker. Connect
your MQTT client and subscribe to your messages (you may do it using a wildcard
character), i.e. with means of the MQTT spy application. Remember to connect MQTT spy
to public IP address unless you're a student physically present in our laboratory room
and you have direct access to the internal.IOT network. Observe data on the LCD screen
the same as over MQTT messages (note, there may be a delay because of the network
bottlenecks and MQTT broker load).

FAQ
I want to implement PID controller of the position of the flap, using TX air
pushing node (VRELS 2 and 4). 200ms latency between consecutive reads
seems too large, to implement efficient loopback. What to do?: In this case, you
should drop MQTT communication and communicate directly between nodes, i.e. your RX
node (VREL1 and 3) can send a UDP message over the network. Our WiFi internal.IOT
is a pretty efficient one, and should handle it with ease.

9.0.14. U9: A CoAP client


In this scenario, you will interact with a CoAP server implemented as a NodeRED node.
You will perform simple CoAP request to the NodeRED server, waiting for you. In return,
you will obtain a secret code.

Target group
Undergraduate / Bachelor / Engineering Students

76
9. Hands-on lab scenarios for SUT VREL nodes

Prerequisites
We assume you already know how to:

▪ handle LCD screen to present information (refer to the scenarios B1 and B2 when in
doubt),
▪ connect to the existing WiFi network: internal.IOT,
▪ additionally, we will ask you to install and use a CoAP client of your choice. We
suggest using chrome extension Cooper4Cr, chrome plugin, but any CoAP client will
work here. You connect your solution to the private IP of the NodeRED server but the
same information is available on the public IP as well, so you can check it from your
home.
NodeRED CoAP server is present in the internal.IOT network and it is also visible under
public address. Refer to the node documentation for the latest information.

Note - information present in source code samples can be not up-to-date - remember
to refer to the VREL node documentation for the latest information on IPs, users and
passwords for both internal.IOT network access and for the NodeRED access.

CoAP server data is:

▪ IP address (implemented with NodeRED) is: 192.168.90.5 as seen from the


internal.IOT network, or 157.158.56.54 when accessing from the public space;
▪ The only implemented URI is ”“ (simply root resource) - for other URIs you will get
4.04 (Not Found) error;
▪ CoAP port is 5683 (default);

Scenario
I this scenario, once you get connected to the WiFi as AP and then you will make a UDP
request using CoAP protocol to the NodeRED server acting as CoAP server. Please note,
we do not implement here discovery services for CoAP, for simplicity and because of
constrained resources, so you won't be able to use clients' CoAP discover feature. You
will obtain a secret code from the server (it varies over time). As a bonus, you may
try to discover the secret code generation algorithm :-). You're expected to present the
results of the CoAP query on the LCD screen. To implement a CoAP client feature you
will use a dedicated library ESP-CoAP simple library, available via Platformio library
management system.

Result
You should be able to obtain a UDP message in CoAP, with the payload containing an
ASCII text with secret code, and present it on the LCD screen.

Start
Define some identifiers to separate and update AP's SSID and passphrase easily. To
simplify conversion, use IPAddress class to create IP address of the CoAP server. To
format lines for the LCD, we suggest using a char buffer of 20 characters (one full line)
and some 2-3 integers for iterators. Remember to declare the LCD control class in your

77
9. Hands-on lab scenarios for SUT VREL nodes
code. You do not need to instantiate WiFi communication class - as you have only one
interface here, it is singleton class you can refer directly using WiFi. Reading analogue
input brings you an integer value. Note, you're supposed to instantiate your MCU as AP
even if using UDP communication.

Steps
Following steps do not present full code - you need to supply missing parts on your own!
We do not present here how to connect to the WiFi AP. If you're in doubt, rever to the U1
scenario. Please refer to scenario B1, if you need a recall on how to handle LCD screen.

Step 1
Include all necessary libraries. We use ESP-CoAP simple library to contact CoAP server
as a client. Note, this library also implements a CoAP server features but we do not use
it in our scenario here. The minimum set here is:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include "coap_client.h"
#include <LiquidCrystal_I2C.h>
...

Declare some identifiers and variables/class instances to let you easier handle necessary
modifications and keep code clear:

#define wifi_ssid "internal.IOT"


#define wifi_password "IoTlab32768"

IPAddress ip(192,168,90,5);//take NodeRed Address


int port = 5683;

...

Step 2
Declare coapClient and WiFi client, to implement CoAP client instance, PubSubClient,
initialise, instantiate and connect to the network. If in doubt, refer to the scenario U3 on
how to prepare networking code for your solution:

...

coapClient coap;

...

Step 3
Prepare CoAP client response asynchronous handler.

CoAP uses UDP for communication, so you will be informed asynchronously, when
response to your request appears. That is fully handled by asynchronous response
handler and mechanism is implemented by the library.

78
9. Hands-on lab scenarios for SUT VREL nodes
As messages may come quickly in the queue (many replies) due to the heavy use or UDP
nature, you are required to make a copy of the payload ASAP, best using memcpy, as first
operation in your asynchronous response handler.

void callback_response(coapPacket &packet, IPAddress ip, int port);


...
// coap client response callback
void callback_response(coapPacket &packet, IPAddress ip, int port) {
char p[packet.payloadlen + 1]; //declare local buffer for the payload
memcpy(p, packet.payload, packet.payloadlen); //quickly copy payload contents
p[packet.payloadlen] = NULL;

//response from coap server - check if this is regular one (response to your request), o
if(packet.type==3 && packet.code==0){
//that means you've obtained a ping request so handle it (i.e. show on LCD)
...
}
... //handle payload.
}
...

Step 4
Start your CoAP client in the setup() function:

... // remember to initialise it AFTER you make a WiFi connection, not before
coap.respinse(callback_response); // add response handler
coap.start(); //start coap client

Step 5
Your loop() function should include call to the CoAP client methods. Here we use only
CoAP GET, as this is the only one implemented by the NodeRED server, we provide to
you:

void loop()
{
...
int msgid = coap.get(ip,port,"");
bool state = coap.loop();
...
delay(10000);
}

Mind to keep a delay(…), not to saturate NodeRED server with issuing dozens of UDP
requests. Minimum reasonable delay between issuing consecutive requests is about
500ms.

Result validation
Observe connection progress on the LCD via video stream. Once WiFi is connected, you
should be able to see secret code as a return from CoAP server. Note, you may want to
implement presentation of the communication status, i.e. present msgid and state of the

79
9. Hands-on lab scenarios for SUT VREL nodes
coap.loop().

FAQ
Secret changes over time so do not be surprised that you will obtain different numbers
when returning to this exercise or executing in loop for a time. Note, to distinguish from
random data, there is always some extra, textual message to let you be sure that server
returned a value.

80
10. ITT modular component laboratory

10. ITT modular component laboratory


10.1. ITT Controller module basics

10.1.1. Introduction
This chapter describes the IOT ITT controller module. The controller module is necessary
for any other module to work.

10.1.2. Prerequisites
General knowledge of MQTT protocol: topics, brokers, subscribe, publish. General
knowledge on microcontrollers and Arduino IDE.

10.1.3. Technical details


The ITT IoT controller module is based on the Wemos D1 Mini controller. Its pinout can
be seen in the following schematic.

81
10. ITT modular component laboratory

10.1.4. Specifications
▪ 11 digital input/output pins
▪ Micro USB connector
▪ Compatible with ArduinoIDE
▪ Compatible with nodemc
▪ 4 MB flash-memory

10.1.5. Electrical connection


Modules are using following I/O ports

▪ RGB LED Shield GPIO4


▪ Relay Shield GPIO5
▪ OLED Display Shield GPIO4, GPIO5
▪ Motor Shield GPIO4, GPIO5
▪ Temperature/Humidity DHT Pro Shield GPIO2
▪ Sensor Shield (ITT ver. 1.1) GPIO4, GPIO5, GPIO6, GPIO7, A0

10.1.6. Actuators
As this is the controller module, no actuators or sensors are installed to it.

10.1.7. Software, libraries and externals


To program the controller module ITTIoT library is used. This is a custom library made
specifically for ITT IoT kits. It aims to make the board easier to use with simple but yet
effective methods. A non-exclusive list of methods is presented below:

Method Description
Does the operations necessary for setting up the ITTIoT
iot.setup()
framework and MQTT communications.
iot.printConfig() Prints the module configuration to the serial port.
Does the background work necessary for the communications
to work. For example, checks if the communication with the
iot.handle()
broker is still working and checks if any new messages have
been received. This method has to be called periodically.
A method defined by the user that is called when the
connection with the MQTT broker has been established. It
iot.connected()
is primarily used to subscribe to topics with the method
iot.subscribe().
Subscribes to the topic specified as the operand. For example
iot.subscribe(String
iot.subscribe(“IoT/button”) subscribes to the topic “IoT/
topic)
button”.
iot.received(String User-defined method that is called when the controller

82
10.2. ITT RGB LED module
Method Description
receives a message from one of the subscribed topics. The
topic, String msg) topic from which the message is received is the string “topic”
and the body of the message is the string “msg”.
iot.publishMsgTo(String Publishes the message “msg” to the topic “topic”. Boolean
topic, String msg, bool retain informs the broker if the message should be saved into
retain) the memory of the broker.

10.1.8. Communication
The user can connect to and program this controller using the Distancelab environment.

10.1.9. Limits
At the same time, one user can program the controller. But all users connected to the
Distancelab MQTT broker can subscribe to and publish messages to the topics.

10.2. ITT RGB LED module


This laboratory is located in the office of ITT Group in Tallinn, Estonia.

10.2.1. Introduction
This laboratory consists of an RGB LED module connected to the ITT IoT controller
module. The module contains one RGB LED. This node can be used to create very basic
MQTT systems but can also be used as a signalling part of other more complicated
systems.

83
10. ITT modular component laboratory

10.2.2. Prerequisites
General knowledge of MQTT protocol: topics, brokers, subscribe, publish.

10.2.3. Technical details


This laboratory conisists of a ITT IoT controller module connected to a RGB LED module.

Actuators
This laboratory involves a WS2812B RGB LED. RGB LEDs are basically three LEDs (red,
green, blue) that are built inside one shell. They include a WS2812 driver that makes it
possible to use only one pin to control them.

Specifications
▪ LED size: 5050
▪ Colors: 16777216

Electrical connection
Connected to port GPIO4.

Software, libraries and externals


To control WS2812B RGB LED the following libraries are used:

▪ ITTIoT libary - used to program the controller module.


▪ Adafruit NeoPixel libary - used to control the RGB LED.

Communication
The user can connect to this controller using the Distancelab environment.

Limits
At the same time, one user can program the controller. But all users connected to
the Distancelab MQTT broker can control the RGB LED, assuming they use the topic
described in the controller program.

10.2.4. Hands-on labs

Example code
#include <Arduino.h>
#include <ittiot.h>
#include <Adafruit_NeoPixel.h>

#define PIN D2

// When we setup the NeoPixel library, we tell it how many pixels,


// and which pin to use to send signals.

84
10.2. ITT RGB LED module
// Note that for older NeoPixel strips you might need to change
// the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(1, PIN, NEO_GRB + NEO_KHZ800);

// https://stackoverflow.com/questions/9072320/split-string-into-string-array
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length()-1;

for(int i=0; i<=maxIndex && found<=index; i++)


{
if(data.charAt(i)==separator || i==maxIndex)
{
found++;
strIndex[0] = strIndex[1]+1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}

return found>index ? data.substring(strIndex[0], strIndex[1]) : "";


}

// Change RGB LED color


// mosquitto_pub -u test -P test -t "ITT/IOT/3/rgb" -m "51;255;153"
void iot_received(String topic, String msg)
{
Serial.print("MSG FROM USER callback, topic: ");
Serial.print(topic);
Serial.print(" payload: ");
Serial.println(msg);

String r = getValue(msg,';',0);
String g = getValue(msg,';',1);
String b = getValue(msg,';',2);

Serial.print("R: ");
Serial.println(r);

Serial.print("G: ");
Serial.println(g);

Serial.print("B: ");
Serial.println(b);
// Moderately bright green color.
pixels.setPixelColor(0, r.toInt(), g.toInt(), b.toInt());

pixels.show(); // This sends the updated pixel color to the hardware.


}

void iot_connected()
{
Serial.println("MQTT connected callback");
iot.subscribe("rgb");
iot.log("IoT NeoPixel example!");
}

85
10. ITT modular component laboratory

void setup()
{
Serial.begin(115200);
Serial.println("Booting");

iot.printConfig(); // print json config to serial


iot.setup();

pixels.begin(); // This initializes the NeoPixel library.


}

void loop()
{
iot.handle();
delay(200);
}

10.2.5. Support
info@ittgroup.ee

10.3. ITT Temperature and humidity sensor module


This laboratory is located in the office of ITT Group in Tallinn, Estonia.

10.3.1. Introduction
This laboratory can be used to practice reading values from sensors and send them over
MQTT. It can be used as a simple task of sending the sensor value or part of a bigger
system, where actuators from other modules perform actions based on the sensor values
received.

86
10.3. ITT Temperature and humidity sensor module

10.3.2. Prerequisites
For this laboratory, the student should understand basic MQTT concepts like topics,
broker, subscribing and publishing.

10.3.3. Technical details


This laboratory consists of a DHT22 temperature and humidity sensor module attached
to the ITT IoT controller module.

Sensors
This laboratory uses the DHT22 temperature and humidity sensor. It uses a capacitive
humidity sensor and a thermistor to measure temperature. The sensor only transmits
digital data (no analogue values). The sensor is calibrated and doesn't require extra
components so you can get right to measuring relative humidity and temperature.

Specifications
▪ 1-wire digital interface
▪ Humidity from 0-100% RH
▪ -40 - 80 degrees C temperature range
▪ +-2% RH accuracy
▪ +-0.5 degrees C

Electrical connection
The 1-wire data connection is connected to port GPIO2.

Software, libraries and externals


▪ ITTIoT libary - used to program the controller module.
▪ Adafruit DHT sensor libary - used to read the values from the DHT22 sensor.

Communication
The user can connect and program this controller using the Distancelab environment.

Limits
At the same time, only one user can program the controller. But all users connected
to the Distancelab MQTT broker can read the values if they are being transmitted over
MQTT. That is assuming they use the topic described in the controller program.

10.3.4. Hands-on labs

Example code
#include <Arduino.h>

87
10. ITT modular component laboratory
#include <ittiot.h>

#include <DHT.h>
#define DHTPIN D4 // what pin we're connected to
#define DHTTYPE DHT22 // DHT 22 (AM2302)

DHT dht(DHTPIN, DHTTYPE);

void iot_connected()
{
Serial.println("MQTT connected callback");
iot.log("IoT DHT example!");
}

void setup()
{
Serial.begin(115200);
Serial.println("Booting");
iot.printConfig(); // print json config to serial
iot.setup();
pinMode(16, OUTPUT);
dht.begin();

void loop()
{
iot.handle();

float h = dht.readHumidity();
float t = dht.readTemperature();

char buf[10]; // Put whatever length you need here


String(t).toCharArray(buf,10);

digitalWrite(16,HIGH);
iot.publishMsg("temp",buf);
delay(2000);
digitalWrite(16,LOW);

String(h).toCharArray(buf,10);
iot.publishMsg("hum",buf);
delay(2000);
}

10.3.5. Support
info@ittgroup.ee

10.4. ITT Servo module


This laboratory is located in the office of ITT Group in Tallinn, Estonia.

10.4.1. Introduction
This laboratory can be used to practice controlling the servo motor attached to the

88
10.4. ITT Servo module
controller.

10.4.2. Prerequisites
For this laboratory, the student should understand basic MQTT concepts like topics,
broker, subscribing and publishing.

10.4.3. Technical details


This laboratory consists of a servo with the add-on module attached to the ITT IoT
controller module.

Sensors
This laboratory does not have any sensors.

Specifications
Table 3: Servo specifications

89
10. ITT modular component laboratory
Specification Value
Speed at 6V 0,07 sec/60°
Stall torque at 6V 0,042 N-m
Speed at 4,8V 0,09 sec/60°
Stall torque at 4,8V 0,028 N-m

Electrical connection
The signal lead of the servo is connected to D3 pin of the controller.

Software, libraries and externals


▪ ITTIoT libary - used to program the controller module.
▪ Servo libary - used to control the servo.

Communication
The user can connect and program this controller using the Distancelab environment.

Limits
At the same time, only one user can program the controller. But all users connected to
the Distancelab MQTT broker can subscribe and publish to topics specified.

10.4.4. Hands-on labs

Example code
/*
* IoT Servo example
*
* This example subscribe to the "servo" topic. When a message received, then it
* change servo position
*
* Created 11 Sept 2017 by Heiko Pikner
*/

#include <Arduino.h>
#include <Servo.h>
#include <ittiot.h>

//Pin definition for the Servo (D3)


#define SERVO_PIN D3

Servo myservo; // create servo object to control a servo

// Change the servo position (value between 0 and 180)


// mosquitto_pub -u test -P test -t "RL/esp-{ESP-ID}/servo" -m "51"
// = this calls servo motor to change position

void iot_received(String topic, String msg)

90
10.5. ITT Relay module
{
Serial.print("MSG FROM USER callback, topic: ");
Serial.print(topic);
Serial.print(" payload: ");
Serial.println(msg);

Serial.print("Servo: ");
Serial.println(msg);

myservo.write(msg.toInt());
}

// Function started after the connection to the server is established


void iot_connected()
{
Serial.println("MQTT connected callback");
// Subscribe to the topic "servo"
iot.subscribe("servo");
iot.log("IoT Servo example!");
}

void setup()
{
Serial.begin(115200);
Serial.println("Booting");

// Print json config to serial


iot.printConfig();
// Initialize IoT library
iot.setup();

myservo.attach(SERVO_PIN);
}

void loop()
{
// IoT behind the plan work, it should be periodically called
iot.handle();
delay(200);
}

10.4.5. Support
info@ittgroup.ee

10.5. ITT Relay module


This laboratory is located in the office of ITT Group in Tallinn, Estonia.

10.5.1. Introduction
This laboratory can be used to practice controlling the relay module attached to the
controller.

91
10. ITT modular component laboratory

10.5.2. Prerequisites
For this laboratory, the student should understand basic MQTT concepts like topics,
broker, subscribing and publishing. Also the basics of relays and where they can be used.

10.5.3. Technical details


This laboratory consists of a relay module attached to the ITT IoT controller module.
The relay module is an electrically operated switch of the mains voltage. It means
that it can be turned on or off, letting the current go through or not. Many relays use
an electromagnet to mechanically operate the switch and provide electrical isolation
between two circuits.

Sensors
This laboratory does not have any sensors.

Specifications
▪ 5V 1-Channel Relay interface board
▪ Relay: SRD-05VDC-SL-C (AC 250V 10A, DC 30V 10A NO/NC)

Electrical connection
The signal lead of the servo is connected to GPIO5 pin of the controller.

Software, libraries and externals


▪ ITTIoT libary - used to program the controller module.

Communication
The user can connect and program this controller using the Distancelab environment.

92
10.5. ITT Relay module

Limits
At the same time, only one user can program the controller. But all users connected to
the Distancelab MQTT broker can subscribe and publish to topics specified.

10.5.4. Hands-on labs

Example code
#include <Arduino.h>
#include <ittiot.h>

#define RELAY_PIN 5

// If the message received switch relay


void iot_received(String topic, String msg)
{
Serial.print("MSG FROM USER callback, topic: ");
Serial.print(topic);
Serial.print(" payload: ");
Serial.println(msg);
if(msg == "1")
{
digitalWrite(RELAY_PIN, HIGH);
}

if(msg == "0")
{
digitalWrite(RELAY_PIN, LOW);
}
}

void iot_connected()
{
Serial.println("MQTT connected callback");
iot.subscribe("relay");
iot.log("IoT relay example!");
}

void setup()
{
Serial.begin(115200);
Serial.println("Booting");

iot.printConfig(); // print json config to serial


iot.setup();
pinMode(RELAY_PIN, OUTPUT);
}

void loop()
{
iot.handle();
delay(200);
}

93
10. ITT modular component laboratory

10.5.5. Support
info@ittgroup.ee

10.6. ITT OLED display module


This laboratory is located in the office of ITT Group in Tallinn, Estonia.

10.6.1. Introduction
This laboratory can be used to practice displaying messages on the OLED screen.

10.6.2. Prerequisites
For this laboratory, the student should understand basic MQTT concepts like topics,
broker, subscribing and publishing. Also, knowledge about I2C interface is recommended
but not mandatory.

10.6.3. Technical details


This laboratory consists of an OLED display module attached to the ITT IoT controller
module. Oled module contains an organic light-emitting diode, that is a light-emitting

94
10.6. ITT OLED display module
diode in which the emissive electroluminescent layer is a film of organic compound that
emits light in response to an electric current.

=== Sensors ===Relay This laboratory does not have any sensors.

Specifications
Table 4: OLED screen specifications

Specification Value
Screen size 64×48 pixels (0,66”)
Driver IC SSD1306
Interface I2C
I2C address 0x3C or 0x3D

Electrical connection
Connected to ports GPIO4 (SDA) and GPIO5 (SCL).

Software, libraries and externals


▪ ITTIoT libary - used to program the controller module.
▪ Adafruit GFX library - general libary for Adafruit displays
▪ Adafruit SSD1306 Wemos Mini OLED - libary for controlling the OLED screen.

Communication
The user can connect and program this controller using the Distancelab environment.

Limits
At the same time, only one user can program the controller. But all users connected to
the Distancelab MQTT broker can subscribe and publish to topics specified.

10.6.4. Hands-on labs

Example code
#include <Arduino.h>
#include <ittiot.h>
#include <Ticker.h>
#include <ESP8266WiFi.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 0 // GPIO0

95
10. ITT modular component laboratory
Ticker timeTicker;
Adafruit_SSD1306 display(OLED_RESET);

// ITT splashs screen bitmap. Generator: http://javl.github.io/image2cpp/


static const unsigned char PROGMEM logo16_glcd_bmp[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x1f, 0xff, 0xff, 0xc0, 0x00,
0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x07,
0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0xc0, 0x00, 0x00, 0x00, 0x07, 0x1f, 0xe3, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x07, 0x1f, 0xe3, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x07, 0x10,
0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0xe2, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x10, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0x10, 0xe3, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x07, 0x10, 0xe0,
0x00, 0x00, 0x18, 0x00, 0x00, 0x07, 0x10, 0xe0, 0x00, 0x00, 0x18,
0x00, 0x00, 0x07, 0x10, 0xe0, 0x00, 0x00, 0x18, 0x00, 0x00, 0x07,
0x10, 0xe3, 0xfc, 0xff, 0xf8, 0x00, 0x00, 0x07, 0x10, 0xe3, 0xfc,
0xff, 0xf8, 0x00, 0x00, 0x07, 0x10, 0xe2, 0x1c, 0x80, 0x00, 0x00,
0x00, 0x07, 0x10, 0xe2, 0x1c, 0x80, 0x00, 0x00, 0x00, 0x07, 0x10,
0xe2, 0x1c, 0x80, 0x00, 0x00, 0x00, 0x07, 0x10, 0xe2, 0x1c, 0x80,
0x00, 0x00, 0x00, 0x07, 0x10, 0xe2, 0x1c, 0x80, 0x00, 0x00, 0x00,
0x07, 0x10, 0xe2, 0x1c, 0x80, 0x00, 0x00, 0x00, 0x07, 0x10, 0xe2,
0x1c, 0x80, 0x00, 0x00, 0x00, 0x07, 0xf0, 0xe2, 0x1c, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe2, 0x1c, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0xe2, 0x1c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x1c,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x1c, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0xe2, 0x1c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0xe2, 0x1c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x1c, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x1c, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x1c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

#if (SSD1306_LCDHEIGHT != 48)


#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

bool isBootModeNormal;
bool sendDataFlag;

int i = 0;

// Ticker library callback, which will occur 0.5 second interval.


void sendData()
{
sendDataFlag=true;
}

96
10.6. ITT OLED display module
// Function started after the connection to the server is established.
void iot_connected()
{
Serial.println("MQTT connected callback");
iot.log("IoT OLED screen example!");
isBootModeNormal = true;
}

void setup()
{
Serial.begin(115200);
Serial.println("Booting");

// initialize with the I2C addr 0x3C (for the 64x48)


display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

// Since the buffer is intialized with an Adafruit splashscreen


// internally, we should clear it
display.clearDisplay();

// Load ITT splash screen into buffer


display.drawBitmap(0, 0, logo16_glcd_bmp, 64, 48, 1);
// Show image buffer on the display
display.display();

// Display splashscreen two second


delay(2000);

// print IoT json config to serial


iot.printConfig();

// Initialize IoT library


iot.setup();

// Initialize Ticker interval and callback


timeTicker.attach(0.5, sendData);
}

void loop()
{
// IoT behind the plan work, it should be periodically called
iot.handle();

// Increase counter value


i++;

// Display counter value and boot mode on the OLED screen


display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Counter: ");
display.println(i);

display.setCursor(0,30);

if(isBootModeNormal)
{

97
10. ITT modular component laboratory
display.println("Mode: NORM");
}
else
{
display.println("Mode: BOOT");
}

display.display();

// Send counter value to the server


if(WiFi.isConnected() && isBootModeNormal)
{
if(sendDataFlag)
{
sendDataFlag = false;
String msg = String(i);
iot.publishMsg("count", msg.c_str());
Serial.println(msg);
}
}
}

10.6.5. Support
info@ittgroup.ee

98
11. SmartMe Network Laboratory: Arduino Nodes 1-5

11. SmartMe Network Laboratory: Arduino Nodes


1-5
The SmartMe lab is located at the Engineering building of the University of Messina, in
Messina, Italy.

11.1. Introduction
Its main goal is to provide a simple testbed of a smart city, mainly focusing on smart
environment application scenarios. To this purpose, 6 nodes have been equipped and
made available to students for practising in these contexts. These nodes can be framed
into the MCU (Arduino) + MPU (Raspberry Pi) category: 5 out of 6 combine an Arduino
Uno with a Raspberry Pi 3 b+, the last node is a combo board developed by a spinoff
company (SmartMe.io), Arancino, which combines in the same board an Arduino-like
MCU (based on an ARM Cortex M0+ @48MHz) and a Raspberry Pi 3 compute module. In
this section, we will focus on the 5 pure Arduino nodes and their sensors and actuators.

11.2. Prerequisites
To approach this laboratory, the student should grasp:

▪ basic MQTT concepts like topics, broker, subscribing and publishing;


▪ quantities and metrics related to the physical quantities that can be detected using
DHT and PMS sensors: temperature (°C and F), relative humidity (%), air quality
(PMx concentration).

11.3. Technical details


4 Arduino nodes are Internet-connected by a router through ETH, while the 5th is
reachable only by the IoT gateway (RaspPi). The Lab configuration is shown in the figure
below

99
11. SmartMe Network Laboratory: Arduino Nodes 1-5

11.3.1. Node schematic


All Arduino nodes are configured as reported in the following schematic

100
11.3. Technical details

101
11. SmartMe Network Laboratory: Arduino Nodes 1-5
11.4. Sensors
Each node is equipped with either a DHT11 or DHT22 sensor and a PMS7003 sensor.
The DHT sensors allow measuring temperature and relative humidity, while the PMS7003
sensor allows measuring the air quality through the PMx concentration.

Parameter DHT11 DHT22


Operating Voltage 3 to 5V 3 to 5V
0.3mA (measuring) 60uA 0.3mA (measuring) 60uA
Operating Current
(standby) (standby)
Humidity Range 20-80% / 5% 0-100% / 2-5%
Temperature
0-50°C / ± 2°C -40 to 80°C / ± 0.5°C
Range
Sampling Rate 1 Hz (reading every second) 0.5 Hz (reading every 2 seconds)
Body size 15.5mm x 12mm x 5.5mm 15.1mm x 25mm x 7.7mm
Advantage Ultra low cost More Accurate
16-bit Temperature and 16-bit Temperature and
Resolution
Humidity Humidity
Accuracy ±1°C and ±1% ±0.5°C and ±1%
Sampling period 1 second 2 second
Price $1 to $5 $4 to $10

Some nodes of the lab are equipped with “MIKROE-2818 DHT22 2 click” sensors.
This sensor feature ultra-small size, low-power consumption, data signal transmission
distance up to 20mts, and good measuring accuracy [1]. The sensing part is the CM2322,
which uses a capacitive humidity sensor and a thermistor to measure the surrounding
air. Typical temperature accuracy is ±0.3°C, while relative humidity accuracy is 2%
RH. The humidity and temperature measurement are compensated by some calibration
coefficient, which is saved in the OTP memory of an integrated MCU. The integrated MCU
also provides I2C or 1Wire interface, selectable by the onboard SMD jumper selectors.
The operating voltage can also be selected by the onboard SMD jumper [2]. As shown in
the previous figure, the 1Wire mode was chosen while the operating voltage is 5V. The
sensor is connected to pin 8 of Arduino Uno.

The PMS7003 consists of a digital and universal particle concentration sensor, which can
be used to obtain the number of suspended particles in the air, i.e. the concentration
of particles, and output them in the form of a digital interface. The working principle of
such a sensor consists into produce scattering by using a laser to radiate suspending
particles in the air, then collect scattering light to a certain degree, and finally obtain the
curve of scattering light change with time. In the end, the equivalent particle diameter
and the number of particles with different diameters per unit volume can be calculated
[3]. So, the values of PM1.0, PM2.5, and PM10, will be available for our scopes. In order
to physically interface the 10 bus lines of the sensor with Arduino Uno, the PMS7003
connector shown in the previous figure was employed [4]. By supplying the adapter at
5V, the particle sensor will operate correctly and the data will be available at RX and

102
11.5. Actuators
TX pins. However, the serial voltage level is 3.3V typical, while Arduino Uno needs 5V.
For this reason, a bi-directional level converter was introduced [5]: by supplying the HV
(High Voltage) side at 5V and the LV (Low Voltage) side at 3.3V, the serial levels will be
correct on both sides (Arduino at 5V, PMS7003 at 3.3V). Since is not possible to deploy
the code by using, at the same time, the default RX, TX pins (0,1) of Arduino Uno, the
PMS7003 is connected to pins 9 and 10: by using the <SoftwareSerial.h> library, such
pins can be used as RX and TX of Arduino Uno, respectively.

[1]https://www.mouser.it/new/mikroelektronika/mikroelektronika-
mikroe-2818-dht22-2-click/

[2]http://www.farnell.com/datasheets/2618831.pdf

[3]https://download.kamami.com/
p564008-p564008-PMS7003%20series%20data%20manua_English_V2.5.pdf

[4]https://kamami.com/others/564553-adapter-from-127mm-pitch-to-254mm-for-
pms7003.html

[5]https://kamami.com/voltage-level-converters/234535-logic-level-converter-bi-
directional.html

11.5. Actuators
There are no mechanical actuators in this laboratory. Each node is equipped with a
2×16 LCD screen and with an RGB led, but it is possible to use only the green light
component. The green led of the RGB is connected to the Arduino pin 3. Since such
a pin supports the PWM, the led brilliance can be set. Moreover, the led can be used
for blinking or to indicate when a threshold is reached. The 2×16 LCD is a Displaytech
162B based on the HD44780 standard. Such standard means that the display supports
almost all characters of the ASCII character table. Therefore, it is possible to display the
most important characters. The display controller, which is integrated into the display,
can generate these characters and send them to the matrix. In addition to the already
208 known characters, it is also possible to draw any other characters and signs. The
display controller handles most of the operations, so the code for the microcontroller
is very short [6]. Both 8 bit or 4-bit mode can be used to drive the display. The
<LiquidCrystal.h> library supports the 4 bit communication. As shown in the figure, the
Arduino Uno pins 5, 4, 13, 2 are used for the 4 bit communication (display pins 13, 14,
15, 16), while the Arduino Uno pins 7, 6 are used for the RS (Register Select) and for the
E (Enable) (display pins 8, 6). The not used display data pins (9, 10, 11, 12) are simply
not connected. The other display pins are used for the power supply (1,2) and to control
the display light via the potentiometer (3,4). The display R/W pin (7) is simply connected
to GND since only the write operation is required.

[6] https://www.aeq-web.com/atmega328-4bit-16x2-lcd-display-amtel-studio-
c/?lang=en

Power supply
Each node is equipped with a Breadboard Power Supply Module MB120. The MB102 is
able to provide up to 700 mA, with a voltage of 3.3V and/or 5V. It can be supplied with
an external DC power supply, in the range of 6.5 - 12V. The required voltage can be
selected by properly choice the onboard jumper position. Both 3.3V and 5V are required

103
11. SmartMe Network Laboratory: Arduino Nodes 1-5
in the project.

11.6. Software, libraries and externals


The following libraries are required to run the example proposed below for the hands-on
labs:

▪ Liquid Crystal
▪ DHT sensor Library (mandatory version 1.3.0)
▪ Adafruit Unified Sensor
▪ PMS
▪ Ethernet
▪ MQTT
LCD display requires a dedicated library. Of course, you can control it on the low-level
programming, but we suggest using a library first. As there are many universal libraries,
and many of them are incompatible with this display, we strongly recommend using
"Liquid Crystal Library for Arduino". The LCD control library can be imported to the source
code via:

#include <LiquidCrystal.h>

Then configure your LCD controller:

// initialize the library with the numbers of the interface pins


LiquidCrystal lcd(7, 6, 5, 4, 13, 2);

DHT11 and DHT22 sensors require some dedicated library. We strongly recommend
using the “DHT sensor library” version 1.3.0, which is not the last version available on
the repository. DHT sensor library depends on the “Adafruit Unified Sensor”, so it is
mandatory to include this library. The DHT sensor library can be imported to the source
code via:

#include <DHT.h>

Configure your DHT sensor:

#define DHTPIN 8 // Digital pin connected to the DHT sensor


// Uncomment whatever type you're using!
//#define DHTTYPE DHT11 // DHT 11
#define DHTTYPE DHT22
// Initialize DHT sensor.
DHT dht(DHTPIN, DHTTYPE);

PMS sensor requires a dedicated library. The Arduino library for Plantower PMS sensors,
also “PMS” library, supports PMS x003 sensors (1003, 3003, 5003, 6003, 7003). The
PMS sensor library can be imported to the source code via:

#include "PMS.h"

104
11.7. Communication
The PMS sensor is connected to pins 9 and 10: by using the <SoftwareSerial.h> library,
such pins can be used as rx and tx of Arduino Uno, respectively.

#include <SoftwareSerial.h>
SoftwareSerial mySerial(9,10); // Arduino Rx and Tx ports

Arduino Ethernet Shield requires a dedicated library. With the Arduino Ethernet Shield,
the Ethernet.h library allows an Arduino board to connect to the Internet. The Arduino
Ethernet Shield library can be imported to the source code via:

#include <Ethernet.h>

Then configure your Ethernet Shield:

// Enter a MAC address and IP address for your controller below.


byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF};
byte ip[] = {192, 168, 0, 99}; // <- change to match your network

MQTT connectivity protocol requires a dedicated library. The MQTT.h library uses the
Arduino Ethernet Client API for interacting with the underlying network hardware. This
library provides a client for doing simple publish/subscribe messaging with a server that
supports MQTT. The Arduino Ethernet Shield library can be imported to the source code
via:

#include <MQTT.h>

“platformio.ini” (Project Configuration File)


The Project configuration file is named platformio.ini.

[env:uno]
platform = atmelavr
board = uno
framework = arduino

lib_ldf_mode=deep+
lib_compat_mode=strict

lib_deps =
DHT sensor library@1.3.0
Adafruit Unified Sensor@1.0.3
Ethernet@2.0.0
MQTT@2.4.3
PMS@1.1.0

lib_deps_external =
https://github.com/arduino-libraries/LiquidCrystal.git#1.0.7

11.7. Communication
The user can connect and program the controller of each node by using the Distancelab
environment by booking it for the time he needs. The user can use the MQTT protocol.

105
11. SmartMe Network Laboratory: Arduino Nodes 1-5
MQTT stands for Message Queuing Telemetry Transport.

MQTT is a machine-to-machine (M2M) connectivity protocol usable for “Internet of


Things” solutions. MQTT is a simple messaging protocol, designed for constrained devices
with low-bandwidth. So, it’s the perfect solution for Internet of Things applications.

This publish/subscribe messaging pattern requires a message broker. The broker is


responsible for distributing messages to interested clients based on the topic of a
message. So a client must connect to a broker in order to:

▪ publish messages specifying a topic so that other clients that have subscribed to that
topic will be able to receive those messages;
▪ receive messages subscribing to a specific topic.

11.8. Limits
At the same time, only one user can program the controller. But all users connected
to the Distancelab MQTT broker can read the values if they are being transmitted over
MQTT.

11.9. Support
gmerlino@unime.it, rdipietro@unime.it

11.9.1. IB1: Basic operations on the 2x16 LCD screen


Whatever you do, you expect to have some output of the system. Sometimes there is a
blinking LED, sometimes information about connected/disconnected network and some
other time simply trace algorithm progress. In laboratories where you have connected
the MCU physically to your programming device (i.e., your laptop), you usually would
like to choose the serial port to report about what is going on. However, here all you
have at runtime is the access to the video stream. Perhaps those are the reasons why
you will use the LCD display in every lab work you will do.

Target group
This hands-on lab guide is intended for the Beginners but other target groups may
benefit from it, treating it as basics for advanced projects.

Prerequisites
There are no other prerequisites besides the Liquid Crystal library. All the nodes of

106
11.9. Support
SmartME Network Laboratory are equipped with a 2×16 LCD Displaytech 162B based on
the HD44780 standard. It is necessary to initialize the library by associating any pin of
the LCD interface to the Arduino pin number to which it is connected (see Step 2).

The circuit:
▪ LCD pin 1 = 5v+ (220 ohm resistance)
▪ LCD pin 2 = GND
▪ LCD pin 3 = GND
▪ LCD pin 4 = 5v
▪ LCD pin 5 = center of potentiometer (potentiometer leg 1 goes to 5v and leg 3 goes
to ground)
▪ LCD pin 6 = Arduino pin 7
▪ LCD pin 7 = GND
▪ LCD pin 8 = Arduino pin 6
▪ LCD pin 13 = Arduino pin 5
▪ LCD pin 14 = Arduino pin 4
▪ LCD pin 15 = Arduino pin 13
▪ LCD pin 16 = Arduino pin 2

Scenario
Initialize the LCD screen with the text “SmartMe Lab!”, then turn it off, then turn it
on again, in a loop: each phase lasting half a second. Delays are expressed in ms
(milliseconds) and not in s (seconds).

Result
You should see the text “Smart lab!” appearing and disappearing every half second.

Start
There are no special steps to be performed.

Steps

Step 1
Include LCD driver library:

#include <LiquidCrystal.h>

Step 2
Instantiate the software controller component for the LCD display:

// initialize the library with the numbers of the interface pins


LiquidCrystal lcd(7, 6, 5, 4, 13, 2);

107
11. SmartMe Network Laboratory: Arduino Nodes 1-5

Step 3
Initialize display - we suggest to do it in the setup() function:

void setup() {
// set up the LCD's number of columns and rows
lcd.begin(16, 2);
// print a message to the LCD
lcd.print("SmartMe lab!");
}

Step 4
Implement loop() to turn off and on the LCD display, for 500 ms each:

void loop() {
// turn off the display
lcd.noDisplay();
delay(500);
// turn on the display
lcd.display();
delay(500);
}

Result validation
Observe the text appearing and disappearing every half second.

Platformio.ini
[env:uno]
platform = atmelavr
board = uno
framework = arduino

lib_ldf_mode=deep+
lib_compat_mode=strict

lib_deps_external =
https://github.com/arduino-libraries/LiquidCrystal.git#1.0.7

IB1.cpp
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 6, 5, 4, 13, 2);

void setup() {
// set up the LCD's number of columns and rows
lcd.begin(16, 2);
// print a message to the LCD
lcd.print("SmartMe Lab!");
}

108
11.9. Support
void loop() {
// turn off the display
lcd.noDisplay();
delay(500);
// turn on the display
lcd.display();
delay(500);
}

11.9.2. IB2: Presenting temperature and humidity values on the


LCD

Target group
This hands-on lab guide is intended for the Beginners but other target groups may
benefit from it, treating it as basics for advanced projects.

Prerequisites

Liquid Crystal
For this library, you may refer to the B1 exercise.

DHT sensors
The nodes of SmartME Network Laboratory are equipped with different versions of DHT
sensors: DHT11 and DHT22. The sensors look a bit similar and have the same pinout,
but have different characteristics. Below you can find the DHT technical specifications:

DHT11
▪ Ultra-low-cost
▪ 3 to 5V power and I/O
▪ 2.5mA max current use during conversion (while requesting data)
▪ Good for 20-80% humidity readings with 5% accuracy
▪ Good for 0-50°C temperature readings ±2°C accuracy
▪ No more than 1 Hz sampling rate (once every second)
▪ Body size 15.5mm x 12mm x 5.5mm
▪ 4 pins with 0.1“ spacing

DHT22
▪ Low cost
▪ 3 to 5V power and I/O
▪ 2.5mA max current use during conversion (while requesting data)
▪ Good for 0-100% humidity readings with 2-5% accuracy
▪ Good for -40 to 80°C temperature readings ±0.5°C accuracy

109
11. SmartMe Network Laboratory: Arduino Nodes 1-5
▪ No more than 0.5 Hz sampling rate (once every 2 seconds)
▪ Body size 15.1mm x 25mm x 7.7mm
▪ 4 pins with 0.1” spacing
DHT sensors are able to detect temperature and relative humidity. Relative humidity
consists of the amount of water vapour in air vs. the saturation point of water vapour
in the air. At the saturation point, water vapour starts to condense and accumulate on
surfaces forming dew. The saturation point changes with air temperature. Cold air can
hold less water vapour before it becomes saturated, and hot air can hold more water
vapour before it becomes saturated.

Temperature and relative humidity can be used to determine the apparent temperature
or the human perceived equivalent temperature, also called “heat index”. The heat index
was developed in 1978 by George Winterling and was adopted next year. It is also known
as humiture, according to Wikipedia contributors.

Scenario
First, initialize LCD screen with the labels of temperature and relative humidity. Then,
after the sensor detection, next to the labels, the sensor values will be displayed, one
per line, every 3 seconds. Note, the function readTemperature() reads temperature
as Celsius (the default). If you want to read the temperature as Farenight, you have
to set the true value as a parameter of the signature in the readTemperature(true)
function. The relative humidity is expressed as a percentage. That means that at
100% RH the condensation occurs, while at 0% RH the air is completely dry. More,
but not used in the proposed exercise, it is possible to compute the heat index in
Fahrenheit (the default) by using the function computeHeatIndex(temp_value_farenight,
humidity_value), or if you want in Celsius (isFahreheit = false) by using the function
computeHeatIndex(temp_value_celsius, humidity_value, false). Result You should see
the values of temperature and relative humidity, that is sampled and displayed every 3
seconds (3000 ms). Start There are no special steps to be performed.

Steps

Step 1
Include LCD driver library and DHT library:

#include <LiquidCrystal.h>
#include "DHT.h"

Step 2
Instantiate the software controller component for the LCD display. Then set up:

1. the DHTPIN (which refers to the digital pin we use to get the signal);
2. the DHT sensor type in use (DHT11 or DHT22, it depends on the node of the lab you
are using).
Then initialize the DHT sensor.

// initialize the library with the numbers of the interface pins

110
11.9. Support
LiquidCrystal lcd(7, 6, 5, 4, 13, 2);
#define DHTPIN 8 // what pin we are connected to
// Uncomment whatever type you're using!
#define DHTTYPE DHT11
//#define DHTTYPE DHT22
// Initialize DHT sensor
DHT dht(DHTPIN, DHTTYPE);

Step 3
Initialize display and Initialize the DHT sensor - we suggest to do it in the setup()
function:

void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print Temperature label to the LCD.
lcd.print("Temp. *C");
lcd.setCursor(0,1);
// Print the Humidity label to the LCD.
lcd.print("Hum. %");
dht.begin();
}

Step 4
Implement loop() to sample and display the values of temperature and relative humidity
on the LCD display, every 3 seconds:

void loop() {
// Wait three seconds between measurements.
delay(3000);

// read relative humidity


float h = dht.readHumidity();
// read temperature as Celsius
float t = dht.readTemperature();
// read temperature as Fahrenheit
//float f = dht.readTemperature(true);
// compute heat index in Fahrenheit (the default)
float hif = dht.computeHeatIndex(f, h);
// compute heat index in Celsius (isFahreheit = false)
float hic = dht.computeHeatIndex(t, h, false);
// print Temperature value to the LCD
lcd.setCursor(14, 0);
lcd.print(t);
// print the Humidity value to the LCD
lcd.setCursor(14, 1);
lcd.print(h);
}

Result validation
Observe the temperature and relative humidity values shown in the LCD display. The
display will refresh values every 3 seconds.

111
11. SmartMe Network Laboratory: Arduino Nodes 1-5

Platformio.ini
[env:uno]
platform = atmelavr
board = uno
framework = arduino

lib_ldf_mode=deep+
lib_compat_mode=strict

lib_deps =
DHT sensor library@1.3.0
Adafruit Unified Sensor@1.0.3

lib_deps_external =
https://github.com/arduino-libraries/LiquidCrystal.git#1.0.7

IB2.cpp
#include <LiquidCrystal.h>
#include "DHT.h"

// initialize the library with the numbers of the interface pins


LiquidCrystal lcd(7, 6, 5, 4, 13, 2);

#define DHTPIN 8 // what pin we are connected to


// uncomment whatever type you're using
#define DHTTYPE DHT22
//#define DHTTYPE DHT22

// initialize DHT sensor


DHT dht(DHTPIN, DHTTYPE);

void setup() {
// set up the LCD's number of columns and rows
lcd.begin(16, 2);
// Print Temperature label to the LCD
lcd.print("Temp. C");
lcd.setCursor(0,1);
// Print the Humidity label to the LCD
lcd.print("Hum. %");
dht.begin();
}

void loop() {
// wait three seconds between measurements
delay(3000);
// read humidity
float h = dht.readHumidity();
// read temperature as Celsius
float t = dht.readTemperature();
// read temperature as Fahrenheit
//float f = dht.readTemperature(true);

// compute heat index in Fahrenheit (the default)


// float hif = dht.computeHeatIndex(f, h);

112
11.9. Support
// compute heat index in Celsius (isFahreheit = false);
float hic = dht.computeHeatIndex(t, h, false);

// print Temperature value to the LCD


lcd.setCursor(14, 0);
lcd.print(t);
// print the Humidity value to the LCD
lcd.setCursor(14, 1);
lcd.print(h);
}

11.9.3. IB3: PWM mode (~) of digital pins, programming threshold


values

Target group
This hands-on lab guide is intended for the Beginners but other target groups may
benefit from it, treating it as a tool for advanced projects.

Prerequisites

Liquid Crystal
For this library, you may refer to the B1 exercise.

RGB LED
The SmartME Network Laboratory Arduino nodes 1-5 are equipped with an RGB LED. To
connect other devices, however, only the green light component is available, exposed as
a separate LED. To turn on the green LED, you have to follow three steps:

1. first, you have to define a variable with the number of the pin where the LED is
connected to (int greenPin = 3;);
2. second, you need to configure this variable in output mode (OUTPUT) by invoking
the pinMode(pin, mode) function, inside the setup() function.
3. finally, you need to send to this variable a HIGH signal by using the digitalWrite(pin,
value) function, inside the loop() function.
To turn off the LED, you need to send a LOW signal value to this pin. You can make the
LED flashing by tuning the delay of HIGH and LOW states. The digital pins either give you
5V (when turned HIGH) or 0V (when turned LOW) and the output is a square wave signal.
PWM stands for Pulse Width Modulation and it is a technique used in controlling the
brightness of the LED. The PWM pins are labelled with ~ sign. The function analogWrite()
can be used to generate a PWM signal in those digital pins that are labelled with ~ sign.
The frequency of this generated signal for most pins will be about 490Hz and you can
give the value from 0-255 using this function

▪ analogWrite(0) means a signal of 0% duty cycle.


▪ analogWrite(127) means a signal of 50% duty cycle.
▪ analogWrite(255) means a signal of 100% duty cycle.
The function random() generates pseudo-random numbers. The syntax is random(max)

113
11. SmartMe Network Laboratory: Arduino Nodes 1-5
or random(min, max), where min represents the lower bound of the random value,
inclusive (optional); and max represents the upper bound of the random value,
exclusive. The function returns a long random number between min and max-1.

The circuit:
RGB GREEN pin = Arduino pin 3 (~)

Scenario
Initialize the LCD screen with the label “rand value”, then calculates a random value. If
randomValue is lower than lowThreshold, turn on the LED. If randomValue is upper than
highThreshold, turn off the LED. After 1 second, print the random value to the LCD. Then,
turn on the LED for 3 seconds, assigning it a value of brightness which corresponds to the
random value previously calculated. Note, you can set the two values of the threshold as
you prefer. You can modify the brightness of the LED because, although it is connected
to a digital pin, the Arduino pin number 3 is labeled with ~ sign (PWM).

Result
You should see the LED on or off for 1 second, a second if the value is greater or less
than the predefined threshold values. Next, you should see the randomly calculated
value between 0 and 255 on the LCD, at that point, the LED should assign a brightness
associated with that value, and keep it for 3 seconds.

Start
There are no special steps to be performed.

Steps

Step 1
Include the LCD driver library:

#include <LiquidCrystal.h>

Step 2
Instantiate the software controller component for the LCD display. Initialize the LED pin.
Declare the threshold values.

// initialize the library with the numbers of the interface pins


LiquidCrystal lcd(7, 6, 5, 4, 13, 2);
// initializing LED Pin
int greenPin = 3;
// declaring the threshold values
int lowThreshold = 127;
int highTreshold = 128;

Step 3
Initialize the display and declare the LED pin as OUTPUT - preferably in the setup()

114
11.9. Support
function:

void setup(){
pinMode(greenPin, OUTPUT); // declaring LED pin as output
lcd.begin(16, 2); // set up the LCD's number of columns and rows
lcd.print("rand value"); // print the random value label to the LCD
}

Step 4
Implement loop() to do in the order: calculate a random value between 0 and 255;
compare the random value with the lower threshold and with the upper threshold in order
to decide whether to switch the LED on or off for 1 second; display the random value on
the screen, and use it to assign a specific brightness value to the LED, which must be
held for 3 seconds.

void loop() {
// calculate a randomValue in the range 0-255
int randomValue = random(255);
if (randomValue < lowThreshold){
digitalWrite(greenPin, HIGH);
}
if (randomValue > highTreshold){
digitalWrite(greenPin, LOW);
}
delay(1000); // print the random value of light to the LCD
lcd.setCursor(14, 0);
lcd.print(randomValue);
analogWrite(greenPin, randomValue);
delay(3000);
}

Result validation
The state of the LED will depend on the random number calculated and on the threshold
values that have been set. The random value will be shown by the display monitor. It
also will affect the LED brightness for 3 seconds.

Platformio.ini
[env:uno]
platform = atmelavr
board = uno
framework = arduino
lib_ldf_mode=deep+
lib_compat_mode=strict
lib_deps =
DHT sensor library@1.3.0
Adafruit Unified Sensor@1.0.3
lib_deps_external =
https://github.com/arduino-libraries/LiquidCrystal.git#1.0.7

115
11. SmartMe Network Laboratory: Arduino Nodes 1-5

IB3.cpp
#include <LiquidCrystal.h>
#include "DHT.h"
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 6, 5, 4, 13, 2);
// initializing LED Pin
int greenPin = 3;
// declaring of threshold values
int lowThreshold = 500;
int highTreshold = 600;

void setup(){
// declaring LED pin as output
pinMode(greenPin, OUTPUT);
// set up the LCD's number of columns and rows
lcd.begin(16, 2);
// print the random value label to the LCD
lcd.print("rand value");
}

void loop() {
int randomValue = random(255);
if (randomValue < lowThreshold){
digitalWrite(greenPin, HIGH);
}
if (randomValue > highTreshold){
digitalWrite(greenPin, LOW);
}
delay(1000);
// print the random value of light to the LCD
lcd.setCursor(14, 0);
lcd.print(randomValue);
analogWrite(greenPin, randomValue);
delay(3000);
}

11.9.4. IU1: Showing temperature, humidity and dust values on


the 2x16 LCD screen

Target group
This hands-on lab guide is intended for the Undergraduate but other target groups may
benefit from it, treating it as basics for advanced projects.

Prerequisites

Liquid Crystal
For this library, you may refer to the B1 exercise.

DHT
For this library, you may refer to the B2 exercise.

116
11.9. Support

PMS7003
All the SmartME Network Laboratory Arduino nodes are equipped with a PMS7003
sensor. This sensor allows measuring the air quality by taking into account the PMx
concentration. The working principle of such a sensor is based on producing scattering
by using a laser to radiate suspending particles in the air, then collecting scattering light
to a certain degree, and finally obtaining the curve of scattering light change with time.
In the end, the equivalent particle diameter and the number of particles with different
diameters per unit volume can be calculated [1]. So, the values of PM1.0, PM2.5, and
PM10, will be available for our scopes.

In order to physically interface the 10 bus lines of the dust sensor with Arduino Uno, we
used the PMS7003 connector [2]. By supplying the adapter at 5V, the particle sensor
will operate correctly and the data will be available at RX and TX pins. However, the
serial voltage level is 3.3V typical, while Arduino Uno needs 5V. For this reason, to
supply the HV (High Voltage) side at 5V and the LV (Low Voltage), we introduced a bi-
directional level converter [3] which allows correcting the serial levels of Arduino (5V)
and of PMS7003 (3.3V).

[1]https://download.kamami.com/
p564008-p564008-PMS7003%20series%20data%20manua_English_V2.5.pdf

[2]https://kamami.com/others/564553-adapter-from-127mm-pitch-to-254mm-for-
pms7003.html

[3]https://kamami.com/voltage-level-converters/234535-logic-level-converter-bi-
directional.html

Arduino Serial
This function is used for communication between the Arduino board and a computer or
other devices. All Arduino boards have at least one serial port. On Uno pins 0 and 1 are
used for communication with the computer. Serial communication on pins TX/RX uses
TTL logic levels (5V or 3.3V depending on the board) [4].

Since is not possible to deploy the code by using, at the same time, the default RX, TX
pins (0,1) of Arduino Uno, the PMS7003 is connected to pins 9 and 10: by using the
<SoftwareSerial.h> library [5], such pins can be used as RX and TX of Arduino Uno,
respectively.

[4]https://www.arduino.cc/reference/en/language/functions/communication/serial/

[5] https://www.arduino.cc/en/Reference/softwareSerial

Scenario
First, initialize LCD screen with the labels of temperature (“T”), relative humidity (“H”),
and dust particles (“PM10”). Then, after the sensor detection, next to the labels, the
sensor values will be displayed, every 1 second. Notice that, by enabling the serial print
section, data will be available to the serial monitor too. The sensor is able to measure
three types of dust particles: PM1.0, PM2.5, and PM10. It may take several seconds
to have more precious values about these values. Such values are represented by two
bytes: the MSB and the LSB one, as shown in [6] (appendix I). Only the MSB byte

117
11. SmartMe Network Laboratory: Arduino Nodes 1-5
can be shown or, alternatively, both values, separated by a point, as for the display
management in this example. Various options and combinations are possible for you. For
example, the PM2.5 value can be shown on the display, instead of the temperature one.
Similarly, for the serial monitor.

[6]https://download.kamami.com/
p564008-p564008-PMS7003%20series%20data%20manua_English_V2.5.pdf

Result
You should see the values of temperature, relative humidity and dust that are sampled
and displayed every 1 second (1000 ms).

Start
There are no special steps to be performed.

Steps

Step 1
Include LCD driver library, DHT library and Software Serial library:

#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
#include "DHT.h"

Step 2
Instantiate the software controller component for the LCD display. Then set up:

1. 1) the DHTPIN (which refers to the digital pin we use to get the signal);
2. 2) the DHT sensor type in use (DHT11 or DHT22, it depends on the node of the lab
you are using).
Set the RX and TX pin of Arduino in the object of the SoftwareSerial library.

#define DHTPIN 8
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);


LiquidCrystal lcd(7, 6, 5, 4, 13, 2);
// Arduino Uno port RX, TX
SoftwareSerial mySerial(9,10);

Step 3
Initialize display. Initialize the DHT sensor. Sets the data rate in bits per second (baud)
for serial data transmissions, both for debugging (115200) and for communication
(9600). We suggest to do it in the setup() function:

void setup() {

118
11.9. Support
lcd.begin(16, 2);
// Print Temperature label to the LCD
lcd.print("T");
lcd.setCursor(9,0);
// Print the Humidity label to the LCD
lcd.print("H");
dht.begin();
lcd.setCursor(0,1);
lcd.print("PM10");
// for debugging
Serial.begin(115200);
// Use software serial
mySerial.begin(9600);
}

Step 4
Implement loop() to sample and display the values of the temperature, relative humidity
and dust on the LCD display, every 1 second:

void loop() {
float h = dht.readHumidity();
// read temperature in Celsius
float t = dht.readTemperature();
// compute heat index in Celsius (isFahreheit = false);
float hic = dht.computeHeatIndex(t, h, false);
// in Fahrenheit
//float f = dht.readTemperature(true);
// float hif = dht.computeHeatIndex(f, h);

// print Temperature value to the LCD


lcd.setCursor(2, 0);
lcd.print(t);
lcd.setCursor(6,0);
lcd.print("C");

// print the Humidity value to the LCD


lcd.setCursor(11, 0);
lcd.print(h);
lcd.setCursor(15,0);
lcd.print("%");

int chksum=0;
byte pms[32]={0,};
if(mySerial.available()>=32){
for(int j=0; j<32 ; j++){
pms[j]=mySerial.read();
if(j<30)
chksum+=pms[j];
}
if(pms[30] != (byte)(chksum>>8)
|| pms[31] != (byte)(chksum) ){
}
}
delay(1000);
lcd.setCursor(5, 1);
lcd.print(pms[14]);

119
11. SmartMe Network Laboratory: Arduino Nodes 1-5
lcd.print(".");
lcd.print(pms[15]);
lcd.print("ug/m3 ");
}

Result validation
Observe the temperature, relative humidity and dust values shown in the LCD display.
The display will refresh values every 1 second.

Platformio.ini
[env:uno]
platform = atmelavr
board = uno
framework = arduino

lib_ldf_mode=deep+
lib_compat_mode=strict

lib_deps =
DHT sensor library@1.3.0
Adafruit Unified Sensor@1.0.3

lib_deps_external =
https://github.com/arduino-libraries/LiquidCrystal.git#1.0.7

IU1.cpp
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
#include "DHT.h"
#define DHTPIN 8

#define DHTTYPE DHT22


DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal lcd(7, 6, 5, 4, 13, 2);

SoftwareSerial mySerial(9,10); // Arduino Uno port RX, TX

void setup() {
lcd.begin(16, 2);
// Print Temperature label to the LCD
lcd.print("T");
lcd.setCursor(9,0);
// Print the Humidity label to the LCD
lcd.print("H");
dht.begin();
lcd.setCursor(0,1);
lcd.print("PM10");

// for debuging
Serial.begin(115200);

// Use software serial

120
11.9. Support
mySerial.begin(9600);
}
void loop() {
float h = dht.readHumidity();
// read temperature as Celsius
float t = dht.readTemperature();
// read temperature as Fahrenheit
// float f = dht.readTemperature(true);
// compute heat index in Fahrenheit (the default)
// float hif = dht.computeHeatIndex(f, h);
// compute heat index in Celsius (isFahreheit = false);
float hic = dht.computeHeatIndex(t, h, false);

// print Temperature value to the LCD


lcd.setCursor(2, 0);
lcd.print(t);
lcd.setCursor(6,0);
lcd.print("C");
// print the Humidity value to the LCD
lcd.setCursor(11, 0);
lcd.print(h);
lcd.setCursor(15,0);
lcd.print("%");

int chksum=0;
byte pms[32]={0,};

if(mySerial.available()>=32){
for(int j=0; j<32 ; j++){
pms[j]=mySerial.read();
if(j<30)
chksum+=pms[j];
}
if(pms[30] != (byte)(chksum>>8)
|| pms[31] != (byte)(chksum) ){
}
}
delay(1000);
lcd.setCursor(5,1);
lcd.print(pms[14]);
lcd.print(".");
lcd.print(pms[15]);
lcd.print("ug/m3 ");
}

11.9.5. IM1: MQTT to publish a message with a topic


MQTT is one of the most commonly used protocols in IoT projects. It stands for Message
Queuing Telemetry Transport. In addition, it is designed as a lightweight messaging
protocol that provides publish/subscribe operations to exchange data between parties.
This exercise is to be considered as closely related to the M2 exercise. Both are part of
the same scenario. This exercise shows how to publish a message as a client.

Target group
This hands-on lab guide is intended for master students. Other target groups may benefit

121
11. SmartMe Network Laboratory: Arduino Nodes 1-5
from it only if they follow it after having dealt with all the exercises proposed which
belong to lower levels of difficulty.

Prerequisites

Liquid Crystal
For this library, you may refer to the B1 exercise.

DHT
For this library, you may refer to the B2 exercise.

Understand what Arduino Ethernet Shield is, and how it works


The Arduino Ethernet Shield V1 allows an Arduino board to connect to the internet. It
is based on the Wiznet W5100 [1] ethernet chip (datasheet [2]). The Wiznet W5100
provides a network (IP) stack capable of both TCP and UDP-based communication. It
supports up to four simultaneous socket connections. Use the Ethernet library [3] to
write sketches that connect to the Internet using the shield. The ethernet shield connects
to an Arduino board using long wire-wrap headers which extend through the shield. This
keeps the pin layout intact and allows another shield to be stacked on top.

[1] http://www.wiznet.co.kr/Sub_Modules/en/product/
Product_Detail.asp?cate1=5&cate2=7&cate3=26&pid=1011

[2] http://www.wiznet.co.kr/UpLoad_Files/ReferenceFiles/W5100_Datasheet_v1.2.2.pdf

[3] https://www.arduino.cc/en/Reference/Ethernet

Understand what MQTT is and how it works.


MQTT (Message Queue Telemetry Transport) is a standard (SO/IEC PRF 20922) machine-
to-machine (M2M) communication protocol for the Internet of Things smart objects and
devices. MQTT is a simple messaging protocol, designed for constrained devices with low-
bandwidth. So, it’s the perfect solution for Internet of Things applications. This publish/
subscribe messaging pattern requires a message broker. The broker is responsible for
distributing messages to interested clients based on the topic of a message. So a client
must connect to a broker in order to: publish messages specifying a topic so that other
clients that have subscribed to that topic will be able to receive those messages; receive
messages subscribing to a specific topic.

This exercise uses shiftr.io [4]. Shiftr.io is a web-based visualization for messages going
through an MQTT broker. It is possible to use broker.shiftr.io directly as a public broker.

[4] https://shiftr.io

Scenario
This node, which acts as a publisher, takes care of sampling the temperature value and
sending it to other nodes, which serve as subscribers and were initialized as in exercise
M2.

122
11.9. Support

Result
It will be possible to display the value of the temperature, measured from the sensors
attached to this node of the lab, on the LCD display attached to another node of the lab,
provided that in the latter node the M2 sketch has been previously launched. Start This
exercise is to be considered as closely related to the M2 exercise. This means that if you
want to reproduce a complete experiment, you have to book at least two nodes of the
lab, and then you have to run both IM1 and IM2 sketches, one per node.

Steps

Step 1
Include the following libraries: LCD driver, DHT, MQTT, and Ethernet.

#include <LiquidCrystal.h>
#include <Ethernet.h>
#include <MQTT.h>
#include <DHT.h>

Step 2
Instantiate the software controller component for the LCD display. Then assign to the
ethernet interface a MAC and IP address, the latter valid for the internal laboratory
network (192.168.0.0/24 in this case). Thus instantiate the EthernetClient and
MQTTClient objects. Finally declare the connect() function.

// initialize the library with the numbers of the interface pins


LiquidCrystal lcd(7, 6, 5, 4, 13, 2);
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
byte ip[] = {192, 168, 0, 98};
EthernetClient net;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
Serial.print("connecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
}

Step 3
Initialize the display and the Ethernet connection with IP and MAC address. Then launch
the connection() function and initialize the MQTT client with the shift.io broker. You can
visualize your device stream, after a successful connection, here: https://shiftr.io/try.

We suggest doing all of the above in the setup() function, as follows:

void setup() {
lcd.begin(16, 2);

123
11. SmartMe Network Laboratory: Arduino Nodes 1-5
lcd.print("Temp. *C");
lcd.setCursor(0,1);
lcd.print("MQTT PUB");

Serial.begin(115200);
Ethernet.begin(mac, ip);

client.begin("broker.shiftr.io", net);

connect();
}

Step 4
Implement the loop() function to detect the value of temperature from the DHT sensor
and publish it as a message with the topic “iotopenume” every 1 second, as follows:

void loop() {
client.loop();
if (!client.connected()) {
connect();
}
int t = dht.readTemperature();
String payload = String(t);
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
Serial.println(payload);
//publish to the iotopenume topic
client.publish("/iotopenume", payload);
lcd.setCursor(14, 1);
lcd.print(payload);
}
}

Result validation
It will be possible to display the value, sampled by the temperature sensor attached to
this node, on the LCD display attached to the node you will use as a subscriber, as soon
as you start the M2 sketch on the latter.

Platformio.ini
[env:uno]
platform = atmelavr
board = uno
framework = arduino

lib_ldf_mode=deep+
lib_compat_mode=strict

lib_deps =
DHT sensor library@1.3.0
Adafruit Unified Sensor@1.0.3
Ethernet@2.0.0

124
11.9. Support
MQTT@2.4.3

lib_deps_external =
https://github.com/arduino-libraries/LiquidCrystal.git#1.0.7

IM1_pub.cpp
#include <Ethernet.h>
#include <MQTT.h>
#include <DHT.h>
#include <LiquidCrystal.h>

#define DHTPIN 8
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

LiquidCrystal lcd(7, 6, 5, 4, 13, 2);


byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
byte ip[] = {192, 168, 0, 98};
EthernetClient net;
MQTTClient client;
unsigned long lastMillis = 0;

void connect() {
Serial.print("connecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
}

void setup() {
lcd.begin(16, 2);
lcd.print("Temp. *C");
lcd.setCursor(0,1);
lcd.print("MQTT PUB");
Serial.begin(115200);
Ethernet.begin(mac, ip);
client.begin("broker.shiftr.io", net);
connect();
}

void loop() {
client.loop();
if (!client.connected()) {
connect();
}
int t = dht.readTemperature();
String payload = String(t);
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
Serial.println(payload);
client.publish("/iotopenume", payload);
lcd.setCursor(14, 1);
lcd.print(payload);

125
11. SmartMe Network Laboratory: Arduino Nodes 1-5
}
}

11.9.6. IM2: MQTT to subscribe to a topic to receive messages


MQTT is one of the most commonly used protocols in IoT projects. It stands for Message
Queuing Telemetry Transport. In addition, it is designed as a lightweight messaging
protocol that provides publish/subscribe operations to exchange data between parties.
This exercise is to be considered as closely related to the M1 exercise. Both are part of
the same scenario. This exercise shows how to subscribe to a topic to receive messages
belonging to it.

Target group
This hands-on lab guide is intended for master students. Other target groups may benefit
from it only if they follow it after having dealt with all the exercises proposed which
belong to lower levels of difficulty.

Prerequisites

Liquid Crystal
For this library, you may refer to the B1 exercise.

DHT
For this library, you may refer to the B2 exercise.

Understand what Arduino Ethernet Shield is and how it works


The Arduino Ethernet Shield V1 allows an Arduino board to connect to the internet. It
is based on the Wiznet W5100 [1] ethernet chip (datasheet [2]). The Wiznet W5100
provides a network (IP) stack capable of both TCP and UDP-based communication. It
supports up to four simultaneous socket connections. Use the Ethernet library [3] to
write sketches that connect to the Internet using the shield. The ethernet shield connects
to an Arduino board using long wire-wrap headers which extend through the shield. This
keeps the pin layout intact and allows another shield to be stacked on top.

[1] http://www.wiznet.co.kr/Sub_Modules/en/product/
Product_Detail.asp?cate1=5&cate2=7&cate3=26&pid=1011

[2] http://www.wiznet.co.kr/UpLoad_Files/ReferenceFiles/W5100_Datasheet_v1.2.2.pdf

[3] https://www.arduino.cc/en/Reference/Ethernet

Understand what MQTT is and how it works.


MQTT (Message Queue Telemetry Transport) is a standard (SO/IEC PRF 20922) machine-
to-machine (M2M) communication protocol for the Internet of Things smart objects and
devices. MQTT is a simple messaging protocol, designed for constrained devices with low-
bandwidth. So, it’s the perfect solution for Internet of Things applications. This publish/
subscribe messaging pattern requires a message broker. The broker is responsible for
distributing messages to interested clients based on the topic of a message. So a client

126
11.9. Support
must connect to a broker in order to: publish messages specifying a topic so that other
clients that have subscribed to that topic will be able to receive those messages; receive
messages subscribing to a specific topic.

This exercise uses shiftr.io [4]. Shiftr.io is a web-based visualization for messages going
through an MQTT broker. It is possible to use broker.shiftr.io directly as a public broker.

[4] https://shiftr.io

Scenario
This node, which acts as a subscriber, shows the value of temperature received by the
other node that was initialized with the exercise M1.

Result
It will be possible to display the value of the temperature, measured from the sensors
attached to the node where the M1 sketch had been previously launched, on the LCD
attached to this node. Start This exercise is to be considered as closely related to the M1
exercise. This means that if you want to reproduce a complete experiment, you have to
book at least two nodes of the lab, and then you have to run both IM1 and IM2 sketches,
one per node.

Steps

Step 1
Include the following libraries: LCD driver, MQTT, and Ethernet.

#include <LiquidCrystal.h>
#include <Ethernet.h>
#include <MQTT.h>

Step 2
Instantiate the software controller component for the LCD display. Then assign to the
ethernet interface a MAC and IP address, the latter valid for the internal laboratory
network (192.168.0.0/24 in this case). Then instantiate the EthernetClient and
MQTTClient objects. Then declare the connect() and messageReceived() functions. In
particular, in the connect() body there is a call to the subscribe() function, in order to
subscribe to a specific topic. In the messageReceived() body the payload of the message
(the temperature value, in this case) is written in the LCD display of the node.

// initialize the library with the numbers of the interface pins


LiquidCrystal lcd(7, 6, 5, 4, 13, 2);
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF};
byte ip[] = {192, 168, 0, 99};
EthernetClient net;
MQTTClient client;

void connect() {
Serial.print("connecting...");
while (!client.connect("arduino", "try", "try")) {

127
11. SmartMe Network Laboratory: Arduino Nodes 1-5
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
// subscribe to the iotopenume topic
client.subscribe("/iotopenume");
}

void messageReceived(String &topic, String &payload) {


Serial.println("incoming: " + topic + " - " + payload);
lcd.setCursor(14, 1);
lcd.print(payload);
}

Step 3
Initialize the display and the Ethernet connection with IP and MAC address. Then launch
the connection() function and initialize the MQTT client with the shift.io broker. You can
visualize your device stream, after a successful connection, here: https://shiftr.io/try.

We suggest doing all of the above in the setup() function, as follows:

void setup() {
lcd.begin(16, 2);
lcd.print("Temp. *C");
lcd.setCursor(0,1);
lcd.print("MQTT SUB");
Serial.begin(115200);
Ethernet.begin(mac, ip);
client.begin("broker.shiftr.io", net);
client.onMessage(messageReceived);
connect();
}

Step 4
Implement loop() to try connecting until success, as follows:

void loop() {
client.loop();
if (!client.connected()) {
connect();
}
}

Result validation
Observe on your LCD display, its hosting node acting as a subscriber, the value sampled
by the temperature sensor attached to the publisher, as soon as you start the M1 sketch
on the latter.

128
11.9. Support

Platformio.ini
[env:uno]
platform = atmelavr
board = uno
framework = arduino

lib_ldf_mode=deep+
lib_compat_mode=strict

lib_deps =
DHT sensor library@1.3.0
Adafruit Unified Sensor@1.0.3
Ethernet@2.0.0
MQTT@2.4.3

lib_deps_external =
https://github.com/arduino-libraries/LiquidCrystal.git#1.0.7

IM2_sub.cpp
#include <LiquidCrystal.h>
#include <Ethernet.h>
#include <MQTT.h>

LiquidCrystal lcd(7, 6, 5, 4, 13, 2);


byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF};
byte ip[] = {192, 168, 0, 99};
EthernetClient net;
MQTTClient client;

void connect() {
Serial.print("connecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/iotopenume");
}

void messageReceived(String &topic, String &payload) {


Serial.println("incoming: " + topic + " - " + payload);
lcd.setCursor(14, 1);
lcd.print(payload);
}

void setup() {
lcd.begin(16, 2);
lcd.print("Temp. *C");
lcd.setCursor(0,1);
lcd.print("MQTT SUB");
Serial.begin(115200);
Ethernet.begin(mac, ip);
client.begin("broker.shiftr.io", net);
client.onMessage(messageReceived);

129
11. SmartMe Network Laboratory: Arduino Nodes 1-5
connect();
}

void loop() {
client.loop();
if (!client.connected()) {
connect();
}
}

130

You might also like