You are on page 1of 162

Begin with Arduino®

Begin with Arduino®


BEGIN YOUR JOURNEY AS A MAKER

Sanjib Acharya
Copyrights © 2020 Sanjib Acharya

All rights reserved. No part of this book may be reproduced, stored, or transmitted by any means-
whether auditory, graphical, mechanical, or electronic-without written permission of the author. Any
unauthorized reproduction of any part of this book is illegal and is punishable by law.

To the maximum extent permitted by law, the author and publisher disclaim all responsibility and
liability to any person, arising directly or indirectly from any person taking or not taking action based
on the information available in this publication.

Printed in India and published by BUUKS.


Table of Contents

Preface: Why you should read this book

Chapter 1 Tools & Equipment

Chapter 2 Arduino® family

Chapter 3 Arduino® and friends

Chapter 4 Important Terminology for Beginners

Chapter 5 Arduino® anatomy

Chapter 6 Brain of Arduino® UNO

Chapter 7 Input Devices - Sensors

Chapter 8 Output Devices

Chapter 9 Building Circuit on Breadboard

Chapter 10 Getting Started with Programming

Chapter 11 Analog Input

Chapter 12 Analog Output using PWM

Chapter 13 Writing Code for LCD Display

Chapter 14 Completing the Input-Output Loop


PREFACE
Why you should read this book

he age to come would belong to Artificial Intelligence. As technological


T advancements keep on producing computers having higher speed,
memory and power density, complex algorithms could be run, more and
more data could be stored and analyzed. This trend will keep the evolution of
intelligent machines going, and someday these machines would cross our
paths more often in our day-to-day life than they do now. We would see more
intelligent and powerful machines like Siri or Alexa managing our homes,
assisting in our day-to-day work or implementing home automation.
Transport could be using pilotless self-driven vehicles. Some of these could
amaze us now as it would be a significant change for us. Nevertheless, just
like smartphones & internet technology replaced telephones, this would
happen, and we will accept these to become part of our lives. On a positive
note, more jobs or assignments would be created to build and maintain such
gadgets, writing complex algorithms, programs. Therefore why not preparing
ourselves for the future from now?
Arduino® is a popular, low-cost platform, which is an excellent
introduction to the world of electronics and programming for a beginner. As
the Arduino® platform is designed to be user friendly even for a school
student, without prior knowledge of electronics engineering or programming
knowledge, the students in the middle or high school could grasp the
concepts of programming using Arduino® with ease. This book is compiled
for those youngsters in schools (ideally starting from 7th/8th standard) to pick-
up on the programming concepts and basic electronics. Nevertheless, this
book would also help the fresh engineers and beginners of any age who
aspire to be an electronics geek or a techy enthusiast. If you want to make
some cool staffs like automating plant watering system in your garden or
automating your window curtains or want to make little robots for fun but
you are a beginner into the electronics and programming world, you might
want to begin with Arduino®. Then you might find this book helpful. Again,
if you have just started hearing the words such as Arduino®, RASPBERRY
PI, MICRO:BIT and other OPEN SOURCE HARDWARE, but you want to
learn more about them, this book should get you started.
The Arduino® family of boards are introduced in this book with all
necessary technical details for you to make your hardware application and to
write your program to run it successfully. As the title suggests, this book
focuses only on Arduino® family and mostly on Arduino® UNO. There are
other similar or advanced computer boards available, which are also very
popular. Chapter 2 talks about a few other popular boards and provides a
comprehensive comparison between all these variants for my readers to get a
bigger picture.
While reading through the chapters, the readers are encouraged to practice
hands-on by building things with Arduino® or constructing some project
ideas talked about in the later chapters. As the focus of this book is to enable
the readers to make fun staffs and useful gadgets, the practical experience
should accompany their reading experience. For practical work, readers
would need certain tools and equipment. Hence this book starts with Chapter
1, which consolidates a list of tools and equipment you would need at the
minimum to get your Arduino® home lab started.
CHAPTER 1
Tools & Equipment

o start with, we would need a set of hardware equipment and tools. We


T should get the following list of hardware and tools arranged to set up a
small lab or workspace for us to carry out our experiments and to create
our gadgets without any interruptions. A summary of a list of equipment and
tools are given in table 1.

Serial No. Tool/Equipment/Component Comments


1 Desktop or Laptop loaded The Arduino Programming
with Windows 10 and Software (also called
having enough memory for Arduino IDE) is required to
the Arduino software and create your programs
projects. (sketches) and to program
into the hardware board.
2 At a minimum one This board could be bought
Arduino® development online from
board. I have used www.arduino.cc or the
Arduino® UNO and Seeed resellers.
Studio Lotus board for the
project examples described
in this book.1
3 110/230V AC to 9V, 1A Usually, the programming
Power adapter and cable (USB) comes with the
programming cable for the Arduino board. The same
Arduino board. board can power it up.
However, if we would want
to run our board when
disconnected from our PC,
we would need a power
adapter.
4 Breadboard – equal to or A breadboard is needed to
higher than 400 points build our circuit and
integrate it with the Arduino
board without the need for
soldering.
5 22 AWG single core jumper We could buy 3-5 different
wires for breadboard. coloured wires for making
and later changing the
circuit. For example, use
red wire for positive
voltage, black for negative
voltage (or 0V). Use
orange, yellow and white
for digital signals.
6 Wirecutter/stripper. An essential tool for cutting
the breadboard jumper
wires into pieces of required
sizes and to remove the
insulation sleeve.
7 Four to five LEDs I suggested three sets of
(Through-hole type) each colours as there will be
for three or more set of problems in this book which
colours – e.g. Red, Yellow, would need different
Green. coloured LEDs.
8 Sets of five to ten resistors, These resistors are to limit
each having values: the current through the
a) 220 ohm LEDs to get the desired
b) 330 ohm brightness of the light
emitted. Since the resistor is
c) 470 ohm
connected in series with the
LED, more the value of the
resistor less would be the
current through the LED
and hence, less would be
the brightness (or intensity).
We need to choose the
desired value of the resistor
according to the LED we
use. We could get this data
from the datasheet of the
LED.

9 10K trimmer potentiometer Useful to arrange a 10K


potentiometer or several
values of variable resistor
for Analog Input/Output
projects and various other
projects.
10 Grove “Beginner Kit for This comes with a basic set
Arduino” of sensors and LED
modules, LCD for us to get
started. The good part it is
that it contains a Seeed
Studio Lotus board also,
which is an Arduino® UNO
clone. Hence if this kit
collected, a separate
Arduino® UNO board might
not be needed.
11 The multimeter should be This is an expensive tool,
capable of measuring at which is not essential to
least DC voltage, current, have at this moment, but
frequency, resistance, certainly will help in
capacitance. checking our circuit
connections, voltages, LED
polarities while we build
our circuit on a breadboard.
Table 1: List of Equipment, component and tools we would need at the
minimum
The items specified in Table 1 are the basic requirements for one to start
learning with Arduino®. After the items illustrated in Table 1 are arranged
and assuming we have access to the internet, we should be ready to go. All
the best! We could always keep on enhancing our lab by collecting the Input
and Output Devices specified in this book and the corresponding shield
boards once we are a bit confident on this topic. Nevertheless, for now, we
are good to go ahead with this first list of items for our Arduino lab.
I have deliberately avoided soldering kit in the list as I would use the
breadboard for building our circuits in this book and I think starting with
breadboards is much more convenient and safer for the beginner than directly
jumping on to a soldering iron.
Now, let us get on!

1 Check the latest revision in official Arduino® website: www.arduino.cc


CHAPTER 2
Arduino® family

rduino® UNO is one member in the Arduino® family of controller


A boards based on an MCU (Microcontroller Unit) ATmega328P. This
board is open-source type hardware (controlled under creative
commons licensing) and it has several other family members too. Though I
will refer to Arduino® UNO in the examples given in this book, I would
recommend learning about the other members of the family too.
At the entry-level, we have the following active MCU boards offered as
on the date of writing of this book, the overview of which is captured in
Table 2:

Serial Arduino® MCU# Memory Speed


Models (FLASH/RAM)2
1 UNO ATmega328P 32KB/ 2KB 16MHz
2 LEONARDO ATmega32u4 32KB/ 2.5KB 16MHz
3 NANO ATmega328 32KB/ 2KB 16MHz
4 MICRO ATmega32u4 32KB/ 2KB 16MHz
5 UNO Rev3 ATmega328P 32KB/ 2KB 16MHz
SMD
6 NANO ATMega4809 48KB/ 6KB 20MHz
EVERY
Table 2: Entry-level Arduino MCU boards captured in the Chronological
order of Introduction

From Table 2, it can be seen that Arduino® UNO is the first board
introduced in this series. In Italian, “UNO” means “ONE”, indicating the first
one in the Arduino® family. It is based on the 8-bit3 MCU ATmega328P
which has 32KB Flash memory and 2KB SRAM. The MCU ATmega328P
can have a maximum clock speed of 16MHz. These are some necessary
features based on which the other members of the Arduino® family are
compared. As it could be seen, all other Arduino® boards except the
Arduino® NANO EVERY has same sized memory – 32KB FLASH for
storing the program and 2KB SRAM for creating and manipulating variables
during execution. The Arduino® NANO EVERY, which is an enhanced
version of Arduino® NANO, has an 8-bit MCU ATMega4809. This MCU
has 50% higher FLASH memory and three times the SRAM memory
Arduino® UNO and others in the list. Also, we could use the maximum clock
speed of 20MHz, 25% higher compared to others. As the FLASH memory,
which stores the Arduino® sketch or program, is larger in memory size than
peers, the Arduino® NANO EVERY can store and execute a larger program
compared to Arduino® UNO. As the SRAM is bigger and clock speed could
be higher, this MCU could execute the same application program a bit faster.
However, it might be difficult for us to feel this without proper measurement.
Apart from FLASH and SRAM, each of these MCUs has another non-
volatile memory called EEPROM, where long term data (e.g. “board
Identification number” or “board ID”) is stored. We will go through these in
detail again in the later chapters. As a beginner, we could use any of these
boards to start our journey into the digital world. As Arduino® NANO
EVERY is the latest and has a decently powerful MCU among these entry-
level Arduino® offerings, and the price is the lowest, I would recommend
starting with that. Nevertheless, I have chosen Arduino® UNO for this book
as it stands out among the popular kick-starter platforms because of the ease
of use
There are some advanced boards available for more complex and larger
programs. An overview of those boards is given in Table 3.

Serial Arduino® MCU# Memory Speed Comm5


Models (F/R)4
Arduino® boards with Enhanced Features:
1 DUE AT91SAM3X8E 512KB/ 84MHz
96KB
2 ZERO AT91SAM3X8E 256KB/ 48MHz
32KB
3 MKR SAMD21 264KB/ 48MHz
ZERO 32KB
4 MEGA ATmega2560 256KB/ 48MHz
2560 REV3 32KB
Arduino® boards For IoT Applications:
5 MKR1000 ATSAMW25 256KB/ 48MHz WiFi
WiFi 32KB
6 MKR SAMD21 256KB/ 48MHz LoRa
WAN 1300 32KB
7 MKR GSM SAMD21 256KB/ 48MHz GSM/3G
32KB
8 YUN REV ATmega32U4 32KB/ 16MHz WiFi
2 2.5KB
Atheros 400MHz
AR9331 16MB/
64MB
(for LINUX)
+ Micro
SD
9 MKR WiFi SAMD21 256KB/ 48MHz WiFi
1010 32KB
10 MKR NB SAMD21 256KB/ 48MHz NB1
1500 32KB
11 UNO WiFi ATMEGA4809 48KB/ 16MHz WiFi
Rev2 6KB
12 NANO 33 SAMD21 256KB/ 48MHz WiFi,
IOT 32KB BLE/Bluetooth
13 NANO 33 nRF52840 1MB/ 64MHz BLE
BLE 256KB
14 NANO 33 nRF52840 (+ 1MB/ 64MHz BLE
BLE sensors) 256KB
SENSE
15 MKR SAMD21
256KB/ 64MHz LoRa
WAN 1310 32KB (+
2MB
external)
16 PROTENTA STM32H747XI 16MB/ 480MH/ BLE, WiFi
H7 8MB 240MHz
(upto
128MB/
64MB
external)
Table 3: Arduino Boards with Enhanced Features

The first four board in Table 3 are Arduino® MCU boards with enhanced
features. For example, Arduino® DUE is based on an MCU, which has the
highest amount of memory. These models also have a greater number of IO
pins compared to the entry-level Arduino® boards. If we have a larger
application program for which we would need more FLASH memory storage
space or require a large number of IOs, we might want to choose any of
these. Also note that, out of these four boards, Arduino® DUE is the oldest
and Arduino® MEGA 2560 REV3 is the latest. It is generally wise to choose
the latest so that the MCU board will mostly be available for a more extended
period.

2 Flash Memory (Non-Volatile): which is used to store your program. SRAM (Volatile): which is
required during execution of your program. Refer chapter 6.
3 Flash Memory (Non-Volatile): which is used to store your program. SRAM (Volatile): which is
required during execution of your program. Refer chapter 6.
4 F; Flash Memory (Non-Volatile), which is used to store your program. R: SRAM (Volatile), .which
is required during execution of our program. Refer chapter 5.
5 Only wireless communication capabilities are mentioned.
CHAPTER 3
Arduino® and friends

rduino® UNO is one member in the Arduino family of controller


A boards based on an MCU (Microcontroller Unit) ATmega328P. It is
open-source type hardware, and it has other friends too. We should
learn a bit about them so that we know what other options we have to choose
the right one for the right job. There are many, but let us pick the names of
the four most popular computing platforms, similar to the Arduino® boards.
These are listed below:

A) BBC Micro:bit
B) Raspberry Pi
C) ESP8266 (NodeMCU)
D) BeagleBone® Black

Micro:bit is a tiny computing platform launched by BBC for providing


computer education to the school students (starting from 11 years of age).
This board has the size smaller than a credit card. The best part of Micro:bit
is, it is a cute little board with a powerful microcontroller from Nordic
Semiconductor. The little board has a sufficiently large memory, Bluetooth
communication interface and a couple of essential built-in sensors such as an
accelerometer (for measuring the change of speed) and magnetometer (for
measuring direction). Another useful feature of this board is: it has built-in 25
LEDs (surface-mount type) arranged in a 5 x 5 array, which serves the
purpose of a small display.
Apart from the cute, compact hardware, the website6 is quite resourceful.
All necessary knowledge about the hardware and software is nicely presented
together for a beginner to get started. That makes learning easy and faster.
The concepts of programming using graphical code blocks in the MakeCode
Editor tool is a more straightforward coding platform for the new
programmers. The graphical user interface (GUI) of the MakeCode Editor
does not necessitate prior knowledge of a programming language. Advanced
learners can either code using Javascript in MakeCode Editor or could choose
Python editor. The only downside I see is that most of the coding tools for
Micro:bit are accessible online, unlike Arduino IDE, which can be installed
in the PC and can be used offline. Hence we need the internet connectivity to
code for Micro:bit. Another hardship, unlike cheaper and abundantly
available Arduino shields, the shield-boards for Micro:bit are not readily
available. Even if some shields are available, those could be a bit heavy for
our pockets. As Micro:bit has an edge connector, we need to have a shield
with the corresponding mating connector so that we could slide this board
into the shield and could access the IO pins.
Nonetheless, the scope of building things with Micro:bit is enormous to
bring your imaginations out. The major application of Micro:bit could be to
make mobile robots or drones as it has a built-in accelerometer and
magnetometer.
The next one in my list is Raspberry Pi Zero W (called as RPi Zero in
short). RPi Zero W was launched towards the end of February 2017. The
‘Zero’ in the name is a misnomer, as far as the performance is concerned. The
RPi Zero is, by design, a tiny computer and has much more processing power
compared to an Arduino® UNO. Indeed, it is the smallest sized computer in
the Raspberry Pi Family, about half the size of a credit card. The letter ‘W’
indicates that wireless LAN and Bluetooth features are built-in. Using a
wireless keyboard and mouse connected to RPi Zero through its USB
interface and connecting a display to it through its built-in mini-HDMI port,
we can build a low-cost computer. Unlike Arduino®, RPi needs an Operating
Systems such as NOOBS loaded on a microSD card, to boot-up. This boot-up
process is like our PC booting up Windows. However, one needs to have
some prior knowledge of Linux Operating Systems before starting. We could
also make our applications and run the same standalone, just like Arduino®.
However, we need to have some advanced knowledge in Python, the official
programming language of the Raspberry Pi. Therefore RPi Zero W would be
a tougher guy to start our learning curve. We will find many resources, codes
available online to start quickly as RPi series is as popular as Arduino®.
There are many online communities sincerely contributing codes, libraries for
projects based on Raspberry Pi boards, sensors and shields. There are various
Raspberry Pi models available other than RPi Zero W, but those are meant
for more advanced programmers and developers. The new versions keep on
coming all the time. The best will be to go through the official website7 if you
are interested to learn about them.
The next one to mention is NodeMCU. The NodeMCU module is based
on ESP8266 MCU from a company called Expressif. This board came out in
2014 and still very popular as it is another inexpensive option that comes
with WiFi and the sufficient number of IOs, memory and processing power in
a small form factor to build a small but intelligent application. The other
advantages are quite similar to Arduino® – availability of free tools for
coding, easier to learn the programming language, a strong community of
users making online resources of re-usable source codes, tutorials and project
ideas. Note that the same Arduino® IDE tool could be used to develop the
code for NodeMCU and could be used to upload the program to the
NodeMCU module.
The last one in this comprehensive list is the “Beaglebone Black”, which
is a single-board computer, developed by Texas Instruments. This board
might not be as popular as Raspberry Pi or Arduino®. However, this board
was also developed as an educational board to teach hardware & software to
college students. Like the Arduino® and Raspberry Pi boards, there is a
robust online community8 of developers and hobbyists supporting with codes,
ideas and solutions to the questions discussed in the user’s forum. The
software languages supported for Beaglebone are Debian, Ubuntu, Android,
Cloud9 IDE on Node.js with BoneScript library. The hardware is pretty
powerful and open-source. There are a processor and two microcontrollers on
Beaglebone black, and hence it is much more powerful compared to an
Arduino® Uno. Also, it is easier to start with a Beaglebone compared to a
Raspberry Pi. Raspberry Pi Zero W does not have a micro USB cable and
also does not have a pre-installed operating system. Therefore, a microSD
card is needed to load the boot and Operating System image to run the
system.
Whereas, the Beaglebone comes with a mini cable which helps to supply
power to the system. It can boot from the onboard storage. However, the
Beaglebone Black is priced higher compared to the Arduino® UNO or even
some of the Raspberry Pi boards.
In Table 4, brief comparisons are shown between these four platforms
discussed. There are many more such platforms available. Each has certain
advantages over the peers.

Micro:bit Raspberry NodeMCU Beaglebone


Pi Zero W Black
Microprocessor None Yes None Yes
Microcontroller Yes None Yes None
Master Chip nRF51822 BCM2835 ESP8266 AM335x
Part# (Nordic) (ARM®)
(Expressif) (ARM®)
(Broadcom)
(TI)
Non-volatile 256 KB microSD 4 MB 4 GB
Memory Card
(32 GB)
Volatile 16 KB 512 MB 128 KB 512 MB
Memory
Clock Speed 16 MHz 1.0 GHz 80 MHz 1.0 GHz
Communication Bluetooth, Bluetooth, WiFi, Serial USB,
Serial (USB) Serial (USB) Ethernet
(USB),
WiFi
Max GPIOs 19 40 10 66
Built-in Accelerometer, None None None
Sensors Magnetometer
Table 4: A Brief Comparison Between The Popular Single Board Computing
Platforms Similar to Arduino®

6 Refer https://microbit.org/
7 https://www.raspberrypi.org/
8 https://beagleboard.org/black
CHAPTER 4
Important Terminology for Beginners

n this chapter, a glossary of some of the terminology used in the rest of the
I book is given. If you are a beginner into electronics, you could scan
through it if you want. Later part of this chapter introduces the Binary and
Hexadecimal numbering systems as those two knowledge areas are essential
in digital computing, and we should undoubtedly be familiar with those
numbering systems. You could also skip this chapter now and could come
back later to refer some of these terms as you read through the other chapters.

The glossary of essential terms:


AC – Alternating current, which reverses direction periodically with time and
so does the voltage, which is the source for this current. The AC source
powers up the appliances at our home. Different regions in the world have
different AC voltage levels for domestic use.
Actuator – A type of output device of a control circuit, which converts
electrical energy into a mechanical action like motion or movements like
an electrical motor or a valve.
Active High – In digital logic, when the logic is TRUE, the signal is asserted
or driven HIGH. This is called active high logic.
Active Low – In digital logic, when the logic is TRUE, the signal is de-
asserted or driven LOW. This is called active-low logic.
ADC – Analog-to-Digital converter is a circuit that converts the analog
voltage into a digital number of counts. Nowadays, most of the
microcontrollers come with built-in ADCs. Stand-alone ADC chips are
also available for various applications.
Ampere – Unit of current flowing through a circuit or a conductor.
Analog – Continuous signal with an infinite number of possible values.
Anode – Positive terminal of a diode or LED or the positive electrode of the
battery. The positive voltage has to be connected to the anode of a diode or
LED.
Arduino® Shields - Arduino shields are modular circuit boards having
additional component and circuit, compatible with the Arduino® boards,
which can extend the functionality of the Arduino® board.
Baud – This is the short form of bits per second or bit rate, used for serial
communication.
Binary – This is a number system which can have only two values – 0/1 or
LOW/HIGH or OFF/ON or TRUE/FALSE. The binary system is used in
the electronic computation.
Bit – The smallest piece of information a digital signal can have. A bit can
have only two values – ‘0’ or ‘1’.
Boolean – A datatype that indicates binary values.
Bootloader – Bootloader is a program, which starts after the microcontroller
is power-up and comes out of reset. The bootloader program sets the
necessary configurations and then hand over the control to the application
program. The bootloader also helps in uploading a user program by storing
the uploaded program imaged into the destined FLASH memory locations.
Byte – Eight bits of digital information is called one byte.
Capacitance – The capacity to hold an electric charge. Capacitance is a value
of the capacitor, the electrical component, which can store charge.
Cathode – Negative terminal of a diode or LED or the negative electrode of
the battery.
Clock – A repetitive pulse which gets repeated at a fixed time interval. A
microcontroller or a microprocessor must have a clock signal to come
alive.
CPU – Central Processing Unit. CPU is the device or component inside a
microcontroller or processor which fetches data, decodes it and complete
the programmed task successfully.
Current – Rate of flow of electric charge is current and has the unit an
Ampere.
DAC – Digital to Analog Converter is a device or component which just does
the opposite of what an ADC does. It converts a digital value into an
analog signal.
Databus – In a computer subsystem, databus is referred to a set of digital
data lines, that allows transferring digital data from one component to
another component inside a chip or on a board (e.g. processor to memory
chip) or between two computers.
Data packets: A collection of a certain number of data bits containing
meaningful information for the program.
Datasheet – A technical document that describes the specifications of a
component. Typical information in a datasheet includes the maximum
voltage and current a component requires. Also contains an explanation of
the functionality of the pins, information about the package. The datasheet
contains technical information about the components necessary for design
and manufacturing.
Data type: Classification of data stored in a variable for a computer
programming language.
DC – Direct Current does not change with time and flows in the same
direction. The DC voltage is usually constant. For example, the battery
produces constant current or voltage.
Digital – Unlike analog values, the digital system deals with discrete values.
DIP – Dual In Package: A through-hole type of IC package, when the pins
are available on two sides of the IC.
Duty Cycle – For a train of repetitive pulses with a fixed time for repetition
(called time-period), the percentage of one pulse time for which the pulse
is ON is called the duty cycle. So, the duty cycle is (ON Time / (ON Time
+ Off Time)).
EEPROM – Electrically erasable programmable read-only memory.
EEPROM is a type of non-volatile memory, which retains the data
programmed in it.
Embedded Systems – An embedded system is a computer system—a
combination of a processor, memory, and input/output peripheral devices
—that has a specific function.
Firmware – Firmware is a piece of software, which is closely associated for
specific hardware like a particular microcontroller. It is used in embedded
systems, and it is made of machine code instructions.
FLASH Memory – It is an electrically programmable non-volatile memory,
a different type of memory compared to EEPROM. The FLASH memory
is used to store the program image of a microcontroller.
Frequency – The number of times a signal pattern is repeated per second.
Function – An independent block of code that executes a specific task, which
could be called from another function block.
Ground (GND) – The point of a circuit where there is 0 potential electrical
energy. This is the return path for the current. The current flows out from
VCC (3.3V or 5V), through the circuit before it returns to the ground.
Hardware – In electronics, hardware refers to the circuit board assembly.
I2C – Inter-Integrated Circuit - is two wires serial synchronous bus that
provides communication between two Integrated Circuits.
IDE – Integrated Development Environment is a software tool for
developing, programming and fixing codes for the microcontroller or
microprocessor.
Inductor – Like capacitors store energy in the form of electric charge an
inductor stores electromagnetic energy.
IC – A complex circuit of nano or micro scale with a given package used for
a specific purpose.
Load – The device in an electrical circuit which demands and draws current
from a source, such as the appliances in our house.
LSB – Least significant bit. For an 8-bit register, the bits are written starting
with MSB (Leftmost) to LSB (rightmost). For the byte 0xA4, it is written
as “10100100”. Here, LSB = ‘0’.
Memory IC – Digital devices which can store digital information
temporarily or permanently.
MCU – Microcontroller Unit. Refer “Microcontroller” below.
Microcontroller – The microcontroller has a CPU inside it, just like your
computer, but in a miniature form. It also has built-in memory and other
peripheral components to perform specific computation based on some
input and can drive some outputs as programmed. This is the brain of
Arduino®.
Microprocessor – Microprocessor is having more powerful computational
power or a bigger CPU than a microcontroller and can run a much bigger
program than a microcontroller. The Raspberry Pi boards have
Microprocessor as its brain.
MSB – Most Significant Bit. For an 8-bit register, the bits are written starting
with MSB (Leftmost) to LSB (rightmost). For the byte 0xA4, it is written
as “10100100”. Here, MSB = ‘1’.
Ohm – Unit of measurement of resistance.
Optocoupler – This is a device which has a photo-diode (LED) and a
phototransistor built into an IC package. Optocoupler helps in isolating an
electric circuit.
PCB – Printed Circuit Board, which has the circuit connections printed
(using copper tracks) on an insulated board.
Period – The fixed time interval, at which a signal is repeated endlessly.
Photoresistor – A resistive device whose resistance varies according to how
much light falls on it.
Phototransistor – A transistor, which changes state from ON to OFF
depending on light falls on it or not.
Power adapter – A power adapter converts one type of voltage to the other –
e.g. AC to DC.
Power supply rail – A power supply rail is a supply voltage that provides
power for electrical or electronic devices or components on a circuit
board.
Pull-down – A floating signal having neither High (e.g. VCC or 5V) or Low
state (e.g. GND or 0V), when tied to GND by a resistor or a transistor, is
called to be pulled down.
Pull-up – A floating signal having neither High (e.g. VCC or 5V) or Low
state (e.g. GND or 0V), when tied to High or VCC by a resistor or a
transistor, is called to be pulled-up.
PWM – A repetitive pulse train, the width of which can be controlled
keeping the period constant is called pulse width modulation or PWM in
short.
Reset – Reset means to start over. For a microcontroller, a reset signal
restarts its program execution from the very beginning.
Resistor – The electrical element which resists the flow of current is called a
resistor. As per Ohm’s law V = I x R; V is voltage, I is current and R is the
resistance.
Register – A memory unit which stores a series of bits. The size of register is
usually multiple of 8 (one byte).
Serial Communication – When digital information in bits is sent or received
serially over a communication signal.
Semiconductor - A solid substance, the conductivity, which falls between
that of most metals and the same for insulators, either due to the addition
of an impurity or because of temperature effects. The semiconductor
elements such as Silicon, Germanium are used to manufacture electronics
devices.
Sensor – The sensors are the devices which measure the physical parameters
and convert those into the electrical signal such that the microcontrollers
could read.
SPI – Serial Peripheral Interface – a serial digital communication.
Soldering – A process of connecting an electronic component to the PCB.
Synchronous – When two or more digital signals occur at the same time or
based on the same clock signal.
Transistor – A semiconductor device which is the building block of all
semiconductor devices and complex ICs.
Tri-state – In digital logic also there could be three states (hence the name
Tri-state) – High, Low or neither high nor low (signal floats – not pulled
up or down). This type of logic is called tri-state logic.
UART – Universal Asynchronous Receiver Transmitter is a serial
communication protocol.
USB – Stands for Universal Serial Bus. It is a generic port that is standard on
most computers today. With a USB cable, it is possible to program and
power an Arduino over a USB connection.
VCC – This label marks the pin used to supply the positive voltage to a
circuit, a device or a PCB assembly (circuit board). The other pin, for
ground, is usually labelled VSS or GND.
Variable – A datatype that stores values which are likely to change as our
program runs.

Introduction to Binary and Hexadecimal Numbering systems:


As I am sure you are aware that the numbering system that we use for our
day to day computation is called the “decimal system”. In the decimal
system, the base is 10. For instance, 23 can be expressed as: 2x101 + 3x100.
Similarly, 356 can be represented as 3x102 + 5x101 + 6x100. Thus, the
position ‘n’ of a number in the decimal system is represented by the nth
power of 10.
For the binary system, there are only two numbers 0 and 1. The base here
is 2. So, the binary number 10 can be expressed as:

1x21 + 0x20 = 2 (decimal)


Similarly, 1010 could be expressed as:
1x23 + 0x22 + 1x21 + 0x20 = 8 + 2 = 10 (decimal)
The binary number 1111 could be expressed as:
1x23 + 1x22 + 1x21 + 1x20 = 8 + 4 + 2 + 1 = 15 (decimal)

The major reason behind using the binary numbering system in digital
computing, because the digital signals can have only two levels – HIGH (e.g.
5V) or LOW (e.g. 0V). Thus, the binary numbers 0 and 1 are used to
represent these two levels. If we want to represent only two signal levels, we
could do so using one digital signal. Now, if we want to represent more than
two signal levels, we would need greater than one number of digital signals
for that. For example, if we want to represent as a signal having ten values or
discrete states, we need four signals and can represent 0 to 9 (10 states) as
shown in Table 5.

Decimal Binary
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
Table 5: Binary Numbers Representing 0 to 9

The number of binary digits required to represent a decimal number will


be equal to the number of digital signals needed. We could determine this
quickly by calculating the power of base 2, which will represent the highest
decimal number in the range. In the above example, you know 23 = 8 < 9 and
24 = 16 > 10. Therefore, numbers ranging 0 – 9 could be expressed by four
binary digits. In digital electronics, each of these digits is called ‘bit’. Hence,
in digital electronics term, we would need 4-bits to represent discrete states 0
to 9.
Now, let us take a larger number. Say, if we want to represent any number
between 0 to 1023 (1024 numbers of states), then how many binary digits or
bits we would need. If we calculate by the power of two methods: 210 = 1024.
Thus, we will require 10 bits or ten digital signals to represent 1024 states. In
digital electronics 1024 is called 1 Kilobit or 1 Kb in short. Similarly, 1
Megabit or 1 Mb will correspond to 1024 x 1024 = 1048576. As 220 =
1048576, we would need 20 bits or 20 digital signals to derive 1048576
numbers of states. As we could see, the decimal number 1048575 can be
expressed as “1111 1111 1111 1111 1111” in binary – 20 number of 1’s.
Though it is easier to use binary numbering systems to describe digital
logic states and convenient to use the binary system in digital computing, it is
usually difficult to express a decimal number by a binary number. The
difficulty arises as it involves a large number of digits. For example, we
could see that we need 20 binary digits to represent 1048575 or even four
binary digits to represent a small number like 10 or 15. The introduction of
the hexadecimal number system into digital electronics was aimed to solve
this problem.
The base for the hexadecimal system is 16. Hence the two-digit numbers
after 9, such as 10, 11, 12, 13, 14 and 15 are represented by A, B, C, D, E and
F respectively.

Decimal Binary Hexadecimal


0 0000 0
1 0001 1
2 0010 2
3 0011 3
4 0100 4
5 0101 5
6 0110 6
7 0111 7
8 1000 8
9 1001 9
10 1010 A
11 1011 B
12 1100 C
13 1101 D
14 1110 E
15 1111 F
16 10000 10
17 10001 11
18 10010 12
Table 6: Hexadecimal Numbers

As shown in Table 6, up to decimal 15, or binary “1111”, we could use


one hex (short form of hexadecimal) digit. After that, we need two hex digits
till “1111 1111” (decimal 31). The hex number for binary “1111 1111” is
“FF”. Note that hex numbers are denoted with a “0x” as the prefix in some of
the software languages such as C and C++. Thus:

“1010 1010” = 0xAA


“0011 1101” = 0x3D
“10 1100 1000” = 0x2C8
“1111 1010 1001” = 0xFA9
“1111 1111 1111” = 0xFFF
“1111 1111 1111 1111 1111” = 0xFFFFF

From the above examples, we could make the following observations:

1. Every four bits starting from LSB could be represented by one hex
digit. This four-bit aggregation is also called a “Nibble”.
2. Two hex digits could represent every eight bits starting from the LSB.
This is called one “Byte”.
3. Since, the registers in digital systems can contain 8, 16, 32 or 64 bits of
information (power of 2); it is straightforward to represent such binary
values by shorter hex digits. Thus it is easier to write codes using hex
numbers. Also, the hex number system is undeniably more convenient
compared to the decimal system in converting to binary and back.

These are the reasons why the hex number system is widely used in digital
computing and programming.
This was a quick introduction to the binary and hexadecimal system. If
you are new to this, to sharpen your newfound skill, you have to practice it
some more so that you could do binary to hex conversion or vice-versa
mentally. Going forward, we will see that the addresses of memory locations
or the register values or the variables used in the sketches are expressed in
hex numbers. It will be a bit easier for you to pick those concepts if you are
familiar to the hex system.
CHAPTER 5
Arduino® anatomy

efore we start building projects using Arduino® UNO, we need to learn


B a bit about the hardware. Studying electronics engineering or similar
professional course is not an essential requirement to gain a high-level
understanding of the Arduino® UNO and its components. Therefore the
beginners need not worry.
Figure 1 shows the major components and circuit-blocks on an Arduino®
UNO board.

Figure 1: Major components & circuit blocks of Arduino Uno


Like any other electronic gadget, the Arduino® UNO board needs a
voltage source and requires current to turn on and to run its program. The
Arduino® UNO board has two ways of receiving power. There is a power
jack which accepts DC voltage of 7V to 12V DC, could be supplied from an
AC to 9V DC 1A rated power adapter or a 9V battery. Ensure that the applied
voltage does not cross beyond 12V. Even though the minimum and
maximum working limits specified for Arduino® UNO is 6V to 20V, beyond
12V, the voltage converter circuit on the board might overheat and eventually
could get damaged over a while. The voltage converter circuit converts the
input voltage to the circuit’s working voltages 5V and 3.3V. The voltage
converter circuit regulates these voltages, which means that the regulator
keeps the working voltage levels of 5V and 3.3V rails stable, even when the
input voltage might vary between the range of 6V to 20V.
A second way to power-up an Arduino® UNO board is through the USB
port. The same port is also used for uploading the program image from a
computer running the Arduino® IDE software. The USB port on Arduino®
UNO is compatible with a USB 2.0 cable type A/B. The USB port has four
signal pins – two signals for 5V DC power supply rails and the other two for
the data signal line D+/D-. The voltage supplied by the USB port of a
computer is around 5V and this can power-up the Arduino® board without
the 9V supply connected to the 7V-12V Power Jack. If we want to develop
our code for the Arduino® and download it to the UNO board, we need to
connect the USB cable between the Arduino® UNO board and the computer.
The small IC next to the USB connector is an 8-bit microcontroller which
acts as a USB controller. On the Arduino® UNO R3 (“R3” denotes the
revision) board this part is an ATmega32U2 microcontroller. This IC
functions as a bridge between the computer’s USB port driver and the UART
of Arduino® UNO’s main microcontroller ATmega328P. When the Arduino®
IDE software communicates with the main microcontroller on Arduino®
UNO, the ATmega32U2 device translates data packets sent and received over
USB into a format understood by the “bootloader”9 program pre-programmed
into the FLASH memory of the main controller.
The “Power LED” shown in Figure 1 is a green LED, which turns on
when the Arduino® UNO board receives the correct voltage. If this LED does
not turn on GREEN, then we might need to check if the power supply and the
connection are correct.
There are three more LEDs on Arduino® UNO. Two of those are marked
as “TX” and “RX” and the third one is marked as “L”. The “TX” and “RX”
LEDs are driven by the ATmega32U2 microcontroller when there is a serial
communication from a PC. The other LED marked as “L” is connected to the
Arduino® UNO’s pin D13.
The push-button for “Resetting” the microcontroller is located next to the
USB connector on one corner of the Arduino® UNO R3 board. The “Reset”
push-button on Arduino® UNO R3 board is connected between the RESET
pin of the main microcontroller ATmega328P and 0V (Ground). When this
button is not pressed, the RESET signal is pulled-up HIGH to +5V by a pull-
up resistor. Therefore the default level of the RESET signal is HIGH. When
the Reset Button is pressed, the RESET signal is shorted to 0V through the
button and is pulled LOW (a voltage close to 0V). After the button is pressed
briefly and then released, this action triggers the microcontroller to restart the
program execution from the very beginning
There are two rows of Input / Output (IO) port headers for connecting
other components, making circuit connections or connecting the Arduino®
compatible shield boards to the UNO board. One of these headers has
connections for the digital IOs. The other header has the connections for the
analog input pins, reset signal, the reference voltage for the ADC and voltage
pins. Most of the IOs could perform several alternative functions other than
their default configuration and can be programmed to do so. The detailed pin
description for these two headers is given in the following sections.
Figure 2: Arduino® UNO R3 Pinout Diagram of the POWER & ANALOG IN header (source:
www.arduino.cc)

POWER/RESET Header: Figure 2 shows the Analog Input port, Power


and Reset port connections. Table 7 below describes the Power and Reset
header pins. Note that, the pins marked with “PC” followed by a number as
shown in Figure 2, are the IO port pins of ATmega328P on Arduino® UNO.

Pin Intended Alternative Description


Marking Function Functions
NC No NIL This pin is not connected
Connection anywhere on the Arduino®
UNO board.
IOREF Voltage NIL Serves as IO Reference
reference (5V voltage for some shields
for Arduino® that use this as an input to
UNO) match with the same
operating voltage of the
microcontroller
RESET RESET Input Interrupt IN An external reset input that
PCINT[14] resets the microcontroller if
driven low (to GND). This
signal is connected to Port
C, pin 6 (PC6). This pin
also could be configured as
an interrupt pin.
3.3V 3.3V output NIL Regulated 3.3V source for
an external circuit
5V 5V output NIL Regulated 5V source for an
external circuit
GND Return for NIL 0V reference for 5V, 3.3V
3.3V, 5V
VIN Voltage Input NIL Power input connection for
from an the Arduino® UNO brought
external out on the header. Some
source Shields might use this pin to
power up the Arduino
UNO. If Arduino UNO is
powered using VIN pin,
external power would be
redundant.
Table 7: Power, RESET Header Pin Description

Analog IN Header: Table 8 describes the Analog Input header pins. As


shown in Figure 2, the default configuration of the PC0-PC5 pins is Analog
Input channels ADC[0]-ADC[5] for the internal ADC of ATmega328P.

Pin Default Alternative Description


Marking Function Functions
A0 Analog Input Digital IO Default functionality of this
(ADC Channel D14, pin is Analog Input
0) connection to the internal
Pin Change ADC’s channel 0.
Interrupt 8 Alternatively, this pin could
PCINT[8] be configured as a digital IO
or a pin change interrupt
input. This signal is
connected to pin 0 of Port C
(PC0) of ATmega328P.
A1 Analog Input Digital IO Default functionality of this
(ADC Channel D15, pin is Analog Input
1) connection to the ADC
Pin Change channel 1. Alternatively,
Interrupt 9 this pin could be configured
PCINT[9] as digital IO or a pin change
interrupt input. This signal
is connected to pin 1 of Port
C (PC1) of ATmega328P.
A2 Analog Input Digital IO Default functionality of this
(ADC Channel D16, pin is Analog Input
2) connection to the ADC
Pin Change channel 2. Alternatively,
Interrupt 10 this pin could be configured
PCINT[10] as digital IO or a pin change
interrupt input. This signal
is connected to pin 2 of Port
C (PC2) of ATmega328P.
A3 Analog Input Digital IO Default functionality of this
(ADC Channel D17, pin is Analog Input,
3) connection to the ADC
Pin Change channel 3. Alternatively,
Interrupt 11 this pin could be configured
PCINT[11] as digital IO or a pin change
interrupt input. This signal
is connected to pin 3 of Port
C (PC3) of ATmega328P.
A4 Analog Input Digital IO Default functionality of this
(ADC Channel D18, pin is Analog Input,
4) connection to the ADC
Pin Change channel 4. Alternatively,
Interrupt 12 this pin could be configured
PCINT[12], as digital IO or a pin change
interrupt input. This pin also
I2C Data SDA could be configured as the
data line for I2C
communication. This signal
is connected to pin 4 of Port
C (PC4) of ATmega328P.

A5 Analog Input Digital IO Default functionality of this


(ADC Channel D19, pin is Analog Input,
5) connection to the ADC
Pin Change channel 5. Alternatively,
Interrupt 13 this pin could be configured
PCINT[13], as digital IO or a pin change
I2C Clock interrupt input. This pin also
SCL could be configured as the
clock line for I2C
communication. This signal
is connected to pin 5 of Port
C (PC5) of ATmega328P.
Table 8: Analog IN Header Pin Description

On the other side of the Arduino® UNO board, the Digital IO header
provides connections for the UART, SPI, I2C and Digital IO functionalities
as shown in Figure 3. The default and alternative functions are described in
Table 9.
Figure 3: Digital IO Header pin description

Pin Default Alternative Description


Marking Function Functions
D0/RX USART RX Digital IO D0, By default, this pin is the
receive (RX) signal for the
Pin Change serial communication
Interrupt 16 between the USB controller
PCINT[16] chip and ATmega328P.
Alternatively, this pin could
be configured as a digital IO
or a pin change interrupt
input. This signal is
connected to pin 0 of Port D
(PD0) of ATmega328P.
D1/TX USART TX Digital IO D1, By default, this pin is the
transmit (TX) signal for the
Pin Change serial communication
Interrupt 17 between the USB controller
PCINT[17] chip and ATmega328P.
Alternatively, this pin could
be configured as a digital IO
or a pin change interrupt
input. This signal is
connected to pin 1 of Port D
(PD1) of ATmega328P.
D2 Digital IO D2 Pin Change This pin could be
Interrupt 18 configured as a digital IO or
PCINT[18], a pin change interrupt input.
Alternatively, this pin could
External be used as an external
Interrupt 0 interrupt (0). This signal is
INT[0] connected to pin 2 of Port D
(PD2) of ATmega328P.
∼D3 Digital IO D3 Pin Change This pin could be
Interrupt 19 configured as digital IO or a
PCINT[19], pin change interrupt input
or an external interrupt (1)
External This pin could also be
Interrupt 1 configured as the Timer /
INT[1], Counter 2 output compare
Timer/Counter2 match & PWM output. This
output signal is connected to pin 3
compare of Port D (PD3) of
match OC2B ATmega328P.
or PWM
D4 Digital IO D4 Pin Change This pin could be
Interrupt 20 configured as a digital IO or
PCINT[20], a pin change interrupt input.
Timer/Counter Alternatively, this pin could
0 external be used to receive the
counter input external clock input for the
T0, USART or Timer/Counter 0
input. This signal is
USART connected to pin 4 of Port D
external clock (PD4) of ATmega328P.
input XCK
∼D5 Digital IO D5 Pin Change This pin could be
Interrupt 21 configured as a digital IO or
PCINT[21], a pin change interrupt input.
This pin could also be
Timer/Counter configured as the
1 external Timer/Counter0 output
counter input compare match or PWM
T1, output. This pin could also
Timer/Counter0 be configured as
output Timer/Counter 1 input. This
compare signal is connected to pin 5
match OC0B of Port D (PD5) of
or PWM ATmega328P.
∼D6 Digital IO D6 Pin Change This pin could be
Interrupt 22 configured as a digital IO or
PCINT[22], a pin change interrupt input.
Alternatively, this could be
analog configured as the Timer /
comparator Counter2 output compare or
positive input PWM output. The pin could
AIN[0], also be configured as an
Timer/Counter2 analog comparator positive
output input. This signal is
compare connected to pin 6 of Port D
match OC0A (PD6) of ATmega328P.
or PWM
D7 Digital IO D7 Pin Change This pin could be
Interrupt 23 configured as a digital IO or
PCINT[23], a pin change interrupt input.
The pin could also be
analog configured as an analog
comparator comparator negative input.
negative input This signal is connected to
AIN[1] pin 7 of Port D (PD7) of
ATmega328P.

D8 Digital IO D8 Pin Change This pin could be


Interrupt 0 configured as a digital IO.
PCINT[0], Alternatively, this pin could
be configured as a pin
Input capture change interrupt input or
pin for input capture pin to capture
Timer/Counter1, time stamp for
Divided Timer/Counter1 (ICP1).
system clock This pin could also be used
output as a clock frequency divider
output. This pin is
connected to pin 0 of Port B
(PB0) of ATmega328P.
∼D9 Digital IO D2 Pin Change This pin could be
or PWM Interrupt 1 configured as a digital IO or
PCINT[1], a pin change interrupt input.
Alternatively, this pin could
Timer/Counter1 be configured as a
output Timer/Counter1 output
compare compare match & PWM
match OC1A output. This signal is
connected to pin 1 of Port B
(PB1) of ATmega328P.
∼D10 SPI slave Pin Change The default function of this
select (SS) Interrupt 2 pin is “slave select” for SPI
PCINT[2], interface. Alternatively, this
pin could be configured as a
Digital IO digital IO or a pin change
D10, interrupt input. This pin
Timer/Counter1 could also be configured as
output Timer/Counter1 output
compare compare match or PWM
match output. This signal is
OC1B/PWM connected to pin 2 of Port B
(PB2) of ATmega328P.
∼D11 SPI Master Pin Change The default function of this
Out Slave In Interrupt 3 pin is “Master Out Slave In”
(MOSI) PCINT[3], data signal (MOSI) for the
SPI interface. Alternatively,
Digital IO this pin could be configured
D11, as digital IO or a pin change
Timer/Counter2 interrupt input or as
output Timer/Counter2 output
compare compare match or PWM
match output. This signal is
OC2B/PWM connected to pin 3 of Port B
(PB3) of ATmega328P.
D12 SPI Master In Pin Change The default function of this
Slave Out Interrupt 4 pin is “Master In Slave Out”
(MISO) PCINT[4], data signal (MISO) for the
SPI interface. Alternatively,
Digital IO this pin could be configured
D12 as digital IO or a pin change
interrupt. This signal is
connected to pin 4 of Port B
(PB4) of ATmega328P.
D13 SPI clock Pin Change The default function of this
signal (SCK) Interrupt 5 pin is the clock signal
PCINT[5], (SCK) for the SPI interface.
Alternatively, this pin could
Digital IO be configured as digital IO
D13 or a pin change interrupt.
This signal is connected to
pin 5 of Port B (PB5) of
ATmega328P.
GND Return for NIL Reference for 5V, 3.3V
3.3V, 5V (0V)

AREF External NIL Apart from the 1.1V


voltage internal voltage reference
reference input (VREF) for the ADC, this
for the ADC pin provides an option to
connect external reference
for the ADC.
D18/SDA I2C Data Digital IO 18, The default configuration
for this pin is I2C data IO
Analog Input signal. Alternatively, the
(ADC same is brought out on the
Channel 4), Analog IO header for ADC
Pin Change channel 4. It could also be
Interrupt 12 used as a pin change
PCINT[12] interrupt pin or a digital IO
pin.
D19/SCL I2C Clock Digital IO 19, The default configuration
for this pin is an I2C clock
Analog Input signal. Alternatively, the
(ADC same is brought out on the
Channel 5), Analog IO header for ADC
Pin Change channel 5. It could also be
Interrupt 13 used as a pin change
PCINT[13] interrupt pin or a digital IO
pin.
Table 9: Digital IO Header

The main component on an Arduino® UNO board is its brain – the


microcontroller ATmega328P. A microcontroller needs three ‘P’s at the
minimum for its operation:

A. Power: Proper voltage and recommended current for its operation.


B. Program: A valid program in the recommended memory locations
C. A Periodic Pulse Train (Clock): Proper clock source

The microcontroller ATmega328P needs DC voltage between the


recommended range of 2.7V to 5.5V for operating correctly. On an Arduino®
UNO nominal 5V is provided to power-up ATmega308P. This
microcontroller has an internal non-volatile FLASH memory of 32K bytes,
which stores the boot-loader program and user’s program. The boot-loader
program is pre-programmed into the fixed locations (takes ∼0.5K bytes) of
the 32K bytes FLASH memory. The boot-loader program acts as the “guide”
for the application program to reach the destined memory locations and get
programmed during an upload. However, we do not have to worry much as
long as we are using the Arduino® IDE software for uploading our program
over the USB interface. In the following chapter, we will learn about the
functionalities built into the microcontroller ATmega328P. As an overview,
ATmega328P is an 8-bit microcontroller as it could process 8-bit of
instruction or data at a time. It has 23 programmable IO pins. The IO pins are
connected to the IO headers on the Arduino® UNO board described in Table
8 and Table 9.
A microcontroller always needs a clock signal to run through its program.
A clock signal is a periodic train of pulses, repeated indefinitely. It is like the
pulse rate or the heartbeat that maintains the required blood flow in the blood
vessels of our body, that keeps us alive. The time between two consecutive
pulses is called the Time-period (T) or one “clock tick”. The frequency (f) of
a pulse train is the number of “ticks” occurring in one second. The
relationship between the frequency and time-period can be expressed as f =
(1/T). If the “clock tick” is 1 second, i.e. T = 1sec, frequency (f) of the clock
is expressed as 1 Hertz or Hz in short. The clock signal to ATmega328P on
the Arduino® UNO has a frequency of 16 MegaHertz, i.e. f = 16 MHz. Thus
for the frequency of 16 MHz, the number of “clock ticks” in a second is
16,000,000. Isn’t that pretty fast? Now, could you compute the Time-period
of the clock pulse?10 For each “clock tick,” the microcontroller executes an
instruction or part of it. You could guess that more clock speed would give
you faster execution time of your program.

Figure 4: Clock Signal – Periodic Pulse Train

On Arduino® UNO, the clock signal for ATmega328P is supplied using a


ceramic resonator pulse.
In case we use an Arduino® board other than the Arduino® UNO, we
would need to gain awareness about the following essential information from
the official Arduino® website:

The voltage and current the board will need


The port pin functionality definitions
The major parts on the board
The main microcontroller’s feature details on a high level

For instance, you might buy other variants of Arduino® UNO boards such as
the Arduino® UNO SMD version as shown in the picture Figure 5 below.
This board have everything same as the Arduino® UNO R3 board except the
package of the ATmega328 microcontroller IC. You could also buy an
Arduino® Leonardo board, which is a bit different than Arduino® UNO. The
Leonardo board has a single microcontroller ATmega32U2, which does both
the functions of a USB controller and all the functions of the main
microcontroller as the ATmega328P does on Arduino® UNO. Note that the
Leonardo board also have a different USB connector than the one Arduino®
UNO board has. You would need a micro USB cable (similar to the USB
cable for phone charger) to connect and program.

Figure 5: Arduino® UNO Alternative - Arduino® UNO SMD R3 and Arduino® Leonardo R3 Boards
9 The bootloader is a program (stored in a pre-determined location of the non-volatile FLASH
memory), which accepts the application program image sent to the microcontroller over the
communication interface and stores the received program image in the destined memory locations.
10 T = (1/16000000) second = 0.0625 micro second (us) or 62.5 nano second (ns)
CHAPTER 6
Brain of Arduino® UNO

n this chapter, we will explore deeper into the microcontroller


I ATmega328P, which is the brain of Arduino® UNO. Our brains process
external stimuli and thoughts, analyze signals captured by our sensory
organs and decide on appropriate actions. Likewise, a microcontroller also
processes instructions programmed into its memory, processes input signals.
According to the programmed instructions, it performs appropriate actions
such as driving relays or motors, communicating pre-determined information
to the connected devices.

Figure 6: Microcontroller – The Brain Of Arduino® and Its Scanning Process

Figure 6 depicts how the microcontroller of a single-board computer such


as Arduino® UNO reads input devices connected to its port pins, executes
programmed logic and accordingly drives output devices. This loop is
executed repeatedly until the microcontroller runs the program. In this
chapter, we will learn about the microcontroller ATmega328P.

CPU, memory & control units


Just like our computer, the microcontroller has a CPU inside it but in a
miniature form. There is a fixed set of instructions for every CPU. The
ATmega328P CPU has 8-bit RISC (Reduced Instruction Set Computer)
architecture, which can execute the majority of the instructions in one single
clock cycle (in a single clock “tick”), enabling faster execution. RISC is a
type of computer that has a relatively limited number of instructions.
The non-volatile FLASH memory, which contains the boot-loader and
user program, is directly connected to this CPU. The size of the FLASH
memory of the ATmega328P is 32K bytes. As one byte contains 8-bits of
data, one Kilobyte (1K byte) contains 1024 bytes, 32K bytes FLASH
memory could store 32 x 1024 x 8 bits of information. Since the FLASH
memory is connected to the CPU directly with a 16-bit interface, the
calculation will look like 16 x 1024 x 16 bits, which indicates that there are
16 x 1024 locations (=16,384 locations) in the memory. Converting (16,384 –
1) to hex, we get 0x3FFF. Thus, the FLASH memory has the hexadecimal
address locations ranging from 0x0000 to the location 0x3FFF. Out of this,
0.5 K bytes of the FLASH is occupied by the boot-loader program. Hence the
remaining 15.5 x 1024 x 16 bits = 258,048 bits are available to the user to
store the application program. The FLASH memory and the division between
the boot and the application programs could be visualized like it is shown in
Figure 8. When the user uploads the application program to the Arduino®
UNO, the program is stored in the “Application Program” area of the FLASH
memory. The Flash memory can be re-programmed a finite number of times
and can tolerate around 100,000 program cycles. However, this is not any
less. For instance, even if we upload ten programs a day, we could continue
to do so every day for the next 27 years before the FLASH might wear out.
That is quite a lot of programming.
Like the FLASH memory, the volatile memory SRAM is also directly
connected to the CPU, as shown in Figure 8. Unlike the non-volatile FLASH
memory, SRAM cannot retain its content when the input power is turned off.
That is why SRAM is not used to store boot or application programs as the
same will be lost after power is turned off. The SRAM is designed for the
program to create and manipulate variables when it runs. Hence, SRAM is
referred to as the data memory or the user data space. To draw an analogy,
this is like the rough sheet we use to scribble necessary calculations before
putting down the answer on the fair copy.

Figure 7: FLASH Memory Organization In ATmega328P

Another type of memory is called “Stack”. The “Stack” memory


consumes contiguous locations in SRAM. When interrupts and subroutine
calls are executed, the return address is stored on the stack. The stack grows
from higher to lower memory locations. Stack size is limited by the total
SRAM size and the usage of the SRAM. The size of the SRAM on
ATmega328 is only 2K bytes or 2 x 1024 x 8 bits = 16,384 bits. Hence we
could have space for 2,048 variables, assuming each variable has a size of 8-
bits. It is vital to know this as our program could grow in size; we might run
out of SRAM space. When that happens, our program could fail to run
unexpectedly.
The other type of memory available in ATmega328P is EEPROM.
EEPROM is a non-volatile memory that can be read or written from the
program running in the microcontroller of the Arduino® UNO. It can only be
read byte-by-byte as the EEPROM is connected to the CPU through the same
8-bit data bus on which the other peripherals are also connected. So, it can be
a little slower to use. It has a finite lifetime of about 100,000 program cycles.
Hence the EEPROM can be written ten times more than the FLASH memory.
We can read it as many times as we want. In EEPROM we could choose to
store some constants which our program would use during execution. For
example, an ID of our device or application we are making using the
Arduino®. The ID of a board would need to be programmed once but would
be read each time the device is powered-up.

Figure 8: Memory Organization Inside ATmega328P

Figure 8 shows how these memories are organized and connected to the
CPU block inside the microcontroller ATmega328P.
Other than these three types of memories, we need to know about some
registers, which are part of the user data space like SRAM but not physically
implemented as SRAM.

A. General Purpose Registers: There are thirty-two bytes of general-


purpose working registers, each of which is 8-bit wide, labelled as R0
to R31, which are mapped to addresses 0x0000 through 0x001F in the
user data space.
B. IO Register Space: Sixty-four bytes (8-bit wide) of data memory space
is for CPU peripheral functions (via control registers), SPI, and other
IO functions. The IO registers are mapped to address 0x0020 through
0x005F in the user data space. There are two crucial registers worth
mentioning here.
i. Stack-pointer: We have discussed “stack” before. The stack pointer
register holds the address (points to) of the top of the stack. It is a
16-bit register in the I/O space. This register is composed of two 8-
bit registers, SPL (Stack Pointer Low) and SPH (Stack Pointer
High). At the beginning of the program execution, after reset, the
stack pointer must be initialized to the address 0x08FF, which is the
last location or the bottom of the stack memory in SRAM. In that
case, the register SPL will hold the value 0xFF and SPH will hold
0x08. If the top of the stack becomes 0x0789 any point of time
during the program execution, then SPL will have 0x89 and SPH
will have 0x07.
ii. Status Register: A single byte in the IO register space that contains
information about the result of the most recently executed
arithmetic instruction. The status information can be used for
performing conditional operations in the program. The status
register is mapped to the address 0x005F.
C. Extended IO Space: The address space from 0x0060 to 0x00FF (160 x
8-bit registers) belongs to the extended IO space registers. Some
instructions need this space for their execution.

Figure 9: Data Memory Space – Registers, SRAM, STACK

The thirty-two bytes of general-purpose registers connected directly to the


ALU – Arithmetic Logic Unit. ALU is an integral part of the CPU as it
performs the following three primary operations on these registers during
program execution:

1. Arithmetic operations such as addition, subtraction, multiplication.


2. A logical operation such as logical AND, logical OR and so on.
3. Bit-wise operation: logical shift left, logical shift-right, set or clear bit
in IO register and likewise.

Apart from these three main instructions, there are more such as Jump and
Call, Branch and Skip, Move, Load, Store instructions. The complete
knowledge of the entire instruction set is required for advanced programmers.
Hence this topic is intentionally kept out of the scope for this book.
There are a few more control units of the CPU that we should be aware
of. First one is a Program Counter (PC). The Program Counter (PC) of
ATmega328P is a 14-bit register. It holds the address of the next instruction
in the Program Memory (FLASH memory). The second one is an Instruction
Register (IR) which holds the current program instruction. These are the two
crucial registers we should be aware of, though we are not going to
manipulate these registers directly in our programs.
Apart from these two registers, there is another control unit in the CPU,
which decodes the instructions and generates the control signals for various
sections, peripherals of the microcontroller. This control unit is called
“Instruction Decoder”.

IO and Peripheral
Other than CPU, memory and control units, which are like core of the brain
of the microcontroller, there are IO and other special function control units,
through which, the microcontroller receives inputs and drives the desired
outputs and thus interact with its outside world.

Digital IO:
The microcontroller ATmega328P has two 8-bit IO ports, namely Port B,
Port D and a 7-bit Port C. As mentioned in Table 7, Table 8 and Table 9,
these port pins are brought out to the IO headers on the Arduino® UNO
board. We need to remember that the pin 6 of Port C (PC6) is used as the
RESET signal and the pin 6 (PB6) and pin 7 (PB7) of Port B are used for
connecting the clock signals from the clock source (which is a ceramic
resonator) on Arduino® UNO. All other port pins are used for analog inputs
or digital IO, which could also be configured to perform the alternative
functions mentioned in Table 8 and Table 9. Each port has three 8-bit control
registers inside the microcontroller, namely, DDRx, PINx and PORTx (x Є
B, C, D).

Name of Description of Function


Register Register
DDRx Direction Each pin defines whether a pin is an
Register input (0) or and output (1). Every bit
(denoted 0 to 7) of this register for the
corresponding port, is both readable and
writable (R/W) individually or together,
except Bit 7 of DDRC (Direction
Register of Port C) as Port C has only 7
IO pins (denoted 0 to 6). PC7 is not
used and can only be read.
The default value of these bits after
power-up and reset deserted is ‘0’.
Hence all port pins are configured as
“Input” as default.
PINx Pin Input Value Reading from this register returns the
digital signal value of the corresponding
port. For example, in your application
program if you read a value
“00100110” (0x26) from PIND register,
that means Port D pins have the
following signal levels:
PD0 = ‘0’; PD1 = ‘1’, PD2 = ‘1’; PD3
= ‘0’; PD4 = ‘0’; PD5 = ‘1’; PD6 = ‘0’;
PD7 = ‘0’
PINx bits only could be read, but
cannot be written by the program.
PORTx Pin Output Writing to this register sets the
Value corresponding value of the pins, i.e.
drives the signal on the respective pins.
Each of the bits of the registers PORTx
could be read or written individually or
together. The default value of these bits
after power-up and reset deserted is ‘0’.
Another use of the PORTx register:
If any bit of the DDRx is set as ‘0,’ i.e.
input, setting the corresponding bit ‘1’
in the PORTx register will connect a
pull-up register on that pin. Again, if
that bit of the PORTx is ‘0’, the pull-up
will be off, and the pin will float.
Table 10: Port Configuration Registers

The IO port configuration registers need to be configured input to output


or vice-versa through a sequence, which is depicted in Figure 10.

Figure 10: States of the Port Register Bit while Setting The Port Pin Input to Output or vice-versa

Interrupts:
Arduino® UNO has two external interrupt pins connected to its Digital IO
header. These are INT[0] and INT[1], connected to the Arduino® UNO pins
D2 and D3 respectively. As we have seen in Figure 6, the microcontroller
executes the program in a loop, which is in a sequence. If something crucial
is needed to be addressed in between that sequence, the interrupt feature is a
way to suspend the current program sequence execution and to perform a
higher priority task associated with that particular interrupt. That higher
priority task or function associated with the interrupt is called an Interrupt
Sub-Routine or ISR. In the ISR, we could write our program defining the
response of the microcontroller to a particular interrupt input. There are built-
in functions available in the Arduino® IDE library for defining ISR to make
things available for a quick start, and hence we will use the same.
Apart from the two external interrupts, there are interrupts generated
internal to the microcontroller ATmega328P. There are interrupts generated
by the ADC subsystem, timers/counters that the microcontroller would need
to service by executing the corresponding interrupt service routine (ISR).
Apart from the above two types of interrupts, the pin change interrupts
associated with each port on the Arduino® is also available. These are
labelled PCINT0 to PCINT23, as mentioned in Table 8 and Table 9. These
interrupts provide much simpler functionality than INT0 and INT1, as they
only trigger on a RISING or FALLING edge of the signal on an IO pin. I will
reserve this topic for a more advanced Arduino® user and will not use much
as a beginner. Thus I am keeping this topic out of the scope of this book.

Analog Inputs/ADC:
The Port C pins PC0 to PC5 could also be configured as Analog Input pins.
These six pins are brought in from the Analog IN header on the Arduino®
UNO board like it is shown in Figure 2 and discussed in Table 8. As a Digital
signal has only two states for ON/OFF conditions or HIGH/LOW levels, the
microcontroller being a digital device can read it directly. On the contrary,
analog signals cannot be read by a digital logic system directly without a
circuit translating the analog signal levels into a binary “code”. The circuit
component that converts the analog signal into digital codes is called an
Analog to Digital Converter or in short – ADC. The microcontroller
ATmega328P on Arduino® UNO has a 6-channel 10-bit ADC built-in. The
ADC converts an analog input voltage to a 10-bit digital value through
successive approximation. Therefore, it is called a Successive Approximation
Register type ADC or SAR ADC. In our program, when we set the Port C
pins 0 to 5 as analog inputs, internally, those pins get connected to the six
channels of the ADC. However, we need to make an important note here: the
ADC is a single channel ADC. These six channels are multiplexed; means we
could select one channel at a time. Thus, we could only read one channel at a
point in time. The analog input channel is selected by writing to the MUX
bits in ADMUX register and control the ADC using ADC Control and Status
register ADCSRA.
An ADC can convert a signal only if the value of the signal falls in the
maximum range or the full-scale range, for which the ADC is designed. If we
provide a voltage outside its range, it will convert it into a wrong code, or it
could get damaged. Hence, we should ensure that our input signal always
falls inside the full-scale range (FS range) of the ADC. The ADC of the
ATmega328P controller has a configurable range. This full-scale range is
configured by setting the appropriate voltage reference for the ADC. For
ATmega328P, we could either select AVCC or the internal 1.1V reference or
an external reference to the AREF pin of the Arduino®.
If we select AVCC as the reference for the ADC, which is the default
setting, the signal voltage shall be within the range 0V (GND) to 5V
maximum. As the ADC inside ATmega328P is a 10-bit one, it will convert
this analog range of 0-5V into the corresponding binary codes ranging from 0
to (210 – 1) where 0V signal will have the integer value 0 or binary value
“0000000000” (hex: 0x000). On the other side of the range, 5V will be read
as the integer value (210 – 1), i.e. 1023 or binary value “1111111111”
(0x3FF). The ADC generates a 10-bit result which is presented in the ADC
data registers, ADCH and ADCL. By default, the converted result is “right
adjusted”. That means, the registers ADCL and ADCH would contain the
lower 8 bits and the upper two bits respectively.
If the voltage of a channel exceeds VREF, then the ADC conversion
result would be a code close to 0x3FF (Full-scale maximum). Nevertheless,
we must not apply a voltage larger than 5V to the ADC input as that might
damage the microcontroller and the Arduino® UNO board. In case, the
analog signal falls within a tiny range of 0-1.1V, we should select the 1.1V
internal reference using the REFS0 and REFS1 bits of the ADMUX register.
In that case, the analog range of 0-1.1V will be mapped to the digital or
binary range of 0-1023 count (0x000 to 0x3FF).
We have a third choice of using the external reference voltage AREF. If
we select AREF to be the input for the ADC reference, we should connect a
DC voltage to the AREF pin. That shall be in the range of 1.0V to AVCC
(5V for Arduino® UNO). We should use this configuration for measuring an
analog signal falling in a range, say 0.5V to 3.5V and for that, we would need
to apply 4V to AREF pin. The voltage reference selection and the
corresponding full-scale range is depicted in Figure 11.

Figure 11: ADC Full Scale Range Selection

There is a built-in function analogReference() in the Arduino® library for


selecting the voltage reference. If this is function is not used, the default
selection will be: VREF = AVCC. Therefore, the default full-scale range of
the ADC input would be 0V to 5V. To select the internal 1.1V, we have to
declare:

analogReference(INTERNAL); // “INTERNAL” for 1.1V reference


selection (for UNO)

For selecting the external reference (AREF), we need to declare:


analogReference(EXTERNAL); // “EXTERNAL” for external reference
selection (for UNO)

Figure 12: ADC Registers and Their Connection To The Internal Data Bus

The ADC also needs a clock. There is no external ADC clock input on the
chip, but the required clock is generated internally from the same clock used
to run the microcontroller. By default, the ADC of AT-mega328P requires an
input clock frequency between 50kHz and 200KHz to get the maximum
resolution of 10 bits. The CPU clock is faster, and hence an adjustable
“Prescaler” is needed to divide the CPU clock frequency for generating a
slower ADC clock. The Prescaler can be any choice of divisors among 2, 4,
8, 16, 32, 64, or 128 and it is up to us to select one that results in an ADC
clock within the acceptable range.
Let us now get familiar with the ADC registers. An advanced Arduino®
user should always refer to the datasheet or the user manual document of the
microcontroller, which is the right place to find all the required information.
As I have kept the scope of this book limited to beginners, I have attempted
to provide just enough information for my readers to develop a certain level
of acquaintance without the need to refer the datasheet.

A. ADMUX Register:
The ADMUX register controls:

The reference voltage setting for the ADC for controlling the full-scale
range.
The input multiplexer for selecting one of the six input channels.
The modes for arranging the conversion results in the ADCH and
ADCL registers.

7 6 5 4 3 2 1 0
REFS1 REFS0 ADLAR -- MUX3 MUX2 MUX1 MUX0
Table 11: ADMUX Register Bits

Four LSBs of the register ADMUX, MUX3 down to MUX0 control the
selection of one of the six input channels of the ADC, as shown in Table 12.

MUX3 MUX2 MUX1 MUX0 Selected Analog Input Channel


on Arduino® UNO
0 0 0 0 A0
0 0 0 1 A1
0 0 1 0 A2
0 0 1 1 A3
0 1 0 0 A4
0 1 0 1 A5
Table 12: Analog Input Channel Selection Bits

The ADLAR bit determines how to arrange the converted result in the
ADCH and ADCL registers. We will use the default setting for the right
adjusted result and let us ignore the other setting for now.

ADLAR Conversion Result in ADCH & ADCL


0 Right adjusted for 10-bit results
1 Left adjusted for 8-bit results
Table 13: ADLAR bit of ADMUX

The last two bits REFS1 and REFS0 control the selection of the reference
voltage source for the ADC as shown in Table 14. This setting determines the
full-scale range of the ADC.

REFS1 REFS0 Reference Voltage Selection


0 0 AREF (1.0V to AVCC)
0 1 AVCC (5V)
1 1 Internal 1.1V Reference
Table 14: Reference Voltage Selection Bits

B. ADCSRA - Control and Status Register A:


The ADC module of the ATmega328P has two control and status registers,
ADCSRA and ADCSRB (Control and Status Register B). For basic ADC
operations, only the bits in the ADCSRA register have to be modified.

7 6 5 4 3 2 1 0
ADEN ADSC ADATE ADIF ADIE ADPS2 ADPS1 ADPS0
Table 15: ADCSRA Register Bits

Bit 2 down to Bit 0 are the Prescaler bits those set the divisor for the
ADC clock.
ADPS2 ADPS1 ADPS0 Prescaler
Value
0 0 0 2
0 0 1 2
0 1 0 4
0 1 1 8
1 0 0 16
1 0 1 32
1 1 0 64
1 1 1 128
Table 16: ADC Prescaler Bits

Bit 3, ADIE is the interrupt. If ADIE is set ‘1’, an interrupt will be


generated on the completion of a conversion.
Bit 4 is the ADC conversion complete status bit. After the conversion is
completed, ADIF is set high. If ADIE bit is already set as ‘1’, ADIF going
high will trigger an interrupt request (IRQ).
Bit 5, ADATE is ADC Auto Trigger Enable bit. Nevertheless, we will not
use this much and hence will ignore it now.
Bit 6 is the ADC Start Conversion bit. Setting the ADSC bit to a 1
initiates a single conversion. This bit will remain a one until the conversion is
complete. If our program using the polling method (not using interrupt) to
determine when the conversion is complete, it can test the state of this bit to
determine when it can read the result of the conversion from the data
registers. As long as this bit is ‘1’, the data registers do not yet contain a valid
result.
Bit 7 is the ADC Enable bit. This bit must be set to 1 to do any ADC
operations.

C. ADCH and ADCL – Data Registers:


After the conversion is completed, the 10-bit result is stored in two-byte
format into the ADCH and ADCL Data Registers. If ADLAR bit is cleared to
‘0’, then the 10-bit conversion result is stored in the “right-justified” format
as shown in Table 17.
ADCH 7 6 5 4 3 2 1 0
-- -- -- -- -- -- ADC9 ADC8
ADCL 7 6 5 4 3 2 1 0
ADC7 ADC6 ADC5 ADC4 ADC3 ADC2 ADC1 ADC0
Table 17: ADCH and ADCL Registers (Right Adjusted) When ADLAR = ‘0’

If ADLAR is set to ‘1’, then the result will be “left-adjusted” like shown
in Table 18. The advantage is we could just use the value in the ADCH
register and ignore the last two LSBs stored in the ADCL register. However,
the converted result will have an 8-bit resolution instead of 10-bit.

ADCH 7 6 5 4 3 2 1 0
ADC9 ADC8 ADC7 ADC6 ADC5 ADC4 ADC3 ADC2
ADCL 7 6 5 4 3 2 1 0
ADC1 ADC0 -- -- -- -- -- --
Table 18: ADCH and ADCL Registers (Left Adjusted) When ADLAR = ‘1’

These are the essential registers for setting up the ADC using
programming. We might not need to use or modify any of these registers
directly by ourselves as the functions available in the Arduino® library will
do all that. Instead, we need to use those functions in our code. We just need
to be aware of what happens in the background. In Chapter 11, we will see
the use of analogRead() function, which will configure all these registers for
you.

Timers/Counters:
The next function we are going to learn about is Timer & Counter. This is
another critical function. There is a lot to know if we want to utilize this
feature to the full extent. To begin making, we might not need to know a
whole lot. In this section, I have highlighted some of these “need to know”
aspects of Timer/Counter. ATmega328P contains three timers or counters:
Timer/Counter0, 1 and 2, as shown in Table 19 below. Please note that each
timer has two output channels A and B.

Timer Bits Timer Output UNO pin


Timer/counter0 8 OC0A ∼D6
OC0B ∼D5
Timer/counter1 16 OC1A ∼D9
OC1B ∼D10
Timer/counter2 8 OC2A ∼D11
OC2B ∼D3
Table 19: Lists of Timer/Counters Available In Arduino® UNO

Timers are counters which count up (increment count) or count down


(decrement count) on every clock edge. Based on the counter value, we could
perform various tasks. If Timer0 or Timer2 starts from count “0000 0000”,
the count will reach binary value “1111 1111” or hex 0xFF after (28 – 1) or
255 clock cycles. Similarly, if Timer1 starts from 0x0000, it will reach value
0xFFFF after (216 – 1) or 65,535 clock cycles, as Timer1 has a 16-bit count
register.
Each of these three timers has several modes of operation. For example,
Timer0 has eight different modes of operation, while Timer1 has sixteen
different modes. Therefore, we could utilize these timers in our application in
a lot of different ways. The simplest model of operation is Normal mode. In
this mode, the counting direction is always up (incrementing), and no counter
clear is performed. When a timer is configured in Normal mode, it “rolls-
over” after the count reaches the maximum value (255 for Timer0/ Timer2
and 65,535 for Timer1).
Consequently, the corresponding Timer Overflow interrupt flag TOVx (x
indicates the timer number) is set, and the timer continues to count again,
starting from 0. The user program should service the interrupt and take
actions according to the program written in the ISR. This maximum value is
referred to as the “Top” of the counter. It is the maximum limit, reaching
where the counter rolls over back to zero counts. Keep in mind that the
counter does not stop and wait for the interrupt to be serviced. It continues to
count regardless of when or if the user program services the interrupt.
Imagine if we are using the same clock frequency 16MHz (time-period =
0.0625 microseconds) for the timer’s “time tick”, after every 0.0625 micro-
seconds, the counter will increment. Starting from count 0, Timer0 and
Timer2 will reach count 255 after (0.0625 x 256) microseconds, i.e. 16
microseconds and we get an interrupt for the corresponding timer. That might
be too quick if we want to implement delays in seconds. Even if we use
Timer1, we will get the interrupt every (0.0625 x 65,536) microseconds, i.e.
∼4 milliseconds. Even this might not be enough to get a much longer delay in
seconds. For this reason, the clock for the timers has separate “Prescaler” to
divide the internal clock by any of 8, 64, 256 or 1024 for Timer0/1 and any of
8, 32, 64, 128, 256 or 1024 for Timer2 before it reaches the timer. Hence, if
we choose Prescaler of 1024 for Time1, we will get a maximum delay of
(1024 x 0.004) seconds or 4 seconds interval between two consecutive
interrupts. In our program, we could count multiple interrupts to get more
delay.
Now, is there a way to stop the counters? Indeed, there is a way out. To
turn the timer off, set the Prescaler bits to all-zeros. The action of setting the
Prescaler bits to something other than all-zeros starts the timer counting. For
Timer0 and Timer1, instead of deriving the clock through the Prescaler, we
could also derive the clock source from the external clock signals connected
to Arduino® UNO header pins D4 and ∼D5 as shown in Figure 3 and
mentioned in Table 9.

Timer Register Name Register Description


Timer0/2 TCNT0/TCNT2 Timer/Counter Register (8-bit)
OCR0A/OCR2A Output Compare Register A
OCR0B/OCR2B Output Compare Register B
TCCR0A, Timer/Counter Control Register A
TCCR0B/TCCR2A, &B
TCCR2B
TIMSK0/TIMSK2 Timer/Counter Interrupt Mask
Register
TIFR0/TIFR2 Timer/Counter Interrupt Flag
Register
Timer1 TCNT1H, TCNT1L Timer/Counter Register (2x8-bit)
OCR1AH, Output Compare Registers A (2x8-
OCR1AL bit)
OCR1BH, OCR1BL Output Compare Registers B (2x8-
bit)
TCCR1A, B, C Timer/Counter Control Register A,
B & Cs
TIMSK1 Timer/Counter Interrupt Mask
Register
TIFR1 Timer/Counter Interrupt Flag
Register
ICR1H, ICR1L Input Compare Register (2x8 bit)
Table 20: ATmega328P Timer Registers

The timer registers are listed in Table 20. The TCNTn register contains
the counter value for the timer. Note that ‘n’ denotes the corresponding
number of the Timer0, 1 or 2. For the ease of describing, I am going to use
‘n’ in the nomenclature of the timer/counter registers or any particular bit of a
register to denote the respective number of the timer. When the timer runs,
the control logic increments the TCNTn register by one on each “clock tick”.
As discussed before, the timer “clock tick” could be different from the
Arduino® UNO’s “clock tick” depending on the Prescaler bits setting in the
control registers TCCRnA/B/C.
TCCRnA/B/C registers are the control registers of the respective timers.
As we could see in Table 20, Timer0 and Timer2 have two 8-bit control
registers each, while Timer1 has three 8-bit control registers. By setting the
bits of the control registers of a timer ‘1’ or ‘0’, we could configure the
corresponding timer for a mode. In the following section, we will see two
basic configurations of a Timer: mode selection and configuring the
Prescaler. Using individual bits of the timer/counter control registers, we
could configure the mode in which the timer would operate and with other
bits select the clock Prescaler.
Prescaler Selection: A Prescaler dictates the speed of our timer according
to the following equation:

Timer Speed (Hz) = (Arduino Clock Speed (= 16 MHz for


UNO))/prescaler

The Prescaler for a timer is determined by the three LSBs of the register
TCCRnB. These bits are CSn2, CSn1 and CSn0. Three bits could generate 23
= 8 possible values for the Prescaler. Among these three timers, only Timer2
uses all eight values for Prescaler. Timer0 and Timer1 use six combinations
of CSn bits for configuring the Prescaler, and last two combinations are used
for selecting the external clock for the timer. The Table shows the use of the
CSn bits for the three timers.

CSn2 CSn1 CSn0 Timer0 & Timer1 Timer2


0 0 0 Timer/Counter Timer/Counter
Disabled Disabled
0 0 1 No Prescaling No Prescaling
(Prescaling = 1) (Prescaling = 1)
0 1 0 Prescaler = 8 Prescaler = 8
0 1 1 Prescaler = 64 Prescaler = 32
1 0 0 Prescaler = 256 Prescaler = 64
1 0 1 Prescaler = 1024 Prescaler = 128
1 1 0 External clock Prescaler = 256
source on T0 and T1
pins for Timer0 and
Timer 1
respectively; falling
edge
1 1 1 External clock Prescaler = 1024
source on T0 and T1
pins for Timer0 and
Timer 1
respectively; rising
edge
Table 21: CS Bits To Configure Prescaler

Note that, as shown in Figure 3, T0 pin is mapped to Arduino® UNO port


D4 and T1 pin is mapped to port ∼D5.
Mode Selection: There are three WGM (Waveform Generator Mode) bits
for Timer0, Timer2 and four WGM bits for Timer1, which configure the
mode in which the timer would operate. As there are four WGM bits for
Timer1, namely WGM13, WGM12, WGM11 & WGM10, Timer1 could have
24 = 16 different modes or configurations. On the other hand, Timer0 could
have only 23 = 8 modes possible with three “mode” bits WGM02, WGM01
& WGM00. Likewise, Timer2 also could have a maximum eight mode
selections with three “mode” bits WGM22, WGM21 & WGM20. Timer0,
Timer1 and Timer2 can be configured in any of the 6, 15 and 6 modes
respectively by configuring WGMn bits. These modes could be “Normal
Mode”, “CTC” or different “PWM” modes. I will introduce the “Normal
Mode” and “CTC” in this section and will discuss the “PWM” mode in
chapter 12.
Normal Mode: The simplest mode in which the timers could be
configured is the Normal Mode. In Normal Mode, the Prescaler receives a
pulse from a clock cycle and passes it onto the Control Logic. The Control
Logic increments the TCNTn register by 1. When TCNTn hits the TOP
(0xFF in the 8-bit timers and 0xFFFF in the 16-bit timer) it overflows to 0
and sets the TOVn bit in the TIFRn register. The normal mode could be
configured by resetting all WGMn bits for a timer to ‘0’.
CTC Mode: The CTC mode stands for “Clear Timer on Compare”. In this
mode, the value programmed in the OCRn register sets the TOP, instead of a
default maximum as in the Normal Mode. In CTC mode, the Prescaler
receives a pulse from a clock cycle and passes it onto the Control Logic. The
Control Logic increments the TCNTn register by 1. The TCNTn register is
compared to the content of the OCRn register, which is the TOP in CTC
(Mode 4 for Timer0, 1 & 2). When a compare match occurs, the TOVn bit of
the TIFRn register is set. Therefore, to implement the delay using the Timer1
in CTC mode, we would need to configure four bits: WGM12 and WGM13
of the TCCR1B register and WGM10 and WGM11 bits of the TCCR1A
register as shown in Table 22. Timer1 has two CTC modes – Mode 4 and
Mode 12. In CTC Mode 4, OCIF1A can generate an interrupt when it detects
a compare match. To activate the CTC interrupt of Timer1 we need to set the
OCF1A bit of the TIMSK1 register to ‘1’.
In CTC Mode 12, TICIE1 can generate an interrupt when it detects a
compare match. To activate the CTC interrupt of Timer1, we need to set the
TICIE1 bit within the TIMSK1 register to ‘1’.

Timer WGMn3 WGMn2 WGMn1 WGMn0 Mode Top


n (#number)
Timer0 -- 0 0 0 Normal 0xFF
Mode (#0)
-- 0 1 0 CTC (#4) OCR0A
Timer1 0 0 0 0 Normal 0xFFFF
Mode (#0)
0 1 0 0 CTC (#4) OCR1A
1 1 0 0 CTC (#12) ICR1
Timer2 -- 0 0 0 Normal 0xFF
Mode (#0)
-- 0 1 0 CTC (#4) OCR2A

Table 22: Normal & CTC Modes

Figure 13: Illustration of Counter Value Incrementing in TCNT Register With Timer Clock

In Figure 13, it is illustrated that the counter register of the respective


timer increments with each positive clock edge of the timer clock, when the
timer is running. Since the timer gets incremented in discrete steps, we could
see a “stair-case like” stepped waveform. Now as we increase the timer scale,
or in other words, if we show more numbers of clock pulses on the time axis,
the size of the steps would keep on appearing smaller, and the counter
waveform would look like a straight line. Therefore in Figure 14, the counter
waveforms are shown as straight lines instead of stepped waveforms.

Figure 14: Illustration of The Timer Configured in Mode0 – Normal Mode

The operational waveforms of the timers configured in the normal mode


(Mode0) are illustrated in Figure 14. Note that on every edge of the timer
clock, the counter keeps on incrementing till it hits the TOP, which is 255 for
the eight-bit Timer0, Timer2 and 65,535 for the sixteen-bit timer1. After the
counter hits the TOP, TOVn bit is set, interrupt is triggered (if enabled) and
the counter is reset to 0.
In Figure 15, the operational waveforms of the timers configured in the
CTC mode (Mode2 for Timer0 and Timer2; Mode4 for Timer1) are
illustrated. In this CTC mode, TOP is defined by the OCRnA register value.
Only Timer1 has another CTC mode, which is Mode12. In Mode12, the TOP
for Timer1 is determined by the value stored in the ICR1 register.
Figure 15: Illustration of The Timer Configured in CTC Mode

Now, we might be able to appreciate one advantage of the CTC mode. In


normal mode, the time needs to reach to the maximum value of the counter
TOP to set the TOVn bit and generate an interrupt. So for a particular setting
of the timer clock frequency, our counter would hit the top always after a
fixed interval. However, in the CTC mode, we could always get different
delays for a clock configuration by configuring different values in the
OCRnA register.

Communication Interfaces:
Another primary function of a microcontroller is communication. The
communication interface of the microcontroller enables other intelligent
devices such as another microcontroller, personal computer to send and
receive meaningful information in the form of digital data (bits: ‘1’s and
‘0’s). Two types of communication interfaces are available – parallel
interface and serial interface.
The parallel communication needs a data bus of width 4, 8, 16, 32, 64 or
more. The concept of parallel interface is simple: we arrange the information
to be sent in arrays or packets of the same size as the data bus and send all
those bits in the packet at the same time on a single clock edge. If the parallel
interface has a width of 8 bits, we could send 8-bit wide arrays of information
on each clock edge, as shown in Figure 16. However, in this type of
communication, we need a larger number of signal pins compared to the
same for serial communication. For example, we need eight signal pins for
sending 8-bit data or 64 signal lines for sending 64-bit data apart from the
clock and control signals.

Figure 16: Data Flow with respect to the Clock Edges on 8-Bit Parallel Communication Interface

The other type of interface is a serial communication interface. In serial


communication, data is sent serially one after another on a single data signal
on each edge of the clock signal, as shown in Figure 17. The advantage of a
serial interface is that we need a lesser number of signals compared to the
parallel interface, as only one data signal is used. On the other hand, we
would need to go much higher on the clock speed so that the same number of
bits are sent or received per second. The bits sent or received per second is
also called the data rate or throughput. As the number of pins is a major
constrain for a small microcontroller board like Arduino® UNO, the serial
communication interface makes more sense.

Figure 17: Data Flow with respect to the Clock Edges on a Serial Communication Interface

The ATmega328P microcontroller provides options of three types of


serial communication interfaces – Universal Synchronous Asynchronous
Serial Receiver and Transmitter (known as USART), IIC (Inter-Integrated
Circuit) or commonly known as I2C interface and Serial Peripheral Interface
(SPI). All these three types of communication interfaces are serial
communication types as the digital data is sent or received serially over a
single data signal. In asynchronous communication interfaces, there is no
physical clock signal used. Only two data lines are used to transmit (Tx) and
receive (Rx). Optionally, two more lines might be used to provide
handshaking option between the communicating devices. The
synchronization between transmitter and receiver is obtained by extracting
timing information from the data stream itself. Start and stop bits are added to
the data, and precise formatting allows reliable data transfer. Note that, both
the communicating devices will have the datarate or baud rate set the same.
To understand asynchronous communication, we could think about an
analogy. Let us consider two friends decide to meet at a place at a particular
time. They do not have the reference to a common clock, but both check and
adjust their watches to get the same time and then follow their own watches
to arrive at the rendezvous.
The USART port of the ATmega328P microcontroller on Arduino® UNO
is used to communicate to the computer running the Arduino® IDE software
and also to download the program into the microcontroller. Table 23 shows a
relative comparison between these three serial communication interfaces.

Specifications USART I2C SPI


Max Data Rate 250 Kbps 400 Kbps 8 Mbps
Number of Two Two Four
Signals (minimum)
Error Data overrun and Not Not
Detection Framing Error detection Supported Supported
Table 23: Brief Comparison of The Various Serial Communication Interfaces
Available On Arduino®

Each of these three serial communication options has some advantages


over the other. Therefore, all of these are popularly used in the respective
applications. The USART is the oldest one, but still very popular for the
communication between the PC to a microcontroller. If we need a speed
higher than 400 Kbps, we should use SPI communication. If the
communication between multiple devices is required, we might need to
choose between USART or I2C as both will support connecting multiple
devices on two wires. Most of the sensors or the output devices use either I2C
or SPI as the communication interface. Figure 18 shows the different
communication pins on the Arduino® UNO board.

Figure 18: Communication Interface Pins on Arduino® UNO


CHAPTER 7
Input Devices - Sensors

e have the sensory system to see, hear, feel hot or cold when we touch
W something and experience our surroundings for making informed
decisions. Likewise, a microcontroller also can use electronic sensors
and could be programmed to perform actions based on specific input signals
from the sensors connected to it. The sensors are the devices which measure
the physical parameters and convert those into the electrical signal the
microcontrollers could read. To build an intelligent machine such as a robot,
we need to use several such sensors. The more intelligence we want to pack
in our gadget, more numbers of different sensors are needed to be connected
to our device.
The sensors convert physical parameters into electrical signals. Thus, we
need to know what type of signal is produced by a particular sensor before
connecting the same to the Arduino® UNO board. We have already seen that
the Arduino® UNO could accept only the following types of signals – (A)
Digital (High or Low), (B) Analog (0 – 5V maximum). Apart from the
signals, we could also read the measured values through any of the serial
communication interfaces such as SPI or I2C or USART supported by the
sensor. We need to know what maximum voltage the sensor can produce. If
the voltage is higher than 5V, we shall not connect that signal directly to the
port pin of the Arduino® UNO as a voltage higher than 5.5V might damage
the port pin of the microcontroller and the board. Hence we need to double-
check whether the sensor is compatible with the Arduino® UNO or if we
need an intermediate circuit component.
Buttons and Switches: The switches and buttons act as the input devices
to the microcontrollers as “user interfaces” (UI). There are special types of
switches specific to different applications. For example, a magnetic reed
switch closes or opens its contacts influenced by the presence or absence of a
magnetic field in its proximity. Therefore, this type of switch is used as a
proximity sensor. Another type is a contact switch or commonly known as
the “limit switch”. It is used to detect the limiting distance till which a
mechanism could move and touch the lever of the switch. Subsequently, the
switch position change is detected, and the movement could be stopped. The
application of limit switches could be seen in the elevator system of a
building. Once the elevator hits a sensor while moving up or down, the
elevator’s controller senses the position of the elevator and takes appropriate
actions such as stopping at the destined floor or displaying information about
the floor it passes by.

Figure 19: Buttons and Switches

The switches and buttons have contacts which either close to allow the
flow of current through a circuit or open to stop the flow of current through
the circuit. Depending on the state of the contact, whether opened or closed, a
signal having two digital states such as HIGH or LOW, could be generated.
The microcontroller can read this signal as a digital input. Figure 20 shows
how we should connect a switch or a button to a digital IO of Arduino® UNO
or any other microcontroller board for reading the state of the contact. When
the contact is open, the current does not flow through the switch. Hence, the
voltage on the DIO pin becomes 5V as there is a pull-up resistor connected to
the 5V supply. When the switch is closed, the voltage on the DIO changes to
0V as the DIO pin gets shorted to ground (GND) through the switch. Thus,
the microcontroller on Arduino® reads ‘1’ or HIGH when the switch is OFF
and reads ‘0’ or LOW when the switch is ON. Practically, a signal state
change from HIGH to LOW or the vice-versa does not happen
instantaneously. As the switch or the button is pressed, the contact
“debounces” due to spring action. That means, the switch randomly turns on
and off for several milliseconds. This phenomenon is called contact
debounce. As the microcontroller can read much faster than a millisecond,
during “debounce time” it will read ‘1’s and ‘0’s as the contact debounces.
The debouncing results in an incorrect signal that we need to filter. As a
hardware solution, a debounce filter capacitor could be connected in parallel
to the switch contact like it is shown in Figure 20. The functions such as
delay() or millis() could be used to wait after a change detected before
checking if the last change was stable. The pull-up resistor and the capacitor
will form a filter, which will ignore the fast change in the signal. Hence, the
input signal transition from 5V to 0V will be read correctly. Alternatively, a
software solution could be to write a “debounce filter algorithm” in the
program. The functions such as delay() or millis() could be used to wait after
a change detected before checking if the last change was stable. However,
this would need a bit more experience in programming. Hence, connecting a
debounce capacitor is always useful. As a thumb rule, we could connect 10uF
debounce capacitor with a 10 KΩ pull-up resistor. We do not need to bother
much as the digitalRead() function that we will use to read the state of a
button has the debounce filter implemented.

Figure 20: Connecting Switch to Arduno® and Debounce Filter Capacitor


Sound Sensor: The sound sensor module is based on a tiny microphone,
which converts the sound wave into an electrical signal. As the sound wave
hits the diaphragm of the microphone, the diaphragm vibrates, which gets
converted into a change of capacitance. The change of capacitance is then
amplified by a circuit and presented as an electrical signal to the
microcontroller. There are two types of sound sensor modules available. One
type of sensor has a comparator that compares the converted signal of the
input sound wave with a reference voltage. If the input signal is higher than
the reference voltage, it drives the output signal HIGH (usually 5V). This
types of sensors are sound detectors, which generate a digital signal. One
popular application of this kind of sensors is “clap-switch”. We could turn the
light ON or OFF just by clapping.

Figure 21: Sound Sensor Modules

The other kind of sensor module comes with an additional amplifier and
associated circuit, which converts the sound energy level into an analog
signal proportional to the sound level. This signal generated by this type of
module is an analog type and needed to be connected to the analog input port
pin of the Arduino® UNO board. The ATmega328P microcontroller reads the
sound levels as count values using the analogRead() function. This type of
modules could be used for measuring the sound pollution level.
Ambient light sensor: Ambient light sensors are the photosensors, which
are sensitive only to the visible spectrum of light. Hence, the ambient light
sensors could closely imitate the human eye response to visible light. As we
know, light is an electromagnetic wave. Different colours in the visible light
spectrum have different wavelengths, as shown in Figure 22. The ambient
photo sensors are responsive only to the visible light spectrum and sense
ambient light closely similar to as human eye sees the light.
Before we learn more about the sensors, let us get a little familiar with
some of the terms which are used to measure light.

Figure 22: Visible Light Spectrum and Wavelengths (source: https://www.newelectronics.co.uk/)

Lux – This is a unit of illuminance, which expresses the total amount of


light that falls on a particular surface.
Lumen – This is a measure of the total quantity of visible light emitted by
a source per unit of time.
Luminous Intensity – the quantity of visible light that is emitted in unit
time per unit solid angle. The higher the luminous intensity, the higher the
sensitivity it is to our eyes.
There are plenty of light sensor modules available from various
manufacturers for different applications. The ambient light sensors could be
of different types such as Light Dependent Resistor (LDR), Photo Diode,
Photo Transistor and digital light sensors. The first three mentioned are
analog sensors, and the circuit could be made to convert the different amount
of light into varying levels of voltages within a range, suppose 0 – 5V. The
Light Dependent Resistor or LDR is a type of device, the resistance of which
changes when the intensity of light falling on it varies. We could use these
types of sensors when it is required to detect the presence and absence of
light or measure the light intensity.
The photo-diode and the phototransistors are the semiconductor devices,
which convert light into an electrical current. The microcontroller senses the
presence or absence of light using this type of sensor modules. The
photodiode generates ON/OFF kind of response based on whether the sensor
detects light or not. The microcontroller senses the presence or absence of
light using this type of sensor modules. Photodiode based modules generate
digital output that we could connect to a digital input of Arduino®.
The phototransistor based light sensors provide analog output. Hence, we
could connect this signal to an analog input pin, so that the internal ADC of
ATmega328P could read the analog signal. To read the intensity of light
effectively, we need to know the characteristics of the sensor thoroughly.
Another kind of sensor module has the photosensor and an ADC
integrated into the sensor module, which converts the intensity of the light
into digital values. The ATmega328P microcontroller on the Arduino® UNO
could read this signal over the digital communication interface such as I2C.
These types of light sensor modules are a bit costly compared to the analog
ones but much more accessible and more accurate. Some of the light to
digital converters are TSL2561, SI1145, APDS9960, VEML7700, BH1715,
BH1750 and Arduino® compatible modules are available based on those.

Figure 23: Ambient Light Sensor Modules


The ambient light sensors could have various applications. You might
have observed the auto-brightness adjust feature on your smartphone. The
brightness of the screen gets automatically adjusted according to the ambient
light. There is an ambient light sensor behind this auto-brightness feature of
the phone screen. Another application could be to turn the garden lights ON
automatically at dusk when it gets dark. Again, the program could turn those
OFF at dawn. One more popular project idea could be to build a “line
following robot”, which follows a black line painted on a surface. We could
use the photo-diode and sensor pair for this project. One idea could be to use
black tape on the floor to draw a thick black line, which the robot should
follow. As we know, the light falling on a black surface mostly get absorbed
and hence not much of that reflect from that surface. The light emitted by the
photo-diode would not get reflected back to the photo-sensor until the robot
moves along the black line. An algorithm could be developed to make the
robot more accurate and quick at the same time. You might think of
organizing a robotics tournament in your neighbourhood to make it a fun
event. We always learn better from others when we participate in such
healthy competitions.
Temperature, Humidity and Pressure Sensors: The temperature
sensor, humidity sensor and barometric pressure sensors often come
integrated into a single package and popularly known as “climatic sensors”.
The popular temperature, humidity or barometric pressure sensor ICs, based
on which Arduino® compatible modules are available are listed in the
table24. Relative comparison is also presented in Table 24.

Sensor Sensor Range Minimum Relative Interface


Model# Type Accuracy Cost Type
LM35 Temperature -55◦C to ±0.75◦C Low Analog
150◦C Voltage
DS18B20Temperature -55◦C to ±0.5◦C Low 1-Wire
125◦C Digital

DHT11 Temperature 0◦C to 50◦C ±2◦C Low 1-Wire


Digital
RH 20-89% 5%
DHT22 Temperature -40◦C to ±0.5◦C Medium 1-Wire
80◦C Digital
RH 0-100% 2-5%
BME280 Temperature -40◦C to ±1.5◦C High I2C, SPI
85◦C
RH 0-100% ±3%
Pressure 300-1100 ±1.7 hPa
hPa
SHT31A-Temperature -40◦C to ±0.3◦C High I2C
DIS11 85◦C
RH 0-100% ±2%
HTU21D Temperature -40◦C to ±1.6◦C Medium I2C
105◦C
RH 0-100% ±2%
Table 24: Popular Climatic Sensor IC Models and Comparison

The climatic sensors can have various applications such as building


temperature and Relative Humidity (RH) monitoring devices, automatic
control of air-conditioning, predicting the weather, measuring the height from
the sea level and likewise.
Touch Sensor: The touch sensor modules are the devices, using which
we could detect touch by our fingers. The touch sensor modules are based on
the ICs designed explicitly for detecting touch. Figure 24 shows the basic
principle of operation of the capacitive touch sensors. The touch sensor
circuit usually has a microcontroller unit (MCU), R-C circuit and the touch
plate. The MCU keeps on measuring the capacitance of the circuit. When
someone touches the plate or brings the finger to proximity to the plate, the
human body forms a parallel R-C circuit, shown as “Rh” and “Ch” in Figure
24. The MCU detects a change in the capacitance and declares that a touch
has occurred. The MCU runs complex algorithms to avoid detecting spurious
touch signals and keeps track of the parametric changes related to change in
ambient temperature, humidity.
Figure 24: Principle of Operation Behind The Capacitive Touch Sensors

Figure 25: Touch Sensor Modules, Those could be Used with Arduino

The touch sensor modules usually have the I2C interface for the
Arduino® to read the status of whether someone touched. The screens of our
smartphones have a touch sensor.
Accelerometer Sensor: The accelerometer sensor measures the
acceleration along with one or multi directions. The sensor which measures
the angular acceleration on one axis is called Gyroscope. The GY521
gyroscope module for Arduino® is based on a chip MPU6050. The MPU6050
IC consists of three independent gyroscopes, which detect rotation about the
X-, Y-, and Z- Axes. When the gyros are rotated about any of the sense axes,
the “Coriolis Effect” causes a vibration that is detected by a capacitive
pickoff. The resulting signal is amplified, demodulated, and filtered to
produce a voltage that is proportional to the angular rate. This voltage is
digitized using individual on-chip 16-bit Analog-to-Digital Converter (ADC)
to sample each axis. The GY521 module has the I2C interface using which
Arduino® can configure the MPU6050 IC and access the data.
Figure 26: Accelerometer Module Based on MCU6050

One of many applications of the gyroscopes is to sense gestures. Gestures


are motions such as shaking, tilting and flipping the module or a device on
which the module is attached, can be detected by this module or similar
modules.
Ultrasound (Sonar) Sensor: An Ultrasonic Sensor is a device that could
detect any sound with a frequency above 20,000 Hz, that is above the highest
frequency sound audible to human ears. An ultrasound detector could
measure the distance to an object. It works by sending out a sound wave at
ultrasonic frequency and waiting for it to reflect from the object. The time lag
between the start of transmission of the signal and receiving of the reflected
sound wave is used to calculate the distance as below:

Distance = (Speed of sound in the air * time lag)/2

As we know, the speed of sound is air is 343 meters/second or


0.0343cm/microsecond. We would need to use this value in the above
equation:

Distance (in cm) = [0.0343 * time lag (in microseconds)]/2 = time lag (in
microseconds) / 58

The popular sonar module is HC-SR04, which has both the transmitter and
the receiver, as shown in Figure 27. The transmitter is marked with “T”, and
the receiver is marked with “R”. The module operates with 5V and has two
signal lines – “Trig” and “Echo”. When the microcontroller on the Arduino®
UNO sends a pulse of width 10us to the “Trig” pin of the HC-SR04 module,
the module sends eight ultrasound pulses of ∼40KHz in the forward direction
with an angle of ±45◦. The most effective angle in which the HC-SR04 works
best is ±30◦.

Figure 27: HC-SR04 Ultrasound Module Details

The chip on the module calculates the distance of any object from which
the echo reflects. Next, the HC-SR04 module drives a pulse on the “Echo”
pin. The width of the pulse varies between 150us and 25ms according to the
distance of the object. This width of the echo pulse is the “time lag” (in
microseconds) in the equation explained above. If the pulse width is
anywhere between 150us and 25ms, we could get the distance in cm of the
object by dividing the pulse width in microseconds with 58. If the “Echo”
pulse width is 38ms, that indicates that the HC-SR04 module did not find an
object ahead. The signal “Trig” can be a digital output from Arduino®, and
we could connect the “Echo” signal to a digital input pin of Arduino®. We
would also need to connect the 5V and GND from Arduino® to power the
module up.
IR Sensor: The IR sensor modules available in the market are based on
Infra-Red sensor (looks like an LED) and the IC393, which is a comparator.
The infrared spectrum has longer wavelengths than the highest wavelength
(∼750nm for RED) in the visible light spectrum. The infrared (IR) spectrum
is shown in Figure 22, works in the 760nm – 1100nm wavelength range.
Figure 28: 760nm - 1100nm IR Infrared Flame Sensor Module For Arduino

The detection angle of the module is about 60◦. As the flame has some
infrared content too, this sensor module also could be used as a flame sensor
for a maximum sensing distance of 0.8 meters. The accuracy of detection
could be adjusted using the potentiometer shown in Figure 28. There are two
output signals available from this module – analog output and digital output.
The digital output indicates whether flame/IR is detected or not. The analog
output provides a voltage proportional to the intensity of the IR/flame
detected by the sensor. We could connect either or both to Arduino®
depending on our application.
There could be several applications of the IR sensor. Some of those are –
IR remote control, proximity sensor, flame sensor, motion sensor, thermal IR
sensor, burglar alarm – human body detection and likewise.
There are countless other types of sensors available, but these are the
primary sensors that we should know to start with our experiments.

11 There are other models having different specifications available and this series of ICs are referred
as SHT3x by the module manufacturers. Hence please check which model is on the module and refer
specification of the same.
CHAPTER 8
Output Devices

o far, we have learned about the brain of the Arduino® - ATmega328P


S microcontroller, the input devices or the sensors. To complete the loop
illustrated in Figure 6, we are yet to learn about the output devices and
subsequently about writing sketches to enjoy watching our Arduino® board
come alive. In this chapter, we are going to explore the popular output
devices compatible with Arduino®. We would also learn how we should
connect those devices to the Arduino® for building various applications.
In Chapter 6, we have learned that the digital IO pins of the
microcontroller ATmega328P on Arduino® UNO could be configured as
output by configuring DDRx and PORTnx registers appropriately. When an
IO pin of the microcontroller is set as an output, the driver circuit of that IO
pin can “source” or “sink” a certain amount of current to the load connected
to the pin. The load is referred to as the output device that is being driven by
the microcontroller. For example, the load could be an LED circuit or a motor
driver. Figure 29 shows a comparison between the sourcing and sinking
circuit configurations.
In the “sourcing” configuration, the current is driven out of the output pin
of the microcontroller. The “sourced” current returns to the ground or 0V
through the load. The sinking current returns to the ground through the output
pin of the microcontroller and IO driver of the microcontroller. Then the
current returns to the ground through the output pin of the microcontroller
and IO driver of the microcontroller. As shown in Figure 29, DO1 pin of the
microcontroller “sources” current to the load when the internal IO circuit
turns ON the output transistor. In this case, the DO1 pin will have a voltage
close to Vdd (5V on Arduino®), i.e. logic HIGH. On the other hand, DO2 pin
of the microcontroller “sinks” current from the power supply and through the
load when the internal IO circuit turns ON the output transistor. In this case,
the DO2 pin will have a voltage very close to 0V (GND), i.e. logic LOW.
Figure 29: IO Drivers Sourcing or Sinking Load Current

It is vital to know that the microcontroller can source or sink a limited


amount of current. For example, the ATmega328P microcontroller output pin
could source or sink ∼20mA current in normal steady-state conditions. This
current could be sufficient to drive an LED but might not be enough to drive
devices, which demand more current – such as a servo motor.
Now, let us discuss the output devices the microcontroller could drive.
Hence we need to know the current needed by the device we want to be
driven by the microcontroller and might need to connect additional devices in
between the microcontroller output pin and the load. For example, we might
need a motor driver IC or a relay in between for driving a large load like a
motor. Otherwise, either the microcontroller might not be able to drive the
load, or the microcontroller could get damaged.
LEDs: An LED is a diode, which emits light when the required voltage is
applied it to drive the LED into the forward biased condition, and a required
amount of current is flown through it. We could drive an LED by an IO pin in
two ways, as shown in Figure 30. One way is to source the current through
the IO pin, and the other way is to sink the current through the LED into the
IO pin.

Figure 30: Driving LED Using Arduino® IO Pin

As shown in Figure 30, we would need to connect a suitable resistor in


series with the LED, to limit the current through it. If we do not connect the
series resistor, either the LED or the microcontroller or both could get
damaged. Usually, a through-hole type LED needs ∼10 to 20mA of current.
We could connect a resistor of value somewhere between 200 – 300ohm to
get the required brightness or intensity. As we choose a lower value of the
series resistor, the LED will glow brighter. However, at the same time, the
current might exceed the rated source/sink current for the microcontroller pin.
The Arduino® UNO has a built-in LED connected to its D13 pin (port pin
PB5 of ATmega328P). Thus, if we program Arduino® to turn that LED on,
we just need to configure D13 as digital output by setting the fifth bit of
DDRB as one and then drive the same pin HIGH using the bit-5 of PORTB
register. However, we do not need to write all these in our code as there are
built-n functions such as pinMode() and digitalWrite() are available for doing
this job for us.
Relays: The relays are electrically controller switches, which are usually
used to handle a large amount of current or AC load like a light bulb. The IO
driver circuit of the microcontrollers is not rated for driving these kinds of
loads directly. Nevertheless, the microcontroller can control the relay to turn
such a load on or off. The relays are of two types – electro-mechanical relays
and solid-state relays. An electromechanical relay has a coil and one or more
spring-loaded contacts, as shown in Figure 31. The required voltage applied
across the relay coil (between C1 and C2 terminals), turns the coil into an
electromagnet and pulls the contacts. A normally open (NO) contact gets
closed, and a normally closed (NC) contact opens. Thus, when the relay coil
is energized, the circuit connected between the terminals NO1 and NO2 gets
closed as the NO contact “makes” and this type of relays are called FORM A
relay. On the other hand, for the FORM B type of relays, the circuit
connected between NC1 and NC2 opens as the NC contact “breaks” when the
coil is energized.

Figure 31: Electro-Mechanical Relay

There is a third type of relay, which has change-over contacts. This type
of relay is called FORM C type. When the coil of a Form C relay is
energized, the NC contact breaks and NO contact makes, and a change-over
happens. In a UPS, we have heard this sound of the relay changing over
between the mains power and battery.
The electromechanical relays are very popular and widely used, despite
being an older technology. The solid-state relay (SSR) is a relatively newer
technology, which is gaining popularity and displacing electromechanical
relays in many applications. Even though the initial cost of SSR is higher
compared to the cheaper electro-mechanical counterparts, SSRs have more
durability and reliability and in the long term. The solid-state relays do not
have the mechanical contacts for switching. Instead, they have semiconductor
switches such as transistors or triacs. The control of the switching is usually
provided using optical diodes or LEDs built into the SSR, as shown in Figure
32.

Figure 32: Solid-State Relay Schematics (SSR)

The light sensor is packaged together with the semiconductor switch,


which is usually a photo-transistor. Applying the required voltage between
the C1-C2 makes the photo-diode to turn ON. Subsequently, the photo-
transistor switches ON and conducts the current through the load connected
between LOAD1 and LOAD2 terminals. When the input voltage is removed,
the photo-transistor turns OFF. Subsequently, almost all current is blocked,
causing the load to become disconnected from the power supply. The pairing
of an LED with light sensors is very similar to how optocoupler works. The
optocouplers are meant for digital circuit isolation and cannot handle such
heavy load as an SSR.
Figure 33 shows an SSR module and one relay module that could be
driven by the Arduino® board. Sometimes, the relay coil might be rated for
6V or 12V. We need to be careful in choosing the right device for our
application so that the driving voltage required is in the 0-5V range. As the
5V relay modules are also available, we should better choose 5V rated
modules so that we could use 5V from the Arduino® board itself.
Figure 33: SSR module and Relay Module for Arduino

A note of caution: If you plan to connect a high voltage AC circuit


such as 230V on the secondary side of the relay, but if you are not
experienced in working with such high voltage, it is not safe for you.
Motors: If we want to build something that moves, we will need a motor.
What we are going to cover in this book are tiny motors, those are powered
by DC low voltage and can be controlled by Arduino® with the available
modules and shields. Otherwise, there are innumerous types of motors
available having different sizes for different applications. In this book, we are
going to discuss majorly four types of motors, which are – (1) DC motor
(brushed) (2) Stepper motor (3) Servo motor (4) Brush-less DC motors or
popularly known as BLDC motors. All of these motors operate with DC
voltage. The working principles behind all of these motors are based on the
principles physics following “ampere’s law” & “Right Hand Rule”. When
current is passed through a wire placed in a magnetic field, the wire
experiences a force.
Following the same principle, the coils in the motor experience a force
that pushes the coil and begins the rotation. Let us take a pause here, and we
will not venture into the detailed theory of electromagnetism. Instead, we will
focus more on what motor to choose for different applications for our
Arduino® based projects. We could decide what type of motor to use if we
know a relative comparison between the features of these motors and their
advantages. A brief comparison is presented in Table 25.

Figure 34: Different Types of Motors


DC Motor Servo Motor Stepper Motor BLDC Motor
(Brushed)
High Speed Reasonably high Low speed High Speed
speed
High torque at High torque High torque at High torque at
low speed low speed low speed
Continuous Accurate Stepped Continuous
Rotation rotation - rotation, very Rotation, quiet
positioning accurate rotation & efficient
- positioning
Simple Control Complicated Simple control Complicated
control Control
Applications: Application: Application: 3D Application:
Car, fan, drill Robotic arms or printer, robotic Drones
etc. legs movements etc.
requiring
precise
positioning
Table 25: Relative Comparison Between Commonly Used Motors

The motors need a larger current than the microcontroller’s pin could
supply. Thus, we need to use a motor driver shield which can supply the
current needed for driving the motor and can be controlled by the
microcontroller.
Figure 35: BLDC Motor Shield For Arduino (source www.infineon.com)

In Figure 35, an Arduino® compatible driver shield for a range of BLDC


motors is shown, which is available at the time of writing this book. This
shield or a similar one can be installed on the IO header of the Arduino®
UNO. We need to follow the respective manuals to make the electrical
connections from a battery and the connections to the BLDC motor. The
instruction for this particular shield from Infineon could be found in
Arduino®’s official website. The instructions for the electrical connections to
the battery and the motors are to be made are presented there. The software
code for the shields is also downloadable. One could download the code from
www.infineon.com or as instructed on the webpage of www.arduino.cc. Once
we make the connections and upload the code, we should be able to drive a
BLDC motor using Arduino®. There are various driver shields available for
other types of motors. We need to read through the respective manuals or the
instructions to make the electrical connections. The interfaces needed for the
motor drivers from the Arduino® are usually digital or PWM or serial
communication such as UART, SPI, I2C.
Displays: The displays are often called user interface or UI in short. The
UI is an interface device between human and the computer. Just like we use a
display along with our personal computer, we often need to use displays with
the microcontroller boards such as Arduino® to show messages, data, graphs
or pictures. Hence, let us consider displays also in the output device category
as the Arduino® drives signals to send appropriate data to the display
connected to it. There is a wide variety of displays those could be used with
Arduino® and for which the code is readily available. Let us get ourselves a
bit acquainted with those.
Dot Matrix Display: Figure 36 shows an 8x8 LED matrix display, on
which there are 64 LEDs arranged in an 8x8 matrix format. Since each of
these 64 LEDs are individually controllable, we would need around 64 IO
lines to control each of these LEDs. However, so many IO lines are not
available on the microcontrollers like ATmega328P. Even if those many IOs
were available, the microcontroller would have needed a massive amount of
current through its IO driver circuit to source or sink the current for all those
64 LEDs. The microcontrollers are usually not rated for that current. At the
same time, it would be a wastage of resources if we need to block 64 IO lines
only to drive LEDs. Therefore the LEDs are arranged in a matrix format and
connected as shown in Figure 37. Eight LEDs in each row have common
anode connections. On the other hand, eight LEDs in each column have
common cathode connections.

Figure 36: 8x8 Dot Matrix Display With MAX7219 Driver (Source: instructables.com)

As shown in Figure 37, eight LEDs arranged in a row has the anode (+)
terminals of the LEDs are connected. Those eight anode connections of the
eight rows are labelled with letters A, B, C, D, E, F, G and H. On the other
hand, the common cathode (-) terminals for eight columns of LEDs are
labelled with the numbers 1 to 8. Now, we would need only 16 IOs altogether
to drive 64 LEDs, which is four times lower. However, for a small
microcontroller like ATmega328P, reserving 16 IO pins for driving only
LEDs can not be afforded, and the current driving requirements is still an
issue. To solve this problem, ICs such as MAX7219, which has 24 IO pins
and technique improvised based on “Persistence of vision” could be used by
Arduino® to make the LEDs appeared to be permanently ON whereas those
are not driven continuously. Our eyes cannot see a quick blink which happens
as fast as 20 milliseconds or quicker, and this is called persistence of vision.
So, if we turn an LED ON, then turn it OFF for less than 20 ms and again
turn it ON, to our eyes the LED will appear to be ON all the time. Our eyes
will miss a blink. We could use this technique in driving the LEDs in the dot
matrix array one at a time with a quick blink and can save on driving current
& power requirements. On the other hand, the Arduino® needs only three of
its IO pins for driving the Data (DIN), Clock (CLK) and Chip Select (CS)
signals of the MAX7219 IC on the LED Dot Matrix module as shown in
Figure 36. As we have discussed in Chapter 6, this is the SPI interface.

Figure 37: LED Dot Matrix Arrangements

7-Segment LED Display: A seven-segment LED display has eight LEDs,


one for each of the seven segments plus one for the “decimal point”. The
segment LEDs are arranged in the fashion to appear as an “8”. There is also a
dot (“.”) next to the digit, as shown in Figure 38. The LEDs are internally
connected in common cathode or common anode configuration inside the
display. In the common anode configuration, the anodes or the positive
terminals of the LEDs are connected, and a positive voltage is applied to the
common terminal. In the common cathode configuration, cathodes or the
negative terminals are connected, and that common terminal is connected to
the ground.
The common anode configuration is shown in Figure 38. Each unit of the
display has ten pins out of which eight are for the LED terminals and two for
the anode connection. The “common-anode” configuration is shown in
Figure 38. Usually, each unit of the display has ten pins out of with eight are
for each of those LED terminals and two for the anode if it is “common-
anode” type.

Figure 38: 7-Segment LED Display & The Circuit Diagram

The common-anode terminal (pin 3 & 8) could be connected to 5V on the


Arduino® board itself with a series resistor. The cathode terminals for the
LEDs could be connected to the DIO pins of the Arduino®. If we drive DIO
connected to the pin#7 low, segment A will glow. Again, if the DIO
connected to pin# 2 of the display is pulled low, the segment D will glow.
Recalling the concept of “sourcing” and “sinking”, the common-anode
display would need a “sinking” type of drive from the microcontroller. The
connection from the DIO pins of Arduino® UNO to a 7-segment display is
shown in Figure 39. If we want to display an “A”, we need to drive the DIO
pins 2, 4, 10, 11, 12, 13 LOW as per the connections shown in Figure 38.
On the other hand, the common-cathode display would require a
“sourcing” type of IO driver connections. One point to note here, again it is
too many IOs needed to drive one 7-segment display. If we need to drive two
of these, we would need 16 pins. For constructing a digital clock, we would
need at least 4 of these 7-segment displays and 64 IOs to drive those. Here
again, ICs such as MAX7219 could be used to drive the 64 IO terminals,
exploiting the perception of visual concept and from Arduino®, we would
need only three pins for the SPI interface to the chip.

Figure 39: Connection To 7-Segment Display

LCD Display: LCD stands for Liquid Crystal Display, another technology
based on which displays are made. We just need to know that the characters
in the LCD are made of pixel matrixes, on which letters or numbers could be
imprinted by turning the respective pixels on. The concept behind displaying
on a pixel matrix is very similar to displaying a character on the LED dot
matrix display. Arduino® only needs to send appropriate data on the signal
pins of the display and the driver IC on the LCD takes care in displaying the
corresponding character on the pixel matrix of the display.
Figure 40: 16x2 LCD Display And The Breadboard Layout Connections With Arduino

The display shown in Figure 40 is a 16x2 display. There are two rows of
16 characters in each of the rows. Each character is formed by 5x7 pixel
matrix. This is very small, isn’t it? There are graphical LCDs available, in
which one large grid of pixels (e.g. 128x64) could accommodate much larger
sized characters or some simple graphical symbols. As we go for bigger
LCDs with more pixels, we would need to pay more. The 16x2 LCD has
eleven signal lines. There are eight data lines D0 through D7 and three
control lines such as RS, EN, RW. We will revisit these signals when we
program the Arduino® to display a message on an LCD.
OLED Display: Organic Light Emitting Diode or OLED is a relatively
newer technology compared to the LCD technology. Nowadays, different
varieties of OLED displays are used on smartphones. An LCD has certain
limitations, which are overcome with OLED technology. For example, we
cannot see the characters displayed on an LCD screen in the dark. We will
need a back-light for illuminating the screen. The display of a calculator is an
LCD. We have experienced that we cannot read the display in the dark
without the backlight. The OLED, on the other hand, does not need a
backlight as it is easily visible in the dark. Another issue with the LCD is that
the viewing angle is very narrow. If we cannot get a seat directly in front of
the TV with an LCD screen, we might not be able to see the picture correctly.
For OLED display, the viewing angle is wider than the same on an LCD.
Hence, OLED is more in use nowadays.
One of the commonly available OLED displays for Arduino® is a 0.96-
inch display with 128x4 pixels, as shown in the figure. At the time of writing,
the part number of the 0.96-inch OLED display is SSD1306 from “Solomon
Systech”. If interested, one could download the datasheet and read through it
to learn more about the display. This display has an I2C interface, using
which the Arduino® could talk to it.

SSD1306 Pins Arduino® UNO Pins


VIN 5V
GND GND
SCL A5
SDA A4
Table 26: SSD1306 Pins To Arduino Pin Connections

Table 26 captures the pin connections between the SSD1306 display and
the Arduino® UNO board. The signals SCL and SDA are the clocks and the
data signals for the I2C interface. As multiple slaves could be connected on
the I2C bus, we could connect multiple displays on the I2C bus with the
Arduino®. The code library for “Adafruit SSD1306” (By Adafruit) is also
readily available for download and use.
E-paper Display: The E-paper display technology is still evolving. The
Kindle users have already experienced the beauty of the reading from an E-
paper display. The E-paper display works based on “E-ink” technology. The
significant advantage of the E-paper display is that it consumes meagre
power compared to its other display counterparts. The reason behind a low
power consumption is that the E-paper does not need the power to maintain
the image being displayed. It will need power when it needs to change the
image. The major drawback is that the image displayed on an E-paper cannot
be changed at a fast rate. Therefore, a video cannot be viewed on an E-paper
display. It is challenging to find a coloured E-paper display.
Nevertheless, the E-paper display has its applications where the image
displayed is stable for a longer duration, such as e-book (Kindle). There are
some small E-paper displays available, which could be easily connected to
the Arduino®. These displays have SPI or I2C interface using which the
Arduino® board could send data to be displayed. However, the E-paper
displays are mostly black-and-White, and these are still a bit expensive.
So far, we have learned about various sensors and output devices. Next,
we will learn how we could connect these components to the Arduino® UNO
board and how we could program the Arduino® board to build an application.
CHAPTER 9
Building Circuit on Breadboard

he Breadboard helps in prototyping our circuit connecting Arduino® and


T other components, pretty quickly and without the need to take the hassle
of soldering. To make a circuit lasting long, we need to solder for
making connections robust. However, for trying to build circuit first time, or
for learning, we should first start with breadboards. Before the modern
breadboards came into existence, the electronic circuit connections were
made using wires tied between the components, placed on a wooden board
similar to the one for cutting bread. Hence, the name of such a circuit board
has become breadboard. Even though the circuit board technology has
evolved much since then, the name “breadboard” was carried forward.

Figure 41: Breadboard – 400 Tie Points

The Breadboard shown in Figure 41 has 400 tie points consisting of 300
tie points on one terminal strip and 100 tie points on two distribution strips.
The dimension of this Breadboard is 3.2”x2.1”. There are other models of the
Breadboards available with a higher number of tie points per terminal strips
and multiple terminal strips and distribution strips. Nevertheless, the 400 tie
points should be good enough for a beginner to start with smaller circuits.
The layout of a 400-tie point Breadboard is shown in Figure 42. There are
two columns of connections on each side along the longer length of the
Breadboard. One column of tie-points is marked with “+’ and the other
column is marked with “-“. All the tie-points in a column, marked with “+”
are internally electrically connected. The same is for the tie-points marked
with “-“. The tie-points connected are shown in Figure 42 by the lines drawn
through them. Each of these “+” and “-” columns are made out of one single
metal strip. This connection is hidden inside the plastic cover and appear as
separate points. Therefore, all the “+” tie points are electrically shorted. The
same applies to the “-” tie-points. These two columns of tie-points are meant
for connecting the voltage rails for supplying the power needed for the
circuit. For example, connect 5V to “+” and GND to “-“. If we need another
voltage such as 3.3V, we need to use the other power distribution strip.

Figure 42: Layout Of A 400 Tie Point Bread Board

The terminal strips in the middle are arranged in rows. Each row of a 400-
point breadboard has two separate strips. In each of the thirty rows, five tie-
points marked as ‘a’, ‘b’, ‘c’, ‘d’ and ‘e’ are electrically shorted as these
points are made out of a single metal strip. The same is true for the other five
tie-points marked as ‘f’, ‘g’, ‘h’, ‘i’ and ‘j’. Each of these five tie-points in a
row marked with letters a-to-e or f-to-j can be imagined as a circuit node
where the wires are connected. In Figure 43, a circuit node is replicated on
the breadboard. In this circuit node, one terminal each of the three
pushbuttons are connected to the positive terminal of the 9V battery. As
shown in Figure 43, the row 10, tie-points a-to-e replicates the same circuit
node as shown by the orange coloured wire on the circuit on the left side.

Figure 43: Demonstrating A Circuit Node Formation On Breadboard

Now, let us see how we should come up with our circuit on the
breadboard. Let us get ahead with a simple circuit shown in Figure 44. A
push-button and a resistor form an input circuit such that when the button is
pressed, the pin D10 of Arduino® UNO will be pulled LOW. The signal
remains HIGH when the button is not pressed. The code running in Arduino®
detects a LOW signal on D10, when the button is pressed and drives the pin
D7 LOW to turn on the LED connected to the same pin.
In Figure 44, each piece of the wires indicates a circuit node. The wires
are electrically shorted together in each node. For example, the wire between
the 5V and the two resistors denotes the “5V” node. The wire connected from
the push button to the GND pin on Arduino® indicates the “GND” (Ground)
node. The input is connected from the node where the 10K ohm resistor and
the push-button are connected. This wire is connected to D10 of the
Arduino® UNO. The wire from the D7 pin of Arduino® is the output node
which drives the LED.
Figure 44: A simple Input & Output Circuit Using Arduino UNO

Now, let us look up to a useful online tool for constructing virtual


breadboard circuits. We could draw the circuit, write the code for Arduino®
and simulate using this tool, to verify if our circuit connections and program
work. To access the tool, we need to visit the web page
https://www.tinkercad.com/. To start using the tools available on this website,
we need to create an account, which is free. After we complete the
registration process and log in to the website using our credentials, we will be
able to access the tools as “3D Designs”, “Circuits” and “Codeblocks”. We
need to launch the “Circuits” tool to construct our breadboard circuit
connections. As shown in Figure 45, we will find the tabs for the online tools
available on tinkercad.com webpage after logging in. We need to select the
“Circuits” tab and then click on “Create new Circuit” tab for creating a new
circuit.
After we click on “Create new Circuit”, a new webpage will open, as
shown in Figure 46. On the right side of this page, we would find a pull-down
menu. If we select “Components: Basics” as shown in Figure 46, we will find
breadboard, Arduino® UNO and several other essential components for
building our circuit. It is also straightforward to build our circuit as we could
just click on the component on the panel on the right side of the window for
adding the same to our circuit. By just clicking on a tie-point on the
breadboard or the terminal of a component, we could add wire. We could also
change the colour of wire, as shown in Figure 46.

Figure 45: Tools Available In tinkercad.com

Figure 46: Starting A New Wiring Diagram In The “Circuits” Tool On Tinkercad

With this overview, let us get on building the circuit described in Figure
44, using the virtual breadboard, Arduino® UNO. Once the breadboard circuit
is completed, the simulation could be the next step provided we have a
working code. There are two main options available for coding: either we
could code using the supported programming languages, or we could use
“Code Blocks”. For a new programmer, the “Code Blocks” option is helpful.
However, beginners should be encouraged to pick up the programming
language instead of using the graphical programming blocks. Coding using a
language would be much more flexible, compact, and we will get many
reference codes available on the net, for us to get started. Figure 47 shows the
coding example using “Blocks”. As shown in Figure 48, if we click on the
“Code” tab on the toolbar, the code window will open. Here, we could type
our code or copy and paste a working code.

Figure 47: Coding Using Code Blocks

After we complete drawing our circuit and adding code, we would click
on the “Start Simulation” button to simulate what we have just built. Once we
simulate our circuit successfully, we should be able to replicate the same on
the breadboard physically, and it should work. If our simulation does not
show expected results, we need debug. Remember that the issue could be
there in the code or the circuit connection. Hence we need to simplify our
circuit first, to check if the basics are working. Debugging is a step-by-step
process of simplifying a complex circuit or code, into a very basic one. We
need to make the minimum features work and then, would continue adding
changes one at a time while checking in each step unless the bug is found.
We need to continue the incremental change and test to reach our desired
circuit configuration.
Figure 48: Adding The Code For This Project

Figure 50 shows the simulated wiring of the circuit that was described in
Figure 44. The working code for this circuit is shown in Figure 49. We will
learn about coding in the next few chapters, but the readers could always try
this out in the code section of the tool along with the breadboard circuit to
simulate the connections.

Figure 49: Working Code For the Push-Button and LED Circuit
Figure 50: Breadboard Wiring Diagram Of the Push-Button and LED circuit
CHAPTER 10
Getting Started with Programming

o far, what we have learned is commonly called “hardware”. Next, what


S we will learn is more like software, but commonly known as “embedded
software” or “firmware”. In simple terms, the program or the code we
write for the Arduino® UNO board or similar microcontroller boards will be
“tightly linked” to the particular hardware. That means, if we change the
hardware platform, the same “firmware” code might not work with the new
microcontroller. Hence the firmware does not have “portability” as it is
dependent on a particular microcontroller hardware architecture. Because of
its close association to the hardware platform, the program for the
microcontroller is known as “firmware”.
To write the firmware code for Arduino® UNO and to be able to
download the same into the microcontroller on the Arduino® board, we need
to have a development and programming tool, which is a software that runs
on our PC. The programming software is called Arduino® IDE and
comprehensive instructions for installing this software on Windows, Linux
and Mac computers can be found at the Arduino® website www.arduino.cc.
The full form of IDE is Integrated Development Environment. It is called so,
as this software tool has several components integrated for the developers to
write the code, compile, upload to the hardware. It is also possible to debug
our code to some extent by monitoring what is going in the hardware using
the “serial monitor” tool.
In this book, I have shown all the illustrations based on the Arduino®
software running on the Windows PC. After installing the latest version of
Arduino® software in the PC, we need to launch the software by double-
clicking on the Arduino® icon on the desktop. The Arduino® software
window will appear like it is shown in Figure 51. The codes written for the
Arduino® are referred to as “sketches”. The graphical user interface (GUI) is
very well designed to present a more straightforward layout compared to
other microcontroller programming software tools I have experienced. It has
five menus on the top as encircled in Figure 51. Just below these menus,
there are five buttons. The button with a “tick mark” is for verifying and
compiling the code written. In case any errors are detected by the compiler
tool, the messages will be displayed on the log window shown with the black
background in the code window. The next button with an “arrow” pointing
towards the right, is for compiling the code and uploading the programming
image to the Arduino® board connected to the COM port (using a USB cable)
of your PC. We will come across these functions again as we get on. The first
thing we are going to do is to upload an example program that comes with the
default installation of the Arduino® IDE.

Figure 51: Arduino Software Window

The first step would be to connect the Arduino® UNO or a compatible


board such as Seeed Studio Lotus board to the PC, in which we have installed
Arduino® IDE. The procedure is pretty simple, as we just need to use an
appropriate USB cable to connect the Arduino® UNO board to the PC. As
soon as we connect the USB cable, we would see the Power LED on the
board turns on GREEN. We might also see that the built-in LED marked with
“L” is flashing ON and OFF alternately. The Arduino® UNO board usually
comes with the “LED blink” program programmed into its FLASH memory.
We will flash12 it again, and then we will try to modify the code and iterate a
couple of times more to observe the change in the LED blink pattern.

Figure 52: Opening The Example Codes

To open the example “Blink” code that comes with the Arduino® IDE
installation, click on File → Examples → 01.Basic and there we will find the
“Blink” code. It could also be observed that other folder containing the
example code such as “02.Digital”, “03.Analog,” “04.Communication”,
“05.Control”, “06.Sensors”, “07.Display” and so on are also made available
for us to explore. We will use some of those sketches in the subsequent
chapters.

Figure 53: Example “Blink” Code

After we click on the “Blink” code, as shown in Figure 52, another


window will pop up launching the “Blink” code. The code that we would see
is displayed in Figure 53. An Arduino® sketch has two blocks – setup() and
loop(). These are built-in functions. After the Arduino® is powered on or
reset, the code enclosed within the setup() block runs only once. On the other
hand, the code enclosed in the loop() function repeatedly runs forever till
the Arduino® remains powered ON. The setup() block is meant for the code
to configure the internal registers of the microcontroller, to set the IO port
pins, to configure ADC or Timers or to configure serial communication
parameters such as baud-rate. Usually, we will do this configuration only
once at the beginning of program execution. In the “Blink” code example.
The following function is the only line of code kept inside the setup()
function. This function sets the Arduino® pin D13 (used as a variable having
a name “LED_BUILTIN”) as an OUTPUT:

pinMode(LED_BUILTIN, OUTPUT);

In the loop() block, the sequence of code shown is repeated in an endless


loop. We could visualize this loop like it is shown in Figure 6. One such loop
is one “scan cycle”. The function digitalWrite() writes values HIGH (logic
‘1’) and LOW (logic ‘0’) to the variable “LED_BUILTIN” (Arduino® UNO
pin D13) alternatively. The other function delay() provides a delay in terms
of ms. In the current program, delay(1000) allows ∼1second of the time delay
between the execution of two consecutive statements. If the readers are not
familiar with the term “function”, not to worry. We will discuss this briefly
later in this chapter.

Figure 54: Selecting The Arduino Board


Next, we will set the board in the Arduino® IDE tool and will connect to
it through the serial port of the Arduino® UNO board as shown in Figure 54
and Figure 55 using the Tool → Board and then Tool → Port menus
respectively.

Figure 55: Configuring The Port To Which Arduino Board is Connected


Figure 56: Getting Board Information

After the connection from the PC to the Arduino® UNO board is


established, we could check if the Arduino® board is connected. Just click on
Tools → Get Board Info. A similar message like it is shown in Figure 57 will
pop-up provided the connection is successful. Different boards might have
different values. If this happens, then congratulations! If it does not appear,
no worries, we might need to check if the driver is installed correctly by
going to the Windows Device Manager menu or need to change the USB
cable.
Figure 57: Board Information Displayed

Once the connection is established, we are ready to download the “Blink”


code. We need to click on the upload button on the taskbar on the top,
marked with an arrow pointing towards the right. The Arduino® IDE tool will
start compiling the sketch. Once the compilation process completes without
any errors, the software tool will upload the program into the Arduino® UNO
board serially over the USB port of the PC and the USB to UART converter
chip on the Arduino® UNO board. After the upload process is completed, a
message will be displayed on the bottom left of the Arduino® IDE window
saying “Done uploading”, as shown in Figure 59. Please note that, as
mentioned in the comment section in the “Blink” code, the same sketch will
also work for the other Arduino® boards such as Arduino® MEGA or
Arduino® ZERO. For MEGA, the “LED_BUILTIN” variable is set to the
digital pin D13 as like UNO. For the MKR1000 or MKR1010, the
“LED_BUILTIN” is set to the digital pin D6, to with the built-in LED is
connected. Hence if we use any of these boards, the same code will work.
Figure 58: Upload The Program Into Arduino UNO Board

Next, we will make a small change in the “Blink” code. In the default
sketch, the value of the delay() function is set as 1000, which is in a
millisecond. We will change this value to 200 in both the places in the sketch.
This change would alter the delay between successive OFF and ON from 1
second to “0.2 seconds”. With this change we expect to see the LED to blink
at a faster rate, isn’t it? After we make the change, as shown in Figure 60, we
need to save the change by going to File → Save menu. Next, we need to
compile and upload the sketch by hitting the “Upload” button. We could also
use the Sketch → Upload menu. After the Arduino® software compiles our
code and uploads the program into the Arduino® UNO board, we would then
see the LED blinking at a faster rate.

Figure 59: Completion of Uploading


Figure 60: Change Delay Value to 200

We could play with the values further, but as we have progressed so far,
we are now all set to start building our code. However, before we go ahead,
let us get ourselves familiar with some of the C/C++ terminologies.
In this book, as I have focused on proving an overview on each of the
topics that could enable the beginners to start their learning journey into the
world of electronics, open-source microcontroller boards and programming
using Arduino®. The programming languages such as C or C++, used for
developing the embedded program for a microcontroller would be an
advanced and a vast topic. In this chapter, I will not be able to cover all
concepts of the programming language. Nevertheless, nothing should
discourage the readers from picking-up on some of the terminologies or
concepts on this topic if the readers are interested. The idea to be highlighted
again: to start our journey, we will not need to know all the concepts of the
programming language right at the beginning. As many resources are
available online, we could always re-use many of the codes written by
various people for different devices and could just tweak the code a little to
make our gadget. In the following section, some of the useful concepts and
terminologies of the programming languages used for Arduino® are
introduced. If the readers need to refer to the complete Language Reference,
they would need to visit: https://www.arduino.cc/reference/en/.
Sketch: In Arduino® community language, one complete code for
Arduino® is called a “sketch”. This file gets saved in the hard drive with a
“.ino” extension. We could also open this file in Notepad++ (a good editor
for writing or viewing codes, available free of cost). An Arduino® sketch
contains two built-in functions: setup() and loop(). These two are the main
elements of any Arduino® code.
Syntax: The exact style following which the code shall be written is called
syntax. We must follow the syntax; otherwise, the compiler will throw errors.
Please remember that the languages such as C or C++ are case sensitive;
hence we need to use the exact case for the keywords or variables.
Semicolon: It is essential to note that “;” is used to end a statement.
Forgetting to end a line with a semicolon will result in a compiler error.
Constant: Constants are predefined expressions or values in the Arduino®
language. A few of the constants are listed below.

Constant Description
Name
true The equivalent of logic ‘1’.
false The equivalent of logic ‘0’.
HIGH Digital signal level of an input or output pin. When a
pin is configured to OUTPUT with pinMode(), and set
to HIGH with digitalWrite(), the pin is at 5V for
Arduino® UNO.
LOW When a pin is configured to OUTPUT with pinMode()
and set to LOW with digitalWrite(), the pin is at 0
volts.
INPUT A pin can be configured as an input using the
pinMode() function such as:
const int buttonPin = 2;

pinMode(buttonPin, INPUT);
INPUT_PULLUP The ATmega microcontroller on the Arduino® has
internal pull-up resistors that we can access. If we use
internal pull-up resistors, we could use the
INPUT_PULLUP argument in pinMode().
OUTPUT A pin can be configured as an output using the
pinMode() function such as:
pinMode(LED_BUILTIN, OUTPUT);
LED_BUILTIN The constant LED_BUILTIN is the number of the pin
to which the on-board LED is connected. The UNO
board has this LED connected to digital pin 13.

Variable: A variable is a name assigned for a data as a “place holder” so


that you could use the name of the variable in your code. A variable is
required to be declared as:

datatype <variable_name> = <variable_value>;

Datatype: It is used to declare what type of data (integer, character,


floating-point or Boolean) a variable can store. There are about 18 datatypes
in the Arduino® programming language. However, we will introduce only the
most commonly used ones here.
Datatype “int”: When a variable is declared of “int” type, it can store
integer values (not having fraction or decimal part). The integer type of
numbers will have range -32,768 to 32,767 (16-bit or 2-byte value).

int count = 50;

Datatype “char”: When a variable is declared of “char” type, it can store


characters such as ‘A’, ‘Z’, ‘t’, ‘%’, ‘*’. To be noted: we need to include a
character within single quotes for assigning the same to a variable like it is
shown below:

char a = ‘A’;

Datatype “float”: When a variable is declared of “float” type, it can store


decimal values, which consumes 32-bits or 4-bytes in the memory. The float
type of variables has a higher resolution compared to int type and hence more
used for analog type data such as temperature reading, weight and likewise.
float f1, f2 = 14.52;

Comment: Commenting on the code is a good practice. It helps others to


understand what a piece of code does, by going through the comments
quickly. If the comment contains multiple lines, we need to use “/*” and “*/”
to enclose the entire block of the comment. This is called “block
commenting”. In case we need to comment on a single line, we could also
use “//” at the beginning.
Array: An array is a collection of variables having the same datatypes.
The elements of an array could be accessed using the corresponding index or
position of the element in the array. The first element of the array always has
index = 0. An integer array could be declared as:

int myArray[4];
int myArray[]={21,32,43,54};

In the above array, myArray[2] will contain 43.


An example of a char type array could be:

char myName[6]= “Sanjib”;

In the above example, myName[0] will have ‘S’ stored in it.


#include<>: Any library file that might be used in the sketch shall be
included using #include statement. For example, the header file “Wire.h” is
needed to be inclusive when we want to use I2C port pins. We shall need to
include that library at the very beginning of the sketch, as shown below:

#include <Wire.h>

void setup(){

}
void loop(){

}

If the library file is placed in the same project folder (e.g. for a custom
library), we could also use double quotes (““) in place of (<>) and include the
name of the file in double-quotes. Then, the compiler finds the library file in
the project folder and does not take this from the default search path for the
Arduino® libraries.
#define: This is a directive for the compiler for defining a constant so that
the compiler uses the same during compilation. That constant does not
occupy any space in the memory.
Function: In straightforward terms, a function defines a reusable code-
block, which can be used in the same or the other sketches or functions. We
are going to use functions a lot in the following examples illustrated in the
following chapters. Writing a custom function might be tough for a beginner,
but using the function available in the library would make things easier for
us. Hence let us focus on using the built-in functions instead of trying to write
our function for now. We would get a complete list of available functions in
the official Arduino® webpage: https://www.arduino.cc/reference/en/.
However, let us get ourselves familiar about the syntax of a function and the
syntaxes for calling a function in our code:

Return_type function_name (argument1, argument2,…)


{
Statement1;
Statement2;
.
.
.
}

As shown above, a function shall have a name. The arguments are the
parameter values that should optionally be passed into the function. The
“Return_type” is the data type of the variable returned by the function. If the
function does not return any value, it should be written as “void”. For
example, for the Arduino® built-in functions, we need to write “void setup()”.
Within the “{ }” the function statements shall be written.
To call a function, when it does not return a value, we just need to write:

myFunction(<value1>, <value2>); // value1,2 should be the values of


the arguments

To call a function, when it does return a value – suppose an integer value,


we should write:

funcVal = myFunction(<value1>, <value2>); //funcVal is int type


variable

The variable funcVal should also be a “int” type variable above.


Arithmetic operations: All basic arithmetic operations such as addition,
subtraction, multiplication, division, reminder can be performed on integer,
float type of variables. The syntaxes for the operations are as below:
Addition: ‘+’; Subtraction: ‘-‘; Multiplication: ‘*’; Division: ‘/’;
Reminder or Modulo: ‘%’.

int x=12;
int y=4;
int a,s,m,d,r;
a = x + y; //result: a = 16
s = x – y; //result: s = 8
m = x * y; //result: m = 48
d = x / y; //result: d = 3; denominator MUST be a NON ZERO value
r = x % y; //result: r = 0
Comparison operations: These operations compare two variable and
return “true” or “false” if the relation holds or false, respectively. The
examples in the table below assume A = 5, B = 10.

Operator Syntax Description Example


Name
Equal to == Checks if the left operand is equal (A==B) is
to the right operand false
Not equal != Checks if the left operand is not (A!=B) is
to equal to the right operand true
Less than < Checks if the left operand is less (A<B) is
than the right operand true
Greater > Checks if the left operand is higher (A>B) is
than than the right operand false
Less than <= Checks if the left operand is less (A<=B) is
or equal to than or equal to the right operand true
Greater >= Checks if the left operand is greater (A>=B) is
than or than or equal to the right operand false
equal to
Table 27: Comparison Operators

Boolean or Logical Operators: The following Boolean operators are


supported.

Operator Syntax Description Example


Name
Logical ! Logical NOT of expression if (!x) {
NOT is TRUE is the result of the
expression is false. In the //statements
example, the statements }
inside if block are executed
if x is false.
Logical && If both operands are true, if ((A==5) &&
AND Logical AND results in (B==10))
true. For example, if A=5, { //statements
B=10, then the statements
inside the if block shown in }
the example are executed.
Logical || If either of the two operands if ((A==9) &&
OR are true, Logical OR results (B==10))
in true. For example, if { //statements
A=5, B=10, then the
statements inside the if }
block shown in the example
are executed.
Table 28: Boolean Operators

Control Statements: The control statements such as “if”, “for”, “while”


check an expression for a particular condition and execute a set of statements
if the condition is met. Few of the commonly used control statements are
shown in Table 29.

Control Syntax Description


Statement
if if (condition) { The if statement checks for a
condition and executes the
//statements; proceeding statement or set of
} statements if the condition is ‘true’.
for for The for statement is used to repeat a
(initialization; block of statements enclosed in
condition; curly braces till the condition is
increment) { met. An increment counter is
usually used to increment and
// statement(s); terminate the loop. The counter is
} needed to be initialized first.
if…else if (condition1) { An else clause (if at all exists) will
be executed if the condition in the if
// do Thing A statement results in false.
}
else if
(condition2) {
// do Thing B
}
else {
// do Thing C
}

while while The statements inside the while


(condition) { loop get repeated continuously, and
infinitely, until the expression
// statement(s) inside the parenthesis, () becomes
} false.
Table 29: Control Statements

12 Usually the term “flashing” is commonly used to mean “programming the flash memory” in short.
CHAPTER 11
Analog Input

s we have now learned how we could upload the program image into
A the Arduino® and have seen it running on the Arduino® UNO board,
hopefully, my readers might have now gathered courage for venturing
into coding all by themselves. As we have discussed in Chapter 10, there are
two main blocks setup() and loop() where we are going to include our code.

Figure 61: Where To Get the Sketch Template From

To start with, we could get the empty code template from the menu File
→ Examples → 01.Basics → BareMinimum as it is shown in Figure 61. The
“BareMinimum” code is an Arduino® code template, as shown in Figure 62.
As like in the “Blink” code, the setup() and loop() functions are in this code
template, but those are left blank. We need to add our code there.
In this chapter, we will read an Analog Input. There is a function for
reading an analog input already made available in the Arduino® library. The
function is analogRead(). This function reads the analog voltage value in the
range 0-5V and returns a count value between 0 to 1023. Now, from where
does this number 1023 appear? In Chapter 6, we have seen that the resolution
of the ADC inside ATmega328 microcontroller is 10-bit. That means, the
ADC converts its entire input range into 0 to (210-1) = 1023 counts. For 2.5V,
this function will return 2.5*1023/5 = 512. The argument for this function is
the pin name of the corresponding analog input, which is being read. For
Arduino® UNO, the argument for this function could be any one of A0 to A5.
We need to write a line of code below to read the analog voltage connected to
pin A0:

analogVal = analogRead(A0);
Figure 62: BareMinimum Code Template

Note that analogVal is a “variable” declared in the code. As the function


returns the count corresponding to the analog voltage on A0, which is an
integer data type, the variable analogVal also holds ‘int’ data type. Hence
analogVal is declared as “int” type. We would find more details about this
function on the official website of Arduino®:
https://www.arduino.cc/reference/en/#functions
Things are made easier for us, as there is an example code provided with
the Arduino® IDE installation. To find the example code for analog input
read, you need to go to File → Examples → 01.Basics → AnalogReadSerial,
as shown in Figure 63.

Figure 63: The Example AnalogReadSerial for Reading an Analog Input

The “AnalogReadSerial” code is shown in Figure 64. The code reads the
analog voltage signal connected to the Arduino® analog input A0 every one
millisecond and stores the value in a variable called “sensorValue”. The same
variable is sent to the PC through the serial port of Arduino®, which could be
displayed on the “serial monitor” tool built-in to the Arduino® IDE tool. The
Serial Monitor tool pops up as a separate window, that acts as a serial
interface terminal. This tool is a “User Interface” for receiving and sending
serial data to the connected Arduino® board. The Serial Monitor tool sends or
receives data on the same COM port of the PC, to which the Arduino® UNO
board is connected. The Serial Monitor often serves as a great debugging tool
while debugging an issue.

Figure 64: AnalogReadSerial Code

Coming back to the code shown in Figure 64, the AnalogReadSerial code
uses the functions described in Table 30:

Functions Description
Serial.begin() Sets the data rate in bits per second (baud) for serial data
transmission. In this code, baud is set as 9600 bits/second.
Serial.println() Prints data to the serial port as human-readable ASCII text
followed by a carriage return character (ASCII 13, or ‘\r’)
and a newline character (ASCII 10, or ‘\n’). In this code,
the value contained by the variable sensorValue is written
in a new line on the Serial Monitor console every time this
function is executed.
analogRead() Reads the value from the specified analog pin. In this
code, this function reads the analog voltage on the
Arduino® pin A0.
delay() Pauses the program for the amount of time (in
milliseconds) specified as the parameter. In this code,
after the program reads the value and sends the value
serially to the PC, it pauses for one millisecond before it
does it again.
Table 30: Functions Used in AnalogReadSerial Code

We could test this code by making a simple circuit. For this circuit, we
need a variable resistor or potentiometer.

Figure 65: Connecting A 10K Potentiometer To Arduino® Board

A potentiometer or a trimpot (short form of trimmer potentiometer), is a


variable resistor. A trimpot has three leads. The resistance between the two
end leads is fixed. The resistance between the middle lead and any of the two
end leads is variable, which could be changed by turning the adjustment
screw or nob. The adjustment screw for the middle lead is also referred to as
“wiper”. If we connect the 10K trimpot, as shown in Figure 65, the middle
lead connected to A0 will provide a variable voltage between 0V to 5V
depending on the position of the nob.
Figure 66: The Analog Voltage On A0 is Displayed on The Serial Monitor

In Figure 66, the screenshot of the serial monitor readings is captured for
the set-up described. Based on a preset position of the trimpot’s wiper, the
Arduino® UNO board in the set-up reads 370 counts at the start. When the
wiper nob or screw is rotated, the value changes to 230. This count values
could be converted into voltage as (370*5)/1023 = 1.8V or (230*5)/1023 =
1.12V. Using a multimeter, we could measure the voltage of the signal
connected to the A0 pin with reference to the GND.
Let us experiment with another example code that is made available with
the Arduino® IDE installation. We could get this code from File → Examples
→ 01.Basic → ReadAnalogVoltage. In this code an additional line of code is
added to convert the count into voltage:

float voltage = sensorValue * (5.0 / 1023.0);

Note that, the variable “voltage” is declared as float datatype. This is


because the variable “voltage” could contain decimal values. Once this
program is uploaded in the same set-up, we would see that the Arduino®
UNO board is actually sending the voltage readings and not counts anymore.
If we keep on rotating the nob to the extreme ends, we will read either 0
counts or 1023 counts depending on whether we hit the 0V end of the 5V
end. This entire range is called “Full-Scale Range” or FS range in short.

Figure 67: The Change Of Analog Voltage On A0 Being Reflected On The Serial Monitor

In the snapshot captured in Figure 67, it could be seen that the wiper
screw of the potentiometer is rotated quickly to the two extreme ends and the
maximum and minimum counts 1023 and 0 are read by the Arduino® and
send serially to the serial monitor console.
Now, suppose, we need to read two sensor inputs. You could improvise
very easily. We need to assign two sensor values to two variables, as shown
below or in Figure 68.

int sensor1Value = analogRead(A0);


int sensor2Value = analogRead(A1);

The code is modified by assigning the count value of A0 to sensor1Value


and the count value of A1 to sensor2Value. The Serial.print() function could
be used to print the sensor1Value and sensor2Value with a tab in between.
Please note that Serial.print(“\t”) prints a tab and Serial.print(“\n”) prints a
new line.
Figure 68: Reading Two Sensor Inputs

So far, we have learned about the functions for:

Reading analog input (ADC sub-system)


Pausing or delaying using a timer (delay() function uses Timer0)
Sending the data serially to the PC (UART/USART)
Driving a digital output (“Blink” code)

As discussed in Chapter 6, we could also use analogReference() function


to select the internal 1.1V signal to deal with a signal that can have voltage,
not more than 1.1V. Alternatively, we could even use an external reference
voltage as a reference.
Well, we are making good progress. One thing we have not seen –
reading a digital input. However, I would leave it for my readers to explore.
We need to use pinMode() function to configure a digital pin as input and
would need to use digitalRead() function to read the signal on the pin. Unlike
analogRead(), you would read either HIGH (‘1’) or LOW (‘0’) using
digitalRead(). I would encourage my readers to learn about these functions
from the website:
https://www.arduino.cc/reference/en/#functions
CHAPTER 12
Analog Output using PWM

s an ADC converts an analog signal to its digital form, the opposite -


A digital to analog convertion is performed by a DAC. For a digital
system, ADC is an input device, whereas a DAC is an output device.
However, the microcontroller ATmega328P on the Arduino® UNO does not
have any DAC built-in. Instead, we could use the Pulse Width Modulation or
PWM feature of the microcontroller to produce an analog signal from digital
codes formed using integer type values in the range 0 to 255. Put simply, for
a repeated ON-OFF pulse-train signal, when we could control the ON time,
keeping the time-period (total ON+OFF time) unchanged, the technique is
called Pulse Width Modulation or PWM.
The term Duty Cycle specifies what percentage of the Time-period, the
pulse remains ON. Hence, Duty Cycle = 0% means, the signal is never ON.
That is, the signal is LOW all the time. If the Duty Cycle = 100%, the signal
is always ON, that is the signal is always HIGH (5V for Arduino® UNO).
When the Duty Cycle is 50%, the signal is ON 50% of the time and OFF 50%
of the time. Therefore, the ON time and OFF time is equal for 50% Duty
Cycle. Now, if we average the pulse train over time, we will get a DC signal,
which will be proportional to the Duty Cycle of the PWM. Therefore, PWM
is a technique, which can be applied to generate an analog signal from a
digital value.
There is a built-in function analogWrite(), which generates a PWM
signal. We could pass an integer value between 0 to 255 to this function. As
shown in Figure 69, if we pass 0 to analogWrite() function, the Duty Cycle
will be 0%, and the signal will be LOW all the time. If we pass 255 to
analogWrite() function, the Duty Cycle will be 100%, and the signal will be
HIGH all the time. Similarly, if we pass 127 to analogWrite() function, Duty
Cycle will be 50%, and the average voltage signal will be midway between
HIGH and LOW (approximately 2.5V at the Arduino® UNO pin). Likewise,
analogWrite(64) will generate a pulse train, the average of which will be
∼25% of 5V for Arduino® UNO, i.e. 1.25V and analogWrite(191) will
generate a pulse train, the average of which will be ∼75% or 5V for Arduino®
UNO, i.e. 3.75V.

Figure 69: PWM Signal, Duty Cycle and analogWrite() Function

We will now try this out on the Arduino® UNO board. For this
experiment, we need one LED and a resistor of value, say 220 ohms. Connect
the resistor and the LED in series and connect the LED be-tween digital
output pin D9 and GND. Note that, we need to connect the LED in the
correct direction such that cathode of the LED is connected to GND, as
shown in Figure 30. If we take a leaded LED (Through-hole type), the
Cathode (-) lead will be smaller in length compared to the anode (-) lead, and
the LED case will be marked with a flat edge on the cathode side as shown in
Figure 70.
Once we are ready with the circuit, let us focus on the code. Here again,
the reference code is available for us to get started. Open File → Examples
→ 03.Analog → Fading as shown in Figure 71. This code “fades” an LED in
and out alternatively using the PWM signal generated by analogWrite()
function.

Figure 70: Identifying LED Cathode and Anode


Figure 71: analogWrite() example: Example Code “Fading”

The “Fading” example code, shown in Figure 72, increments a variable


fadeValue in steps of 5 from 0 to 255 inside a for() loop. For every
increment, a 30ms delay is used. Once the fadeValue reaches 255, using
another for() loop, the fadeValue is decremented in steps of 5 till the value
reaches 0. Again between two subsequent decrement steps, a 30ms delay is
used. I changed this delay to 60ms in both places as that gives a good pace of
dimming, 30ms was a bit fast for me. This variable fadeValue is passed into
the function analogWrite() to drive the PWM output to the ledPin, which is
the variable name declared for the Arduino® output D9.
Figure 72: LED Fading Example Code

Next, we need to compile the code and upload the same into the Arduino®
UNO board. Once the upload is successful, we will see the LED connected to
D9 is fading in and out alternatively. Isn’t it fun? We could add more fun to
this project by fading multiple colour LEDs alternatively using multiple
PWM outputs. By reusing the “Fading” code, the code for fading the multiple
LEDs could be written.
Thus far, you might have developed an inquisitiveness for exploring
coding a bit further. Maybe, I could help you with a problem statement,
which you would want to solve. In the previous chapter, you have seen how
you could read an analog input voltage, which could be varied in the range 0-
5V using a potentiometer. In this chapter, we have explored how to use PWM
outputs to control its brightness of LEDs or simply dimming LEDs. Now,
could you control dimming an LED using a potentiometer connected to A0
pin of Arduino®? More specifically, if the wiper nob is turned clockwise, the
brightness of the LED should increase, and if the nob is turned anti-
clockwise, the LED’s brightness should reduce as the nob is turned and
would turn-off. I am sure you can do it13.

13 Hint: Read the potentiometer input as in analog input signal and drive the PWM output
proportional to the same. Take a look at the example: File → Examples → 03.Analog →
AnalogInOutSerial
CHAPTER 13
Writing Code for LCD Display

n chapter 8, we have seen an example of displaying a message on a 16x2


I character LCD. This type of LCD with a parallel data interface is
commonly used as a small display. Another type of LCD is popularly
used, which has an I2C interface instead of eight data lines plus a few control
signals. We will explore both of these two types.
Let us start with the 16x2 LCD, which has 8-bit parallel data interface. In
Figure 73, the interface to the 16x2 LCD using a parallel data interface is
shown. All of the eight data bits DB0 to DB7 are not used. Instead, only the
four MSBs DB4 to DB7 is used, as shown in Table 31.

Figure 73: 16x2 LCD Display Interface With Arduino

LCD PIN Arduino® FUNCTION


UNO PIN
GND GND Ground or 0V.
VCC 5V 5V sourced from Arduino® UNO.
V0 A voltage in Use a 10K potentiometer or variable
between 5V resistor. Connect 5V and GND to both ends
and 0V and connect the middle lead (wiper) to V0
pin of the LCD.
RS D12 Register Select: When this signal is:
LOW – Command Register selected
HIGH – Data Register selected
RW GND Read/Write: When this signal is:
LOW – Write to the register
HIGH – Read from the register
In this case, it is tied to GND (LOW).
EN D11 Enable signal: When HIGH, instruction is
executed.
DB0 to DB3 Not Four LSBs of the 8-bit Databus; Not
Connected connected in this configuration.
DB4 D5 Data pin#4 of LCD is connected to
Arduino® UNO’s DIO pin D5
DB5 D4 Data pin#5 of LCD is connected to
Arduino® UNO’s DIO pin D4
DB6 D3 Data pin#6 of LCD is connected to
Arduino® UNO’s DIO pin D3
DB7 D2 Data pin#7 of LCD is connected to
Arduino® UNO’s DIO pin D2
LED+ 5V (through Anode of the backlight LED. Should be
a 220-ohm connected to 5V, but through a suitable
resistor) resistor (e.g. 220 ohms) to limit the current.
LED- GND The cathode of the backlight LED.
Table 31: Pin Mapping Between 16x2 LCD Display and Arduino UNO

The connections between the LCD and Arduino® UNO could be made
using a breadboard, jumper wires, one 10K potentiometer and a 220-ohm
resistor. Table 32 shows the list of components we would need for this
project. This list of components would help us in getting the required
components handy before we start our project. This kind of component list is
also referred to as a Bill of Material or BoM in hardware engineering. Once
we have the parts, we could complete the breadboard circuit like it is shown
in Figure 73.

Serial Number Component Quantity


1 Arduino® UNO Board 1
2 A 400-tie point Breadboard 1
3 Jumper wires or breadboard wires 20 to 25
4 220-ohm resistor 1
5 10K ohm Potentiometer 1
6 16x2 LCD Display 1
Table 32: Bill of Material Needed for LCD Display Project

After the breadboard connections are made, it is time to write the code in
the Arduino® IDE. Before trying this out on the real hardware, we could
simulate the same in the “Circuits” tool on tinkercad.com. After we open
Arduino® IDE and create a new sketch by clicking File → New as shown in
Figure 74, the new sketch would pop-up in a new window with a default
name. We could save this with a different name. I chose the name as
“myLCD” and saved the sketch with that name. Here again, things are more
straightforward than my readers might be thinking as the libraries are
available. For the 16x2 LCD with an 8-bit or 4-bit parallel interface, we will
use “LiquidCrystal” library. This library is developed for enabling the
Arduino® boards to interface with the LCDs with Hitachi HD44780 (or a
compatible) chipset. To know more about this library and the built-in
functions, we could visit https://www.arduino.cc/en/Reference/LiquidCrystal.
We would refer to the example codes mentioned on the same page to
understand how these functions could be used in the program for developing
similar features into the application.

Figure 74: Creating A New Sketch In Arduino® IDE

To use the LiquidCrystal library, we need to include the library in our


code by writing:

#include <LiquidCrystal.h>

A simple code, displaying two lines of text “BEGIN WITH Arduino®”, is


shown in Figure 75. In the code, we could see several functions are used
which are built into the LiquidCrystal library. The first one is
LiquidCrystal(), which is written as:

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

This function maps the Arduino® UNO pins D12, D11, D5, D4, D3, D2
to the LCD pins RS, EN, DB4, DB5, DB6, DB7 respectively. These
assignments are at par with what is described in Table 31 before. This
function also creates a variable of type “LiquidCrystal” with the name “lcd”.
In other words: “lcd” is a variable, which could contain datatype
“LiquidCrystal”. Please note that this is done outside setup() and loop()
functions. As the functions for driving the LCD are defined inside the
“LiquidCrystal” library, we need to call these functions by adding “lcd.”
before the function name. The functions for initializing the LCD registers and
displaying a message are written inside the setup() function.
We have already have seen that the code written inside setup() is executed
only once. Since we are going to display only one message, it should be okay
to put this code in setup(), and we need not write anything inside loop(). That
is why we are not seeing any code written inside the loop() function in this
example, as shown in Figure 75. Nevertheless, we need to remember to keep
the loop() {} function in our code, even if it is empty to avoid compiler error.
The first function in setup(), lcd.begin(16,2) initializes the LCD display
registers. The next function lcd.setCursor(0,0) sets the cursor at the first
character of the first line on the display. In the next line in the code, the
function lcd.print() prints the text mentioned within the double-quotes. The
following function lcd.setCursor(0,1) shifts the cursor to the first character of
the second line on the display. Lastly, the function lcd.print() prints the text
“Arduino®” in the second line. We could try uploading this code into the
hardware by simulating on tinkercad.com, or we could try this on an
Arduino® UNO hardware if the wiring is made. We will see this message
displayed like it is shown in Figure 73.
Figure 75: Simple Code For Displaying a Text On A 16x2 LCD Display (Parallel Interface)

By making a simple change in the code, we could reposition the message


to the middle of the LCD. We could set the cursor at the first line and fourth
character from the left by writing lcd.setCursor(3,0). Next, set the cursor at
the second line and fifth character from the left by writing lcd.setCursor(4,1).
The message will now be displayed approximately in the middle of the LCD,
as shown in Figure 76.
Figure 76: Displayed Text Shifted To The Middle

The text “BEGIN WITH Arduino®” has 18 characters (includes two


“spaces” too), whereas one line of this LCD has only 16 characters. Thus, we
cannot display the entire string on one line. Nevertheless, there is a function
that could be used to scroll the text to the left so that the entire message could
be visible. This function is lcd.scrollDisplayLeft(), which scrolls the text
displayed to the left by one character. If we write this function inside the
loop() function, the scrolling of characters will get repeated in a loop, and the
entire text displayed will appear to be moving to the left repeatedly. The code
is shown in Figure 77. In this code example, the complete text is now
included in the lcd.print() function. This change prints the text on the first
line of the display. The function lcd.scrollDisplayLeft() is placed in the loop()
function for the scrolling to get repeated. A small delay of 100 milliseconds
is added after the scroll function to control the speed of scrolling. If the
scrolling action is too fast for us, we could always adjust the delay by
increasing it accordingly.
Figure 77: Code For Scrolling The Display To The Left

We could also write a text on the second line and scroll both the lines
together by using the same function lcd.scrollDisplayLeft() as shown in
Figure 78. Once we run this code, both the text messages displayed on both
lines will get scrolled together. Isn’t that easy and fun?
If we want to keep the wiring to the display more straightforward, we
could buy one LCD with the I2C interface. In Figure 79, the Grove LCD with
I2C interface is being driven from an Arduino® UNO compatible Lotus board
from Seeed Technology Co. Ltd. The advantage here is that wiring to the
display becomes much convenient and we have the pluggable connector
wires available. As this Grove display has the I2C interface and this is not the
same as the LCD with the 8-bit parallel display, we need to use a different
library in our code to drive the display from Arduino® UNO or equivalent
board. In Figure 79, I have used the Grove library “rgb_lcd” downloaded
using the Library Manager tool on the Arduino® IDE. We would need to
launch the Library Manager tool by clicking on the Tool → Manage Libraries
menu on the toolbar or by pressing the short key “ctrl + shift + I”, type
“Grove LCD” in the search window. The “Grove – LCD RGB Backlight”
library will appear in the Library Manager window. If it is already installed in
the PC, it will be shown as “installed” (refer Figure 80). If it is not already
installed, we will get the “Install” button for installing the same.
Figure 78: Scrolling Both Lines In The Display

After we install the Grove LCD library, it will appear in the File →
Examples menu as “Grove – LCD RGB Backlight” as shown in Figure 81.
We could then connect the Grove RGB LCD with I2C interface to the
Arduino® UNO or compatible board. We should be able to try out any of the
sketches available in this Grove library. In my set-up shown in Figure 79, I
have slightly modified the “HelloWorld” code to display the message, which
I wanted to get displayed on the LCD. The code used is shown in Figure 82.
Please note that there are two libraries use: Wire and rgb_lcd in this code.
The library “Wire” is used for configuring and working with the I2C interface
on Arduino® UNO. The other library rgb_lcd is similar to the LiquidCrystal
library but meant to work with the “Grove – LCD RGB Backlight” display.
After including the libraries, the following statement: rgb_lcd lcd creates a
variable type “rgb_lcd” assigned with a name “lcd”, very similar to what we
have seen in the parallel display example. As we have seen before, all
function built into the rgb_lcd will now be called with an “lcd.” preceding the
respective function names. In the next three lines of the code, three constants
of “integer” type – colorR, colorG, colorB are declared. These are passed as
parameters later in the function lcd.setRGB() to turn the LCD backlight on.
Thus far, we should already be familiar with the rest of the functions, which
were discussed earlier.
Figure 79: Interfacing Grove 16x2 LCD With Arduino® UNO Compatible Seeed Studio Lotus Board
Using I2C Interface

Figure 80: Installing Grove LCD RGB Backlight Library


Figure 81: Using Grove LCD RGB Backlight Library
Figure 82: Code Used To Display Message On The Grove RGB LCD
CHAPTER 14
Completing the Input-Output Loop

o far, we have either read input or driven an output. Let us now


S implement one complete input to output loop (as depicted in Figure 6)
using the existing sketches available in the installed library or
downloadable using the Library Manager of the Arduino® IDE, so that a
complete product idea emerges.

Figure 83: Temperature And Humidity Indicator Using Arduino Compatible Board

On a hot and humid day, we would certainly like our room to be


maintained cosy, isn’t it? On such a day, I thought of checking the
temperature and the humidity inside my room, which was making me feel
uncomfortable. I have a “Grove Beginner Kit for Arduino”, which comes
with a Grove DHT11 temperature and humidity sensor, an LCD with I2C
interface and a Seeed Studio Lotus board, all that I needed to build a
temperature & humidity monitoring device. The advantage of the Grove
sensors and the Seeed studio Lotus board is that wiring becomes very simple.
We could just use the cable connectors provided with the kit to connect the
sensor to the Arduino® compatible Lotus board, as shown in Figure 83. The
I2C port of the Grove 16x2 LCD is connected to one of the I2C port. The
DHT11 sensor is connected to the port “D2” of the Lotus board.
As the connection was easy and quick with the Grove Beginner kit
components, I started searching for the DHT11 code using the Library
Manager tool available with the Arduino® IDE and the found it by typing
“Grove DHT11” on the search window as shown in Figure 84.

Figure 84: Installing Grove Temperature And Humidity Sensor Library

After this library was installed, I launched the DHTtester sketch by


clicking on the File → Examples → Grove Temperature And Humidity
Sensor → DHTtester menu, as shown in Figure 85. The DHTtester sketch is
an example code for Arduino® boards to read from various DHT humidity
and temperature sensors and to display the values on the Serial Monitor tool
available with the Arduino® IDE.

Figure 85: Launching The DHTtester Code From The Grove Temperature & Humidity Library

The default configuration of this code is meant to work with the DHT22
sensor. The “#define” statement defining “DHTTYPE” as “DHT22” does the
same. The #define statement is a useful C/C++ component that allows the
programmer to assign a name to a constant value before the program is
compiled, which saves on Arduino® memory. As I was using a DHT11
sensor, I needed to make a slight change in this section by commenting out
the #define line for the DHT22 sensor and un-commented the same for the
DHT11 sensor as shown in Figure 87.

Figure 86: Default Configuration Of DHTtester Sketch

With this change, I wanted to try this code on my set-up shown in Figure
83. So, I compiled this code and uploaded the same to the Seeed Studio Lotus
board.

Figure 87: The Code Change Done To Configure The Code To Work with DHT11 Sensor

After the upload was successful, I opened the serial monitor by clicking
on the Tool → Serial Monitor menu. Please note that the Serial Monitor tool
could also be launched by pressing “Ctrl+Shift+M”. Once the Serial Monitor
was open, the temperature and humidity data started getting logged, as shown
in Figure 88. If we do not see any data on the serial monitor tool while trying
this code, we need to ensure the serial data transfer rate (Baud Rate) setting is
correct as 115200 bits/sec as shown in Figure 88. The baud rate configured
on the serial monitor must match the same that is set in the code. We could
find this in the setup() function: the very first line has this function called:

SERIAL.begin(115200);

This line of code configures the serial port data rate as 115200 baud or
bits/second. Hence, we need to set the same value on the Serial Monitor too.

Figure 88: Temperature And Humidity Log On The Serial Monitor Tool

Next, I needed to merge the Grove RGB LCD code with the DHTtester
sketch to display the temperature and humidity data on the Grove LCD
instead of the Serial Monitor tool. First, I renamed the sketch as
“DTH11_LCD”. Then, I included the required library “rgb_lcd.h” for driving
the Grove LCD followed by copying the portion of the code which was
written outside both the setup() and loop() functions. The added lines of
codes are shown in boxes in Figure 89.
As we have seen in the previous chapter, the statement: “rgb_lcd lcd”
creates a variable type rgb_lcd with the name “lcd”. Similarly, the statement:
“DHT dht (DHTPIN, DHTTYPE)” creates a variable type DHT having name
“dht” and initializes it with two constants “DHTPIN” (=2) and DHTTYPE (=
DHT11) so that the functions in the class “DHT” would work correctly with
the DHT11 sensor connected to the pin# D2 of Arduino® UNO. This might
sound complex but trust that we need not know more profound into the
programming language as of yet, for starting with our Arduino® sketches. We
just need to know where to tinker and improvise. That should automatically
help us in our learning journey.
Figure 89: Merging LCD Code With The DHTtester Sketch – Outside SETUP () and LOOP ()
functions

Next step for me was to merge the codes written inside the setup()
function. Again, I copied the portion of the code written inside setup()
function, from my previous LCD display project (refer Chapter 13) and
pasted the same inside the setup() function of the DTH11_LCD sketch. The
changes and inclusions are shown in boxes in Figure 90. The first two lines
were commented out as those were meant to use the serial port driver
functions, and I did not need it anymore. Next, the code to initialize the LCD
and to turn the backlight on was included as shown. The remaining lines of
code already existed in the DHTtester sketch, and I kept those unchanged.

Figure 90: Changes in The Setup() Function

The remaining function loop() was modified next. In the DHTTester


sketch, the temperature and humidity values were sent serially through the
UART port of the Arduino® board. In my project, I chose to display those
values on the LCD connected on the I2C port pins of my Lotus board. Hence,
instead of SERIAL.print() function, I used lcd.print() function to display the
temperature and humidity values on the LCD. Also used the lcd.setCursor()
function to print the relative humidity (RH) value on the first line of the
display and temperature data on the second line. The code changes are shown
in Figure 91.
Inside the loop() function, the temperature and humidity data is read from
the sensor and displayed on the LCD repeatedly. The first statement: float
temp_hum_val[2] = {0}; declares an array of two “float” type variables
temp_hum_val[0] and temp_hum_val[1]. Unlike the integer (“int”) data type,
the floating-point (“float”) data type variables could store numbers having a
decimal point such as “53.28”. The variables having “float” datatypes are
stored as 32 bits (4 bytes) of information. The next statement is a logical “if-
else” statement, which uses the dht.readTempAndHumidity() function to
check if the sensor is online or not. If the sensor is online, it executes the next
set of statements mentioned within the curly bracket pairs after the
conditional “if” statement. If the sensor is offline or there are some issues, the
statements after “if” are skipped. Also, the set of statements within “{ }” next
to “else” statements are executed. In my setup, the Lotus board detected the
Grove DHT11 sensor online and

Figure 91: Changes In The Loop() Function

hence the cursor was set to the first character of the first line by executing
the statement: “lcd.setCursor(0,0);”. The next line of code prints the string
“RH:” starting from the first character of the first line. In the lcd.print()
statement, anything mentioned within double quotes is considered as a
character or a string (collection of characters). The content mentioned within
the double quote is displayed as specified. When the value of a variable is to
be printed, double quotes are not used. Instead, the name of the variable is
mentioned inside the first brackets of the lcd.print() function call. The
statement: “lcd.print(temp_hum_val[0])” does the same. It prints the value of
the float variable temp_hum_val[0], which stores the humidity data read from
the DHT11 sensor. The following statement prints the percentage symbol
“%” as a text. The next set of statements are similar to the statements for
printing the humidity number. These following statements print a text
“Temp:” and then prints the value of the variable temp_hum_val[1] followed
by a string “*C” to indicate degree centigrade.
In the else statement block, the failure condition is included, and that is
executed in case Arduino® fails to communicate with the sensor. It displays a
message that “Failed to get temperature and humidity value”. As the length of
this message is more than 16 characters, the last few characters in this string
will not be displayed. Hence, we could either shorten it or could use
lcd.scrollDisplayLeft() function to scroll the message to display the entire
message.
Outside the “if-else” statement, there are two more statements in the
loop() function block. The delay() function allows a delay between each
reading. In my program, it is 4 seconds, which could be increased further as
the room temperature and humidity do not change significantly that fast. The
lcd.clear() function clears the current data displayed. As all these statements
are executed in the loop() function, the program reads the recent data from
the sensor, display the same on the LCD screen and waits for the delay
repeatedly. After I uploaded this program in my Lotus board, I started getting
the readings on the LCD, as shown in Figure 83.
As it can be seen, it is not that complex to build a complete project using
Arduino® UNO or compatible boards, even if we might not know the
programming language such as C/C++ in depth. As there are so many
resources available online and we would most probably find the library for
the input or output device that we would need to connect with Arduino®
UNO for our project, things are much more straightforward. We need to start
experimenting and indeed, we will pick-up on the language. If we want to
learn more about the syntax and programming languages, we will get many
resources14 online apart from the tutorial provided on the official Arduino®
website: www.arduino.cc. Start building and explore online resources to
continue your learning journey. Wish you all the very best!!

14 I liked the blog: https://technobyte.org/arduino-programming-coding-guide-for-beginners/ for


beginners

You might also like