Asadi F. Essentials of Arduino Boards Programming. Step-By-Step Guide... 2023
Asadi F. Essentials of Arduino Boards Programming. Step-By-Step Guide... 2023
I N N O VAT I O N S
SERIES
Essentials of
Arduino™ Boards
Programming
Step-by-Step Guide to
Master Arduino Boards Hardware
and Software
—
Farzin Asadi
Maker Innovations Series
Jump start your path to discovery with the Apress Maker Innovations
series! From the basics of electricity and components through to the most
advanced options in robotics and Machine Learning, you’ll forge a path to
building ingenious hardware and controlling it with cutting-edge software.
All while gaining new skills and experience with common toolsets you can
take to new projects or even into a whole new career.
The Apress Maker Innovations series offers projects-based learning,
while keeping theory and best processes front and center. So you get
hands-on experience while also learning the terms of the trade and how
entrepreneurs, inventors, and engineers think through creating and
executing hardware projects. You can learn to design circuits, program AI,
create IoT systems for your home or even city, and so much more!
Whether you’re a beginning hobbyist or a seasoned entrepreneur
working out of your basement or garage, you’ll scale up your skillset to
become a hardware design and engineering pro. And often using low-
cost and open-source software such as the Raspberry Pi, Arduino, PIC
microcontroller, and Robot Operating System (ROS). Programmers and
software engineers have great opportunities to learn, too, as many projects
and control environments are based in popular languages and operating
systems, such as Python and Linux.
If you want to build a robot, set up a smart home, tackle assembling a
weather-ready meteorology system, or create a brand-new circuit using
breadboards and circuit design software, this series has all that and more!
Written by creative and seasoned Makers, every book in the series tackles
both tested and leading-edge approaches and technologies for bringing
your visions and projects to life.
Farzin Asadi
Essentials of Arduino™ Boards Programming: Step-by-Step Guide to Master
Arduino Boards Hardware and Software
Farzin Asadi
Department of Electrical and Electronics Engineering, Maltepe University,
Istanbul, Türkiye
ISBN-13 (pbk): 978-1-4842-9599-1 ISBN-13 (electronic): 978-1-4842-9600-4
https://doi.org/10.1007/978-1-4842-9600-4
Copyright © 2023 by Farzin Asadi
This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or
part of the material is concerned, specifically the rights of translation, reprinting, reuse of
illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way,
and transmission or information storage and retrieval, electronic adaptation, computer software,
or by similar or dissimilar methodology now known or hereafter developed.
Trademarked names, logos, and images may appear in this book. Rather than use a trademark
symbol with every occurrence of a trademarked name, logo, or image we use the names, logos,
and images only in an editorial fashion and to the benefit of the trademark owner, with no
intention of infringement of the trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if
they are not identified as such, is not to be taken as an expression of opinion as to whether or not
they are subject to proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of
publication, neither the authors nor the editors nor the publisher can accept any legal
responsibility for any errors or omissions that may be made. The publisher makes no warranty,
express or implied, with respect to the material contained herein.
Managing Director, Apress Media LLC: Welmoed Spahr
Acquisitions Editor: Miriam Haidara
Development Editor: James Markham
Coordinating Editor: Jessica Vakili
Cover image designed by eStudioCalamar
Distributed to the book trade worldwide by Apress Media, LLC, 1 New York Plaza, New York, NY
10004, U.S.A. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail [email protected],
or visit www.springeronline.com. Apress Media, LLC is a California LLC and the sole member
(owner) is Springer Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance
Inc is a Delaware corporation.
For information on translations, please e-mail [email protected]; for
reprint, paperback, or audio rights, please e-mail [email protected].
Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook
versions and licenses are also available for most titles. For more information, reference our Print
and eBook Bulk Sales web page at http://www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is
available to readers on GitHub (https://github.com/Apress). For more detailed information,
please visit http://www.apress.com/source-code.
Paper in this product is recyclable
Dedicated to my lovely brother, Farzad, and my lovely
sisters, Farnaz and Farzaneh.
Table of Contents
About the Author�������������������������������������������������������������������������������xiii
Introduction��������������������������������������������������������������������������������������xvii
vii
Table of Contents
viii
Table of Contents
ix
Table of Contents
x
Table of Contents
xi
Table of Contents
Index�������������������������������������������������������������������������������������������������327
xii
About the Author
Farzin Asadi received his BSc in Electronics
Engineering, MSc in Control Engineering, and
PhD in Mechatronics Engineering.
Currently, he is with the Department of
Electrical and Electronics Engineering at
Maltepe University, Istanbul, Turkey.
Dr. Asadi has published more than 40 papers
in ISI/Scopus indexed journals. He has written 25
books. His research interests include switching
converters, control theory, robust control of
power electronics converters, and robotics.
xiii
About the Technical Reviewer
Hai Van Pham received his BSc, MSc, and PhD
in Computer Science.
Currently, he is with the School of
Information and Communication Technology,
Hanoi University of Science and Technology,
Hanoi, Vietnam.
Dr. Pham has published over 100 papers in
ISI/Scopus indexed journals. He is an associate
editor in domestic and international journals
and served as chair and technical committee
member of many national and international
conferences including SOICT 2014, KSE 2015, KSE 2017, KSE 2019, KSE
2021, and KSE 2022.
His research interests include artificial intelligence, knowledge-based
systems, big data, soft computing, rule-based systems, and fuzzy systems.
xv
Introduction
Arduino is an open source hardware and software company, project,
and user community that designs and manufactures single-board
microcontrollers and microcontroller kits for building digital devices.
Arduino boards use a variety of microcontrollers, and each board is
suitable for a specific application. For instance, Arduino Nano or Pro Mini
is an ideal option if space or weight is important for you. If you search for
a board with many input/output (I/O) pins, then Arduino MEGA is a good
option for you. If you need an Arduino board for a time-critical application
like a robot control, then Arduino DUE is a good choice. Arduino UNO is a
good option for educational purposes. All of the examples in this book are
done with Arduino UNO.
There exist many other development boards in the world, but why are
Arduino boards so famous with millions of users? Here are some of the
basic reasons that make Arduino boards outstanding:
xvii
Introduction
xviii
Introduction
xix
CHAPTER 1
Introduction
to Arduino Boards
1.1 Introduction
Arduino is an open source platform used for building electronics projects.
Arduino consists of both a physical programmable circuit board (often
referred to as a microcontroller) and a piece of software or IDE (Integrated
Development Environment) that runs on your computer, used to write and
upload computer code to the physical board.
The Arduino platform has become quite popular with people just
starting out with electronics, and for good reason. Unlike most previous
programmable circuit boards, the Arduino does not need a separate piece
of hardware (called a programmer) in order to load new code onto the
board; you can simply use a USB cable. Additionally, the Arduino IDE uses
a simplified version of C++, making it easier to learn to program. Finally,
Arduino provides a standard form factor that breaks out the functions of
the microcontroller into a more accessible package.
This chapter is an introduction to microcontrollers and Arduino
boards and makes the foundation for other chapters.
1.2 Microcontrollers
A microcontroller is a compact integrated circuit designed to govern a specific
operation in an embedded system. A typical microcontroller includes a
processor, memory, and input/output (I/O) peripherals on a single chip.
Some of the commonly used microcontrollers are shown in Figures 1-1 to 1-3.
3
Chapter 1 Introduction to Arduino Boards
1.3 Elements of a Microcontroller
The core elements of a microcontroller are
4
Chapter 1 Introduction to Arduino Boards
While the processor, memory, and I/O peripherals are the defining
elements of the microprocessor, there are other elements that are
frequently included. The term I/O peripherals itself simply refers to
supporting components that interface with the memory and processor.
There are many supporting components that can be classified as
peripherals. Having some manifestation of an I/O peripheral is elemental
to a microprocessor, because they are the mechanism through which the
processor is applied.
Other supporting elements of a microcontroller include
5
Chapter 1 Introduction to Arduino Boards
1.5 Arduino Boards
In a nutshell, an Arduino (/ɑːrˈdwiːnoʊ/) is an open hardware development
board that can be used by tinkerers, hobbyists, and makers to design and
build devices that interact with the real world.
The Arduino hardware and software were designed for artists,
designers, hobbyists, hackers, newbies, and anyone interested in creating
interactive objects or environments. Arduino can interact with buttons,
LEDs, motors, speakers, GPS units, cameras, the Internet, and even your
smartphone or your TV! This flexibility combined with the fact that the
Arduino software is free, the hardware boards are pretty cheap, and both
6
Chapter 1 Introduction to Arduino Boards
the software and hardware are easy to learn has led to a large community
of users who have contributed code and released instructions for a huge
variety of Arduino-based projects.
Most Arduino boards use Atmel 8-bit microcontrollers (ATmega8,
ATmega168, ATmega328, ATmega1280, or ATmega2560). Some Arduino
boards use ARM Cortex–based microcontrollers.
Some of the commonly used Arduino boards are shown in
Figures 1-4 to 1-6.
7
Chapter 1 Introduction to Arduino Boards
8
Chapter 1 Introduction to Arduino Boards
All of the experiments of this book are done with the aid of the
Arduino UNO board (Figure 1-4). Arduino UNO uses the ATmega328
microcontroller made by ATMEL. ATmega328 is made in different
packages (Figures 1-7 and 1-8).
9
Chapter 1 Introduction to Arduino Boards
10
Chapter 1 Introduction to Arduino Boards
11
Chapter 1 Introduction to Arduino Boards
Programs written using the Arduino IDE are called sketches. These
sketches are written in the text editor and are saved with the file .ino
extension.
As shown in Figure 1-10, the C code has two default functions: setup
and loop. The code inside the void setup will be executed once, and only
once, at the beginning of the program. Then, the code inside the void loop
will be executed again and again (hence the name “loop”), until you power
off the Arduino board.
12
Chapter 1 Introduction to Arduino Boards
1.8 HEX File
A HEX file is a hexadecimal source file typically used in the programming
of microcontrollers. If you share a .INO file, anyone can edit or see the
main program. But HEX files are much more secure than INO files; no one
can edit them because of the hexadecimal format.
Let’s see how we can see the generated HEX file associated with a C
code. Open the Arduino IDE (Figure 1-12).
13
Chapter 1 Introduction to Arduino Boards
Write the code shown in Figure 1-13. This code turns on the onboard
LED, waits for 1 s, turns off the onboard LED, waits for 1 s, and repeats this
procedure.
14
Chapter 1 Introduction to Arduino Boards
Click File ➤ Save or press Ctrl+S. This opens the Save sketch folder as…
window for you (Figure 1-14). Save the file with the name of blink.
15
Chapter 1 Introduction to Arduino Boards
16
Chapter 1 Introduction to Arduino Boards
17
Chapter 1 Introduction to Arduino Boards
18
Chapter 1 Introduction to Arduino Boards
19
Chapter 1 Introduction to Arduino Boards
You can use Notepad++ to open the HEX file (Figure 1-20). As the
name suggests, it contains a collection of HEX numbers.
Now write your code and save it (Figure 1-23). Then click the Upload
button (Figure 1-24) to upload the code into the Arduino board.
22
Chapter 1 Introduction to Arduino Boards
23
Chapter 1 Introduction to Arduino Boards
24
Chapter 1 Introduction to Arduino Boards
Some Arduino boards like UNO, MEGA, and DUE come with a DC
socket that can be used to power the boards (Figure 1-26). In this method,
a power supply adapter that provides 7–12 V DC is required.
25
Chapter 1 Introduction to Arduino Boards
1.11 Ready-to-Use Examples
You can find ready-to-use examples in the File ➤ Examples section
(Figure 1-27). Note that each example may need a specific hardware
configuration. Hardware details are written as comment in the first lines of
the code.
26
Chapter 1 Introduction to Arduino Boards
27
Chapter 1 Introduction to Arduino Boards
1.12 Arduino Shields
Shields are modular circuit boards that piggyback onto your Arduino
to instill it with extra functionality. Want to connect your board to the
Internet? There is a shield for it (Figures 1-28 and 1-29). Want to control a
DC motor? There is a shield for it (Figures 1-30 and 1-31). Many different
types of Arduino shields are in access today.
28
Chapter 1 Introduction to Arduino Boards
29
Chapter 1 Introduction to Arduino Boards
1.13 Language Reference
The Language Reference section of the Arduino website (www.arduino.
cc/reference/en/) is the best reference to learn the C programming of
Arduino boards. Don’t forget to visit there.
31
CHAPTER 2
Digital
Input/Output (I/O)
2.1 Introduction
A digital signal is a signal that represents data as a sequence of discrete
values; at any given time, it can only take on, at most, one of a finite
number of values. This contrasts with an analog signal, which represents
continuous values; at any given time, it represents a real number within a
continuous range of values.
In this chapter, you will learn how to use the Arduino board to read
or generate digital signals. According to Figure 2-1, pins 0–13 are digital
pins, and they can be used as digital input or output (I/O). Pins which have
a tilde (~) symbol behind them (pins 3, 5, 6, 9, 10, and 11) can be used
for pulse width modulation (PWM) purposes as well. PWM is studied in
Chapter 7. Pins 0 and 1 are used to transmit and receive the serial data as
well. Therefore, it is a good idea not to use them as digital I/O when your
project contains serial communication.
34
Chapter 2 Digital Input/Output (I/O)
35
Chapter 2 Digital Input/Output (I/O)
36
Chapter 2 Digital Input/Output (I/O)
37
Chapter 2 Digital Input/Output (I/O)
38
Chapter 2 Digital Input/Output (I/O)
39
Chapter 2 Digital Input/Output (I/O)
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(LED,HIGH);
delay(1000);
digitalWrite(LED,LOW);
delay(1000);
}
After uploading the code to the Arduino board, you will see that the
onboard LED starts to blink: it is on for one second, and it is off for one
second. You can use any integer numbers instead of using HIGH and LOW
constants. Any nonzero integer generates a high signal (i.e., +5 V), and zero
generates a low signal (i.e., 0 V). For instance, the previous code can be
written as follows as well:
40
Chapter 2 Digital Input/Output (I/O)
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(LED,1);
delay(1000);
digitalWrite(LED,0);
delay(1000);
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(LED,true);
delay(1000);
digitalWrite(LED,false);
delay(1000);
}
41
Chapter 2 Digital Input/Output (I/O)
void setup() {
// put your setup code here, to run once:
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
t0=millis();
digitalWrite(LED_BUILTIN, HIGH);
while (millis()<(t0+1000)){
}
t1=millis();
digitalWrite(LED_BUILTIN, LOW);
while (millis()<(t1+1000)){
}
}
After uploading the preceding code to the Arduino board, you will see
that the onboard LED starts to blink.
42
Chapter 2 Digital Input/Output (I/O)
void setup() {
// put your setup code here, to run once:
pinMode(LED,OUTPUT);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
t0=micros();
digitalWrite(LED,HIGH);
t1=micros();
digitalWrite(LED,LOW);
t2=micros();
Serial.println((String)"digitalWrite(LED,HIGH) requires:
"+(t1-t0)+" us.");
43
Chapter 2 Digital Input/Output (I/O)
Serial.println((String)"digitalWrite(LED,LOW) requires:
"+(t2-t1)+" us.");
Serial.println();
delay(1000);
}
44
Chapter 2 Digital Input/Output (I/O)
45
Chapter 2 Digital Input/Output (I/O)
int pin = 2;
void setup() {
pinMode(pin, OUTPUT); // sets the digital pin as output
}
46
Chapter 2 Digital Input/Output (I/O)
void loop() {
digitalWrite(pin, HIGH);
delayMicroseconds(1000);
digitalWrite(pin, LOW);
delayMicroseconds(1000);
}
Upload the following code to the Arduino board. In this code, the
output voltage is determined by two arrays. Each number in the arrays
determines the corresponding output for a 100 ms interval. For instance,
the third value of LED1Array is 1. This means that LED 1 is high for the
[200 ms, 300 ms] interval.
47
Chapter 2 Digital Input/Output (I/O)
int LED1Array[]={1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,
0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0};
int LED2Array[]={1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,
1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0};
void setup() {
// put your setup code here, to run once:
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
digitalWrite(LED1,LED1State);
digitalWrite(LED2,LED2State);
}
void loop() {
// put your main code here, to run repeatedly:
delay(100);
k=k+1;
digitalWrite(LED1,LED1Array[k-1]);
digitalWrite(LED2,LED2Array[k-1]);
if (k==40) k=0;
}
48
Chapter 2 Digital Input/Output (I/O)
The following points help you to determine the anode and cathode of
an LED easily:
49
Chapter 2 Digital Input/Output (I/O)
2.11 RGB LED
An RGB LED is a combination of red, green, and blue LEDs put into
a single package. RGB LEDs can be used to produce almost any color
by controlling the intensity of red, green, and blue lights that LEDs
produce. RGB LEDs can be used in different applications such as outdoor
decoration lighting, stage lighting designs, home decoration lighting, LED
matrix display, and more.
RGB LEDs are divided into two groups: common cathode RGB LEDs
(Figure 2-12) and common anode RGB LEDs (Figure 2-13).
50
Chapter 2 Digital Input/Output (I/O)
51
Chapter 2 Digital Input/Output (I/O)
Upload the following code to the board. This code forces the common
cathode RGB LED to produce red, green, blue, and white lights:
#define Rpin 8
#define Gpin 9
#define Bpin 10
void setup() {
// put your setup code here, to run once:
pinMode(Rpin, OUTPUT);
pinMode(Gpin, OUTPUT);
pinMode(Bpin, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(Rpin,HIGH);
delay(1000);
digitalWrite(Rpin,LOW);
digitalWrite(Gpin,HIGH);
delay(1000);
digitalWrite(Gpin,LOW);
digitalWrite(Bpin,HIGH);
delay(1000);
digitalWrite(Bpin,LOW);
digitalWrite(Rpin,HIGH);
digitalWrite(Gpin,HIGH);
digitalWrite(Bpin,HIGH);
delay(1000);
digitalWrite(Rpin,LOW);
52
Chapter 2 Digital Input/Output (I/O)
digitalWrite(Gpin,LOW);
digitalWrite(Bpin,LOW);
}
Let’s write the code for common anode RGB LEDs as well. The anodes
of common anode RGB LEDs are connected to +5 V. When you send the
low signal to the cathodes, the corresponding LED is turned on.
Upload the following code to the board. This code forces the common
anode RGB LED to produce red, green, blue, and white lights:
53
Chapter 2 Digital Input/Output (I/O)
#define Rpin 8
#define Gpin 9
#define Bpin 10
void setup() {
// put your setup code here, to run once:
pinMode(Rpin, OUTPUT);
pinMode(Gpin, OUTPUT);
pinMode(Bpin, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(Rpin,LOW);
delay(1000);
digitalWrite(Rpin,HIGH);
digitalWrite(Gpin,LOW);
delay(1000);
digitalWrite(Gpin,HIGH);
digitalWrite(Bpin,LOW);
delay(1000);
digitalWrite(Bpin,HIGH);
digitalWrite(Rpin,LOW);
digitalWrite(Gpin,LOW);
digitalWrite(Bpin,LOW);
delay(1000);
digitalWrite(Rpin,HIGH);
digitalWrite(Gpin,HIGH);
digitalWrite(Bpin,HIGH);
}
54
Chapter 2 Digital Input/Output (I/O)
55
Chapter 2 Digital Input/Output (I/O)
56
Chapter 2 Digital Input/Output (I/O)
57
Chapter 2 Digital Input/Output (I/O)
Figure 2-20 shows how different values can be displayed on the seven-
segment display. Table 2-1 summarizes this figure. In this figure, activated
segments are shown with 1. For instance, in order to show number 3,
segments a, b, c, d, and g must be turned on.
58
Chapter 2 Digital Input/Output (I/O)
59
Chapter 2 Digital Input/Output (I/O)
void setup() {
pinMode(a,OUTPUT);
pinMode(b,OUTPUT);
pinMode(c,OUTPUT);
pinMode(d,OUTPUT);
pinMode(e,OUTPUT);
pinMode(f,OUTPUT);
pinMode(g,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
for (i=0;i<=9;i++){
displayNumber(i);
delay(1000);
}
}
void clearDisp(){
digitalWrite(a,LOW);
digitalWrite(b,LOW);
digitalWrite(c,LOW);
digitalWrite(d,LOW);
digitalWrite(e,LOW);
digitalWrite(f,LOW);
digitalWrite(g,LOW);
}
void displayNumber(int n)
{
switch (n){
case 0:
clearDisp();
60
Chapter 2 Digital Input/Output (I/O)
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,HIGH);
digitalWrite(f,HIGH);
digitalWrite(g,LOW);
break;
case 1:
clearDisp();
digitalWrite(a,LOW);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,LOW);
digitalWrite(e,LOW);
digitalWrite(f,LOW);
digitalWrite(g,LOW);
break;
case 2:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,LOW);
digitalWrite(d,HIGH);
digitalWrite(e,HIGH);
digitalWrite(f,LOW);
digitalWrite(g,HIGH);
break;
61
Chapter 2 Digital Input/Output (I/O)
case 3:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,LOW);
digitalWrite(f,LOW);
digitalWrite(g,HIGH);
break;
case 4:
clearDisp();
digitalWrite(a,LOW);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,LOW);
digitalWrite(e,LOW);
digitalWrite(f,HIGH);
digitalWrite(g,HIGH);
break;
case 5:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,LOW);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,LOW);
digitalWrite(f,HIGH);
digitalWrite(g,HIGH);
break;
62
Chapter 2 Digital Input/Output (I/O)
case 6:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,LOW);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,HIGH);
digitalWrite(f,HIGH);
digitalWrite(g,HIGH);
break;
case 7:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,LOW);
digitalWrite(e,LOW);
digitalWrite(f,LOW);
digitalWrite(g,LOW);
break;
case 8:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,HIGH);
digitalWrite(f,HIGH);
digitalWrite(g,HIGH);
break;
63
Chapter 2 Digital Input/Output (I/O)
case 9:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,LOW);
digitalWrite(f,HIGH);
digitalWrite(g,HIGH);
break;
}
}
64
Chapter 2 Digital Input/Output (I/O)
2.13 Binary Counter
In this example, we want to make an 8-bit binary counter. We will use the
Data Direction Register and Port Data Register for this purpose.
The Arduino UNO board uses the ATmega328 microcontroller.
Figure 2-22 shows the connection between ATmega328 microcontroller
pins and Arduino board pins. For instance, according to Figure 2-22, PB5
(6th bit of I/O port B) and PD2 (3rd bit of I/O port D) are connected to
pins 13 and 2 of the Arduino UNO board, respectively.
Tables 2-2 to 2-4 show the connection between ATmega328 I/O pins
and Arduino UNO pins.
PB0 8
PB1 9
PB2 10
PB3 11
PB4 12
PB5 13
PC0 A0
PC1 A1
PC2 A2
PC3 A3
PC4 A4
PC5 A5
66
Chapter 2 Digital Input/Output (I/O)
PD0 0
PD1 1
PD2 2
PD3 3
PD4 4
PD5 5
PD6 6
PD7 7
// PORT
//See: https://create.arduino.cc/projecthub/Hack-star-Arduino/
learn-arduino-port-manipulation-2022-10f9af
//See: https://www.instructables.com/Arduino-and-Port-
Manipulation/
void setup() {
// put your setup code here, to run once:
DDRD=0b11111111;
}
67
Chapter 2 Digital Input/Output (I/O)
void loop() {
// put your main code here, to run repeatedly:
for (int i=0;i<=255;i++){
PORTD=i;
delay(250);
}
}
68
Chapter 2 Digital Input/Output (I/O)
69
Chapter 2 Digital Input/Output (I/O)
70
Chapter 2 Digital Input/Output (I/O)
Here, we want to make an 8-bit binary counter, but this time we will
use only three I/O pins of the Arduino board. Upload the following code:
71
Chapter 2 Digital Input/Output (I/O)
void setup() {
// put your main code here, to run repeatedly:
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop() {
// count from 0 to 255 and display the number
// on the LEDs
// bit: 7 6 5 4 3 2 1 0 (7 shows the MSB, 0 shows the LSB)
// IC pin: 7 6 5 4 3 2 1 15
for (int numberToDisplay = 0; numberToDisplay < 256;
numberToDisplay++) {
// take the latchPin low so
// the LEDs don't change while you're sending in bits:
digitalWrite(latchPin, LOW);
// shift out the bits:
shiftOut(dataPin, clockPin, MSBFIRST, numberToDisplay);
//take the latch pin high so the LEDs will light up:
digitalWrite(latchPin, HIGH);
// pause before next value:
delay(500);
}
}
72
Chapter 2 Digital Input/Output (I/O)
Connect pins 11, 12, and 14 of 74LS595 to pins 12, 8, and 11 of the
Arduino board, respectively. Don’t forget to connect the GND and +5 V of
the Arduino board to pins 8 and 16 of 74LS595. LEDs are connected to the
74LS595 pins as shown in Figure 2-26 (IC-n shows pin n of 74LS595). The
LED connected to pin 7 of the 74LS595 is the MSB, and the LED connected
to pin 15 of 74LS595 is the LSB.
void setup() {
// put your main code here, to run repeatedly:
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop() {
// count from 0 to 255 and display the number
// on the LEDs
// bit: 7 6 5 4 3 2 1 0 (7 shows the MSB, 0 shows
the LSB)
// IC pin: 15 1 2 3 4 5 6 7
for (int numberToDisplay = 0; numberToDisplay < 256;
numberToDisplay++) {
// take the latchPin low so
// the LEDs don't change while you're sending in bits:
digitalWrite(latchPin, LOW);
// shift out the bits:
74
Chapter 2 Digital Input/Output (I/O)
2.15 Four-Digit Display
74LS595 can be used to drive a four-digit display as well. This example
shows how to drive a four-digit common anode display (Figure 2-27) with
two 74LS595 ICs. Table 2-5 shows which code must be used for each digit.
DP in this table represents the decimal point LED.
75
Chapter 2 Digital Input/Output (I/O)
Table 2-5. Truth table for each decimal digit displayed on a common
anode seven segment
Decimal Digit Individual Segment Illuminated HEX
DP G f e d c b a
0 1 1 0 0 0 0 0 0 C0
1 1 1 1 1 1 0 0 1 F9
2 1 0 1 0 0 1 0 0 A4
3 1 0 1 1 0 0 0 0 B0
4 1 0 0 1 1 0 0 1 99
5 1 0 0 1 0 0 1 0 92
6 1 0 0 0 0 0 1 0 82
7 1 1 1 1 1 0 0 0 F8
8 1 0 0 0 0 0 0 0 80
9 1 0 0 1 0 0 0 0 90
76
Chapter 2 Digital Input/Output (I/O)
77
Chapter 2 Digital Input/Output (I/O)
Upload the following code to the Arduino board. This code shows 7890
on the display:
int digit1=0;
int digit2=0;
int digit3=0;
78
Chapter 2 Digital Input/Output (I/O)
int digit4=0;
void setup(){
// put your setup code here, to run once:
pinMode(LATCH_DIO,OUTPUT);
pinMode(CLK_DIO,OUTPUT);
pinMode(DATA_DIO,OUTPUT);
}
void loop(){
// put your main code here, to run repeatedly:
displayNumber(7890);
}
WriteNumberToSegment(0,digit1);
WriteNumberToSegment(1,digit2);
WriteNumberToSegment(2,digit3);
WriteNumberToSegment(3,digit4);
}
79
Chapter 2 Digital Input/Output (I/O)
80
Chapter 2 Digital Input/Output (I/O)
81
Chapter 2 Digital Input/Output (I/O)
82
Chapter 2 Digital Input/Output (I/O)
#include <TM1637.h>
int CLK=2;
int DIO=3;
TM1637 tm(CLK,DIO);
void setup() {
// put your setup code here, to run once:
tm.init();
tm.set(2); //set brightness 0-7
}
void loop() {
// put your main code here, to run repeatedly:
// this code shows 12:34
83
Chapter 2 Digital Input/Output (I/O)
tm.display(0,1);
tm.display(1,2);
tm.point(1);
tm.display(2,3);
tm.display(3,4);
}
#include <TM1637.h>
int CLK=2;
int DIO=3;
int number=0;
TM1637 tm(CLK,DIO);
void setup() {
// put your setup code here, to run once:
tm.init();
tm.set(2); //set brightness 0-7
randomSeed(analogRead(0));
delay(500);
}
void loop() {
// put your main code here, to run repeatedly:
// this code generates a random number between 1000-9999 and
displays it
number=random(1000,9999);
displayNumber(number);
delay(1000);
}
84
Chapter 2 Digital Input/Output (I/O)
int pushButton=9;
void setup() {
// put your setup code here, to run once:
pinMode(LED_BUILTIN,OUTPUT);
pinMode(pushButton,INPUT);
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(LED_BUILTIN,digitalRead(pushButton));
}
85
Chapter 2 Digital Input/Output (I/O)
86
Chapter 2 Digital Input/Output (I/O)
87
Chapter 2 Digital Input/Output (I/O)
int value=0;
void setup() {
// put your setup code here, to run once:
pinMode(LED,OUTPUT);
pinMode(pushButton,INPUT_PULLUP);
}
void loop() {
// put your main code here, to run repeatedly:
value=digitalRead(pushButton);
digitalWrite(LED_BUILTIN,!value);
}
88
Chapter 2 Digital Input/Output (I/O)
When you press the push button, the onboard LED turns on. When you
release it, the onboard LED turns off.
2.19 Toggle a Pin
This example does the same job as the one shown in Section 2.6. After
uploading the code to the board, the onboard LED starts to blink.
void setup() {
// put your setup code here, to run once:
pinMode(LED_BUILTIN,OUTPUT);
}
89
Chapter 2 Digital Input/Output (I/O)
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));
delay(1000);
}
void setup() {
pinMode(a,OUTPUT);
pinMode(b,OUTPUT);
pinMode(c,OUTPUT);
pinMode(d,OUTPUT);
pinMode(e,OUTPUT);
90
Chapter 2 Digital Input/Output (I/O)
pinMode(f,OUTPUT);
pinMode(g,OUTPUT);
pinMode(dec,INPUT);
pinMode(inc,INPUT);
}
void loop() {
// put your main code here, to run repeatedly:
if (digitalRead(dec)==LOW){
delay(300);
value=value-1;
if (value<0)
value=0;
}
if (digitalRead(inc)==LOW){
delay(300);
value=value+1;
if (value>9)
value=9;
}
displayNumber(value);
}
void clearDisp(){
digitalWrite(a,LOW);
digitalWrite(b,LOW);
digitalWrite(c,LOW);
digitalWrite(d,LOW);
digitalWrite(e,LOW);
digitalWrite(f,LOW);
digitalWrite(g,LOW);
}
91
Chapter 2 Digital Input/Output (I/O)
void displayNumber(int n)
{
switch (n){
case 0:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,HIGH);
digitalWrite(f,HIGH);
digitalWrite(g,LOW);
break;
case 1:
clearDisp();
digitalWrite(a,LOW);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,LOW);
digitalWrite(e,LOW);
digitalWrite(f,LOW);
digitalWrite(g,LOW);
break;
case 2:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,LOW);
digitalWrite(d,HIGH);
digitalWrite(e,HIGH);
92
Chapter 2 Digital Input/Output (I/O)
digitalWrite(f,LOW);
digitalWrite(g,HIGH);
break;
case 3:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,LOW);
digitalWrite(f,LOW);
digitalWrite(g,HIGH);
break;
case 4:
clearDisp();
digitalWrite(a,LOW);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,LOW);
digitalWrite(e,LOW);
digitalWrite(f,HIGH);
digitalWrite(g,HIGH);
break;
case 5:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,LOW);
digitalWrite(c,HIGH);
93
Chapter 2 Digital Input/Output (I/O)
digitalWrite(d,HIGH);
digitalWrite(e,LOW);
digitalWrite(f,HIGH);
digitalWrite(g,HIGH);
break;
case 6:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,LOW);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,HIGH);
digitalWrite(f,HIGH);
digitalWrite(g,HIGH);
break;
case 7:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,LOW);
digitalWrite(e,LOW);
digitalWrite(f,LOW);
digitalWrite(g,LOW);
break;
94
Chapter 2 Digital Input/Output (I/O)
case 8:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,HIGH);
digitalWrite(f,HIGH);
digitalWrite(g,HIGH);
break;
case 9:
clearDisp();
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,LOW);
digitalWrite(f,HIGH);
digitalWrite(g,HIGH);
break;
}
}
95
Chapter 2 Digital Input/Output (I/O)
2.21 Electronic Dice
In this example, we want to make a digital dice. The output of this example
is a random number between one and six. The output is shown on a
common cathode seven-segment display. Upload the following code to
the board:
96
Chapter 2 Digital Input/Output (I/O)
void setup() {
pinMode(a,OUTPUT);
pinMode(b,OUTPUT);
pinMode(c,OUTPUT);
pinMode(d,OUTPUT);
pinMode(e,OUTPUT);
pinMode(f,OUTPUT);
pinMode(g,OUTPUT);
pinMode(pushButton,INPUT_PULLUP);
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,HIGH);
digitalWrite(f,HIGH);
digitalWrite(g,LOW);
randomSeed(analogRead(0));
}
void loop() {
// put your main code here, to run repeatedly:
value=digitalRead(pushButton);
if (value==LOW){
delay(250);
displayNumber(random(7));
}
}
97
Chapter 2 Digital Input/Output (I/O)
void clearDisp(){
digitalWrite(a,LOW);
digitalWrite(b,LOW);
digitalWrite(c,LOW);
digitalWrite(d,LOW);
digitalWrite(e,LOW);
digitalWrite(f,LOW);
digitalWrite(g,LOW);
}
void displayNumber(int n)
{
switch (n){
case 1:
clearDisp();
delay(100);
digitalWrite(a,LOW);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,LOW);
digitalWrite(e,LOW);
digitalWrite(f,LOW);
digitalWrite(g,LOW);
break;
case 2:
clearDisp();
delay(100);
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,LOW);
digitalWrite(d,HIGH);
98
Chapter 2 Digital Input/Output (I/O)
digitalWrite(e,HIGH);
digitalWrite(f,LOW);
digitalWrite(g,HIGH);
break;
case 3:
clearDisp();
delay(100);
digitalWrite(a,HIGH);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,LOW);
digitalWrite(f,LOW);
digitalWrite(g,HIGH);
break;
case 4:
clearDisp();
delay(100);
digitalWrite(a,LOW);
digitalWrite(b,HIGH);
digitalWrite(c,HIGH);
digitalWrite(d,LOW);
digitalWrite(e,LOW);
digitalWrite(f,HIGH);
digitalWrite(g,HIGH);
break;
case 5:
clearDisp();
delay(100);
digitalWrite(a,HIGH);
99
Chapter 2 Digital Input/Output (I/O)
digitalWrite(b,LOW);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,LOW);
digitalWrite(f,HIGH);
digitalWrite(g,HIGH);
break;
case 6:
clearDisp();
delay(100);
digitalWrite(a,HIGH);
digitalWrite(b,LOW);
digitalWrite(c,HIGH);
digitalWrite(d,HIGH);
digitalWrite(e,HIGH);
digitalWrite(f,HIGH);
digitalWrite(g,HIGH);
break;
}
}
100
Chapter 2 Digital Input/Output (I/O)
2.22 Reading a Keypad
In this section, we will see how a keypad can be read with the aid of a
Keypad library. The schematic of a typical keypad is shown in Figure 2-43.
This keypad has four rows and four columns.
101
Chapter 2 Digital Input/Output (I/O)
The following code shows how to read a keyboard with the aid of a
Keypad library:
#include <Keypad.h>
102
Chapter 2 Digital Input/Output (I/O)
void setup(){
Serial.begin(9600);
}
void loop(){
char key = keypad.getKey();
R4 2
R3 3
R2 4
R1 5
C4 6
C3 7
C2 8
C1 9
103
Chapter 2 Digital Input/Output (I/O)
After uploading the code to the board, click Tools ➤ Serial Monitor in
order to see the result. When you press the keypad keys, they are shown in
the Serial Monitor window.
2.23 Simple Calculator
In this example, we want to make a simple calculator. The keypad of this
calculator is shown in Figure 2-44.
104
Chapter 2 Digital Input/Output (I/O)
#include <Keypad.h>
String num1="",num2="";
String operation="";
float result=0.0;
void setup(){
Serial.begin(9600);
}
void loop(){
char key = keypad.getKey();
if (operation=="/"){
result=num1.toFloat()/num2.toFloat();
Serial.println((String)"="+result);
num1="";
106
Chapter 2 Digital Input/Output (I/O)
num2="";
operation="";
result=0;
}
if (operation=="+"){
result=num1.toFloat()+num2.toFloat();
Serial.println((String)"="+result);
num1="";
num2="";
operation="";
result=0;
}
if (operation=="-"){
result=num1.toFloat()-num2.toFloat();
Serial.println((String)"="+result);
num1="";
num2="";
operation="";
result=0;
}
}
delay(50);
}
107
Chapter 2 Digital Input/Output (I/O)
R4 2
R3 3
R2 4
R1 5
C4 6
C3 7
C2 8
C1 9
After uploading the code to the board, click Tools ➤ Serial Monitor in
order to see the result. Use the = key to see the result (Figure 2-45).
108
Chapter 2 Digital Input/Output (I/O)
#include <Keypad.h>
String code="";
const int password="12A7";
109
Chapter 2 Digital Input/Output (I/O)
void setup(){
Serial.begin(9600);
pinMode(LED_BUILTIN,OUTPUT);
digitalWrite(LED_BUILTIN,LOW);
Serial.print("Enter your password: ");
}
void loop(){
char key = keypad.getKey();
110
Chapter 2 Digital Input/Output (I/O)
delay(50);
}
R4 2
R3 3
R2 4
R1 5
C4 6
C3 7
C2 8
C1 9
After uploading the code to the board, click Tools ➤ Serial Monitor in
order to see the result.
111
Chapter 2 Digital Input/Output (I/O)
There are ICs available in the market for switch debouncing. Some
of the debouncing ICs are MAX6816, MC14490, and LS118. For instance,
debouncing with the aid of MAX6816 is shown in Figure 2-48.
113
Chapter 2 Digital Input/Output (I/O)
AND &
OR |
XOR ^
NOT !
Shift Right >>
Shift Left <<
114
Chapter 2 Digital Input/Output (I/O)
#define Apin 2
#define Bpin 3
#define Cpin 4
#define Fpin 13
int A=0;
int B=0;
int C=0;
int F=0;
void setup() {
// put your setup code here, to run once:
pinMode(Apin,INPUT);
pinMode(Bpin,INPUT);
pinMode(Cpin,INPUT);
pinMode(Fpin,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
A=digitalRead(Apin);
B=digitalRead(Bpin);
C=digitalRead(Cpin);
F=A&(!(B|C));
digitalWrite(Fpin,F);
}
115
Chapter 2 Digital Input/Output (I/O)
116
Chapter 2 Digital Input/Output (I/O)
int a=0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
int n=0b101101;
Serial.println("n is a binary number with value of 101101.");
for (int i=1;i<=6;i++){
a=n>>i;
Serial.print((String)"Result of n>>"+i+" is ");
Serial.println(a,BIN);
}
Serial.println("-------");
117
Chapter 2 Digital Input/Output (I/O)
delay(120000);
}
After uploading the code, open the Serial Monitor (Tools ➤ Serial
Monitor) to see the output of the code.
118
Chapter 2 Digital Input/Output (I/O)
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println((String)"a=10110010="+a+", b=10010110="+b);
Serial.println("");
c=~a;
d=~b;
Serial.print("~a=");
Serial.println(c,BIN);
Serial.print("~b=");
Serial.println(d,BIN);
Serial.println("");
119
Chapter 2 Digital Input/Output (I/O)
c=a&b;
d=a|b;
Serial.print((String)"a&b=10110010&10010110=");
Serial.print(c,BIN);
Serial.println((String)", in decimal= "+c);
Serial.println("");
Serial.print((String)"a|b=10110010|10010110=");
Serial.print(d,BIN);
Serial.println((String)", in decimal= "+d);
Serial.println("-------------------------------------------");
delay(60000);
}
After uploading the code, open the Serial Monitor (Tools ➤ Serial
Monitor) to see the output of the code.
120
Chapter 2 Digital Input/Output (I/O)
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("a=178=10110010");
Serial.println();
Serial.println();
b=bitSet(a,6);
Serial.println((String)"bitSet(a,6)="+b); //11110010=242 is
expected.
c=bitClear(b,6);
Serial.println((String)"bitClear(b,6)="+c); //10110010=178 is
expected.
delay(60000);
}
After uploading the code, open the Serial Monitor (Tools ➤ Serial
Monitor) to see the output of the code.
121
Chapter 2 Digital Input/Output (I/O)
void setup() {
pinMode(9,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
tone(9,900); // 900 Hz on pin 9, duty cycle 50%
delay(500);
noTone(9);
delay(3000);
}
122
Chapter 2 Digital Input/Output (I/O)
123
Chapter 2 Digital Input/Output (I/O)
the microcontroller pin (this happens especially when the relay voltage is
high). Therefore, the schematic shown in Figure 2-51 works; however, from
an isolation point of view, it is not a good solution. Let’s try to solve the
isolation problem.
124
Chapter 2 Digital Input/Output (I/O)
Let’s see how the circuit shown in Figure 2-53 works. When the
microcontroller pin is high, the LED sends a light to the phototransistor,
and the voltage drop between pins 3 and 4 in Figure 2-53 becomes around
0 V. This permits the base current to pass. The base current forces the
transistor to go into the saturation, and the relay is activated. When the
microcontroller pin is low, the LED doesn’t generate any light, and the
phototransistor acts as an open circuit and stops the base current. When
the base current is around zero, the transistor goes into cutoff, and the
relay is turned off.
125
Chapter 2 Digital Input/Output (I/O)
https://bit.ly/3VoJbi6
[2] Digital pins of Arduino:
https://bit.ly/3PT9fAy
https://bit.ly/3VFr2wF
https://bit.ly/3jrt6L8
https://bit.ly/3I1D3ZW
[5] Debouncing:
https://bit.ly/3hVJOBV
https://bit.ly/3jw6WaE
[7] Keypad:
https://bit.ly/3WrQ6rU
https://bit.ly/3Wrhu9o
126
CHAPTER 3
Analog-to-Digital
Converter (ADC)
and Digital-to-Analog
Converter (DAC)
3.1 Introduction
In the previous chapter, you learned how to read and generate digital
signals. This chapter shows how you can read and generate analog
signals. Digital systems can generate or read analog signals with the aid
of two building blocks: digital-to-analog converter and analog-to-digital
converter. These two building blocks are introduced as follows.
A digital-to-analog converter (DAC, D/A, or D-to-A) is a system that
converts a digital signal into an analog signal. Arduino UNO doesn’t have an
onboard DAC. If your project requires a DAC, you need to add it externally.
An analog-to-digital converter (ADC, A/D, or A-to-D) is a system that
converts an analog signal, such as a sound picked up by a microphone or
light entering a digital camera, into a digital signal. The microcontrollers
128
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
The AREF (Analog Reference) pin (see the top-right side of
Figure 3-1) can be used to provide an external reference voltage for the
analog-to-digital conversion of inputs to the analog pins. The reference
voltage essentially specifies the value for the top of the input range and
consequently each discrete step in the converted output. When the AREF
pin is not connected to anywhere, the reference voltage is +5 V.
If we show the reference voltage and output of the ADC with VREF
and N, respectively, then the analog voltage applied to the analog pin
is N/1023×VREF. Let’s study an example. Assume that the ADC reads
0111011100 and AREF is not connected to any external reference voltage.
In this case, the reference voltage is 5 V, and the analog voltage applied to
the analog pin is 476/1023 × 5 = 2.326 V. Note that (0111011100)2 = (476)10.
As another example, assume that the output of the ADC is 1000110011
and the AREF pin is connected to 1.1 V. In this case, the analog
voltage applied to the analog pin is 563/1023 × 1.1 = 0.605 V. Note that
(1000110011)2 = (563)10.
3.2 Protection of ADC
The ADC cannot accept negative voltages and voltages bigger than +5 V.
Therefore, it is a good idea to protect the ADC against voltages outside
the allowed range. The simplest protection is shown in Figure 3-2. When
the input voltage is bigger than 5 V, the Zener diode enters into the
breakdown region, and the voltage that reaches the analog pin keeps
constant at around +5 V. The Zener diode becomes forward bias when
negative voltages are applied. In this case, the voltage of the analog pin is
around –0.7 V. If you put a Schottky diode in parallel with the Zener diode
(Figure 3-3), this value decreases to around –0.2 V.
129
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
You can use a voltage divider to measure the voltages bigger than 5 V.
For instance, the voltage divider in Figure 3-4 has an attenuation ratio of
100
= 0.312. This circuit can be used to measure the voltages up
100 + 220
to 16 V. The Zener diode protects the ADC against voltages bigger than 16 V.
You can put a Schottky diode in parallel with the Zener diode as well in
order to make a better protection against negative voltages.
130
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
Figure 3-4. The voltage divider decreases the voltage that reaches
the ADC
It is a good idea to filter the signal before applying the signal to the
ADC. For instance, assume that we know that our input signal is band
limited to 100 Hz. In this case, components more than 100 Hz are not
important for us and need to be removed. You can add a capacitor to the
voltage divider in order to make a simple low pass RC filter (Figure 3-5).
1 RR
The cutoff frequency is given by f = where R = 1 2 . For instance,
2π RC R1 + R2
assume that R=68.75 kΩ in Figure 3-5. For the cutoff frequency of 100 Hz, C
must be equal to 23.15 nF.
131
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
3.3 Simple DC Voltmeter
In this example, you will make a simple DC voltmeter. This voltmeter
measures the voltages between 0 and +5 V. Upload the following code to
the board:
int analogPinA0=A0;
int value=0;
double Vref=5.0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
value=analogRead(analogPinA0);
double voltageA0=value*Vref/1023;
132
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
Serial.println((String)"Voltage given to ADC A0:
"+voltageA0);
Serial.println("------------------------------");
delay(3000);
}
After uploading the code to the board, click Tools ➤ Serial Monitor in
order to see the result. Connect a digital voltmeter to pin A0 and compare
its reading with the output of the code.
133
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
3.4 Serial Plotter
The Serial Plotter is a very useful tool to graphically see the graph of a data
that comes from the serial port. Let’s see how the Serial Plotter works.
Upload the following code to your board. This code sends two numbers
to the computer: a random number and a constant number with a
value of 500.
int random_variable;
int static_variable = 500;
void setup() {
Serial.begin(9600);
}
void loop() {
random_variable = random(0, 1000);
Serial.print("Variable_1:");
Serial.print(random_variable);
Serial.print(",");
Serial.print("Variable_2:");
Serial.println(static_variable);
delay(500);
}
After uploading the code, click Tools ➤ Serial Plotter. It starts to show
the graph of data (Figure 3-7).
134
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
Note that the unit of the horizontal axis is not time. The Serial Plotter is
a simple tool which graphically shows the value(s) received from the serial
port. A horizontal axis can be considered as the index of received data.
Let’s use the Serial Plotter to see the graph of voltage that is applied to
pin A0 of Arduino as well. Upload the following code to the board:
int analogPinA0=A0;
int value=0;
double Vref=5.08;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
value=analogRead(analogPinA0);
double voltageA0=value*Vref/1023;
Serial.println(voltageA0);
delay(50);
}
135
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
The hardware of this example is shown in Figure 3-8. Rotate the
potentiometer shaft; the Serial Plotter shows the changes of the voltage on
the screen (Figure 3-9).
136
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
3.5 AREF Pin
The AREF (Analog Reference) pin can be used to provide an external
reference voltage for the analog-to-digital conversion of inputs to the
analog pins. The reference voltage essentially specifies the value for the top
of the input range and consequently each discrete step in the converted
output. For instance, if you apply 3.3 V to the AREF pin, the analogRead
returns 1023 for the input voltage of 3.3 V and 341 for the input voltage
of 1.1 V. In this case, sensitivity is 3.3/1023= 3.2 mV. When no voltage is
connected to the AREF pin, the reference voltage is 5 V.
Negative voltages and values bigger than 5 V cannot be applied to the
AREF pin. If you’re using an external reference on the AREF pin, you must
set the analog reference to EXTERNAL before calling analogRead().
Let’s make the simple voltmeter of Section 3.3 more accurate. Note
that increasing the accuracy is achieved by decreasing the maximum of
input voltage that is applicable to the ADC. Upload the following code to
the board:
int analogPinA0=A0;
int value=0;
double Vref=3.3;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
analogReference(EXTERNAL);
}
void loop() {
value=analogRead(analogPinA0);
137
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
double voltageA0=value*Vref/1023;
Serial.println((String)"Voltage given to ADC A0: "+voltageA0);
Serial.println("------------------------------");
delay(3000);
}
138
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
3.6 Speed of Conversion
The conversion from analog to digital takes some time. The following code
measures this conversion time. Upload the code to the board:
//ADC
//On ATmega based boards (UNO, Nano, Mini, MEGA), it takes
about 100 microseconds
//to read an analog input, so the maximum reading rate is about
10,000 times a second.
//https://www.arduino.cc/reference/en/language/functions/
analog-io/analogread/
int analogPinA0=A0;
int value=0;
double Vref=5.0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
double t0=micros();
value=analogRead(analogPinA0);
double t1=micros();
int deltaT=t1-t0;
double voltageA0=value*Vref/1023;
139
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
Serial.println((String)"Voltage given to ADC A0:
"+voltageA0);
Serial.println("-------------------------------------");
delay(3000);
}
140
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
141
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
When the input voltage is between 0 and 1 V, LED 1 turns on; when
the input voltage is between 1 V and 2 V, LED 1 and LED 2 turn on; when
the input voltage is between 2 V and 3 V, LED 1, LED 2, and LED 3 turn on;
when the input voltage is between 3 V and 4 V, LED 1, LED 2, LED 3, and
142
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
LED 4 turn on; when the input voltage is between 4 V and 5 V, all of the
LEDs are turned on. Upload the code to the board:
int analogPin=A0;
double voltage=0;
double Vref=5.0;
void setup() {
// put your setup code here, to run once:
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);
pinMode(LED4,OUTPUT);
pinMode(LED5,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
voltage=analogRead(analogPin)/1023.0*Vref;
143
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
if (voltage>1.0 && voltage<=2.0){
digitalWrite(LED1,HIGH);
digitalWrite(LED2,HIGH);
digitalWrite(LED3,LOW);
digitalWrite(LED4,LOW);
digitalWrite(LED5,LOW);
}
delay(250);
}
144
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
3.8 Measurement of Negative Voltages
The ADC cannot measure negative voltages. One way to measure negative
voltages is to use a voltage divider. For instance, with the aid of a circuit
shown in Figure 3-13, you can measure the voltages in the [–12 V, +4.8 V]
interval.
145
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
146
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
In Figure 3-14, the voltage that reaches the analog pin is
–0.271×Vin+3.506. For instance, when the analog pin senses 2 V, the input
voltage (Vin) is around +5 V.
Another technique to measure negative voltages can be found in the
references section.
147
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
Let’s make a DC ammeter with this sensor. Upload the following code
to the board. This code measures the current 50 times and displays the
average of measured values. Use the Serial Monitor to see the output of
this code.
148
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
int value=0;
float Vref=5.0;
float sensorSensitivity=66e-3; //ACS712ELC-30 is used here.
float current=0;
float sum=0;
int n=50;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
for (int i=0;i<n;i++){
value=analogRead(A0)-511;
sum=sum+(value*Vref/1023)/sensorSensitivity;
delay(3);
}
current=sum/n;
sum=0;
Serial.println((String)"Measured current is: "+current);
Serial.println("---");
delay(500);
}
149
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
150
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
151
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
The schematic of the breakout board is shown in Figure 3-20.
3.11 PCF8591 As ADC
The following code shows how to use PCF8591 as an ADC. Upload the
code to the Arduino board:
152
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
#define PCF8591_DAC_ENABLE 0x40
#define PCF8591_ADC_CH0 0x40
#define PCF8591_ADC_CH1 0x41
#define PCF8591_ADC_CH2 0x42
#define PCF8591_ADC_CH3 0x43
byte adc_value;
float voltage=0;
void setup(){
Serial.begin(9600);
Wire.begin();
Serial.println("ADC Test");
}
void loop()
{
adc_value = getADC(PCF8591_ADC_CH3); //Channel 3 is the pot
voltage=adc_value*5.0/255.0;
153
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
Serial.println((String)"Voltage of center terminal of the
potentiometer is: "+voltage+" V.");
delay(500);
}
154
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
3.12 PCF8591 As DAC
The following code shows how to convert a digital data into an analog
voltage:
#include <Wire.h>
#define PCF8591 (0x90 >> 1) // Device address = 0
#define PCF8591_DAC_ENABLE 0x40
#define PCF8591_ADC_CH0 0x40
#define PCF8591_ADC_CH1 0x41
#define PCF8591_ADC_CH2 0x42
#define PCF8591_ADC_CH3 0x43
byte dac_value=0;
byte enteredValue=0;
void setup(){
Serial.begin(9600);
Serial.println("Please enter a number in the 0-255 range:");
Wire.begin();
}
155
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
void loop(){
while(Serial.available()>0){
enteredValue=Serial.parseInt();
Serial.println((String)"Entered number is:"+enteredValue);
putDAC(enteredValue);
Serial.println();
Serial.println("Please enter a number in the 0-255 range:");
}
}
156
CHAPTER 3 ANALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
Table 3-2 shows some of the entered values and voltages associated
with them.
0 0.024
10 0.196
20 0.388
30 0.528
40 0.728
50 0.880
60 1.06
70 1.26
80 1.46
(continued)
157
CHAPTER 3 ANALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
Table 3-2. (continued)
90 1.66
100 1.84
110 2.04
120 2.24
130 2.44
140 2.60
150 2.80
160 3.00
170 3.20
180 3.36
190 3.56
200 3.76
210 3.92
220 4.16
230 4.16
240 4.16
250 4.16
Figure 3-24 shows the graph of data in Table 3-2. For values bigger
than 215, saturations are observed. The graph is linear for the [0, 215]
region. Using curve fitting, we obtain Vout=0.01887×n–0.02726 or
n=(Vout+0.02726)/0.01887 for the linear region of the graph (0≤n≤215).
158
CHAPTER 3 A NALOG-TO-DIGITAL CONVERTER (ADC) AND DIGITAL-TO-ANALOG
CONVERTER (DAC)
https://bit.ly/3FV5oP4
[2] Current measurement with ACS712:
https://bit.ly/3FSFD1D
https://bit.ly/2I8clQc
https://bit.ly/3GgWZqv
[4] PCF8591:
https://bit.ly/3PXWHrU
https://bit.ly/3hXoJXF
159
CHAPTER 4
LCD and EEPROM
4.1 Introduction
In this chapter, you will learn how to connect a Liquid Crystal Display
(LCD) and Electrically Erasable Programmable Read-Only Memory
(EEPROM to an Arduino board. Connecting an LCD to an Arduino board
permits you to make portable devices which don’t require to be connected
to a computer in order to show the outputs.
EEPROM plays the role of a hard disk for microcontroller systems.
They can store data even when the power is turned off. ATmega328 (the
microcontroller used in Arduino UNO, Nano, and Mini) has 1024 bytes
of EEPROM memory. The internal EEPROM memory has a specified life
of 100,000 write/erase cycles, so you may need to be careful about how
often you write to it. An EEPROM write takes around 3.3 ms to complete;
therefore, it is not a high-speed memory. This chapter studies both internal
EEPROM and connecting an external EEPROM to Arduino boards.
Let’s take a closer look at LCDs. Normally, LCDs are output devices,
that is, show data to the user. However, they can be input devices as well,
that is, take data from the user. For instance, touchscreen LCDs are both an
output and input device. In this chapter, we will study nontouchable (i.e.,
character LCD) LCDs only.
Character (or text) LCDs can be divided into two groups: parallel
LCDs and I2C LCDs. Parallel LCDs have 16 pins, and they use parallel data
transfer. Therefore, they eat many of the pins of your microcontroller. They
require at least eight pins to work: VCC, GND, and six data pins. Therefore,
they eat six digital I/O pins of your microcontroller. I2C requires only four
pins: VCC, GND, and I2C pins (SCL and SDA). They don’t eat digital I/O
pins of your microcontroller. In the Arduino UNO board, SDA and SCL are
connected to A4 and A5 pins. If you connect an I2C LCD to the board, then
you cannot use A4 and A5 for analog-to-digital conversion purposes. In
other words, you will lose two analog pins.
Character LCDs are known by the number of rows and number of
characters that can be shown in each row. For instance, a 2×16 LCD has
two rows, and each row can contain up to 16 characters.
Figure 4-1 shows a parallel LCD. Table 4-1 studies each pin in detail.
162
Chapter 4 LCD and EEPROM
Pin 1 This is the ground pin Connected to the ground of the Arduino board
(VSS) of the LCD
Pin 2 This is the supply Connected to +5 V of the Arduino board
(VDD) voltage of the LCD
Pin 3 Adjusts the contrast of Connected to a variable POT that can source
(V0) the LCD 0–5 V (Figure 4-2)
Pin 4 Toggles between Connected to an MCU pin and gets either 0 or 1.
(RS) command and data 0 for command mode and 1 for data mode
registers
Pin 5 Toggles the LCD Connected to the ground
(RW) between read and write
operations
Pin 6 (E) Enable Connected to the Arduino board and always held
high
Pin Data bits In 4-wire mode, only 4 pins (0–3) are connected
(7–14) to the Arduino board. In 8-wire mode, all 8 pins
D0…D7 (0–7) are connected to the Arduino board
Pin 15 Anode of a backlight Connected to +5 V through a 220 Ω resistor
(A) LED (Figure 4-3)
Pin 16 Cathode of a backlight Connected to the ground (Figure 4-3)
(K) LED
163
Chapter 4 LCD and EEPROM
164
Chapter 4 LCD and EEPROM
165
Chapter 4 LCD and EEPROM
After uploading the code and in the first run, the LCD may show
meaningless symbols. In this case, simply press the reset button on the
Arduino board to reset the system.
#include <LiquidCrystal.h>
/*
- LCD's VSS -> Ground pin of Arduino
- LCD's VDD -> +5 V pin of Arduino
- LCD's V0 pin -> Center terminal of potentiometer
- LCD's RS pin -> Arduino's pin 12
- LCD's R/W pin-> Ground
- LCD's Enable (E) pin -> Arduino's pin 11
- LCD's D0, D1, D2 and D3 pins -> Not connected
- LCD's D4 pin -> Arduino's pin 5
- LCD's D5 pin -> Arduino's pin 4
- LCD's D6 pin -> Arduino's pin 3
- LCD's D7 pin -> Arduino's pin 2
*/
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
lcd.begin(16, 2); //number of column and rows
lcd.print("Time elpassed:");
}
void loop() {
lcd.setCursor(0,1); // cursor is put at first column of
second row
lcd.print((String)(millis()/1000)+" sec.");
}
166
Chapter 4 LCD and EEPROM
int Address=0x27;
#include <Wire.h>
#include <LiquidCrystal_I2C.h> //https://www.arduino.cc/
reference/en/libraries/liquidcrystal-i2c/
void setup() {
// put your setup code here, to run once:
lcd.init();
lcd.backlight(); //Turns on the backlight
//lcd.noBacklight(); //Turns off the backlight
}
void loop() {
// put your main code here, to run repeatedly:
lcd.setCursor(0,0); // (Column, Row)
i=i+1;
167
Chapter 4 LCD and EEPROM
lcd.print((String)"i= "+i);
delay(1000);
lcd.setCursor(0,1);
lcd.print("Second Line...");
}
4.4 Internal EEPROM
The following code writes a random number between 0 and 255 to the
location 0 of EEPROM and reads the content of location 0.
The following code uses the EEPROM.update(address, value)
command to write a value at the location determined by the address. You
can use the EEPROM.write(address, value) command to write a value at
the location determined by the address as well. However, the use of the
EEPROM.update command is recommended. Because the EEPROM.
update command compares the value that is requested to be written with
the current content of that location. If two values are the same, then no
writing takes place. However, the EEPROM.write command writes the
value even when the two values (the value requested to be written and the
168
Chapter 4 LCD and EEPROM
current content of that address) are the same. Remember that the number
of writings to EEPROM is limited. Therefore, EEPROM.update doesn’t
consume the lifetime of the EEPROM without reason.
#include <EEPROM.h>
byte a=0;
int selection=0;
void setup()
{
Serial.begin(9600);
randomSeed(analogRead(A0));
Serial.println("1.Write to EEPROM");
Serial.println("2.Read EEPROM");
}
void loop(){
if (Serial.available()>0){
selection=Serial.parseInt();
if (selection==1){
a=random(255+1); //value of generated random number a is
between 0 and 255.
EEPROM.update(0,a);
Serial.println((String)"\n"+a+" is written to the
EEPROM...");
}
if (selection==2){
Serial.println((String)"Value of EEPROM at location 0 is:
"+EEPROM.read(0)+".\n");
}
}
}
169
Chapter 4 LCD and EEPROM
#include <EEPROM.h>
double a=1.23;
double b=45.67;
double c=890.12;
double readValue=0.00;
int selection=0;
int n=0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
170
Chapter 4 LCD and EEPROM
EEPROM.put(0,a);
EEPROM.put(sizeof(a),b);
EEPROM.put(sizeof(a)+sizeof(b),c);
}
void loop() {
// put your main code here, to run repeatedly:
if (Serial.available()>0){
selection=Serial.parseInt();
if (selection==1){
n=0;
EEPROM.get(n,readValue);
Serial.println((String)"Value stored at location 0 is:
"+readValue+".");
};
if (selection==2){
n=sizeof(a);
EEPROM.get(n,readValue);
Serial.println((String)"Value stored at location "+n+"
is: "+readValue+".");
};
if (selection==3){
n=sizeof(a)+sizeof(b);
EEPROM.get(n,readValue);
Serial.println((String)"Value stored at location "+n+"
is: "+readValue+".");
};
}
}
171
Chapter 4 LCD and EEPROM
4.6 External EEPROM
External EEPROM ICs can be used to store what you want. In this section,
we will see how 24LC16B EEPROM can be connected to Arduino. The WP
(Write Protect) pin of 24LC16B must be connected to 0 V; otherwise, you
cannot write over it. Upload the following code to the Arduino. This code
writes and retrieves the byte data type:
#include "Wire.h"
#include "I2C_eeprom.h"
byte x[]={0,1,2,3,4};
byte y[]={10,1,2,3,40};
byte z[]={0,0,0,0,0,0};
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
ee.begin();
}
void loop() {
// put your main code here, to run repeatedly:
ee.writeBlock(0, (uint8_t *) &x, sizeof(x)); // Starts from
location 0 and
writes array x
ee.writeByte(5,7); //Writes 7 at location 5
for (int i=0;i<6;i++){
172
Chapter 4 LCD and EEPROM
Serial.println();
ee.updateBlock(0, (uint8_t *) &y, sizeof(y));
for (int i=0;i<6;i++){
Serial.println((String)"At location "+i+" of EEPROM "+ee.
readByte(i)+" is written.");
}
Serial.println();
ee.readBlock(0, (uint8_t *) &z, 6);
for (int i=0;i<6;i++){
Serial.println((String)"z("+i+")= "+z[i]+" is written.");
}
Serial.println();
ee.setBlock(0,1, 6); //Writes 1 in the first 6 locations
for (int i=0;i<6;i++){
Serial.println((String)"At location "+i+" of EEPROM "+ee.
readByte(i)+" is written.");
}
delay(60000);
}
173
Chapter 4 LCD and EEPROM
#include "Wire.h"
#include "I2C_eeprom.h"
float x=12.34;
float y=0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
ee.begin();
ee.setBlock(0,0,sizeof(x));
ee.writeBlock(0,(uint8_t *) &x, sizeof(x));
}
174
Chapter 4 LCD and EEPROM
void loop() {
// put your main code here, to run repeatedly:
ee.readBlock(0,(uint8_t *) &y, sizeof(y));
Serial.println(y);
delay(10000);
}
#include "Wire.h"
#include "I2C_eeprom.h"
175
Chapter 4 LCD and EEPROM
struct measurement{
float temp;
int pressure;
char* location;
};
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
ee.begin();
ee.setBlock(0,0,sizeof(measurement));
}
void loop() {
// put your main code here, to run repeatedly:
measurement m1;
measurement m2;
m1.temp=32.7;
m1.pressure=12;
m1.location="Inside the city.";
Serial.println((String)"m2.temp="+m2.temp);
Serial.println((String)"m2.pressure="+m2.pressure);
Serial.println((String)"m2.location="+m2.location);
Serial.println("-----");
delay(10000);
}
176
Chapter 4 LCD and EEPROM
https://bit.ly/3FXIGWf
https://bit.ly/3G2I7uG
[3] Connection of external EEPROM to the Arduino:
https://bit.ly/3WJBqnT
https://bit.ly/3Vo1Bzu
https://bit.ly/3VkR3Rr
https://bit.ly/3WrA55d
https://bit.ly/3WLRZiS
177
CHAPTER 5
Serial Communication
5.1 Introduction
This chapter focuses on universal asynchronous receiver/transmitter
(UART)–based serial communication between the Arduino board and
your computer. Serial communication uses pins 0 and 1 (Figure 5-1).
Serial communication helps us to show results on the computer screen
with the aid of a tool called Serial Monitor. A Serial Monitor is a part of the
Arduino IDE. For instance, assume that you read the voltage of an analog
pin. In this case, you have two options to see the measured value: (1) use
an LCD and show the measured value on it; (2) use serial communication
and show the measured value on a computer screen. The first method
requires an LCD, and the LCD must be connected to the Arduino board
using suitable connections. However, in the second method, everything
is prepared already, and you need to write a few lines of code. In the
second method, data transfer will be done using the USB cable connected
between the computer and the Arduino board.
A UART channel has two data lines. There is an RX pin and a TX pin
on each device (RX for receive and TX for transmit). Each device’s RX pin
is connected to the other device’s TX pin (Figure 5-2). Note that there are
no shared clock lines! This is the asynchronous aspect of the universal
asynchronous receiver/transmitter.
180
Chapter 5 Serial Communication
181
Chapter 5 Serial Communication
182
Chapter 5 Serial Communication
183
Chapter 5 Serial Communication
int a=10;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
184
Chapter 5 Serial Communication
void loop() {
// put your main code here, to run repeatedly:
Serial.println(a);
}
int a=0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
if (Serial.available()>0)
a=Serial.parseInt();
}
185
Chapter 5 Serial Communication
long randNumber=0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
randomSeed(analogRead(0));
}
void loop() {
// put your main code here, to run repeatedly:
186
Chapter 5 Serial Communication
After uploading the code, open the Serial Monitor in order to see the
output of the code.
//https://www.arduino.cc/reference/en/language/functions/
communication/serial/readstring/
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(LED_BUILTIN,OUTPUT);
}
void loop() {
if (Serial.available()>0){
String inputCommand=Serial.readString();
Serial.println((String)"Entered command: "+inputCommand);
187
Chapter 5 Serial Communication
digitalWrite(LED_BUILTIN,HIGH);
}
if (inputCommand=="off"||inputCommand=="OFF"||inputCommand==
"Off")
{
digitalWrite(LED_BUILTIN,LOW);
}
}
}
Open the Serial Monitor after uploading the code to the board. Enter
the command into the Serial Monitor window and press the Enter key
to run it (Figure 5-8). Select the “No line ending” to avoid addition of
anything to what you entered.
188
Chapter 5 Serial Communication
//https://www.arduino.cc/reference/en/language/functions/
communication/serial/parsefloat/
//parsInt command exist as well.
float radius=0;
float area=0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("Strated...");
}
void loop() {
if (Serial.available()>0){
radius=Serial.parseFloat();
area=PI*pow(radius,2);
Open the Serial Monitor after uploading the code to the board. Enter
the radius into the Serial Monitor window and press the Enter key to
see the calculated area (Figure 5-9). Select the “No line ending” to avoid
addition of anything to what you entered.
189
Chapter 5 Serial Communication
int incomingNumber=0;
int a=1;
int b=1;
int c=0;
int s=0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("Enter the number of terms that you want.");
}
190
Chapter 5 Serial Communication
void loop() {
// put your main code here, to run repeatedly:
if (Serial.available()>0){
incomingNumber=Serial.parseInt();
Serial.println((String)"User entered "+incomingNumber+".");
Serial.print("1,1,");
for (int i=1;i<=incomingNumber-2;i++){
s=a+b;
Serial.print((String)s+',');
c=a;
a=b;
b=c+b;
}
}
}
Open the Serial Monitor after uploading the code to the board. Enter
the number of terms that you want into the Serial Monitor window and
press the Enter key to see the output (Figure 5-10). Select the “No line
ending” to avoid addition of anything to what you entered.
191
Chapter 5 Serial Communication
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("\"Hello World!\" is the first program that
programmers write.");
Serial.println("'Hello World!\' is the first program that
programmers write.");
Serial.println();
delay(120000);
}
5.8 Printing Binary
and Hexadecimal Numbers
Serial.print and Serial.println commands can print the binary and
hexadecimal representations of a variable. The following is an example.
Note that 45 in decimal is equal to 00101101 in binary and 2D in
hexadecimal.
byte b = 45;
void setup() {
Serial.begin(9600);
Serial.println(b); // print in decimal by default
192
Chapter 5 Serial Communication
Open the Serial Monitor after uploading the code to the board. The
output of the code is shown in the Serial Monitor window.
void setup(){
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop(){
// put your main code here, to run repeatedly:
Serial.println((String)"Given string is: "+str);
Serial.println();
193
Chapter 5 Serial Communication
Serial.println();
Serial.println((String)"\"ABC DEF\" is compared with
\"ABC DEF\" (comparison is case sensitive). Result is:
"+str.equals(str2));
Serial.println((String)"\"ABC DEF\" is compared with
\"xyz\" (comparison is case sensitive). Result is:
"+str.equals(str4));
Serial.println((String)"\"ABC DEF\" is compared with
\"ABC dEf\" (comparison is not case sensitive). Result is:
"+str.equalsIgnoreCase(str3));
Serial.println();
str.toLowerCase(); //Result is saved in the str variable.
Serial.println("Conversion of \"ABC DEF\" to lower case: "+str);
str3.toUpperCase(); //Result is saved in the str variable.
Serial.println("Conversion of \"xyz\" to upper case: "+str3);
194
Chapter 5 Serial Communication
Serial.println();
String str7="ABCDEFGHIJKLM";
str7.remove(2,3);
Serial.println((String)"remove(2,3) is applied to
\"ABCDEFGHIJKLM\". Result is: \""+str7+"\".");
String str8="123";
int sum1=str8.toInt()+5;
Serial.println();
Serial.println((String)"sum= "+sum1+". Expected value
is 128.");
String str9="123.456";
float sum2=str9.toFloat()+5.0;
Serial.println();
Serial.println((String)"sum= "+sum2+". Expected value is
128.456.");
String str10="123.456";
double sum3=str10.toDouble()+5.0;
Serial.println();
Serial.println((String)"sum= "+sum3+". Expected value is
128.456.");
Serial.println("------------------------------------------");
delay(180000);
}
Open the Serial Monitor after uploading the code to the board. The
output of the code is shown in the Serial Monitor window.
195
Chapter 5 Serial Communication
5.10 Useful Functions
for Character Variables
The Arduino IDE has many useful functions to work with character
variables. A list of these functions can be found in the Characters section of
the Arduino website (Figure 5-11).
196
Chapter 5 Serial Communication
char ch1;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
ch1=Serial.read();
if (Serial.available()>0){
Serial.println((String)"ch1="+ch1);
if (isUpperCase(ch1)){
Serial.println("variable ch1 is UPPERCASE.");
}else{
Serial.println("variable ch1 is lowercase.");
}
if (isDigit(ch1)){
Serial.println("variable ch1 is a digit.");
}else{
Serial.println("variable ch1 is not a digit.");
}
Serial.println();
}
delay(1000);
}
197
Chapter 5 Serial Communication
Open the Serial Monitor after uploading the code to the board. The
output of the code is shown in the Serial Monitor window. Sample outputs
for “a” and “Ab1” are shown in Figures 5-12 and 5-13.
198
Chapter 5 Serial Communication
https://bit.ly/3WG04X3
[2] Comparison of UART with I2C and SPI:
https://bit.ly/3HZvyTr
https://bit.ly/2LLOzbI
199
CHAPTER 6
Mathematical
Functions
6.1 Introduction
Mathematical operations are indispensable part of many programs. This
chapter shows how mathematical operations can be done with Arduino.
//https://www.arduino.cc/en/math/h
//asin can be calculated with the aid of //https://
tr.wikipedia.org/wiki/Ters_trigonometrik_fonksiyonlar
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
randomSeed(analogRead(0));
}
void loop() {
Serial.println("Compare the given results with what
calculated by Arduino.");
Serial.println();
float x=12.34;
float y=5.678;
float z=x/y;
int t=x/y;
Serial.println();
Serial.println((String) "Note that 12.34/5.678=2.17330");
Serial.println((String) "float z=12.34/5.678= "+z);
Serial.println((String) "int t=12.34/5.678= "+t);
Serial.println();
Serial.println((String) "Reminder of 5/2 is:"+5%2);
Serial.println((String) "Reminder of 7/4 is:"+7%4);
Serial.println();
Serial.println("sin, cos and tan takes the angle in
RADYANS.");
Serial.println((String)"Note that sin(pi/6)=0.5");
Serial.println((String) "sin(pi/6)= "+sin(PI/6));
Serial.println();
Serial.println((String)"Note that cos(pi/6)=0.866");
Serial.println((String) "cos(pi/6)= "+cos(PI/6));
Serial.println();
Serial.println((String)"Note that tan(pi/6)=0.5774");
Serial.println((String) "tan(pi/6)= "+tan(PI/6));
Serial.println();
Serial.println((String)"Note that cot(pi/6)=1.7319");
Serial.println((String) "cot(pi/6)= "+1/tan(PI/6));
202
Chapter 6 Mathematical Functions
Serial.println();
Serial.println((String)"Note that atan(1.5)=0.98279 Rad");
Serial.println((String) "atan(1.5)= "+atan(1.5));
Serial.println((String) "atan2(1.5,1)= "+atan2(1.5,1));
Serial.println((String) "atan2(-1.5,-1)= "+atan2(-1.5,-1));
Serial.println();
Serial.println((String)"Note that exp(2.6)=13.4637");
Serial.println((String) "exp(2.6)= "+exp(2.6));
Serial.println();
Serial.println((String)"Note that ln(2)=0.6931 and
log10(2)=0.3010");
Serial.println((String) "log(2)= "+log(2));
Serial.println((String) "log10(2)= "+log10(2));
Serial.println();
Serial.println((String) "floor(1.2)= "+floor(1.2));
Serial.println((String) "floor(-1.2)= "+floor(-1.2));
Serial.println((String) "ceil(1.2)= "+ceil(1.2));
Serial.println((String) "ceil(-1.2)= "+ceil(-1.2));
Serial.println();
Serial.println((String)"Note that 5.2^3.4=271.901");
Serial.println((String) "5.2^3.4= "+pow(5.2,3.4));
Serial.println();
Serial.println((String)"Note that 7.3^0.5=2.7019");
Serial.println((String) "sqrt(7.3)= "+sqrt(7.3));
203
Chapter 6 Mathematical Functions
Serial.println();
Serial.println((String) "square of 1.23, i.e. 1.23^2= "+
sq(1.23));
Serial.println((String) "square root of 1.23, i.e.
1.23^0.5= "+ sqrt(1.23));
Serial.println();
Serial.println((String) "Random number between 10 and 20:
"+random(10,20+1));
Serial.println((String) "Random number between 0 and 20:
"+random(20+1));
Serial.println();
Serial.println((String) "Max(1.23,4.56)= "+
max(1.23,4.56));
Serial.println((String) "Min(1.23,4.56)= "+
min(1.23,4.56));
Serial.println(); //https://www.arduino.cc/reference/en/
language/functions/math/constrain/
Serial.println((String) "constrain(0,1,10)=
"+constrain(0,1,10));
Serial.println((String) "constrain(5,1,10)=
"+constrain(5,1,10));
Serial.println((String) "constrain(15,1,10)=
"+constrain(15,1,10));
delay(60000);
}
204
Chapter 6 Mathematical Functions
6.3 Overflow of Variables
When you use a variable, you must ensure that the value that it saves lies in
the allowed range for that variable. For instance, integer (int) variables can
take a number from –32768 to +32767. If a stored value is outside of this
range, then it is not stored correctly. For instance, in the following code,
33000 is assigned to an int variable:
int i=33000;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("Value of 33000 is assigned to int
variable i.");
Serial.println((String)"Value of i is: "+i);
delay(10000);
}
205
Chapter 6 Mathematical Functions
Upload the code to the board and open the Serial Monitor to see the
output. As shown in Figure 6-1, the value of variable i is not the expected
value (33000).
6.4 E Notation
You can use the E or e in order to enter numbers given in scientific format.
In the following code, a=1000, b=0.053, and c=0.000123. Note that the
output of this code for a×c is rounded to 0.00.
double a=1E3;
double b=5.3E-2;
double c=1.23e-4;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
206
Chapter 6 Mathematical Functions
void loop() {
// put your main code here, to run repeatedly:
Serial.println("1000*0.053=53");
Serial.println((String)"a*b= "+a*b);
Serial.println();
Serial.println("1000*0.000123=0.123");
Serial.println((String)"a*c= "+a*c);
Serial.println();
Serial.println("0.053*0.000123=0.0000065190");
Serial.println((String)"b*c= "+b*c);
Serial.println();
delay(15000);
}
6.5 Map Function
The map function linearly converts values from an input range to values
from another range. For instance, assume that we are given a value x from
the [a, b] interval, that is, x ∈ [a, b]. We want to find value y from [c, d]
that is linearly proportional with the given point and interval. We need
x −a y −a
to solve +a = + c . After simple algebraic operations, we reach
b−a d −c
d −c
to y = ( x − a ) + ( d − c ) ( a − c ) + c . The map function implements this
b−a
formula. For instance, int mappedVal=map(328,0,1024,0,255) converts 328
from [0,1024] into a proportional value from the [0,255] interval (x=328,
a=0, b=1024, c=0, d=255). This command returns 81.
207
Chapter 6 Mathematical Functions
int dutyCycle=0;
void setup() {
pinMode(9,OUTPUT);
}
void loop() {
dutyCycle = analogRead(A0);
dutyCycle = map(dutyCycle, 0, 1023, 0, 255);
analogWrite(9, dutyCycle);
}
300
250
200
150
100
50
0
0 200 400 600 800 1000 1200
208
Chapter 6 Mathematical Functions
6.6 sizeof Operator
The sizeof operator returns the number of bytes in a variable type or the
number of bytes occupied by an array. Upload the following code to the
board. Use the Serial Monitor to see the output of the code. Note that for
Arduino UNO, float and double data types are the same. However, in the
Arduino DUE board, a float takes 4 bytes and double takes 8 bytes.
209
Chapter 6 Mathematical Functions
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println((String)"int takes "+sizeof(a)+" Bytes.");
Serial.println((String)"unsigned int takes "+sizeof(b)+"
Bytes.");
Serial.println((String)"short takes "+sizeof(c)+" Bytes.");
Serial.println((String)"long takes "+sizeof(d)+" Bytes.");
Serial.println((String)"unsigned long takes "+sizeof(e)+"
Bytes.");
Serial.println((String)"byte takes "+sizeof(f)+" Bytes.");
Serial.println((String)"word takes "+sizeof(g)+" Bytes.");
Serial.println((String)"float takes "+sizeof(h)+" Bytes.");
Serial.println((String)"double takes "+sizeof(i)+" Bytes.");
Serial.println((String)"char takes "+sizeof(j)+" Bytes.");
Serial.println((String)"bool takes "+sizeof(k)+" Bytes.");
Serial.println((String)"char array
{'A','r','d','u','i','n','o'} takes "+sizeof(ch)+" Bytes.");
Serial.println("--------------------------------");
delay(60000);
}
210
Chapter 6 Mathematical Functions
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println((String)"Value of a in decimal is: "+a);
Serial.println();
211
Chapter 6 Mathematical Functions
https://bit.ly/2HtPHhC
https://bit.ly/3FULbJ5
https://bit.ly/3PRlyNT
https://bit.ly/2Lve1mn
212
CHAPTER 7
Pulse Width
Modulation (PWM)
7.1 Introduction
The duty cycle for a periodic pulse is defined as the ratio of the high
section divided by the period. In Figure 7-1, all of the pulses have the same
period and frequency; however, their duty cycles are different. When the
duty cycle increases, the average and RMS values of the signal increase. For
instance, the waveform with a 75% duty cycle has the maximum average
and RMS values between the signals shown in Figure 7-1.
RMS and average values for a pulse with a duty ratio of D and a high
level of V are equal to D × V and D × V, respectively. For instance, RMS
and average values of the signal with a 75% duty cycle shown in Figure 7-1
are D ×V = 0.75 × 5 = 4.33 V and D × V = 0.75 × 5 = 3.75 V, respectively.
Pulse width modulation (PWM) is a method of reducing the average
power delivered by an electrical signal by effectively chopping it up into
discrete parts. PWM can be used to control the speed of DC motors and
intensity of the LED’s lights.
Arduino can be used to generate PWM signals. Pins that have a tilde
(~) symbol behind them (pins 3, 5, 6, 9, 10, and 11 in Figure 7-2) can be
used to generate PWM signals. The frequency of the output waveform for
pins 3, 9, 10, and 11 is 490.2 Hz by default. The default PWM frequency for
pins 5 and 6 is 976.56 Hz. At the end of this chapter, you will learn how to
change this default frequency.
214
Chapter 7 Pulse Width Modulation (PWM)
215
Chapter 7 Pulse Width Modulation (PWM)
void setup() {
// put your setup code here, to run once:
pinMode(pwmPin, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
analogWrite(pwmPin,dutyCycle*255);
}
void setup() {
// put your setup code here, to run once:
pinMode(pwmPin, OUTPUT);
}
216
Chapter 7 Pulse Width Modulation (PWM)
void loop() {
// put your main code here, to run repeatedly:
analogWrite(pwmPin,dutyCycle*255);
}
//frequency = 490 Hz
int pwmPin=9;
void setup() {
// put your setup code here, to run once:
pinMode(pwmPin, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
analogWrite(pwmPin,analogRead(A0)/4);
}
217
Chapter 7 Pulse Width Modulation (PWM)
You can use the generated PWM signal to control the speed of a
small DC motor (Figure 7-4). Increasing the duty cycle of the PWM signal
increases the speed of the motor.
218
Chapter 7 Pulse Width Modulation (PWM)
219
Chapter 7 Pulse Width Modulation (PWM)
int LED=9;
int Delay=30;
int dutyCycle=0;
void setup() {
// put your setup code here, to run once:
pinMode(LED,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
dutyCycle=0;
for (int i=0;i<17;i++){
dutyCycle=dutyCycle+15;
analogWrite(LED,dutyCycle);
delay(Delay);
}
delay(500);
}
220
Chapter 7 Pulse Width Modulation (PWM)
The code of this example can be written with the aid of functions as
well. In the following code, the fade function turns on and off the LED
smoothly:
int LED=9;
int Delay=30;
int dutyCycle=0;
void setup() {
// put your setup code here, to run once:
pinMode(LED,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
fade(3);
delay(2000);
}
221
Chapter 7 Pulse Width Modulation (PWM)
dutyCycle=dutyCycle+15;
analogWrite(LED,dutyCycle);
delay(Delay);
}
delay(500);
}
}
222
Chapter 7 Pulse Width Modulation (PWM)
Table 7-2. Codes to change the PWM frequency of pins D9 and D10
Frequency (Hz) Required Code
Table 7-3. Codes to change the PWM frequency of pins D3 and D11
Frequency (Hz) Required Code
223
Chapter 7 Pulse Width Modulation (PWM)
Let’s study an example to see how these tables can be used. For
instance, assume that we want to generate a PWM signal with a frequency
of 31.372 kHz and a duty cycle of 30% on pin 9 of the Arduino board. The
following code does this job for us:
void setup() {
// put your setup code here, to run once:
pinMode(pwmPin, OUTPUT);
TCCR1B = TCCR1B & B11111000 | B00000001;
}
void loop() {
// put your main code here, to run repeatedly:
analogWrite(pwmPin,dutyCycle*255);
}
You can connect an oscilloscope to pin 9 and ensure that the generated
waveform is what we expect.
https://bit.ly/3GjFq94
https://bit.ly/3vitka0
224
CHAPTER 8
Control of Different
Types of Motors
8.1 Introduction
Motors are building blocks of many projects. This chapter shows how
different types of motors can be controlled with an Arduino board.
int shaftAngle=0;
#include <Servo.h>
Servo servo1;
void setup() {
// put your setup code here, to run once:
servo1.attach(9);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
shaftAngle=map(analogRead(A0),0,1023,0,180);
servo1.write(shaftAngle);
Serial.println((String)"Given command: "+shaftAngle);
delay(100);
}
226
Chapter 8 Control of Different Types of Motors
227
Chapter 8 Control of Different Types of Motors
The SG90 servo motor without any load makes no problem for the
Arduino board shown in Figure 8-1. Therefore, you can use the schematic
shown in Figure 8-1. The shaft of the motor rotates when you rotate the
potentiometer shaft.
8.3 Control of BLDC
In this section, we want to control the speed of a Brushless Direct Current
(BLDC) motor. You need a driver in order to control the speed of a BLDC
motor. The driver has eight wires: two wires for motor supply, three wires
for connecting the motor windings to the driver, and three wires for taking
the control signals. These three wires are connected to the Arduino board.
The three wires that reconnected to the Arduino have red, brown, and
orange colors. Red and brown supply the driver board, and the control
signal is applied to the orange terminal. Red, brown, and orange wires are
thin; other wires are thick.
Upload the following code to the board:
/*
Arduino Brushless Motor Control
*/
#include <Servo.h>
void setup() {
// Attach the ESC on pin 9
ESC.attach(9,1000,2000); // (pin, min pulse width, max pulse
width in microseconds)
}
228
Chapter 8 Control of Different Types of Motors
void loop() {
potValue = analogRead(A0); // reads the value of the
potentiometer (value between 0 and 1023)
potValue = map(potValue, 0, 1023, 0, 180); // scale it to
use it with the servo library (value between 0 and 180)
ESC.write(potValue); // Send the signal to the ESC
}
Stepper motors typically have a step size of 1.8° or 200 steps per
revolution; this refers to full steps. A microstepping driver such as the A4988
allows higher resolutions by allowing intermediate step locations. This is
achieved by energizing the coils with intermediate current levels. For instance,
driving a motor in quarter-step mode will give the 200-step-per-revolution
motor 800 microsteps per revolution by using four different current levels. The
resolution (step size) selector pins (MS1, MS2, and MS3) allow you to select
one of the five step resolutions according to Table 8-1. When you leave MS1,
MS2, and MS3 unconnected, the motor is in full step as well.
230
Chapter 8 Control of Different Types of Motors
The following code rotates the Stepper motor shaft one revolution
in the clockwise direction and one revolution in the counterclockwise
direction. Upload the code to the board:
void setup() {
// Declare pins as output:
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
}
void loop() {
// Set the spinning direction clockwise:
Rotate(200); //Rotate the motor 1 revolution
delay(500);
RotateReverse(200); //Rotate the motor 1 revolution in the
reverse direction
delay(500);
}
231
Chapter 8 Control of Different Types of Motors
digitalWrite(stepPin, LOW);
delayMicroseconds(Delay);
}
}
232
Chapter 8 Control of Different Types of Motors
Upload the following code to the Arduino board. This code rotates
the shaft one revolution in the clockwise direction, waits for one second,
rotates the shaft one revolution in the counterclockwise direction, waits for
one second, and repeats this process.
233
Chapter 8 Control of Different Types of Motors
#define IN1 8
#define IN2 9
#define IN3 10
#define IN4 11
#define Delay 2
void setup() {
// put your setup code here, to run once:
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
}
void loop() {
// put your main code here, to run repeatedly:
Rotate(512); // Rotates the shaft 1 full revolution
delay(1000);
RotateReverse(512);
delay(1000);
}
234
Chapter 8 Control of Different Types of Motors
delay(Delay);
digitalWrite(IN1,LOW);
digitalWrite(IN2,HIGH);
delay(Delay);
digitalWrite(IN2,LOW);
digitalWrite(IN3,HIGH);
delay(Delay);
digitalWrite(IN3,LOW);
digitalWrite(IN4,HIGH);
delay(Delay);
digitalWrite(IN4,LOW);
}
}
digitalWrite(IN3,HIGH);
delay(Delay);
digitalWrite(IN3,LOW);
digitalWrite(IN2,HIGH);
delay(Delay);
digitalWrite(IN2,LOW);
digitalWrite(IN1,HIGH);
delay(Delay);
digitalWrite(IN1,LOW);
}
}
235
Chapter 8 Control of Different Types of Motors
236
Chapter 8 Control of Different Types of Motors
Working with DC motor driver boards is quite easy. Nearly all of the
DC motor drivers use the same interface. All of the DC motor driver boards
are composed of the following pins:
1) Motor supply voltage terminals: The energy of the
motor is supplied from these pins.
238
Chapter 8 Control of Different Types of Motors
239
Chapter 8 Control of Different Types of Motors
#define IN1 8
#define IN2 9
#define EN 10
void setup() {
// put your setup code here, to run once:
pinMode(IN1,OUTPUT);
pinMode(IN2,OUTPUT);
pinMode(EN,OUTPUT);
}
240
Chapter 8 Control of Different Types of Motors
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(IN1,HIGH);
digitalWrite(IN2,LOW);
analogWrite(EN,125);
delay(3000);
digitalWrite(IN1,LOW);
digitalWrite(IN2,LOW);
delay(1000);
digitalWrite(IN1,LOW);
digitalWrite(IN2,HIGH);
analogWrite(EN,250);
delay(3000);
}
8.7 Reading an Encoder
An encoder is used to convert the angular position or motion of a shaft to
digital output signals. Encoders are used for closed loop control of electric
motors (Figure 8-11). Some types of encoders are used as input devices
and permit the Arduino to take some variables from the user (Figure 8-12).
For instance, in Figure 8-1 we used a potentiometer to control the shaft
of a servo motor. You can replace the potentiometer with an encoder. In
this case, the servo motor moves clockwise when the shaft of the encoder
is rotated clockwise and moves counterclockwise when the shaft of the
encoder is rotated counterclockwise. Refer to the references given at the
end of this chapter if you are not familiar with the working principle of
encoders.
241
Chapter 8 Control of Different Types of Motors
242
Chapter 8 Control of Different Types of Motors
//visit: http://www.pjrc.com/teensy/td_libs_Encoder.html
//Download the library from https://github.com/
PaulStoffregen/Encoder
#include <Encoder.h>
void setup() {
Serial.begin(9600);
Serial.println("Basic Encoder Test:");
}
void loop() {
long newPosition = myEnc.read();
if (newPosition != oldPosition) {
oldPosition = newPosition;
Serial.println(newPosition);
}
}
243
Chapter 8 Control of Different Types of Motors
If you don’t have an encoder, you can use the simple circuit shown
in Figure 8-14. The clock can come from a fancy function generator or a
cheap 555 timer chip. The frequencies of OutA and OutB are equal to each
other; however, there exists a 90° of phase difference between them. The
frequency of the output is one fourth of the frequency of the input clock.
244
Chapter 8 Control of Different Types of Motors
int shaftAngle=0;
#include <Encoder.h>
#include <Servo.h>
245
Chapter 8 Control of Different Types of Motors
void setup() {
// put your setup code here, to run once:
servo1.attach(9);
Serial.begin(9600);
}
void loop() {
// write command is explained in https://www.pjrc.com/teensy/
td_libs_Encoder.html
long newPosition = myEnc.read();
//following two lines force the encoder to generate a number
between 0 and 1800.
if (newPosition<0) myEnc.write(0);
if (newPosition>1800) myEnc.write(1800);
246
Chapter 8 Control of Different Types of Motors
https://bit.ly/3vjjCnU
[2] Stepper motor control with A4988:
https://bit.ly/3Il1dPt
https://bit.ly/3VrmEkG
https://bit.ly/2Ga9wOD
247
Chapter 8 Control of Different Types of Motors
https://bit.ly/3FNjLVu
[6] Encoder:
https://bit.ly/3PT0qa7
https://bit.ly/2U3JSm3
248
CHAPTER 9
Interrupts and Internal
Comparator
9.1 Introduction
An interrupt is a signal emitted by hardware or software when a process
or an event needs immediate attention. It alerts the processor to a high
priority process requiring interruption of the current working process.
When the event or interrupt happens, the processor takes immediate
notice, saves its execution state, runs a small chunk of code (Interrupt
Service Routine, ISR), and then returns back to whatever it was
doing before.
Consider a case; while a car is running, the microcontroller is busy
sensing the speed of the car, checking other sensors, controlling the air
conditioner temperature, etc. But suddenly an accident happened! At that
time, the controller stops all the works and goes to the airbag activation
section. So what makes a sudden opening of airbag in seconds? An
interrupt signal is used here which has the highest priority of all.
250
Chapter 9 Interrupts and Internal Comparator
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(9,OUTPUT);
analogWrite(9,122);
pinMode(2,INPUT);
attachInterrupt(digitalPinToInterrupt(2),ISR_
measureFreq,RISING);
}
void loop() {
// put your main code here, to run repeatedly:
if (b){
Serial.println((String)"Freq. is: "+ 1E6/(t1-t0) +" Hz.");
t0=t1;
b=false;
}
}
void ISR_measureFreq(){
t1=micros();
b=true;
}
251
Chapter 9 Interrupts and Internal Comparator
After uploading the code and connecting pin 2 to 9, open the Serial
Monitor to see the result of measurement (Figure 9-2).
252
Chapter 9 Interrupts and Internal Comparator
253
Chapter 9 Interrupts and Internal Comparator
int deltaT=1000;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
pinMode(9,OUTPUT);
analogWrite(9,122);
pinMode(2,INPUT);
attachInterrupt(digitalPinToInterrupt(2),ISR_
measureFreq,RISING);
}
void loop() {
// put your main code here, to run repeatedly:
if (b){
t3=millis();
if ((t3-t2)>deltaT){
Serial.println((String)"Freq. is: "+ 1E6/(t1-t0));
t2=t3;
}
t0=t1;
b=false;
}
}
void ISR_measureFreq(){
t1=micros();
b=true;
}
254
Chapter 9 Interrupts and Internal Comparator
After uploading the code and connecting pin 2 to 9, open the Serial
Monitor to see the result of measurement.
255
Chapter 9 Interrupts and Internal Comparator
void setup() {
Serial.begin(9600);
FreqCount.begin(1000); //counts the number of pulses in
1000 ms.
}
void loop() {
if (FreqCount.available()) {
unsigned long count = FreqCount.read();
Serial.println((String)"Frequency is: "+count+"Hz.");
}
}
9.5 pulseIn Command
In this example, we want to use the pulseIn command to measure the
duration of high (tH) and low (tL) sections of a pulse (you can use this
method to measure frequency as well since f=1/T=1/(tH+tL)). Upload the
following code to the Arduino board:
256
Chapter 9 Interrupts and Internal Comparator
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(pin,INPUT);
}
void loop() {
posDuration=pulseIn(pin,HIGH); //reads the positive width in
micro seconds
negDuration=pulseIn(pin,LOW); //reads the positive width in
micro seconds
Serial.println((String)"Length of positive
section:"+posDuration);
Serial.println((String)"Length of negative
section:"+negDuration);
Serial.println();
delay(1000);
}
9.6 Triggering an Interrupt
with a Push Button
In this section, we want to use a push button connected to pin 2 to trigger
the interrupt. In the following code, pin 2 is pulled up to VCC with the aid
of an internal pull-up resistor. When the user presses the push button,
the button connects pin 2 to ground. At the instant that the pin goes from
high (+5 V) to low (0 V), we have a falling edge. This falling edge is used to
257
Chapter 9 Interrupts and Internal Comparator
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
pinMode(2,INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2),LEDblink,FALLING);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println(n);
}
void LEDblink(){
n++;
for (int i=0;i<3;i++){
digitalWrite(13, HIGH);
for (int j=0;j<500;j++)
delayMicroseconds(1000);
digitalWrite(13, LOW);
for (int k=0;k<500;k++)
delayMicroseconds(1000);
}
}
258
Chapter 9 Interrupts and Internal Comparator
As an exercise, edit the preceding code to blink the LED when you
release the push button.
259
Chapter 9 Interrupts and Internal Comparator
In the following code, the onboard LED blinks three times when the
user presses the push button:
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(13,OUTPUT);
digitalWrite(13,LOW);
pinMode(2,INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2),LEDblink,LOW);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println(n);
}
void LEDblink(){
n++;
for (int i=0;i<3;i++){
digitalWrite(13, HIGH);
for (int j=0;j<500;j++)
delayMicroseconds(1000);
digitalWrite(13, LOW);
for (int k=0;k<500;k++)
delayMicroseconds(1000);
}
}
260
Chapter 9 Interrupts and Internal Comparator
9.8 Comparator Interrupt
ATmega328 has an internal comparator which permits you to do analog
comparisons without any need to external Op Amps or comparator IC.
A block diagram of the internal comparator is shown in Figure 9-6
(Figure 9-6, Figures 9-8 to 9-12, and Tables 9-1 and 9-2 are taken from [1].
The label above figures/tables shows the label of the figure/table in the
original reference).
261
Chapter 9 Interrupts and Internal Comparator
The analog comparator compares the input values on the positive pin
AIN0 and negative pin AIN1. When the voltage on the positive pin AIN0 is
higher than the voltage on the negative pin AIN1, the analog comparator
output, ACO, is set. The comparator’s output can be set to trigger the
Timer/Counter1 input capture function. In addition, the comparator can
trigger a separate interrupt, exclusive to the analog comparator. The user
can select interrupt triggering on the comparator output rise, fall, or toggle.
As shown in Figure 9-7, pins AIN0 and AIN1 of the analog comparator
module are externally connected to the I/O pins PD6 (pin 6 of the Arduino
UNO board) and PD7 (pin 7 of the Arduino UNO board).
262
Chapter 9 Interrupts and Internal Comparator
Even though AIN0 is fixed as one of the inputs, AIN1 can be varied
using the ADMUX output as shown in Table 9-1. If ACME is cleared
or ADEN is set, AIN1 is applied to the negative input of the analog
comparator.
263
Chapter 9 Interrupts and Internal Comparator
264
Chapter 9 Interrupts and Internal Comparator
265
Chapter 9 Interrupts and Internal Comparator
ACD bit (Analog Comparator Disable): When this bit is set by writing 1,
the analog comparator is switched off.
ACBG bit (Analog Comparator Bandgap Select): When this bit is set, a
fixed bandgap reference voltage replaces the positive input to the analog
comparator. When this bit is cleared, AIN0 is applied to the positive input
of the analog comparator.
ACO bit (Analog Comparator Output): The output of the analog
comparator is synchronized and then directly connected to ACO. The
synchronization introduces a delay of one to two clock cycles. To check the
output of the analog comparator, one can read the ACO bit.
ACI bit (Analog Comparator Interrupt Flag): This bit is set by hardware
when a comparator output event triggers the interrupt mode defined by
ACIS1 and ACIS0. The analog comparator interrupt routine is executed if
the ACIE bit is set and the I-bit in SREG is set. ACI is cleared by hardware
when executing the corresponding interrupt handling vector. Alternatively,
ACI is cleared by writing a logic one to the flag.
ACIE bit (Analog Comparator Interrupt Enable): When the ACIE bit
is written logic one and the I-bit in the status register is set, the analog
comparator interrupt is activated. When written logic zero, the interrupt is
disabled.
ACIC bit (Analog Comparator Input Capture Enable): When written
logic one, this bit enables the input capture function in Timer/Counter1 to
be triggered by the analog comparator.
266
Chapter 9 Interrupts and Internal Comparator
I-bit (Global Interrupt Enable): The global interrupt enable bit must be
set for the interrupts to be enabled. The individual interrupt enable control
is then performed in separate control registers. If the global interrupt
enable register is cleared, none of the interrupts are enabled independent
of the individual interrupt enable settings. The I-bit is cleared by hardware
267
Chapter 9 Interrupts and Internal Comparator
9.10 Example Code
for the Internal Comparator
Let’s study some example code to see how an internal comparator can
be used.
Example 1: Upload the following code to your Arduino board. This
code compares two voltages given to pins 6 (PD6) and 7 (PD7). Pins 6 and
7 are connected to + and – terminals of the internal comparator. When the
voltage of pin 6 is bigger than pin 7, the onboard LED turns on.
void setup() {
// put your setup code here, to run once:
ACSR=0x00; //clear bits of ACSR register
ADCSRB=0x00; //clear bits of ADCSRB register
pinMode(LED_BUILTIN,OUTPUT);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
268
Chapter 9 Interrupts and Internal Comparator
269
Chapter 9 Interrupts and Internal Comparator
when the voltage applied to pin 7 is less than 1.1 V, and it turns off when
the input voltage is bigger than 1.1 V.
void setup() {
// put your setup code here, to run once:
ACSR=0b01000000; //makes ACBG=1 which connect the +
terminal of the
//comparator to internal reference
voltage source.
ADCSRB=0x00; //clear bits of ADCSRB register
pinMode(LED_BUILTIN,OUTPUT);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
270
Chapter 9 Interrupts and Internal Comparator
digitalWrite(LED_BUILTIN,LOW);
}
}
271
Chapter 9 Interrupts and Internal Comparator
when ADMUX=1.
*/
void setup() {
// put your setup code here, to run once:
ACSR=0b01000000; //makes ACBG=1 which connect the +
terminal of the
//comparator to internal reference
voltage source.
ADCSRA=0b00000000; //ADEN=0.
ADCSRB=0b01000000; //ACME=1
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
// when output of comparator is low, i.e., 0, ACSR&0x20
generates 0.
// when output of comparator is high, i.e., 1, ACSR&0x20
generates 32.
if ((ACSR&0x20)==0){
Serial.println("voltage of A0 is bigger than 1.1 V.");
}else{
Serial.println("voltage of A0 is less than 1.1 V.");
}
272
Chapter 9 Interrupts and Internal Comparator
}else{
Serial.println("voltage of A1 is less than 1.1 V.");
}
Serial.println("------------------------------------");
delay(2000);
}
Open the Serial Monitor to see the output of the code. You can use
a digital voltmeter to measure the voltage of pin A0 and ensure that the
output of the code (i.e., shown message) is correct.
273
Chapter 9 Interrupts and Internal Comparator
void setup() {
// put your setup code here, to run once:
cli();
ACSR=0b01001011; //makes ACBG=1 which connect the +
terminal of the
//comparator to internal reference
voltage source.
//set interrupt on rising edge
ADCSRA=0b00000000; //ADEN=0.
ADCSRB=0b01000000; //ACME=1.
ADMUX=0; //select A0 for - terminal of comparator.
sei();
pinMode(LED_BUILTIN,OUTPUT);
Serial.begin(9600);
}
274
Chapter 9 Interrupts and Internal Comparator
void loop() {
// put your main code here, to run repeatedly:
Serial.println(n);
digitalWrite(LED_BUILTIN,ACSR&0b00100000);
//shows the output of the comparator.
//when led is on output of the comparator is high.
//when led is off output of the comparator is low.
}
ISR (ANALOG_COMP_vect){
n++;
}
275
Chapter 9 Interrupts and Internal Comparator
Open the Serial Monitor to see the value of variable n. When does the
value of variable n change – when the push button is pressed or when it is
released? Why?
Example 5: This example is quite similar to the previous example. In
this example, the + terminal of the comparator is connected to the 1.1 V
internal reference voltage, and the – terminal is connected to analog pin
A0. In this example, ANALOG_COMP_vect is called when the result of the
comparison goes from high to low, that is, on a falling edge. The onboard
LED shows the status of the output of the comparator.
276
Chapter 9 Interrupts and Internal Comparator
void setup() {
// put your setup code here, to run once:
cli();
ACSR=0b01001010; //makes ACBG=1 which connect the +
terminal of the
//comparator to internal reference
voltage source.
//set interrupt on falling edge
ADCSRA=0b00000000; //ADEN=0.
ADCSRB=0b01000000; //ACME=1.
ADMUX=0; //select A0 for - terminal of comparator.
sei();
pinMode(LED_BUILTIN,OUTPUT);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println(n);
digitalWrite(LED_BUILTIN,ACSR&0b00100000);
//shows the output of the comparator.
//when led is on output of the comparator is high.
//when led is off output of the comparator is low.
}
277
Chapter 9 Interrupts and Internal Comparator
ISR (ANALOG_COMP_vect){
n++;
}
Open the Serial Monitor to see the value of variable n. When does the
value of variable n change – when the push button is pressed or when it is
released? Why?
278
Chapter 9 Interrupts and Internal Comparator
void setup() {
// put your setup code here, to run once:
cli();
ACSR=0b01001000; //makes ACBG=1 which connect the +
terminal of the
//comparator to internal reference
voltage source.
//set interrupt on toggle
ADCSRA=0b00000000; //ADEN=0.
ADCSRB=0b01000000; //ACME=1.
ADMUX=0; //select A0 for - terminal of comparator.
sei();
pinMode(LED_BUILTIN,OUTPUT);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println(n);
279
Chapter 9 Interrupts and Internal Comparator
digitalWrite(LED_BUILTIN,ACSR&0b00100000);
//shows the output of the comparator.
//when led is on output of the comparator is high.
//when led is off output of the comparator is low.
}
ISR (ANALOG_COMP_vect){
n++;
}
280
Chapter 9 Interrupts and Internal Comparator
Open the Serial Monitor to see the value of variable n. When does the
value of variable n change – when the push button is pressed or when it is
released? Why?
281
Chapter 9 Interrupts and Internal Comparator
if the interrupt was caused by a HIGH or LOW input, then you’ll have to
figure that out yourself.
The catch is that pin change interrupts are grouped into ports (port
B=pins 8, 9, 10, 11, 12, and 13 of Arduino UNO, port C=pins A0, A1, A2,
A3, A4, and A5 of Arduino UNO, and port D=pins 0, 1, 2, 3, 4, 5, 6, 7, and
8 of Arduino UNO), and all the pins on the same port create the same pin
change interrupt. This is fine if you are only using one; otherwise, you’ll
need to figure out which pin caused the interrupt.
Arduino UNO has 24 pin change interrupts (Figure 9-19).
282
Chapter 9 Interrupts and Internal Comparator
283
Chapter 9 Interrupts and Internal Comparator
Interrupt service routing for the pin change interrupt must have the
following names:
Let’s study an example. The following code activates the pin change
interrupt of pins 11 and 12. The onboard LED of the board toggles when
the user presses or releases the push button connected to these pins.
void setup() {
// put your setup code here, to run once:
PCICR|=0b00000001; // PCINT for pins 8, 9, 10, 11, 12 and 13
is enabled.
PCMSK0|=0b00011000; // Select PCINT3 and PCINT4 = pins 11 and
12 of Arduino UNO
pinMode(LED_BUILTIN,OUTPUT);
pinMode(11,INPUT_PULLUP);
pinMode(12,INPUT_PULLUP);
}
void loop() {
// put your main code here, to run repeatedly:
284
Chapter 9 Interrupts and Internal Comparator
ISR (PCINT0_vect){
state=!state;
digitalWrite(LED_BUILTIN, state);
}
285
Chapter 9 Interrupts and Internal Comparator
void setup() {
// put your setup code here, to run once:
PCICR|=0b00000001; // PCINT for pins 8, 9, 10, 11, 12 and 13
is enabled.
PCMSK0|=0b00011000; // Select PCINT3 and PCINT4, pins 11 and
12 of Arduino UNO
pinMode(LED_BUILTIN,OUTPUT);
pinMode(11,INPUT_PULLUP);
pinMode(12,INPUT_PULLUP);
}
void loop() {
// put your main code here, to run repeatedly:
ISR (PCINT0_vect){
if (digitalRead(11)==LOW)
digitalWrite(LED_BUILTIN, LOW);
if (digitalRead(12)==LOW)
digitalWrite(LED_BUILTIN, HIGH);
}
https://bit.ly/3YKsLn7
https://bit.ly/2NdzU9e
286
Chapter 9 Interrupts and Internal Comparator
https://bit.ly/3jlANCq
https://bit.ly/3PQR3rq
https://bit.ly/3C53YAq
https://bit.ly/3YJpMeB
https://bit.ly/3hQThdI
https://bit.ly/2NdzU9e
https://bit.ly/3VynEUg
https://bit.ly/3Z1ldMS
287
CHAPTER 10
Timers
10.1 Introduction
A timer or, to be more precise, a timer/counter is a piece of hardware built
in the Arduino board’s microcontroller. It is like a clock and can be used
to measure time events. The timer can be programmed by some special
registers. This chapter focuses on the timers and how to use them.
Arduino UNO has three timers: Timer 0, Timer 1, and Timer 2. Timer 0
and Timer 2 are 8-bit counters (they count from 0 to 255), while Timer 1 is
a 16-bit counter (it counts from 0 to 65535). The values of timers/counters
are stored in the TCNTn register where n=0, 1, and 2. For example, TCNT0
keeps the current value of Timer 0.
Internally, Timer 0 is used for the millis() function, and, therefore, it
is recommended not to mess with it. You can use Timer 1 and Timer 2 for
your custom requirements.
Figures of this chapter are taken from [1]. The label above each figure
shows the location of the figure in the original reference.
290
Chapter 10 Timers
291
Chapter 10 Timers
Study the definitions given in Table 10-1 before going into the details of
CTC mode.
292
Chapter 10 Timers
In CTC mode, the timer counts up until the counter value TCNTn
(where n is 0, 1, or 2) reaches the TOP value, and at this point, a match
occurs and the output at the output compare pin OCnA or OCnB can be
either cleared, set, or toggled. The TOP value depends upon which Timer
is used. Arduino has three timers called Timer 0, Timer 1, and Timer 2,
and each timer can be used in CTC mode. Timer 0 has one CTC mode with
TOP at OCR0A, Timer 1 has two CTC modes with TOP at OCR1A and ICR1,
and Timer 2 has one CTC mode with TOP at OCR2A.
Let’s use Timer 0 for blinking the onboard LED with 1 s durations.
Timer 0 registers are shown in Figures 10-3 and 10-4.
293
Chapter 10 Timers
294
Chapter 10 Timers
Table 10-5 shows how to select the desired prescaler for Timer 0. The
value of clkI/O is 16 MHz for Arduino UNO.
295
Chapter 10 Timers
/*
This program turns on and off a LED on pin 13 each 1 second
using an internal timer
*/
int timer=0;
bool state=0;
void setup() {
//put your setup code here, to run once:
pinMode(LED_BUILTIN,OUTPUT);
296
Chapter 10 Timers
void loop(){
//put your main code here, to run repeatedly:
digitalWrite(LED_BUILTIN,state);
}
void setup () {
//OC0A is connected to pin 6 of Arduino
pinMode(6, OUTPUT);
void loop() {
297
Chapter 10 Timers
void setup () {
//OC0B is connected to pin 5 of Arduino
pinMode(5, OUTPUT);
void loop() {
void setup () {
//OC0B is connected to pin 5 of Arduino
//OC0A is connected to pin 6 of Arduino
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
298
Chapter 10 Timers
void loop() {
299
Chapter 10 Timers
Table 10-8 shows how to select the desired prescaler for Timer 1. The
value of clkI/O is 16 MHz for Arduino UNO.
300
Chapter 10 Timers
Let’s study an example and see how Timer 1 can be used in CTC mode.
The following code generates a 10 kHz square wave on pin 9 of Arduino.
This code uses mode 4 (Table 10-7):
void setup () {
//OC1A is connected to pin 9 of Arduino
pinMode(9, OUTPUT);
void loop() {
301
Chapter 10 Timers
void setup () {
//OC1A is connected to pin 9 of Arduino
pinMode(9, OUTPUT);
void loop() {
void setup () {
//OC1B is connected to pin 10 of Arduino
pinMode(10, OUTPUT);
302
Chapter 10 Timers
void loop() {
The following code generates the 10 kHz square wave on pins 9 and 10
simultaneously:
void setup () {
//OC1A is connected to pin 9 of Arduino
//OC1B is connected to pin 10 of Arduino
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
// Load 799 to generate 10 kHz sq.wave
ICR1 = 799;
// Toggle OC1A and OC1B on compare match, mode 12 (CTC),No
prescalar, Start the timer
TCCR1A = (1 << COM1A0)|(1 << COM1B0);
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1 << CS10); //TCCR1B=00011001
}
void loop() {
303
Chapter 10 Timers
304
Chapter 10 Timers
Table 10-11 shows how to select the desired prescaler for Timer 2. The
value of clk is 16 MHz for Arduino UNO.
305
Chapter 10 Timers
void setup () {
//OC2A is connected to pin 11 of Arduino.
pinMode(11, OUTPUT);
void loop() {
306
Chapter 10 Timers
In the following code, ISR is called each 16.38 ms. After uploading the
code, open the Serial Monitor to see the output.
void setup () {
TCCR2A=0; //Reset Timer 2 control registers
TCCR2B=0;
OCR2A = 255;
Serial.begin(9600);
}
void loop() {
Serial.println(i);
}
307
Chapter 10 Timers
https://bit.ly/3I5ej30
[2] Arduino CTC mode programming:
https://bit.ly/3YJqMzn
https://bit.ly/3VtK0Ga
308
CHAPTER 11
Reading Different
Sensors with Arduino
11.1 Introduction
This chapter shows how some of the commonly used sensors can be
connected to the Arduino board. Many of the sensor producers have
ready-to-use Arduino libraries for their products, which simplify the use of
sensors considerably. Always search the Internet in order to see whether
there is a ready-to-use library for your sensor. This helps you to save your
time and energy.
310
Chapter 11 Reading Different Sensors with Arduino
void setup() {
Serial.begin(9600);
dht.begin();
}
void loop() {
delay(2000);
humidity = dht.readHumidity();
temperature= dht.readTemperature();
Serial.print("Humidity (in %): ");
Serial.println(humidity);
Serial.print("Temperature(in C): ");
Serial.println(temperature);
Serial.println("---------------------");
}
311
Chapter 11 Reading Different Sensors with Arduino
312
Chapter 11 Reading Different Sensors with Arduino
Upload the following code to the board. Connect the VCC, Trig, Echo,
and GND pins of the module to the +5 V, 13, 12, and GND pins of the
Arduino board. Open the Serial Monitor to see the output of the code.
#include <HCSR04.h>
void setup () {
Serial.begin(9600); // We initialize serial connection so
that we could print values from sensor.
}
void loop () {
// Every 500 miliseconds, do a measurement using the sensor
and print the distance in centimeters.
Serial.println(distanceSensor.measureDistanceCm());
delay(500);
}
313
Chapter 11 Reading Different Sensors with Arduino
Upload the following code to the board. Connect the VCC, GND,
and A0 pins of YL69 to +5, GND, and A0 pins of Arduino. Open the Serial
Monitor to see the output of the code.
//https://randomnerdtutorials.com/guide-for-soil-moisture-
sensor-yl-69-or-hl-69-with-the-arduino/
int analogPin= A0;
int thresholdValue = 800;
void setup(){
pinMode(analogPin, INPUT);
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(analogPin);
314
Chapter 11 Reading Different Sensors with Arduino
delay(500);
}
https://bit.ly/3joL7cR
https://bit.ly/3Wmb2AC
https://bit.ly/3C4BkiC
https://bit.ly/3GjSXgX
https://bit.ly/3GlBmp8
https://bit.ly/3FWaw5n
315
APPENDIX A
Testing the
Components
A.1 Introduction
Sometimes, you need to test your components to ensure that they are not
faulty. This appendix shows how to test some of the most commonly used
components.
A.2 Testing the Resistors
You can use a digital multimeter to measure the value of a resistor
(Figure A-1). If the value is close to the value shown by the color bands
and your measurements are close, then you can deduce that the resistor
is good.
You need to know the resistance of the probes when you want to
measure small resistors (i.e., in the range of a few Ohms). You can measure
the probe’s resistance by connecting the probes together as shown in
Figure A-2. For instance, in Figure A-2 the resistance of the probes is 0.4 Ω.
If you connect the probes to a resistor and the digital multimeter shows
2.6 Ω, then the real value is 2.6 –0.4 = 2.2 Ω.
318
Appendix A Testing the Components
319
Appendix A Testing the Components
Figure A-4. One leg of the resistor is isolated from the circuit
Figure A-5. Both legs of the resistor are isolated from the circuit
You can test the transformers and incandescent lamps with the resistance
measurement section of the digital multimeter as well (Figure A-6). When the
transformer winding is opened, or the lamp is blown, you read infinity (i.e., it
shows OL).
320
Appendix A Testing the Components
A.3 Testing the Diodes
You can test the diode by selecting the diode section of the digital
multimeter, connecting the red probe to the anode and connecting the
black probe to the cathode. The number shown on the display is the
forward voltage drop of the diode (Figure A-7).
321
Appendix A Testing the Components
You need to observe the OL (Open Loop) when you connect the red
and black probes to cathode and anode terminals, respectively. Remember
that no current can go from the cathode to the anode.
A.4 Testing the LEDs
You can test the LEDs with the aid of the circuit shown in Figure A-8. If the
LED turns on, you deduce that it is not faulty. The voltage drop of the LED
is between 1.8 V and 3.3 V. The voltage drop varies by the color of the LED.
322
Appendix A Testing the Components
323
Appendix A Testing the Components
Figure A-9. The position of the servo motor shaft is controlled with
the aid of two push buttons
324
Appendix A Testing the Components
Figure A-10. The position of the servo motor shaft is controlled with
the aid of a potentiometer
325
Index
A Zener diode, 129, 130
Analog Comparator Multiplexer
ADC/DAC
Enable (ACME), 263, 265
ACS712 breakout board, 148
Analog Reference (AREF) pin
AREF pin, 129, 137, 138
EXTERNAL, 129, 137
building blocks, 127
ADC/DAC converter, 137
current signal
Analog-to-digital converter (ADC),
measurements, 147–150
5, 127, 129, 145, 152, 217
DC voltmeter, 132, 133
Arduino board
external ADC and DAC, 150–152
ATmega328, 10
negative voltage
data transfers, 185
measurement, 145–147
external power source, 26
PCF8591
hardware development board, 6
ADC code, 152–154
HEX files, 13–20
Aout pin values/
IDE, 12, 13
voltages, 157
language reference section, 31
breakout board, 151, 152
MEGA board, 8
DAC code, 155–159
microcontrollers (see
hardware, 154
Microcontroller)
input-output
motor shield, 30
characteristics, 159
Nano board, 8
protection, 129–132
pin connections, 10, 11
Schottky diode, 130
power supply, 24–26
serial plotter, 134–136
ready-to-use examples, 26, 27
speed conversion, 139–141
sensors, 309
UNO board, 128
shields, 28–30
voltage divider, 131, 132
UNO board, 7, 34, 180, 215
voltage level indicator, 141–144
328
INDEX
pins configuration H
input properties, 35
Hexadecimal source file (HEX)
INPUT_PULLUP, 38, 39
button verification, 18
output properties, 38, 39
compiling option, 19
pinMode command, 35
empty sketch, 14
pull-up/pull-down
file generation, 19, 20
resistor, 36, 37
INO file, 13
relay control, 123–125
mathematical operations, 211
RGB LED, 50–55
Notepad++, 20
right shift operator >>, 117, 118
onboard LED, 14, 15
serial monitor tool, 44
preferences, 16–18
seven-segment display, 56
save option, 15, 16
time measurement, 43–46
toggle pins, 89
UNO board, 34 I, J, K
voltage pattern, 47–50 Integrated Development
Digital multimeter (DMM), 156, Environment (IDE), 1
317, 320, 321 Arduino boards, 12
Digital-to-analog converter download section, 13
(DAC), 5, 127 sketches, 12
Dual inline package (DIP), 9 Inter-Integrated Circuit (I2C), 162,
167, 168, 177, 199
E, F, G Internal comparator
Electrically Erasable ACSR register, 266
Programmable Read-Only ADCSRA register, 265
Memory (EEPROM) ADCSRB register, 265
external code, 172–175 ADMUX register, 265
integer data type, 174 analog comparator,
internal code, 168–170 262, 274–276
LCD (see LCD/EEPROM) connection, 263
put()/get() functions, 170, 171 input voltage, 269–271
writing/reading interrupt mode, 267
structures, 175–177 negative input, 264
Ethernet shield, 28, 29 PCICR register, 283
329
INDEX
330
INDEX
331
INDEX
332