Dokumen - Pub The Raspberry Pi Zero 2 W Go Book 389576549x 9783895765490
Dokumen - Pub The Raspberry Pi Zero 2 W Go Book 389576549x 9783895765490
Dokumen - Pub The Raspberry Pi Zero 2 W Go Book 389576549x 9783895765490
books books
books
The Raspberry Pi
Zero 2 W GO! Book The Raspberry Pi
> Cloud storage of captured temperature, humidity, and pressure data Ground
D + A r d u i n
LC oo
TT + Bluet
All programs discussed in this book are contained in an archive file
you can download free of charge from the Elektor website. Head to:
+ I o T + M Q
www.elektor.com/books and enter the book title in the Search box.
Dogan Ibrahim
●
Dogan Ibrahim
● All rights reserved. No part of this book may be reproduced in any material form, including photocopying, or
storing in any medium by electronic means and whether or not transiently or incidentally to some other use of this
publication, without the written permission of the copyright holder except in accordance with the provisions of the
Copyright Designs and Patents Act 1988 or under the terms of a licence issued by the Copyright Licencing Agency
Ltd., 90 Tottenham Court Road, London, England W1P 9HE. Applications for the copyright holder's permission to
reproduce any part of the publication should be addressed to the publishers.
● Declaration
The author, editor, and publisher have used their best efforts in ensuring the correctness of the information contained
in this book. They do not assume, and hereby disclaim, any liability to any party for any loss or damage caused by
errors or omissions in this book, whether such errors or omissions result from negligence, accident or any other cause.
All the programs given in the book are Copyright of the Author and Elektor International Media. These programs
may only be used for educational purposes. Written permission from the Author or Elektor must be obtained before
any of these programs can be used for commercial purposes.
Elektor is the world's leading source of essential technical information and electronics products for pro engineers,
electronics designers, and the companies seeking to engage them. Each day, our international team develops and delivers
high-quality content - via a variety of media channels (including magazines, video, digital media, and social media) in
several languages - relating to electronics design and DIY electronics. www.elektormagazine.com
●4
Contents
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
●5
5.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
●6
5.13 Project 12: Analog temperature sensor thermometer with LCD output . . . . . . . 104
5.16 Project 15: Real-Time graph of the temperature and humidity . . . . . . . . . . . . . 115
6.3 Project 21: Sending a text message to a smartphone using TCP/IP . . . . . . . . . . . 135
6.4 Project 22: Two-way communication with the smartphone using TCP/IP . . . . . . . 138
6.6 Project 24: Controlling an LED connected to the Zero 2 W from the smartphone,
using TCP/IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
6.7 Project 25: Sending a text message to a smartphone using UDP . . . . . . . . . . . . 145
6.8 Project 26: Controlling an LED connected to the Raspberry Pi Zero 2 W from the
smartphone, using UDP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
6.9 Using Flask to create a Web Server to control Raspberry Pi Zero 2 W GPIO ports
from the Internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
6.10 Project 27: Web Server — Controlling an LED connected to the Raspberry Pi
Zero 2 W, using Flask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
●7
6.17 Project 30 – Fetching and displaying the real-time weather data on the screen . 179
●8
7.11 Using the ALEXA in Node-RED projects with the Raspberry Pi Zero 2 W . . . . . . . 207
7.11.2 Project 39: Controlling an LED and a buzzer using Alexa . . . . . . . . . . . . . . . . 211
7.11.3 Project 40: Controlling an LED and a buzzer using Alexa – using a trigger node 213
8.6 Project 42: Controlling an LED using ESP8266 NodeMCU with MQTT –
LED connected to Raspberry Pi Zero 2 W . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
●9
9.4.1 Project 45: Communicating with an Arduino Uno over Bluetooth . . . . . . . . . . . 239
9.5 Project 46: Play audio (like music) on a Bluetooth speaker via Zero 2 W . . . . . . . 245
Appendix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
● 10
The Raspberry Pi Zero 2 W is the latest member of the Raspberry Pi family of credit card
sized computers that can be used in many applications including IoT, digital audio and video
media centers, as a desktop computer, in industrial controllers, robotics, and in countless
domestic, commercial, and industrial applications. In addition to many features found in
"bigger" family members, the Raspberry Pi Zero 2 W also offers Wi-Fi and Bluetooth capa-
bility which makes it highly desirable in remote and Internet-based control and monitoring
applications. The Raspberry Pi Zero 2 W replaces the older Raspberry Pi Zero W, provides
5 times more computing power, and in addition features Bluetooth capability. As a bonus
feature, the Raspberry Pi Zero 2 W comes with a colored pinheader connector, making it
easy to link hardware to its GPIO pins.
The book kicks off with the installation of the latest Raspberry Pi operating system on an
SD card, followed by the configuration and practical use of the GPIOs. Next, the core of
the book explains the use of the Raspberry Pi Zero 2 W running the Python programming
language, always in simple terms and backed by many tested and working example pro-
jects. On part of the reader, familiarity with the Python programming language and some
experience with one of the Raspberry Pi computers will prove helpful. Although previous
electronics experience is not required, some knowledge of basic electronics is beneficial,
especially when venturing out to modify the projects for your own applications.
The book includes many simple, software-only examples to widen your knowledge of Py-
thon. Besides these, over 30 tested and working hardware-based projects are given in the
book, covering the use of Wi-Fi, communication with smartphones and with a Raspberry Pi
Pico W computer. Additionally, there are Bluetooth projects including elementary commu-
nication with smartphones and with the popular Arduino Uno.
All the projects given in the book have been fully tested and are working. The following
sub-headings are used in the projects where applicable:
• Project title
• Project description
• Aim of the project
• Block diagram
• Circuit diagram
• Program description using PDL
• Program listing with full documentation
All programs discussed in this book are contained in an archive file you can download free
of charge from the Elektor website. Head to: www.elektor.com/books and enter the book
title in the Search box. You can easily download and use these programs without any mod-
ifications. Alternatively, feel free to modify the programs to suit your own applications.
I hope you find the book helpful and enjoy reading it.
● 11
1.1 Overview
The Raspberry Pi Zero 2 W is an immensely popular member of the Raspberry Pi family
of development boards for embedded microcontroller applications. In this chapter, you"ll
discover the hardware details of this development board and also learn how to install the
latest operating system on an SD card for use with the Raspberry Pi Zero 2 W. From now
on, this development board will be referred to as the Zero 2 W for short.
● 12
The major advantage of the Zero 2 W is that the board incorporates both Wi-Fi and Blue-
tooth interface modules along with Bluetooth Low Energy (BLE). The board shares the
same form factor as the original Raspberry Pi Zero and therefore fits inside existing Rasp-
berry Pi Zero cases. The board is powered externally with 5 V, 2.5 A via a MicroUSB socket.
The Zero 2 W board is available with pre-soldered male color-coded header (ZERO 2 WHC)
for ease of identifying the pins. This is shown in Figure 1.2. Thick internal copper layers
are used to conduct heat away from the processor and consequently achieve higher perfor-
mance without heating the processor.
Table 1.1 shows a comparison of the Zero 2 W with other Raspberry Pi Zero development
boards. Notice that the Zero 2 W is a 64-bit device and about 5 times faster than the orig-
inal Zero W.
● 13
CPU 32-bit Single core Arm11 64-bit Quad core Arm Cortex-A53
USB
GPIO 40-pin
Figure 1.3 shows the pin configuration of the Zero 2 W board. In this book, the use of a Zero
2 WHC with color-coded header is assumed. The following colors are used on the header
(Figure 1.4):
• Red = 5 V
• Orange = 3.3 V
• Black = GND
• Pink = I2C
• Purple = UART
• BLUE = SPI
• Yellow = DNC (reversed I2C)
• Green = GPIO
● 14
The Zero 2 W operates at +3.3 V and the GPIO pins are not +5 V tolerant. It is there-
fore important not to connect any peripherals to Zero 2 W that operate at supply voltages
exceeding +3.3 V. A voltage between +1.8 V and +3.3 V is read as logic High by the pro-
cessor. A voltage lower than +1.8 V is read as logic Low.
The Zero 2 W draws about 280 mA when idle and 580 mA when under a heavy computing
load. The current limit of a GPIO pin is about 17 mA and more than 51 mA should not be
drawn from all GIO pins at any time.
The GPIO pins can be configured as inputs or outputs. By default, they are configured as
inputs on power-up, except GPIO 14 and GPIO 15.
The Raspberry Pi operating system is normally stored on an SD card although it is also pos-
sible to store it on other media such as an SSD drive. The Raspberry Pi operating system
is complimentary and can be downloaded to a PC and then transferred to an SD card that
can be used to boot the Raspberry Pi development boards.
The steps to download and transfer the operating system to an SD card are given below.
Please note that these are the steps that apply if you are using a Windows PC.
● 15
https://www.raspberrypi.com/software/
• You should see a file with the name imager_1.7.3.exe downloaded to your PC
(this was the filename at the time of authoring this book. Your filename may be
different).
• Insert the micro SD card into the card holder of your PC (you may have to use
an adapter).
● 16
• Click CHOOSE STORAGE and select the SD card (Figure 1.8) as the storage
medium. A 32-GB micro SD card was used for the examples in this book.
• Click the Settings icon (gear-shaped) at the bottom right of the screen and set
the following (Figure 1.9):
• Click Write to write the operating system on the micro SD card. Wait until the
write and verify operations are finished (Figure 1.10).
● 17
https://www.putty.org/
● 18
Putty is a standalone program and there is no need to install it. Simply double-click to run
it and the Putty startup screen will be displayed. Click SSH and enter the Raspberry Pi
IP address, then click Open (see Figure 1.11). The message shown in Figure 1.12 will be
displayed the first time you access the Raspberry Pi. Click Yes to accept this security alert.
You will be prompted to enter the username and password. After a successful login, you
should see the command mode as follows:
pi@raspberrypi:~ $
You should now enable VNC so that your Zero 2 W can be accessed graphically over the
Internet using your PC. This can be done by entering the following command at the termi-
nal session:
● 19
Go to the configuration menu and select Interface Options. Go down to P3 VNC and
enable VNC. Click <Finish> to exit the menu.
• Restart Putty.
• Set the Default Foreground and Default Bold Foreground colors to black
(Red:0, Green:0, Blue:0).
• Set the Cursor Text and Cursor Color to black (Red:0, Green:0, Blue:0).
• Select Appearance under Window and click Change in Font settings. Set
the font to Bold 12.
• Select Session and give a name to the session (e.g., MyZero) and click Save.
• Click Open to open the Putty session with the saved configuration.
• Next time you restart Putty, select the saved session, and click Load followed
by Open to start a session with the saved configuration.
● 20
pi$raspberrypi:~ $ tightvncserver
You will be prompted to create a password for remotely accessing the Raspberry Pi desktop.
You can also set up an optional read-only password. The password should be entered every
time you want to access the Desktop. Enter a password and remember it.
pi$raspberrypi:~ $ vncserver :1
You can optionally specify the screen pixel size and color depth in bits as follows:
• You should now set up a VNC viewer on your laptop (or desktop) PC. There
are many VNC clients available but the recommended one which is compatible
with TightVNC is the TightVNC for the PC which can be downloaded from the
following link:
https://www.tightvnc.com/download.php
• Download and install the TightVNC software for your PC. You will have to
choose a password during the installation.
• Start the TightVNC Viewer on your PC and enter the Raspberry Pi IP address
followed by :1. Click Connect to connect to your Raspberry Pi (Figure 1.13).
• Enter the password you have chosen earlier. You should now see the Raspberry
Pi Desktop displayed on your PC screen (Figure 1.14).
● 21
• The VNC server is now running on your Raspberry Pi Zero 2 W and you have
access to the Desktop.
In this section, you will learn how to fix your IP address so that it does not change between
reboots. The steps are as follows:
● 22
• Find the IP address of your router by entering the command ip r (Figure 1.16).
In this example, the IP address was: 192.168.3.1.
• Find the IP address of your DNS by entering the following command (Figure
1.17). This is usually same as your router address:
• Add the following lines to the bottom of the file (these will be different for your
router). If these lines already exist, remove the comment character # at the
beginning of the lines and change the lines as follows (you may notice that
eth0 for Ethernet is listed):
interface wlan0
static_routers=192.168.3.1
static domain_name_servers=192.168.3.1
static ip_address=192.168.3.20/24
• Save the file by entering CNTRL + X followed by Y and reboot your Raspberry
Pi.
• In this example, the Raspberry Pi should reboot with the static IP address:
192.168.3.20.
● 23
A text editor is used to create or modify the contents of a text file. There are many text ed-
itors around for the Linux operating system. Some popular ones go by the names of nano,
vim, and vi. In this chapter, you will learn to use "nano" which is the most commonly used
text editor in Linux. In later chapters, you will see that the nano text editor can be used to
create your Python programs.
You should see the editor screen as in Figure 2.1. The name of the file to be edited is written
at the top middle part of the screen. The message New File at the bottom of the screen
shows that this is a newly created file. The shortcuts at the bottom of the screen are there
to perform various editing functions. These shortcuts are accessed by pressing the Ctrl key
together with another key. Some of the useful shortcuts are given below.
Ctrl+J: Justify
● 24
Step 2: Look for word simple by pressing Ctrl+W and then typing simple in the window
opened at the bottom left hand corner of the screen. Press the Enter key. The cursor will be
positioned on the word simple (see Figure 2.2).
Step 3: Cut the first line by placing the cursor anywhere on the line and then pressing
Ctrl+K. The first line will disappear.
● 25
Step 4: Paste the line cut after the first line. Place the cursor on the second line and press
Ctrl+U (see Figure 2.3).
Step 5: Place cursor at the beginning of the word simple on the first row. Enter Ctrl+C.
The row and column positions of this word will be displayed at the bottom of the screen.
Step 6: Press Ctrl+G to display help page as in Figure 2.4. Notice that the display is many
pages long and you can jump to the next pages by pressing Ctrl+Y or to the previous pag-
es by pressing Ctrl+V. Press Ctrl+X to exit the help page.
Step 7: Press Ctrl+- and enter line and column numbers as 2 and 5, followed by the Enter
key, to move cursor to line 2, column 5.
Step 8: Replace word example with word file. Press Ctrl+\ and type the first word as
example (see Figure 2.5). Press Enter and then type the replacement word as file. Press
Enter and accept the change by typing y.
● 26
Step 9: Save the changes. Press Ctrl+X to exit the file. Type Y to accept the saving, then
enter the filename to be written to, or simply press Enter to write to the existing file (first.
txt in this example). The file will be saved in your current working directory.
pi@raspberrypi ~ $
In summary, nano is a simple and yet powerful text editor allowing us to create new text
files or edit existing files.
● 27
3.1 Overview
Read this chapter and learn how to create and then run a very simple Python program.
As described here, basically there are three methods that you can use to create and run a
Python program. The text message Hello From Raspberry Pi Zero 2 W will be displayed
on your screen as an example.
Version 3.9.2 of Python was the current version at the time this book was written and this
is the version that you will be using in this book. You may find that both version 2.x and
3.x are installed on your Zero 2 W. Enter the following commands to display the versions of
Python you have on your Raspberry Pi (Figure 3.1):
The advantage of using Python 3 is that most of the new libraries are being developed for
it. Additionally, version 3.x has better error handling and improved GUI support over earlier
releases.
• At the command prompt enter python3. You should see the Python command
mode which is identified by three characters >>>.
● 28
pi@raspberrypi:~ $ vncserver :1
● 29
• Start the VNC Viewer on your PC by entering the IP address of your Zero 2 W
followed by :1. e.g.,
192.168.3.20:1
• Click Continue.
• Click Programming and then click Thonny Python IDE (see Figure 3.4).
• Type in your program as shown in Figure 3.5 and save it with a name, for
example, hello2.py.
• Run the program by clicking Run. You should see the program output displayed
at the bottom part (Shell) of the screen as shown in Figure 3.6.
● 30
Notice that you can also run interactive Python statements in the Shell part of the screen.
An example is shown in Figure 3.7.
● 31
● 32
4.1 Overview
In this Chapter, example Python programs are given to familiarize you with the Python
programming language. The plans in this chapter are software-only and they do not access
any external or internal hardware of the Zero 2 W development board.
Solution 1
The program is named Average and the program listing and an example run of the pro-
gram are shown in Figure 4.1. Function input is used to read the numbers in the form of
strings from the keyboard. These strings are then converted into floating-point numbers
and stored in variables n1 and n2. The average is calculated by adding and then dividing
the numbers by two. The result is displayed on the screen.
Solution 2
This demo program is named Average10 and the program listing and an example run are
shown in Figure 4.2. In this program, a loop is constructed which runs from 0 to 9 (i.e.,
10 times). Inside this loop the numbers are read from the keyboard, added, and stored in
variable sum. The average is then calculated and displayed by dividing sum by 10. Notice
that a new-line is not printed after the print statements since the option end = " " is used
inside the print statement.
● 33
Solution 3
The program is named CylArea and the program listing and an example run of the pro-
gram are shown in Figure 4.3. The surface area of a cylinder is given by:
Surface area = 2 π r h
Where r and h are the radius and height of the cylinder respectively. In this program the
math library is imported so that function Pi can be used in the program. The surface area
of the cylinder is displayed after reading its radius and height.
● 34
Solution 4
The program is named CtoF and the program listing and an example run of the program
are shown in Figure 4.4. The formula to convert ºC to ºF is:
F = 1.8 × C + 32
Solution 5
The program is named CylAreaSurf and the program listing and an example run of the
program are shown in Figure 4.5. The surface area and the volume of a cylinder are given
by:
Surface area = 2 π r h
Volume = π r2 h
Where r and h are the radius and height of the cylinder respectively. The function Calc is
used to get the radius and height of the cylinder. The function returns the surface area and
volume to the main program which puts both values on the screen.
● 35
Solution 6
The program is named Squares and the program listing and an example run of the pro-
gram are shown in Figure 4.6. Notice that \t prints a tab so that the data can be tabulated
nicely.
Solution 7
The program is named Sines and the program listing and an example run of the program
are shown in Figure 4.7. It is important to notice that the arguments of the trigonometric
functions must be in radians and not in degrees.
● 36
Solution 8
The program is named Trig and the program listing and an example run of the program
are shown in Figure 4.8.
● 37
Solution 9
The program is named TrigUser and the program listing and an example run of the pro-
gram are shown in Figure 4.9.
Solution 10
When a number of resistors are in series, the resultant resistance is the sum of the resist-
ances of each individual resistor. When the resistors are in parallel, the reciprocal of the
resultant resistance is equal to the sum of the reciprocal resistances of each resistor.
Figure 4.10 shows the program listing (program: Serpal). At the beginning of the program
a heading is displayed and the program enters into a while loop. Inside his loop, the user
is prompted to enter the number of resistors in the circuit and whether they are connected
in series or in parallel. The function str converts a number into its equivalent string. For ex-
ample, number 5 is converted into string "5". If the connection is serial (mode equals "s")
then the value of each resistor is accepted from the keyboard and the result is calculated
and displayed on the screen. If, on the other hand, the connection is parallel (mode equals
"p"), then again the value of each resistor is accepted from the keyboard and the recipro-
cal of the number is added to the total. When all resistor values are entered, the resultant
resistance is displayed on the screen.
while yn == "y":
N = int(input("\nHow many resistors are there?: "))
● 38
if mode == "s":
for n in range(0,N):
s = "Enter resistor " + str(n+1) + " value in Ohms: "
r = int(input(s))
resistor = resistor + r
print("Total resistance = %d Ohms" %(resistor))
● 39
Solution 11
The required program listing is shown in Figure 4.12 (program: Letters). A word is read
from the keyboard and stored in string variable word. Then the letters of this word are
displayed in reverse order. An example run of the program is shown in Figure 4.12.
Solution 12
The required program listing is shown in Figure 4.13 (program: Calc). Two numbers are
received from the keyboard and stored in variables n1 and n2. Then, the required math-
ematical operation is received and it is performed. The result, stored in variable result, is
displayed on the screen. The user is given the option of terminating the program.
any = "y"
while any == "y":
print("\nCalculator Program")
print("==================")
if op =="+":
result = n1 + n2
elif op == "-":
result = n1 - n2
elif op == "*":
result = n1 * n2
● 40
elif op == "/":
result = n1 / n2
print("Result = %f" %(result))
any = input("\nAny more (yn): ")
Solution 13
The program is named Filew and its listing and an example run are shown in Figure 4.15.
The file is opened in write (w) mode and the text is written in it using function write. Notice
here that fp is the file handle.
● 41
Solution 14
The program is named Filer and its listing and an example run are shown in Figure 4.16.
The fire is opened in read (r) mode and its contents is displayed.
Solution 15
The program is named Cubes and its listing and an example run are shown in Figure 4.17.
Solution 16
The program is named Times and its listing and an example run are shown in Figure 4.18.
● 42
Solution 17
The program is named OddEven and its listing and an example run are shown in Figure
4.19.
Solution 18
The program is named Conv and its listing and an example run are shown in Figure 4.20.
● 43
Solution 19
The program is named AddMatrix and its listing and an example run are shown in Figure
4.21.
Solution 20
The areas of the shapes to be used in the program are as follows:
● 44
The required program listing is shown in Figure 4.22 (program: areas.py). A different
function is used for each shape and the sizes of the sides are received inside the functions.
The main program displays the calculated area for the chosen shape.
import math
print("AREAS OF SHAPES")
print("===============\n")
print("What is the shape?: ")
shape = shape.lower()
if shape == 's':
a = float(input("Enter a side of the square: "))
area = Square(a)
s = "Square"
elif shape == 'r':
a = float(input("Enter one side of the rectangle: "))
b = float(input("Enter other side of the rectangle: "))
area = Rectangle(a, b)
s = "Rectangle"
elif shape == 'c':
radius = float(input("Enter radius of the circle: "))
● 45
area = Circle(radius)
s = "Circle"
elif shape == 't':
base = float(input("Enter base of the triangle: "))
height = float(input("Enter height of the triangle: "))
area = Triangle(base, height)
s = "Triangle"
elif shape == 'y':
radius = float(input("Enter radius of cylinder: "))
height = float(input("Enter height of cylinder: "))
area = Cylinder(radius, height)
s = "Cylinder"
a x**2 + b x + c = 0
Solution 21
The required program listing is shown in Figure 4.24 (program: quadratic). The coeffi-
cients a, b, and c are specified at the beginning of the program. The two roots are calculat-
ed and displayed on the screen.
● 46
Solution 22
The elements of the two matrices are specified at the beginning of the program. Figure 4.25
shows the program listing (program: multmatrix).
Solution 23
The program listing is shown in Figure 4.26 (program: factorial).
● 47
Solution 24
Compound interest is calculated using the formula:
FV = IV(1 + i / 100) ** yr
Compound interest = FV – IV
Where FV and IV are the future and initial values, i is the interest rate and yr is the number
of years.
● 48
Solution 25
The program listing is shown in Figure 4.28 (program: guess). An example run of the pro-
gram is shown in Figure 4.29.
import random
total_guesses = 0
if guess == number:
print ("You guessed in {0} attempts".format(total_guesses))
else:
print ("Sorry... The secret number was {0}".format(number))
● 49
Solution 26
The program listing is shown in Figure 4.30 (program: integrate). The integration is per-
formed inside function integrate. This function is divided into equal small segments be-
tween the required lower and upper limits. The area of each segment is calculated. The
total area is equal to the required integral of the function. The arguments of this function
are the function to be integrated, low and high limits, and the number of points to consider.
Figure 4.31 shows an example run of the program where the following integral is calculated
by using 100 segments and the result displayed on the Thonny screen:
● 50
1. Addition
2. Subtraction
3. Multiplication
4. Division
Choice:
Generate two random integer numbers between 1 and 1000 and ask the user to carry out
the required operation. Check the user answer and display CORRECT or INCORRECT.
Solution 27
Figure 4.32 shows the required program (Program: arithmetic). Functions are used for
the addition, subtraction, multiplication, and division. The number entered by the user is
checked and appropriate message is displayed.
import random
def addition():
n1 = random.randint(1, 1000)
n2 = random.randint(1, 1000)
print(n1, «+», n2, «= «)
user_answer = int(input(«Enter answer: «))
correct_answer = n1 + n2
return (user_answer, correct_answer)
def subtraction():
n1 = random.randint(1, 1000)
n2 = random.randint(1, 1000)
print(n1, «-», n2, «= «)
user_answer = int(input(«Enter answer: «))
correct_answer = n1 - n2
return (user_answer, correct_answer)
def multiplication():
n1 = random.randint(1, 1000)
n2 = random.randint(1, 1000)
print(n1, «X», n2, «= «)
user_answer = int(input(«Enter answer: «))
correct_answer = n1 * n2
return (user_answer, correct_answer)
def division():
n1 = random.randint(1, 1000)
n2 = random.randint(1, 1000)
● 51
print(« 1. Addition»)
print(« 2. Subtraction»)
print(« 3. Multiplication»)
print(« 4. Integer Division»)
ch = int(input(«Choice: «))
if ch == 1:
user,correct = addition()
elif ch == 2:
user,correct = subtraction()
elif ch == 3:
user,correct = multiplication()
else:
user,correct = division()
chk(user,correct)
The matplotlib library module must be installed in Python before it can be used. This is
done in command mode by entering the following command:
● 52
The graphics can only be drawn in GUI Desktop mode. You should therefore use the VNC
Viewer to get into the GUI mode and then create and run your program from there by se-
lecting Python 2 (IDLE). The program listing is as follows:
Figure 4.34 shows the graph plotted. Function linspace(0,4,100) creates a list 100 in-
teger numbers in x, starting from 0 and terminating at 4. Function plot draws the graph
where the y value is equal to x2 . Function show() physically displays the graph. Notice
that there are some buttons at the bottom of the window. These buttons are (from left to
right as shown in Figure 4.35):
Home: Clicking this button displays the default figure as in Figure 4.34
Back: Brings back the plot after zooming
Next: This button is opposite of Back button
Pan: This button moves the window coordinates
Zoom: This button selects a zoom window
Adjust: this button adjusts the plot parameters
Save: click to save the plot
● 53
The graph in Figure 4.34 can be made more user friendly by labeling the axes and giving a
title to the graph. The modified program is given below:
● 54
plt.plot(x, x**3,label="Cubic")
plt.xlabel("X values")
plt.ylabel("Y values")
plt.title("Graphs of linear, quadratic, and cubic functions")
plt.legend()
plt.show()
Function plot draws a smooth graph by joining the x,y values. You can also draw different
types of graphs. For example, function scatter draws a scatter graph as shown in Figure
4.38. The program for this graph is as follows:
● 55
Function bar draws a bar chart as shown in Figure 4.39. The program for this graph is as follows.
● 56
matplotlib is a large graphics library with many functions and the details of these func-
tions are beyond the scope of this book. Interested readers can find books, tutorials, and
applications notes on matplotlib on the Internet, for example,
https://matplotlib.org/faq/usage_faq.html
● 57
Chapter 5 • S
imple Projects for the Raspberry Pi
Zero 2 W
5.1 Overview
In this chapter you will be developing simple hardware projects with the Raspberry Pi Zero
2 W, using the nano text editor. The following sub-headings will be given for each project
where applicable:
• Title
• Description
• Aim
• Block diagram
• Circuit diagram
• PDL (where necessary)
• Program listing
• Suggestions for future work (where necessary)
All the programs in this chapter have been developed using the nano text editor, although
you can also use the Thonny IDE program if you prefer. A breadboard was used to construct
and test the projects where necessary.
Block diagram: Figure 5.1 shows the block diagram of the project. The colored header
connector is not shown in this diagram.
● 58
Circuit diagram: The circuit diagram of the project is shown in Figure 5.2, where the LED
is connected to port pin GPIO2 (pin 3) of Zero 2 W through a 470-ohm current limiting
resistor.
● 59
The required value of the current limiting resistor can be calculated as follows. In cur-
rent-sourcing mode, assuming the output High voltage is +3.3 V, the voltage drop across
the LED is 2 V, and the current through the LED is 3 mA, the required value of the current
limiting resistor R is:
Program listing: Figure 5.5 shows the program listing (Program: ExtFlash.py). At the
beginning of the program, the GPIO and time libraries are imported to the program and
warning messages are disabled. Then, BCM pin numbering is used so that, for example,
port pin GPIO2 is referenced as 2 and not as the physical pin number 3. The LED at GPIO2 is
configured as an output. A while loop is then formed which runs until stopped by the user.
Inside this loop, the LED is turned ON and OFF with one second delay between each output.
#---------------------------------------------------------
# FLASHING AN EXTERNAL LED
# ========================
#
# In this program an external LED is connected to port pin
# GPIO2 (pin 3). The LED is flashed every second
#
# Author: Dogan Ibrahim
# File : ExtFlash.py
# Date : December, 2022
#----------------------------------------------------------
import RPi.GPIO as GPIO # import GPIO library
import time # import time library
GPIO.setwarnings(False) # disable warning messages
GPIO.setmode(GPIO.BCM) # set BCM pin numbering
while True:
GPIO.output(LED, ON) # turn ON LED
time.sleep(1) # wait 1 second
GPIO.output(LED, OFF) # turn OFF LED
time.sleep(1) # wait 1 second
● 60
Assuming that you have created the program using the nano text editor, enter the follow-
ing statement in command mode to run the program:
The program is halted by entering CNTRL+C at the terminal. Although the program in
Figure 5.5 works perfectly well, terminating the program this way is not recommended. If
the warnings are not disabled, then a second run of the program will give error messages
since the GPIO buffers are not cleared.
Figure 5.6 shows the modified program (Program: ExtFlash2.py) where pressing CN-
TRL+C is detected and the program clears the GPIO buffers and terminates orderly. Notice
that it is not necessary to disable warnings in this version of the program.
#--------------------------------------------------------------
# FLASHING AN EXTERNAL LED
# ========================
#
# In this program an external LED is connected to port pin GPIO2
# (pin 3). The LED is flashed every second.
#
# This program detects CNTRL+C and terminates orderly
#
# Author: Dogan Ibrahim
# File : ExtFlash2.py
# Date : December, 2022
#----------------------------------------------------------------
import RPi.GPIO as GPIO # import GPIO library
import time # import time library
GPIO.setmode(GPIO.BCM) # set BCM pin numbering
try:
● 61
Figure 5.7 shows the project built with a resistor and an LED.
The block diagram and circuit diagram of this project are same as in Figure 5.1 and Figure
5.2 respectively.
Program listing. Figure 5.8 shows the program listing (Program: SOS.py). At the begin-
ning of the program, the dot, dash, and gap times are defined. Then a loop is formed using
a while statement. Inside this loop, three for loops are formed, each iterating three times.
The first loop displays three dots, the second loop, three dashes, and finally the last loop
displays three dots. This process is repeated after two seconds of delay.
#---------------------------------------------------------
# LED FLASHING SOS
# ================
#
# In this program the external LED at port GPIO2 flashes the
# SOS signal (... --- ...)
#
# Author: Dogan Ibrahim
# File : SOS.py
# Date : December, 2022
#----------------------------------------------------------
import RPi.GPIO as GPIO # import GPIO library
import time # import time library
● 62
Suggestions: You could easily replace the LED with a buzzer to make the SOS signal au-
dible. There are two types of buzzers: active and passive. Passive buzzers require an audio
signal to be sent to them and the frequency of the output signal depends on the frequency
of the supplied signal. Active buzzers are ON/OFF type devices and they produce audible
sound when activated. In his project you can use an active buzzer with a transistor switch
(any NPN type transistor can be used) as shown in Figure 5.9.
● 63
Note: You may find it easier to create and run your Python programs in Desktop mode
using Thonny since the correct Python indentation is automatically placed in your code
as you type the code.
Aim: The aim of this project is to show how 8 LEDs can be connected to the Zero 2 W GPIO
pins. In addition, the project shows how to group the LEDs as an 8-bit port and control
them as a single port.
Block diagram: The block diagram of the project is shown in Figure 5.10.
● 64
Circuit diagram: The circuit diagram of the project is shown in Figure 5.11. The LEDs are
connected to 8 GPIO pins through 470-ohm current limiting resistors. The following 8 GPIO
pins are grouped as an 8-bit port, where GPIO 2 is configured as the LSB and GPIO 9 is
configured as the MSB:
MSB LSB
GPIO: 9 10 22 27 17 4 3 2
Pin no: 21 19 15 13 11 7 5 3
● 65
Project PDL: PDL (Program Description Language) describes the operation of a pro-
gram in simple English-like statements. The project PDL is shown in Figure 5.13.
BEGIN
Import GPIO library
Import time library
CALL Configure Port to configure the port as output
Set cnt = 0
DO FOREVER
CALL Port_Output with cnt
Wait 1 second
Increment cnt
ENDDO
END
BEGIN/Configure_Port
IF port is output THEN
CALL GPIO.setup to configure the port as output
ELSE
CALL GPIO.setup to configure the port as input
ENDIF
END/Configure_Port
BEGIN/Port_Ouput
CALL GPIO.output to send the byte to the port
END/Port_Output
Program listing: The program is called LEDCNT.py and the listing is shown in Figure
5.14. The program was written using the nano text editor. At the beginning of the program
the RPi.GPIO and the time modules are imported to the project. Then the pin number-
ing is configured to use the BCM notation. All the 8 GPIO channels used in the project are
configured as outputs using function Configure_Port. Notice that the Configure_Port
function is general and list DIR sets the directions of the GPIO pins. An "O" sets as an
output and an "I" sets as an input. Then, a loop is formed to execute forever, and inside
this loop the LEDs count up by one in binary. Variable cnt is used as the counter. Function
Port_Output is used to control the LEDs. This function can take integer numbers from 0 to
255 and it converts the input number (x) into binary using the built-in function bin. Next,
the leading "0b" characters are removed from the output string b (bin function inserts
characters "0b" to the beginning of the converted string). Then, the converted string b is
made up of 8 characters by inserting leading 0s. The string is then sent to the PORT bit by
bit, starting from the most-significant bit (GPIO 9) position.
● 66
#-----------------------------------------------------------
#
# BINARY UP COUNTING LEDs
# =======================
#
# In this project 8 LEDs are connected to the following
# GPIO pins:
#
# 9 10 22 27 17 4 3 2
#
# The program groups these LEDs as an 8-bit port and then
# the LEDs count up in binary with one second delay between
# each output.
#
# Program: LEDCNT.py
# Date : December, 2022
# Author : Dogan Ibrahim
#------------------------------------------------------------
import RPi.GPIO as GPIO # import GPIO library
import time # import time library
GPIO.setwarnings(False) # disable warning messages
GPIO.setmode(GPIO.BCM) # set BCM pin numbering
PORT = [9, 10, 22, 27, 17, 4, 3, 2] # port connections
DIR = ["0","0","0","0","0","0","0","0"] # port directons
#
# This function configures the port pins as outputs ("0") or
# as inputs ("I")
#
def Configure_Port():
for i in range(0, 8):
if DIR[i] == "0":
GPIO.setup(PORT[i], GPIO.OUT)
else:
GPIO.setup(PORT[i], GPIO.IN)
return
#
# This function sends 8-bit data (0 to 255) to the PORT
#
def Port_Output(x):
b = bin(x) # convert into binary
b = b.replace("0b", "") # remove leading "0b"
diff = 8 - len(b) # find the length
for i in range (0, diff):
● 67
#
# Main program loop. Count up in binary every second
#
cnt = 0
while True:
Port_Output(cnt) # send cnt to port
time.sleep(1) # wait 1 second
cnt = cnt + 1 # increment cnt
Recommended modifications: Modify the program such that the LEDs count down every
two seconds.
The block diagram and circuit diagram of this project are as in Figure 5.10 and Figure 5.11
respectively.
BEGIN
Import GPIO library
Import time library
Import random number library
CALL Configure_Port to configure the port as output
DO FOREVER
● 68
BEGIN/Configure_Port
IF port is output THEN
CALL GPIO.setup to configure the port as output
ELSE
CALL GPIO.setup to configure the port as input
ENDIF
END/Configure_Port
BEGIN/Port_Ouput
CALL GPIO.output to send the byte to the port
END/Port_Output
Program listing: The program is called XMAS.py and the listing is shown in Figure 5.16.
The program was written using the nano text editor. At the beginning of the program, the
RPi.GPIO, time, and random modules are imported to the project. Then, the pin num-
bering is configured to use the BCM notation. All the 8 GPIO channels used in the project
are configured as outputs using function Configure_Port as in the previous project. Then,
a loop is formed to execute forever, and inside this loop a random number is generated be-
tween 1 and 255. This number is used as an argument conveyed to function Port_Output.
The binary pattern corresponding to the generated number is sent to the port which turns
the LEDs ON or OFF in a random manner.
#-----------------------------------------------------------
#
# CHRISTMAS LIGHTS
# ================
#
# In this project 8 LEDs are connected to the Raspberry Pi 3
# and these LEDs flash randomly at 0.5 second intervals. The
# connections of the LEDs are to the following GPIO pins:
#
# 9 10 22 27 17 4 3 2
#
# The program groups these LEDs as an 8-bit port and then
# generates random numbers between 1 and 255 and turns the
# LEDs ON and OFF depending on the generated number.
● 69
#
# Program: XMAS.py
# Date : December, 2022
# Author : Dogan Ibrahim
#------------------------------------------------------------
import RPi.GPIO as GPIO # import GPIO library
import time # import time library
import random # import random library
GPIO.setwarnings(False) # disable warning messages
GPIO.setmode(GPIO.BCM) # set BCM pin numbering
PORT = [9, 10, 22, 27, 17, 4, 3, 2] # port connections
DIR = ["0","0","0","0","0","0","0","0"] # port directons
#
# This function configures the port pins as outputs ("0") or
# as inputs ("I")
#
def Configure_Port():
for i in range(0, 8):
if DIR[i] == "0":
GPIO.setup(PORT[i], GPIO.OUT)
else:
GPIO.setup(PORT[i], GPIO.IN)
return
#
# This function sends 8-bit data (0 to 255) to the PORT
#
def Port_Output(x):
b = bin(x) # convert into binary
b = b.replace("0b", "") # remove leading "0b"
diff = 8 - len(b) # find the length
for i in range (0, diff):
b = "0" + b # insert leading os
● 70
#
# Main program loop. Count up in binary every second
#
while True:
numbr = random.randint(1, 255) # generate a random number
Port_Output(numbr) # send cnt to port
time.sleep(0.5) # wait 0.5 second
Recommended modifications: Modify the program such that 10 LEDs can be connected
to the Zero 2 W and flashed randomly.
Block diagram: The block diagram of the project is shown in Figure 5.17.
Circuit diagram: The circuit diagram of the project is shown in Figure 5.18. The LEDs are
connected to 8 GPIO pins through 470-ohm current limiting resistors as in the previous
project. The pushbutton switch is connected to GPIO 11 (pin 23) of the Zero 2 W. The push-
button switch is connected through a 10 k-ohm resistor. When the switch is not pressed,
the input is at logic 1. When the switch is pressed the input changes to logic 0.
● 71
BEGIN
Import GPIO library
Import time library
CALL Configure_Port to configure the port as output
Configure GPIO 11 as input
Set rot = 1
DO FOREVER
IF button is pressed THEN
Shift rot left
ELSE
Shift rot right
ENDIF
CALL Port_Output to send rot to the LEDs
Wait one second
ENDDO
END
BEGIN/Configure_Port
IF port is output THEN
CALL GPIO.setup to configure the port as output
ELSE
CALL GPIO.setup to configure the port as input
ENDIF
END/Configure_Port
● 72
BEGIN/Port_Ouput
CALL GPIO.output to send the byte to the port
END/Port_Output
Program listing: The program is called rotate.py and the listing is shown in Figure 5.20.
The program was written using the nano text editor. At the beginning of the program,
the RPi.GPIO, and time modules are imported to the project. Then, the pin numbering is
configured to use the BCM notation. All the 8 GPIO channels used in the project are con-
figured as outputs using function Configure_Port as in the previous project. Then, a loop
is formed to execute forever and inside this loop variable rot is used as an argument to
the Port_Output function. If the button is not pressed, then rot is shifted right and the
LED ON sequence is from left to right (from MSB to LSB). If, on the other hand, the button
is pressed, then the LED On sequence is from right to left (from LSB to MSB). A 1-second
delay is inserted between each output.
#------------------------------------------------------------------
#
# ROTATING LEDs WITH PUSH-BUTTON
# ==============================
#
# In this project 8 LEDs are connected to the Raspberry Pi 3.
# In addition, a push-button switch is connected to GPIO 11
# (pin 23) through resistors. Normally the output of the button
# is at logic 1 and goes to logic 0 when the button is pressed.
# The LEds rotate in one direction when the button is not pressed
# and in the opposite direction when the button is pressed.
#
# Connections of the LEDs are to the following GPIO pins:
#
# 9 10 22 27 17 4 3 2
#
# On second delay is inserted between each output.
#
# Program: rotate.py
# Date : December, 2022
# Author : Dogan Ibrahim
#--------------------------------------------------------------------
import RPi.GPIO as GPIO # import GPIO library
import time # import time library
GPIO.setwarnings(False) # disable warning messages
GPIO.setmode(GPIO.BCM) # set BCM pin numbering
PORT = [9, 10, 22, 27, 17, 4, 3, 2] # port connections
DIR = ["0","0","0","0","0","0","0","0"] # port directions
● 73
#
# This function configures the port pins as outputs ("0") or
# as inputs ("I")
#
def Configure_Port():
for i in range(0, 8):
if DIR[i] == "0":
GPIO.setup(PORT[i], GPIO.OUT)
else:
GPIO.setup(PORT[i], GPIO.IN)
return
#
# This function sends 8-bit data (0 to 255) to the PORT
#
def Port_Output(x):
b = bin(x) # convert into binary
b = b.replace("0b", "") # remove leading "0b"
diff = 8 - len(b) # find the length
for i in range (0, diff):
b = "0" + b # insert leading os
#
# Main program loop. Rotate the LEDs
#
rot = 1
while True:
Port_Output(rot)
time.sleep(1) # wait 1 second
if GPIO.input(11) == 0: # button pressed?
rot = rot << 1 # shift left
if rot > 128: # at the end
● 74
Block diagram: The block diagram of the project is shown in Figure 5.21.
Circuit diagram: The circuit diagram of the project is shown in Figure 5.22 where an ac-
tive buzzer is connected to GPIO 2 of the Zero 2 W.
● 75
Project PDL: In a Morse code, each letter is made up of dots and dashes. Figure 5.23
shows the Morse code of all the letters in the English alphabet (this table can be extended
by adding the Morse code of numbers and punctuation marks). The following rules apply to
the timing of dots and dashes:
• The duration of a dot is taken as the unit time and this determines the speed
of the transmission. Normally the speed of transmission is quoted in words
per minute (wpm). The standard required minimum in Morse code based
communication is 12 wpm.
In this project the Morse code is simulated at 10 wpm. Thus, the unit time is taken to be
1200 / 10 = 120 ms.
● 76
U : ..-
V : ...-
W : .--
X : -..-
Y : -.--
Z : --..
BEGIN
Import GPIO library
Import time library
Configure channel 2 as an output pin
DO until text QUIT is received
Read text from the keyboard
IF space detected (inter-word character) THEN
CALL Do_SPACE
ELSE
DO for all letters of the text
Find the Morse code
IF the code contains a dot THEN
CALL DO_DOT
ELSE IF code contains a dash THEN
CALL DO_DASH
ENDIF
ENDDO
Wait 2 seconds
ENDDO
Cleanup the I/O resources used
END
BEGIN/DO_DOT
Send 1 to GPIO pin 2
Wait 120ms (unit time)
Send 0 to GPIO pin 2
Wait 120ms (unit time)
END/DO_DOT
BEGIN/DO_DASH
Send 1 to GPIO pin 2
Wait 360ms (3 x unit time)
Send 0 to GPIO pin 2
● 77
BEGIN/DO_SPACE
Wait 7 unit time
END/DO_SPACE
Program listing: The program is called morse.py and the listing is shown in Figure 5.25.
At the beginning of the program, the RPi.GPIO and the time modules are imported to the
project. Then the pin numbering is configured to use the BCM notation. GPIO 2 is config-
ured as an output pin and this is where the buzzer is connected to. The Morse code alphabet
is stored in list Morse_Code. Function DO_DOT implement a single dot with a duration of
one unit time. Function DO_DASH implement a single dash with duration of 3 unit times.
Function DO_SPACE implements a space character with a duration of 7 unit times. The rest
of the program is executed in a loop where a text is read from the keyboard and the buzzer
sounds in such a way to represent the Morse code of this text. The program terminates if
the user enters the text QUIT.
You should run the program from the command mode as follows:
#-----------------------------------------------------------------
#
# MORSE CODE EXERCISER
# ====================
#
# This project can be used to learn the Morse code. A buzzer is
# connected to GPIO 2 of the Zero 2 W.
#
# The program reads a text from the keyboard and then sounds the
# buzzer to simulate sending or receiving the Morse code of this
# text.
#
# In this project the Morse code speed is assumed to be 10 wpm,
# but can easily be changed by changing the parameter wpm.
#
# File : morse.py
# Date : December, 2022
# Author: Dogan Ibrahim
#-----------------------------------------------------------------
import RPi.GPIO as GPIO # import GPIO module
● 78
Pin = 2
words_per_minute = 10 # define words per min
wpm = 1200/words_per_minute # unit time in milliseconds
unit_time = wpm / 1000
Morse_Code = {
'A': '.-',
'B': '-...',
'C': '-.-.',
'D': '-..',
'E': '.',
'F': '..-.',
'G': '--.',
'H': '....',
'I': '..',
'J': '.---',
'K': '-.-',
'L': '.-..',
'M': '--',
'N': '-.',
'O': '---',
'P': '.--.',
'Q': '--.-',
'R': '.-.',
'S': '...',
'T': '-',
'U': '..-',
'V': '...-',
'W': '.--',
'X': '-..-',
'Y': '-.--',
'Z': '--..'
}
#
# This function sends a DOT (unit time)
#
def DO_DOT():
GPIO.output(Pin, 1)
● 79
time.sleep(unit_time)
GPIO.output(Pin, 0)
time.sleep(unit_time)
return
#
# This function sends a DASH ( 3*unit time)
#
def DO_DASH():
GPIO.output(Pin, 1)
time.sleep(3*unit_time)
GPIO.output(Pin, 0)
time.sleep(unit_time)
return
#
# This function sends inter-word space (7*unit time)
#
def DO_SPACE():
time.sleep(7*unit_time)
return
#
# Main program code
#
text = ""
while text != "QUIT":
text = input("Enter text to send: ")
if text != "QUIT":
for letter in text:
if letter == ' ':
DO_SPACE()
else:
for code in Morse_Code[letter.upper()]:
if code == '-':
DO_DASH()
elif code == '.':
DO_DOT()
time.sleep(unit_time)
time.sleep(2)
Recommended Modifications: An LED can be connected to the GPIO pin instead of the
buzzer so that the Morse code can be seen in visual form.
● 80
Block diagram: The block diagram of the project is shown in Figure 5.26.
Figure 5.27 shows the LEDs that should be turned ON to display the 6 dice face numbers.
Circuit diagram: The circuit diagram of the project is shown in Figure 5.28. Here, 8 GPIO
pins are collected to form a PORT. The following pins are used for the LEDs (there are 7
LEDs, but 8 port pins are used in the form of a byte where the most-significant bit position
is not used):
PORT bit 7 6 5 4 3 2 1 0
GPIO: 9 10 22 27 17 4 3 2
● 81
BEGIN
Import GPIO library
Import time library
Import random library
Configure GPIO 11 as input
Create DICE_NO list for LED bit patterns
CALL Configure_Port to configure the PORT as output
Declare callback handler (DICE) on pin GPIO 11
DO FOREVER
Wait for the button to be pressed
ENDDO
END
BEGIN/Configure_Port
IF port is output THEN
CALL GPIO.setup to configure the port as output
ELSE
CALL GPIO.setup to configure the port as input
ENDIF
END/Configure_Port
BEGIN/Port_Ouput
● 82
BEGIN/DICE
Generate a random number between 1 and 6
Get the LED bit pattern corresponding to this number
CALL Port_Output to send the data to the LEDs
Wait 3 seconds
Turn OFF all LEDs
END/DICE
Table 5.1 gives the relationship between a dice number and the corresponding LEDs to be
turned ON to imitate the faces of a real dice. For example, to display number 1 (i.e., only
the middle LED is ON), you have to turn LED D3 ON. Similarly, to display number 4, you
have to turn ON D0, D2, D4 and D6.
1 D3
2 D0, D6
3 D0, D3, D6
The relationship between the required number and the data to be sent to the PORT to turn
on the correct LEDs is given in Table 5.2. For example, to display dice number 2, you have
to send hexadecimal 0x22 to the PORT. Similarly, to display number 5, you have to send
hexadecimal 0x5D to the PORT, and so on.
Program listing: The program is called dice.py and the listing is shown in Figure 5.30.
● 83
At the beginning of the program, the RPi.GPIO, time and random modules are imported
to the project. Then, port pins are declared as a list in variable PORT, and the direction of
each pin is declared as output ("O") in a list variable called DIR. The bit pattern to be sent
to the LEDs corresponding to each dice number is stored in hexadecimal format in a list
called DICE_NO (see Table 5.2).
The pin numbering is configured to use the BCM notation. GPIO 11 is configured as an input
pin and the pushbutton switch is connected to this pin to simulate the throwing of a dice.
A callback routine called DICE is created so that when the button is pressed, the program
jumps to this function. The callback function is set up to trigger when the button is pressed
(i.e., when it goes from logic 1 to 0). Switch debouncing is also used in the callback routine.
Inside the callback function, a random number is generated between 1 and 6. Then, the
list called DICE_NO is used to find the LEDs that should be turned ON, and the required
bit pattern is sent to the PORT to display the dice number. The program displays the dice
number for 3 seconds and then all the LEDs are turned OFF to indicate that the program is
ready for the next game.
#------------------------------------------------------------------
#
# ELECTRONIC DICE
# ===============
#
# This program is an electronic dice. GPIO 11 of Zero 2 W is
# configured as an input and a push-button switch is connected to
# this port pin. When the button is pressed a random dice number is
# displayed between 1 and 6 on the LEDs.
#
# 7 LEDs are mounted on the breadboard in the form of the face of
# a real dice. The following GPIO pins are used for the LEDs (bit
# 7 is mot used):
#
# Port pin: 7 6 5 4 3 2 1 0
# GPIO : 10 22 27 17 4 3 2
#
# The following PORT pins are used to construct the dice:
#
# D0 D4
# D1 D3 D5
# D2 D6
#
# Program: dice.py
# Date : December, 2022
# Author : Dogan Ibrahim
#------------------------------------------------------------------
import RPi.GPIO as GPIO # import GPIO library
● 84
#
# This function configures the port directions
#
def Configure_Port():
for i in range (0, 8):
GPIO.setup(PORT[i], GPIO.OUT)
return
#
# This function sends a byte (8-bit) data to the PORT
#
def Port_Output(x):
b = bin(x) # convert into binary
b = b.replace("0b", "") # remove leading 0b
diff = 8 - len(b) # find the difference
for i in range (0, diff):
b = "0" + b # insert leading 0s
#
# The program jumps here after the button is pressed
#
def DICE(dummy):
n = random.randint(1, 6) # generate a random number
pattern = DICE_NO[n] # find the pattern
Port_Output(pattern) # turn ON required LEDs
time.sleep(3) # wait for 3 seconds
Port_Output(0) # turn OFF all LEDs
return
● 85
GPIO.setup(Dice_Pin, GPIO.IN)
#
# Configure PORT as outputs
#
Configure_Port()
#
# Setup callback to function DICE when the button is pressed
#
GPIO.add_event_detect(Dice_Pin, GPIO.FALLING, bouncetime=50,
callback=DICE)
#
# Program waits here for the button to be pressed, then a random
# number is generated between 1 and 6 and is displayed on the LEDs
#
while True:
pass # Do nothing
Background: PWM waves are frequently used in power control applications. The waveform
is basically a positive squarewave with variable ON and OFF times. As shown in Figure 5.31,
the total of the ON and OFF times is known as the period of the waveform. The ratio of the
ON time to the period is known as the Duty Cycle and it is represented as a percentage. i.e.,
where T is the ON time, and P, the period (ON time + OFF time).
● 86
By varying the duty cycle from 0% to 100% you can easily control a load, say, a motor. For
example, at 50% duty cycle the load receives half of the total power. Similarly, at 100%
duty cycle the load receives full power.
The average value of the voltage applied to the load can be calculated by considering a
general PWM waveform shown in Figure 5.31. The average value A of waveform f(t) with
period T and peak value ymax and minimum value ymin is calculated from:
or
or
As it can be seen from the above equation, the average value of the voltage supplied to
the load is directly proportional to the duty cycle of the PWM waveform and by varying the
duty cycle you control the average load voltage. Figure 5.32 shows the average voltage for
different values of the duty cycle.
● 87
It is interesting to notice that with correct low-pass filtering, the PWM can be used as a DAC
if the MCU does not have a DAC channel. By varying the duty cycle you can effectively vary
the average analog voltage supplied to the load.
Block diagram: The block diagram of the project is shown in Figure 5.33.
Circuit diagram: The circuit diagram of the project is shown in Figure 5.34. Buttons
BRIGHTER and DIMMER are connected to port pins GPIO 2 (pin 3) and GPIO 3 (pin 5) re-
spectively. The LED is connected to port pin GPIO 4 (pin 7).
● 88
Program listing: The program is called pwm.py, and its listing is shown in Figure 5.35. At
the beginning of the program, the RPi.GPIO module is imported to the project. Ports GPIO
2 and GPIO 3 are configured as inputs and LED port (GPIO 4) is configured as output. The
default state of the buttons is logic 1 and they go to logic 0 when pressed.
GPIO pin 4 is configured as a PWM port with a frequency of 200 Hz using the following
statement:
P = GPIO.PWM(LED, 200)
Then, the PWM is started with 50% Duty Cycle using the statement:
p.start(Duty)
Inside the program loop the state of both buttons are checked. Every time button BRIGHT-
ER is pressed, the Duty Cycle is incremented by 5 until it reaches to maximum (100%).
Similarly, every time button DIMMER is pressed, the Duty Cycle is decremented by 5 until
it reaches the minimum (0%). The program runs until stopped by the user.
#-----------------------------------------------------------------------
# LED BRIGHTNESS CONTROL
# ======================
#
# In this program two buttons and an LED are used. Pressing button
● 89
GPIO.setmode(GPIO.BCM)
BRIGHTER = 2 # button BRIGHTER
DIMMER = 3 # button DIMMER
LED = 4 # LED
● 90
Block diagram: Figure 5.36 shows the block diagram of the project.
Circuit diagram: The circuit diagram of the project is shown in Figure 5.37, where 7 LEDs
are connected to the Zero 2 W through current limiting resistors. The button is connected to
GPIO11 (pin 23). Normally, the output of the button is at logic 1 and goes to logic 0 when
the button is pressed.
● 91
Program listing: Figure 5.38 shows the program listing (Program: LuckyDay.py). At the
beginning of the program, all the 8 LED GPIO pins are combined into a single port and is
addressed as a single 8-bit port using function PORT_Output. Notice that the system date
and time are jointly used as the seed value to the random number generator function so
that different values are available every time the program is started. An integer random
number is generated between 1 and 7 and this number is used to turn ON one of the LEDs
corresponding to a day of the week.
#--------------------------------------------------------------
# LUCKY DAY OF THE WEEK
# =====================
#
# In this program 7 LEDs are connected to Zero 2 W where each
# LED represents a day of the week. Pressing a button
# turns ON one of the LEDs randomly and this corresponds to
# your lucky day of the week
#
# Author: Dogan Ibrahim
# File : LuckyDay.py
# Date : December, 2022
#---------------------------------------------------------------
import RPi.GPIO as GPIO # import GPIO library
import time # import time library
GPIO.setwarnings(False) # disable warning messages
GPIO.setmode(GPIO.BCM) # set BCM pin numbering
import random # random no
from datetime import datetime
● 92
GPIO.setup(BUTTON, GPIO.IN)
#
# This function configures the port pins as outputs ("0") or
# as inputs ("I")
#
def Configure_Port():
for i in range(0, 8):
if DIR[i] == "0":
GPIO.setup(PORT[i], GPIO.OUT)
else:
GPIO.setup(PORT[i], GPIO.IN)
return
#
# This function sends 8-bit data (0 to 255) to the PORT
#
def Port_Output(x):
b = bin(x) # convert into binary
b = b.replace("0b", "") # remove leading "0b"
diff = 8 - len(b) # find the length
for i in range (0, diff):
b = "0" + b # insert leading os
#
# Main program loop, check if Button is pressed
#
print("Press the Button to display your lucky number...")
dt = datetime.today()
seconds = dt.timestamp()
random.seed(seconds)
● 93
Block Diagram: Figure 5.39 shows the block diagram of the project.
Circuit Diagram: The I2C LCD has 4 pins: GND, +V, SDA, and SCL. SDA is connected to
pin GPIO 2 and SCL is connected to pin GPIO 3. The +V pin of the display should be con-
nected to +5 V (pin 2) on the Zero 2 W. Notice that Zero 2 W pins are not +5 V tolerant,
but the I2C LCD operates with +5 V where its SDA and SCL pins are pulled to +5 V. It is
not a good idea to connect the LCD directly to the Zero 2 W as it can damage the latter"s
I/O circuitry. There are several solutions here. One solution is to remove the I2C pull-up
resistors on the LCD module. The other option is to use an I2C device which does operate
at +3.3 V. The other solution is to use a bidirectional +3.3 V to +5 V logic level converter
chip. In this project, you will use the TXS0102 bidirectional logic level converter chip like
the one shown in Figure 5.40. The circuit diagram of the project is shown in Figure 5.41.
● 94
The LCD used in this project is based on the I2C interface. I2C is a multi-slave, multi-mas-
ter, single-ended serial bus used to attach low-speed peripheral devices to microcontrollers.
The bus consists of only two wires called SDA and SCL where SDA is the data line and SCL is
the clock line and up to 1008 slave devices can be supported on the bus. Both lines must be
pulled up to the supply voltage by suitable resistors. The clock signal is always generated
by the bus master. The devices on the I2C bus can communicate at 100 kHz or 400 kHz.
Figure 5.42 shows the front and back of the I2C based LCD. Notice that the LCD has a
small board mounted at its back to control the I2C interface. The LCD contrast is adjusted
through the small potentiometer mounted on this board. A jumper is provided on this board
to disable the backlight if required.
● 95
Program Listing: Before using the I2C pins of the Zero 2 W you have to enable the I2C
peripheral interface on the device. The steps for this are as follows:
Now you have to install the I2C library on your Zero 2 W. The steps are as follows:
• Connect the I2C display to your Zero 2 W and enter the following command to
test the installation and LCD hardware address:
You should see a table similar to the one shown below. A number in the table
means that the LCD has been recognized correctly and the I2C slave address of the
LCD is shown in the table. In this example, the LCD address is 27:
1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
● 96
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
Now install an I2C LCD library so you can send commands and data to your LCD. There are
many Python libraries available for the I2C type LCDs. The one chosen here is called the
RPLCD and it can be installed as follows:
The I2C LCD library supports the following functions (see the RPLCD I2C LCD library docu-
mentation for more details):
Alternatively, if you have used the Thonny IDE, then just run the program.
#---------------------------------------
#
# LCD TEST PROGRAM
# ================
#
# Author: Dogan Ibrahim
# File : lcdtest.py
# Date : December, 2022
#---------------------------------------
from RPLCD.i2c import CharLCD
lcd=CharLCD('PCF8574', 0x27)
lcd.clear()
● 97
lcd.home
lcd.write_string("MY LCD")
You are now all set to write your program. Figure 5.44 shows the program listing (lcd.py).
At the beginning of the program, libraries RPi.GPIO, timer, and the LCD driver library are
all imported to the program. The heading SECONDS COUNTER is displayed for 2 seconds.
The program then clears the LCD screen and enters into an infinite loop. Inside this loop,
variable cnt is incremented every second and the total value of cnt is displayed on the LCD
continuously.
#---------------------------------------------------------
# I2C LCD SECONDS COUNTER
# =======================
#
# In this program an I2C LCD is connected to the Zero 2 W.
# The program counts up in seconds and displays on the LCD.
#
# At the beginning of the program the text SECONDS COUNTER is
# displayed for 2 seconds
#
# Program: lcd.py
# Date : December, 2022
# Author : Dogan Ibrahim
#----------------------------------------------------------
import time
from RPLCD.i2c import CharLCD
lcd=CharLCD('PCF8574', 0x27) # Init LCD
● 98
Block Diagram: Figure 5.45 shows the block diagram of the project.
Circuit Diagram: The dual MCP3002 ADC chip is used in this project to provide analog
input capability to the Zero 2 W. This chip has the following features:
The MCP3002 is a successive approximation 10-bit ADC with on-chip sample and hold
amplifier. The device is programmable to operate as either differential input pair or as dual
single-ended inputs. The device is offered in 8-pin package. Figure 5.46 shows the pin con-
figuration of the MCP3002.
● 99
In this project, the supply voltage and the reference voltage are set to +3.3 V. Thus, the
digital output code is given by:
each quantization level corresponds to 3300 mV / 1024 = 3.22 mV. Thus, for example,
input data "00 0000001" corresponds to 3.22 mV, "00 0000010" corresponds to 6.44 mV,
and so on.
The MCP3002 ADC has two configuration bits: SGL/DIFF and ODD/SIGN. These bits follow
the sign bit and are used to select the input channel configuration. The SGL/DIFF is used
to select single ended or pseudo-differential mode. The ODD/SIGN bit selects which chan-
nel is used in single ended mode and is used to determine polarity in pseudo-differential
mode. In this project, you are using channel 0 (CH0) in single-ended mode. According to
the MCP3002 datasheet, SGL/DIFF and ODD/SIGN must be set to 1 and 0, respectively.
Figure 5.47 shows the circuit diagram of the project. A type TMP36DZ analog temperature
sensor chip is connected to CH0 of the ADC. TMP36DZ is a 3 terminal small sensor chip
with pins: Vs, GND, and Vo. Vs is connected to +3.3V, GND is connected to system ground,
and Vo is the analog output voltage. The temperature in degrees Centigrade is given by:
The CS, Dout, CLK, and Din pins of the ADC are connected to SPI pins CE0, MISO, SCLK,
and MOSI pins of the Raspberry Pi 3, respectively.
● 100
Program listing: Figure 5.48 shows the program listing (program: tmp36.py). The func-
tion get_adc_data is used to read the analog data, where the channel number (chan-
nel_no) is specified in the function argument as 0 or 1. Notice that you have to send the
start bit, followed by the SGL/DIFF and ODD/SIGN bits and the MSBF bit to the chip.
It is recommended to send leading zeroes on the input line before the start bit. This is often
done when using microcontroller-based systems that are required to send 8 bits at a time.
The following data can be sent to the ADC (SGL/DIFF = 1 and ODD/SIGN = channel_no) as
bytes with leading zeroes for more stable clock cycle. The general data format is:
For channel 0: 0000 0001 1000 0000 0000 0000 (0x01, 0x80, 0x00)
For channel 1: 0000 0001 1100 0000 0000 0000 (0x01, 0xC0, 0x00)
Notice that the second byte can be sent by adding 2 to the channel number (to make it 2
or 3) and then shifting 6 bits to the left as shown above to give 0x80 or 0xC0.
The chip returns 24 bit data (3 bytes) and you must extract the correct 10 bit ADC data
from this 24 bit data. The 24 bit data is in the following format ("X" is a don"t-care bit):
Assuming that the returned data is stored in 24 bit variable ADC, you have:
● 101
Thus, you can extract the 10 bit ADC data with the following operations:
and
(ADC[1] & 15) << 6) so, high byte = "DD DD00 0000"
Adding the low byte and the high byte you get the 10-bit converted ADC data as:
DD DDDD DDDD
Function Description
xfer2([array of bytes]) Send an array of bytes to the device with CEx asserted
at all times
xfer([array of bytes]) Send an array of bytes de-asserting and asserting CEx
with every byte transmitted
The module spidev must be imported at the beginning of the program before any of the
above functions are called. Also, you must enable the SPI interface on your Zero 2 W in the
configuration menu. The steps are:
● 102
At the beginning of the program in Figure 5.48, modules RPi.GPIO and spidev are imported
to the program and an instance of the SPI is created. Function get_adc_data reads the
temperature from sensor chip MCP3002 and returns a digital value comprised between 0
and 1023. This value is then converted into millivolts, 500 is subtracted from it, and the
result is divided by 10 to find the temperature in degrees Centigrade. The temperature is
displayed on the monitor every second.
#---------------------------------------------------------------
# ANALOG TEMPERATURE SENSOR
# =========================
#
# In this project a TMP36 type analog temperature chip is used
# to measure the ambient temperature. The temperature is read
# using a MCP3002 type ADC chip. The result is converted into
# degrees Centigrade and is displayed on the monitor
#
# Program: tmp36.py
# Date : December, 2022
# Author : Dogan Ibrahim
#----------------------------------------------------------------
import RPi.GPIO as GPIO
import spidev
import time
GPIO.setwarnings(False)
#
# Create SPI instance and open the SPI bus
#
spi = spidev.SpiDev()
spi.open(0,0) # we are using CE0 for CS
spi.max_speed_hz = 4000
GPIO.setmode(GPIO.BCM)
#
# This function returns the ADC data read from the MCP3002
#
def get_adc_data(channel_no):
ADC = spi.xfer2([1, (2 + channel_no) << 6, 0])
rcv = ((ADC[1] & 15) << 6) + (ADC[2] >> 2)
return rcv
● 103
#
# Start of main program. Read the analog temperature, convert
# into degrees Centigrade and display on the monitor every second
#
while True:
adc = get_adc_data(0)
mV = adc * 3300.0 / 1023.0 # convert to mV
Temp = (mV - 500.0) / 10.0 # temperature in C
print("Temperature = %5.2f " %Temp) # display temperature
time.sleep(1) # wait one second
Block diagram: Figure 5.50 shows the block diagram of the project
Circuit diagram: The circuit diagram is shown in Figure 5.51. The I2C LCD is connected
● 104
to Zero 2 W using a voltage translator chip. The ADC chip is connected as in the previous
project.
Program listing: Figure 5.52 shows the program listing (Program: tmp36lcd.py). The
program is similar to the one in Figure 5.48 but here an I2C LCD is used to display the
temperature. At the beginning of the program, the LCD library and other libraries used in
the program are imported. The LCD is configured to 16 characters and 2 rows. Inside the
program loop, the temperature is read from TMP36DZ via the ADC and gets converted into
degrees Celsius and subsequently displayed on the LCD.
#---------------------------------------------------------------
# ANALOG TEMPERATURE SENSOR - LCD OUTPUT
# ======================================
#
# In this project a TMP36 type analog temperature chip is used
# to measure the ambient temperature. The temperature is read
# using a MCP3002 type ADC chip. The result is converted into
# degrees Centigrade and is displayed on I2C LCD
#
# Program: tmp36lcd.py
# Date : December, 2022
# Author : Dogan Ibrahim
#----------------------------------------------------------------
import RPi.GPIO as GPIO
import spidev
import time
from RPLCD.i2c import CharLCD
lcd=CharLCD('PCF8574', 0x27)
GPIO.setwarnings(False)
#
# Create SPI instance and open the SPI bus
● 105
#
spi = spidev.SpiDev()
spi.open(0,0) # we are using CE0 for CS
spi.max_speed_hz = 4000
GPIO.setmode(GPIO.BCM)
#
# This function returns the ADC data read from the MCP3002
#
def get_adc_data(channel_no):
ADC = spi.xfer2([1, (2 + channel_no) << 6, 0])
rcv = ((ADC[1] & 15) << 6) + (ADC[2] >> 2)
return rcv
lcd.clear()
lcd.home()
lcd.write_string("TEMP - TMP36")
time.sleep(2)
#
# Start of main program. Read the analog temperature, convert
# into degrees Centigrade and display on the monitor every second
#
while True:
adc = get_adc_data(0)
lcd.clear()
lcd.home()
lcd.write_string("Temperature") # heading
lcd.cursor_pos = (1, 0) # cursor at (1, 0)
mV = adc * 3300.0 / 1023.0 # convert to mV
Temp = (mV - 500.0) / 10.0 # temperature in C
T = str(Temp)[:5]
lcd.write_string(T) # display temperature
time.sleep(2) # wait two seconds
● 106
Block Diagram: Figure 5.54 shows the block diagram of the project.
Circuit Diagram: The circuit diagram of the project is simple (Figure 5.55), consisting of
an LED and a pushbutton switch. The LED and the button are connected to GPIO 2 and
GPIO 3 port pins respectively. The button is connected such that by default its output is at
logic 1, and goes to logic 0 when pressed.
Program listing: The program is called reaction.py and its listing is given in Figure 5.56.
At the beginning of the program, RPi.GPIO, time, and random libraries are imported. The
● 107
button is configured as an input and the LED, as an output. The program runs in a loop
where the system time is recorded as soon as the LED is turned ON. The program waits
for the user to press the button, and the system time is read again at this moment. The
difference between this time and the first time is displayed as the reaction time of the user.
This process repeats after a random delay of 1 to 10 seconds. Notice that the floating-point
function time.time() returns the time in seconds since the epoch.
#----------------------------------------------------------
# REACTION TIMER
# ==============
#
# This is a reaction timer program. The user presses a button
# as soon as he/she see a light. The time between seeing the
# light and pressing the button is measured and is displayed
# in milliseconds as the reaction time of the user. The light
# comes ON after a random number of seconds between 1 and 10
# seconds.
#
# Program: reaction.py
# Date : December, 2022
# Author : Dogan Ibrahim
#-----------------------------------------------------------
import RPi.GPIO as GPIO
import time
import random
#
# LED is output, button is input
#
GPIO.setup(Button, GPIO.IN)
GPIO.setup(LED, GPIO.OUT)
#
# Start of main program
#
while True:
T = random.randint(1, 10)
time.sleep(T)
● 108
GPIO.output(LED, 1)
start_time = time.time() # start time
while (GPIO.input(Button) == 1): # wait until button pressed
pass
end_time = time.time()
diff_time = 1000.0*(end_time - start_time)
diff_int = int(diff_time)
print("Reaction time=%d " %diff_int)
GPIO.output(LED, 0)
time.sleep(3)
Block Diagram: Figure 5.58 shows the block diagram of the project.
● 109
Circuit Diagram: A pair of U/S sensors are used to sense the distance both at the front
and at the rear of a vehicle. The outputs of the ultrasonic sensors are at +5 V and therefore
are not compatible with the inputs of Zero 2 W. Resistive potential divider circuits are used
to lower the voltage to +3.3 V. The voltage at the output of the potential divider resistor is:
In this project, type HC-SR04 ultrasonic transmitter/receiver modules are used (see Fig-
ure 5.59). These modules have the following specifications:
Vcc: +V power
Trig: Trigger input
Echo: Echo output
Gnd: Power ground
● 110
Therefore,
or,
Figure 5.60 shows the principle of operation of the ultrasonic sensor module. For exam-
ple, if the time to receive the echo is 294 microseconds, then the distance to the object is
calculated as:
Figure 5.61 shows the circuit diagram of the project. The trig and echo pins of the Front
ultrasonic sensor are connected to GPIO 2 and GPIO 3 respectively. Similarly, the trig and
echo pins of the Rear ultrasonic sensor are connected to GPIO 4 and GPIO 17, respective-
ly. To drop the voltage levels to +3.3 V, the Echo outputs of the ultrasonic sensors are
connected to the Zero 2 W through potential divider resistors. The buzzer is connected to
GPIO 27.
● 111
Program listing: Figure 5.62 shows the program listing (program parking.py). The front
sensor pins are named trig_f and echo_f. Similarly, the rear sensor pins are named trig_r
and echo_r. The distances from both sensors to obstacles are measured using function
GetDistance, where the trig and echo pin names of the sensor whose distance to the ob-
stacles is to be measured. A 10-microsecond trigger pulse is sent and then the time taken
to receive the echo pulse is measured. Here, the time.time() function is used after send-
ing the trigger pulse and the same function is used as soon as the echo pulse is received.
The difference between the two times is the time taken to receive the echo pulse. This time
is divided by 2 and the distance to the object expressed in cms is found as follows:
where "time" is in seconds and the time taken to receive the echo pulse. We can re-write
the above equation as:
If the distances of either sensors to the objects is less than or equal to the Allowed_Dis-
tance (which is set to 10 cm) then the buzzer is sounded to indicate that the vehicle is too
close to objects (either at the front or at the rear).
Since the parking sensor is to be operated away from a PC, it is necessary to auto start
the program when power is applied to the Raspberry Pi. The program name parking.py
must be included in file /etc/rc.local in the following format for it to launch as soon as the
Raspberry Pi starts after a power-up or after a reboot:
● 112
#-------------------------------------------------------------------
# PARKING SENSORS
# ===============
#
# This is a parking sensors project. Ultrasonic tranamitter/receiver
# sensors are attached to the front and rear of a vehicle. In addition
# an active buzzer is connected to the Zero 2 W. The program senses
# the objects in the front and rear of the vehicle and sounds the buzzer
# if the vehicle is too close to the objects. In this project a distance
# less than 10cm is considered to be too close.
#
# File : parking.py
# Date : December, 2022
# Author: Dogan Ibrahim
#--------------------------------------------------------------------
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
Allowed_Distance = 10 # Distance in cm
#
# Front Ultrasonic sensor pins
#
trig_f = 2 # GPIO 2
echo_f = 3 # GPIO 3
#
# Rear ultrasonic sensor pins
#
trig_r = 4 # GPIO 4
echo_r = 17 # GPIO 17
#
# BUZZER pin
#
Buzzer = 27 # GPIO 27
#
# Configure trig and buzzer as outputs, echos as inputs
#
GPIO.setup(trig_f, GPIO.OUT)
GPIO.setup(trig_r, GPIO.OUT)
GPIO.setup(echo_f, GPIO.IN)
GPIO.setup(echo_r, GPIO.IN)
● 113
GPIO.setup(Buzzer, GPIO.OUT)
#
# Turn ON the Buzzer
#
def BUZZERON():
GPIO.output(Buzzer, 1)
return
#
# Turn OFF the Buzzer
#
def BUZZEROFF():
GPIO.output(Buzzer, 0)
return
#
# Start of the main program loop. Measure the distance to obstacles
# at the front and rear of the vehicle and activate the buzzer if the
# distance is below the allowed distance
#
BUZZEROFF()
while True:
obstacle_f = GetDistance(trig_f, echo_f) # distance to front obstacles
obstacle_r = GetDistance(trig_r, echo_r) # distance to rear obstacles
if (obstacle_f <= Allowed_Distance or obstacle_r <= Allowed_Distance):
BUZZERON() # Turn Buzzer ON
else:
● 114
After applying power, wait until the Raspberry Pi Zero 2 W boots and the program should
launch automatically. You should remove your Python program name from file /etc/rc.lo-
cal after testing and completing your project so that the program does not start every time
you restart your Pi.
Block diagram: The block diagram of the project is shown in Figure 5.63.
Circuit diagram: A type DHT11 temperature and relative humidity sensor chip (see Figure
5.64) is used in this project. This is normally a 3-pin sensor (there is also a 4-pin version
of this sensor where one of the pins is not used) with pins GND, +V, and Data. GND and
+V are connected to Ground and the +3.3 V power supply pins of the Raspberry Pi Zero
2 W. The Data pin must be connected to +V through a 10 k-ohm resistor. In this project,
a 3-pin version of the DHT11 is used with built-in 10 k-ohm pull-up resistor. As shown in
Figure 5.65, the Data pin of the sensor is named as S and it is connected to GPIO 2 of the
Zero 2 W.
● 115
The DHT11 uses a capacitive humidity sensor, and a thermistor to measure the ambient
temperature. Data output is available from the chip at a rate of about one second. The basic
features of DHT11 are:
• 3 to 5 V operation
• 2.5 mA current consumption (during a conversion)
• Temperature reading in the range 0–50 ºC with an accuracy of ±2 ºC
• Humidity reading in the range 20-80% with 5% accuracy
• Breadboard-compatible with 0.1-inch pin spacings
Program listing: In this program, the Adafruit DHT11 library and matplotlib modules
are used. These modules should be installed into Python before they can be used. The in-
structions for are as follows:
pi@raspberrypi:~ $ cd Adafruit_Python_DHT
● 116
• Install matplotlib:
Figure 5.66 shows the program listing (program: graph.py). At the beginning of the pro-
gram, the matplotlib, numpy, time, and Adafruit modules are imported. The sensor
type (variable sensor) is set to be DHT11, and it is connected to port GPIO 2. The X and
Y axes are labeled and a title is given to the graph. The graph is set to be interactive by
the statement ion(). The remainder of the program runs in a for loop which executes as
variable i changed from 0 to 100 in steps of 2, and this corresponds to the time axis (the
length of the data collection time and hence the length of the X-axis can be changed if de-
sired). The humidity and temperature are then read from the DHT11 and stored in variables
humidity and temperature respectively. These values are then converted into floating
and are stored in variables t and h, ready to be plotted. Scatter graphs are then drawn in
real-time as the temperature and humidity data are received from the DHT11. A 5-second
delay is introduced between each loop.
#-------------------------------------------------------------------
# REAL TIME GRAPH OF HUMIDITY AND TEMPERATURE
# ===========================================
#
# This program reads the ambient temperature and himidity from
# a DHT11 type sensor and displays them on the monitor in real-time
# as a graph.
#
# In this program data is collected every 5 seconds
#
# Program: graph.py
# Date : December, 2022
# Author : Dogan Ibrahim
#------------------------------------------------------------------
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import numpy as np
import time
import Adafruit_DHT
sensor = Adafruit_DHT.DHT11
● 117
GPIO = 2
#
# Start of main program. Humidity and temperature are read from
# DHT11 and are plotted in real time as the data are being read
#
plt.axis([0,100,0,100])
plt.title('Humidity and Temperature')
plt.xlabel('Time')
plt.ylabel('Hum. & Temp')
plt.clf()
j=1
plt.ion()
The real-time changes in temperature and humidity are shown in Figure 5.67. In this im-
age, the top graph is the humidity (RH) and the bottom one is the temperature (T).
● 118
The Sense HAT board (Figure 5.68) consists of 7 main components and an LED matrix.
The components on the board are controlled via the I2C bus interface. The following are the
main components on the board:
The Sense HAT board is normally plugged into the 40-way connector of the Raspberry Pi.
In order to interface external components to the Raspberry Pi in addition to the Sense HAT
board, you need to connect the Sense HAT to the Raspberry Pi using either a ribbon cable
or jumper wires allowing other Raspberry Pi pins to remain accessible. In other words, you
need to know which pins of the Sense HAT board are used by Raspberry Pi, and which pins
of Raspberry Pi are free.
In addition to the I2C control lines, the ATTINY88 microcontroller on the board can be
programmed via the SPI bus control lines (MOSI, MISO, SCK, CE0) provided on the board.
● 119
The following pins are used by the Sense HAT 40-way connector:
The Sense HAT board can be connected to the Zero 2 W using only the following 9 pins of
the 40-way connectors:
Note: You can also plug in the Sense HAT board directly on top of the Zero 2 W board
instead of making the above connections.
Before developing a project using the Sense HAT board, the Sense HAT library must be im-
ported into your Python program. Also, the sense object must be created at the beginning
of the program, meaning the following two statements must be included at the beginning
of your programs:
● 120
The remainder parts of this Chapter is devoted to developing simple projects with the Sense
HAT using the Raspberry Pi Zero W.
If you get an error message saying that the RPi-Sense FB device cannot be detected,
then do the following:
Notice that there are two versions of the Sense HAT board. Version 1.0 has no color sensor
while Version 2.0 does have it. You may get a warning message saying that it failed to ini-
tialize the color sensor if you are using Version 1.0.
You can also display a single letter using the statement: sense.show_letter, for example:
sense.show_letter("A"). Notice that the letter is displayed permanently.
In addition to displaying text in default mode, you can use the following options.
scroll_speed: This floating point number changes the speed that the text scrolls. The de-
fault value is 0.1. A bigger number slows down the scroll speed.
text_colour: Used to change the text color. The color is specified as (Red, Green, Blue)
where each color can take a value between 0 and 255 and you can mix the colors to obtain
any other colour. For example, (255, 0, 0) is red and so on.
back_colour: used to change the color of the background. Color is defined as in the
text_color option.
● 121
In the following example, the same text as above is scrolled slowly, in red, with a yellow
background color:
Notice that in the above program the text is displayed only once, but the background color
remains yellow.
If, for example, you wish to repeat displaying the text — say, every two seconds — then
the required program is as shown in Figure 5.69 (program: txt.py). Notice how the contin-
uation line is used in Python.
#-----------------------------------------------------------
# Display Text
# ------------
#
# This program displays the text Sense HAT every 2 seconds.
# the text colour is RED and back ground colour is YELLOW
#
# Author: Dogan Ibrahim
# File : txt.py
# Date : December, 2022
#------------------------------------------------------------
from sense_hat import SenseHat
import time
sense = SenseHat()
while True:
sense.show_message("Sense HAT",scroll_speed=0.3,\
text_colour=[255,0,0],back_colour=[255,255,0])
time.sleep(2)
The sense.clear() statement can be used to turn OFF all the LEDs. This may be necessary
to ensure that all the LEDs are turned OFF at the beginning of a program. Similarly, a color
can be passed to the clear statement to set all the LEDs to the same color, like so:
red = (255, 0, 0)
sense.clear(red)
The brightness of the LED matrix can be changed by toggling the low_light statement. In
the following examples the brightness is toggled:
● 122
sense.low_light = True
or
sense.low_light = False
The displayed text (or image) can be rotated by using the statement set_rotation(n)
where n is the rotation angle in degrees, taking the values of 0, 90, 180, or 270. The
following statement rotates character s by 90 degrees and displays it on the LED matrix:
sense.set_rotation(90)
sense.show_letter("s")
Text (or image) can be flipped horizontally or vertically by using the statements flip_h or
flip_v respectively. In the following example the character X is flipped horizontally and is
then displayed:
sense.flip_h
sense.show_letter("X")
Figure 5.70 shows the program listing (program: mult.py). Two integer random numbers
are generated between 1 and 99 and are stored in variables no1 and no2. Variable ques-
tion holds the question as a string and this is displayed in green as shown in the following
example:
25 x 10 =
The program waits for 10 seconds and after this time the result 250 is displayed in red.
After 2 seconds the LEDs are cleared and the program continues displaying two new num-
bers.
#-----------------------------------------------------------
# Multiplication Test
# -------------------
#
# This program displays two numbers between 1 and 99 and waits
# for 10 seconds until the user finds the correct answer. The
# correct answer is then displayed so that the user can check with
● 123
# his/her answer
#
# Author: Dogan Ibrahim
# File : mult.py
# Date : December, 2022
#------------------------------------------------------------
from sense_hat import SenseHat
sense = SenseHat()
import time
import random
spd = 0.2 # Scroll speed
red = (255, 0, 0) # Red colour
green = (0, 255, 0) # Green colour
try:
while True:
no1 = random.randint(1,99) # First number
no2 = random.randint(1, 99) # Second number
question = str(no1) + "x" + str(no2) + "="
sense.show_message(question, scroll_speed = spd, text_colour=(green))
time.sleep(10)
result = str(no1 * no2)
sense.show_message(result, scroll_speed = spd, text_colour=(red))
time.sleep(2)
sense.clear()
time.sleep(1)
except KeyboardInterrupt:
exit()
5×1=5
5×2=10
5×3=15
5×4=20
5×5=25
5×6=30
5×7=35
● 124
5×8=40
5×9=45
5×10=50
5×11=55
5×12=60
Figure 5.71 shows the program listing (program: timestab.py). Variable Tablefor stores
the number whose times table is required. A loop is formed which goes from 0 to 11. Inside
this loop variable j takes values from 1 to 12. Variable result stores the result of the mul-
tiplication at each iteration of the loop. String variable disp stores the data to be displayed
by the LED matrix at each iteration. Users can easily change the value of Tablefor to gen-
erate times table for another number.
#-----------------------------------------------------------------
# Times Table
# -----------
#
# This program generates a times table. The table is selected at the
# beginning of the program by setting variable Tablefor.
#
# Author: Dogan Ibrahim
# File : timestab.py
# Date : December, 2022
#-------------------------------------------------------------------
from sense_hat import SenseHat
sense = SenseHat()
import time
try:
for k in range(12): # Do 0 to 11
j = k + 1 # 1 to 12
result = Tablefor * j
disp = str(Tablefor) + "x" + str(j) + "=" + str(result)
sense.show_message(disp, scroll_speed = spd, text_colour=(red))
time.sleep(1)
sense.clear()
except KeyboardInterrupt:
exit()
● 125
Figure 5.72 shows the program listing (program: thp.py). The program runs in a loop every
two seconds where the temperature, humidity, and pressure readings are displayed on the
scrolling LED. Notice that the readings are all in floating-point format and the round()
function is used to configure them to have one digit after the decimal point.
#--------------------------------------------------------------
# TEMPERATURE,HUMIDITY & PRESSURE
# -------------------------------
#
# This program reads the temperature, humidity and pressure and
# displays on the scrolling LEDs. The data is displayed in the
# following format:
#
# T=nn.nC H=nn.n% P=nnnn.nmb
#
# Author: Dogan Ibrahim
# Date : December, 2022
# File : thp.py
#--------------------------------------------------------------
from sense_hat import SenseHat
sense=SenseHat()
import time
while True:
T = round(sense.get_temperature(), 1) # Get temperature
H = round(sense.get_humidity(), 1) # Get humidity
P = round(sense.get_pressure(), 1) # Get pressure
enviro = "T="+str(T)+ "C H="+str(H)+ "% P="+str(P)+"mb "
sense.show_message(enviro, scroll_speed = 0.2)
time.sleep(2)
We could have also displayed the data on the PC screen by running the following program
code. Figure 5.73 shows the output of the program:
● 126
P = sense.get_pressure()
TT = round(T, 1)
HH = round(H, 1)
PP = round(P, 1)
print("Temperature: %s, Humidity: %s, Pressure:%s"
%(TT, HH, PP))
time.sleep(1)
We could also display the temperature or the humidity as integer variables on non-scrolling
LEDs by using the Disp function.
Block diagram: Figure 5.74 shows the block diagram of the project.
● 127
Circuit diagram: The circuit diagram of the project is shown in Figure 5.75, where the
buzzer is connected to port pin GPIO 4 of the Zero 2 W. Both the buzzer and the Sense HAT
board are connected to the Zero 2 W using jumper wires.
Program listing: In this program, the library function created by the author, named
Disp() is used. This function has 3 arguments: number to be displayed, color, and mode (0
or 1, 1 to clear the display). This function is contained in the Python program called dis-
play.py which can be found in software archive for this book hosted on the Elektor website.
Calling function Disp() displays a number without scrolling the display. Figure 5.76 shows
the full program listing of display.py. Make sure that display.py is in the same directory
as your main program.
#-------------------------------------------------------------
# FUNCTION TO DISPLAY NUMBERS
# ---------------------------
#
# This function displays a two-digit number on the LED matrix
# without scrolling the display. The number to be displayed and
# its colour are entered as the arguments of the function.The
# third parameter controls whether or not to clear the display
# before displaying the number. Setting this parameter to 1
# will clear the display
#
# Author: Dogan Ibrahim
# Date : March 2022
# File : display.py
#------------------------------------------------------------
from sense_hat import SenseHat
sense = SenseHat()
● 128
[[0,0,1,0], # 1
[0,1,1,0],
[0,0,1,0],
[0,0,1,0],
[0,0,1,0],
[0,0,1,0],
[0,0,1,0],
[0,1,1,1]],
[[0,1,1,0], # 2
[1,0,0,1],
[0,0,0,1],
[0,0,0,1],
[0,0,1,0],
[0,1,0,0],
[1,0,0,0,],
[1,1,1,1]],
[[1,1,1,1], # 3
[0,0,1,1],
[0,0,1,1],
[1,1,1,1],
[1,1,1,1],
[0,0,1,1],
[0,0,1,1],
[1,1,1,1]],
[[0,0,1,0], # 4
[0,1,1,0],
[1,1,1,0],
[1,0,1,0],
[1,1,1,1],
[0,0,1,0],
[0,0,1,0],
● 129
[0,0,1,0]],
[[1,1,1,1], # 5
[1,0,0,0],
[1,0,0,0],
[1,1,1,1],
[0,0,0,1],
[0,0,0,1],
[0,0,0,1],
[1,1,1,1]],
[[1,1,1,1], # 6
[1,0,0,0],
[1,0,0,0],
[1,1,1,1],
[1,0,0,1],
[1,0,0,1],
[1,0,0,1],
[1,1,1,1]],
[[1,1,1,1], # 7
[0,0,0,1],
[0,0,0,1],
[0,0,0,1],
[0,0,0,1],
[0,0,0,1],
[0,0,0,1],
[0,0,0,1]],
[[0,1,1,0], # 8
[1,0,0,1],
[1,0,0,1],
[1,1,1,1],
[1,0,0,1],
[1,0,0,1],
[1,0,0,1],
[0,1,1,0]],
[[1,1,1,1], # 9
[1,0,0,1],
[1,0,0,1],
[1,1,1,1],
[0,0,0,1],
[0,0,0,1],
[0,0,0,1],
[1,1,1,1]]
● 130
blank = [0,0,0]
blanks=[0,0,0,0]
Disp = [] # List to store patterns
if mode == 1:
sense.clear() # Clear LEDs
The program listing is shown in Figure 5.77 (program: tempcont.py). At the beginning of
the program, the modules used in the program are imported to the program. The buzzer is
assigned to number 4 which will correspond to GPIO 4. The set temperature value is stored
in variable SetTemperature and is hardcoded as "24" in his example. The buzzer is turned
OFF at the beginning of the program. The remainder of the program runs in an endless
loop. Inside this loop, the ambient temperature is read from the Sense HAT, and this tem-
perature is compared with the setpoint value. If the ambient temperature is less than the
set value, then the buzzer is turned ON and the ambient temperature is displayed in red as
non-scrolling. If, on the other hand, the ambient temperature exceeds the set value, the
buzzer is turned OFF and the ambient temperature is displayed in blue.
#--------------------------------------------------------------------
# ON-OFF TEMPERATURE CONTROLLER
# -----------------------------
#
# This is an ON-OFF temperature control project. In this project
# a buzzer is connected to port pin GPIO 4 of the Zero 2 W in
# addition to the Sense HAT. The Sense HAT is connected using
● 131
while True:
T = int(sense.get_temperature_from_humidity()) # get temperature
if(T < SetTemperature): # T < setpoint?
Disp(T, red, 0) # display in red
GPIO.output(Buzzer, 1) # Buzzer ON
else:
Disp(T, blue, 0) # display in blue
GPIO.output(Buzzer, 0) # Buzzer OFF
The buzzer used in this project can easily be replaced with a relay and a heater can be
connected to the relay contacts to permit powering from the mains. The room temperature
is then effectively governed by the program.
● 132
6.1 Overview
Two of the key features of the Raspberry Pi Zero 2 W are its Wi-Fi and Bluetooth com-
munication capabilities. Your Raspberry Pi Zero 2 W is equipped with a 2.4-GHz 802.11
b/g/n wireless LAN module. Without such features, you"d have to resort to external
communication modules. Network communication is handled using either UDP or TCP-
type protocols. In this chapter, you will be learn how to write Python programs using
both the UDP and TCP type protocols using the on-board Wi-Fi module.
TCP UDP
Slow Fast
● 133
Server tasks
1. Create UDP socket
2. Bind the socket to server address
3. Wait until datagram packet arrives from client
4. Process the datagram packet
5. Send a reply to the client, or close the socket
6. Go back to Step 3 (if not closed)
Client tasks
Server tasks
● 134
Client tasks
Background information: Port numbers range from 0 to 65535. Numbers from 0 to 1023
are reserved and called as established ports. For example, port 23 is the Telnet port, port
25 is the SMTP port etc. In this chapter you"ll use port number 5000 in your programs.
Block diagram: Figure 6.3 shows the project block diagram where the Zero 2 W and
smartphone communicate over a Wi-Fi router.
● 135
Raspberry Pi Zero 2 W program listing: In this project, the Zero 2 W is the server.
Figure 6.4 shows the program listing (Program: tcpserver.py). At the beginning of the
program, a TCP/IP socket is created (sock.SOCK_STREAM) and is then bound to port
5000. The program listens for a connection. Notice that it is possible for the server to listen
to multiple clients, but it can of course communicate with only one at any time. When the
client makes a connection, this is accepted by the server. The server then reads a message
from the keyboard and sends it to the client over the Wi-Fi link. Notice that the setsock-
opt() statement makes sure that the program can be used again without having to wait for
the socket timeout of 30 seconds.
#===============================================================
# SEND TEXT MESSAGES USING TCP/IP
# ===============================
#
# This is the TCP/IP server program. It receives text messages
# from the keyboard and sends to an Android smart phone over
# a Wi-Fi link
#
# Author: Dogan Ibrahim
# File : tcpserver.py
# Date : December, 2022
#==============================================================
import socket
yn = 'y'
● 136
while yn == 'y':
msg = input("Enter your message: ") # read a message
client.send(msg.encode('utf-8')) # send the message
Testing
There are many TCP apps available free of charge for smartphones. In this project, the TCP
Client by JOY S.R.L. app is utilized on an Android smartphone. This app is available free
of charge in the Play Store (see Figure 6.5).
• Run the Android app and configure it as shown in Figure 6.6, where
192.168.3.21 is the IP address of the Zero 2 W.
● 137
• Click the icon at the top left corner of the app (disconnected) to connect to the
Zero 2 W over TCP/IP.
● 138
Program listing: Figure 6.9 shows the program listing (Program: tcp2way.py). Here,
port 5000 is used as in the previous project. The program has been changed to send and
receive messages from the smartphone. Socket function recv(byte count) sends mes-
sage over the TCP/IP link to the connected node.
#===============================================================
# SEND/RECEIVE TEXT MESSAGES USING TCP/IP
# =======================================
#
# This is the TCP/IP server program. It receives text messages
# from the keyboard and sends to an Android smart phone over
# a Wi-Fi link
#
# Author: Dogan Ibrahim
# File : tcp2way.py
# Date : December, 2022
#==============================================================
import socket
yn = 'y'
try:
while yn == 'y':
msg = input("Enter your message: ") # read a message
msg = msg +"\n"
client.send(msg.encode('utf-8')) # send the message
msg = client.recv(1024)
print("Received message: ")
print(msg.decode('utf-8'))
except KeyboardInterrupt:
print("\nClosing connection to client")
sock.close()
● 139
Testing
You will be using the Android app as in Figure 6.5. Start the Zero 2 W server program and
then exchange messages between the Zero 2 W and the smartphone. An example com-
munication session is shown in Figure 6.10. In this example, the Zero 2 W sends message
MESSAGE FROM ZERO 2 W. In reply, the Android smartphone sends the message: mes-
sage from Android.
Figure 6.10: Example communication between the Zero 2 W and the Android app.
Background Information: In the project, the Raspberry Pi Zero 2 W is the server and the
PC is the client. The programs at either side are developed using the Python programming
language. Python 3.10 is used on the PC. If you do not have Python on your PC, you could
install it from the following website:
https://www.python.org/downloads/
Block diagram: Figure 6.11 shows the block diagram where the Zero 2 W and the PC
communicate over a Wi-Fi router.
● 140
Zero 2 W program Listing: The Zero 2 W program listing is shown in Figure 6.12 (Pro-
gram: tcppc.py). The program is very similar to the one given in Figure 6.9, i.e., program:
tcp2way.py. You should terminate the program by entering Cntrl+C.
#===============================================================
# SEND/RECEIVE TEXT MESSAGES USING TCP/IP
# =======================================
#
# This is the TCP/IP server program. It communicates with a PC
# running TCP/IP on the same port
#
# Author: Dogan Ibrahim
# File : tcppc.py
# Date : December, 2022
#==============================================================
import socket
import time
try:
while True:
msg = input("Enter your message: ") # read a message
msg = msg +"\n"
client.send(msg.encode('utf-8')) # send the message
msg = client.recv(1024)
print("Received message: ", msg.decode('utf-8'))
except KeyboardInterrupt:
print("\nClosing connection to client")
sock.close()
time.sleep(1)
PC Program Listing: The PC program listing is shown in Figure 6.13 (program: client.
py). The program creates a socket and then connects to the server. Next, messages are
exchanged between the client and the server.
● 141
#=============================================================
# TCP/IP CLIENT
# =============
#
# This is the client program on the PC.The program exchanges
# messages with the server on the Raspberry Pi Zero 2 W
#
# Author: Dogan Ibrahim
# File : client.py
# Date : December 2022
#=============================================================
import socket
import time
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.connect(("192.168.3.21", 5000))
try:
while True:
msg = sock.recv(1024)
print("Received message: ", msg.decode('utf-8'))
data = input("Enter message to send: ")
sock.send(data.encode('utf-8'))
except KeyboardInterrupt:
print("Closing connection to server")
sock.close()
time.sleep(1)
● 142
Note: You may find that after exiting the program you may not be able to run it again.
This is because the socket stays open for about 30 seconds and the error message saying
Address is already in use may be displayed. You can check the state of the port with the
following command:
If the display includes the text ESTABLISHED, it means that the socket has not been
closed properly and you will have to restart your Zero 2 W to run the program again. If, on
the other hand, you see the message TIME_WAIT, simply wait about 30 seconds before
restarting the program.
6.6 Project 24: Controlling an LED connected to the Zero 2 W from the
smartphone, using TCP/IP
Description: In this project, an LED is connected to the Zero 2 W. The LED is turned ON
and OFF by sending commands ON and OFF respectively from an Android smartphone. The
aim of this project is to show how an LED connected to the Zero 2 W can be controlled from
an Android smartphone by sending commands using the TCP/IP protocol over a Wi-Fi link.
In this project, your Zero 2 W is the server and your smartphone acts as the client.
Block diagram: Figure 6.15 shows the block diagram of the project.
● 143
The LED is connected to port pin GPIO 2 (pin 3) through a 470-ohm current-limiting resis-
tor.
Program Listing: Figure 6.16 shows the program listing (program: serverled.py). As in
the previous program, a socket is created and port 5000 is used. The LED is assigned to
port GPIO 2, configured as output, and turned OFF at the beginning of the program. The
server waits for a connection from the client and then accepts the connection and displays
message Connected. It then waits to receive a command from the client. If the command
is ON, the LED is turned ON. If, on the other hand, the command is OFF, the LED is turned
OFF. Sending command X terminates the server connection and exits the program.
#=============================================================
# CONTROL LED FROM SMART PHONE
# ============================
#
# In this program TCP/IP is used where Zero 2 W is the server
# and smart phone is the client. An LED connected to Zero 2 W
# GPIO 2 and is controlled from the smart phone
#
# Author: DOgan Ibrahim
# File : serverled.py
# Date : December, 2022
#===============================================================
import socket
import RPi.GPIO as GPIO
import time
● 144
print("Closing connection")
GPIO.cleanup()
sock.close()
time.sleep(1)
The program is evaluated using the Android app TCP client (Figure 6.5) used in Project 21.
The server program started, then the client is started. Figure 6.17 shows sending the ON
command to turn ON the LED.
Program Listing: In this project, your Zero 2 W is the server and your smartphone is the
client. Figure 6.18 shows the program listing (program: udpserver.py). At the beginning
of the program, a UDP socket is created (sock.SOCK_DGRAM) and is subsequently bound
to port 5000. The server program then reads text messages sent from the smartphone and
displays them on the screen. Messages sent by the Zero 2 W are displayed on the smart-
phone.
● 145
#=======================================================
# SEND TEXT MESSAGES USING UDP
# ============================
#
# This is the UDP server program running on Zero 2 W.
# The program exchanges text messages with an Android
# smart phone
#
# Author: Dogan Ibrahim
# File : udpserver.py
# Date : December, 2022
#=======================================================
import socket
try:
while True:
data, addr = sock.recvfrom(1024)
print("Received msg:", data.decode('utf-8'))
msg = input("Message to send: ")
sock.sendto(msg.encode('utf-8'), addr)
except KeyboardInterrupt:
print("\nClosing connection to client")
sock.close()
There are many UDP apps available free of charge for both Android and iOS smartphones.
In this pΩroject UDP Sender/Receiver by JC Accounting & Innovative Technologies
Inc. for Android smartphones is used with good results (Figure 6.19).
● 146
• Write a message on the mobile phone app and click Send/Receive. The
message: Message from smartphone was sent as an example (Figure 6.21).
● 147
The LED can easily be replaced with a relay, for example, to control electrical appliances
from a smartphone.
The block diagram of the project is same as in Figure 6.14, but here port 2000 is used
instead of 5000.
Program Listing: Figure 6.22 shows the program listing (program: udpled.py). As in the
previous program, a socket is created and the server waits to receive commands from a cli-
ent to control the LED. If the command is ON, the LED is turned ON. If, on the other hand,
the command is OFF, the LED is turned OFF. Command X terminates the server program.
● 148
#==================================================================
# CONTROL LED FROM SMART PHONE
# ============================
#
# In this program UDP is used where Zero 2 W is the server
# and smart phone is the client. An LED connected to the server
# and is controlled from the smart phone
#
# Author: DOgan Ibrahim
# File : udpled.py
# Date : December, 2022
#===================================================================
import socket
import RPi.GPIO as GPIO
import time
print("Closing connection")
GPIO.cleanup()
sock.close()
time.sleep(1)
The program can be evaluated using the UDP Sender/Receiver app used in Figure 6.18.
● 149
• Write command ON and press Send on the smartphone (Figure 6.24). The LED
should turn ON. Similarly, write OFF and the LED should turn OFF. Sending X
should terminate the Zero 2 W program.
● 150
Flask should already be available in Python on your Raspberry Pi Zero W. If not, it can be
installed with the following command:
It"s wise to create a new folder on your Raspberry Pi Zero W and store all of your Flask-re-
lated documents there. So go ahead and create a folder called MyFlask under your default
directory /home/pi:
pi@raspberrypi:~ $ cd MyFlask
You are now ready to create your first web server application using Flask. To evaluate Flask
on your Zero 2 W development board, use the nano text editor and create a file called
flasktest.py with the following lines in it:
● 151
@app.route("/")
def index(): # run index when called
return "Hello from Flask" # msg to display when run
if __name__ == "__main__":
app.run(debug=True, port=80, host="0.0.0.0") # listen on port 80
You should see messages similar to the ones shown in Figure 6.25.
Now, open a web browser (e.g. Google Chrome) from a computer connected to the same
Wi-Fi router and then enter the IP address of your Raspberry Pi Zero 2 W — in this exam-
ple: 192.168.3.21. You should see the Hello from Flask message appear on a web page
as shown in Figure 6.26.
You can now create an HTML page and pass variables from a Python program. Create a
folder called templates under MyFlask, move to directory templates and create a file
called index.html using the nano text editor with the following lines (notice that the
variables inside the double curly brackets will have data passed to them from the Python
program):
● 152
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>Hello from Flask</h1>
<h2>The time on the server is: {{ time }}</h2>
</body>
You will now modify our flasktest.py program under directory MyFlask as follows:
app = Flask(__name__)
@app.route("/")
def index():
now = time.ctime()
DataToPass = {
"title" : "TESTING FLASK",
"time": now
}
return render_template("index.html", **DataToPass)
if __name__ == "__main__":
app.run(debug=True, port=80, host="0.0.0.0") # listen on port 80
The current date and time set is obtained using the function call time.ctime() and gets
stored in a variable now. Then, a dictionary called DataToPass is created and values of title
and time are stored in this dictionary. These values will be passed to the items in double
curly brackets in the web page defined by index.html. When the function returns, variables
inside the dictionary are returned to the web browser through the dictionary.
Next, go to a web browser and enter the IP address of your Raspberry Pi Zero 2 W
(192.168.3.21 for author"s Zero 2 W). You should see a display similar to the one shown
in Figure 6.27.
● 153
Now that you have learned how to pass variables from a Python program to a web page,
you can monitor the status of a GPIO pin, or control a GPIO pin from a web page.
HTML Template Program Listing: The HTML template index.html in folder /home/
pi/MyFlask/templates is simple and it consists of a title and two buttons: ON and OFF.
The title is in double curly brackets and therefore it expects data to be passed to it from
Python. Two buttons are defined called LED ON and LED OFF with green and red colors,
respectively. The LED ON button is referenced as /LED/on and the LED OFF button, as /
LED/off. Figure 6.28 shows the program listing.
<head>
<title>{{ title }}</title>
</head>
<body>
<h3>
<a href="/LED/on"><button type="button"><font color="green">LED ON
</button></a>
<a href="/LED/off"><button type="button"><font color="red">LED OFF
</button></a>
</h3>
</body>
Figure 6.28: HTML template program listing.
Raspberry Pi Program Listing: Figure 6.29 shows the Python program listing for the
Raspberry Pi Zero 2 W in folder /home/pi/MyFlask (program: flasktest.py). The pro-
gram has the basic Flask type template as shown earlier with some additional code. Port
pin GPIO 2 is configured as an output and the LED is turned OFF at the beginning of the
program. The title to be passed to index.html is named LED CONTROL and function
index is used to pass this string. Notice that another app.route is created with parame-
● 154
ters device and action. In this example the device is LED and its actions are on and off.
Function action checks the device and if it is LED then the actuator is set to LED. For
every actuator you must have an action. If the action is on, the LED is turned ON by the
statement GPIO.output(actuator, GPIO.HIGH), otherwise, if the action is off, the LED
is turned OFF.
#========================================================
# CONTROLLING LED FROM WEB PAGE
# =============================
#
# This program turns the LED ON or OFF from a web browser
# activated from any computer on the same Wi-Fi router as
# the Zero 2 W. The LED is controlled by clicking buttons
# when the web page is started
#
# Author: Dogan Ibrahim
# File : flasktest.py
# Date : December, 2022
#=========================================================
from flask import Flask,render_template
import RPi.GPIO as GPIO
app=Flask(__name__)
#
# Define GPIO2 as output and turn OFF LED at beginning
#
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
LED = 2
GPIO.setup(LED, GPIO.OUT)
GPIO.output(LED, 0)
@app.route('/')
def index():
DataToPass = {
'title': "LED CONTROL"
}
return render_template('index.html', **DataToPass)
@app.route("/<device>/<action>")
def action(device, action):
if device == "LED":
actuator = LED
● 155
if action == "on":
GPIO.output(actuator, GPIO.HIGH)
if action == "off":
GPIO.output(actuator, GPIO.LOW)
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True, port=80,host='0.0.0.0')
To run the program, you should follow the steps given below:
• Activate a web browser from a computer connected to the same Wi-Fi router
and enter the IP address of your Raspberry Pi Zero 2 W. As shown in Figure
6.29, you should see two buttons to control the LED. Clicking the buttons turns
the LED ON or OFF.
Modified Program
You could remove file index.html from the project and use only flasktest.py to control
the LED. The modified program (flasktest2.py) is shown in Figure 6.31. To control the
LED, you should enter the following web commands after starting flasktest2.py (Here
192.168.3.21 is the IP address of the Raspberry Pi Zero 2 W). Run program flasktest2.py
as sudo python3 flasktest2.py:
● 156
#========================================================
# CONTROLLING LED FROM WEB PAGE
# =============================
#
# This program turns the LED ON or OFF from a web browser
# activated from any computer on the same Wi-Fi router as
# the Zero 2 W. The commands are (assuming that the IP
# address of Raspberry Pi is: 192.168.3.21):
#
# 192.168.1.202/LED/on turn LED ON
# 192.168.1.202/LED/off turn LED OFF
#
# Author: Dogan Ibrahim
# File : flasktest2.py
# Date : December, 2022
#=========================================================
from flask import Flask,render_template
import RPi.GPIO as GPIO
app=Flask(__name__)
#
# Define GPIO2 as output and turn OFF LED at beginning
#
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
LED = 2
GPIO.setup(LED, GPIO.OUT)
GPIO.output(LED, 0)
@app.route("/<device>/<action>")
def action(device, action):
if device == "LED":
actuator = LED
if action == "on":
GPIO.output(actuator, GPIO.HIGH)
return "LED turned ON"
if action == "off":
GPIO.output(actuator, GPIO.LOW)
return "LED turned OFF"
if __name__ == '__main__':
app.run(debug=True, port=80,host='0.0.0.0')
● 157
The modified program displays messages LED turned ON and LED turned OFF. Figure 6.32
shows the web command to turn ON the LED.
At the two edges of the board there are 40 gold-colored metal GPIO (General-Input-Out-
put) pins with holes. You should solder pins to these holes so that external connections
can easily be made to the board. The holes are marked starting with number 1 at the top
left corner of the board and the numbers increase downwards up to number 40 which is
at the top right-hand corner of the board. The board is breadboard-compatible (i.e., 0.1-
inch pin spacing), and after soldering the pins, it can be plugged on a breadboard for easy
connection to the GPIO pins using jumper wires. Next to these holes you will see bumpy
circular cut-outs which can be plugged in on top of other modules not having any physical
pins fitted.
At one edge of the board there is the micro-USB B port for providing power to the board and
for programming it. Next to the USB port there is an on-board user LED that can be used
during program development. Next to this LED there is a button named BOOTSEL that"s
used during programming of the microcontroller as you will see in next chapters. Next to
the processor chip, there are three holes where external connections can be made to. These
are used to debug your programs using Serial Wire Debug (SWD). At the other edge of the
board is the single-band 2.4-GHz Wi-Fi module (802.11n). Next to the Wi-Fi module is the
on-board antenna.
● 158
Figure 6.34 shows the back view of the Pico hardware module. Here, all the GPIO pins are
identified with letters and numbers. You will notice the following types of letters and num-
bers:
Some of the GPIO pins are used for internal board functions. These are:
● 159
The Pico GPIO hardware is +3.3 V compatible which makes it important to be careful not
to exceed this voltage when interfacing external input devices to the GPIO pins. +5 V to
+3.3 V logic converter circuits or resistive potential divider circuits must be used if it is
required to interface devices with +5 V outputs to the Pico GPIO pins.
The Pico can be programmed using MicroPython or C/C++ languages. In this section, you
will be using the MicroPython with the Thonny editor to program your Pico. It is assumed
that you have Pico development boards with MicroPython ready installed. It will also be
useful if you are familiar with Thonny running on the Pico. An excellent book entitled Rasp-
berry Pi Pico W is available at the Elektor web site and interested readers should purchase
it for developing Raspberry Pi Pico-based projects.
● 160
Block diagram: Figure 6.36 shows the block diagram of the project.
● 161
Circuit diagram: The circuit diagram of the project is shown in Figure 6.37 with the button
and relay connected to the Pico and Zero 2 W, respectively.
Pico program listing: Figure 6.38 shows the Pico program listing (Program: picoudp.
py). At the beginning of the program, an LED is assigned to port GP2 and is turned OFF.
Function Connect() is called to connect to local Wi-Fi. Then, a socket is created with port
number 2000 and IP address 192.168.3.21. When the Button is pressed, the program
sends "1" to the Zero 2 W so that the LED can be turned ON. This process is repeated after
a 1-second delay.
● 162
#--------------------------------------------------------------
# RASPBERRY PI PICO W - RASPBERRY PI ZERO 2 W COMMS
# =================================================
#
# In this project a pushbutton is connected to GP2 of PICO W.
# Presingthe button sends a command to Zero 2 W to activate
# a relay. UDP protocol is used in this project
#
# Author: Dogan Ibrahim
# File : picoudp.py
# Date : December, 2022
#-------------------------------------------------------------
from machine import Pin
import network
import socket
import utime
global wlan
#
# This function attempts to connect to Wi-Fi
#
def connect():
global wlan
wlan = network.WLAN(network.STA_IF)
while wlan.isconnected() == False:
print("Waiting to be connected")
wlan.active(True)
wlan.connect("TP-Link_6138_EXT", "24844994")
utime.sleep(5)
connect()
print("Connected")
UDP_PORT = 2000 # Port used
UDP_IP = "192.168.3.21" # Zero 2W IP
cmd = b"1" # Cmd to turn ON
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while True:
while BUTTON.value() == 1: # Not pressed
pass
while BUTTON.value() == 0: # Not released
pass
sock.sendto(cmd, (UDP_IP, UDP_PORT)) # Send cmd
● 163
Zero 2 W program listing: Figure 6.39 shows the Zero 2 W program listing (Program:
zeroudp.py). At the beginning of the program, the libraries used are imported, while Relay
is configured at port GPIO 2 and deactivated. Then, a socket is created and the program
binds to it with the Zero 2 W IP address. The program then waits to receive a command
from the Pico. The received command is stored in variable data and if it is 1, the Relay is
activated for 5 seconds. At the end of this time the Relay is deactivated and the program
repeats waiting for a command.
#=========================================================
# RASPBERRY PI PICO W - RASPBERRY PI ZERO 2 W COMMS
# ============================
#
# This is the UDP server program running on Zero 2 W. The
# program receives a command from PICO W and activates a
# relay connected to GPIO 2 for 5 seconds
#
# Author: Dogan Ibrahim
# File : zeroudp.py
# Date : December, 2022
#=======================================================
import RPi.GPIO as GPIO
GPIO.setwarnings (False)
GPIO.setmode(GPIO.BCM)
import socket
import time
try:
while True:
data, addr = sock.recvfrom(1024) # GEt command
if data == b'1': # Command is 1?
GPIO.output(RELAY, 1) # Activate Relay
time.sleep(5) # 5 seconds delay
GPIO.output(RELAY, 0) # Deactivate Relay
● 164
• Run the Pico program in Thonny by clicking the green Run button. You should
see the message Connected when Pico connects to the local router.
• Push the button on Pico. The message Command sent will be displayed on the
Pico terminal. A packet will be sent to the Zero 2 W which will turn ON the LED
for 5 seconds.
• Enter Cntrl+C to terminate the program.
BMP280
The BMP280 is an absolute barometric pressure and temperature sensor chip, originally
developed for mobile applications. Its small dimensions and low power consumption allow
easy implementation in battery-powered devices such as mobile phones, GPS modules,
and watches. The BMP280 is based on Bosch"s proven piezo-resistive pressure sensor
technology featuring high accuracy and linearity as well as long-term stability and high EMC
robustness. The device is optimized in terms of power consumption, resolution and filter
performance. The basic specifications of the BMP280 include:
Block diagram: The block diagram of the project is shown in Figure 6.40.
● 165
Circuit diagram: Figure 6.41 shows the circuit diagram. SCL and SDA pins of BMP280 are
connected to the SDA (pin 3) and SCL (pin 5) of your Zero 2 W. 10 k-ohm pull-up resis-
tors are used for the I2C bus as the BMP280 board has no pull-up resistors (some BMP280
modules may already have on-board pull-up resistors). The sensor is powered from +3.3 V.
The Cloud
There are several cloud services that can be used to store data (for example, SparkFun,
ThingSpeak, Cloudino, Bluemix, etc). In this project, ThingSpeak is used. This is a free
cloud service where sensor data can be stored and retrieved using simple HTTP requests.
Before using the ThingSpeak, you have to create an account from their website and then
log in to this account.
https://thingspeak.com/
● 166
Click Get Started For Free and create an account if you don"t already have one. Then, you
should create a new channel by clicking on… New Channel! Fill in the form as shown in
Figure 6.42. Give the name Raspberry Pi Zero 2 W to the application, give a description,
and create two fields called Atmospheric Pressure and Temperature. You can option-
ally fill in the other items as well if you wish.
Figure 6.42: Create a New Channel (only part of the ThingSpeak form shown).
Click Save Channel at the bottom of the form. Your channel is now ready to be used with
your data. You will now see tabs with the following names. You can click on these tabs and
view the contents to make corrections, if necessary:
• Private View: This tab displays private information about your channel which
only you can see.
• Public View: If your channel is public, use this tab to display selected fields
and channel visualizations.
• Channel Settings: This tab shows all the channel options you set at creation.
You can edit, clear, or delete the channel from this tab.
• API Keys: This tab displays your channel API keys. Use the keys to read from
and write to your channel.
• Data Import/Export: This tab enables you to import and export channel
data.
● 167
• You should click the API Keys tab and save your Write API and Read API
keys and the Channel ID in a safe place as you will need to use them in our
program. The API Keys and the Channel ID in this project were:
Also, select the Public View and navigate to Sharing. You may select option Share chan-
nel view with everyone so that everyone can access your data remotely.
Program listing: In this program, you will use a BMP280 library for Raspberry Pi. The
steps to install the library are as follows:
After constructing the circuit, you should check to make sure that the BMP280 is detected
by the Zero 2 W. Enter the following command:
You should see the hardware address of the BMP280 chip displayed as: 76 (see Figure
6.43).
Figure 6.44 shows the program listing (Program: Cloud.py). At the beginning of the pro-
gram, the libraries used get imported to the program. The ThingSpeak Write Key and
Host Address are defined. The main program loop starts with the while statement. Inside
● 168
this loop, the IP address of the ThingSpeak website is extracted and a connection is made
to this site at port 80. Then, the atmospheric pressure and temperature readings are ob-
tained from the BMP280 module and are included in the path statement. The sock.send
statement sends an HTTP GET request to the ThingSpeak site and uploads the pressure
and temperature values. This process is repeated every 30 seconds.
Figure 6.45 shows the pressure and temperature data plotted by ThingSpeak. The Chart
Options can be clicked on to change various parameters of the charts. For example, Figure
6.46 shows the temperature as a column display. In Figure 6.47, the pressure is shown
as a step graph. A title and X-axis label are added in Figure 6.48 to the pressure graph.
Figure 6.49, finally, shows the atmospheric pressure displayed in a clock format (click Add
Widgets for this type display).
Because the Channel was saved as Public, you can view the graph from a web browser
by entering the Channel ID. In this project, the link to view the data graphs from a web
browser is:
https://api.thingspeak.com/channels/2004389
You can also export some or all of the fields in CSV format by clicking Export recent data,
so that it can be analyzed by external statistical packages such as Excel.
#-----------------------------------------------------------------------------
# ATMOSPHERIC PRESSURE AND TEMPERATURE ON THE CLOUD
# =================================================
#
# The ambient temperature and pressure sensor BMP280 is connected to Zero 2 W.
# The project reads the temperature and atmospheric pressure and sends
# to the Cloud where it can be accessed from anywhere. In addition, change
# of the temperature and the pressure can be plotted in the cloud.
#
#
# The program uses the Thingspeak cloud service
#
# Author: Dogan Ibrahim
# File : Cloud.py
# Date : January, 2022
#------------------------------------------------------------------------------
import socket
import time
from bmp280 import BMP280
from smbus import SMBus
bus = SMBus(1)
bmp280 = BMP280(i2c_dev=bus)
● 169
#
# Send data to Thingspeak. This function sends the temperature and
# humidity data to the cloud every 30 seconds
#
while True:
sock = socket.socket()
addr = socket.getaddrinfo("api.thingspeak.com",80)[0][-1]
sock.connect(addr)
p=bmp280.get_pressure()
t=bmp280.get_temperature() # Temperature in C
path = "api_key="+APIKEY+"&field1="+str(p)+"&field2="+str(t)
sock.send(bytes("GET /update?%s HTTP/1.0\r\nHost: %s\r\n\r\n"
%(path,host),"utf8"))
time.sleep(5)
sock.close()
time.sleep(25)
● 170
6.14.1 Ping
This is one of the useful commands that is used to detect devices on a network. The general
form of the command is:
● 171
The display is repeated every second. You can restrict the number of attempts with the –c
option. For example, to restrict to 5 attempts, use ping hostname –c 5. An example is
shown in Figure 6.50.
6.14.2 hostname
This command has several options. Command hostname shows the host name. host-
name –I shows the IP address assigned to our Pi, hostname – d shows the DNS name.
An example is shown in Figure 6.51.
6.14.3 ifconfig
This command displays network information about your RPi. The options are:
● 172
You can shutdown or bring up our Wi-Fi network interface with the commands: sudo ifcon-
fig wlan0 down and sudo ifconfig wlan0 up respectively.
6.14.4 route
This command is used to configure and display Wi-Fi router information. An example is
shown in Figure 6.53. In this example, your Wi-Fi router IP address is 192.168.3.0, having
the mask 255.255.255.0.
6.14.5 netstat
This command displays information about your network and ports. An example is shown
in Figure 6.54. The following options are useful (enter netstat –help to display a list of all
options):
● 173
6.14.6 host
The host command is used to find the IP address of a particular DNS. An example is shown
in Figure 6.55.
country=GB
update_config=1
ctrl_interface=/var/run/wpa_supplicant
network={
● 174
scan_ssid=1
ssid="MySSID"
psk="MyPassword"
}
• Save the file to the boot folder on your SD card with the name: wpa_
supplicant.conf.
• Insert the SD card back into your Raspberry Pi Zero 2 W and power-up the
device.
• The Raspberry Pi Zero 2 W should boot and access the local Wi-Fi router.
● 175
country=GB
update_config=1
ctrl_interface=/var/run/wpa_supplicant
network={
scan_ssid=1
ssid="MySSID"
psk="MyPassword"
}
● 176
• Open the app and tick on Who is Using My WiFi? (Figure 6.58)
• Yu should see a list of the devices connected to your Router. Note the one with
the Name: raspberrypi. In this example, the IP address was 192.168.3.21
(Figure 6.59)
● 177
http://www.nirsoft.net/utils/wireless_network_watcher.html
Download and click on the setup file to run the program. Figure 6.60 shows an example
output from the program (only part of the output is shown here. The output displays more
information about each node on the right hand side of the screen). From this output, you
can see that the IP address of our Pi is 192.168.3.21.
● 178
• install nmap
• You should get a display showing all the devices connected to your Wi-Fi,
together with their names and MAC addresses. Part of the display is shown in
Figure 6.61.
● 179
Before using the Open Weather Map, you have to register to it and get an API key free of
charge (up to 1000 API calls per day are free!). The steps are as follows:
https://openweathermap.org/
• Click Sign In at the top menu and end then click Create an Account (Figure
6.62)
• You should now click Get API key to get an API. The API key will be sent to your
email address. It is something like: 05ff9a8a5d66e4f3115c50d50ff7dAA9. The
key will be activated in a few hours.
● 180
• Now, you have to install the Python library (called: pyowm) for Open Weather
Map. Enter the following command to install the library:
• You are now ready to write your Python program and fetch and display the
current weather every 15 seconds (until stopped by the user). See the following
website for a detailed list of available commands:
https://pyowm.readthedocs.io/en/latest/v3/code-recipes.html
Program listing: Figure 6.64 shows the program listing (Program: LondonWeather.py).
At the beginning of the program, you imported the pyowm library. After entering the API
key assigned to you, go ahead and display the weather data as shown in the program. The
display is updated every 15 seconds until stopped by the user.
#=======================================================
# DISPLAY LONDON WEATHER IN REAL-TIME
#
# This program fetches the real-time weather data
# for a give city from Open Weather MAp and displays
# on the screen every 15 seconds
#
# Author: Dogan Ibrahim
# File : LondonWeather.py
# Date : January, 2023
#=======================================================
from pyowm import OWM # import Open Weather Map
import time # import time
#
# Enter your API key below
#
weather = OWM('05ff9a8a5d66e4f3115c5YOUR API')
manager = weather.weather_manager()
#
# Now we enter the city and country details
#
cty = manager.weather_at_place('London,GB')
MyWeather = cty.weather
while True:
W = MyWeather.wind()
print(" Wind: ", W['speed'], " m/s")
print(" Wind: ", W['deg'], " Degrees")
● 181
T = MyWeather.temperature('celsius')
print(" Min Temp: ", T['temp_min'], " C")
print(" Max Temp: ", T['temp_max'], " C")
print(" Feels like: ", T['feels_like'], " C")
time.sleep(15)
Run the program as follows (notice that the program is run from directory pyowm):
● 182
polarization of the crystal material which determines the amount of light that reaches the
color filter from the backlight. TFT displays are available in many different physical sizes
and also by different number pixel numbers.
In this section, you will use a 1.8-inch TFT display within a Raspberry Pi Zero 2 W project.
The display has an 8-bit connector on one side for the display logic, and a 4-bit connector
on the other side for the SD card interface. You will be using the display logic interface
which has the following pins:
8-pin connector
● 183
• Start raspi-config and enable the SPI interface under Interface Options:
Figure 6.68 shows the pixel co-ordinates of the TFT display used.
● 184
https://github.com/pimoroni/st7735-python
#=========================================================
# DISPLAY TEXT ON TFT
# ===================
#
# Author: Dogan Ibrahim
# File : TFTexample.py
# Date : January, 2023
#=========================================================
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import ST7735
width = disp.width
height =disp.height
img=Image.new('RGB', (160,128),color=(0,0,0))
draw=ImageDraw.Draw(img)
font=ImageFont.load_default()
draw.text((5,60),msg, font=font)
disp.display(img)
Figure 6.70 shows the text on the display. The display background is set to black using the
statement color=(0, 0, 0).
● 185
Rectangle
To draw a rectangle with the desired outline color and fill color, use the following statement.
x0 any y0 are the top-left coordinates and xm and ym, are the bottom-right coordinates:
draw.rectangle((x0, y0, xm, ym), outline = (0, 0, 0), fill = (0, 0, 0))
For example, the statement draw.rectangle((5, 5, 150, 120), outline = (0, 255,
0)) draws a green empty rectangle with the top left coordinate at (5, 5) and bottom
right coordinate at (150, 120).
Ellipse
To draw an ellipse, use the following statement:
draw.ellipse((x0, y0, xm, ym), outline = (0, 0, 0), fill = (0, 0, 0))
Line
To draw a line, use the following statement:
Polygon
To draw a polygon, use the following statement:
draw.polygon([(x1, y1), (x2, y2), (x3, y3), x4, y4)], outline = (0, 0, 0),
fill = (0, 0, 0))
● 186
#=========================================================
# DISPLAY VARIOUS SHAPES ON TFT
# =============================
#
# Author: Dogan Ibrahim
# File : TFTshapes.py
# Date : January, 2023
#=========================================================
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import ST7735
width = disp.width
height =disp.height
img=Image.new('RGB', (160,128),color=(0,0,0))
draw=ImageDraw.Draw(img)
font=ImageFont.load_default()
● 187
Program listing: Figure 6.73 shows the program listing (Program: TFTweather.py).
Make sure the required libraries are imported to the program as illustrated in Figure 6.64.
After configuring the TFT display and Open Map Weather, an endless loop is formed. Inside
this loop the heading LONDON WEATHER is displayed inside a double rectangle. Then, the
following weather parameters are extracted and displayed:
• Humidity
• Minimum temperature
• Maximum temperature
• Wind speed
• Wind direction
• Atmospheric pressure
• Current date and time
#=======================================================
# DISPLAY LONDON WEATHER IN REAL-TIME ON TFT
#
# This program fetches the real-time weather data
# for a give city from Open Weather MAp and displays
# on the screen every 5 seconds
#
# Author: Dogan Ibrahim
# File : TFTweather.py
# Date : January, 2023
#=======================================================
from pyowm import OWM # import Open Weather Map
import time # import time
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import ST7735
from datetime import datetime
#
# Enter your API key below
#
weather = OWM('05ff9a8a5d66e4f3115c50d YOUR API')
manager = weather.weather_manager()
● 188
#
# TFT configuration
#
disp=ST7735.ST7735(port=0,cs=0,rst=27,dc=17,width=128,height=160,
rotation=90,invert=False,offset_left=0,offset_top=0)
disp.begin()
width=disp.width
height=disp.height
while True:
img = Image.new('RGB', (160, 128), color=(0, 0, 0))
draw = ImageDraw.Draw(img)
font = ImageFont.load_default()
#
# Now we enter the city and country details
#
cty = manager.weather_at_place('London,GB')
MyWeather = cty.weather
● 189
d = datetime.now().strftime("%d-%m-%y %H:%M:%S")
draw.text((20, 105), str(d), fill = (0, 255, 0))
disp.display(img)
time.sleep(5)
Figure 6.74 shows the local weather data in London displayed on the TFT.
● 190
CHAPTER 7 • U
sing Node-Red with the Raspberry Pi
Zero 2 W
7.1 Overview
Node-RED is an open-source visual editor for wiring the Internet of Things, produced by
IBM. Node-RED comes with substantial number of nodes to manage a variety of tasks. The
required nodes are selected and joined together to perform a certain task. Node-RED is
based on flow-type programming where nodes are configured and joined together to form
the application program. There are nodes for doing fairly complex tasks, including web ac-
cess, Twitter, E-mail, HTTP, Bluetooth, MQTT, controlling the GPIO ports, etc. The nice thing
about Node-RED is that the programmer does not need to learn to do complex programs.
For example, an email can be sent by joining a few nodes together and writing a few lines
of code. In this chapter, you will develop some projects using Node-RED running on your
Raspberry Pi Zero 2 W.
You can start Node-RED by entering the following command in the command mode (char-
acters entered by the user are in bold for clarity):
pi@raspberrypi:~ $ node-red-start
When started, you should see some messages scrolling on your screen. A part of these
messages is shown in Figure 7.1.
● 191
Notice that this is a "service" type application and therefore it can be accessed from any-
where on the network, as well from other computers. To do this, you have to know the IP
address of your Raspberry Pi Zero 2 W. This can be found by entering the following com-
mand at the command prompt:
pi@raspberrypi:~ $ ifconfig
You can now enter the following command on your web browser to display the Node-RED
startup screen:
http://192.168.1.238:1880
When started, you should see the Node-RED startup screen as in Figure 7.2. When Node-
RED is started as a service, pressing Cntrl+C does not stop the service since it keeps run-
ning in the background.
Notice that, if you are using a browser running on the same computer as Node-RED, you
can access Node-RED using the following url:
http://localhost:1880
● 192
pi@raspberrypi:~ $ node-red-start
• Enter the following url into your web browser to display the Node-RED screen
(you will have to enter the IP address of your own Zero 2 W):
http://192.168.1.202:1880
• From the node palette, Click on inject node at the left-hand side and drag it to
the workspace.
• Double-click on this node, click on Payload, select String and enter the
following string Hello World! as shown in Figure 7.4.
● 193
• Click Done.
• Add node debug by clicking on debug node and dragging it to the right-hand
side of the inject node already in the workspace.
• Wire the two nodes together. Place the mouse cursor over the inject node"s
output port (a small grey square on the right-hand side of the node), then left-
click and drag a wire over to the input port of the Debug node. A wire should
now connect the two nodes as shown in Figure 7.5.
• Click the Deploy button at the top right-hand side of the screen.
• Click the small grey square at the right-hand side of node debug to activate
the node. You should see the message Successfully activated: debug
displayed by the console window.
• Click the inject node's button, which is the small square coming out from the
left-hand side of the node. Clicking the button will inject the message into the
flow and towards the debug node. The output should be displayed in the debug
window as shown in Figure 7.6.
● 194
• Notice that, if you place a wrong node on the workspace, you can click on the
node and then use the keyboard Delete button to remove it.
In this example, you first created an inject node. The inject node can be used to manually
trigger a flow by clicking the node's button within the workspace. It can also be used to
automatically trigger flows at regular intervals. You then stored the string Hello World! in
this node. Next, you created a debug node and connected the two nodes together and ac-
tivated the debug node. By triggering the inject node, the string is sent to the debug node
and is subsequently displayed in the debug window. The Debug node can be used to display
messages in the Debug sidebar within the editor. In addition to the displayed messages,
the debug sidebar includes information about the time the message was received as well
as the ID of the Debug node that sent the message. Clicking on the ID reveals the node
that sent the message.
Modified Program
You can modify the flow program, for example to display the string every 5 seconds. The
steps to do this are given below:
• Set the Repeat Interval to every 5 seconds (Figure 7.7) and click Done.
• Click Deploy.
● 195
• Click the inject node"s button. You should see the message displayed every 5
seconds like in Figure 7.8.
catch: If a node gives an error while managing a message, it is likely that the flow will
halt. The catch node can be used to catch the errors and return messages about the error.
mqtt in: this node connects to a MQTT broker and subscribes to messages from the spec-
ified topic.
http in: this node creates an HTTP end-point for creating web services.
websocket: this node provides an endpoint for a browser so that a websocket connection
can be established with Node-RED.
tcp: this node is used to establish TCP communications on a specified port. It accepts in-
coming TCP requests.
udp: this node is used to establish communication using the UDP protocol. It accepts in-
coming UDP packets.
● 196
serial in: this node reads serial data from the serial port of the local device. The node can
be configured to read at specific times.
mqtt out: this node connects to a MQTT broker and publishes messages.
http response: this node sends responses back to the HTTP requests received from HTTP
input node.
http request: this node sends HTTP requests and returns the response.
udp: this node sends UDP messages to the configured UDP host where the IP address and
port number are specified. Broadcast is supported.
serial out: this node sends data to the defined serial port of the local device. The node can
be configured to send some control characters such as newline after a message.
template: this node is useful for constructing messages and configuration files where
name:value pairs are inserted into the template.
trigger: this node can be used as a watchdog timer. It can also be used to create two out-
put messages with time intervals when an input message is received.
http request: this node is used to construct and then send a HTTP request to a given URL.
tcp request: this node sends msg.payload to a TCP server and expects a response. The
node is configurable — for example, it can be configured to wait for a specific character, or
to return immediately.
● 197
change: this node can be used to set, change, or delete the properties of incoming mes-
sages.
range: this node maps numerical input data to new output data.
csv: this node parses msg.payload and converts to or from CSV format. The input can be
a string in which case a JavaScript object is output. If on the other hand the input is a Ja-
vaScript object, then a CSV formatted string is outputted.
html: this node is used to extract data from an html type document in msg.payload.
json: this node converts to or from a JSON object and JavaScript object.
xml: this node converts to or from XML format and JavaScript object.
random: this node generates a random number between a high and a low value.
smooth: this node is used for various functions such as max, min, mean, high, and low
pass filter.
rbe: this is the "rbe" (Report By Exception) node which generates message if its input is
different from the previous input.
twitter out: this node Tweets the msg.payload on the configured user account. Text and
binary (image) messages can be sent.
file in: this node reads the specified file and sends it contents as msg.payload.
● 198
feedparse: this node monitors an RSS/atom feed for new entries and if there are new
entries, it delivers them as messages.
exec: this node calls to a system command and provides stdout, stderr, and the return
code.
rpi gpio out: this is the Raspberry Pi output node. The selected hardware pin of the Rasp-
berry Pi is set High or Low depending whether msg.payload is 0 or 1. You"ll be using this
node in the Raspberry Pi-based projects in later chapters.
rpi mouse: this is the Raspberry Pi mouse button node. The node generates a 0 or 1 when
the selected mouse button is clicked and released. A USB mouse is required.
rpi keyboard: this node is used to capture keystrokes from a USB keyboard.
• Create a random node and name it as Dice. Double-click to edit it and set to
generate whole integer numbers between 1 and 6 as shown in Figure 7.9. Click
Done.
● 199
• Join all three nodes as shown in Figure 7.10 and click Deploy.
• Click the inject node"s button. You should see a number between 1 and 6
displayed in the Debug window. Every time you click the inject node"s button, a
random number will be generated and displayed between 1 and 6 as pictured in
Figure 7.11.
• Create two random nodes with the names Dice1 and Dice2. Double-click to
edit them and set to generate whole integer numbers between 1 and 6 for both
nodes as in the previous project.
• Create a join node with the name join payloads. Double-click this node and
edit as shown in Figure 7.12. Notice that the message parts is set to 2 and are
separated with a space character. Click Done.
● 200
• Join the five nodes as shown in Figure 7.13 and click Deploy.
• Click the inject node"s button to generate two random numbers next to each
other in the Debug window as shown in Figure 7.14.
Notice here that, if the After a number of message parts in node "join" was set to 1,
then the two dice numbers would not have been displayed adjoining as shown in Figure
7.15.
● 201
Circuit Diagram: In this project, an LED is connected to port pin GPIO17 (pin 11) of the
Zero 2 W through a 470-ohm current-limiting resistor.
Node-RED flow program: Figure 7.16 shows the flow program. In this program, two
inject nodes and an rpi gpio out node are used.
● 202
• Create another inject node with the configuration as shown in Figure 7.18.
• Create a rpi gpio out node with the configuration as shown in Figure 7.19, set
the Type to Digital output, initialize pin state to 0, and name it as LED. Click
Done.
• Join the 3 nodes together as shown in Figure 7.16, and click Deploy.
• Click the button of inject node ON, you should see the LED turning ON. Click
the button of inject node OFF, and this time the LED should turn OFF.
● 203
As shown in Figure 7.20, if desired, you can connect debug nodes to the flow so that the
state of the LED can be displayed at any time in the Debug window (don't forget to click
Deploy and then Debug messages). Figure 7.21 shows the LED state as the LED is
turned ON or OFF.
Node-RED flow program: Figure 7.22 shows the flow program. In this program, an in-
ject node, a trigger node, and a rpi gpio out node are used.
● 204
• Create a trigger node to send out 1, wait for 1 second and then send out 0,
with the configuration as shown in Figure 7.24. Click Done.
• Create the rpi gpio out node as in the previous project. Join the three nodes
and click Deploy.
● 205
• Click the inject node's button. You should see the LED flashing every second.
In this project, the inject node activates the trigger node every two seconds, which in turn
controls the LED by turning it ON for a second, and OFF for a second.
You could insert a debug node to the flow program so that the state of the LED can be dis-
played. Additionally, you can see the timing accuracy of the project in the Debug window.
The button used in this project is a small component with four pins as shown in Figure 7.25.
Actually, the button is a 2-pin device with the pins paralleled for convenience.
Mechanical switches have bouncing problems. When a mechanical switch is operated, its
mechanical contacts bounce rapidly (i.e., move from one state to another state) until they
settle. Although this settling time may seem to be small (around 10 ms), it is actually a long
time considering a microcontroller"s processing time. Special switch debouncing circuits
can be used to eliminate this effect called "contact bounce." Luckily, the rpi gpio in the
node provides a parameter to set the switch debouncing time so that the contacts are not
read before this time expires. This makes sure that the correct switch output state (ON or
OFF) is read by the microcontroller.
Circuit Diagram: The LED is connected to port pin GPIO17 through a 470-ohm cur-
rent-limiting resistor. Port pin GPIO2 is connected to one side of the button at GND poten-
tial, while the other side of the button is connected to +3.3 V through a 10 k-ohm resistor
(Figure 7.26)
● 206
Node-RED flow program: Figure 7.27 shows the flow program. In this program two
nodes are used.
• Create an rpi gpio in node and name it as BUTTON, set the pin name to
GPIO2, set the resistor to pulldown.
• Create a rpi gpio out node and name it as LED, set the pin name to GPIO17,
and initialize the pin level to 0.
• Join the two nodes as shown in Figure 7.27, and click Deploy.
• You should see that the LED is initially OFF. Pressing the button should change
the state of port GPIO2 and the LED will turn ON. You should see the state of
port GPIO2 on the flow diagram under node BUTTON.
● 207
latest model of Alexa at the time of authoring this book was the 3rd generation of devices.
Figure 7.28 shows the 3rd Gen Alexa Dot device.
In this section, you will combine Node-RED with Alexa and the Raspberry Pi Zero 2 W and
learn how to control the GPIO ports of the Zero 2 W by issuing spoken commands to Alexa.
Block Diagram: The block diagram of the project is shown in Figure 7.29.
Circuit Diagram: In this project, a small LED is connected to port pin GPIO17 (pin 11) of
the Zero 2 W through a 470-ohm current-limiting resistor.
Node-RED flow program: Before developing your flow program, you have to install Alexa
node to your Node Palette. Because the Alexa nodes "listen" on port 80, it is important that
you start your Node-RED on the Raspberry Pi with a super user command. i.e.,
● 208
• Start the node-red screen on your PC web browser by entering the Zero 2 W IP
address followed by :1880.
• You should see two new nodes called amazon echo hub and amazon echo
device added to your Node Palette.
If you find that your Raspberry Pi GPIO nodes are not listed in the Nodes Palette, you can
re-install them using the following steps:
Figure 7.30 shows the flow program which consists just four nodes: an amazon echo hub
node, an amazon echo device node, a function node, and an rpi gpio out node.
• Create an amazon echo hub node and make sure that the Port is set to 80
and Process Input is set to No.
• Create an amazon echo device node and set the Name to Bedroom Light
(this is the name that Alexa will associate with the LED — you should choose
your own name here).
● 209
var out = 0;
if(msg.payload == "on")
out = 1;
else
if(msg.payload == "off")
out = 0;
msg.payload = out;
return msg;
• Create an rpi gpio out node and name it as LED. Set the Pin to GPIO17 Type:
digital output, and Initialize the pin state to logic 0.
Note: Alexa Echo uses port 80 for communication, You may find that port 80 is not available
on your Zero 2 W and the message unable to start port 80 may be displayed under the
Amazon Echo Hub. Also, you may get the following error message in Debug window:
If you get this error message, redirect port 80 to say 8080 using the following commands.
Also change the port number to 8080 by double-clicking on node Amazon Echo Hub:
Note that the above port redirection commands are not retained after a reboot.
● 210
To test the project, ask Alexa: "Alexa, discover devices". After a minute or so Alexa will
confirm that it has detected your device (Bedroom Light in this project).
To turn the LED ON, ask Alexa: "Alexa, turn on bedroom light". Alexa will respond with
OK and the light will turn ON.
To turn the LED OFF, ask Alexa "Alexa, turn off bedroom light". Alexa will respond with
OK and the light will turn OFF.
The nodes can be used to turn on/off a device or to dim a light and it is supported by the
1st, 2nd, and 3rd generation Alexa devices. Notice that you can add as many amazon echo
devices as you wish to your design for the control of various equipment. An example pro-
ject isgiven below where you get to add a buzzer to your design.
Block Diagram: The block diagram of the project is shown in Figure 7.32.
Circuit Diagram: The circuit diagram of the project is shown in Figure 7.33. The LED is
connected to GPIO17 (pin 11) and the buzzer to GPIO27 (pin 13).
● 211
Node-RED flow program: Figure 7.34 shows the flow program. Notice that you have
added another amazon echo device node to our program and named it Buzzer. Now, you
have two devices with the names: Bedroom and Buzzer. This second node drives another
function node which has exactly the same content as the previous one. The second rpi
gpio out node is used to drive the buzzer where its Pin is set to GPIO27 and its Type is
digital output as before. Because the new amazon echo device is not known to Alexa, you
have to ask Alexa to discover nodes again: "Alexa, discover devices". After this, you can
control the LED and the buzzer by asking the Alexa:
Notice that if you change the names of the devices in nodes Amazon-echo-device, you will
have to go to Alexa apps and remove the old device names from Alexa.
Also notice that you could have used another Alexa node called node-red-contrib-alexa-
home-skill for more sophisticated Alexa based control tasks. This node, called the Alexa
Home node, requires the user to be registered and have an account before using it. Alexa
Home node supports the following commands:
● 212
• TurnOnRequest
• TurnOffRequest
• SetPercentageRequest
• IncrementPercentageRequest
• DecrementPercentageRequest
• SetTargetTemperatureRequest
• IncrementTargetTemperatureRequest
• DecrementTargetTemperatureRequest
• GetTemperatureReadingRequest
• GetTargetTemperatureRequest
• SetLockState
• GetLockState
• SetColorRequest
• SetColorTemperatureRequest
Interested readers can get much more information from the web link:
https://alexa-node-red.bm.hardill.me.uk/docs
7.11.3 Project 40: Controlling an LED and a buzzer using Alexa – using
a trigger node
Description: In the previous Alexa based projects, the LED is turned ON and OFF by send-
ing spoken commands to Alexa. In some applications, you may want to turn the LED ON
by sensing a command, then you may want the LED to turn OFF automatically after some
time. For example, before entering a room, you may ask Alexa to turn the light ON and
after 15 seconds you may want the light to turn OFF automatically. This shows how it can
be done in this project.
Node-RED flow program: This can be done easily by adding a trigger node to Figure
7.30. In the example flow program shown in Figure 7.35, the LED is turned OFF after 15
seconds. The trigger node is configured to send 1 for 15 seconds and then it sends 0. Figure
7.36 shows the trigger node contents. Notice that the output of the trigger node is reset
if msg.payload is equal to 0 (i.e., if Alexa is asked to turn the Bedroom Light OFF).
● 213
● 214
8.1 Overview
MQTT stands for Message Queuing Telemetry Transport. It is a message protocol created
for machine-to-machine (M2M) communication and based on publishing and subscribing.
MQTT is especially useful when it comes to sending data and controlling information with
low bandwidth and high response times. This protocol is especially worth considering when
it is required to send data to actuators and retrieve data from sensors. MQTT was first de-
veloped by IBM in 1999 mainly for satellite communications, and since then has become
the standard communications protocol for the Internet of Things (IoT) applications. MQTT
uses your existing home network to send messages to your IoT devices and receive re-
sponses from them. The official website of MQTT is: http://mqtt.org.
MQTT works on top of the TCP/IP protocol and is faster than sending HTTP requests since a
message can be as small as two bytes and there are no headers as with HTTP. Additionally,
in MQTT, messages are distributed automatically to the interested clients.
In this chapter, you will be using MQTT with Node-RED on the Raspberry Pi Zero 2 W.
In Figure 8.1, for example, the temperature sensor publishes (or sends) its measured value
to the broker, who accepts and saves the data. The broker then sends this measured value
to other devices which have subscribed to receive this data.
● 215
In MQTT there are five basic concepts that you should understand:
• Publisher
• Subscriber
• Messages
• Topics
• Broker
Publisher: The publisher is the node that sends data or the message on a topic. For exam-
ple, a publisher can be a sensor node that sends the ambient temperature values.
Messages: Messages are the information exchanged within the MQTT network. A message
can be data or a command. For example, a message can be the temperature value, or a
command to turn ON a switch.
Topics: Topics are important concepts of MQTT. These are the ways you register interest
for incoming messages or how you specify where you want to publish the message. i.e.,
the message exchange takes place via the topics. Topics in MQTT are represented with
character strings, separated by a forward slash. Each forward slash indicates a topic level.
An example is shown below; this one creates a topic for an LED in your kitchen:
home/kitchen/led
In the above example, home, kitchen, and led are the topic levels and they are separated
by the topic level separators. The topics are case sensitive and for example, Home/kitchen/
led is not the same as above.
Single Level Wildcards: You can use wildcards in topics enabling several sensors to be
queried at the same time. A "+" sign is used to identify a single-level wildcard. An example
is given below:
Multi-Level Wildcards: You can also use multi-level wildcard, represented by the sign
"#". This must always be used at the end of a topic. An example is given below:
● 216
Broker: the broker receives all messages, filters them, decides who are interested in them,
and then sends the message to all subscribed clients.
Figure 8.2 illustrates the operation of the MQTT, which can be summarized as follows:
• The processor (and sensor) publishes ON and OFF messages on topic home/
kitchen/led.
You can make Mosquitto to auto-start on boot by entering the following command:
To evaluate the Mosquitto installation, enter the command mosquitto –v as shown in Fig-
ure 8.3. This command displays the version of the Mosquitto running on your system (don't
worry about the Error: Address already in use).
● 217
Now, because the terminal is listening for messages from your broker, you have to open an-
other session with your Zero 2 W so that you can publish messages. After opening another
window, enter the following command to publish to TestTopic:
Here, the topic name is after –t, and the message is after –m. After hitting the Enter you
will see the message appear on your subscriber terminal as shown in Figure 8.4.
Figure 8.5 shows the basic MQTT system setup. The sensors, actuators, relays, switches,
lamps, LEDs, and so on are connected to the system via an Arduino, ESP32, ESP8266, or
any other compatible processor (system).
● 218
Node-RED offers two MQTT nodes (mqtt in and mqtt out) which can be found in the net-
work palette as shown in Figure 8.6.
You can send a message to the MQTT broker using an inject node of Node-RED as shown
in Figure 8.7. Notice that the small green box under the mqtt out node indicates that the
connection from the mqtt out node to the broker has been established. In Figure 8.7, the
topic is set to TestTopic, and the inject node Payload is set to message Hello From
Me!!. This message is displayed on the MQTT subscriber as shown in the image. In this flow
program, the mqtt out node Server was set to localhost and the Port number was set
to 1883 (network ports 1883 and 8883 are reserved by default):
Notice that, by using different topics you can send (publish) different messages, and these
messages will be received by the subscribers having the same topics.
● 219
A quite simple example is given below which illustrates how an LED can be controlled using
the MQTT.
Circuit Diagram: In this project, an LED is connected to Raspberry Pi Zero 2 W port pin
GPIO17 (pin 11) through a 470-ohm current-limiting resistor.
Node-RED flow program: Figure 8.8 shows the flow program of the project. Basically,
two inject nodes are used with the Payloads set to 1 and 0 respectively (see Figure 8.9 for
one of the nodes). Use an mqtt out node with the name TestTopic, Server set to local-
host, and port set to 1883. Connect the two inject nodes as shown in Figure 8.9. When,
for example, the button of the upper inject node is clicked, then a 1 is sent to the broker
via the mqtt out node. The mqtt in node in the lower flow is given the same topic name
as the mqtt out node, and this node drives the rpi gpio out node which controls the LED
accordingly. Name the rpi gpio out node as LED and configure it for GPIO17 with the initial
pin state set to digital 0. Click Deploy. Click the left part of the upper inject node to turn
ON the LED, Similarly, click the left part of the bottom inject node to turn OFF the LED.
The Raspberry Pi Zero 2 W console displays the data received by the GPIO port since it is
subscribed to the same topic, as shown in Figure 8.11.
● 220
In more complex projects, instead of using inject nodes, you usually have processors with
sensors connected to their inputs. The data from these sensors gets sent to the broker via
the mqtt out node. The mqtt in node then receives and processes this data (e.g., display
or activate an actuator).
In the next section, you will learn how to use the ESP8266 NodeMCU development board
as the client in an MQTT application.
8.6 Project 42: Controlling an LED using ESP8266 NodeMCU with MQTT
– LED connected to Raspberry Pi Zero 2 W
Description: This is quite a simple project where an LED is connected to one of the GPIO
ports of the Raspberry Pi Zero 2 W. Additionally, a pushbutton switch is connected to the
ESP8266 NodeMCU. The LED is toggled when the button is pressed. The aim of this project
is to show how the MQTT can be used with the ESP8266 NodeMCU and the Zero 2 W. Here,
the NodeMCU is the client (publisher) and the Zero 2 W is the subscriber which receives
the messages.
Block Diagram: Figure 8.12 shows the block diagram of the project.
● 221
Circuit Diagram: The circuit diagram of the project is shown in Figure 8.13. The button is
connected to port pin GPIO2 of the ESP8266 NodeMCU. Similarly, the LED is connected to
port pin GPIO2 of the Raspberry Pi Zero 2 W.
ESP8266 NodeMCU Program Listing: Figure 8.14 shows the program listing (program:
mqttesp8266). NodeMCU employs the Wi-Fi link to communicate with the Raspberry Pi
Zero 2 W in MQTT-based applications. Therefore, you need to know the SSID name and the
password of your Wi-Fi router and the IP address of your Raspberry Pi Zero 2 W. In this
example you have the following settings (you will have to enter your own settings):
SSID: BTHomeSpot-XNH
Password: 49350baeb
Raspberry Pi IP address: 192.168.1.238
You have to enter these values into your program. Notice that the Button is connected to
port pin GPIO2 of the ESP8266:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
● 222
In this example, you have chosen the MQTT topic as: kitchen/light
WiFiClient wclient;
PubSubClient client(wclient);
Inside the setup() function you will initialize the Arduino IDE Serial Monitor at 115200
Baud so that you can trace the execution of the code easily. You will also have to configure
port pin GPIO2 where the button is connected to as input and enable the pull-up resistor,
and then enable the Wi-Fi on your ESP8266 NodeMCU:
void setup()
{
Serial.begin(115200);
pinMode(Button, INPUT);
digitalWrite(Button, HIGH);
delay(100);
setup_wifi();
client.setServer(mqtt_server, 1883);
}
The Wi-Fi is set up inside the setup routine as follows (readers who used the ESP8266 be-
fore should be familiar with the following code):
void setup_wifi()
{
Serial.print("\nESP32 NodeMCU connecting to: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
● 223
The main program loop attempts to reconnect to the client by calling function reconnect if
the connection is lost, and reads the status of the button to check if it is pressed.
void loop()
{
if (!client.connected()) reconnect();
client.loop();
/******************************************************************
* ESP8266 NodeMCU MQTT PROGRAM
* ============================
* In this program a push-button switch is conencted to port
* GPIO2 of the EXP8266 NodeMCU. Similarly, an LED is connected
* to port GPIO2 of the Zero 2 W. The NodeMCU is the client.
* Pressing the button toggles the LED.
*
* Author: Dogan Ibrahim
* File : mqttesp8266
* Date : Janury, 2022
*
******************************************************************/
#include <ESP8266WiFi.h>
● 224
#include <PubSubClient.h>
WiFiClient wclient;
PubSubClient client(wclient);
//
// Connect to local Wi-Fi router. This function connects the
// NodeMCU to the local WiFi router. Because the Serial Monitor
// is enabled, we can see the progress in the monitor
//
void setup_wifi()
{
Serial.print("\nESP32 NodeMCU connecting to: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
//
// This is the setup routine. Here the Serial Monitor is enabled,
// Button is configured as digital input, and the WiFi is setup.
// Notice that the MQTT server (Zero 2 W) operate on port 1883
//
void setup()
{
Serial.begin(115200); // Enable Serial Monitor
pinMode(Button, INPUT); // Button is input
digitalWrite(Button, HIGH); // Pull Button HIGH
delay(100); // Small delay
setup_wifi(); // Setup WiFi
client.setServer(mqtt_server, 1883); // Define client
● 225
//
// Reconnect to client if the connection is lost
//
void reconnect()
{
while (!client.connected())
{
Serial.print("Attempting MQTT connection...");
if (client.connect(ID))
{
Serial.println("connected");
Serial.print("Publishing to: ");
Serial.println(Topic);
Serial.println('\n');
}
else
{
Serial.println(" Trying to connect again in 5 seconds");
delay(5000);
}
}
}
//
// Main program loop. Check the Button status and publish on or off
// depending on this status
//
void loop()
{
if (!client.connected()) reconnect();
client.loop();
● 226
Node-RED flow program: Figure 8.15 shows the flow program for the Raspberry Pi Zero
2 W which consists of just three nodes: an mqtt in node, a function node, and an rpi
gpio out node.
• Create an mqtt in node and set its Server to localhost, Port to 1883, and the
Topic to kitchen/light/.
• Create a function node named ON/OFF and enter the following statements
inside this function:
if(msg.payload == "on")
msg.payload = 1;
else if(msg.payload == "off")
msg.payload = 0;
return msg;
• Create an rpi gpio out node and set the Pin to GPIO2, Type to digital output,
and Initialize to 0.
Testing
The project can be evaluated as follows:
• Power on the ESP8266 NodeMCU and open the Serial Monitor and set its Baud
rate to 115200.
● 227
• You should see messages on the Serial Monitor saying that the NodeMCU is
connected to your Wi-Fi (see Figure 8.16) and that it can publish to the MQTT
with the topic kitchen/light/
• Press the button. You should see the following message displayed on the Serial
Monitor (see Figure 8.17). At the same time, the LED will turn ON:
kitchen/light/ is ON
• Release the button and press again. You should see the following message
displayed on the Serial Monitor. At the same time, the LED will turn OFF:
kitchen/light/ is OFF
● 228
9.1 Overview
In the previous chapter, you explored the writing of programs aiming to use Wi-Fi and then
communicate with other devices over LAN using the UDP and TCP protocols. In this chapter,
you will develop programs for using Bluetooth communication.
The Raspberry Pi Zero 2 W supports both classic Bluetooth and Bluetooth Low Energy
(BLE). BLE is intended for reduced-power applications while providing reasonable range.
Most smartphones including Android, iOS, Windows Phone, Blackberry, macOS and many
others, support BLE. BLE uses the same 2.4-GHz radio frequency as the classic Bluetooth
and dual-mode devices, therefore can share the same, single antenna. Classic Bluetooth
can handle large amounts of data quickly, whereas BLE has been developed to handle
smaller amounts of data.
Block diagram: Figure 9.1 shows the block diagram of the project.
● 229
Enabling Bluetooth
Before using your smartphone for Bluetooth applications, you have to enable it. Depending
on the model of the smartphone you have, this is usually done from the Settings menu.
Similarly, before using Bluetooth on your Zero 2 W, you have to enable it. There are two
ways you can enable Bluetooth on the Zero 2 W: using the graphical desktop (GUI mode)
or using the command mode.
• If you have a monitor connected directly to the Zero 2 W, skip the next item.
• Start the VNC server on your Zero 2 W and log in using the VNC Viewer.
• Click on the blue Bluetooth icon on your Zero 2 W screen at the top right
hand side, and turn Bluetooth ON if it is not already ON. Then, select Make
Discoverable. You should see the Bluetooth icon flashing. Click Add Device.
• Click Pair to accept the pairing request on your Zero 2 W as shown in Figure
9.2.
• You should now see the message Pairing Successfully on your Zero 2 W.
● 230
You can enable Bluetooth on your Zero 2 W using the command mode. Additionally, you
can make Bluetooth discoverable, scan for nearby Bluetooth devices and then connect to a
Bluetooth device. The steps are given below (characters typed by the user are in bold for
clarity):
• Find the Bluetooth MAC address of your smartphone. For Android phones, the
steps are usually:
• Start the Bluetooth tool on your Zero 2 W from the command mode:
pi@raspberrypi:~ $ bluetoothctl
bluetooth]# power on
● 231
bluetooth]# agent on
[bluetooth]# default-agent
[bluetooth]# discoverable on
• Scan for nearby Bluetooth devices; this may take several minutes:
[bluetooth]# scan on
• Enter the command devices to detect any nearby Bluetooth devices (see
Figure 9.4). You may have to wait couple of minutes for the display to update.
Make a note of the MAC address of the device you wish to connect to (Android
mobile phone in this project) as you will be using this address to connect to the
device.
[Bluetooth]# devices
In this example, the author's smartphone is Galaxy A71 and the Bluetooth MAC
address is: 50:50:A4:0F:62:3F
● 232
You can find the Bluetooth MAC address of your Zero 2 W by entering the following com-
mand:
You can change the Bluetooth broadcast name by the following command:
• Add –C at the end of the ExecStart= line. Also add another line after the
ExecStart line. The final two lines should look like:
ExecStart=/usr/lib/bluetooth/bluetoothd -C
ExecStartPost=/usr/bin/sdptool add SP
● 233
Program listing: Figure 9.5 shows the program listing (Program: bluetxt.py). Do not call
your program: Bluetooth.py! The Bluetooth code is similar to TCP/IP code. At the begin-
ning of the program, the modules socket and Bluetooth are imported to the program. The
program then creates a Bluetooth socket, binds, and listens on this socket, and then waits
to accept a connection. The remainder of the program is executed in a loop where the pro-
gram issues the statement ClientSock.recv and waits to read data from the smartphone.
The received data is decoded and displayed on the screen. The user is then expected
to send text message to the smartphone. This message is displayed on the smartphone
screen. This process is repeated until halted by the user.
#=======================================================
# BLUETOOTH COMMUNICATION
# =======================
#
# In this project text messages are exchanged with a smart
# phone using the Bluetooth protocol
#
# Author: Dogan Ibrahim
# File : bluetxt.py
# Date : December, 2022
#========================================================
import socket
import bluetooth
#
# Start of main program loop.Configure Bluetooth, create a
# port, listen for client connections, and accept connection
#
port = 1
ServerSock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
ServerSock.bind(("", port))
ServerSock.listen(1)
ClientSock, addr = ServerSock.accept()
#
# Now receive text from smart phone and display
#
try:
while True:
data = ClientSock.recv(1024) # receive text
print("Received data: ", data.decode('utf-8'))
msg = input("Enter data to send: ") # TExt to send
ClientSock.send(msg.encode('utf-8')) # Send text
● 234
Testing
The project can be evaluated by the following steps:
• Make sure that Bluetooth is enabled on both the smartphone and the Zero 2 W
and the devices are paired.
• You will be using the freely available Bluetooth app on your smartphone to
communicate with your Zero 2 W. In this project, the app called Bluetooth
Terminal HC05 by mightyIT is used (Figure 9.6).
• Start the smartphone app and select the paired Zero 2 W device (e.g.,
raspberrypi).
• Enter a message in column Enter ASCII Command and press Send ASCII.
The message will be sent to the Zero 2 W.
• Enter a message on the Zero 2 W. This message will be sent and displayed on
the smartphone top part of the screen.
• Figure 9.7 shows a sample message exchange between the Zero 2 W and the
smartphone. In this example, the smartphone sends the message: message
from the smartphone and the Zero 2 W sends message: message from
Zero 2 W.
● 235
The following commands can be sent from the Android smartphone to control the LED:
Block diagram: Figure 9.8 shows the block diagram of the project.
Program Listing: Figure 9.9 shows the program listing of the project (program: blueled.
py; do not call your program Bluetooth.py!). The Bluetooth code is similar to TCP/IP
code. At the beginning of the program, the modules socket, RPi.GPIO, and Bluetooth are
imported to the program. The LED port is defined and configured as output. The program
● 236
then creates a Bluetooth socket, binds, and listens on this socket, and then waits to accept
a connection. The remainder of the program is executed in a loop where the program issues
the statement ClientSock.recv and waits to read data from the smartphone. Note that the
smartphone app automatically appends carriage-return (CR) and line-feed (LF) characters
to the end of the data (i.e. \r\n).
#=======================================================
# LED CONTROL BY BLUETOOTH
# ========================
#
# In this project an LED is connected to GPIO 17.The LED
# LED is controlled by sending commands from an Android
# smart phone using a Bluetooth apps.
#
# Valid comamdns are:
# L1 Turn ON the LED
# L0 Turn OFF the LED
#
# Author: Dogan Ibrahim
# File : blueled.py
# Date : December, 2022
#========================================================
import socket
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
import bluetooth
#
# LED is at GPIO 17, configure as output and turn OFF
#
LED = 17 # LED at port 17
GPIO.setup(LED, GPIO.OUT) # LED as output
GPIO.output(LED, 0) # LED OFF
#
# Start of main program loop.Configure Bluetooth, create a
# port, listen for client connections, and accept connection
#
port = 1
ServerSock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
ServerSock.bind(("", port))
ServerSock.listen(1)
ClientSock, addr = ServerSock.accept()
● 237
while True:
data = ClientSock.recv(1024) # receive command
if data == b'L1\r\n': # L1?
GPIO.output(LED, 1) # turn ON LED
elif data == b'L0\r\n': # L0?
GPIO.output(LED, 0) # turn OFF LED
Testing
The same Android app as in the previous project is used. The steps are:
• Make sure that the Bluetooth is enabled on both the smartphone and Zero 2 W
and that they are already paired.
• Start the app as before. To send command L1, enter L1 and click Send ASCII.
The LED should turn ON.
You could enter the program name in the following format inside file /etc/rc.local so that
the program automatically starts every time the Zero 2 W re-starts:
When you finish your project, don"t forget to remove the above line from file /etc/rc.lo-
cal, otherwise the program will run every time your Zero 2 W is restarted. You should also
shut down your Zero 2 W orderly instead of just unplugging the power cable. The command
to shut down properly is:
● 238
• +3.3 V to +6 V operation
• 30-mA unpaired current (10-mA matched current)
• Built-in antenna
• Band: 2.40 GHz – 2.48 GHz
• Power level: +6 dBm
• Default communication: 9600 baud, 8 data bits, no parity, 1 stop bit
• Signal coverage 30 feet (approx. 10 m)
• Safety feature: Authentication and encryption
• Modulation mode: Gaussian frequency-shift keying (FSK)
Block diagram: Figure 9.11 shows the block diagram of the project.
● 239
Circuit diagram: The circuit diagram is shown in Figure 9.12. The button is connected to
pin 2 of the Arduino Uno through a pull-up resistor. The relay is connected to port GPIO
4 of the Zero 2 W. The HC-06 is a serial device with TX and RX pins. Only the RX input of
the HC-06 are used since in this project you only send data to the Bluetooth module. The
output pin voltage of Arduino Uno is +5 V but the HC-06 is not +5 V compatible. Therefore,
a resistive voltage divider circuit is used to lower the Arduino voltage to +3.3 V. The TX pin
of HC-06 is connected to pin 3 of Arduino Uno (pin 3 is software-configured as a "software
serial port").
• Construct the Arduino circuit (Figure 9.12) and apply power so that HC-06 can
be accessed. The red LED on HC-06 will flash to indicate that it is not currently
connected to any device.
pi@raspberrypi:~ $ bluetoothctl
● 240
[bluetooth]# power on
[bluetooth]# agent on
[bluetooth]# default-agent
[bluetooth]# discoverable on
• Scan for nearby Bluetooth devices, you may have to wait several minutes:
[bluetooth]# scan on
• Enter command devices to see the nearby Bluetooth devices. You may have to
wait several minutes for the display to update. You should see the HC-06 listed
with its MAC address.
[Bluetooth]# devices
In this example, the author"s HC-06 was identified with the MAC address:
98:D3:91:F9:6C:19
• After finding out the MAC address, you may get information about the HC-06 by
entering the following command:
● 241
Exit the Bluetooth tool by entering Cntrl+Z and then enter the following statement to make
a connection in command mode (enter your own HC-06 MAC address):
You should be connected now and the red LED on HC-06 should stop flashing. You are now
ready to develop your programs for the Arduino Uno and Zero 2 W concurrently or sepa-
rately.
RPi Zero 2 W program: Figure 9.14 shows the Zero 2 W program (Program: zeroprog.
py). In this program, you will not be using the Bluetooth library. When you connect to the
HC-06, a virtual serial terminal named /dev/rfcomm0 is created on the Zero 2 W. You
can read the commands sent by the HC-06 by opening this serial port and then viewing
the traffic.
Serial port /dev/rfcomm0 is opened with the baud rate set to 9600 (the default baud rate
of the HC-06 is 9600) using the following statement:
data = ser.read()
If the received data is b"1" then the Relay can be activated for 5 seconds by the following
statements:
GPIO.output(RELAY, 1)
Time.sleep(5)
GPIO.output(RELAY, 0)
#=======================================================
# RELAY CONTROL BY BLUETOOTH
# ==========================
#
# In this Case Study a Relay is connected to GPIO 4.The
# Relay is controlled by sending command from an Arduino
# Uno using a Bluetooth apps.
#
# Valid command is: "1"
#
# Author: Dogan Ibrahim
# File : zeroprog.py
# Date : December, 2022
#========================================================
● 242
#
# Relay is on GPIO 2, configure as output and turn OFF
#
RELAY = 4 # Relay at port 4
GPIO.setup(RELAY, GPIO.OUT) # Relay as output
GPIO.output(RELAY, 0) # Relay OFF
#
# Attach to virtual serial port /dev/rfcomm0
#
ser = serial.Serial(port='/dev/rfcomm0', baudrate=9600)
#
# Now receive commands and decode
#
try:
while True:
data = ser.read() # receive comman
if data == b'1': # 1?
GPIO.output(RELAY, 1) # activate Relay
time.sleep(5) # 5 seconds
GPIO.output(RELAY, 0) # Relay OFF
Arduino Uno program: Figure 9.15 shows the Arduino Uno program (Program: ard-
prog). Software serial port is used in this program where pin 3 is configured as the TX pin
and pin 4 as the RX pin (RX is not used in this project). Button is then assigned to port 2.
Inside the setup() function, the serial port baud rate is set to 9600 and Button is config-
ured as an input pin. Inside the main program loop, the program waits until the button is
pressed and then released. A "1" is then sent to the HC-06, with the Zero 2 W responding
by turning ON the LED upon reception of this command.
● 243
/*================================================
ARDUINO UNO - RASPBERRY PI ZERO 2 W COMMS
=========================================
In this project a button is connectd to Arduino Uno
pin 2. HC-06 Bluetooth module is connected to pin 3
The program sends command "1" over the Bluetooth when
the button is pressed
void setup()
{
MySerial.begin(9600); // Baud rate
pinMode(Button, INPUT); // Button is input
}
//
// MAin program looop
//
void loop()
{
while (digitalRead(Button) == 1); // Button not pressed
while (digitalRead(Button) == 0); // Button not released
MySerial.print("1"); // Send "1"
delay(1000);
}
Testing
• Press and release the button. The LED should turn ON for 5 seconds.
● 244
9.5 Project 46: Play audio (like music) on a Bluetooth speaker via
Zero 2 W
Description: In this project you will play music on an external Bluetooth speaker via your
Raspberry Pi Zero 2 W. You will discover how to store your MP3 music files on the Zero 2 W
and then play them on the Bluetooth speaker.
Before you can send audio to a Bluetooth speaker, you have to have a program on your
Zero 2 W that can play audio files like MP3's. In this project, you will be using the popular
VLC Media Player program on your Zero 2 W. The steps to install VLC are:
You now have to pair with your Bluetooth speaker and connect to it. You will do this from
the Desktop. The steps are:
• Click the Bluetooth icon at the top right-hand corner of Desktop and select to
turn ON Bluetooth.
• Click on Bluetooth icon and click Add Device to pair and add your speaker,
or if your speaker is already listed., click on it and click to Connect (in the
author"s case, the Bluetooth speaker had the name BT-888). See Figure 9.16.
• You are now connected to your speaker. Next thing to do is to direct your audio
output to the speaker. Right-click on the Volume icon at the top right-hand
corner of Desktop and select your Bluetooth speaker"s name (like BT-888 in
author"s case).
● 245
• Click Media Quit to stop playing the music and exit from VLC.
Suggestion: You can create a Play List using the VLC Media Player and store your fa-
vorite music files in this list for playing later.
● 246
Appendix
Bill of Materials
Components and modules used to replicate the projects described in this book.
• 8× red LED
• 8× 470 ohm resistor
• 1× MCP3002 ADC
• 1× TMP36
• 2× HC-SR04 ultrasonic module
• 1× I2C LCD
• 1× Sense HAT
• 1× Buzzer
• 2× 10 k-ohm resistor
• 2× pushbutton switch
• 1× TXS0102
• 1× DHT11
• 1× BMP280
• 1× HC-06
Additionally
• 1× Raspberry Pi Zero 2 W
• 1× Raspberry Pi Pico W
• 1× Arduino Uno
• Jumper cables
• microUSB cables
• Breadboard
● 247
Index
A E
Advanced nodes 199 echo 112
ALEXA 207 Electronic dice 81
ambient temperature 165 Enabling Bluetooth 230
Analysis nodes 198
API Keys 167 F
Arduino Uno 239 Factorial 47
atmospheric pressure data 165 File processing 41
Average of 10 numbers 33 Flask 151
Average of two numbers 33 Function nodes 197
B G
BCM2710A1 12 GUI mode 29
BCM notation 84
bidirectional logic level converter 94 H
Binary counting 64 HC-06 Bluetooth module 239
Binary, octal, and hexadecimal 43 home automation 218
Bluemix 166 host 174
Bluetooth 229 hostname 172
bluetoothct 231
BMP280 165 I
Broker 215 ifconfig 172
Input nodes 196
C integration 49
Calculator 40 Interface Options 20
Channel Settings 167 IoT 218
CHOOSE OS 17 IP address 176
CHOOSE STORAGE 17
Christmas Lights 68 L
Cloud 165 LED brightness 86
Cloudino 166 local weather 188
Compound interest 48
Configuring Putty 20 M
Core nodes 196 matplotlib 52, 117
Cursor Color 20 matrices 44
Cursor Text 20 Matrix multiplication 47
MCP3002 99
D Morse Code exerciser 75
Data Import/Export 167 Mosquitto Broker 217
debugger 31 MQTT 215
Default Background 20 Multi-Level Wildcards 216
Default Foreground 20 multiple graphs 54
DHT11 115
display driver library 184
● 248
N static IP address 22
nano 24 Storage nodes 198
netstat 173 Subscriber 215
nmap 179 Surface area of a cylinder 34
Node-RED 191 T
numpy 117 Table of squares 36
Table of trigonometric sine 36
O TCP 133
Odd or even 43 temperature controller 127
Output nodes 197 TFT displays 182
ThingSpeak 166
P Thonny screen 31
Play audio 245 TightVNC for the PC 21
Plotting in Python 52 tightvncserver 20
Private View 167 TightVNC Viewer 21
Public View 167 timetable 42
Publisher 215 trig 112
Putty 18 Trigonometric function 37
TXS0102 94
Q
quadratic equation 46 U
UDP 133
R UDP Sender/Receiver 146
Raspberry Pi Pico W 158 ultrasonic transmitter/receiver 109
Raspbian 15 Using MQTT 215
raspi-config tool 175
Reaction timer 107 V
Real-Time graph 115 vehicle parking 109
Rotating LEDs 71 vi 24
route 173 vim 24
RP3A0 12 VNC 19
running Node-RED 191
W
S weather data 179
Seconds counter 94 Weather Map 180
Sense HAT 119 Web Server 151, 154
Shapes 44 Wi-Fi 133
Single Level Wildcards 216
Social nodes 198 Z
SOCK_STREAM 136 ZERO 2 WHC 13
SOS signal 62
SparkFun 166
SPI 103
Squares and cubes of numbers 42
SSH 19
ST7735 184
● 249
The Raspberry Pi
Zero 2 W GO! Book The Raspberry Pi
> Cloud storage of captured temperature, humidity, and pressure data Ground
D + A r d u i n
LC oo
TT + Bluet
All programs discussed in this book are contained in an archive file
you can download free of charge from the Elektor website. Head to:
+ I o T + M Q
www.elektor.com/books and enter the book title in the Search box.
Dogan Ibrahim