FAST School of Computing IO4041: Internet of Things
Working on Raspberry Pi
boards II
Operating Pi in headless mode
▪ Connecting a monitor is not always feasible.
▪ Particularly for IoT applications where Pi is used as data collection unit
or edge processing unit.
▪ Like on any computer, we can install remote desktop or remote login
server apps
▪ Then connect to Pi using client apps on another machine.
▪ Most popular client apps are
▪ TigerVNC for graphical remote desktop
▪ SSH for text-based remote login
▪ Headless machine is the one without a screen connected. Installation of
server apps is an essential prerequisite.
Operating Pi in headless mode
▪ Headless setup can be done
after a Pi has already booted up
(with a screen connected).
▪ More conveniently, the sever
apps can be pre-included in the
SD card image.
Optional ‘OS customization’ setup in Raspberry Pi Imager
Operating Pi in headless mode
To connect via SSH, use command ssh <username>@<server ip>
Voltage Level on GPIO Pins
▪ All GPIO pins on RPi operate at 3.3 Volts (not 5V)
▪ A voltage near 3.3V is treated as logic 1 (high)
▪ 5V pins are there only to supply power to external
devices (like sensors).
▪ To connect a push button to a GPIO, use a circuit
like the one shown.
▪ The 10k resistor performs ‘pull-down’ job when
switch is open.
Creating a voltage divider
▪ GPIO pins should never be connected to a voltage source higher than
3.3V, otherwise there is risk of pin damage.
▪ But several sensors (and other external modules) operate at 5V.
▪ Problem: How can Pi receive digital data that uses 5V as logic high?
▪ Solution: Make a voltage divider using two resistors.
R1 and R2 should be chosen such that 5V
input is stepped down to roughly 3.3V.
𝑅2
𝑉𝑜𝑢𝑡 = 𝑉𝑖𝑛
𝑅1 + 𝑅2
e.g.
when R1 = 300Ω, R2 = 550Ω, Vout = 3.24V
when R1 = 1kΩ, R2 = 2kΩ, Vout = 3.33V
Connecting an ultrasonic distance sensor
Connections
Pi ------ sensor
5V ------- Vcc
GND ------ GND
GP4 ------ Trig
GP17 ----- Echo (via divider)
Voltage divider is used to
convert sensor’s 5V echo
signal to 3.3V
https://projects.raspberrypi.org/en/projects/physical-computing/12
Connecting an ultrasonic distance sensor
▪ An ultrasonic distance sensor sends out pulses of (inaudible) ultrasound
and detects the echo that is sent back when the sound bounces off a
nearby object.
▪ It then uses the speed of sound to calculate the distance from the
object. Speed of sound in air is 343 m/s
▪ For Python code, gpiozero library takes care of all workflow, including
▪ Sending a pulse via Trigger pin
▪ Detecting the echo signal on Echo pin
▪ Converting echo time to distance
from gpiozero import DistanceSensor
ultrasonic = DistanceSensor(echo=17, trigger=4) # BCM pin numbers
while True:
print(ultrasonic.distance)
Controlling DC motor
▪ DC motors are frequently used in IoT projects, e.g. to turn wheels, to spin
something
▪ GPIO pins on Pi can not ‘drive’ a motor. Driving a motor requires
substantial power that Pi pins can’t supply.
▪ But we still want to be able to ‘control’ the motors with Pi, which means
start, stop, change speed etc.
▪ To help with this task, we need external ‘motor driver’ module that sits
between Pi and motor (Note: DC motor has only two terminals)
Reversing motor direction: H bridge
▪ A DC motor can spin forwards or
backwards depending on direction
of current flowing through it.
▪ It will be tedious to rewire the
motor every time you need to spin
in opposite direction.
▪ To solve this issue, motor driver
modules include a circuit that looks
like an ‘H’.
▪ It includes four transistors that act
as electronically controlled switches.
Switch-pairs are closed alternatively Switches (1, 4) and (2, 3) operate in pairs.
to reverse direction of current When one pair is open, other is closed.
through motor.
Motor driver module example
L293D is a well-known dual H-bridge motor driver It contains two H-
bridges to drive two motors independently
• Vss pin needs 3.3-5V for
internal circuit of L293D.
• Vs pin is for motor power
supply 4.5V to 36V.
• Enable pins should be set
motor2
motor1
to high for enabling the 1st
and 2nd H bridge
• Input pins connect to Pi,
output pins connect to
motor
https://www.instructables.com/DC-Motor-Control-With-Raspberry-Pi-and-L293D/
Circuit with L293D driver
https://theorycircuit.com/raspberry-pi/coding-raspberry-pi-interface-dc-motor/
Motor interfacing code
▪ Once again, gpiozero library provides very helpful abstractions.
▪ Motor speed is controlled via a PWM signal.
from gpiozero import Motor
# instantiate a Motor object, specifying BCM pin numbers
motor1 = Motor(forward=24, backward=23, enable=25)
motor1.forward() # start motor spinning at full speed
motor1.forward(0.5) # or set a slower speed (float 0 to 1)
motor1.backward(0.7) # spin backwards at 70% speed
motor1.reverse() # change spinning direction
motor1.stop() # stop spinning
Pi Camera modules
▪ Since Pi is a Linux computer with USB
ports, any USB camera can be used with
Pi (as long as device drivers are
installed).
▪ But in addition, Pi also has a dedicated
port for camera connections: it is
named Camera Serial Interface (CSI).
▪ CSI provides a direct and faster
interface to camera modules.
▪ Several official and third-party camera
modules are available
Enabling CSI
▪ Camera port is not enabled by
default.
▪ A reboot is required after
enabling it through config.
Access camera through code
Capturing stills
from picamera import PiCamera
camera = PiCamera()
# Adjust camera settings if needed
camera.hflip = True
camera.vflip = True
camera.brighness = 50
camera.resolution = (1024, 768)
# Take a picture
camera.capture('hello.jpg')
Access camera through code
Capturing videos
from picamera import PiCamera
import time
camera = PiCamera()
camera.start_recording('myvideo.mp4', format='h264')
time.sleep(10) # make a 10-second video
camera.stop_recording()
Access camera through code
Storing captures directly to a server. Use standard sockets API.
from picamera import PiCamera
import time
import socket
camera = PiCamera()
# Open a client socket
mysocket = socket.socket()
mysocket.connect(('<SERVER_ADDRESS>', 8000))
# Get a file-like object for this socket
conn = mysocket.makefile('wb')
# Pass this file-like object as capture destination
camera.capture(conn, format='jpeg')
References
▪ Remote access to Pi:
https://www.raspberrypi.com/documentation/computers/remote-
access.html
▪ Voltage dividers: https://pimylifeup.com/voltage-dividers/
▪ Circuits for GPIO: https://elinux.org/RPi_GPIO_Interface_Circuits
▪ Using motors: https://projects.raspberrypi.org/en/projects/physical-
computing/14
▪ Using camera: https://projects.raspberrypi.org/en/projects/getting-
started-with-picamera/4
▪ picamera API: https://picamera.readthedocs.io/