Motorcontrol Ebook
Motorcontrol Ebook
MOTOR CONTROL
Dogan Ibrahim
LEARN DESIGN SHARE
DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN
SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN
LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE
DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN
SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN
Motor Control
Projects with Arduino
&
Raspberry Pi Zero W
Dogan Ibrahim
an Elektor Publication
LEARN DESIGN SHARE
● This is an Elektor Publication. Elektor is the media brand of
Elektor International Media B.V.
78 York Street, London W1H 1DP, UK
Phone: (+44) (0)20 7692 8344
● 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 sue 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 and publisher have used their best efforts in ensuring the correctness of the information
contained in this book. They do not assume, or 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 caus
● ISBN 978-1-907920-66-0
Elektor is part of EIM, 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 (e.g., magazines, video, digital media, and social media)
in several languages - relating to electronics design and DIY electronics. www.elektor.com
LEARN DESIGN SHARE
Content
PREFACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.5.1 Torque. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
1.5.2 Speed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.5.3 Accuracy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.5.5 Cost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.8 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
●5
Motor Control - Projects with Arduino & Raspberry Pi Zero W
2.7 PROJECT 6 – Motor Speed and Direction Control Using H Bridge Integrated Circuit . . 70
●6
Content
●7
Motor Control - Projects with Arduino & Raspberry Pi Zero W
2.18 PROJECT 17 – Mobile Robot Basic Control (Raspberry Pi Zero W). . . . . . . . . . . . 131
●8
Content
4.3 PROJECT 2 – Controlling the Servo Motor with a Potentiometer (Arduino Uno) . . . 176
4.5 PROJECT 4 – Moving the Motor Shaft to a Given Angle (Raspberry Pi Zero W). . . . 183
●9
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 10
Content
INDEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
● 11
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 12
PREFACE
PREFACE
Arduino is probably the most widely used platform for developing microcontroller based
projects. It is used by students all over the world, by electronic hobbyists, and by anyone
else interested in developing a microcontroller based project. One of the strong points
of Arduino is that it is an open source computer hardware and is therefore supported by
large number of developers and groups. Arduino hardware is based on the popular Atmel
AVR and ARM Cortex processors. The boards are equipped with sets of analog and digital
input-output pins that may be interfaced to various external devices for monitoring and
control applications. Arduino programs are widely developed using te Integrated Develop-
ment Environment (IDE) which uses a dialect of features from the C and C++ programming
languages.
Raspberry Pi Zero W is the latest low-cost member of the Raspberry Pi family of single
board computers, which extends the basic family features by the addition of wireless LAN
and Bluetooth connectivity. This is a tiny board costing about $15 and including a 1 GHz
single-core BCM2835 CPU, RAM, and wireless chip supporting 2.4 GHz Wi-Fi 802.11n and
Bluetooth 4.0. Raspberry Pi Zero W uses the Linux distribution Rasbian operating system,
designed specifically for the Pi. The board includes large number of input-output ports and
supports various peripheral protocols, such as I2C, SPI, UART and so on. The processor can
be programmed using the highly popular Python programming language.
This book is about DC electric motors and their use in Arduino and Raspberry Pi Zero W
based projects. Many tested and working projects are given in the book for real-time con-
trol of standard DC motors, stepper motors, and servo motors, and mobile robots.
One of the interesting and strong points of this book is that it gives complete projects for
remote control of a mobile robot from mobile phones, using the Arduino Uno as well as the
Raspberry Pi Zero W as the controller processors. These projects are developed using Wi-Fi
as well as the Bluetooth connectivity.
I hope you like reading the book and find it useful for your next motor control or robotic
project.
● 13
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 14
CHAPTER 1 • ELECTRIC MOTORS
1 .1 Overview
In this Chapter we will be looking at the types and basic principles of the electric motors,
namely the DC motors which are commonly used in microcontroller based systems such as
robotics, factory automation, domestic and industrial control and so on.
• AC motors
• DC motors
Within these categories, there are subdivisions where Figure 1.1 shows some important
motor types in these subdivisions.
Alternating Current (AC) motors are not commonly used in robotics because most robots
are powered with batteries which are DC voltage. AC motors are generally used in industrial
automation applications where very large torques may be required, such as in conveyor
belts, cranes and so on.
● 15
Motor Control - Projects with Arduino & Raspberry Pi Zero W
In this book we are only interested in the following types of DC only electric motors:
• Brushed DC motors
• DC Servo motors
• DC stepper motors
• The brushes wear out in brushed DC motors and may need replacement
• Brushes generate electrical sparks which could fire or explosions in certain en-
vironments
• Brushes generate RF noise that may interfere with nearby electronic equipment
such as TVs, radios etc.
• Professional quality DC motors are expensive
1 .3 Brushed DC Motors
Brushed DC motors normally have two terminals and when voltage is applied across these
terminals the motor rotates proportionally. Brushed DC motors (BDC) are widely used in
most electronic toys and in other low-cost motor applications (Figure1.2). They are very
low-cost, easy to drive, and are available in many sizes and shapes, with and without gear
mechanisms. Unlike other motor types (e.g. brushless DC, and AC), brushed DC motors do
not require a controller to switch to switch the current in the motor windings. As shown in
Figure1.3, all BDC motors are made up of:
• A stator
• A rotor
• Brushes and a commutator
● 16
CHAPTER 1 • ELECTRIC MOTORS
The stator generates a stationary magnetic field that surrounds the rotor. This field is
generated by either permanent magnets placed around the rotor, or by electromagnetic
windings surrounding the rotor.
The rotor (see Figure 1.4) is also called the armature and it is made up of windings which
produce magnetic field when energized by applying a DC voltage. The magnetic poles of the
rotor are attracted to opposite magnetic poles of the stator, thus causing the rotor to turn.
The commutator (Figure 1.5) is placed on the axel of a BDC motor and as the motor turns,
carbon brushes provide supply voltage to the rotor windings through the commutator. The
brushes come in contact with different segments of the commutator, thus providing the
required supply voltage to different windings of the rotor. Note that the commutator is part
of the rotor and as the rotor turns so does the commutator.
● 17
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 18
CHAPTER 1 • ELECTRIC MOTORS
● 19
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 20
CHAPTER 1 • ELECTRIC MOTORS
1 .3 .6 Servo Motors
A servo motor allows for precise control of angular position of its rotor. It usually consists
of a DC motor coupled with a sensor for feedback so that the rotary position of the motor
can be controlled accurately. Servo motors run in closed loop mode to provide high per-
formance and accuracy. These motors are commonly used in radio controlled cars, boats,
helicopters, aeroplanes etc.
Servo motors are normally operated with PWM type pulses (positive going square wave-
form pulses) with a period of 50Hz (20ms period). In most types, a 1.5ms pulse puts the
motor in a stationary position, a 1ms pulse turns the motor 90 degrees to one direction,
and a 2ms pulse turns the motor 90 degrees in the opposite direction. Some types of servo
motors are modified such that they rotate continuously. Figure 1.12 shows a small servo
motor.
● 21
Motor Control - Projects with Arduino & Raspberry Pi Zero W
1 .3 .7 Stepper Motors
Stepper motors (see Figure 1.13) rotate in discrete steps when electrical pulses are applied
across its terminals in the correct sequence. The sequence of the applied pulses determine
the direction of rotation, while the speed of the motor shaft rotation is directly related to
the frequency of the input pulses, and the length of rotation is related to the number of
applied pulses. Stepper motors are ideal for open loop position control applications such as
in printers, plotters, PCB drilling machines and any other applications requiring precise con-
trol of the rotor position. Stepper motors have the disadvantage that the torque produced
is not very large.
Basically, there are two types of stepper motors: unipolar and bipolar. The main difference
between these two types is the applied voltage levels. Unipolar stepper motors (see Figure
1.14 for its circuit diagram) operate with positive voltages only (e.g. 0 and +12V). Bipolar
motors (see Figure 1.15 for its circuit diagram) on the other hand operate with positive and
negative voltages (e.g. -5V and +5V). As shown in the figures, unipolar motors require an
additional wire in the middle of each coil. Bipolar motors have the advantages that they
produce larger torques since the current flows in the entire coil and generates stronger
electromagnetic field, and also they require one less wire for operation.
● 22
CHAPTER 1 • ELECTRIC MOTORS
1 .4 Brushless DC Motors
In a brushless DC motor (BLDC) the rotor is a permanent magnet and the stator has wind-
ings. This is basically like a bushed DC motor turned inside out. There are no brushes or
a commutator in a brushless DC motor and because of this these motors last longer and
require little or no maintenance. In addition, brushless motors do not generate electrical
sparks and are therefore cleaner, less noisy, and more reliable. The disadvantage of these
motors is that they are more expensive. The sequence of voltages applied to the stator
windings replace the function of the commutator and turn the motor. The control of a
brushless DC motor is very different from the normal brushed DC motor as it requires sen-
sors to detect the rotor angular position before applying the voltage pulses. Speed control
of brushless DC motors are achieved using electronic Speed Control (ESC) modules.
1 .5 Motor Selection
Choosing an electric motor for an application is an important task when designing a mo-
bile robot or any other electric car. Some of the important motor specifications to consider
during a choice are:
● 23
Motor Control - Projects with Arduino & Raspberry Pi Zero W
• Torque
• Speed
• Accuracy
• Operating voltage
• Cost
• Physical size and weight
1 .5 .1 Torque
Torque is the turning ability of an electric motor. The higher the torque the more power
the motor has while turning an object. Torque is similar to force, but it is the rotational (or
twisting) force rather than linear force. Torque is calculated by multiplying the force applied
to an object with the perpendicular distance from the pivot point to the point where the
force is applied. A simple example is to imagine pushing a door to open. The applied force
causes the door to rotate about its hinges (the pivot point). The closer you are to the hinges
the harder it is to open the door because you apply a smaller torque. In SI units torque is
measured in Newton-metres, or Nm for short.
The required torque to drive the wheels of a robot (or an electric car) depends upon the
following factors:
• Rolling resistance
• Slope resistance
• Accelerating force
Rolling Resistance
The rolling resistance occurs as a result of the rolling motion of the wheel and it depends
upon the type of surface the wheel is on. The rolling resistance can be calculated as:
R = W x Cr
and
W=mxg
Where, W is the gross vehicle weight, m is the mass of the vehicle, g is the acceleration
due to gravity (9.81m/s2), and Cr is the rolling resistance coefficient, given in Table 1.1 for
some common surfaces.
● 24
CHAPTER 1 • ELECTRIC MOTORS
Slope Resistance
The slope resistance is important when the wheel is moving on an inclined surface. The
slope resistance is given by:
S = W x sin φ
Where φ is the inclination angle of the surface. For flat surfaces φ = 0 and therefore there
is no slope resistance.
Accelerating Force
Accelerating force helps the vehicle to come to a pre-defined speed from rest in a specified
period of time. It is given by:
A = m x a or A = W x a / g
Where, a is the required acceleration, m is the mass of the vehicle, and W is the gross
vehicle weight as before.
T=R+S+A
1 .5 .2 Speed
Speed requirement is easier to estimate as it depends on how fast we want the robot to
run. DC motors usually run at speeds of thousands of RPMs with very low torque. In prac-
tical applications we need to use gear mechanisms between the motor shaft and the actual
wheel. The resultant motor speed with a gear mechanism is given by:
1 .5 .3 Accuracy
Accuracy depends upon whether the motor is used for speed control or for position control.
In speed control applications we want the motor speed to stay the same even if a load is
applied to the motor shaft. In position control applications we want the motor shaft to ro-
tate the required amount and then stop. Accurate motor control is normally obtained using
closed loop control where feedback is used to sense the current speed of the position of the
motor. With the help of this feedback the error between the desired value and the actual
measured value is eliminated or minimized.
1 .5 .4 Operating voltage
The operating voltage is also an important factor when choosing a motor. Most electric mo-
tors used in toys and robotics are brushed DC motors operating with batteries. In general,
higher voltages result is higher motor speeds but this may require more batteries. Using
more batteries will make the vehicle heavier and also the cost of the batteries will increase.
Common voltages used in DC motors are 3, 5, 12 and 24 Volts. It is important to realise
that the motor windings may be damaged if a higher voltage than the absolute maximum
● 25
Motor Control - Projects with Arduino & Raspberry Pi Zero W
is applied to a motor. Similarly, the motor will not rotate if the applied voltage is lower than
the minimum operating voltage.
1 .5 .5 Cost
The cost of the motor is important in robotic applications. Usually lower cost motors may
not be of high quality and the brushes may need to be changed frequently. Such motors
can only be used in hobby applications. A choice should be made between the desired
quality and the cost.
Figure 1.16 shows the circuit diagram of the motor where R (in Ohms) and L (in Henries)
are the resistance and inductance of the motor windings, V (in Volts) is the applied DC
voltage, J (in Kg.m2/s2) is the inertial of the load attached to the motor, and Ve (in Volts) is
the back EMF (electromagnetic force) of the motor.
The torque generated by the motor is proportional to the current through the motor wind-
ings and it can be written as:
T = KT i
Where KT is the motor torque constant and i (in Amperes) is the current (1.1)
The back EMF is proportional to the motor angular speed W (rad/s) and is given by:
● 26
Θ Θ
Θ Θ
Θ Θ CHAPTER 1 • ELECTRIC MOTORS
Ve = KE W (1.2)
Notice that W = dΘ/dt where Θ is the angle rotated by the motor (in radians). KE is the
motor back emf constant.
Using Kirchoff's law, we can write the following equation about the motor circuit:
V – Ve = Ri + L di/dt (1.3)
Or,
V = Ri + Ldi/dt + KEW (1.4)
Also,
T = J dW/dt (1.5)
RJ dW LJ d 2W
V K EW (1.7)
K T dt K T dt 2
In small motors the inductance L is very small and can be neglected. Equation (1.7) then
becomes:
RJ dW
V K EW
K T dt (1.8)
Equation (1.8) is a first order equation. Using the Laplace transforms where s is the Laplace
operator, we can re-write it as:
W (s) 1
V ( s ) K E sRJ / K T (1.9)
or,
W (s) KT
V ( s ) K T K E sRJ (1.10)
We can therefore represent the transfer function of the motor as in Figure 1.17.
● 27
Motor Control -Projects with Arduino & Raspberry Pi Zero W
KT
V(s) ---------------- W(s)
KTKE + sRJ
When a step voltage VO is applied across the motor terminals the motor speed increases ex-
ponentially until it settles down at a final value. The step response of the motor (i.e. the mo-
tor speed when a sudden step voltage is applied) can be derived by multiplying the transfer
function by 1/s and then taking the inverse Laplace transform. The result is given below:
KT K E t
V
W (t ) o 1 e RJ
KE (1.11)
Initially the speed is 0, and it increases exponentially, having a final value of W(t) = VO/KE.
Figure 1.18 shows the typical step response of the motor.
Notice that the term T = RJ/KTKE is known as the motor time constant of the motor and this
is the time it takes for the motor to reach 63% of its final value. Using the time constant,
we can re-write equation (1.11) as:
W (t )
VO
KE
1 e t / T (1.12)
● 28
CHAPTER 1 • ELECTRIC MOTORS
1 .8 Summary
In this Chapter we had a brief look at the types of electric motors. DC motors, especially the
brushed types are commonly used in most microcontroller based robotic and mechanical
movement applications. We have explored the basic principles and advantages/disadvan-
tages of these motors. Additionally, the servo motors and stepping motors have been de-
scribed briefly. The important topic of the choice of a motor for a project, and the DC motor
transfer function and step response, have also been explained briefly.
In the next Chapter we shall be looking at how to use the brushed DC motors in microcon-
troller based projects.
● 29
Motor Control - Projects with Arduino & Raspberry Pi Zero W
2 .1 Overview
In this Chapter, simple DC motor projects are explained. In all the projects in this Chapter a
small brushed permanent magnet DC motor will be used with an Arduino UNO development
board and also with a Raspberry Pi Zero W development board. Arduino programs will be
developed using the Arduino IDE and the Raspberry Pi programs will be developed using
Python programming language.
The projects will be described wherever possible by giving the following for each project:
In this Chapter the term microcontroller will be used to refer to the Arduino UNO develop-
ment board and also to the Raspberry Pi Zero W development board.
2 .2 .1 Block Diagram
Figure 2.1 shows the block diagram of the project. One of the output ports of the microcon-
troller is connected to the motor through a transistor driver.
● 30
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
no Uno through a 3.3K resistor, where the transistor is used as a switch. The motor is con-
nected across the collector of the transistor and the positive power supply. In this project
the motor operates with 3V – 6V. If you are using a larger motor requiring voltage higher
than 5V (or higher current that cannot be supplied by Arduino Uno) make sure that you
use an external power supply to drive the motor. Notice that a diode is connected across
the motor. This diode prevents back emf voltage from damaging the transistor. Back EMF
is generated when the motor is spinning and when the motor stops its windings still carry
charge which result in a reverse current to flow and this current can damage the transistor
if the diode is omitted. The diode must be chosen so that it can dissipate this current.
● 31
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 32
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
At the beginning of the program port 3 is defined as Motor, and ON and OFF are defined
as HIGH and LOW respectively. Inside the setup routine port 3 is configured as an output.
The main program runs in an endless loop where the motor is turned ON for 10 seconds,
and OFF for 5 seconds.
/*****************************************************************
* SIMPLE ON/OFF MOTOR CONTROL
* ===========================
*
* This is a very simple motor ON/OFF control. Pin 3 of the Arduino
* is connected to a small brushed DC motor through a transistor
* switch. The motor is turned ON for 10 seconds, then OFF for
* 5 seconds, and then ON again for 10 seconds. This process is
* repeated forever until stopped manually.
*
*
* File : Motor1
* Date : August 2017
* Author: Dogan Ibrahim
*****************************************************************/
#define Motor 3 // Motor pin
#define ON HIGH
#define OFF LOW
//
// Configure pin 3 where motro is connected as output
//
void setup()
{
pinMode(Motor, OUTPUT);
//
// Turn ON the motor for 10 seconds, then OFF for 5 seconds. This
// process is repated forever
//
void loop()
{
digitalWrite(Motor, ON); // Motor ON
delay(10000); // Wait 10 sec
digitalWrite(Motor, OFF); // Motor OFF
● 33
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Create the program using the nano editor and run it in the command mode (see Appendix
A) by giving the following command:
#-------------------------------------------------------------------
# SIMPLE ON/PFF MOTOR CONTROL
# ===========================
#
# This is a very simplr motor ON/OFF control. Port 2 of the Rpi ZW
# is connected to a small brushed DC motor through a transistor
# switch. The motor is turned ON for 10 seconds, then OFF for 5
# seconds, and then ON again for 10 seconds. This process is repeated
# forever until stopped manually.
#
# The H bridge is connected to pins 2,3,4,17 of the RPi
#
# File : motor1.py
# Date : August 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
Motor = 2
GPIO.setup(Motor, GPIO.OUT)
#
# Motor spins for 10 seconds, then stops for 5 seconds. This process
# is repeated until stopped manually
#
while True:
GPIO.output(Motor, 1)
● 34
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
time.sleep(10)
GPIO.output(Motor, 0)
time.sleep(5)
Notice that you can copy your program file from the RPi ZW to a PC (e.g. for printing etc)
by using the WinSCP file transfer utility. This utility runs on the PC and can be downloaded
from the Internet free of charge.
● 35
Motor Control - Projects with Arduino & Raspberry Pi Zero W
2 .2 .7 Using a Relay
Motors can also be controlled using relays as the switching devices. Figure 2.11 shows the
circuit diagram where the transistor switch is replaced with a relay. The project constructed
on the breadboard is shown in Figure 2.12. Notice that the 3-pin relay with built-in diode
from Elektor is used in this project for simplicity. Again, it is recommended to use an exter-
nal power supply for the motor. Note that there is no change in the program.
● 36
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
● 37
Motor Control - Projects with Arduino & Raspberry Pi Zero W
2 .3 .1 Block Diagram
Figure 2.13 shows the block diagram of the project. A motor driver (MOSFET transistor)
and a push-button switch are connected to the microcontroller.
The DC motor in this project is controlled using PWM waves. PWM control is commonly used
to control motors efficiently. PWM signal is basically a high frequency positive only square
wave (typically 1 kHz or greater). The duty cycle of this waveform is varied in order to vary
the average voltage applied to the load. The duty cycle of PWM wave is normally expressed
as a percentage:
The average value of the voltage applied to the motor can be calculated by considering a
general PWM waveform shown in Figure 2.15. The average value A of waveform f(t) with
period T and peak value ymax and minimum value ymin is calculated as:
● 38
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
1 T
A f (t ) dt
T 0
(2.3)
or,
1 ON
T T
A y m ax dt y m in dt
T
0
TON
(2.4)
ymin = 0 and
the above
In a PWM waveform equation becomes
1
A
TON y max
T (2.5)
or,
A D y m ax
(2.6)
where D is the duty cycle. As it can be seen from equation (2.6), the average value of the
voltage applied to the motor is directly proportional to the duty cycle of the PWM waveform.
If the peak value of the applied voltage is ymax, then as the duty cycle varies from 0% to
100%, the average voltage at the motor varies from 0V to ymax.
● 39
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 40
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
where the button is connected to is at logic 1, pulled high by software. The project con-
structed on a breadboard is shown in Figure 2.19.
● 41
Motor Control - Projects with Arduino & Raspberry Pi Zero W
The frequency of the PWM depends upon the speed of the Timer/Counter which depends
upon counter's clock divided by a pre-scaler value. The pre-scaler is 3-bits wide and is
stored in the three least significant bits of the Timer/Counter registers CS02, CS01, and
CS00. The Timer/Counter registers are TCCR0B, TCCR1B, and TCCR2B. Notice that the
pairs of PWM pins have the same frequency. For example, PWM on pins 11 and 3 are con-
trolled by Timer/Counter TCCR2B, pins 9 and 10 are controlled by TCCR1B, and pins 5 and
6 are controller by TCCR0B.
The default values of the PWM frequencies at boot time are as follows:
In order to change the PWM frequency, we must re-load the three least significant bits of
the required Timer/Counter registers. The values and corresponding PWM frequencies for
PWM pins 11 and 3 are given below (these statements must be included in the setup rou-
tine of the program):
In this program the PWM frequency is set to 980.39 Hz by using the following statement
in the setup routine:
Figure 2.20 shows the Arduino program listing (program: Motor2). Compile the program
as usual and upload to your Arduino Uno. At the beginning of the program port pins 3 and
4 are assigned to names Motor and Button respectively. Inside the setup routine Motor is
configured as output and Button is configured as input and this pin is pulled up so the input
is normally at logic 1.
On Arduino Uno the duty cycle ranges from 0 to 255 where 0 corresponds to 0% and 255
● 42
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
corresponds to 100%. Inside the program loop the state of Button is checked. If the Button
is not pressed, the duty cycle is set to 100% (corresponding to 255), otherwise the duty
cycle is set to 25% (corresponding to 64).
/*****************************************************************
* TWO SPEED MOTOR CONTROL
* =======================
*
* This is a very simple motor speed control. Pin 3 of the Arduino
* is connected to a small brushed DC motor through a power MOSFET
* switch. Also, pin 4 is connected to a push-button switch. The
* output of the switch is normally at logic 1 (pulled up) and it
* goes to logic 0 when the button is pressed. The motor normally
* spins at full speed and when the button is pressed the speed
* falls by 25%. Motro voltage has PWM waveform that has a 100%
* duty cycle when the switch is not pressed, and 50% duty cycle
* when the switch is pressed.
*
* File : Motor2
* Date : August 2017
* Author: Dogan Ibrahim
*****************************************************************/
#define Motor 3 // Motor pin
#define Button 4 // Button pin
//
// Configure pin 3 where motro is connected as output
//
void setup()
{
pinMode(Motor, OUTPUT); // Motor is output
pinMode(Button, INPUT_PULLUP); // Button is input
TCCR2B = TCCR2B & B11111000 | B00000011; // PWM freq = 980.39Hz
}
//
// Generate PWM waveform at motor pin with a 100% duty cycle. When
// the button is pressed, change the duty cycle to 25%. Choose the
// PWM frequency as 1 kHz.
//
void loop()
{
if(digitalRead(Button) == 0)
analogWrite(Motor, 64 ); // 25% duty cycle
● 43
Motor Control - Projects with Arduino & Raspberry Pi Zero W
else
analogWrite(Motor, 255); // 100% duty cycle
}
Figure 2.20 Arduino program listing
Figure 2.21 shows the voltage waveform sent to the motor when the button is pressed (i.e.
25% duty cycle). This graph was obtained using a PCSGU250 PC based oscilloscope. The
horizontal axis was 1ms/division and the vertical axis was 3V/division. Notice that the PWM
frequency is approximately 1 kHz.
At the beginning of the program the GPIO library is imported, port pin 2 is configured as
output and port pin 4 is configured as input with the pin pulled high by software. The PWM
is started with frequency 1000Hz (1kHz) at duty cycle of 100% at pin 4 where the motor is
connected to. When the button is pressed the duty cycle is changed to 25%.
● 44
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
#-------------------------------------------------------------------
# TWO SPEED MOTOR CONTROL
# =======================
#
# This is a very simple motro speed control. Port 2 of the Rpi ZW
# is connected to a small brushed DC motor through a power MOSFET
# switch. Also, pin 4 is connected to a push-button switch. The
# output of the switch is normally at logic 1 (pulled up) and it
# goes to logic 0 when the button si pressed. The motor normally
# spins at ull speed and when the button is pressed teh speed falls
# by 25%/ Motor voltage hasPWM waveform that has 100% duty cycle
# when the switch is no pressed, and 25% duty cycle when the switch
# is pressed.
#
#
# File : motor2.py
# Date : August 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
Motor = 2
Button = 4
GPIO.setup(Motor, GPIO.OUT)
GPIO.setup(Button, GPIO.IN, pull_up_down=GPIO.PUD_UP)
#
# Generate PWM waveform at motor pin with a 100% duty cycle. When the
# switch is pressed, change the duty cycle to 25%. The frequency of the
# PWM waveform is set to 1000Hz
#
p = GPIO.PWM(Motor, 1000)
p.start(100)
while True:
if GPIO.input(Button) == 0:
p.ChangeDutyCycle(25)
else:
p.ChangeDutyCycle(100)
● 45
Motor Control - Projects with Arduino & Raspberry Pi Zero W
2 .4 .1 Block Diagram
Figure 2.23 shows the block diagram of the project. A motor driver (MOSFET transistor)
and a potentiometer are connected to the microcontroller.
The DC motor in this project is controlled using PWM waves as in the previous project. By
varying the potentiometer arm the analog voltage read by the microcontroller is varied and
this in turn changes the PWM duty cycle of the voltage applied to the motor, thus causing
the motor speed to change. Arduino Uno ADC (analog-to-digital converter) is 10-bits wide
and therefore it has 1024 steps (0 to 1023). The ADC reference voltage is +5V, making
each step 4.9mV.
● 46
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
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 2.26 shows the pin con-
figuration of the MCP3002.
● 47
Motor Control - Projects with Arduino & Raspberry Pi Zero W
In this project the supply voltage and the reference voltage are set to +3.3V. Thus, the
digital output code is given by:
each quantization level corresponds to 3300mV/1024 = 3.22mV. Thus, for example, input
data “00 0000001” corresponds to 3.22mV, “00 0000010” corresponds to 6.44mV 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 channel is
used in single ended mode and is used to determine polarity in pseudo-differential mode. In
this project we are using channel 0 (CH0) in single ended mode. According to the MCP3002
data sheet, SGL/DIFF and ODD/SIGN must be set to 1 and 0 respectively.
Figure 2.27 shows the circuit diagram of the project. The potentiometer is connected to
CH0 of the ADC. CS, Dout, CLK, and Din pins of the ADC are connected to the SPI pins (see
Appendix D) CE0 (pin 24), MISO (pin 21), SCLK (pin 23), and MOSI (pin 19) pins of the
Raspberry Pi Zero W. Figure 2.28 shows the project constructed on a breadboard.
● 48
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
Inside the program loop the analog voltage at the potentiometer arm is read as a digital
value between 0 and 1023. Since the duty cycle numbers range from 0 to 255, the poten-
tiometer reading is mapped to the duty cycle by dividing it by 4. For example, a potentiom-
eter reading of 400 corresponds to a duty cycle number of 100 (which corresponds to 25%
duty cycle). Similarly, a reading of 1023 approximately corresponds to 100% duty cycle.
● 49
Motor Control - Projects with Arduino & Raspberry Pi Zero W
/*******************************************************************
* VARYING THE MOTOR CONTROL
* =========================
*
* This is a very simple motor speed control. Pin 3 of the Arduino
* is connected to a small brushed DC motor through a power MOSFET
* switch. Also, analog pin A0 is connected to a potentiometer arm.
* The speed of the motor is varied by moving the potentiometer arm
*
*
* File : Motor3
* Date : August 2017
* Author: Dogan Ibrahim
*******************************************************************/
#define Motor 3 // Motor pin
#define Pot A0 // Button pin
//
// Configure pin 3 where motro is connected as output
//
void setup()
{
pinMode(Motor, OUTPUT); // Motor is output
TCCR2B = TCCR2B & B11111000 | B00000011; // PWM freq = 980.39Hz
}
//
// Generate PWM waveform at motor pin with a varying duty cycle
// where the duty cycle is set by the potentiometer between 0
// and 255 (i.e. 0% to 100%)
//
void loop()
{
int PotValue = analogRead(Pot); // Read Pot value
PotValue = PotValue / 4; // Convert to duty cycle
analogWrite(Motor, PotValue); // Set the duty cycle
}
Figure 2.29 Arduino program listing
Function 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 we have to send the
start bit, followed by the SGL/DIFF and ODD/SIGN bits and the MSBF bit to the chip.
● 50
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
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 must 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 we must extract the correct 10 bit ADC data from
this 24 bit data. The 24 bit data is in the following format (“X” is don't care bit):
Assuming that the returned data is stored in 24 bit variable ADC, we have:
Thus, we can extract the 10 bit ADC data with the following operations:
Adding the low byte and the high byte we get the 10 bit converted ADC data as:
DD DDDD DDDD
Function Description
● 51
Motor Control - Projects with Arduino & Raspberry Pi Zero W
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 RPi ZW in the
configuration menu. The steps are:
At the beginning of the program in Figure 2.30 modules RPi.GPIO and spidev are imported
to the program and an instance of the SPI is created. The program then configures port
2 where the motor is connected to as an output port. Function get_adc_data reads the
analog voltage at the potentiometer arm and returns a digital value between 0 and 1023.
Inside the main program loop the duty cycle of the PWM waveform is set based on the
value read by the ADC. Duty cycle is set such that 0% corresponds to ADC value 0, and
100% corresponds to ADC value 1023. As a result, the speed of the motor changes as the
potentiometer arm is moved.
#-------------------------------------------------------------------
# VARYING THE MOTOR SPEED
# =======================
# This is a very simple motor speed control. A brushed DC motor is
# connected to port pin 2 of the Raspberry Pi Zero W through a
# MOSFET switch. Also, a potentiometer is connected to the RPi ZW
# through the MCP3002 ADC. CH0 of the ADC is used in this project.
# The speed of the motor is varied by moving the potentiometer arm
#
● 52
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
#
# File : motor3.py
# Date : August 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
import spidev
#
# Create SPI instance and open the SPI bus
#
spi = spidev.SpiDev()
spi.open(0,0) # We are using CE0 for CS
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
Motor = 2
GPIO.setup(Motor, GPIO.OUT)
#
# 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
#
# Generate PWM waveform at motor pin with a varying duty cycle
# where the duty cycle is set by the potentiometer. The frequency
# of the PWM waveform is set to 1000Hz. The MCP3002 ADC is a 10
# bit converter (0 to 1023 levels). The duty cycle of the PWM is
# changed from 0% to 100% proportional to the potentiometer value
#
p = GPIO.PWM(Motor, 1000)
p.start(100)
while True:
adc = get_adc_data(0)
Duty = adc * 100 / 1023
p.ChangeDutyCycle(Duty)
● 53
Motor Control - Projects with Arduino & Raspberry Pi Zero W
2 .5 .1 Block Diagram
Figure 2.31 shows the block diagram of the project. A direction control driver circuit is used
to control the direction of the motor. The details of this circuit are explained below.
The speed of a DC motor can be changed by changing the applied voltage level. The direc-
tion of rotation can be changed by simply reversing the polarity of the supply voltage. In
DC motor direction control applications an H bridge circuit is used to change the polarity of
the voltage applied to the motor and hence change the direction of rotation. Figure 2.32
shows the basic operation of an H bridge circuit. Here, we have 4 switches labelled A,B,C,D
and the motor is connected in the middle of the circuit. By controlling the switches we can
easily change the polarity of the voltage applied to the motor. For example, by clocking
switches A and D and opening B and C, the motor will rotate clockwise. Similarly, by closing
switches B and C and opening A and D the motor will rotate in anti-clockwise direction. This
is illustrated below (0 and 1 correspond to switch open and close conditions respectively):
A B C D Motor rotation
0 0 0 0 No rotation
1 0 0 1 Clockwise
0 1 1 0 Anti-clockwise
It is clear from the above table that switches A and D and also B and C must be operated
together.
● 54
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
In real motor direction control applications the switches are replaced by transistors. Figure
2.33 shows an H bridge circuit built using bipolar transistors. In this circuit 4 signals are
required to control the motor direction as explained above. A simpler circuit using only two
control signals is shown in Figure 2.34. By using logic inverters we can make sure that only
one transistor in either side of the motor is turned ON. For example, when A is set to logic
1, the transistor at the top left is turned ON and the one at the bottom left is OFF. NPN and
PNP bipolar transistors can also be used in H bridge circuits requiring two control lines as
shown in Figure 2.35.
● 55
Motor Control - Projects with Arduino & Raspberry Pi Zero W
An H bridge circuit built using power MOSFET transistors is shown in Figure 2.36. Notice
that diodes are used in the H bridge circuits to protect the transistors from the back emf.
Also, in a 4 wire control, A and C or B and D must not be enabled at the same time as this
will short the power supply to the ground and possibly damage the bridge transistors.
● 56
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
● 57
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 58
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
Inside the program loop the state of the button is checked and if the button is pressed
(Button = 0) the motor is spinned anti-clockwise by calling function Anticlockwise. If on
the other hand the button is not pressed (Button = 1) then function Clockwise is called to
spin the motor clockwise.
In a clockwise rotation MOSFETS at pins A and D are turned ON and the other two are
turned OFF. Similarly, in an anticlockwise rotation MOSFETS at pins B and C are turned ON
and the other two are turned OFF.
● 59
Motor Control - Projects with Arduino & Raspberry Pi Zero W
/*****************************************************************
* MOTOR DIRECTION CONTROL
* =======================
*
* In this project the DC motor is connected to the Arduino Uno
* through a MOSFET based H bridge. In addition, a push-button
* switch is connected to port pin 4 of the Arduino Uno. Pressing
* the button changes the direction of rotation.
*
* The H bridge is controlled from port pins 0,1,2,3 of the Arduino
*
*
* File : Motor4
* Date : August 2017
* Author: Dogan Ibrahim
*****************************************************************/
#define A 0 // H bridge A input
#define B 1 // H bridge B input
#define C 2 // H bridge C input
#define D 3 // H bridge D input
#define Button 4 // Button input
//
// Configure H bridge pins as outputs and the Button pin as input
//
void setup()
{
pinMode(A, OUTPUT); // A is output
pinMode(B, OUTPUT); // B is output
pinMode(C, OUTPUT); // C is output
pinMode(D, OUTPUT); // D is output
pinMode(Button, INPUT_PULLUP); // Button is input
StopMotor(); // Stop the motor
}
//
// This function stops the motor
//
void StopMotor()
{
digitalWrite(A, LOW); // A = 0
digitalWrite(B, LOW); // B = 0
digitalWrite(C, LOW); // C = 0
digitalWrite(D, LOW); // D = 0
}
● 60
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
//
// This function turns the motor clockwise
//
void Clockwise()
{
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(A, HIGH);
digitalWrite(D, HIGH);
}
//
// This function turns the motor anticlockwise
//
void Anticlockwise()
{
digitalWrite(A, LOW);
digitalWrite(D, LOW);
digitalWrite(B, HIGH);
digitalWrite(C, HIGH);
}
//
// Motor spins in one direction. When the button is pressed the
// motor spins in the reverse direction
//
void loop()
{
if(digitalRead(Button) == 1)
Clockwise();
else
Anticlockwise();
}
Figure 2.41 Arduino program listing
Inside the program loop the state of the button is checked and if the button is pressed
(Button = 0) the motor is spinned anti-clockwise by calling function Anticlockwise. If on
● 61
Motor Control - Projects with Arduino & Raspberry Pi Zero W
the other hand the button is not pressed (Button = 1) then function Clockwise is called to
spin the motor clockwise.
In a clockwise rotation MOSFETS at pins A and D are turned ON and the other two are
turned OFF. Similarly, in an anticlockwise rotation MOSFETS at pins B and C are turned ON
and the other two are turned OFF.
GPIO.setup(A, GPIO.OUT)
GPIO.setup(B, GPIO.OUT)
GPIO.setup(C, GPIO.OUT)
GPIO.setup(D, GPIO.OUT)
GPIO.setup(Button, GPIO.IN, pull_up_down=GPIO.PUD_UP)
#
# This function stops the motor
#
def StopMotor():
GPIO.output(A, 0)
GPIO.output(B, 0)
GPIO.output(C, 0)
GPIO.output(D, 0)
return
● 62
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
#
#This function turns the motor clockwise
#
def Clockwise():
GPIO.output(B, 0)
GPIO.output(C, 0)
GPIO.output(A, 1)
GPIO.output(D, 1)
return
#
# This function turns the motor anticlockwise
#
def Anticlockwise():
GPIO.output(A, 0)
GPIO.output(D, 0)
GPIO.output(B, 1)
GPIO.output(C, 1)
return
#
# Motor spins in one direction. When the button is pressed the motor
# spins in the reverse direction
#
StopMotor()
while True:
if GPIO.input(Button) == 1:
Clockwise()
else:
Anticlockwise()
2 .6 .1 Block Diagram
The block diagram of the project is as in Figure 2.31. In this project the L293 (From Texas
Instruments. SN754410 is a similar integrated circuit) H bridge integrated circuit is used.
The chip has two H bridges, one on the left side of the chip and one on the right side, and
therefore it can drive two motors independently. The chip operating voltage is 4.5V to 36V
and it can drive up to 1 Ampere of current (L293D can supply up to 600mA of current).
● 63
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Figure 2.43 shows the pin configuration of L293. The pins have the following functions:
The pins on the right hand side of the chip have similar functions for another motor. Table
2.1 shows the motor control logic (for one motor only):
EN 1A 2A Function
1 0 1 Turn right
1 1 0 Turn left
● 64
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
● 65
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 66
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
Function Clockwise sets 1A to 0 and 2A to 1 so that the motor rotates clockwise. Similarly,
function Anticlockwise sets 1A to 1 and 2A to 0 so that the motor rotates anticlockwise.
Inside the main program loop the state of Button is checked. If Button is 1 (i.e. the button
is not pressed) then the motor spins clockwise. If on the other hand the Button is pressed
then the motor spins anticlockwise.
/*******************************************************************
* MOTOR DIRECTION CONTROL - H BRIDGE IC
* =====================================
*
* In this project the DC motor is connected to the Arduino Uno
* through the integrated circuit L293 H bridge. In addition, a push-button
* switch is connected to port pin 4 of the Arduino Uno. Pressing
* the button changes the direction of rotation.
*
* Arsduino Port pins 0 and 1 are connected to L293 pins 1A and 2A
* respectively. Motor roates one direction when 1A=0, 2A =1, and
* reverse direction when 1A = 1, 2A = 0. Power to the motor is
* supplied externally.
*
* File : Motor5
* Date : August 2017
* Author: Dogan Ibrahim
********************************************************************/
#define A1 0 // H bridge 1A input
#define A2 1 // H bridge 2A input
#define Button 4 // Button input
//
// Configure H bridge pins as outputs and the Button pin as input
//
void setup()
{
pinMode(A1, OUTPUT); // 1A is output
pinMode(A2, OUTPUT); // 2A is output
pinMode(Button, INPUT_PULLUP); // Button is input
StopMotor(); // Stop the motor
}
//
// This function stops the motor
//
void StopMotor()
{
digitalWrite(A1, LOW); // 1A = 0
digitalWrite(A2, LOW); // 2A = 0
● 67
Motor Control - Projects with Arduino & Raspberry Pi Zero W
}
//
// This function turns the motor clockwise
//
void Clockwise()
{
digitalWrite(A1, LOW);
digitalWrite(A2, HIGH);
}
//
// This function turns the motor anticlockwise
//
void Anticlockwise()
{
digitalWrite(A1, HIGH);
digitalWrite(A2, LOW);
}
//
// Motor spins in one direction. When the button is pressed the
// motor spins in the reverse direction
//
void loop()
{
if(digitalRead(Button) == 1)
Clockwise();
else
Anticlockwise();
}
Figure 2.48 Arduino program listing
#-------------------------------------------------------------------
# MOTOR DIRECTION CONTROL - H BRIDGE IC
# =====================================
#
# In this project the DC motor is connected to the RPi ZW through a
● 68
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
GPIO.setup(A1, GPIO.OUT)
GPIO.setup(A2, GPIO.OUT)
GPIO.setup(Button, GPIO.IN, pull_up_down=GPIO.PUD_UP)
#
# This function stops the motor
#
def StopMotor():
GPIO.output(A1, 0)
GPIO.output(A2, 0)
return
#
#This function turns the motor clockwise
#
def Clockwise():
GPIO.output(A1, 0)
GPIO.output(A2, 1)
return
#
# This function turns the motor anticlockwise
#
def Anticlockwise():
GPIO.output(A1, 1)
GPIO.output(A2, 0)
● 69
Motor Control - Projects with Arduino & Raspberry Pi Zero W
return
#
# Motor spins in one direction. When the button is pressed the motor
# spins in the reverse direction
#
StopMotor()
while True:
if GPIO.input(Button) == 1:
Clockwise()
else:
Anticlockwise()
2 .7 .1 Block Diagram
The block diagram of the project is shown in Figure 2.50. In this project the LMD18200 H
bridge motor controller integrated circuit is used. The chip has a built-in H bridge where the
speed and the direction of rotation of a motor can be controlled. The speed is controlled
by sending PWM waves to the chip, and the direction of rotation is controlled by setting or
clearing a direction control bit. LMD18200 has the following features:
• Up to 3A continuous current
• Supply voltage up to 55V
• TTL and CMOS compatible inputs
• Motor speed and direction control
• Thermal shutdown
• Motor stop (break) input
● 70
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
Figure 2.51 shows the pin configuration of LMD18200. The pins have the following func-
tions:
LMD18200 controller chip is available as a low-cost small module (see Figure 2.52) with an
on-board heatsink, capacitors, and two screw terminal type connectors for making connec-
tion to a microcontroller and a motor. The module has the following screw pin configuration:
● 71
Motor Control - Projects with Arduino & Raspberry Pi Zero W
1 1 1 Break
1 0 1 Break
0 X 1 Break
● 72
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
to connect the Arduino Uno to the screw terminals on the LMD18200 module.
● 73
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 74
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
is set HIGH. If the speed is f (i.e. fast) then PWM voltage with 100% (i.e. a value of 255)
duty cycle is sent to the PWM pin. If on the other hand the speed is s (i.e. slow) then the
PWM duty cycle is set to 25% (i.e. a value of 64)
/*****************************************************************
* MOTOR SPEED AND DIRECTION CONTROL USING AN IC
* =============================================
*
* This is a simple motor speed and direction control project
* using the LMD18200 motor control module. Pins 0 and 3 of the
* Arduino Uno are connected to pins DIR and PWM of the LMD18200
* respectively. A +12V external power supply is used to power the
* motor.
*
*
*
* File : Motor6
* Date : August 2017
* Author: Dogan Ibrahim
*****************************************************************/
#define DIR 0 // DIR pin
#define PWM 3 // PWM pin
//
// Configure DIR as output
//
void setup()
{
pinMode(DIR, OUTPUT); // Direction is output
pinMode(PWM, OUTPUT); // PWM is output
TCCR2B = TCCR2B & B11111000 | B00000011; // PWM freq = 980.39Hz
}
//
// This function rotates the motor. Argument direction can be 'c'
// for clockwise or 'a' for anticlockwise. Argument speed can be
// 'f' for fast or 's' for slow
//
void Rotate(char direction, char speed)
{
if(direction == 'c')
digitalWrite(DIR, LOW);
else
if(direction == 'a')digitalWrite(DIR, HIGH);
if(speed == 'f')
● 75
Motor Control - Projects with Arduino & Raspberry Pi Zero W
analogWrite(PWM, 255);
else
if(speed == 's')analogWrite(PWM, 64);
}
//
// The motor is rotated as follows:
// 5 seconds clockwise and fast
// 5 seconds clockwise and slow
// 5 seconds anticlockwise and fast
// 5 seconds anticlockwise and slow
//
void loop()
{
Rotate('c', 'f'); // clockwise, fast
delay(5000);
Rotate('c', 's'); // clockwise, slow
delay(5000);
Rotate('a', 'f'); // anticlockwise, fast
delay(5000);
Rotate('a', 's'); // anticlockwise, slow
delay(5000);
}
#-------------------------------------------------------------------
# MOTOR SPEED AND DIRECTION CONTROL USING AN IC
# ===================== =======================
#
# This is a simple motor speed and direction control project
# using the LMD18200 motor control module. Pins 2 and 3 of the
# Raspberry Pi Zero W are connected to pins DIR and PWM of the
# LMD18200 respectively. A +12V external power supply is used
# to power the motor.
● 76
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
#
#
# File : motor6.py
# Date : August 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
DIR = 2
PWM = 3
GPIO.setup(DIR, GPIO.OUT)
GPIO.setup(PWM, GPIO.OUT)
#
# Generate PWM waveform at PWM pin with frequency of 1000 Hz
#
p = GPIO.PWM(PWM, 1000)
p.start(100)
#
# This function rotates the motor with the given direction
# and speed
#
def Rotate(direction, speed):
if direction == 'c':
GPIO.output(DIR, 0)
else:
if direction == 'a':
GPIO.output(DIR, 1)
if speed == 'f':
p.ChangeDutyCycle(100)
else:
if speed == 's':
p.ChangeDutyCycle(25)
return
while True:
Rotate('c', 'f')
time.sleep(5)
Rotate('c', 's')
time.sleep(5)
● 77
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Rotate('a', 'f')
time.sleep(5)
Rotate('a', 's')
time.sleep(5)
2 .8 .1 Block Diagram
The block diagram of the project is shown in Figure 2.59. In this project a small geared
brushed DC motor with a built-in rotary encoder is used (Pololu's motor and encoder).
Figure 2.60 shows a picture of the motor where the rotary encoder is attached to the back
shaft of the motor.
A rotary encoder (or a shaft encoder) is a device that converts the angular position of a
rotating device such as a motor into an electrical signal. Rotary encoders are used in mo-
tor control applications to sense the speed of the motor or the position of the motor shaft.
There are basically two types of rotary encoders: optical and Hall Effect. Optical rotary
encoders work with optical principles where light shines onto a photodiode through slits (or
holes) in a metal or any other form of disc. By counting the number of holes passing in-
front of the photodiode in a given time we can calculate the speed of the motor.
● 78
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
In this project a Hall Effect based rotary encoder is used. Two static magnetic sensors
(called Phase A and Phase B) are used on the encoder board together with a rotating
magnetic disc. The sensors give out pulses as the motor is rotated. By counting the puls-
es in a given time we can calculate the speed of the motor. Figure 2.61 shows the output
waveform of the encoder used in this project. These types of encoders are also known as
quadrature encoders where there are four possible output states. The direction of rotation
is easily determined by finding the order that the output signals change from 0 to 1. For
example, if the Phase A signal rises when Phase A signal is LOW then the motor rotates in
one direction. If on the other hand Phase B signal rises when Phase A signal is LOW then
the motor rotates in the opposite direction (see Figure 2.62).
The specifications of the motor used in this project are as follows (depends on the voltage
applied):
● 79
Motor Control - Projects with Arduino & Raspberry Pi Zero W
• 6V DC operation
• Shaft speed 15000 RPM (at 6V)
• 380:1 gear ratio
• Speed after gears 41 RPM (at 6V)
• Motor torque 2.5Kg.cm
• Current 170 mA
• Built in Hall Effect with two sensors
• Disc with 7 pole pairs
• Hall Effect resolution (7 x 2 x 380 = 5320)
• Weight 18 grams
The speed of the motor is easily found by counting the number of pulses either from one
or from both encoders in a given time. For example, if only the rising edges of phase A
are counted every second then the speed of the motor shaft after the gears in RPM can
be calculated by dividing this count by the Hall Effect resolution and multiplying by 60 (60
seconds in a minute). i.e.
2 .8 .2 Circuit Diagram
The pin configuration of the motor is shown in Figure 2.63 and is as follows:
The circuit diagram of the project is shown in Figure 2.64. Only one of the encoder phases is
used in this example. The motor power is supplied externally using a +6V DC power supply.
The connection between the motor and the Arduino Uno are as follows:
● 80
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
Encoder pulses are received using one of the external interrupt inputs of the Arduino Uno.
Notice that the encoder output signal is very noisy and it may give rise to higher counts.
It is recommended to connect a capacitor from the encoder pin to ground to eliminate
this noise.
2 .8 .3 Program Listing
Arduino Uno has two external interrupt pins at GPIO ports 2 and 3. Pin 2 corresponds to in-
terrupt number 0 and pin 3 corresponds to interrupt number 1. When the attachInterrupt
(interrupt number,… .,… .) function is used to attach an interrupt to a function we have
to specify the interrupt number as the first argument of the function. Alternatively, we can
use function attachInterrupt(digitalPinToInterrupt(pin number),……,…) and specify
the GPIO pin number as the external interrupt pin.
Figure 2.65 shows the program listing of the project (program: motor7). PhaseA is as-
signed to pin number 2 and this pin is attached to interrupt service routine called Encod-
erISR. Variable interval is set to 1 second. Inside the EncoderISR the value of variable
Count is incremented by one.
Function millis() returns the number of milliseconds that elapsed since the program start-
ed running on the Arduino Uno. Inside the program loop the elapsed milliseconds since the
last time is calculated and if this is greater than or equal to the interval (1 second) then it is
assumed that a second has elapsed. At the end of one second the speed of the motor shaft
after the gears is determined in RPM by multiplying the Count by 60 and dividing by the
Hall Effect resolution. This is then displayed on the Serial Monitor of the Arduino IDE. Notice
that the Arduino delay function is not used here to create one second timing interval for
the Count since it gives inaccurate results when this function is interrupted by an external
or a timer interrupt. Instead, the mills() function is used to create a one second timing
● 81
Motor Control - Projects with Arduino & Raspberry Pi Zero W
interval. Figure 2.66 shows the speed displayed on the Serial Monitor.
/*****************************************************************
* MOTOR SPEED SENSE USING ROTARY ENCODER
* ======================================
*
* In this project the speed of a motor is measured using a Hall
* Effect sensor with a magnetic disc attached to the shaft of the
* motor.
*
* The speed (RPM) of the motor is found by counting the number
* of encoder pulses in a given time period (e.g. in a second).
*
* The rotary encoder ouput is connected to pin 2 of the Arduino
* Uno and the pulses generate external interrupts which are
* counted inside the interrupt service routine EncoderISR.
*
*
* File : Motor7
* Date : August 2017
* Author: Dogan Ibrahim
*****************************************************************/
#define PhaseA 2 // Phase A
volatile unsigned long Count = 0; // Encoder count
unsigned long Pulses; // Encoder pulses
unsigned long RPM; // Motor speed
unsigned long previousMillis = 0;
const long interval = 1000; // milliseconds
//
// This is the interrupt service routine which is called everytime
// a pulse is generated from the encoder output rising (going from
// LOW to HIGH)
//
void EncoderISR()
{
Count++;
}
//
// Configure Encoder Phase A as input. Also, attach the Encoder A
// output to external interrupt 0 (GPIO pin 2). The interrupt
// service routine is named EncoderISR and is when an interrupt
// occurs (an encoder pulse is generated). External interrupts
// are generated on the rising edge (LOW to HIGH) of the encoder
//
void setup()
● 82
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
{
Serial.begin(9600);
pinMode(PhaseA, INPUT); // Phase A is input
attachInterrupt(digitalPinToInterrupt(2), EncoderISR, RISING);
}
//
// Wait until a second has elapsed and then calculate the speed
// of the motor in RPM and display the speed on the Serial Monitor.
// The interval is set to 1000ms (1 second). When
// CurrentMillis-previousMillis = interval
// then it is assumed that a second has elapsed
//
void loop()
{
unsigned long CurrentMillis = millis();
if(CurrentMillis - previousMillis >= interval)
{
Pulses = Count; // Copy of Count
previousMillis = CurrentMillis;
Count = 0; // Clear Count
RPM = Pulses * 60 /5320; // Calculate RPM
Serial.println(RPM); // Display motor speed
}
}
Figure 2.65 Program listing of the project
In this project only one sensor is used. For more accurate results you may like to use both
sensors by connecting the PhaseB sensor output to external interrupt input pin 3 and then
incrementing Count in both interrupt service routines.
● 83
Motor Control - Projects with Arduino & Raspberry Pi Zero W
2 .9 .1 Block Diagram
Figure 2.67 shows the block diagram of the project.
2 .9 .2 Circuit Diagram
The circuit diagram of the project is shown in Figure 2.68. The LCD has 4 pins: GND, +V,
SDA, and SCL. GND and +V pins are connected to ground and +5V supply voltages of the
Arduino respectively. SDA is connected to pin A4 and SCL is connected to pin A5. PhaseA
output of the rotary encoder is connected to pin 2 of the Arduino as in the previous project.
The LCD used in this project is based on the I2C (or I2C) interface. I2C is a multi-slave,
multi-master, single-ended serial bus used to attach low-speed peripheral devices to micro-
controllers. 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 2.69 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.
● 84
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
2 .9 .3 Program Listing
The I2C LCD library supports the following commands:
Before programming the Arduino Uno for the I2C LCD, it is necessary to download and
include the I2C LCD library in our Arduino IDE folder (if it not already there). The steps to
do this are given below:
● 85
Motor Control - Projects with Arduino & Raspberry Pi Zero W
https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
• Click button Clone or download (see Figure 2.71) and copy all the files to the
LiquidCrystal_I2C folder as shown in Figure 2.72.
• Start the Arduino IDE. Go to File -> Examples and you should see Liquid-
Crystal_I2C examples in the drop down menu if the library has been installed
correctly.
● 86
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
The program listing is shown in Figure 2.73 (program: motor8). At the beginning of the
program libraries Wire (I2C library) and LiquidCrystal_I2C are included in the program.
Then the address of the LCD (0x27) and its configuration (16 columns by 2 rows) are de-
fined in the I2C LCD library. Inside the setup routine the program then initializes the I2C
LCD library and turns ON the backlight.
Inside the main program loop the encoder pulses are read as in the previous project and
displayed on the second row of the LCD. The text Motor Speed (RPM) is displayed on the
first row of the LCD. External interrupt on pin 2 is then assigned to interrupt service routine
EncoderISR as in the previous project. Figure 2.74 shows the output on the LCD.
/*****************************************************************
* MOTOR SPEED DISPLAY ON LCD
* ==========================
*
* In this project the speed of a motor is measured using a Hall
* Effect sensor with a magnetic disc attached to the shaft of the
* motor as in the previous project. An I2C LCD is connected to
* the Arduino UNO and the motor speed is displayed on the LCD in
* RPM.
*
*
* File : Motor8
* Date : September 2017
* Author: Dogan Ibrahim
*****************************************************************/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
//
// This is the interrupt service routine which is called everytime
// a pulse is generated from the encoder output rising (going from
// LOW to HIGH)
//
● 87
Motor Control - Projects with Arduino & Raspberry Pi Zero W
void EncoderISR()
{
Count++;
}
//
// Configure Encoder Phase A as input. Also, attach the Encoder A
// output to external interrupt 0 (GPIO pin 2). The interrupt
// service routine is named EncoderISR and is when an interrupt
// occurs (an encoder pulse is generated). External interrupts
// are generated on the rising edge (LOW to HIGH) of the encoder
//
void setup()
{
lcd.begin(); // Initialize LCD
lcd.backlight(); // Turn ON backlight
lcd.clear(); // Clear LCD
pinMode(PhaseA, INPUT); // Phase A is input
attachInterrupt(digitalPinToInterrupt(2), EncoderISR, RISING);
}
//
// Wait until a second has elapsed and then calculate the speed
// of the motor in RPM and display the speed on the Serial Monitor.
// The interval is set to 1000ms (1 second). When
// CurrentMillis-previousMillis = interval
// then it is assumed that a second has elapsed
//
void loop()
{
unsigned long CurrentMillis = millis();
if(CurrentMillis - previousMillis >= interval)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(“Motor Speed(RPM)”);
Pulses = Count; // Copy of Count
previousMillis = CurrentMillis;
Count = 0; // Clear Count
RPM = Pulses * 60 /5320; // Calculate RPM
lcd.setCursor(0, 1);
lcd.print(RPM);
}
}
Figure 2.73 Program listing of the project
● 88
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
Figure 2.75 shows the program listing (program: motor9). Notice here that the encoder
time interval is reduced to 5ms.
/*****************************************************************
* MOTOR STEP RESPONSE
* ===================
*
* In this project the speed of a motor is measured using a Hall
* Effect sensor with a magnetic disc attached to the shaft of the
* motor.
*
* The time response of the motor is plotted by applying a 6V
* step voltage and then plotting the speed in rad/sec using the
* Arduino Serial Plotter. The time interval of the encoder readinmg
* is set to 5ms.
*
*
* File : Motor9
* Date : August 2017
* Author: Dogan Ibrahim
*****************************************************************/
#define PhaseA 2 // Phase A
volatile unsigned long Count = 0; // Encoder count
● 89
Motor Control - Projects with Arduino & Raspberry Pi Zero W
//
// Configure Encoder Phase A as input. Also, attach the Encoder A
// output to external interrupt 0 (GPIO pin 2). The interrupt
// service routine is named EncoderISR and is when an interrupt
// occurs (an encoder pulse is generated). External interrupts
// are generated on the rising edge (LOW to HIGH) of the encoder
//
void setup()
{
Serial.begin(9600);
pinMode(PhaseA, INPUT); // Phase A is input
attachInterrupt(digitalPinToInterrupt(2), EncoderISR, RISING);
}
//
// Wait until a second has elapsed and then calculate the speed
// of the motor in RPM and display the speed on the Serial Monitor.
// The interval is set to 5ms
//
void loop()
{
unsigned long CurrentMillis = millis();
if(CurrentMillis - previousMillis >= interval)
{
Pulses = Count; // Copy of Count
previousMillis = CurrentMillis;
Count = 0; // Clear Count
RADS = Pulses * 200*2*3.1415 /5320; // Speed in rad/s
Serial.println(RADS);
}
}
Figure 2.75 Program listing of the project
● 90
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
The time response of the motor is plotted using the Serial Plotter menu option of the Ar-
by multiplying
duino IDE. Here, the
the speed bythe
Y axis is 2πmotor
and dividing
speed in by 60.
radians/sec and the horizontal axis is the
by multiplying the speed by 2π and dividing by 60.
time in units of 5ms (X axis ticks depend upon the interval of the Serial .println statements
used in the program). Figure 2.76 shows the time response of the motor.
The time response of a first order system is found by drawing a line through the initial
slope and then intersecting this line with the final value of the time response. The time at
the intersection point (point A in Figure 2.76) is the time constant of the system. In this
example, the time constant is found to be T = 107ms.
The time response of the motor is shown in Figure 1.12 in Chapter 1 and is repeated below:
W (t )
VO
1 e t /T
KE
(1.12)
Where T is the time constant and VO is the applied step voltage . When the speed settles
down, i..e at large values of time, equation (1.12) reduces to:
V
W (t ) O
KE
The test was carried out with a step input voltage of 6V. From Figure 2.76 the final value of
the speed is 7.5 rad/sec, therefore,
V 6
KE O 0 .8
W (t ) 7.5
The time response of the motor system can therefore be written as:
W (t )
VO
0.8
1 e t / 0.107
● 91
Motor Control - Projects with
Arduino & Raspberry Pi Zero W
or,
W (t ) 1.25VO 1 e t / 0.107
which corresponds to the motor transfer function in the Laplace domain of:
W (s) 0.208
VO ( s ) 0.107 s 1
● 92
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
PID controllers used to be analog where operational amplifiers and similar electronic devic-
es were used to implement the PID functions. The control action in the analog form of the
PID algorithmis as follows:
de(t )
u (t ) K p e(t ) K e(t )dt K
i d
dt
Where e(t) is the error term, Kp is the proportional constant, Ki is the integral constant, and
Kd is the derivative constant of the controller. There are many tuning algorithms that can
be used to estimate the optimum values of these constants. Nowadays, the PID algorithm
is implemented in software on microcontrollers where the digital form of this controller
is used. The digital PID controller has the following digital form, represented in terms of
Z-transforms (The details of the PID algorithm are beyond the scope of this book. Inter-
ested readers can find lots of information on PID controllers on the Internet and in many
automatic control books):
U ( z) K p E( z)
Ki
1
E ( z ) K d 1 z 1 E ( z )
1 z
the program
Figure 2.79 show listing
(program:
motor10).
At the beginning of the program
the I2C LCD libraries are included, PhaseA is assigned to pin 2 and PWM to pin 3 respec-
tively. The PID parameters are then defined and the sampling time is set to 100ms, and
the desired speed is set to 3 radians/second. In this project only PI (proportional+integral)
controller is used. In this type controller the steady state error is always zero. After several
trials and errors the constants Kp and Ki were set to 5.0 and 3.0 respectively which gave
satisfactory time response. Inside the setup routine PhaseA is configured as input and
● 93
Motor Control - Projects with Arduino & Raspberry Pi Zero W
PWM is configured as output. External interrupt from pin 2 is attached to interrupt service
routine EncoderISR.
Inside the program loop the speed of the motor is read as radians/second and stored in
variable Speed. The error between the desired speed and the actual speed is calculate and
stored in variable Error. Then the output of the PID algorithm is calculated and is stored in
variable pid. In PID controller applications wind-up errors can occur because the integral
term increases constantly if there is an error. Since this output can be very large as the
integrator term accumulates the error, it is necessary to limit it. The remainder of the pro-
gram limits the PID output and sends PWM voltage to the motor to control its speed.
The PID algorithm is implemented by the following code:
Figure 2.80 shows the speed response of the motor, plotted using the Serial Plotter of the
Arduino IDE. As it can be seen from this figure, the speed settles down to the desired value
of 3 radians/second.
The Serial .begin and Serial .println statement are used so that the time response can be
plotted. These statements can be removed in a working system to increase the throughput.
/*****************************************************************
* CLOSED LOOP MOTOR SPEED CONTROL
* ===============================
*
* This is a closed loop motor control project. The encoder reading
* is used as feedback and a PID algorithm is used to control the
* speed of the motor.
*
● 94
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
//
// This is the interrupt service routine which is called everytime
// a pulse is generated from the encoder output rising (going from
// LOW to HIGH)
//
void EncoderISR()
{
Count++;
}
//
● 95
Motor Control - Projects with Arduino & Raspberry Pi Zero W
//
// Wait until 100ms has elapsed and then calculate the speed
// of the motor. The sampling tiem is set to 100ms. This loop
// implements the PID algorithm
//
void loop()
{
unsigned long CurrentMillis = millis();
if(CurrentMillis - previousMillis >= interval)
{
lcd.clear(); // Clear lcd
Pulses = Count; // Copy of Count
previousMillis = CurrentMillis;
Count = 0; // Clear Count
Speed = Pulses *2*10*3.1415 /5320; // Actual speed
//
// Implement the PID algorithm
//
Error = DesiredSpeed - Speed; // Error term
Integrator = Integrator + Error;
pid = kp*Error + ki*Integrator; // PID output
PID = (int)pid;
if(PID > 0)
{
if(PID > 255) analogWrite(PWM, 255);
else analogWrite(PWM, PID);
}
● 96
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
if(PID < 0)
{
if(PID < -255)analogWrite(PWM,0);
else
{
PID = abs(PID);
analogWrite(PWM,255-PID);
}
}
lcd.setCursor(0, 0); // Set cursor at 0,0
lcd.print(DesiredSpeed); // Display desired
speed
lcd.setCursor(0,1); // Set cursor at 0,1
lcd.print(Speed); // Actual speed
Serial.println(Speed); // Remove for better performance
}
}
Figure 2.79 Program listing of the project
The project can be modified and can be made more user friendly if the desired speed is read
from an external potentiometer instead of hardcoding it in the program.
● 97
Motor Control - Projects with Arduino & Raspberry Pi Zero W
geared brushed DC motor as the one used in the last few Arduino Uno projects is used.
Level interrupts maintain the interrupt status until the level has been cleared by system
software. Rising edge detection is when the signal at the input pin goes from 0 to 1. Simi-
larly, falling edge detection is when the input signal goes from 1 to 0.
The circuit diagram of the project is shown in Figure 2.82. Only one of the encoder phases is
used in this example. The motor power is supplied externally using a +6V DC power supply.
The connection between the motor and the RPi ZW are as follows (since any input pin can
be configured for external interrupt, pin 2 is chosen in this example project):
● 98
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
Encoder pulses are received using one of the external interrupt inputs of the RPi ZW.
The main program is executed in a function called Encoder. Here, the total number of puls-
es counted in one second is used to calculate the motor speed in RPM. The result is then
displayed on the PC monitor. In this program the threading function is used to call function
Encoder every second. This function has the following format:
Function time .time() returns the time as a floating point number expressed in seconds
since the epoch, in UTC. Variable next_call is incremented by one at every iteration. In
the above statement, function Encoder is executed exactly every second at the same point
in the second.
#-------------------------------------------------------------------
# MOTOR SPEED SENSE USING ROTARY ENCODER
# ======================================
#
# In this project teh speed of a motor is measured using a Hall
# Effect sensor with a magnetic disc attached to the shaft of the
# motor.
#
# The speed (RPM) of the motor is found by counting the number of
# encoder pulses in a given time period (e.g. in a second).
● 99
Motor Control - Projects with Arduino & Raspberry Pi Zero W
#
# The rotary encoder output is connected to pin 2 of the RPi ZW
# and the pulses generate external interrupts which are counted
# inside the interrupt service routine EncoderISR
#
#
# File : motor7.py
# Date : August 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
import time
import threading
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
PhaseA = 2
global Count
Count = 0
GPIO.setup(PhaseA, GPIO.IN)
#
# This is the interrupt service routine. The program jumps
# here when a pulse is received from the encoder
#
def EncoderISR(dummy):
global Count
Count = Count + 1
#
# Attach function EncoderISR to pin 2 so that when pin 2
# goes 0 to 1 (rising) the program generates an interrupt
# and goes to function EncoderISR
#
GPIO.add_event_detect(PhaseA, GPIO.RISING, callback=EncoderISR)
next_call = time.time()
#
# Speed calculation routine. Here the encoder pulses are counted
# in one second and then the motor speed is calculated in RPM
# and displayed on the PC monitor using the print statement
#
def Encoder():
global Count, next_call
Pulses = Count
RPM = Pulses * 60 / 5320
print(RPM)
● 100
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
next_call = next_call + 1
threading.Timer(next_call-time.time(),Encoder).start()
Count = 0
#
# Start the speed calculation routine
#
Encoder()
while True:
pass
Figure 2.83 Program listing of the project
● 101
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Notice that the LCD is powered from an external +5V power supply since the +5V supply
of the RPi ZW does not have enough current to drive the LCD. Also note that there is no
problem mixing the +3.3V GPIO pins of the RPi ZW with the +5V of the I2C LCD. This is
because the RPi ZW is the I2C master device and the SDA and SCL lines are pulled up to
+3.3V through resistors. SCL line is the clock which is always output from the master de-
vice. The slave device (I2C LCD here) only pulls down the SDA line when it acknowledges
the receipt of data and it does not send any data to the master device. Therefore, there
are no voltage level problems as long as the RPi ZW I2C output pins can drive the I2C LCD
inputs, which is the case here.
Now we have to install the I2C library on our Rpi ZW. The steps are as follows:
• Enter the following command to test the installation. You should see i2c_
bcm2835 listed:
Add the following lines (if they are not already there):
● 102
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
i2c-bcm2835
i2c-dev
Exit from nano by typing Ctrl X and Y to save the file. You can check the
Contents of this file by entering the command:
• Connect your LCD to the RPi ZW device and enter the following command to
check whether or not the LCD is recognizedby the RPi ZW:
You should see a table similar to the one shown below. A number in the table
means that the LCD has been recognizes 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: -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
We should now install an I2C LCD library so that we can send commands and
data to our LCD. There are many Python libraries available for the I2C type LCDs.
The one chosen here is called the RPi_I2C_driver. This library is installed as
follows:
https://gist.github.com/DenisFromHR/cc863375a6e19dce359d
• Scroll down to section RPi_I2C_driver .py. Click Raw at the top right hand side
of the screen and save the file in a folder (e.g. Desktop) with the name RPi_
I2C_driver .py (the easiest option might be to copy the file into the Notebook
and then save it as RPi_I2C_driver.py).
● 103
Motor Control - Projects with Arduino & Raspberry Pi Zero W
• Start the WinSCP file copy utility (you should install it if you already do not have
it) on your PC and copy file RPi_I2C_driver .py to folder usr/lib/python2 .7
on your Raspberry Pi Zero W.
• Check to make sure that the file is copied successfully. You should see the file
listed with the command:
pi@raspberrypi: ~ $ ls /usr/lib/python2.7
We are now ready to write our program. Figure 2.86 shows the program listing (program:
motor8.py). At the beginning of the program libraries RPi.GPIO, timer, threading, and the
LCD driver library RPi_I2C_driver have been imported to the program. The heading MO-
TOR SPEED is then displayed on the LCD. Encoder pulses are attached to interrupt service
routine EncoderISR where the pulses are counted. Inside the Encoder routine the motor
speed is calculated and then displayed on the LCD in RPM.
#-------------------------------------------------------------------
# DISPLAY MOTOR SPEED ON LCD
# ==========================
#
# In this project the speed of a motor is measured using a Hall
# Effect sensor with a magnetic disc attached to the shaft of the
# motor.
#
# The speed (RPM) of the motor is found by counting the number of
# encoder pulses in a given time period (e.g. in a second).
#
# The motor speed is displayed on an I2C type LCD in RPM
#
# File : motor8.py
# Date : August 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
import time
import threading
import RPi_I2C_driver
LCD = RPi_I2C_driver.lcd()
LCD.lcd_display_string(“MOTOR SPEED”,1)
time.sleep(2)
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
PhaseA = 4
global Count
Count = 0
● 104
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
GPIO.setup(PhaseA, GPIO.IN)
#
# This is the interrupt service routine. The program jumps
# here when a pulse is received from the encoder
#
def EncoderISR(dummy):
global Count
Count = Count + 1
#
# Attach function EncoderISR to pin 2 so that when pin 2
# goes 0 to 1 (rising) the program generates an interrupt
# and goes to function EncoderISR
#
GPIO.add_event_detect(PhaseA, GPIO.RISING, callback=EncoderISR)
next_call = time.time()
#
# Speed calculation routine. Here the encoder pulses are counted
# in one second and then the motor speed is calculated in RPM
# and displayed on the PC monitor using the print statement
#
def Encoder():
global Count, next_call
Pulses = Count
RPM = Pulses * 60 / 5320
LCD.lcd_clear()
rpm = str(RPM)
LCD.lcd_display_string(rpm,1)
next_call = next_call + 1
threading.Timer(next_call-time.time(),Encoder).start()
Count = 0
#
# Start the speed calculation routine
#
Encoder()
while True:
pass
Figure 2.86 Program listing
The I2C LCD library supports the following functions (see the I2C LCD library documenta-
tion for more details):
● 105
Motor Control - Projects with Arduino & Raspberry Pi Zero W
2 .14 PROJECT 13 – Using Timer Interrupts to Calculate the Motor Speed (Ardui-
no Uno)
This project is similar to Project 7 where the speed of the motor is calculated and displayed
on the Serial Monitor. In this project Timer1 of the Arduino Uno is used to generate inter-
rupts every second. Inside the interrupt service routine the motor speed is calculated and
displayed. Using timer interrupts give very accurate results since the encoder pulses are
read exactly at every second.
2 .8 .3 Program Listing
Arduino Uno has 3 timers called timer0, timer1 and timer2. Each of these timers have a
counter that is incremented by one on each clock pulse. Once a timer counter reaches
the value stored in a compare match register it will clear to zero on the next clock pulse
and at the same time generate an interrupt (if interrupts are enabled). Arduino Uno clock
frequency is 16 MHz which has a period about 63ns. A pre-scaler register is used to divide
the clock frequency by a factor of 8, 64, 256 or 1024 so that longer interrupt times can be
obtained. Timer0 and timer 2 are 8 bit timers, meaning they can store a maximum counter
value of 255. Timer1 is a 16 bit timer which can store a maximum counter value of 65535.
By selecting a pre-scaler value we can set the time to interrupt as desired.
The number to be loaded into the compare match register can be calculated using the fol-
lowing formula (compare match register is zero indexed):
For example, to generate interrupts every second (1 Hz), assuming a pre-scaler of 1024
is used, the value to be loaded into the compare match register is calculated as follows:
The required pre-scaler value is selected by the three least significant bits CS12, CS11, and
● 106
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
CS10 of the TCCRxB register (x is 0 for timer0, 1 for timer1, and 2 for timer2) as shown
in Table 2.3
0 0 0 Timer stopped
0 0 1 No pre-scaling
0 1 0 1/8 pre-scaler
0 1 1 1/64 pre-scaler
1 0 0 1/256 pre-scaler
1 0 1 1/1024 pre-scaler
Timer registers must be configured correctly in order to generate interrupts at the required
times. The registers to be configured in Timer1 are: TCCR1A, TCCR1B, OCR1A, and TIMSK1
(timer0 registers are: TCCR0A, TCCR0B, OCR0A and TIMSK0. Similarly, timer2 registers
are: TCCR2A, TCCR2B, OCR2A, and TIMSK2). As an example, the code for configuring tim-
er1 to generate interrupts every second is given below:
Figure 2.87 shows the program listing (program: motor11). At the beginning of the pro-
gram PhaseA is assigned to port 2. Inside the setup routine the Serial Monitor is initialized,
and timer1 is configured to generate interrupts every second so that the program jumps to
function ISR(TIMER1_COMPA_vect) every second. Also, attachInterrupt is called to
attach the encoder interrupts to function EncoderISR so that the program jumps to this
function to increment the encoder pulse count whenever the encoder signal goes from 0
to 1 (rising). Inside the timer1 interrupt service routine the program calculates and then
displays the motor speed on the Serial Monitor of the Arduino IDE. Notice that the main
program inside the loop does not do any processing.
● 107
Motor Control - Projects with Arduino & Raspberry Pi Zero W
/*****************************************************************
* MOTOR SPEED DETECTION USING TIMER INTERRUPTS
* ============================================
*
* In this project the speed of a motor is measured using a Hall
* Effect sensor with a magnetic disc attached to the shaft of the
* motor.
*
* The speed (RPM) of the motor is found by counting the number
* of encoder pulses in a given time period (e.g. in a second).
*
* In this program Timer1 is configured to interrupt every second
* and the speed is calculated inside the timer interrupt service
* routine
*
*
* File : Motor11
* Date : August 2017
* Author: Dogan Ibrahim
*****************************************************************/
#define PhaseA 2 // Phase A
volatile unsigned long Count = 0; // Encoder count
unsigned long Pulses; // Encoder pulses
unsigned long RPM; // Motor speed
//
// This is the interrupt service routine which is called everytime
// a pulse is generated from the encoder output rising (going from
// LOW to HIGH)
//
void EncoderISR()
{
Count++;
}
//
// Configure Encoder Phase A as input. Also, attach the Encoder A
// output to external interrupt 0 (GPIO pin 2). The interrupt
// service routine is named EncoderISR and is when an interrupt
// occurs (an encoder pulse is generated). External interrupts
// are generated on the rising edge (LOW to HIGH) of the encoder
// This routine also configures the Timer1 interrupts so that they
// occur every second
//
void setup()
{
Serial.begin(9600);
● 108
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
//
// Timer1 interrupt service routine. Inside this routine calculate
// and display the motor speed on the Serial Monitor. This routine
// is called every second
//
ISR(TIMER1_COMPA_vect)
{
Pulses = Count; // Get pulses
Count = 0; // Clear Count
RPM = Pulses * 60 / 5320; // Calculate RPM
Serial.println(RPM); // Display RPM
}
//
// Main program loop - do nothing and wait for interrupts
//
void loop()
{
}
Figure 2.87 Program listing
● 109
Motor Control - Projects with Arduino & Raspberry Pi Zero W
The robot can be built in about half an hour using the instructions supplied. Figure 2.89
shows the robot in built form.
In this project we want to control the robot using an Arduino Uno and because of this the
Arduino Uno is mounted on the robot chassis using two small screws. Additionally a small
breadboard is fixed using Velcro and mounted on the robot chassis. 4 x NiZn AA batteries
are used as the power supply. The reason for using NiZn batteries is because each battery
provides 1.6V and therefore the total voltage is 4 x 1.6 = 6.4V. Arduino 5V regulator re-
● 110
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
quires at least 6V for its operation. Using standard alkaline AA batteries may not supply the
required voltage (we could also use a PP3 9V battery).
The robot motors are controlled using an L293 IC as described earlier in this book (see
Section 2.6). This IC was mounted on the breadboard. Figure 2.90 and Figure 2.91 show
the robot assembly with the Arduino, breadboard, batteries, and the jumper wires.
● 111
Motor Control - Projects with Arduino & Raspberry Pi Zero W
The power supply of the logic side (Vcc1) of the L293 H bridge chip is connected to the +5V
pin of the Arduino Uno. The motor supply voltage of L293 (pin Vcc2) is connected directly
to the battery + pin since Arduino cannot supply enough current to drive the motors.
● 112
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
L293 includes two independent motor driver circuits: 1A, 2A ,1Y, 2Y and 3A, 4A, 3Y, 4Y. The
control inputs 1A, 2A, 3A and 4A are connected to Arduino ports 0,1,2, and 3 respectively.
1Y and 2Y are connected across the terminals of the left wheel motor. Similarly, 3Y and 4Y
are connected across the terminals of the right wheel motor.
StopMotor: This function stops both motors, therefore stopping the robot, by sending logic
0 to all the control inputs of L293.
FORWARD: This function moves the robot forward. This is achieved by configuring both
motors to rotate in the same direction. The function accepts an argument which sets the
time in seconds the motors should run. The robot is stopped at the end of the function.
REVERSE: This function moves the robot in reverse direction. This is achieved by con-
figuring both motors to rotate in the same direction (opposite to the forward direction).
Again, the duration the motors should run is specified in the function argument. The robot
is stopped at the end of the function.
LEFT: This function turns the robot left. This is achieved by stopping the left hand side
motor and activating the right hand side motor. The motor run time is specified as an
argument. The robot is stopped at the end of the function. Another way to turn left is to
reverse the left motor and set the right motor to go forward. This gives a sharper turn with
smaller radius.
RIGHT: This function turns the robot right. This is achieved by stopping the right hand
side motor and activating the left hand side motor. The motor run time is specified as an
argument. The robot is stopped at the end of the function. Another way to turn right is to
● 113
Motor Control - Projects with Arduino & Raspberry Pi Zero W
reverse the right motor and sset the left motor to go forward. This gives a sharper turn
with smaller radius.
StopRobot: This function simply waits forever while the motor is stopped.
/*****************************************************************
* MOBILE ROBOT CONTROL
* ====================
*
* In this project a mobile robot is connected to the Arduino Uno.
* The robot is controlled as follows:
*
* Forward 3 seconds
* Stop for 2 seconds
* Reverse for 3 seconds
* Stop for 2 seconds
* Right turn and go for 3 seconds (keep turning right)
* Stop for 2 seconds
* Left turn for 3 seconds (keep turning left)
* Stop
*
* The aim of this project is to show how the basic movements of a
* robot can be done using an Arduino Uno
*
*
* File : robot1
* Date : September 2017
* Author: Dogan Ibrahim
*****************************************************************/
#define L1A 0 // LEFT motor 1A
#define L2A 1 // LEFT motor 2A
#define R3A 2 // RIGHT motor 3A
#define R4A 3 // RIGHT motor 4A
● 114
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
//
// Configure 1A, 2A, 3A, 4A as outputs
//
void setup()
{
pinMode(L1A, OUTPUT);
pinMode(L2A, OUTPUT);
pinMode(R3A, OUTPUT);
pinMode(R4A, OUTPUT);
}
//
// This function stops the motor
//
void StopMotor()
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, LOW);
digitalWrite(R3A, LOW);
digitalWrite(R4A, LOW);
}
//
// This function moves the robot forward for tim seconds. Both
// motors rotate in the same direction
//
void FORWARD(char tim)
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, HIGH);
digitalWrite(R3A, LOW);
digitalWrite(R4A, HIGH);
delay(tim*1000);
StopMotor();
}
//
// This function reverses the motor for tim seconds. Both motors
// rotate in the same direction
//
void REVERSE(char tim)
{
digitalWrite(L1A, HIGH);
digitalWrite(L2A, LOW);
digitalWrite(R3A, HIGH);
digitalWrite(R4A, LOW);
● 115
Motor Control - Projects with Arduino & Raspberry Pi Zero W
delay(tim*1000);
StopMotor();
}
//
// This function turns the motor LEFT for tim seconds. Left motor
// is stopped and the right motor is activated
//
void LEFT(char tim)
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, LOW);
digitalWrite(R3A, LOW);
digitalWrite(R4A, HIGH);
delay(tim*1000);
StopMotor();
}
//
// This function just waits (used to terminate the loop)
//
void StopRobot()
{
while(1);
}
// This function turns the motor RIGHT for tim seconds. Right motor
// is stopped and the left motor is activated
//
void RIGHT(char tim)
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, HIGH);
digitalWrite(R3A, LOW);
digitalWrite(R4A, LOW);
delay(tim*1000);
StopMotor();
}
//
// Main program loop. Control the robot
//
void loop()
{
FORWARD(3); // Go FORWARD 3 seconds
delay(2000); // Wait 2 secs
REVERSE(3); // REVERSE 3 seconds
● 116
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
● 117
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Vcc: +V power
Trig: Trigger input
Echo: Echo output
Gnd: Power ground
Therefore,
Figure 2.97 shows the principle of operation of the ultrasonic sensor module. For example,
if the time to receive the echo is 294 microseconds then the distance to the object is cal-
culated as:
● 118
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
Figure 2.98 shows the circuit diagram of the project. L293 and the wheel motors are con-
nected as in the previous project. The ultrasonic sensor is powered from the Arduino Uno
and the Trig and Echo pins of the ultrasonic sensor are connected to Arduino port pins 5
and 6 respectively.
Figure 2.99 shows the robot assembly with the ultrasonic sensor module mounted in a hole
near the front of the robot chassis using glue (it might be preferable to mount the sensor
in the middle right in-front of the robot).
● 119
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Functions FORWARD and LEFT move the robot forward and turn to left as described in the
previous project. Function GetDistance reads the distance to an object. The trigger pulse
is sent initially for 10 microseconds. The program then uses the built-in function pulseIn
and waits until the echo is received from the sensor. The time duration to echo is returned
in microseconds by the pulseIn function. The distance to the object is then calculated in
cm by multiplying the time duration by 0.017 and this value is returned to the main pro-
gram loop. Inside the main program loop the distance to the objects is calculated and if the
distance is less than or equal to 50cm then the robot turns left until the it finds a clearance
with a distance more than 50cm. When this clearance is found the robot moves forward.
This process is repeated forever until stopped manually by the user.
● 120
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
/*****************************************************************
* OBSTACLE AVOIDING ROBOT
* =======================
*
* This is an obstacle avoiding robot project. An ultrasonic sensor
* module is used to detect the distance in-front of the robot to
* the objects as the motor moves forward. If the distance to the
* object is 50cm or less then the robot turns left until it finds a
* clearance with no objects within 50cm and it then goes forward.
* This process continues forever until stopped manually
*
*
* File : robot2
* Date : September 2017
* Author: Dogan Ibrahim
*****************************************************************/
//
// Motor pin definitions
//
#define L1A 0 // LEFT motor 1A
#define L2A 1 // LEFT motor 2A
#define R3A 2 // RIGHT motor 3A
#define R4A 3 // RIGHT motor 4A
//
// Ultrasonic sensor module definitions
//
#define trig 5 // Trigger pin
#define echo 6 // Echo pin
float distance;
float allowed_distance = 50.0; // Allowed distance to
object
//
// Configure 1A, 2A, 3A, 4A as outputs. Also trig is an output and
// echo is an input. Stop the robot to start with
//
void setup()
{
pinMode(L1A, OUTPUT);
pinMode(L2A, OUTPUT);
pinMode(R3A, OUTPUT);
pinMode(R4A, OUTPUT);
pinMode(trig, OUTPUT);
pinMode(echo, INPUT);
StopRobot();
● 121
Motor Control - Projects with Arduino & Raspberry Pi Zero W
//
// This function stops the robot
//
void StopRobot()
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, LOW);
digitalWrite(R3A, LOW);
digitalWrite(R4A, LOW);
delay(2000);
}
//
// This function moves the robot forward
//
void FORWARD()
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, HIGH);
digitalWrite(R3A, LOW);
digitalWrite(R4A, HIGH);
}
//
// This function turns the motor LEFT
//
void LEFT()
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, LOW);
digitalWrite(R3A, LOW);
digitalWrite(R4A, HIGH);
}
//
// This function reads the distance to the object and returns the
// distance in cm
//
float GetDistance()
{
long duration;
float DistanceToObject;
digitalWrite(trig, LOW); // Clear trig
delay(80); // WAit to settle
● 122
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
Notice that in this program the left turn was done by stopping the left hand motor and set-
ting the right hand motor to go forward. In a small area it is more efficient to left turn by
reversing the left hand motor and setting the right hand motor to go forward. This gives a
much smaller radius of return, and is therefore suitable for small areas or if the allowable
object distance is small.
In this project a small mobile robot is used as in the previous projects. Two Light Dependent
resistors (LDRs) are mounted in-front of the robot, close to the floor. The robot follows a
dark black line drawn on a large paper.
● 123
Motor Control - Projects with Arduino & Raspberry Pi Zero W
LDR are light dependent resistors whose resistances depend upon the ambient light. When
exposed to light, the resistance is low, and when it is dark the resistance increases sharply.
Figure 2.102 shows a typical resistance-light curve of a typical LDR.
In this project two small LDRs are used to detect the dark line and then the robot is con-
trolled to follow the dark line. LDR has the advantage that it is much cheaper than an IR
sensor module, but it has the disadvantage that it is very sensitive to ambient light condi-
tions, and LDRs are very slow to respond to light changes. Because of this, it is advisable
to shine a bright white LED on the area where the robot is moving to minimize the effects
of ambient light. When an LDR is above the dark line its resistance increases sharply, and
when on the white paper, its resistance decreases. The LDRs are mounted in-front of the
robot close to the floor and are positioned on the robot chassis that one LDR is on the left of
the line and the other LDR is on the right of the line. The LDRs can be in 3 different positions
with respect to the dark line. Figure 2.103 shows these cases. In case 1, the robot moves
forward since the dark line is between the two LDRs. In case II, the left LDR is on the dark
line and the robot must be moved to the left. In case III, the right LDR is on the dark line
and the robot must be moved to the right.
● 124
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
The block diagram of the project is shown in Figure 2.104. A bright white LED is mounted
in-front of the robot to brighten the path so that the effects of the ambient light can be
minimized. The LDRs should be mounted about 5mm above the surface.
● 125
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Figure 2.106 and Figure 2.107 show the robot assembly with the two LDR sensors mounted
in-front of the robot together with the white light. The LDR used in this project is shown
in Figure 2.108. The LDRs are mounted at the end of small straws with the wires routed
inside the straws.
● 126
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
● 127
Motor Control - Projects with Arduino & Raspberry Pi Zero W
int valright;
void setup()
{
Serial.begin(9600);
}
void loop()
{
valright = analogRead(0);
Serial.println(valright);
delay(1000);
}
Figure 2.109 shows the path used to test the program where sticky black tape was used to
make the path. The complete program listing is shown in Figure 2.110 (program: robot3).
At the beginning of the program the motor connections are defined and they are set as
outputs in the setup routine. Inside the main program loop analog values of both LDRs are
read. It was found earlier during the tests that a dark line is detected if the analog read-
ing was over 500. Therefore, if the left LDR is over the dark line (valleft > 500) then the
robot is turned left. Similarly, if the right LDR is over the dark line (valright > 500) then
the robot is turned right. If none of the sensors are on the dark line then the robot moves
forward.
/*****************************************************************
* LINE FOLLOWING ROBOT
* ====================
*
* This is a line following robot project. In this project two LDR
* type sensors are monted in-front of the robot, close to the floor
* where the robot moves. The robot follows the black line drawn
* on the floor.
*
● 128
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
* File : robot3
* Date : September 2017
* Author: Dogan Ibrahim
*****************************************************************/
//
// Motor pin definitions
//
#define L1A 0 // LEFT motor 1A
#define L2A 1 // LEFT motor 2A
#define R3A 2 // RIGHT motor 3A
#define R4A 3 // RIGHT motor 4A
//
// Light Dependent Resistor (LDR) definitions
//
int valleft;
int valright;
//
// Configure 1A, 2A, 3A, 4A as outputs. Also, LDRs as inputs
//
void setup()
{
pinMode(L1A, OUTPUT);
pinMode(L2A, OUTPUT);
pinMode(R3A, OUTPUT);
pinMode(R4A, OUTPUT);
}
//
// This function moves the robot forward
//
void FORWARD()
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, HIGH);
digitalWrite(R3A, LOW);
digitalWrite(R4A, HIGH);
}
//
// This function turns the motor LEFT
//
void LEFT()
{
digitalWrite(L1A, HIGH);
digitalWrite(L2A, LOW);
● 129
Motor Control - Projects with Arduino & Raspberry Pi Zero W
digitalWrite(R3A, LOW);
digitalWrite(R4A, HIGH);
}
//
// This function turns the motor RIGHT
//
void RIGHT()
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, HIGH);
digitalWrite(R3A, HIGH);
digitalWrite(R4A, LOW);
}
//
// This function checks whether or not the robot is following the
// line. If the robot is to the left of the line then it is turned
// right, if it is to the right of the line then it is turned left,
// otherwise it goes forward
//
void loop()
{
valright = analogRead(0);
valleft = analogRead(1);
It is also possible to use more than 2 sensor modules for improved accuracy and smoother
movement. As mentioned earlier, the motor should also be slowed down if the path is small
and the sensors fail to detect the dark line as they pass over it. This is because the response
of the LDR is very slow. Additionally, other marks such as a stop mark can be drawn on the
line to stop the robot. A stop mark is usually a wide dark line drawn perpendicular to the
normal path and it is detected when both sensors are on this dark line (see Figure 2.111).
● 130
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
The robot motors are controlled using an L293 IC as in Project 14. Figure 2.112 shows the
block diagram of the project.
● 131
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Figure 2.114 shows the robot assembly with the RPi ZW, breadboard, battery pack, and
the portable charger.
● 132
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
It is possible to run a Python program automatically at boot time. The steps are as follows:
• Write the full path and name of the program to run at boot time into this file. e.g.
if the program name is myfile .py and it is in folder /yourpath, write the follow-
ing statement inside file rc .local. Notice that the statement must be terminated
with an ampersand character (&) so that the program runs in the background.
If the ampersand is omitted and your program is in a loop then the RPi ZW will
never complete its boot process:
● 133
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Notice that by default, unless changed, your path after logging in to the RPi ZW is /home/
pi
Figure 2.115 shows the program listing of the project (program: robot1.py). The four basic
motor movements are achieved as follows:
At the beginning of the program L293 pins are defined and configured as outputs. Functions
are then created to move the motor forward, reverse, turn left, and turn right.
#-------------------------------------------------------------------
# BASIC ROBOT MOVEMENTS
# =====================
#
# This is a simple robot control project. In this project the RPi ZW
# is mounted on the robot chassis. The L293 IC is used as the motor
# driver. The aim of this project is to show how the basic robot
# movements can be done using the Python programming language
#
# In this project the robot moves as follows:
#
# Forward for 2 second
# Stop 2 seconds
# Reverse for 2 seconds
# Stop 2 seconds
# Forward for 2 seconds
# Stop 2 seconds
# Turn left for 1 second
# Stop 2 seconds
# Forward for 2 seconds
# Right for 1 second
# Stop 2 seconds
# Reverse for 1 second
# Stop
#
#
# File : robot1.py
# Date : August 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
● 134
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
#
# L293 control pins
#
L1A = 2 # GPIO2
L2A = 3 # GPIO3
R3A = 17 # GPIO17
R4A = 27 # GPIO27
#
# Configure L293 control pins as outputs
#
GPIO.setup(L1A, GPIO.OUT)
GPIO.setup(L2A, GPIO.OUT)
GPIO.setup(R3A, GPIO.OUT)
GPIO.setup(R4A, GPIO.OUT)
#
# Stop the motor
#
def StopMotor():
GPIO.output(L1A, 0)
GPIO.output(L2A, 0)
GPIO.output(R3A, 0)
GPIO.output(R4A, 0)
return
#
# Set forward movement
#
def FORWARD(tim):
GPIO.output(L1A, 0)
GPIO.output(L2A, 1)
GPIO.output(R3A, 0)
GPIO.output(R4A, 1)
time.sleep(tim)
return
#
# Set reverse movement
#
def REVERSE(tim):
GPIO.output(L1A, 1)
GPIO.output(L2A, 0)
GPIO.output(R3A, 1)
● 135
Motor Control - Projects with Arduino & Raspberry Pi Zero W
GPIO.output(R4A, 0)
return
#
# Turn left
#
def LEFT(tim):
GPIO.output(L1A, 1)
GPIO.output(L2A, 0)
GPIO.output(R3A, 0)
GPIO.output(R4A, 1)
time.sleep(tim)
return
#
# Turn right
#
def RIGHT(tim):
GPIO.output(L1A, 0)
GPIO.output(L2A, 1)
GPIO.output(R3A, 1)
GPIO.output(R4A, 0)
time.sleep(tim)
return
#
# Start of the main program loop
#
FORWARD(2)
time.sleep(2)
REVERSE(2)
time.sleep(2)
FORWARD(2)
time.sleep(2)
LEFT(1)
FORWARD(2)
RIGHT(1)
time.sleep(2)
REVERSE(1)
StopMotor()
while True:
pass
Figure 2.115 Program listing
● 136
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
The program name robot1 .py was inserted into file /etc/rc .local. The contents of file /
etc/rc .local is shown in Figure 2.116. The program starts automatically after reboot or
when power is applied to the RPi ZW. Make sure that your program is free of errors before
inserting it into file /etc/rc .local.
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will “exit 0” on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
After applying power to the robot, wait until the RPi ZW boots and the program should start
automatically. You should remove your Python program name from file /etc/rc .local after
testing and completing your project so that the program does not start every time you
restart your RPi ZW.
● 137
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 138
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
Port pins GPIO2 (pin 3), GPIO3 (pin 5), GPIO17 (pin 11) and GPIO27 (pin 13) are connect-
ed to L293 pins 1A, 2A, 3A and 4A respectively. The wheel motors are connected to pins
3,6 and 11,14 of the L293 driver IC as before. An active buzzer is connected to GPIO10 (pin
19) port of the RPi ZW. The robot assembly is shown in Figure 2.119.
where, time is in seconds and it is the time taken to receive the echo pulse. We can re-write
the above equation as:
● 139
Motor Control - Projects with Arduino & Raspberry Pi Zero W
If the distance to the objects is less than or equal to the Allowed_Distance (which is set
to 50cm) then the buzzer is sounded and the robot turns left until a clearance can be seen
with no objects within the Allowed_Distance. The robot then moves forward. This pro-
cess is repeated forever until stopped manually.
The program name robot2.py must be included in file /etc/rc .local in the following format
so that the program starts as soon as the RPi ZW boots:
#-------------------------------------------------------------------
# OBSTACLE AVOIDING ROBOT
# =======================
#
# This is an obstacle avoding robot. An ultrasonic module is used
# to detect the disatnce in-front of the robot to the objects as
# the robot moves forward. If the distance to the objects is 40cm
# or less then the robot sounds a Buzzer and turns left until it
# finds a clearance with no obkects within 50cm and ut then goes
# forward.
#
#
# File : robot2.py
# Date : August 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
Allowed_Distance = 50
#
# L293 control pins
#
L1A = 2 # GPIO2
L2A = 3 # GPIO3
R3A = 17 # GPIO17
R4A = 27 # GPIO27
#
# Ultrasonic sensor pins
#
trig = 22 # GPIO22
echo = 4 # GPIO4
● 140
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
#
# BUZZER pin
#
Buzzer = 10 # GPIO10
#
# Configure L293 control pins,trig and Buzzer as outputs.
# Also, configure echo as input
#
GPIO.setup(L1A, GPIO.OUT)
GPIO.setup(L2A, GPIO.OUT)
GPIO.setup(R3A, GPIO.OUT)
GPIO.setup(R4A, GPIO.OUT)
GPIO.setup(trig, GPIO.OUT)
GPIO.setup(echo, GPIO.IN)
GPIO.setup(Buzzer, GPIO.OUT)
#
# Set forward movement
#
def FORWARD():
GPIO.output(L1A, 0)
GPIO.output(L2A, 1)
GPIO.output(R3A, 0)
GPIO.output(R4A, 1)
return
#
# Turn left
#
def LEFT():
GPIO.output(L1A, 1)
GPIO.output(L2A, 0)
GPIO.output(R3A, 0)
GPIO.output(R4A, 1)
return
#
# Turn ON the Buzzer
#
def BUZZERON():
GPIO.output(Buzzer, 1)
return
#
# Turn OFF the Buzzer
● 141
Motor Control - Projects with Arduino & Raspberry Pi Zero W
#
def BUZZEROFF():
GPIO.output(Buzzer, 0)
return
def GetDistance():
GPIO.output(trig, 0) # Wait to settle
time.sleep(0.08)
GPIO.output(trig,1) # Send trig
time.sleep(0.00001) # Wait 10 microseconds
GPIO.output(trig, 0) # Remove trig
while GPIO.input(echo) == 0: # Wait until echo is received
start_time = time.time() # Start time
#
# Start of the main program loop. Measure the distance to
# obstacles and turn the robot left if an obstacle is detected
# in-front of the robot in less than the Allowed_Distance.
# The buzzer is also sounded
#
BUZZEROFF()
while True:
obstacle = GetDistance() # Get distance to obstacle
if obstacle <= Allowed_Distance: # If less than Allowed_Distance
BUZZERON() # Turn Buzzer ON
LEFT() # Turn left
else:
BUZZEROFF() # Turn Buzzer OFF
FORWARD() # Go forward
After applying power to the robot, wait until the RPi ZW boots and the program should start
automatically. You should remove your Python program name from file /etc/rc .local after
testing and completing your project so that the program does not start every time you
restart your RPi ZW.
● 142
CHAPTER 2 • SIMPLE DC MOTOR PROJECTS
2 .20 Summary
In this Chapter we have developed many projects using a DC motor with the Arduino UNO
and Raspberry Pi Zero W.
In the next Chapter we shall be looking at the design of stepper motor projects, again using
Arduino Uno and Raspberry Pi Zero W processors.
● 143
Motor Control - Projects with Arduino & Raspberry Pi Zero W
3 .1 Overview
Stepper motors are DC motors that rotate in small steps. These motors have several coils
that are energized in sequence, causing the motor to rotate one step at a time. Stepper
motors have the advantages that very precise positioning or speed control of the motor
shaft can be achieved. These motors are used in many precision motion control applica-
tions.
There are basically two types of stepper motors: unipolar and bipolar.
Unipolar motors can be rotated in reverse by reversing the sequence of applied pulses.
Unipolar stepper motors can be driven in full stepping mode or in half stepping mode. Most
popular drive modes are 1 phase full-step, 2 phase full-step, and 2 phase half-step.
In 1 phase full-step mode, as shown in Table 3.1, each motor winding receives one pulse
per step. This mode has the disadvantage that the available torque is low.
Step a c b d
1 1 0 0 0
2 0 1 0 0
3 0 0 1 0
4 0 0 0 1
In 2 phase full-step mode, as shown in Table 3.2, two motor windings receive pulses per
step. The advantage of this mode is that a higher torque is available from the motor.
● 144
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
Step a c b d
1 1 0 0 1
2 1 1 0 0
3 0 1 1 0
4 0 0 1 1
Table 3.2 2 Phase full-step mode
In 2 phase half-step mode, as shown in Table 3.3, two motor windings sometimes receive
pulses and sometimes only one winding receives a pulse. Because the motor is driven at
half-step mode, 8 steps are required to complete a cycle instead of 4. This mode gives
higher precision, but at the expense of lower torque.
Step a c b d
1 1 0 0 0
2 1 1 0 0
3 0 1 0 0
4 0 1 1 0
5 0 0 1 0
6 0 0 1 1
7 0 0 0 1
8 1 0 0 1
Table 3.4 shows the steps required to drive a bipolar stepper motor. Here, + and – signs
refer to the polarity of the voltages applied to the motor leads.
● 145
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Step a c b d
1 + - - -
2 - + - -
3 - - + -
4 - - - +
RPM = 60β/360T
or, RPM = β/6T
where, RPM is the number of revolutions per minute, β is the step constant of the motor in
degrees, and T is the time between the steps in seconds.
As an example, assume that the step constant of a stepper motor is 10 degrees (β = 10º).
If we want to rotate this motor at a speed of 1000 RPM (assuming that the motor is capable
of rotating this fast), the time between the pulses is calculated as:
n = v/β
For example, assuming that the step constant is 5º (β = 5), and that we want the motor to
rotate by 200 degrees, the required number of steps is:
n = 200/5 = 40
● 146
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
T0 = nT
For example, assuming that the time between the pulses is 1ms, if we want the motor to
rotate for 5 seconds, the required number of pulses is given by:
Stepper motors can be driven by several ways, such as using bipolar transistors, using
MOSFET transistors, or using integrated circuits such as L293, ULN2003 and so on. In this
Chapter we shall be using a ULN2003 based driver circuit.
3 .2 .1 Block Diagram
In this project a small 28BYJ-48 type unipolar stepper motor (see Figure 3.3) is used. This
motor has the following specifications:
Rated voltage: 5V
Number of phases: 4
Gear ratio: 64
Frequency: 100Hz
Stride angle: 5.625º/64
● 147
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Figure 3.6 shows the Arduino Uno circuit diagram of the project. GPIO pins 0,1,2,3 of the
Arduino Uno are connected to driver module inputs IN1,IN2,IN3 and IN4 respectively. The
project with the stepper motor is shown in Figure 3.7
● 148
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
● 149
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Full-step Mode
In full-step mode there are 4 steps per cycle and 11.25 degrees/step, corresponding to
32 steps per one revolution of the internal motor shaft. Because the motor is geared with
a gear ratio of 64 (in actual fact the gear ratio is 63.68395), the number steps for one
external complete revolution is 2048 steps/revolution (512 cycles with 4 steps per cycle).
Table 3.5 shows the motor winding sequence for the full-step mode (this sequence is re-
peated. Reversing the sequence reverses the direction of rotation).
1 1 1 0 0
2 0 1 1 0
3 0 0 1 1
4 1 0 0 1
● 150
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
Half-step Mode
The half-step mode with 8 steps per cycle is recommended by the manufacturer. In half-
step mode we have 5.625 degrees/step, corresponding to 64 steps per one revolution of
the internal motor shaft. Because the motor is geared with a gear ratio of 64, the number
of steps for one external complete revolution is 4096 steps/revolution (512 cycles with 8
steps per cycle).
Table 3.6 shows the motor winding pulse sequence for the half-step mode (this sequence
is repeated. Reversing the sequence reverses the direction of rotation).
1 1 0 0 0
2 1 1 0 0
3 0 1 0 0
4 0 1 1 0
5 0 0 1 0
6 0 0 1 1
7 0 0 0 1
8 1 0 0 1
Where, RPM is the motor speed in revolutions per minute, and T is the delay between each
step in milliseconds. We usually show the delay in microseconds and the above equation
● 151
Motor Control - Projects with Arduino & Raspberry Pi Zero W
becomes:
At the beginning of the program motor driver pins IN1, IN2, IN3 and IN4 are assigned to
GPIO pins 0, 1, 2, and 3 respectively. Then the motor speed is set to 12 RPM and the steps
per revolution (variable StepsPerRevolution) is set to 512 for full-mode of operation. The
pulses to be sent to the motor in Full-mode are stored in array FullMode. Inside the setup
routine motor pins are configured as outputs and the time delay to be inserted between
each step (StepDelay) is calculated. Inside the main program loop functions CLOCKWISE
and ANTICLOCKWISE are created which rotate the motor clockwise and anticlockwise re-
spectively. Required number of revolutions is sent as an argument to these functions.
Function CLOCKWISE sends 4 pulses to the motor with a delay of StepDelay between each
pulse. This ensures that the motor speed is as required. This is repeated StepsPerRev-
olution times so that the motor makes a complete revolution. This whole process is then
repeated count times which is the number of times we want the motor to rotate complete
revolutions.
/*****************************************************************
* BASIC STEPPER MOTOR CONTROL
* ===========================
*
* In this project a unipolar stepper motor is controlled such that
* the motor is rotated clockwise for 2 revolutions, then after 2
* seconds delays the motor is rotated twice anticlockwise, and then
* it is stopped. The motor is controlled in FULL-STEP mode with
* the speed of 12 RPM.
*
* The motor has 2048 steps/revolutions in FULL-STEP mode, or 512
* cycles per revolution with 4 steps in every cyle
*
* In this project a ULN2003 type motor driver module is used
*
*
* File : stepper1
* Date : September 2017
* Author: Dogan Ibrahim
*****************************************************************/
//
// Stepper Motor pin definitions
//
#define IN1 0 // Motor orange
#define IN2 1 // Motor yellow
#define IN3 2 // Motor purple
#define IN4 3 // Motor blue
● 152
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
//
// Motor control parameters
//
int RPM = 12; // Required speed
int StepsPerCycle = 512; // Steps per cycle
int StepDelay; // Step Delay in
microseconds
int FullMode[4] = {B01100, B00110, B00011, B01001};
//
// Configure motor pins as outputs. Also calculate the time delay
// to be inserted between each step
//
void setup()
{
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
StepDelay = 29300 / RPM;
}
//
// This function rotates teh motor clockwise
//
void CLOCKWISE(int count)
{
for(int j = 0; j < count; j++)
{
for(int m = 0; m < StepsPerCycle; m++)
{
for(int i = 4; i >= 0; i--)
{
SendPulse(i);
delayMicroseconds(StepDelay);
}
}
}
}
//
// This function rotate steh motor anticlockwise
//
void ANTICLOCKWISE(int count)
{
● 153
Motor Control - Projects with Arduino & Raspberry Pi Zero W
//
// Send pulss in FULL-MODE to the motor
//
void SendPulse(int k)
{
digitalWrite(IN1, bitRead(FullMode[k], 0));
digitalWrite(IN2, bitRead(FullMode[k], 1));
digitalWrite(IN3, bitRead(FullMode[k], 2));
digitalWrite(IN4, bitRead(FullMode[k], 3));
}
//
// Main program loop. Control the stepper motor as required:
// 2 rotations clockwise, 2 seconds delay, 2 rotations anticlockwise
//
void loop()
{
CLOCKWISE(2);
delay(2000);
ANTICLOCKWISE(2);
while(1);
}
Figure 3.10 Program listing (full-step mode without library)]
Half-Step Mode
Figure 3.11 shows the program listing driving the motor in half-step mode (program: step-
per2) without the Arduino library (the Arduino library can only drive in full-step mode).
In this example the motor is rotated in one direction for 2 complete revolutions. It is then
stopped for 2 seconds, and then rotated in the reverse direction for 2 complete revolutions.
In this example the motor speed is set to 12 RPM as before. In half-step mode there are
4096 steps in a complete revolution. The motor speed in RPM is given by the following
equation:
● 154
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
Where, RPM is the motor speed in revolutions per minute, and T is the delay between each
step in milliseconds. We usually show the delay in microseconds and the above equation
becomes:
The program in Figure 3.11 is very similar to the ne in Figure 3.10. Here, the pulse se-
quence to be sent to the motor (HalfMode) consists of 8 steps, and the delay between
each pulse is different as shown in the above calculation. Also, the CLOCKWISE and ANTI-
CLOSKWISE functions send 8 pulses per cycle instead of 4.
/*****************************************************************
* BASIC STEPPER MOTOR CONTROL
* ===========================
*
* In this project a unipolar stepper motor is controlled such that
* the motor is rotated clockwise for 2 revolutions, then after 2
* seconds delays the motor is rotated twice anticlockwise, and then
* it is stopped. The motor is controlled in HALF-STEP mode with
* the speed of 12 RPM
*
* The motor has 4096 steps/revolutions in HALF-STEP mode, or 512
* cycles per revolution with 8 steps in every cyle
*
* In this project a ULN2003 type motor driver module is used
*
*
* File : stepper2
* Date : September 2017
* Author: Dogan Ibrahim
*****************************************************************/
//
// Stepper Motor pin definitions
//
#define IN1 0 // Motor orange
#define IN2 1 // Motor yellow
#define IN3 2 // Motor purple
#define IN4 3 // Motor blue
//
// Motor control parameters
//
● 155
Motor Control - Projects with Arduino & Raspberry Pi Zero W
//
// Configure motor pins as outputs. Also calculate the time delay
// to be inserted between each step
//
void setup()
{
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
StepDelay = 14648 / RPM;
}
//
// This function rotates teh motor clockwise
//
void CLOCKWISE(int count)
{
for(int j = 0; j < count; j++)
{
for(int m = 0; m < CyclesPerRevolution; m++)
{
for(int i = 7; i >= 0; i--)
{
SendPulse(i);
delayMicroseconds(StepDelay);
}
}
}
}
//
// This function rotates the motor anticlockwise
//
void ANTICLOCKWISE(int count)
{
for(int j = 0; j < count; j++)
{
for(int m = 0; m < CyclesPerRevolution; m++)
{
● 156
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
//
// Send pulses in HALF-MODE to the motor
//
void SendPulse(int k)
{
digitalWrite(IN1, bitRead(HalfMode[k], 0));
digitalWrite(IN2, bitRead(HalfMode[k], 1));
digitalWrite(IN3, bitRead(HalfMode[k], 2));
digitalWrite(IN4, bitRead(HalfMode[k], 3));
}
//
// Main program loop. Control the stepper motor as required:
// 2 rotations clockwise, 2 seconds delay, 2 rotations anticlockwise
//
void loop()
{
CLOCKWISE(2);
delay(2000);
ANTICLOCKWISE(2);
while(1);
}
Figure 3.11 Program listing (half-step mode)
Stepper(steps, pin1, pin2, pin3, pin4): This function creates a new instance of the
Stepper class. This function must be declared at the top of the program before the setup
routine. The number of parameters can be 2 or 4 depending on how the motor is wired.
Parameter steps is the number of steps in one revolution.
● 157
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Step(steps): This function turns the motor a specific number of steps at the speed spec-
ified by the setSpeed function.
Function Stepper is called and the number of steps per revolution in full-mode (2048) and
the motor pin connections are defined. Notice that the wiring sequence is slightly different
when the library is used. Motor speed is set to 12 RPM in the setup routine and the number
of required revolutions is set to 2. Inside the main program loop function step is called to
rotate the motor required number of times in both directions.
/*****************************************************************
* BASIC STEPPER MOTOR CONTROL
* ===========================
*
* In this project a unipolar stepper motor is controlled such that
* the motor is rotated clockwise for 2 revolutions, then after 2
* seconds delays the motor is rotated twice anticlockwise, and then
* it is stopped. The motor is controlled in FULL-STEP mode with
* the speed of 12 RPM
*
* In this project a ULN2003 type motor driver module is used. This
* version of the program uses the Arduino stepper library
*
*
* File : stepper3
* Date : September 2017
* Author: Dogan Ibrahim
*****************************************************************/
#include <Stepper.h>
#define StepsPerRevolution 2048
Stepper MyMotor(StepsPerRevolution, 0, 2, 1, 3); // Pulse sequence
// Motor definition
int RequiredRevolutions = 2;
int Revolutions;
void setup()
{
MyMotor.setSpeed(12); // Set motor speed
Revolutions = RequiredRevolutions * StepsPerRevolution; //
Required number of revolutions
}
//
// Main program loop. Control the stepper motor as required:
// 2 rotations clockwise, 2 seconds delay, 2 rotations anticlockwise
//
void loop()
● 158
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
{
MyMotor.step(Revolutions);
delay(2000);
MyMotor.step(-Revolutions);
while(1);
}
Figure 3.12 Program listing (Full-step mode with the library)
Figure 3.13 shows the program listing. At the beginning of the program the RPM is set to 12,
steps per revolution to 512, and the delay is set so that the required RPM can be achieved.
Notice that the delay is specified in seconds since the Python time delay function accepts
its parameter in seconds. Then, the motor driver control pins are assigned to the GPIO
ports and these ports are configured as outputs. The half-step sequence is stored in array
HalfStep. Two functions are created: CLOCKWISE and ANTICLOCKWISE as in the Arduino
Uno version of the project. The required number of revolutions is passed as an argument
to these functions. Function SendPulse sends pulses to the motor in the correct sequence.
This function has the following format. Array HalfStep is accessed using two indices, the
first one being the HalfStep row, and the second one the bit inside the selected row.:
def SendPulse(k):
GPIO.output(IN1, HalfStep[k][3])
GPIO.output(IN2, HalfStep[k][2])
GPIO.output(IN3, HalfStep[k][1])
GPIO.output(IN4, HalfStep[k][0])
return
Inside the main program loop the motor is rotated clockwise twice, then after 2 seconds
delay it is rotated anticlockwise, and then it stops.
#-------------------------------------------------------------------
# BASIC CONTROL OF A STEPPER MOTOR
# ================================
#
# This is a simple stepper motor controller. In this project a
# small unipolar motor (28BYJ-48) is connected to the RPi ZW
# processor. The motor is controlled in half-step mode as follows:
#
# Turn 2 revolutions in clockwise direction
# Wait 2 seconds
# Turn 2 revolutions in anticlockwise direction
#
● 159
Motor Control - Projects with Arduino & Raspberry Pi Zero W
#
# File : stepper1.py
# Date : August 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
RPM = 12
StepsPerRevolution = 512
StepDelay = 0.014648 / RPM
#
# Motor driver control pins
#
IN1 = 2 # GPIO2
IN2 = 3 # GPIO3
IN3 = 4 # GPIO4
IN4 = 17 # GPIO17
#
# Configure driver control pins as outputs
#
GPIO.setup(IN1, GPIO.OUT)
GPIO.setup(IN2, GPIO.OUT)
GPIO.setup(IN3, GPIO.OUT)
GPIO.setup(IN4, GPIO.OUT)
#
# Define Half-Step sequence
#
HalfStep = [[1,0,0,0],
[1,1,0,0],
[0,1,0,0],
[0,1,1,0],
[0,0,1,0],
[0,0,1,1],
[0,0,0,1],
[1,0,0,1]]
#
# This function rotates the motor clockwise
#
def CLOCKWISE(count):
● 160
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
global StepsPerRevolution
for j in range(0,count):
for m in range(0,StepsPerRevolution):
for i in range(7, -1, -1):
SendPulse(i)
time.sleep(StepDelay)
return
#
# This function rotates the motor anticlockwise
#
def ANTICLOCKWISE(count):
global StepsPerRevolution
for j in range (0,count):
for m in range (0,StepsPerRevolution):
for i in range (0, 8):
SendPulse(i)
time.sleep(StepDelay)
return
#
# Send pulse to the motor
#
def SendPulse(k):
GPIO.output(IN1, HalfStep[k][3])
GPIO.output(IN2, HalfStep[k][2])
GPIO.output(IN3, HalfStep[k][1])
GPIO.output(IN4, HalfStep[k][0])
return
#
# Start of the main program loop. Rotate the motor as:
# 2 revs clockwise, stop 2 seconds, 2 revs anticlockwise
#
while True:
CLOCKWISE(2)
time.sleep(2)
ANTICLOCKWISE(2)
while True:
pass
● 161
Motor Control - Projects with Arduino & Raspberry Pi Zero W
3 .3 .1 Block Diagram
Figure 3.14 shows the block diagram of the project. The temperature is displayed on a card
board with a dial hand which is controlled by the stepper motor used in the previous pro-
ject. The card board is fixed and the temperature values are marked on it. The dial hand is
moved by the stepper motor and it points to the current measured ambient temperature.
Figure 3.15 shows the card board display with the markings on it.
Temperature scale is marked on a circular card board from 0ºC to 40ºC in steps of 5ºC. A
dial hand, made of a wire is attached to the stepper motor shaft at the center of the board.
A copper wire is mounted at 0ºC and this point is used as the starting point. The copper
wire acts like a switch together with the dial hand wire. When power is applied to the pro-
cessor the dial hand is moved left (stepper motor rotates anticlockwise) until it comes in
contact with the copper wire (part of the dial handle wire is bare and has no sleeve) and it
then stops at the starting point of 0ºC. From this point on, the dial hand moves right to the
correct point on the scale depending upon the measured temperature value. The temper-
ature is checked every minute and the dial hand moves left or right by the correct amount
to show the new temperature if it has changed from the last reading.
There are 180 degrees of angle from 0ºC to 40ºC on the scale. Therefore, each degree of
temperature corresponds to 4.5 degrees of angle. For example, if the temperature is 10ºC,
● 162
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
the angle is 45º, if the temperature is 20ºC the angle is 90º, if the temperature is 40ºC the
angle is 180º and so on. Therefore, the required angle for a given temperature reading is
given by the following formula:
Angle = 4.5 x T
Where, T is the measured temperature in degrees Centigrade, and Angle is the angle that
the dial hand must move to show the correct temperature. If D is the angle in degrees that
the external motor shaft moves for each step applied to the motor, the number of steps re-
quired (S) to move the dial hand to the correct temperature point on the scale is given by:
S = 4.5 x T / D
The above formula can be used to move the dial hand to the correct point on the scale at
the beginning of the program. Notice that this is clockwise rotation of the stepper motor.
If the temperature is T1 degrees Centigrade and after the next reading it is T2 degrees
Centigrade, then the number of steps required to move the dial hand is given by the fol-
lowing algorithm:
T = (Vo – 500) / 10
Where T is the measured temperature in degrees Centigrade, and Vo is the output voltage
of the sensor in millivolts.
The dial hand is connected to +5V. The copper wire placed at 0ºC on the dial is connected
to ground through a 10K resistor. The connection point of the copper wire with the resistor
is connected to port pin 4 of the Arduino Uno. Normally this point is at logic 0 and goes to
logic 1 when the dial hand touches it. When power is applied to the processor the dial hand
is moved left by the stepper motor until it touches the copper wire and this point of the
stepper motor is taken as the reference 0ºC point.
● 163
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Power to the motor was supplied from an external +5V power supply through the motor
driver module and the circuit was built on a breadboard.
The connection point of the copper wire with the resistor was connected to port GPIO27
(pin 13) of the RPi ZW.
● 164
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
Inside the setup routine copper wire is configured as an input and the motor speed is set to
12 RPM. The stepper motor is then activated to turn anticlockwise and move the dial handle
until the handle touches the copper wire. At this point a logic 1 signal is given to pin 4 of the
Arduino Uno and the motor stops. This way we establish the reference point as the point on
the dial with the mark 0ºC. The program then waits for a while (5 seconds) before starting
to measure and show the temperature.
Inside the main program loop the temperature reading is read from TMP36DZ sensor chip
and is converted into degrees Centigrade. This reading is stored in variable mV. Then the
required number of steps to move the dial handle is calculated as discussed earlier and the
motor turns clockwise to move the dial handle to show the temperature reading.
Temperature readings are taken every minute. After moving the dial the first time to show
the temperature, next readings are compared with the previous readings and the dial han-
dle is adjusted accordingly by rotating the stepper motor clockwise (present temperature
greater than the previous one) or anticlockwise (present temperature less than the previ-
ous one) as described earlier. This process continues until stopped manually by the user.
/*****************************************************************
* TEMPERATURE DIAL
* ================
*
* In this project the ambient temperature is read using an analog
* TMP36DZ type sensor chip and it is then displayed on a dial type
* temperature scale. A circular temperature scale was made with the
* temperature values marked from 0C to 40C. A dial is moved by the
* stepper motor to point to the measured temperature.
*
*
* File : stepper4
* Date : September 2017
* Author: Dogan Ibrahim
*****************************************************************/
#include <Stepper.h>
#define StepsPerRevolution 2048
const float DegreesPerStep = 360.0 / StepsPerRevolution;
#define CopperWire 4 // Reference point
input
#define TMP36 0 // TMP36 at A0
Stepper MyMotor(StepsPerRevolution, 0, 2, 1, 3); // Pulse sequence
int Temp;
float mV, Told, Tnew, Diff, RequiredSteps;
int Steps;
int First = 1;
//
● 165
Motor Control - Projects with Arduino & Raspberry Pi Zero W
//
// Main program loop. Read the temperature every minute and move the
// dial to point to the correct temperature
//
void loop()
{
Temp = analogRead(TMP36); // Read temperature
mV = Temp * 5000.0 / 1024.0; // in millivolts
mV = (mV - 500.0) / 10.0; // Temperature
if(First == 1) // If first time
{
First = 0;
Told = mV;
RequiredSteps = 4.5 * mV / DegreesPerStep;
Steps = (int)RequiredSteps;
MyMotor.step(Steps);
}
else // Not first time
{
Tnew = mV;
if(Tnew > Told)
{
Diff = Tnew - Told;
RequiredSteps = 4.5 * Diff / DegreesPerStep;
Steps = (int)RequiredSteps;
MyMotor.step(Steps);
}
else
● 166
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
{
Diff = Told - Tnew;
RequiredSteps = 4.5 * Diff / DegreesPerStep;
Steps = (int)RequiredSteps;
MyMotor.step(-Steps);
}
Told = Tnew;
}
delay(60000); // Wait 1 minute
}
cd Adafruit_python_DHT
If you see an error that a package is already installed or that the package is at the latest
version, you can ignore such messages and just continue.
The program listing is shown in Figure 3.19 (program: stepper2.py). At the beginning of
the program, libraries RPi.GPIO, time, and Adafruit_DHT are imported to the program and
DHT11 is assigned to port GPIO22. The program then specifies that we will be using the
DHT11, and various stepper motor parameters are defined here. Copper wire is assigned
to port GPIO27, motor driver control pins are defined, and these pins are configured as
outputs. Copper wire connection is configured as an input. Then the half-step sequence is
● 167
Motor Control - Projects with Arduino & Raspberry Pi Zero W
The program rotates the stepper motor anticlockwise until the dial handle touches the
copper wire at the reference point (point where the 0ºC is marked). Then the program loop
starts. Inside this loop the temperature (and humidity) is read from the DHT11 and the dial
handled is moved to the show the correct temperature by sending the correct number of
pulses to the stepper motor.
#-------------------------------------------------------------------
# TEMPERATURE DIAL
# ================
#
# In this project the ambient temperature is read using the digital
# DHT11 temperature/humidity sensor chip an dis then displayed on
# a dial type temperature scale. A circular scale was made with
# temperature values marked on it from 0C to 40C. The dial is moved
# by the stepper motor to point to the measured temperature.
#
#
# File : stepper2.py
# Date : September 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
import time
import Adafruit_DHT
sensor = Adafruit_DHT.DHT11
DHT11 = 22 # GPIO22
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
RPM = 12
StepsPerRevolution = 4096.0
DegreesPerStep = 360.0 / StepsPerRevolution
StepDelay = 0.014648 / RPM
CopperWire = 27 # GPIO27
First = 1
global cw, acw
cw = 7
acw = 0
● 168
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
#
# Motor driver control pins
#
IN1 = 2 # GPIO2
IN2 = 3 # GPIO3
IN3 = 4 # GPIO4
IN4 = 17 # GPIO17
#
# Configure driver control pins as outputs
#
GPIO.setup(IN1, GPIO.OUT)
GPIO.setup(IN2, GPIO.OUT)
GPIO.setup(IN3, GPIO.OUT)
GPIO.setup(IN4, GPIO.OUT)
GPIO.setup(CopperWire, GPIO.IN)
#
# Define Half-Step sequence
#
HalfStep = [[1,0,0,0],
[1,1,0,0],
[0,1,0,0],
[0,1,1,0],
[0,0,1,0],
[0,0,1,1],
[0,0,0,1],
[1,0,0,1]]
#
# This function rotates the motor clockwise specified number of
# steps
#
def CLOCKWISE(StepCount):
global cw
j = 0
while j < StepCount:
SendPulse(cw)
time.sleep(StepDelay)
cw = cw - 1
if cw == -1:
cw = 7
j = j + 1
return
● 169
Motor Control - Projects with Arduino & Raspberry Pi Zero W
#
# This function rotates the motor anticlockwise specified number
# of steps
#
def ANTICLOCKWISE(StepCount):
global acw
j = 0
while j < StepCount:
SendPulse(acw)
time.sleep(StepDelay)
acw = acw + 1
if acw == 8:
acw = 0
j = j + 1
return
#
# Send pulse to the motor
#
def SendPulse(k):
GPIO.output(IN1, HalfStep[k][3])
GPIO.output(IN2, HalfStep[k][2])
GPIO.output(IN3, HalfStep[k][1])
GPIO.output(IN4, HalfStep[k][0])
Return
#
# Move the dial hand to the reference point (0 degrees C) and wait
# for 5 seconds before starting
#
while(GPIO.input(CopperWire) == 0):
ANTICLOCKWISE(1)
time.sleep(5)
#
# Start of the main program loop. Read the temperature every minute
# and move the dial hand to point to the correct temperature. Notice
# that DHT11 returns the humidity data as well but it is not used here
#
while True:
humidity,temperature=Adafruit_DHT.read_retry(sensor, DHT11)
if First == 1:
First = 0
Told = temperature
RequiredSteps = 4.5 * temperature / DegreesPerStep
● 170
CHAPTER 3 • SIMPLE STEPPER MOTOR PROJECTS
CLOCKWISE(RequiredSteps)
else:
Tnew = temperature
if Tnew > Told:
Diff = Tnew - Told
RequiredSteps = 4.5 * Diff / DegreesPerStep
CLOCKWISE(RequiredSteps)
else:
Diff = Told - Tnew
RequiredSteps = 4.5 * Diff / DegreesPerStep
ANTICLOCKWISE(RequiredSteps)
Told = temperature
time.sleep(60)
3 .4 Summary
In this section we have seen how to control a stepping motor from Arduino Uno and also
from Raspberry Pi Zero W.
In the next Chapter we shall be looking at how to control a servo motor using an Arduino
Uno and a Raspberry Pi Zero W.
● 171
Motor Control - Projects with Arduino & Raspberry Pi Zero W
4 .1 Overview
Servo motors are DC motors, used in many position control applications where it is required
to position the motor shaft at a desired position. These motors use built-in position sens-
ing devices to determine the position of its shaft, and then rotate in the correct direction
to position the motor shaft at the commanded position. Servo motors do not rotate freely
round and round like a normal motor, but rather they can turn around 180 degrees or so
back and forth.
Unlike other motors, servo motors have 3 wire connections: power, ground, and control
signal. The control signal is positive going Pulse Width Modulated (PWM) voltage such that
the frequency of this voltage (or the period) is fixed, but the duration varies in relation to
the required position of the motor shaft. For example, the SG90 servo motor operates such
that the period of the PWM signal is 20 ms (frequency of 50 Hz) so that the motor checks
the duration of the pulse every 20 ms. The motor shaft is in the middle when the pulse
duration is 1.5 ms, 90 degrees all the way to the right when the pulse duration is 2 ms, and
-90 degrees all the way to the left when the pulse duration is 1 ms.
In this Chapter we shall be learning how to control a small servo motor using an Arduino
Uno and a Raspberry Pi Zero W development boards. The two projects in this Chapter are
simple and aimed to teach the basic control of a servo motor.
The servo motor used in this project is the TowerPro SG90 servo motor shown in Figure 4.1
together with its wiring diagram.
● 172
CHAPTER 4 • SIMPLE SERVO MOTOR PROJECTS
4 .2 .1 Block Diagram
The block diagram of the motor is as in Figure 4.2. The servo motor is simply connected to
the processor. A handle supplied with the motor should be mounted on the motor shaft so
that the rotation of the shaft can easily be seen.
4 .2 .2 Circuit Diagram
SG90 servo motor has the following specifications:
Figure 4.3 shows the circuit diagram of the project. Signal input of the motor (brown wire)
is connected to port pin 3 of the Arduino Uno. The power supply input (red wire) is con-
nected to +5V of the Arduino Uno. Notice that the +5V pin of the Arduino Uno has enough
current capability to drive a small motor. Larger motors must be connected to an external
power supply not to overload the Arduino Uno board.
● 173
Motor Control - Projects with Arduino & Raspberry Pi Zero W
4 .2 .3 Program Listing
In this project the Arduino servo library is used. This library has the following functions:
attach: attach the servo variable to a pin. Additionally, the pulse width corresponding to
the minimum (0 degree) and the maximum (180 degree) angle can also be specified.
write: write an angle value to the servo. Valid values are 0 to 180.
writeMicroseconds: write a value in microseconds to the servo to control the motor shaft.
Normally, 1500 is the middle point, 2000 is fully clockwise, and 1000 is fully anticlockwise.
read: read the current angle of the motor (value passed in the last write)
Figure 4.4 shows the program listing of the project (program: servo1). At the beginning of
the program the servo library header is included in the program and the servo pin is spec-
ified (3 in this project). Inside the setup routine servo pin is attached. The main program
loop turns the servo shaft as specified in the project. At the end, the motor is stopped by
detaching it.
Notice that as shown in Figure 4.5, 90 degrees is the middle point, 0 degrees is 90 degrees
(all the way) clockwise, and 180 degrees is all the way anticlockwise.
/*****************************************************************
* BASIC SERVO MOTOR CONTROL
* =========================
*
* In this project a small servo motor (type TowerPro SG90) is
* connected to pin 3 of the Arduino Uno. The aim of this project
* is to show how the servo motor can be controlled. The motor is
* controlled as follows:
● 174
CHAPTER 4 • SIMPLE SERVO MOTOR PROJECTS
*
* Position the motor shaft to the middle point
* Wait 1 seconds
* Position the motor shaft 90 degrees to the right
* Wait 1 seconds
* Position the motor shaft 90 degrees to the left
* Wait 1 seconds
* Move the motor shaft shaft left to right in increments of 1 degree
* Stop the motor
*
* File : servo1
* Date : September 2017
* Author: Dogan Ibrahim
*****************************************************************/
#include <Servo.h>
Servo MyServo;
//
// Stepper Motor pin definition
//
#define ServoPin 3 // Servo motor signal
//
// Attach the servo to ServoPin
//
void setup()
{
MyServo.attach(ServoPin);
}
//
// Main program loop. Control the servo motor as required
//
void loop()
{
MyServo.write(90); // Servo shaft in the middle
delay(1000); // 1 sec delay
MyServo.write(0); // 90 degrees clockwise
delay(1000); // 1 sec delay
MyServo.write(180); // 90 degrees anticlockwise
delay(1000); // 1 sec delay
//
// Move servo arm left to right (clockwise)
//
for(int Angle = 180; Angle > 0; Angle--)
● 175
Motor Control - Projects with Arduino & Raspberry Pi Zero W
{
MyServo.write(Angle);
delay(100);
}
}
Figure 4.4 Program listing
Notice that the servo motors may need calibration. For example, the shaft of motor that the
author used was not in the middle when it was set to 90 degrees. It was found by experi-
ment that the shaft moved to the middle point when it was set to 105 degrees.
Figure 4.6 shows the servo motor connected to the Arduino Uno.
● 176
CHAPTER 4 • SIMPLE SERVO MOTOR PROJECTS
4 .3 .1 Block Diagram
The block diagram of the motor is shown in Figure 4.7 The servo motor is simply connected
to the processor and a potentiometer is used as the position controller.
4 .3 .2 Circuit Diagram
Figure 4.8 shows the circuit diagram of the project. The motor signal pin is connected to
port pin 3 of the Arduino Uno as before. The arm of the potentiometer is connected to
analog port A0.
4 .3 .3 Program Listing
The program listing is shown in Figure 4.9 (program: servo2). At the beginning of the pro-
gram the servo library header is included, servo pin and the potentiometer arm pins are
defined. Inside the main program loop value of the potentiometer arm is read from analog
port A0 and stored in variable PotValue. Since we have a 10-bit ADC, the value read is
between 0 and 1023. This value is mapped to the servo angles of 0 to 180 degrees using
the Arduino map statement which maps a number from one range to another range. The
mapped value is then sent to the servo motor using the servo write statement. As the
potentiometer arm is rotated so does the servo shaft.
/*****************************************************************
* SERVO CONTROL WITH A POTENTIOMETER
* ==================================
*
* In this project a small servo motor (type TowerPro SG90) is
* connected to pin 3 of the Arduino Uno. In addition, a 10K
* potentiometer is connected to analog input A0. The servo motor
● 177
Motor Control - Projects with Arduino & Raspberry Pi Zero W
//
// Stepper Motor and potentiometer pin definitions
//
#define ServoPin 3 // Servo motor signal
#define PotPin 0 // Potentiomter arm
int PotValue;
//
// Attach the servo to ServoPin
//
void setup()
{
MyServo.attach(ServoPin);
}
//
// Main program loop. Control the servo shaft by the potentiometer
//
void loop()
{
PotValue = analogRead(PotPin); // Read potentiometer
value
PotValue = map(PotValue, 0, 1023, 0, 180); // Map between 0 and 180
degrees
MyServo.write(PotValue); // Send to servo
delay(20); // Wait until servo moves
}
Figure 4.9 Program listing
● 178
CHAPTER 4 • SIMPLE SERVO MOTOR PROJECTS
4 .4 .1 Block Diagram
The block diagram of the motor is as shown in Figure 4.2.
4 .4 .2 Circuit Diagram
Figure 4.11 shows the circuit diagram of the project. Port pin GPIO 2 (pin 3) of the RPi ZW is
connected to the signal input of the motor. Power to the motor is supplied from an external
+5V power supply with the ground of this power supply and the RPi ZW ground pins are
connected together. You should be aware that the RPi ZW power supply has limited capacity
and running the motor from the RPi ZW power supply may damage your RPi ZW.
● 179
Motor Control - Projects with Arduino & Raspberry Pi Zero W
4 .2 .3 Program Listing
The servo motor is controlled by sending PWM voltage waveforms to it with a period of 20
ms (frequency of 50 Hz). The duration of the PWM waveform determines the shaft position
as follows:
The Duty Cycle of a PWM waveform is expressed as a percentage and it is the ratio of the
ON time to its period, multiplied by 100.
Considering that the period is 20 ms, the Duty Cycle for the 3 motor turns can be calculated
as follows:
In Python programming we can use any pin to generate a PWM waveform. The required
statements are:
where freq is the frequency of the PWM waveform and Initial Duty Cycle is the starting
Duty Cycle of the waveform.
Figure 4.12 shows the program listing (program: servo1.py). At the beginning of the pro-
gram the servo pin is defined as port GPIO2 and the PWM channel is configured to operate
at 50 Hz. Notice that all motors, even the same models from the same manufacturer, do
● 180
CHAPTER 4 • SIMPLE SERVO MOTOR PROJECTS
not respond in exactly the same way and it is usually necessary to calibrate a servo motor
to get the best results. This can easily be done with experimentation by changing the Duty
Cycle and observing the motor shaft positions. It was found by experiments that different
duty cycles than the theoretical ones were required to move the motor shaft. The findings
were: 5% (1.0 ms) moved the motor shaft to the middle position, 10% (2.0 ms) moved
the motor all the way to the left, and 2.2% (0.44 ms) moved the motor shaft all the way
to the right. It is therefore best to experiment until you get the correct duty cycle settings.
The motor shaft is put into middle position by setting the Duty Cycle to 5%, after 2 seconds
the Duty Cycle is changed to 2.2% so that the motor rotates all the way to right. After 2
seconds the Duty Cycle is set to 10% so that the motor rotates all the way to left. Finally,
the motor is rotated from left to right with a small delay between the steps.
#-------------------------------------------------------------------
# BASIC CONTROL OF A SERVO MOTOR
# ==============================
#
# This is a simple servo motor controller. In this project a
# small servo motor (TowerPro SG90) is connected to the GPIO2 of
# the RPi ZW processor. The motor is controlled in half-step mode as
follows:
#
# Move the shaft to middle position
# Wait 2 second
# Turn clockwise fully
# Wait 2 second
# Turn to anticlockwise fully
# Wait 2 second
# Move the shaft left to right (clockwise
#
# File : servo1.py
# Date : September 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
ServoPin = 2 # GPIO2
#
# Configure Servo pin as output
#
GPIO.setup(ServoPin, GPIO.OUT)
● 181
Motor Control - Projects with Arduino & Raspberry Pi Zero W
#
# Configure the PWM on pin Servo
#
p = GPIO.PWM(ServoPin, 50)
#
# Start rotating the motor shaft as required
#
p.start(5) # Middle position
time.sleep(2) # Wait 2 second
p.ChangeDutyCycle(2.2) # All the way to the right
time.sleep(2) # Wait 2 second
p.ChangeDutyCycle(10) # All the way to the left
time.sleep(2) # Wait 2 second
#
# Move the motor from left to right with 1 degree steps
#
i = 10.0
while i > 2.1:
p.ChangeDutyCycle(i)
time.sleep(0.1)
i = i - 0.1
p.stop()
#
# Wait here forever
#
while True:
pass
Figure 4.12 Program listing
Figure 4.13 shows the Raspberry Pi Zero W connected to the servo motor.
You can run the program interactively from the command mode by entering the command:
● 182
CHAPTER 4 • SIMPLE SERVO MOTOR PROJECTS
The block diagram and the circuit diagram of this project are as in Figure 4.2 and Figure
4.11.
4 .5 .1 Program Listing
Figure 4.14 shows the 3 main motor positions with the required Duty Cycle to move the
motor shaft to these positions. The graph at the bottom of the figure shows the variation of
the motor positions (shaft angle) with the Duty Cycles. Although this is not a straight-line
graph, we can approximate it to a straight line and find the equation of this line as:
7.8 Angle
Duty Cycle 2.2
180
Thus, for example, if we want to move the motor to an angle of 45 degrees, the Duty Cycle
should be:
7.8 Angle
Duty Cycle 180 2.2
● 183
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Figure 4.15 shows the program listing to move the motor shaft to 45 degrees (program:
servo2.py). Notice that it will be required to calibrate your servo motor and draw a new
graph similar to the one in Figure 4.14 in order to get accurate results.
#-------------------------------------------------------------------
# MOVE SERVO MOTOR to 45 DEGREES
# ==============================
#
# In this project the servo motor shaft is moved to the angle of
# 45 degrees by setting the correct PWM Duty Cycle.
#
# File : servo2.py
# Date : September 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
Angle = 45
DutyCycle = 2.2 + Angle * 7.8 / 180.0
ServoPin = 2 # GPIO2
#
# Configure Servo pin as output
#
GPIO.setup(2, GPIO.OUT)
● 184
CHAPTER 4 • SIMPLE SERVO MOTOR PROJECTS
#
# Configure the PWM on pin Servo and set the PWM to 50 Hz
#
p = GPIO.PWM(ServoPin, 50)
#
# Start rotating the motor shaft as required
#
p.start(DutyCycle) # Move to required angle
#
# Wait here forever
#
while True:
pass
You can run the program interactively from the command mode by entering the command:
4 .6 Summary
In this Chapter we have seen how to control a servo motor.
In the next Chapter we shall be looking at how to control our robot from an Android mobile
phone using Bluetooth communications with an Arduino Uno.
● 185
Motor Control - Projects with Arduino & Raspberry Pi Zero W
5 .1 Overview
Bluetooth is a wireless technology operating from 2.4 to 2.485 GHz and is used to exchange
data over short distances. It is available on all smart phones and on most modern laptops
and desktop computers.
In this Chapter we shall see how to control our robot remotely using Bluetooth on our mo-
bile phone to give commands and Arduino Uno as the robot controller. The robot used in
this Chapter is the one used in Chapter 3. By giving commands on our mobile phone we
shall see how to move the robot forwards, backwards, turning left or right, and so on. In
this project an Android type mobile phone is used to send commands to the robot.
The commands given in Table 5.1 will be used to control the LEDs and the buzzer. The
commands to control the robot movements are given in Table 5.2. In this table n is the
duration in seconds. For example, the command F2 means move robot forwards for 2
seconds and then stop.
Buzzer b1 b0
Table 5.2 Robot movement commands (nn must be 2 digit integer numbers)
5 .2 .1 Block Diagram
Figure 5.1 shows the block diagram of the project. Arduino Uno has no on-board Bluetooth
capability. For this reason a Bluetooth module is connected to the Arduino Uno so that com-
munication with a mobile phone can be achieved.
● 186
CHAPTER 5 • ARDUINO BLUETOOTH ROBOT CONTROL
5 .2 .2 Circuit Diagram
In this project an HC-06 type Bluetooth module is connected to the Arduino Uno so that
it can communicate over the Bluetooth link. Figure 5.2 shows the HC-06 module. This is a
small module that communicates with the host processor over its serial link. The module
has 4 pins: RXD, TXD, GND and VCC. As shown in the circuit diagram in Figure 5.3, VCC
and GND are connected to the +5V power pin and GND pin of the Arduino Uno respectively.
Notice that although HC-06 is a +3.3V module, its power supply can be +3.3V to +6V. The
input pins of the HC-06 are not +5V compatible and they must not be connected to any of
the Arduino output pins. Pin TXD of the HC-06 is serial output pin and it must be connected
to the RXD pin of the Arduino (pin 0). Pin RXD of the HC-06 is the serial input pin which
is not +5V tolerant and must not be connected directly to the Arduino TX pin (pin 1). As
shown in Figure 5.3, a resistive potential divider circuit is used to lower the output voltage
of the Arduino to +3.3V before it is connected to the RXD input of the HC-06.
The front and back (tail) LEDs are connected to Arduino Uno port pins 7 and 6 respectively
through 330 Ohm current limiting resistors. The positive input of the active buzzer is con-
nected to pin 8 of the Arduino, and the other pin is connected to GND.
1A, 2A, 3A and 4A pins of the L293 motor controller chip are connected to port pins 2,3,4
and 5 of the Arduino Uno. As in the previous robot control projects, left and right motors of
the robot are connected to pins 3,6 and 11,14 of the L293 motor driver chip.
Power to the Arduino is supplied using 4 x Ni-Zn batteries, connected to Vin pin of the Ar-
duino Uno. The two wheel motors also receive their power from these batteries through pin
8 of the L293 chip. Notice that you must not power the motors from +5V pin of the Arduino
Uno as it may not be able to supply the required current for the two motors. Always use an
external power supply for the motors.
● 187
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 188
CHAPTER 5 • ARDUINO BLUETOOTH ROBOT CONTROL
● 189
Motor Control - Projects with Arduino & Raspberry Pi Zero W
• Make sure that the program is uploaded into your Arduino Uno and that power is
applied to the robot
• Enable Bluetooth on your mobile phone and make sure that it is paired with the
HC-06 module
• Start the apps Arduino Bluetooth Controller on your mobile phone and select
HC-06 as shown in Figure 5.6 (second one from the top).
● 190
CHAPTER 5 • ARDUINO BLUETOOTH ROBOT CONTROL
• If you are connected to HC-06 successfully you should see a screen where you
can enter characters at the top. Enter the following command and click Send
Data (at the top right hand corner of the screen) to turn ON the front LED (see
Figure 5.7). Notice that all commands must be terminated with the # character.
Also, the time delay in robot movement commands cannot be greater than 99
seconds:
h1#
The front LED should turn ON. To turn it OFF enter command h0#
Similarly, to turn the buzzer on enter b1# and to turn it OFF enter b0#
● 191
Motor Control - Projects with Arduino & Raspberry Pi Zero W
F03#
F12#
5 .2 .6 Program Listing
Figure 5.8 shows the program listing (program: mobile1). At the beginning of the program
motor driver connections, LED connections, and the buzzer connection are defined. Inside
the setup routine motor pins, LEDs and the buzzer are configured as outputs. Also, the
LEDs and the two motors are turned OFF to start with. In addition, the Bluetooth interface
speed is configured as 9600 which is the default value. Functions FORWARD, REVERSE,
LEFT and RIGHT move the robot in the specified directions. These functions have argu-
ments which specify for how long the action should take place in seconds.
Inside the main program loop the program checks if a command is received from the Blue-
tooth module. If a command is available the it is read using function readBytesUntil which
in this program reads until the terminator character # is detected or until 3 characters are
received from the Bluetooth module.
● 192
CHAPTER 5 • ARDUINO BLUETOOTH ROBOT CONTROL
Commands are stored in array cmd and are handled using a switch statement. cmd[0] is
the first character of the command (e.g. h, t, b, F etc). cmd[1] is the action (0 or 1) for the
LED and buzzer commands. cmd[1] and cmd[2] are the delay values for the motor move-
ment commands (F, B, L, R). For example, the front LED command h is handled as follows:
case 'h':
if(cmd[1] == '1')
digitalWrite(FrontLED, HIGH);
else if(cmd[1] == '0')
digitalWrite(FrontLED, LOW);
break;
/*****************************************************************
* REMOTE ROBOT CONTROL USING BLUETOOTH
* ====================================
*
* In this project a mobile robot is connected to the Arduino Uno.
* In addition, a front LED, a back LED, and a buzzer are connected
* to the Arduino Uno.
*
* A Bluetooth module is attached to the Arduino Uno so that it
* communicates with a mobile phone using Bluetooth. The commands
* sent from the mobile phone can turn ON/OFF the LEDs and the buzzer,
* and it can also control the movements of the robot.
*
* The Bluetooth module used is the HC-06 which has the following
* default settings in data mode: 9600 Baud, 8 bits, 1 stop bit, no
* parity, no handshaking
*
* Valid commands are (The ommands must be terminated with the
* “#” character):
*
* h1 Turn ON front LED, h0 Turn OFF front LED
* t1 turn ON tail LED, t0 Turn OFF tail LED
* b1 turn ON buzzer, b0 turn OFF buzzer
* Fn Move robot forward n seconds
* Bn Move robot reverse n seconds
* Ln Turn robot left n seconds
* Rn Turn robot right n seconds
*
*
* File : mobile1
* Date : September 2017
* Author: Dogan Ibrahim
*****************************************************************/
//
● 193
Motor Control - Projects with Arduino & Raspberry Pi Zero W
//
// Define LED and buzzer connections
//
#define FrontLED 7 // Front LED
#define TailLED 6 // Tail LED
#define Buzzer 8 // Buzzer
//
// Configure 1A, 2A, 3A, 4A, LEDs and Buzzer as outputs. Turn OFF
// LEDs and Buzzer at the begining. Also stop the motors at the
// beginning just in case, and the Baud rae is set to 9600
//
void setup()
{
pinMode(L1A, OUTPUT);
pinMode(L2A, OUTPUT);
pinMode(R3A, OUTPUT);
pinMode(R4A, OUTPUT);
pinMode(FrontLED, OUTPUT);
pinMode(TailLED, OUTPUT);
pinMode(Buzzer, OUTPUT);
digitalWrite(FrontLED, LOW);
digitalWrite(TailLED, LOW);
digitalWrite(Buzzer, LOW);
StopMotors();
Serial.begin(9600);
}
//
// This function stops the motor
//
void StopMotors()
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, LOW);
digitalWrite(R3A, LOW);
● 194
CHAPTER 5 • ARDUINO BLUETOOTH ROBOT CONTROL
digitalWrite(R4A, LOW);
}
//
// This function moves the robot forward for tim seconds. Both
// motors rotate in the same direction
//
void FORWARD(char tim)
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, HIGH);
digitalWrite(R3A, LOW);
digitalWrite(R4A, HIGH);
delay(tim*1000);
StopMotors();
}
//
// This function reverses the motor for tim seconds. Both motors
// rotate in the same direction
//
void REVERSE(char tim)
{
digitalWrite(L1A, HIGH);
digitalWrite(L2A, LOW);
digitalWrite(R3A, HIGH);
digitalWrite(R4A, LOW);
delay(tim*1000);
StopMotors();
}
//
// This function turns the motor LEFT for tim seconds. Left motor
// is stopped and the right motor is activated
//
void LEFT(char tim)
{
digitalWrite(L1A, HIGH);
digitalWrite(L2A, LOW);
digitalWrite(R3A, LOW);
digitalWrite(R4A, HIGH);
delay(tim*1000);
StopMotors();
}
// This function turns the motor RIGHT for tim seconds. Right motor
● 195
Motor Control - Projects with Arduino & Raspberry Pi Zero W
//
// This function extracts the required delay in a motor movement
// command. The delay is in seconds
//
int GetDelay()
{
int dly = 10*(cmd[1]-'0') + cmd[2] - '0';
return dly;
}
//
// Main program loop. Read the command from the serial Bluetooth
// device, decode teh command and implement the control action
// as required
//
void loop()
{
cmd[0]=0; // Clear command array
cmd[1]=0;
cmd[2]=0;
● 196
CHAPTER 5 • ARDUINO BLUETOOTH ROBOT CONTROL
digitalWrite(TailLED, HIGH);
else if(cmd[1] == '0')
digitalWrite(TailLED, LOW);
break;
case 'b':
if(cmd[1] == '1')
digitalWrite(Buzzer, HIGH);
else if(cmd[1] == '0')
digitalWrite(Buzzer, 0);
break;
case 'F':
DelayTime = GetDelay();
FORWARD(DelayTime);
break;
case 'B':
DelayTime = GetDelay();
REVERSE(DelayTime);
break;
case 'L':
DelayTime = GetDelay();
LEFT(DelayTime);
break;
case 'R':
DelayTime = GetDelay();
RIGHT(DelayTime);
break;
}
}
}
Figure 5.8 Program listing
● 197
Motor Control - Projects with Arduino & Raspberry Pi Zero W
5 .3 Summary
In this Chapter we have seen how to control a robot remotely from a mobile phone using
the Bluetooth interface.
In the next Chapter we shall be exploring how to control the same robot again from a
mobile phone, but this time using Wi-Fi for communication and by sending UDP messages.
● 198
CHAPTER 6 • ARDUINO WI-FI ROBOT CONTROL
6 .1 Overview
Wi-Fi is one of the most commonly used Internet communications device, found in most
homes and offices in developed countries. It is a technology for wireless local area network-
ing, based on the IEEE 802.11 standards. Devices that can use Wi-Fi technology include
desktop computers, laptop computers, smart phones, tablets, digital cameras, modern
printers, smart TVs and many more Internet compatible devices. These devices access the
Internet via an Access Point (AP). An AP has a typical range of 20 metres indoors, although
extender devices are available to extend this range to several metres or more. Wi-Fi com-
monly uses the 2.4 GHz and 5 GHz UHF frequencies.
In this Chapter we shall look at how to control our robot remotely using Wi-Fi via our mobile
phone to give commands to the Arduino Uno mounted on the robot chassis. The robot used
in this Chapter is the one used in Chapter 3. By giving commands on our mobile phone we
shall see how to move the robot forwards, backwards, turning left or right, and so on. In
this project an Android type mobile phone is used to send commands to the robot. In this
project, UDP data packets are used for communication between the mobile phone and the
Arduino Uno.
Same commands as the ones given in Table 5.1 and Table 5.2 will be used in this project.
6 .2 .1 Block Diagram
Figure 6.1 shows the block diagram of the project. Arduino Uno has no on-board Wi-Fi
capability. For this reason a Wi-Fi module is connected to the Arduino Uno so that commu-
nication with a mobile phone can be achieved.
● 199
Motor Control - Projects with Arduino & Raspberry Pi Zero W
6 .2 .2 Circuit Diagram
In this project an ESP-01 type Wi-Fi module with the ESP8266 processor on-board and is
connected to the Arduino Uno so that the Arduino can communicate over the Wi-Fi link. Fig-
ure 6.2 shows the ESP-01 module. This is a very low-cost small Wi-Fi enabled module that
has an on-board processor and can either be used as a standalone processor with limited
I/O capability, or it can be connected to a host processor to give Wi-Fi capability to the host
processor. In this project ESP-01 is used to give Wi-Fi capability to the Arduino Uno. This is
accomplished by sending AT commands to the ESP-01 to configure it as a Wi-Fi device and
then to communicate via the Wi-Fi link.
ESP-01 is a 3.3V compatible device and its I/O pins must not be raised to greater than
+3.3V. The device has 8 pins:
VCC: Power supply pin. Must be connected to a +3.3V external power supply
GND: Power supply ground
GPIO0: I/O pin. This pin must be connected to +3.3V for normal operation, and to
0V for uploading firmware to the chip
GPIO2: I/O pin
RST: Reset pin. Must be connected to +3.3V for normal operation
● 200
CHAPTER 6 • ARDUINO WI-FI ROBOT CONTROL
Figure 6.3 shows the circuit diagram of the project. It is important to use an external +3.3V
power supply for the ESP-01 board since the Arduino +3.3V power supply cannot provide
enough current for the ESP8266. In this project the LM1086-3.3 power regulator chip is
used to provide power to the ESP-01 board. The regulator receives power from the battery
and its output is connected to the VCC pin of the ESP-01. Additionally, the GPIO0, RST, and
CHD_PD inputs of the ESP-01 are all connected to +3.3V (you may consider connecting the
RST input through a switch so that this pin is connected to GND when the switch is pressed,
thus enabling the device to be reset if required).
The output voltage of an Arduino pin is +5V and this is too high for the inputs of the ESP-
01. In this project a resistor potential divider circuit is used to lower the serial output volt-
age of the Arduino Uno to +3.3V before it is connected to the RX input of ESP-01. The TX
output of ESP-01 is connected to an input pin of the Arduino which is configured as a serial
input by the software. Pins 9 and 10 of the Arduino Uno are used as the serial RX and TX
pins respectively.
The front and back (tail) LEDs are connected to Arduino Uno port pins 7 and 6 respectively
through 330 Ohm current limiting resistors. The positive input of the active buzzer is con-
nected to pin 8 of the Arduino, and the other pin is connected to GND.
1A, 2A, 3A and 4A pins of the L293 motor controller chip are connected to port pins 2,3,4
and 5 of the Arduino Uno. As in the previous robot control projects, left and right motors of
the robot are connected to pins 3,6 and 11,14 of the L293 motor driver chip.
Power to the Arduino is supplied using 4 x Ni-Zn batteries, connected to Vin pin of the Ar-
duino Uno. The two wheel motors also receive their power from these batteries through pin
8 of the L293 chip. Notice that you must not power the motors from +5V pin of the Arduino
Uno as it may not be able to supply the required current for the two motors. Always use an
external power supply for the motors.
● 201
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Notice that the circuit is built on the breadboard mounted on top of the robot chassis. ESP-
01 board is not breadboard compatible and you will need to purchase a suitable adapter so
that you can mount it on the breadboard.
6 .2 .3 UDP or TCP ?
There are basically two protocols used in network applications (e.g. Wi-Fi): TCP/IP and UDP.
TCP/IP is a connection based protocol used to send data reliably from one point to another
one. UDP on the other hand is a connectionless protocol to send data fast from one point to
another one. Although TCP/IP is slow, it is reliable and guarantees the delivery of packets.
In addition, the sender receives an acknowledgement when a packet is delivered success-
fully. UDP does not guarantee the delivery of packets but it is much easier to setup and it
is much faster than the TCP/IP with smaller overheads. In this project we shall be using the
UDP protocol for simple and fast packet delivery from the mobile phone to the Arduino Uno.
● 202
CHAPTER 6 • ARDUINO WI-FI ROBOT CONTROL
• Make sure that the program is uploaded into your Arduino Uno and that power is
applied to the robot
• Start the apps UDP RECEIVE and SEND on your mobile phone
• Enter the following command and click SEND UDP (see Figure 6.5). Notice that
all commands must be terminated with the # character. Also, the time delay in
robot movement commands should be an integer not be greater than 99 seconds.
Notice that in this project the IP address of the ESP-01 was 192 .168 .1 .160 and
the port used for UDP communication was 5000:
h1#
The front LED should turn ON. To turn it OFF enter command h0#
Similarly, to turn the buzzer on enter b1# and to turn it OFF enter b0#
● 203
Motor Control - Projects with Arduino & Raspberry Pi Zero W
F03#
F15#
6 .2 .6 Program Listing
Figure 6.6 shows the program listing (program: mobile2). In this program the software
serial library is used instead of the hardware serial library (Pins 0 and 1, i.e. TX and RX)
for communicating with the ESP-01. The reason for this is because the Serial Monitor uses
the hardware serial pins TX and RX and we may need to use the Serial Monitor to display
various messages during the development of the program. By using the software serial
library we have freed the hardware serial pins and we can therefore use the Serial Monitor.
Software serial library is configured to use pins 9 and 10 for RX and TX respectively. The
serial link is named esp82666.
At the beginning of the program motor driver connections, LED connections, and the buzz-
er connection are defined. Inside the setup routine motor pins, LEDs and the buzzer are
configured as outputs. Also, the LEDs and the two motors are turned OFF to start with. In
addition, the speed of the software serial link esp8266 is set to 115200 (ESP-01 board by
default communicates at 115200 baud). The Serial Monitor is also started since we may
● 204
CHAPTER 6 • ARDUINO WI-FI ROBOT CONTROL
want to display various messages during the development of the program. ESP-01 is reset
by sending it the AT command AT+RST.
As in the previous project in Chapter 5, functions FORWARD, REVERSE, LEFT and RIGHT
move the robot in the specified directions. These functions have arguments which specify
for how long the action should take place in seconds.
Function SentToEsp8266 receives the command and the required timeout in seconds as
its arguments and sends this command to the ESP-01 board. The function waits a specified
number of milliseconds before returning so that the ESP-01 is ready to receive the next
command. The response of the ESP8266 to the send AT command is displayed in this func-
tion by the Serial Monitor. Therefore, you should open the Serial Monitor if you wish to see
the response such as the IP address allocated to the ESP-01 board.
Inside the main program, AT commands are sent to ESP-01 to connect it to the local Wi-
Fi and then waits to receive UDP packets. Notice that each command is terminated with
a carriage-return and line-feed pair. Command AT+CWJAP connects ESP-01 to the local
Wi-Fi where the SSID and the Password of the Wi-Fi must be specified in this command.
Command AT+CIFSR displays the IP address allocated to the ESP-01 by the Wi-Fi router.
Notice that the responses to all these commands are displayed by the Serial Monitor so that
you know what the allocated IP address to the ESP-01 is since this will be required when
sending UDP data from the mobile phone. Command AT+CIPSTART configures ESP-01 to
wait for UDP packets on port number 5000 and from any source.
The remainder of the program is the same as the program in Chapter 5 where the data is
received into array cmd and then the commands are decoded using a switch statement.
/*****************************************************************
* REMOTE ROBOT CONTROL USING Wi-Fi
* ================================
*
* In this project a mobile robot is connected to the Arduino Uno.
* In addition, a front LED, a back LED, and a buzzer are connected
* to the Arduino Uno.
*
* An ESP-01 (ESP8266 procesor) board is attached to the Arduino Uno
* so that it communicates with a mobile phone using Wi-Fi. The
* commands sent from the mobile phone can turn ON/OFF the LEDs
* and the buzzer, and it can also control the movements of the robot.
*
* The ESP-01 is connected to pins 9 and 10 of the Arduino and uses
* software serial communications library of Arduino.
*
* Valid commands are (The ommands must be terminated with the
* “#” character):
*
● 205
Motor Control - Projects with Arduino & Raspberry Pi Zero W
//
// Configure 1A, 2A, 3A, 4A, LEDs and Buzzer as outputs. Turn OFF
// LEDs and Buzzer at the begining. Also stop the motors at the
// beginning just in case. Start the software serial link named
// esp8266 and reset the ESP-01 by sending an AT command.
//
void setup()
{
pinMode(L1A, OUTPUT);
pinMode(L2A, OUTPUT);
pinMode(R3A, OUTPUT);
pinMode(R4A, OUTPUT);
● 206
CHAPTER 6 • ARDUINO WI-FI ROBOT CONTROL
pinMode(FrontLED, OUTPUT);
pinMode(TailLED, OUTPUT);
pinMode(Buzzer, OUTPUT);
digitalWrite(FrontLED, LOW);
digitalWrite(TailLED, LOW);
digitalWrite(Buzzer, LOW);
StopMotors();
esp8266.begin(115200);
Serial.begin(9600);
SendToEsp8266(“AT+RST\r\n”, 2000);
}
//
// This function stops the motor
//
void StopMotors()
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, LOW);
digitalWrite(R3A, LOW);
digitalWrite(R4A, LOW);
}
//
// This function moves the robot forward for tim seconds. Both
// motors rotate in the same direction
//
void FORWARD(char tim)
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, HIGH);
digitalWrite(R3A, LOW);
digitalWrite(R4A, HIGH);
delay(tim*1000);
StopMotors();
}
//
// This function reverses the motor for tim seconds. Both motors
// rotate in the same direction
//
void REVERSE(char tim)
{
digitalWrite(L1A, HIGH);
digitalWrite(L2A, LOW);
digitalWrite(R3A, HIGH);
● 207
Motor Control - Projects with Arduino & Raspberry Pi Zero W
digitalWrite(R4A, LOW);
delay(tim*1000);
StopMotors();
}
//
// This function turns the motor LEFT for tim seconds. Left motor
// is stopped and the right motor is activated
//
void LEFT(char tim)
{
digitalWrite(L1A, HIGH);
digitalWrite(L2A, LOW);
digitalWrite(R3A, LOW);
digitalWrite(R4A, HIGH);
delay(tim*1000);
StopMotors();
}
// This function turns the motor RIGHT for tim seconds. Right motor
// is stopped and the left motor is activated
//
void RIGHT(char tim)
{
digitalWrite(L1A, LOW);
digitalWrite(L2A, HIGH);
digitalWrite(R3A, HIGH);
digitalWrite(R4A, LOW);
delay(tim*1000);
StopMotors();
}
//
// This function extracts the required delay in a motor movement
// command. The delay is in seconds
//
int GetDelay()
{
int dly = 10*(cmd[1]-'0') + cmd[2] - '0';
return dly;
}
● 208
CHAPTER 6 • ARDUINO WI-FI ROBOT CONTROL
//
// Main program loop. Read the command from the ESP-01 device
// through Wi-Fi, decode the command and implement the control action
// as required. AT commands are sent to the ESP-01 to connect the
// Arduino Uno to Wi-Fi and then wait to receive UDP packets.
//
void loop()
{
if(First == 1)
{
First = 0;
SendToEsp8266(“AT+CWMODE=1\r\n”, 5000);
SendToEsp8266(“AT+CWJAP=\”BTHomeSpot-XNH\”,\”49345abaeb\”\r\n”, 5000);
delay(10000);
SendToEsp8266(“AT+CPIMUX=1\r\n”, 2000);
SendToEsp8266(“AT+CIFSR\r\n”,3000);
SendToEsp8266(“AT+CIPSTART=\”UDP\”,\”0.0.0.0\”,0,5000,2\r\n”, 5000);
delay(100);
}
cmd[0]=0; // Clear command array
cmd[1]=0;
cmd[2]=0;
● 209
Motor Control - Projects with Arduino & Raspberry Pi Zero W
if(cmd[1] == '1')
digitalWrite(TailLED, HIGH);
else if(cmd[1] == '0')
digitalWrite(TailLED, LOW);
break;
case 'b': // Buzzer
if(cmd[1] == '1')
digitalWrite(Buzzer, HIGH);
else if(cmd[1] == '0')
digitalWrite(Buzzer, 0);
break;
case 'F': // Forward
DelayTime = GetDelay();
FORWARD(DelayTime);
break;
case 'B': // BAckwards
DelayTime = GetDelay();
REVERSE(DelayTime);
break;
case 'L': // Left
DelayTime = GetDelay();
LEFT(DelayTime);
break;
case 'R': // Right
DelayTime = GetDelay();
RIGHT(DelayTime);
break;
}
}
}
Figure 6.6 Program listing
● 210
CHAPTER 6 • ARDUINO WI-FI ROBOT CONTROL
6 .3 Summary
In this Chapter we have seen how to control a robot remotely from a mobile phone using
Wi-Fi interface. An Arduino Uno is used in this Chapter as the controller.
In the next Chapter we shall be looking at how to control the same robot again from a mo-
bile phone, but this time using Bluetooth on a Raspberry Pi.
● 211
Motor Control - Projects with Arduino & Raspberry Pi Zero W
7 .1 Overview
In this Chapter we shall see how to control our robot remotely using Wi-Fi on our mobile
phone to give commands to the RPi ZW mounted on the robot chassis. The robot used in
this Chapter is the one used in Chapter 3. By giving commands on our mobile phone we
shall see how to move the robot forwards, backwards, turning left or right, and so on. In
this project an Android type mobile phone is used to send commands to the robot. In this
project, UDP data packets are used for communication between the mobile phone and the
RPi ZW.
Same commands as the ones given in Table 5.1 and Table 5.2 will be used in this project.
7 .2 .1 Block Diagram
The block diagram of the project is shown in Figure 7.1. Because the RPi ZW has Wi-Fi
capability, there is no need to use an external Wi-Fi module.
7 .2 .2 Circuit Diagram
The circuit diagram of the project is shown in Figure 7.2. GPIO2, GPIO3, GPIO17 and
GPIO27 pins are connected to pins 1A, 2A, 3A, and 4A of the motor driver IC respectively.
Front and rear LEDs are connected to ports GPIO9 and GPIO22 respectively. The buzzer is
connected to GPIO10. Power to the motors is supplied by the batteries since the RPi ZW
cannot provide power for the motors. A +5V portable charger unit is used to supply power
to the raspberry Pi Zero W.
● 212
CHAPTER 7 • RASPBERRY PI ZERO W WI-FI ROBOT CONTROL
7 .2 .3 Program Listing
The communication between the Android mobile phone and the RPi ZW is based on Wi-Fi.
As in Chapter 6, UDP RECEIVE and SEND by Wezzi Studios (version 4.0) apps is used on
the mobile phone to send UDP packets to the RPi ZW.
The program listing is shown in Figure 7.3 (program: mobile1.py). The Python program on
the RPi ZW uses the socket library. At the beginning of the program the socket library is
imported into the program, motor driver pins, LED pins, and the buzzer pin are assigned to
GPIO ports. These pins are then configured as outputs.
Functions FORWARD, REVERSE, LEFT and RIGHT move the robot by the specified number
of seconds in the selected direction.
The program uses port 5000 to communicate with the mobile phone using UDP packets.
The IP address of the RPi ZW Wi-Fi connection must be specified in the code. This can be
found by entering the following code at the RPi ZW command mode:
Figure 7.4 shows a typical display when the above command is entered. In this example,
the IP address of the RPi ZW was 192 .168 .1 .161 and this was assigned to variable IP in
the program.
● 213
Motor Control - Projects with Arduino & Raspberry Pi Zero W
An endless loop is then formed where inside this loop UDP packets are received in the form
of commands using the following statement:
The received commands are decoded and the required actions are implemented. For exam-
ple, if the command is h1 to turn ON the front LED, then the following code is executed:
if data[0] == 'h':
if data[1] == '1':
GPIO.output(FrontLED, 1)
else:
GPIO.output(FrontLED, 0)
As before, you should enter the program name in the following format into file /etc/rc .lo-
cal so that the program starts automatically after the RPI ZW re-starts:
#-------------------------------------------------------------------
# REMOTE ROBOT CONTROL VIA WI-FI
# ==============================
#
# In this project the RPi ZW is mounted on the robot chassis together
# with the L293 motor driver IC. In addition, two LEDs are mounted on
# the robot chasses: Front LED and Rear LED. Additionally, a buzzer is
# mounted on the breadboard. The Raspberry Pi Zero W has on board
# Wi-Fi and Bluetooth capability. In this example only the Wi-Fi is
# used.
#
# In this project the LEDs, buzzer and the robot movements are all
# controlled from a mobile phone using the Wi-Fi link to establish
# communciation between the mobile phone and the RPi ZW.
● 214
CHAPTER 7 • RASPBERRY PI ZERO W WI-FI ROBOT CONTROL
#
# The commands are as follows (In the robot movement commands the
# time must be an integer number):
#
# h1 Turn ON front LED, h0 Turn OFF front LED
# t1 Turn ON rear LED, t0 Turn OFF rear LED
# b1 Turn ON buzzer, b0 Turn OFF buzzer
# Fn Move robot forward n seconds
# Bn Move robot reverse n seconds
# Ln Turn robot left n seconds
# Rn Turn robot right n seconds
#
#
# File : mobile1.py
# Date : September 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
import time
import socket
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
#
# L293 control pins
#
L1A = 2 # GPIO2
L2A = 3 # GPIO3
R3A = 17 # GPIO17
R4A = 27 # GPIO2
#
# LED and Buzzer pins
#
FrontLED = 9
RearLED = 22
Buzzer = 10
global data
#
# Configure L293 control pins, LED, and buzzer as outputs
#
GPIO.setup(L1A, GPIO.OUT)
GPIO.setup(L2A, GPIO.OUT)
GPIO.setup(R3A, GPIO.OUT)
GPIO.setup(R4A, GPIO.OUT)
● 215
Motor Control - Projects with Arduino & Raspberry Pi Zero W
GPIO.setup(FrontLED, GPIO.OUT)
GPIO.setup(RearLED, GPIO.OUT)
GPIO.setup(Buzzer, GPIO.OUT)
#
# Stop the motor
#
def StopMotor():
GPIO.output(L1A, 0)
GPIO.output(L2A, 0)
GPIO.output(R3A, 0)
GPIO.output(R4A, 0)
return
#
# Set forward movement
#
def FORWARD(tim):
GPIO.output(L1A, 0)
GPIO.output(L2A, 1)
GPIO.output(R3A, 0)
GPIO.output(R4A, 1)
time.sleep(tim)
StopMotor()
return
#
# Set reverse movement
#
def REVERSE(tim):
GPIO.output(L1A, 1)
GPIO.output(L2A, 0)
GPIO.output(R3A, 1)
GPIO.output(R4A, 0)
StopMotor()
return
#
# Turn left
#
def LEFT(tim):
GPIO.output(L1A, 1)
GPIO.output(L2A, 0)
GPIO.output(R3A, 0)
GPIO.output(R4A, 1)
time.sleep(tim)
● 216
CHAPTER 7 • RASPBERRY PI ZERO W WI-FI ROBOT CONTROL
StopMotor()
return
#
# Turn right
#
def RIGHT(tim):
GPIO.output(L1A, 0)
GPIO.output(L2A, 1)
GPIO.output(R3A, 1)
GPIO.output(R4A, 0)
time.sleep(tim)
StopMotor()
return
#
# This function extracts the delay in seconds
#
def GetDelay():
global data
No = int(data[1:])
return No
#
# Start of the main program loop. Get a command from the mobile
# phone, decode the command, and implement the required action
##
# Stop the motors at the beginning of the program. Define the UDP
# port number and the IP address of our RPi ZW (can be found using
# command sudo ifconfig in command mode).
#
StopMotor()
PORT = 5000
IP = “192.168.1.161”
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((IP, PORT))
#
# Start of the program loop where a command is received and implemented
#
while True:
data, addr = sock.recvfrom(10)
#
# Decode and implement the command. First index of data[0] is the comamnd
# itself (h,t,b,F,B,R,L). In ythe case of LED and Buzzer controls, the
# second index cmd[1] is 1 or 0 depending whether or not we wish to turn
# ON or OFF respectively. In teh case of motor movement cmd[1],cmd[2]...
● 217
Motor Control - Projects with Arduino & Raspberry Pi Zero W
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 RPi ZW is re-started. You should also
shutdown your RPi ZW orderly instead of just removing the power cable. The command to
shutdown orderly is:
Figure 7.5 shows the command entered to turn the front LED ON. The robot assembly is
shown in Figure 7.6.
● 218
CHAPTER 7 • RASPBERRY PI ZERO W WI-FI ROBOT CONTROL
● 219
Motor Control - Projects with Arduino & Raspberry Pi Zero W
7 .3 Summary
In this Chapter we have seen how to control a robot remotely from a mobile phone using
Wi-Fi interface. A Raspberry Pi Zero W is used in this Chapter as the controller.
In the next Chapter we shall be looking at how to control the same robot again from a mo-
bile phone, but this time using Bluetooth on a Raspberry Pi Zero W.
● 220
CHAPTER 8 • RASPBERRY PI ZERO W BLUETOOTH ROBOT CONTROL
8 .1 Overview
Raspberry Pi Zero W is both Wi-Fi and Bluetooth enabled. In this Chapter we shall see how
to control our robot remotely using Bluetooth on our mobile phone to give commands to
the RPi ZW mounted on the robot chassis. The robot used in this Chapter is the one used in
Chapter 7. By giving commands on our mobile phone we shall see how to move the robot
forwards, backwards, turning left or right, and so on. In this project an Android type mobile
phone is used to send commands to the robot.
8 .2 .1 Block Diagram
The block diagram of this project is same as the one given in Figure 7.1, but instead of
Wi-Fi, in this project Bluetooth is used for communication between the mobile phone and
the RPi ZW.
8 .2 .2 Circuit Diagram
The circuit diagram of this project is as shown in Figure 7.2. The LEDs, buzzer, and the mo-
tor driver IC are all connected to the RPi ZW. Power to the RPi ZW is supplied from a +5V
portable charger unit mounted on the robot chassis. Power to the wheel motors is supplied
from 4 x NiZn AA type batteries as in the previous robot control projects.
There are two ways you can enable Bluetooth on the RPi ZW: using graphical desktop (GUI
mode), or using the command mode.
• Start the VNC server on your RPi ZW and login to the RPi ZW using the VNC
Viewer.
• Click on the Bluetooth icon on your RPi ZW at the top right hand side, and turn
Bluetooth ON. Then, select Make Discoverable . You should see the Bluetooth
icon flashing (Figure 8.1)
● 221
Motor Control - Projects with Arduino & Raspberry Pi Zero W
• You should now see the message Connected Successfully on your RPi ZW
• Start the Bluetooth tool on your Rpi ZW from the command mode:
pi@raspberrypi:~ $ bluetoothctl
[bluetooth]# power on
[bluetooth]# agent on
[Bluetooth]# default-agent
[Bluetooth]# discoverable on
• Scan for nearby Bluetooth devices. You should see the nearby Bluetooth devices
● 222
CHAPTER 8 • RASPBERRY PI ZERO W BLUETOOTH ROBOT CONTROL
listed with their MAC addresses. Make a note of the MAC address of the device
you wish to connect to (Android mobile phone in this project) as we will be using
this address to connect to the device. An example is shown in Figure 8.3:
[bluetooth]# scan on
In this example our mobile phone is VFD900 and the Bluetooth MAC address is:
28:BE:03:7A:53:F5
You can find the Bluetooth MAC address of your RPi ZW by entering the following command:
You can change the Bluetooth broadcast name by the following command:
● 223
Motor Control - Projects with Arduino & Raspberry Pi Zero W
You can find the Bluetooth MAC address of your Android phone as follows:
• Go to Settings menu
• Tap Status
• Add –C at the end of the ExecStart= line. Also add another line after the Exec-
Start line. The final two lines should look like:
ExecStart=/usr/lib/bluetooth/bluetoothd -C
ExecStartPost=/usr/bin/sdptool add SP
8 .2 .5 Program Listing
RPi ZW supports two types of Bluetooth sockets: RFCOMM and L2CAP. In this project RF-
COMM is used. The two socket types are similar with the difference that they use different
port numbers.
Figure 8.4 shows the program listing (program: mobile2.py). At the beginning of the pro-
● 224
CHAPTER 8 • RASPBERRY PI ZERO W BLUETOOTH ROBOT CONTROL
gram RPi.GPIO, time, and Bluetooth libraries are imported into the program. The motor
driver connections, LED connections, and the buzzer connections are as before. Functions
FORWARD, REVERSE, LEFT and RIGHT move the robot in the specified directions with the
specified duration. The Bluetooth socket is configured so that it accepts connection from
any paired and connected device.
The remainder of the program is executed in an endless loop where the program waits to
receive data through the Bluetooth socket, and then decodes and implements this code as
before.
#-------------------------------------------------------------------
# REMOTE ROBOT CONTROL VIA BLUETOOTH
# ==================================
#
# In this project the RPi ZW is mounted on the robot chassis together
# with the L293 motor driver IC. In addition, two LEDs are mounted on
# the robot chasses: Front LED and Rear LED. Additionally, a buzzer is
# mounted on the breadboard. The Raspberry Pi Zero W has on board
# Wi-Fi and Bluetooth capability. In this example only the Bluetooth
# is used.
#
# In this project the LEDs, buzzer and the robot movements are all
# controlled from a mobile phone using the Bluetooth link to establish
# communciation between the mobile phone and the RPi ZW.
#
# The commands are as follows (In the robot movement commands the
# time must be an integer number):
#
# h1 Turn ON front LED, h0 Turn OFF front LED
# t1 Turn ON rear LED, t0 Turn OFF rear LED
# b1 Turn ON buzzer, b0 Turn OFF buzzer
# Fn Move robot forward n seconds
# Bn Move robot reverse n seconds
# Ln Turn robot left n seconds
# Rn Turn robot right n seconds
#
#
# File : mobile2.py
# Date : October 2017
# Author: Dogan Ibrahim
#----------------------------------------------------------------------
import RPi.GPIO as GPIO
import time
import bluetooth
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
● 225
Motor Control - Projects with Arduino & Raspberry Pi Zero W
#
# L293 control pins
#
L1A = 2 # GPIO2
L2A = 3 # GPIO3
R3A = 17 # GPIO17
R4A = 27 # GPIO2
#
# LED and Buzzer pins
#
FrontLED = 9
RearLED = 22
Buzzer = 10
global data
#
# Configure L293 control pins, LED, and buzzer as outputs
#
GPIO.setup(L1A, GPIO.OUT)
GPIO.setup(L2A, GPIO.OUT)
GPIO.setup(R3A, GPIO.OUT)
GPIO.setup(R4A, GPIO.OUT)
GPIO.setup(FrontLED, GPIO.OUT)
GPIO.setup(RearLED, GPIO.OUT)
GPIO.setup(Buzzer, GPIO.OUT)
#
# Stop the motor
#
def StopMotor():
GPIO.output(L1A, 0)
GPIO.output(L2A, 0)
GPIO.output(R3A, 0)
GPIO.output(R4A, 0)
return
#
# Set forward movement
#
def FORWARD(tim):
GPIO.output(L1A, 0)
GPIO.output(L2A, 1)
GPIO.output(R3A, 0)
GPIO.output(R4A, 1)
● 226
CHAPTER 8 • RASPBERRY PI ZERO W BLUETOOTH ROBOT CONTROL
time.sleep(tim)
StopMotor()
return
#
# Set reverse movement
#
def REVERSE(tim):
GPIO.output(L1A, 1)
GPIO.output(L2A, 0)
GPIO.output(R3A, 1)
GPIO.output(R4A, 0)
StopMotor()
return
#
# Turn left
#
def LEFT(tim):
GPIO.output(L1A, 1)
GPIO.output(L2A, 0)
GPIO.output(R3A, 0)
GPIO.output(R4A, 1)
time.sleep(tim)
StopMotor()
return
#
# Turn right
#
def RIGHT(tim):
GPIO.output(L1A, 0)
GPIO.output(L2A, 1)
GPIO.output(R3A, 1)
GPIO.output(R4A, 0)
time.sleep(tim)
StopMotor()
return
#
# This function extracts the delay in seconds
#
def GetDelay():
global data
No = int(data[1:])
return No
● 227
Motor Control - Projects with Arduino & Raspberry Pi Zero W
#
# Start of the main program loop. Get a command from the mobile
# phone, decode the command, and implement the required action
##
# Stop the motors at the beginning of the program. Initialize the
# Bluetooth code
#
StopMotor()
ServerSock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
Port = 1
ServerSock.bind((“”, Port))
ServerSock.listen(1)
ClientSock,addr = ServerSock.accept()
#
# Start of the program loop where a command is received and implemented
#
while True:
data = ClientSock.recv(1024)
#
# Decode and implement the command. First index of data[0] is the comamnd
# itself (h,t,b,F,B,R,L). In ythe case of LED and Buzzer controls, the
# second index cmd[1] is 1 or 0 depending whether or not we wish to turn
# ON or OFF respectively. In teh case of motor movement cmd[1],cmd[2]...
# are the times in seconds that the motor should be ON
#
if data[0] == 'h':
if data[1] == '1':
GPIO.output(FrontLED, 1)
else:
GPIO.output(FrontLED, 0)
elif data[0] == 't':
if data[1] == '1':
GPIO.output(RearLED, 1)
else:
GPIO.output(RearLED, 0)
elif data[0] == 'b':
if data[1] == '1':
GPIO.output(Buzzer, 1)
else:
GPIO.output(Buzzer, 0)
elif data[0] == 'F':
DelayTime = GetDelay()
● 228
CHAPTER 8 • RASPBERRY PI ZERO W BLUETOOTH ROBOT CONTROL
FORWARD(DelayTime)
elif data[0] == 'B':
DelayTime = GetDelay()
REVERSE(DelayTime)
elif data[0] == 'L':
DelayTime = GetDelay()
LEFT(DelayTime)
elif data[0] == 'R':
DelayTime = GetDelay()
RIGHT(DelayTime)
Figure 8.5 shows the mobile application ready to send command h1 to the RPi ZW to turn
ON the front LED. Notice that you must start the RPi ZW program before starting the apps
on your mobile phone.
As before, you should enter the program name in the following format into file /etc/rc .lo-
cal so that the program starts automatically after the RPI ZW re-starts:
● 229
Motor Control - Projects with Arduino & Raspberry Pi Zero W
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 RPi ZW is re-started. You should also
shutdown your RPi ZW orderly instead of just removing the power cable. The command to
shutdown orderly is:
8 .3 Summary
In this Chapter we have seen how to control a robot remotely using the Bluetooth commu-
nications between an Android mobile phone and the Raspberry Pi Zero W
● 230
APPENDIX A • RASPBERRY PI ZERO W
Raspberry Pi and Raspberry Pi Zero have been around for several years. The Zero W (
W for “wireless”) is a new addition to the family and it incorporates WLAN and Bluetooth
capabilities. In this Appendix we shall briefly look at the specifications of the Raspberry Pi
Zero W (called RPi WZ in future references) and also see how the operating system can be
installed on an SD card. With its low cost of around $20, the RPi WZ is an ideal choice for
many wireless, robotics, control, monitoring, and automation projects.
A .1 The Hardware
The GPIO interface is accessed through a 40-way header which should be soldered to the
board.
Figure A.1 shows the RPi WZ. At the top of the board is the GPIO ports. At the bottom of
the board are the HDMI socket, USB socket, and the power socket. On the left hand side is
the micro SD card socket. On the right hand side is the camera interface.
● 231
Motor Control - Projects with Arduino & Raspberry Pi Zero W
As with all the Raspberry Pi boards, a power supply, a keyboard, mouse (or another input
device), and screen (monitor) must be provided to use the RPi WZ.
The RPi ZW should be connected to a monitor through its HDMI socket. A keyboard, pref-
erably with a mouse should be connected to the micro-USB socket, and the power supply
should be connected to the micro-USB power socket.
The instructions to install the operating system on a blank SD card are given below. You
will need a micro SD card with a capacity of at least 8 GB of memory, although16 GB is rec-
ommended for future expansion and installing new applications and programs. You might
need a SD card adapter to insert the micro SD card into your computer's card slot. The
recommended operating system is called Raspbian.
● 232
APPENDIX A • RASPBERRY PI ZERO W
• Download (ZIP) the current file Image of Raspbian from the following site (see
Figure A.3) to a folder on your PC (e.g. to C:\RPI). It is recommended that first
time users download and install the software called NOOBS (New Out Of Box
Software) onto a new 8GB or larger micro SD card. The version at the time of
writing this book is 2.4.3:
www.raspberrypi.org/downloads/raspbian
• Install the SD Formatter software from the SD Association's web site (see Figure
A.4). At the time of writing this book the software was called SD_CardFormat-
ter0500SetupEN.exe:
https://www.sdcard.org/downloads/formatter_4/eula_windows/index.html
● 233
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Insert your SD card into your computer's card socket and make note of the drive letter
allocated to it. e.g. F:\ as shown in Figure A.5
Figure A.5 Make a note of the drive letter allocated to your SD card
Start the SD card formatter you have installed and enter the drive letter to format the SD
card, select Quick format as shown in Figure A.6 (be careful to enter the correct drive
letter here otherwise you might delete all the files on your computer!).
• Extract all the files from the folder where you have stored the NOOBS operating
system ZIP file.
• Drag all the extracted files and drop them to the newly formatted SD card. All
the necessary files will be transferred to the SD card. After copying, part of the
contents of the SD card are shown in Figure A.7
● 234
APPENDIX A • RASPBERRY PI ZERO W
• Remove the SD card from your computer and install into the Raspberry Pi Zero
W micro SD card slot.
Notice that further information about the installation process can be obtained from the
following link:
https://www.raspberrypi.org/learning/software-guide/quickstart/
Note that the author used the Ultra Mini Keyboard with built-in mouse as shown in Figure
A.9. This keyboard is connected to the RPi WZ via wireless USB port.
● 235
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 236
APPENDIX A • RASPBERRY PI ZERO W
At the end of the installation you should restart the RPi WZ which will display the GUI
screen shown in Figure A.11 after the restart.
Setting Up WiFi
To enable the WiFi on your RPi WZ, the steps are as follows:
• Click on the WiFi icon which is a pair of red crosses at the top right hand side of
the screen
• Select your WiFi router from the displayed list (see Figure A.12)
● 237
Motor Control - Projects with Arduino & Raspberry Pi Zero W
• The WiFi icon should become a typical WiFi image. If you click on the icon now
you should see a green tick next to the selected router as shown in Figure A.13.
• To see the IP address of your WiFi connection, place the mouse over the WiFi
icon as shown in Figure A.14. In this example the IP address was 192.168.1.84
Remote Access
The program we will be using to access our RPi WZ is called Putty with the SSH protocol.
The steps to download and use Putty are as follows:
• Download Putty from the following link (or search Google for “Download Putty”)
● 238
APPENDIX A • RASPBERRY PI ZERO W
http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
• For security reasons the SSH protocol is disabled by default on a new operat-
ing system. To enable it, click on the Applications menu at the top left of the
screen, click Accessories, and then click Terminal (see Figure A.15)
sudo raspi-config
● 239
Motor Control - Projects with Arduino & Raspberry Pi Zero W
• Click <Finish> to exit the configuration menu. You should now be back in the
command mode, identified by the prompt:
pi@raspberrypi:~ $
• Putty is a standalone program and there is no need to install it. Simply double
click to run it. You should see the Putty startup screen as in Figure A.17
• Make sure that the Connection type is SSH and enter the IP address of your RPi
WZ. Click Open as shown in Figure A.18)
● 240
APPENDIX A • RASPBERRY PI ZERO W
• The message shown in Figure A.19 will be displayed on the PC screen the first
time you access the RPi WZ. Click Yes to accept this security alert.
• You will then be prompted for the username and password. The default values
are:
Username: pi
Password: raspberry
• After a successful login you should see the RPi ZW command prompt a sin Figure
A.20.
● 241
Motor Control - Projects with Arduino & Raspberry Pi Zero W
passwd
sudo reboot
• To shutdown the RPi ZW enter the following command. Never shutdown by pull-
ing the power cable as this may result in the corruption or loss of files:
● 242
APPENDIX A • RASPBERRY PI ZERO W
• Connect to your RPi ZW using SSH as explained earlier. Then enter the following
command to install a program called TightVNC server on your RPi ZW. You will
see many lines of messages. Make sure there are no error messages:
• Run the VNC server on your RPi ZW by entering the following command:
vncserver :1
• You will be prompted to enter and verify a password. This will be the password
you will be using to access the Desktop remotely (see Figure A.22).
● 243
Motor Control - Projects with Arduino & Raspberry Pi Zero W
• The VNC server is now running on your RPi ZW. The only command you need to
enter on your RPi ZW to start the VNC server is:
vncserver :1
• We must now setup a VNC client on our laptop (or desktop). There are many VNC
clients available, but the recommended one which is compatible with TightVNC
is the VNCViewer, which can be downloaded from the following link. Note that
this program is not free of charge, but a 30 day free trial version is available. You
should register to get a trial license and then apply this license to the software to
use free of charge for 30 days:
http://www.realvnc.com
● 244
APPENDIX A • RASPBERRY PI ZERO W
• Enter the password selected previously. You should now see the RPi ZW Desktop
displayed on your laptop (or desktop) computer as in Figure A.24 and you can
access all of the Desktop applications remotely.
A .8 Enabling Bluetooth
In this section we will see how to enable the Bluetooth on your RPi ZW so that it can com-
municate with your mobile phone. The steps are given below:
• Click on the Bluetooth icon on your RPi ZW at the top right hand side, and select
Make Discoverable . You should see the Bluetooth icon flashing
• You should now see the message Connected Successfully on your RPi ZW and
you can exchange files between your mobile device and the RPi ZW.
● 245
Motor Control - Projects with Arduino & Raspberry Pi Zero W
• At the command prompt enter python. You should see the Python command
mode which is identified by three characters >>>
• The required text will be displayed interactively on the screen as shown in Figure
A.26
● 246
APPENDIX A • RASPBERRY PI ZERO W
• You should see the Python command mode, identified by characters >>>
• Click File and then click New File and write your program
• Run the program by clicking Run and then Run Module as shown in Figure A.29
• A new screen will be shown with the output of the program displayed as in Figure
A.30
● 247
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Which Method ?
The choice of a method depends upon the size and complexity of a program. Small pro-
grams can be run interactively without creating a program file. Larger programs can be
created as Python files and then they can run either in the command mode or in the GUI
mode. In this book, program files are created for all the Python programs.
If you get an error while trying to import the GPIO library then it is possible that the library
is not installed. Enter the following commands while in the command mode (identified by
the prompt pi@raspberrypi:~ $) to install the GPIO library (characters that should be
entered by you are in bold):
The GPIO provides a number of useful functions. The available functions are given in the
next sections
The second numbering system, also known as the BCM method is the preferred method and
it uses the channel numbers allocated to the pins. This method requires you to know which
channel number refers to which pin on the board. In this book we shall be using this second
method. Enter the following statement to use the BCM method:
● 248
APPENDIX A • RASPBERRY PI ZERO W
Input Configuration
You need to configure the channels (or port pins) you are using whether they are input or
output channels. The following statement is used to configure a channel as an input. Here,
channel refers to the channel number based on the setmode statement above:
When there is nothing connected to an input pin, the data at this input is not defined. We
can specify additional parameters with the input configuration statement to connect pull-up
or pull-down resistors by software to an input pin. The required statements are:
For pull-down:
For pull-up:
We can detect an edge change of an input signal at an input pin. Edge change is when
the signal changes from LOW to HIGH (rising edge), or from HIGH to LOW (falling edge).
For example, pressing a push-button switch can cause an edge change at the input of a
pin. The following statements can be used to wait for an edge of the input signal. These
are blocking functions. i.e. the program will wait until the specified edge is detected at the
input signal. For example, if this is a push-button, the program will wait until the button is
pressed:
We can also wait until either a rising or a falling edge is detected by using the following
statement:
We can use event detection function with an input pin. This way, we can execute the event
detection code whenever an event is detected. Events can be rising edge, falling edge, or
change in either edge of the signal. Event detection is usually used in loops where we can
check for the event while executing other code.
● 249
Motor Control - Projects with Arduino & Raspberry Pi Zero W
We can check whether or not the event occurred by the following statement:
If GPIO .event_detected(channel):
……………………………
……………………………
GPIO .remove_event_detect(channel)
We can also use interrupt facilities (or callbacks) to detect events. Here, the event is han-
dled inside a user function. The main program carries on its usual duties and as soon as
the event occurs the program stops whatever it is doing and jumps to the event handling
function. For example, the following statement can be used to add interrupt based event
handling to our programs on rising edge of an input signal. In this example, the event han-
dling code is the function named MyHandler:
def MyHandler(channel):
………………….
………………….
We can add more than one interrupt by using the add_event_callback function. Here the
callback functions are executed sequentially:
def MyHandler1(channel):
……………………
……………………
def MyHandler2(channel):
……………………
……………………
● 250
APPENDIX A • RASPBERRY PI ZERO W
When we use mechanical switches in our projects we get what is known as the switch
bouncing problem. This occurs as the contacts of the switch bounce many times until they
settle to their final state. Switch bouncing could generate several pulses before it settles
down. We can avoid switch bouncing problems in hardware or software. GPIO library pro-
vides a parameter called bouncetime that can be used to eliminate the switch bouncing
problem. An example use of this parameter is shown below where the switch bounce time
is assumed to be 10ms:
We can also use the callback statement to specify the switch bouncing time as@
To read the state of an input pin we can use the following statement:
GPIO .input(channel)
Output Configuration
The following statement is used to configure a channel as an output. Here, channel refers
to the port number based on the setmode statement described earlier:
We can specify a value for an output pin during its setup. For example, we can configure a
channel as output and at the same time set its value to logic HIGH (+3.3V):
To send data to an output port pin we can use the following statement:
At the end of the program we should return all the used resources to the operating system.
This is done by including the following statement at the end of our program:
GPIO .cleanup()
● 251
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 252
APPENDIX C • ARDUINO UNO PIN DIAGRAM
● 253
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 254
APPENDIX E • USING THE gpiozero LIBRARY
gpiozero is a Python library that includes many functions that can be used to interface to
various peripheral devices such as LEDs, RGB LEDs, LED bar graphs, buttons, line sensors,
motion sensors, light sensors, distance sensors, motors, buzzers, ADC, robot control, digital
input/output, SPI devices, and many more.
gpiozero functions are very detailed and make the programming a much easier task. Fur-
ther information about the use of gpiozero and all of its library functions is available at the
following web site:
https://gpiozero.readthedocs.io/en/stable/index.html
gpiozero library uses Broadcom (BCM) pin numbering for the GPIO pins as was the case in
all the Python programs in this book.
Some examples are given in this Appendix to show how easy it is to develop projects using
the gpiozero library functions.
Example A .1
Write a Python program using the gpiozero library to flash an LED connected to port pin
GPIO2.
Solution A .1
The program is given below:
We could instead use the blink function as follows. The default flashing time is 1 second,
but can be changed if required:
● 255
Motor Control - Projects with Arduino & Raspberry Pi Zero W
where,
background: If True (default) starts a background thread to continue blinking and return
immediately. If False, returns when blink is finished
Example A .2
A push-button switch is connected to port pin GPIO3 with one of the legs of the button
connected to ground. Write a program using the gpiozero library to display the message
Button pressed when the button is pressed, and display Button is not pressed when
the button is not pressed.
Solution A .2
The program is given below:
hold_time: time to wait in seconds (default is 1) after the button is pressed until executing
the when_held handler
hold_repeat: if True, the when_held handler will be repeatedly executed as long as the
device remains active, every hold_time seconds.
● 256
APPENDIX E • USING THE gpiozero LIBRARY
The reader should refer to the web site given at the beginning of this Appendix for further
details on using the gpiozero library.
● 257
Motor Control - Projects with Arduino & Raspberry Pi Zero W
Index
B L
Bipolar Stepper Motor 145 L293 63
Bluetooth 186 LCD 83
Bluetooth apps 189 LDR 123
Brushed DC Motor 16 LEFT 113
Brushless DC Motor 23 Level-sensitive 98
Line Following Robot 123
C LiquidCrystal_I2C 85
closed loop control 92 LM1086-3.3 201
commutator 16, 18 LMD18200 70
compare match register 106
Compound Wound BDC Motor 20 M
MCP3002 47
D millis 81
derivative constant 93 MOSFET 35
DHT11 164 Motor identification 89
duty cycle 39 motor speed 83
Duty Cycle 183 MOTOR STEP RESPONSE 89
E N
Echo 118 NiZn 110
ESP-01 200 NOOBS 233
esp8266 204 NPN 56
F O
falling 98 Obstacle avoidance 117
FORWARD 113 ON/OFF motor control (Arduino) 30
full-step 144, 150 ON/OFF motor control (RPi ZW) 32
H P
half-step 144 Pairing HC-06 189
Half-step 151 Permanent Magnet BDC Motor 18
Half-Step 154 PID control 93
H bridge 55, 57 PNP 56
HC-06 187 portable charger 132
potentiometer 46
I proportional constant 93
I2C 102 pulseIn 120
● 258
Index
S
SD Formatter 233
Separately Excited BDC Motor 20
Series Wound BDC Motor 19
Servo Motor 21
SERVO MOTOR 172
SG90 172
Shunt Wound BDC Motor 19
Slope Resistance 25
SSH 237
stator 16
Stepper Motor 22
STEPPER MOTOR 144
stop mark 130
T
TCP 202
TCRT5000 123
TEMPERATURE DIAL 165
time constant 28, 91
time response 91
Timer Interrupt 106
TMP36 163
Torque 24
Transfer Function 26
Two speed control 37
U
UDP 202
ULN2003 147
● 259
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 260
● 261
Motor Control - Projects with Arduino & Raspberry Pi Zero W
● 262
PROJECTS WITH ARDUINO & RASPBERRY PI
MOTOR CONTROL
Dogan Ibrahim
www.elektor.com
LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN
DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN
SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ●
LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN
DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN ● SHARE ● LEARN ● DESIGN