0% found this document useful (0 votes)
12 views

Peterson, Kathleen - Arduino Projects - The Ultimate Guide For Making The Best of Your Arduino Programming Projects, 1st Edition (2020)

This book contains 10 projects using Arduino components that are designed to be assembled using real equipment. The projects cover topics like creating an Arduino board, automating a door with a password, building a radar to check speed, and creating a simple spider robot. Instructions are provided on setting up the projects and ensuring all necessary materials are obtained.

Uploaded by

Ray
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

Peterson, Kathleen - Arduino Projects - The Ultimate Guide For Making The Best of Your Arduino Programming Projects, 1st Edition (2020)

This book contains 10 projects using Arduino components that are designed to be assembled using real equipment. The projects cover topics like creating an Arduino board, automating a door with a password, building a radar to check speed, and creating a simple spider robot. Instructions are provided on setting up the projects and ensuring all necessary materials are obtained.

Uploaded by

Ray
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 207

HOW TO USE THIS BOOK

The prerequisite will be to understand the use of Arduino, a little bit of


electronics, C language programming for Arduino, as well as a lot of desire
to move on, go further and create. Thus, my first book, already mentioned, is
a perfect match for this one.
Arduino is a platform formed by equipment electronic and an integrated
programming environment (Integrated Development Enviroment - IDE) for
electronic prototyping and
software.
The electronic equipment of the Arduino platform consists of an integrated
circuit board, properly equipped with its electronic components, the central
component of which is Atmel AVR type microprocessor. The software that
will be used to program the Arduino are free and free.
Much has been discussed recently about the use of Arduino in technology
projects, but little about how actually use that component, and what it
actually gives to build with it. This book, a work prepared by Fernando
Bryan, that throughout his academic life has been creating, testing and
innovating projects, it brings us many projects with Arduino. THE
material presented here has the purpose of presenting possible designs that
can be made with some electrical components.
The projects are designed to use only components easy to find in specialized
electronics stores, which low cost and which can be, as far as possible,
shared between projects.
PREFACE
emergence of new ideas and how to put them into practice. Will be 10
chapters with projects ready to follow step by step, giving guidelines for
automating a door (opening it) with password), control the speed of an
object with a radar, automate a lighting system via remote control,
build electronic data, create a video game, among several other ideas, even
the construction of a spider robot.
This book was not written for anyone who wants to learn electronics, but for
those who want to learn to program Arduino through of these projects that
don't exactly require much knowledge electronics, but programming.
Therefore, this book is for those who know or want to learn to program, and
if they know how to program - regardless of language or operating system -
at least
intermediate.
We thank Fernando Bryan, for the support and dedication during these two
years that Arduino has been introducing us and surprising more and more,
not only with this tool technological, but with its willingness to teach, excite
and revolutionize thoughts and ideas.
It is with great satisfaction that we present this book, we believe in working
with Arduino. We get inspired a lot with the book Arduino: Guide to putting
your ideas into practice in our classes, and we appreciate the opportunity to
present this second book, which will bring us many projects and new
concepts of works. In addition, it will stimulate and involve new
interested in that work.
Move on. It's time to learn. Feel free!
1 How to set up projects
2 Project nº 01 - Creating our own Arduino
2.1 Materials used in this project
2.2 Developing the project
2.3 Challenge
3 Project nº 02 - Automating a door with a password via
keyboard
3.1 Materials used in this project
3.2 Developing the project
3.3 Challenge
4 Project nº 03 - Creating a radar to check the speed
of an object
4.1 Materials used in this project
4.2 Developing the project
4.3 Challenge
5 Project nº 04 - How about turning on the lamps in your house with
Remote Control?
5.1 Materials used in this project
5.2 Developing the project
5.3 Challenge
6 Project nº 05 - An electronic data for games
6.1 Materials used in this project
6.2 Developing the project
6.3 Challenge
7 Project nº 06 - Creating a video game for you
7.1 Materials used in this project
7.2 Developing the project
7.3 Challenge
8 Project nº 07 - Refrigerator alarm with monitoring of
opening the door
8.1 Materials used in this project
8.2 Developing the project
8.3 Challenge
9 Project nº 08 - Building an offline GPS tracker
9.1 Materials used in this project
9.2 Developing the project
9.3 Challenge
10 Project nº 09 - Hot, hot ... hot ... burnt potatoes!
10.1 Materials used in this project
10.2 Developing the project
10.3 Challenge
11 Project nº 10 - The simplest spider robot in the world!
11.1 Materials used in this project
11.2 Developing the project
11.3 Challenge
12 General Bill of Materials

The projects in this book are designed to be put together using real
equipment and components, without using a simulator.
Therefore, it is important to obtain all the resources before you begin.
Only one Arduino and one test plate will be used, or prot-o-board and
several other components that are indicated and detailed in each project. But
if you want to keep them assembled, you will need to provide a set for each
project.
You will also need to have a computer to perform the Arduino programming,
as well as having an internet connection. THE latest version of the Arduino
IDE can be downloaded at
http://arduino.cc . Note that it is always a good idea to use the
updated.

HOW TO ASSEMBLE THE


PROJECTS

Figure 1.1: The Arduino website (https://arduino.cc), accessed on March 18, 2016
Give preference to mount the projects on a table or a
stand. After everything is up and running, you can decide
about finishing, adaptations and installation in an appropriate place.
Before starting, try to correctly identify the
components and wiring diagrams.
All source codes featured in the projects in this book
are available at https://github.com/fbryan/fontes/ .
The libraries used for the projects are available at
https://github.com/fbryan/ , the direct paths are
made explicit in the projects.

Source codes

It is always worth emphasizing that these codes can and should


be improved. Study them, understand how they work,
modify, improve and adapt, so you can use them
on their own projects.
Now that you know what you'll need to get started, let's
start and in style: how about creating your own Arduino?

Figure 2.1: The Arduino UNO R3, where the microcontroller will come from
Let's start with a simple program, the simplest of
all: flash the LED on pin 13.

void setup () {
pinMode (13, OUTPUT);
}
void loop () {
digitalWrite (13, HIGH);
delay (1000);
digitalWrite (13, LOW);
delay (1000);
}
Compile and load the program on your Arduino and verify that
everything works fine. That is, if the LED on digital pin 13 is on
for a second and then also deleted for a second,
blinking.
Turn off the Arduino by disconnecting it from the computer and
be very careful, remove the microcontroller from the board. For that, you
you can use your own tweezers to remove integrated circuits,

Figure 2.2: Removing the microcontroller from the Arduino board

Use extreme care when removing the


microcontroller. If you damage any pin, it will not
will neither work out nor connect back to the board of the
Arduino. In particular, make sure you do not bend
any of the pins.
Figure 2.3: The Arduino board without the microcontroller and the microcontroller outside the board
Arduino
One of the things you should pay close attention to is
position of the microcontroller. Note that at the top, where there is
brand and model inscriptions (ATMEGA328), there is also a
chamfer and a point engraved in low relief. See figure a
follow:
Figure 2.4: The microcontroller with the chamfer and the low relief point highlighted at the
left of image

Figure 2.7: The ATMEGA328 microcontroller connected to the prot-o-board


You will also need a 9 volt battery holder
to power the entire circuit:

Figure 2.8: The 9-volt battery holder


Let's enjoy and also connect the battery holder to the
prot-o-board:

Figure 2.9: The battery holder connected to the horizontal tracks on the prot-o-board
A voltage regulator of at least 20 volts to 5 volts.
The used will be a 7805 transistor, easily found in stores
electronic materials at a low cost.
Figure 2.10: A 7805 voltage regulator
Transistor 7805 is a linear voltage regulator capable of
keep the output voltage constant at a certain value, in the
5V case, which is required by the microcontroller. The minimum voltage
input voltage is approximately 7V and maximum 25V, with
maximum current of 1.5A. Then, a 9V battery will handle the
enough message and the circuit will not require more than that
in current.

The three pins are numbered in the following figure:


Figure 2.11: A 7805 voltage regulator with numbered pins
Pin 1 is the voltage input, according to the specifications already
previously mentioned. Pin 2 is the common (that is, GND), and the
pin 3 is the voltage output already set.
So let's put the voltage regulator on the prot-o-board,
connecting pin 1 of the regulator to the positive of the battery, pin 2 of the
regulator to the negative battery (GND) and pin 3 of the regulator to the
pin 7 of the microcontroller (VDC + 5V).

Figure 2.12: Connections between the voltage regulator, battery and pin 7 of the microcontroller
Let's take the opportunity to connect pin 20 of the
microcontroller to the battery positive, and pins 8 and 22 also
microcontroller to battery negative (GND).
Figure 2.13: Pins 8 and 22 of the microcontroller connected to the negative and pin 20 connected to the
positive battery
Pin 21 of the microcontroller (AREF) must also be connected
battery positive.
We also need an oscillating crystal to generate
clock frequency, so that the microcontroller can work.
Figure 2.14: The oscillating crystal, used as a clock
The oscillator crystal will be used as a clock signal generator
for the microcontroller. It is important because it guarantees the
timing and timing so that the microcontroller
function properly.
When you buy a crystal, you will see that there are several frequencies
possible that are generated by them. The microcontroller
ATMEGA328 used in Arduino UNO works in frequency
maximum of 20MHz, but by default, Arduino UNO boards are
16MHz crystals are used.
Connect pins 9 and 10 of the microcontroller to the oscillator crystal. THE
crystal has no polarity.
Figure 2.15: The crystal connected to the microcontroller
There are just a few more to go, just three components. First,
two 22pF ceramic capacitors:
Figure 2.16: The two ceramic capacitors
These capacitors will be connected each between a terminal of the
oscillating crystal and battery negative (GND), as in the figure
follow:
Figure 2.17: Capacitors between the oscillator crystal terminals and the battery negative
The last component is a 10KΩ resistor, which will be connected
between the voltage regulator output (+ 5V) and pin 1 of the
microcontroller. As previously explained, this pin is the
reset and, when you set it to a low level (GND) on it, the
microcontroller will be reset and program execution will begin
again. So, with this resistor, between it and the + 5V,
we guarantee that it will always have a high level ( HIGH ).
If you want to include a reset button, simply turn it on
that when pressed, connect pin 1 of the microcontroller to the
GND (battery negative).
Figure 2.18: The 10KΩ resistor between the voltage regulator and pin 1 of the microcontroller.
Ready! There's your Arduino mounted on the prot-o-board. What
what name will you give? Now, I was in doubt if I keep the idea of
Bryanduíno, or if I call him Fernanduíno. But the toast in
tribute to him is guaranteed.
But, and to test it? Remember that we program the
microcontroller at the beginning of this project to flash an LED that
connected to pin 13? So, let's turn on the LED set and
resistor on pin 13 of the Arduino.
Connect the resistor between pin 19 of the microcontroller (which is 13
Arduino) and the positive LED terminal. Connect the terminal
negative from LED to battery negative (GND).
other things not so obvious.
But for this specific project, a good challenge will be to record
the microcontroller without removing it from the prot-o-board, and placing it
in
an Arduino UNO board. The tip is that, for that, just use a
USB / Serial converter and connect the serial RX pins of the converter to the
Serial TX of the microcontroller, the TX of the converter to the RX of the
microcontroller and the GND of the converter to the battery negative.
The next project could be the first to receive the Arduino
built into it. So that everything fits in a box that also
can contain the keyboard, you can build your own Arduino
to reduce the need for space inside that box. also
it will be a project that can be of practical use and help you not to have
more than remembering the keys to open doors and gates. Let's go
over there!
In this project, we will consider that your door has already
doorknob and lock, and that you don't necessarily want to change it
it for a new one. So the idea is to use an electric lock
common, of those used in gates and residential doors. With
this, the cost will be reduced and the ease of adaptation will be
increased.
Let's set it up, and then you can decide the best way
to install wherever you want. We will need an Arduino UNO:

Figure 3.1: The Arduino UNO R3


You will also need a prot-o-board to support
the entire circuit, which will be very small:

3.2 DEVELOPING THE PROJECT

Figure 3.2: The prot-o-board used, and you can use any one you have
available
We will also need a membrane matrix keyboard
with at least 12 keys:
Figure 3.3: The membrane keyboard, numeric only, with 12 keys, three columns for four
lines
The 12-key membrane keypad, like the shown in the previous figure, has 7
wires, three of which are for access to columns and four to rows. Pin 1 is the
most left, looking at the keyboard from the front, and pin 7 is the rightmost
right.
The keyboard will occupy most of the digital pins of the Arduino,
that each pin on the keyboard must have a corresponding Arduino. To
capture the keys that will be pressed, we will use the Keypad library which is
available at
https://github.com/fbryan/keypad .
On this page, there will be a link for you to download the latest version of
the library. This will bring some functions that map the pins of the button
matrix which is actually this
keyboard.
To import the library, open the Arduino IDE and click on the Sketch menu .
Then select the Include option
Library :
Figure 3.4: The Arduino IDE's Sketch menu with the Include Library option selected.
Click the Add .ZIP library option , which will open the
following box for selecting files:
Figure 3.5: The window for selecting the keypad library in .zip format
Find where you saved the keypad.zip file you obtained
by the previous download. Then, click the Open button . Ready, the
library has been added. If you open the Sketch menu again
and select the Include Library option , see that the Keypad is already
is available, as we see below:
Figure 3.6: The Sketch menu with the Include Library option selected. View the Keypad library
available.
We can already start assembling our project for real, from
from now. Let's connect and program the keyboard to understand how it
works and how to capture what the user is going to type. That it will also
advance part of the project.
We will connect the keyboard directly to the Arduino. For this, you will need
7 wires. I will not connect via prot-o-board, because it won't be necessary,
and that would only increase our use of wires.
Looking at it from the front, starting from left to right, turn on
all pins on the keyboard to digital pins 9, 8, 7, 6, 5, 4 and 3 on the
Arduino, in this sequence:

Figure 3.7: The keyboard connected to the Arduino digital pins


With everything connected, let's go to the schedule:

# include <Key.h>
# include <Keypad.h>
const byte n_lines = 4;
const byte n_columns = 3;
char keys [n_lines] [n_columns] = {
{ '1' , '2' , '3' },
{ '4' , '5' , '6' },
{ '7' , '8' , '9' },
{ '*' , '0' , '#' }
};
byte mapa_linha [n_linhas] = {9,8,7,6};
byte mapa_coluna [n_colunas] = {5,4,3};
Keypad keyboard = Keypad (makeKeymap (keys), row_map, column_map,
n_lines, n_columns);
void setup () {
Serial.begin (9600);
}
void loop () {
char key = keyboard.getKey ();
if (key! = NO_KEY) {
Serial.println (key);
}
}

With the help of the Keypad library , everything is easier, but let's go step by
step. Includes adds the Keypad library and its Key complement to the project.
This library will offer
all objects and methods needed to read the keys. We need define the number
of lines, which we do with the variable n_lines , and also the number of
columns, made with the variable n_columns ,
that exist on the keyboard that we're going to use.
The values ​of the keys that exist are defined in the matrix keys , which
reflects the position and what the keys are. Note that there something
extremely interesting can happen: you can define
any values ​for the keys. If you want that when the number one on the
keyboard is pressed, the % value is read , for example, just define this in this
matrix. The user will find that the
key 1 sends a value, but not really.
We will, of course, use the "normal" values ​for the keys, if he would not
confuse his studies a bit. But this is a possibility that deserves to be
mentioned.
With the vectors mapa_linha , we define which digital pins Arduino are
connected to the pins corresponding to the lines on the keyboard. We do the
same with the pins corresponding to the
keyboard columns with map_columns , as shown previously when connecting
the keyboard to the Arduino.

THE
line
Keypad
keyboard
=
Keypad (makeKeymap (keys), line_map, column_map, n_line
s, n_columns) transforms all of these previous definitions into
object called the keyboard, which is of the Keypad type , and receives the
matrix
with the key map called keys , the pin maps for the
rows map_line and map_column , for columns. also
receives the number of rows and columns of the keyboard.
In the setup () function , we started the serial connection with 9,600
bauds with the Serial.begin line (9600) . In the function () loop is
read the key pressed for the key variable , done with the line
char key = keyboard.getKey () . Then, with the
if selection , we check if any key was pressed with
if (! = NO_KEY key) . This structure will make sure that if a key
is pressed, its corresponding value is shown in the output
serial with the line Serial.println (key) .
Let's test what we have so far. Compile and upload the
your program for Arduino.
Figure 3.8: Serial monitor after pressing all keys
With that ready, we already have the core of our project almost
concluded. Since the idea is to read a password, compare with a password
and whether or not to release the lock. Very little to go, one
Since controlling the lock will be almost the same as
control an LED: on, release the input; off, does not release.
First, following this logic, let's simulate the lock
electrical with the LED of the digital pin 13 of the Arduino: we will type
numeric sequence and we will compare it with a sequence
preset. If they match, we will access the LED; otherwise,
nothing will happen.
Change the previous code to look like the code shown at
follow:

# include <Key.h>
# include <Keypad.h>
const byte n_lines = 4;
const byte n_columns = 3;
char keys [n_lines] [n_columns] = {
{ '1' , '2' , '3' },
{ '4' , '5' , '6' },
{ '7' , '8' , '9' },
{ '*' , '0' , '#' }
};
byte mapa_linha [n_linhas] = {9,8,7,6};
byte mapa_coluna [n_colunas] = {5,4,3};
Keypad keyboard = Keypad (makeKeymap (keys), row_map, column_map,
n_lines, n_columns);
int pos = 0;
int led = 13;
char password [12];
correct char [] = "123456" ;
void setup () {
pinMode (led, OUTPUT);
Serial.begin (9600);
}
void loop () {
char key = keyboard.getKey ();
if (key! = NO_KEY) {
if (key! = '#' ) {
password [pos] = key;
pos ++;
}
if (key == '#' ) {
Serial.println (password);
if (! strcmp (correct, password)) {
Serial.println ( "Correct password" );
digitalWrite (led, HIGH);
delay (5000);
}
for ( int i = 0; i < strlen (password); i ++) password [i] = '' ;
pos = 0;
digitalWrite (led, LOW);
}
}
}
The code hasn't changed much from the previous one, since the use of Keypad
libraries was unchanged. What has changed is that we created the pos
variables that will indicate the reading position of the password being
entered. We also created a led , which will indicate
the digital pin of the Arduino with the LED that we will turn on if the
password is correct, in this case pin 13. The password variable you will receive
the password and has a maximum size of 12
characters, that is, we limit the password length to 12 numbers.
Finally, we create the correct variable [] , which contains the password that
should be used to light the LED.
In the setup () function , we start the LED digital pin as OUTPUT , that is,
output. We are still using the connection serial so that we can verify the
correct functioning of the
program. If something goes wrong, you can check what's happening.
In the loop () function , we read what is typed on the keyboard to key variable
and we use the if selection structure to check if any key was pressed, exactly
as in the first
code that we did. After that, things change a little bit.
We use an if selection structure to check whether the key entered was not #
and, if not, we store the key typed in the password variable at the position
defined by the pos variable , incremented in sequence. That is, each digit is
stored in the next position of the vector up to the size limit determined for
the password variable .
If the key pressed is # , we send the password entered to the serial
connection. You can see it on the Serial Monitor. With another if structure ,
we compare the typed password with the expected one using the strcmp
command (correct, password) . It will return 0 if the
variables have the same content; a value less than zero if the correct variable
is less than the password variable ; and a value greater than zero if the correct
variable is greater than the password
typed.
All of this is in the specification of the strcmp command from language and
causes a problem in if : zero is false. Being so, we need to use the operator ! (
NOT ) to reverse the
return leaving it true for the same strings.
If the password is entered correctly, we send the serial connection to
message

password
correct
with
The
Command

, which you can check on the Serial Monitor. The


Serial.println ("Correct password")
LED on digital pin 13 is lit with digitalWrite (led, HIGH) and will remain so for 5
seconds
thanks to the delay command (5000) .
Next, we use for (int i = 0; i <strlen (password); i ++)
password [i] = '' to clear the password that was entered and wait
a possible new typing. We also reset the pos variable with
pos = 0 for the same reason. We also have to turn off the LED on the
pin 13; for this, we use digitalWrite (led, LOW) .
With this code, we have the project practically ready!
Got it? We just have to replace the LED on pin 13 with a relay,
so that we can control the electric lock with 110V using
the Arduino. Instead of turning on the LED, we will activate the relay which,
for
turn, turn on the lock and open the door.
Before proceeding, remember to take great care
necessary when using electricity. Follow all
safety standards such as carrying out assembly with all
equipment disconnected, protect and isolate contacts and do not
touching metal parts and contacts while the equipment
is in operation. The risks are serious and you must
really be careful not to have an accident. In case of
doubt, review, re-study and seek help.
A relay is an electromechanical switch that has a
coil with a metallic core that is transformed into a
electromagnet when this coil is connected. When the electromagnet,
shown in the next figure, goes into action attracts metallic contacts
existing inside the relay making an electrical connection between them.
There are two types of metallic contacts in a relay: normally
open and normally closed which are moved by the action of the
electromagnet, as we will see below.

Figure 3.9: A relay seen from below with its terminals and the coil connection in evidence
In this figure, terminals numbered 1 and 2 are the contacts for
drive the coil. The relay we are going to use must have the coil
driven by only 5V, so it can be controlled by
Arduino. So with just 5V, we can activate the contacts by
where 110V will pass to activate the electric lock.
Let's see the contact scheme:
Figure 3.10: The relay seen from below with its terminals and the connection of the contacts in evidence
In the case of this figure, the terminals connecting the coil are not
numbered, but you've met them before. The set formed
through terminals 3 and 4 are normally closed contacts, and the
set of terminals 3 and 5 are normally open.
This means that, with the coil disconnected, the connection will be between
the set of terminals 3 and 4. And if the coil is activated, the
connection will be between the set of terminals 3 and 5. And this is how
we will make our switch for the lock.
The following figure shows the position of the terminals when viewed from
up for easy viewing.
Figure 3.11: The relay seen from above with the numbered terminals
There is one last detail before we set everything up. It's not possible
connect the relay directly to the Arduino digital pin. The relay coil
has, in general, a resistance of approximately 70Ω, and a voltage of
5V which results in a current of 0.07A - well above 0.04A
tolerated by Arduino.
However, we can activate it by pin 5V, which is connected
directly to the Arduino voltage regulator which can supply
0.5A. As our total circuit will not consume current above
of that maximum limit, we can use it without problems. For
able to do all of that, we will use a transistor that will make the
interface between the Arduino digital pin and the 5V pin to trigger the
Arduino coil.
First, see the connection of the TIP102 transistor on the prot-o-board:
Figure 3.12: The TIP102 transistor connected to the prot-o-board and connected to the Arduino
Connect the base terminal of the transistor to a 1KΩ resistor, and the
another terminal of the resistor to the digital pin 13 of the Arduino. Like this,
we will not change anything in the program at all.
To the emitter terminal of the transistor, connect one of the GND pins of the
Arduino. The collector terminal of the transistor must be connected to one of
the
terminals of the relay coil. And the other terminal of the relay coil
must be connected to the 5V.
Figure 3.13: The transistor connected to the Arduino's GND and the relay coil, and the relay connected to the 5V
Arduino
Among the contacts of the normally open relay, we will place
our electric lock: just disconnect one of the wires and connect it to the relay,
normally open contacts. So when we trigger the
relay coil, the lock will also be activated.
Figure 3.14: One of the lock drive wires in the sectioned relay with the relay between the
lock and fountain
The following is a panoramic picture of the project:
Figure 3.15: The complete project
With everything set up and ready, just enter the correct password and see the
lock is activated.
A video of this project in operation can be seen at https://youtu.be/dR3-
ssrLrWA .
There are plenty of additions to this project. The possibilities are practically
endless!

3.3 CHALLENGE
You can include a buzzer and, with each key, you can emit a beep to indicate
that the typing has happened. It is also possible include an LCD display to
indicate messages to the user, such as like "access denied", "enter your
password" or even "welcome coming! ".
It is also important to give the user the possibility to generate and
record your own password from an initial password. For this, you can leave
the password saved in the EEPROM memory.
In the EEPROM memory, you can still save who opened the gate (through
password identification) and when this occurred.
Then, through a serial connection (you can also think of bluetooth) with a
computer, you can download this log and know how was the traffic in it
local.
In the next project, we will measure the speed of any thing that moves, but
relatively closely. So, get ready and run!

Figure 4.1: The ultrasonic sensor with its numbered terminals


Terminal 1 must be connected to the 5V and the 4 to the Arduino GND,
which are the electrical power terminals of the sensor. Terminal 2
is the trigger and should be set to high ( HIGH ) and then
then down ( LOW ). This is the signal for the sensor to start
emit the ultrasound pulses and wait for the return.
After the trigger is triggered, the sensor emits eight pulses
(40 KHz), which cannot be heard by humans
because of the frequency used. After emitting the pulse, it leaves the
Echo terminal (3) high ( HIGH ) until this pulse is detected
after reflecting (echoing) on ​some obstacle, when will the
Echo terminal for LOW . With the relationship between the speed of sound
and the time that the Echo terminal was at HIGH , it is possible
determine how far away the obstacle is.
Let's get it up and running! Connect the VCC terminal of the
sensor to the Arduino's 5V and then the sensor's GND terminal
to one of the Arduino GNDs, as in the following figure.
Figure 4.2: VCC (1) and GND (4) terminals connected to the Arduino
Now connect the Echo terminal to the digital pin 2 of the Arduino, and the
Trig terminal to digital pin 3 of the Arduino.
Figure 4.3: Echo (3) and Trig (2) terminals of the sensor connected to the Arduino
With the calls made, we can test it. Before you start anything, you will need
to download and install it on your Arduino IDE the Ultrasonic library. It is
super useful, as it saves us from having to perform various calculations to
count the time the pulse ultrasonic goes to an obstacle and comes back, and
then convert everything in centimeters, meters or even inches.
You can download the Ultrasonic library at
https://github.com/fbryan/ultrasonic .
To install the library on your Arduino IDE, use the same steps already
presented in project nº 02 (chapter 03).
Finally, let's go to the code:

# include <Ultrasonic.h>
Ultrasonic sensor (3, 2);
void setup ()
{
Serial.begin (9600);
}
void loop ()
{
measured float ;
long time = sensor.timing ();
measure = sensor.convert (time, Ultrasonic :: CM);
Serial.print ( "Round trip time =" );
Serial.print (time);
Serial.print ( "microseconds -" );
Serial.print ( "Measured distance =" );
Serial.print (measure);
Serial.println ( "cm" );
delay (1000);
}

The first step is to import the Ultrasonic.h library with


#include <Ultrasonic.h> . Then, we created the object
sensor as being of the Ultrasonic type . The parameters passed
are where the Trig and Echo terminals are connected, with the Trig
is on digital pin 3, and Echo on digital pin 2 on the Arduino.
In the setup () function , we only start serial communication 9600 baud
computer using the command Serial.begin (9600) . In the loop () function , we
declare a float type variable , called measure , which will store what is
measured by the sensor.
We also declare a variable of type long called time , which is already initialized
with the return of the timing () method of the sensor object , which is the total
time that the ultrasonic pulse
it takes to be emitted, reflected in an object and be detected in a return. This
method already includes the routine of firing the sensor trigger and control
it. The measured variable then receives the return of the method convert from the
sensor object . This method should receive as
microseconds parameter of round trip pulse time ultrasonic and the unit of
measurement to be used. The measure to be used can be Ultrasonic :: CM to
return the measurement in
centimeters, or Ultrasonic :: IN to return in inches.
In the rest of the code we send the data to the Monitor
Serial and we use a delay (1000) to make a measurement every
second. To test, compile and send Sketch to your Arduino.
Open the Serial Monitor and you should see something
similar to the figure below.

Figure 4.4: Serial Monitor showing the measurement results


Ok, we know how the ultrasonic sensor works and how
program it, but it's not quite what we want yet. We need
make a measurement and, immediately after, make another and, for the
difference
of distance between them, calculate the displacement. Recalling the
High School Physics classes and with the following code,
we solved this:

# include <Ultrasonic.h>
Ultrasonic sensor (3, 2);
previous float = 0;
float distance = 0;
displacement float = 0;
void setup ()
{
Serial.begin (9600);
}
void loop ()
{
long time = sensor.timing ();
measure float = round (sensor.convert (time, Ultrasonic :: CM));
distance = abs (measure - anterior);
displacement = (distance * 10) / 100;
Serial.print ( "previous =" );
Serial.print (previous);
Serial.print ( "-" );
Serial.print ( "measure =" );
Serial.print (measure);
Serial.print ( "-" );
Serial.print ( "distance =" );
Serial.print (distance);
Serial.print ( "-" );
Serial.print ( "speed =" );
Serial.print (offset);
Serial.println ( "m / sec" );
delay (100);
previous = measure;
}

This code is basically a modification of the previous one. In him


we declare the sensor object of type Ultrasonic , as in the code
above, and three global float variables .
The first variable is called the previous one , which will store the
immediately previous measurement, so that we can make the relationship
between two measurements and calculate the displacement, which also has
its variable ( offset ) to store it. The variable
distance will store the subtraction between the previous variable
(with the measurement in the previous instant) and the measured variable ,
contains the measurement at the current time.
In the setup () function , again we start the communication
serial with the computer with a baud rate of 9600 baud.
In the loop () function , we declare the variable of type long
called time , which is already initialized with the return of the method
timing () of the sensor object , being the total time that the pulse
ultrasound takes to be emitted, reflected in an object and be
detected back. The variable measured this time will receive the value of
convert method of sensor in centimeters already rounded,
not to contain too many decimal places.
Next, we calculate the distance traveled between the measurement
previous and current ( measured variable ). To do this, simply subtract a
the other. We use the abs function to return the value in
module, ie ignoring the signal. This result will be stored
in the distance variable .
To find out the displacement, we multiply the distance covered
by 10, because we want to know the measurement in seconds, since the time
data is 100 milliseconds between measurements (command delay (100) further
down in the code). Then, we need to divide everything for 100, since the
desired is to obtain the data in meters and
not centimeters, as the convert method of the sensor object
Returns.
The Serial.print and Serial.println command sequence
will send all data to the Serial Monitor, so you can
track measurements. Finally, we match the variable
Figure 4.6: The button connected to the Arduino
As we are not using prot-o-board, we have no way
share digital pin 4 or 5V with more than one
component. So I'm going to use the Arduino's internal PULL-UP resistor
on digital pin 4.
The Arduino's internal PULL-UP resistor is activated via software and has a
value between 20KΩ and 50KΩ. It will have the effect of ensure the
function of the button. That is, when the button is
open, we will read on digital pin 4 the HIGH value , and when it is closed
(pressed), we will read the LOW value on that same pin.
Let's change our code so that only measurements take place
when the button is pressed:

# include <Ultrasonic.h>
Ultrasonic sensor (3, 2);
int button = 4;
previous float = 0;
float distance = 0;
displacement float = 0;
void setup ()
{
Serial.begin (9600);
pinMode (button, INPUT_PULLUP);
}
void loop ()
{
if (digitalRead (button) == LOW) {
long time = sensor.timing ();
measure float = round (sensor.convert (time, Ultrasonic :: CM));
distance = abs (measure - anterior);
displacement = (distance * 10) / 100;
Serial.print ( "previous =" );
Serial.print (previous);
Serial.print ( "-" );
Serial.print ( "measure =" );
Serial.print (measure);
Serial.print ( "-" );
Serial.print ( "distance =" );
Serial.print (distance);
Serial.print ( "-" );
Serial.print ( "speed =" );
Serial.print (offset);
Serial.println ( "m / sec" );
delay (100);
previous = measure;
}
}

The changes from this code to the previous one are really few
again: I declared an entire variable called a button , initialized with number 4,
indicating which digital pin it is on button on. With pinMode (button,
INPUT_PULLUP) ,
initialize the button pin with the activation of the PULL-UP resistor
as explained above.
If the button is pressed, the return of the digital pin will be
LOW , so I used the if selection structure (digitalRead (button)
== LOW) to read the pin return and compare it with LOW . If
comparison is true, the code that performs the
ultrasonic sensor measurements and calculates speed.
Only two things are missing: include a two-segment 7-segment display
digits or two single-digit 7-segment displays to show the
speed and put everything somewhere to make it more practical
than the table. So, let's go to him.
A 7-segment display is a display for numbers
just (although I really like to invent with him, making him
show other things).

Figure 4.7: A 7-segment display

The display consists of 7 LEDs that, on or off in


together show shapes of numbers. There is also the point
decimal, which is also a segment that can be lit or not.
Look the following picture:
Figure 4.9: The identified segments
The 7-segment display that I will use will have two digits. That is,
will consist of two conjugated displays, each terminal
will link the segments of both displays. But for the segment
lights up, it will also be necessary to supply the common terminal, which
my case will be anode (positive).
Figure 4.10: The 7-segment display with two digits
The terminals are connected to the segments, the decimal point and the
common, as enumeration shown in the figure below that
I will detail shortly after:
Figure 4.11: The display terminals numbered 1 through 10
The segment pins are common to two digits. For
show a number in just one segment, just trigger it
through the common anode pin of the desired digit. To show
different numbers in each of the two digits of the display, just
trigger the segments of one of the digits for a few milliseconds,
then activate the segments of the other digit also for some
milliseconds and alternate between them. The change is so fast
which, to the human eye, it will appear that the two digits are lit as
all the time.
The terminal sequence is:
1. Segment D
2. Decimal point
3. Segment E
4. Segment C
5. Common anode (+ 5Vdc) of the digit on the right
6. Segment B
7. Segment A
8. Segment F
9. Segment G
10. Common anode (+ 5Vdc) of the digit on the left
To activate the display, we will use an existing library that
it will make our life much easier. It’s called SevSeg.h , from Seven
Segments, and can be obtained from
https://github.com/fbryan/sevseg . Use what was explained in
project nº 02 (chapter 3) to install it.
For this library, we will have to pass the pins where they are LED segments
of the 7-segment display are connected and where common display pins will
be connected. We can use both
digital and analog pins for this task - which is excellent, as we don't have
many digital pins left to connect the display, and if we depended on them,
we wouldn't have enough.
To connect the display to the Arduino, use the following scheme:
1. Place a resistor of at least 330Ω in each terminal
common anode, that is, on pins 5 and 10, as shown in the figure:
Figure 4.12: Resistors on the display anodes
2. Now connect the resistors of the common terminals to the Arduino,
the digit on the right (5) must go on the analog pin
A0, and the digit on the left on analog pin A1.
Figure 4.13: Common anodes connected to Arduino
3. Call:
The terminal of segment A (7) to digital pin 5 of the
Arduino;
The terminal of segment B (6) to digital pin 6 of the
Arduino;
Terminal of segment C (4) to digital pin 7;
Terminal of segment D (1) to digital pin 8;
E segment terminal (3) to digital pin 9;
Terminal of segment F (8) to digital pin 10;
Terminal of segment G (9) to digital pin 11;
Decimal point terminal (2) to digital pin 12.
Figure 4.14: All display terminals connected to the Arduino

Let's test to see if it's working properly. Use the following code to show the
number 1.2 on the 7-
segments:

# include <SevSeg.h>
SevSeg display;
void setup () {
byte digits = 2;
byte pino_digitos [] = {A0, A1};
byte pino_segmentos [] = {5, 6, 7, 8, 9, 10, 11, 12};
display.begin (COMMON_ANODE, digits, pin_digits, pin_segment
s);
}
void loop () {
display.setNumber (12,1);
display.refreshDisplay ();
}

After compiling and uploading to your Arduino, you should see the
number 1.2 (the number 1 in the left digit, first dot lit decimal, the number 2
in the right digit and second point decimal), as in the figure before the code.
For this code, we included the SevSeg.h library with the line
#include <SevSeg.h> and then we declare the object
display as being of the SevSeg type with the SevSeg line
display . In the void setup () function , we declare the variable
digits as being byte type and initialized with the number
2. It will determine the number of digits in our
7-segment display.
The typo byte vector , called pino_digitos [] , stores
the pins where the anodes (or cathodes, if applicable) are connected
display digits. The byte vector , called
pin_segments [] , stores where the segments of
Display LED, in alphabetical sequence of segments and, for
last, the decimal point.
With the display.begin method (COMMON_ANODE, digits,
pino_digitos, pino_segmentos) , we initialize the display
indicating COMMON_ANODE , because it is a common anode. If it were
common cathode, we would use COMMON_CATHODE . Then,
we indicate the number of digits on the display, where the pins are
common and segment pins.
In the loop () function , we only use the setNumber method
as display.setNumber (12.1) , indicating that the numbers
shown are 1 in the left digit, 2 in the right digit, and
the first lit decimal point (1). To light the second point
decimal, we should use 0 instead of 1.
Just remember that the display can only show at most
the number of digits you have. The method
display.refreshDisplay () causes the number to be
actually shown.

Figure 4.15: 1.2 on the 7-segment display

Now let's enjoy and do another test with a code


to run the counter from zero to 99. So we can now
envision how to put it all together.

# include <SevSeg.h>
SevSeg display;
void setup () {
byte digits = 2;
byte pino_digitos [] = {A0, A1};
byte pino_segmentos [] = {5, 6, 7, 8, 9, 10, 11, 12};
display.begin (COMMON_ANODE, digits, pin_digits, pin_segment
s);
}
void loop () {
for ( int i = 0; i <= 99; i ++) {
display.setNumber (i, 0);
display.refreshDisplay ();
delay (10);
}
}

The configuration was the same, so I just changed the function


loop () putting a repeating for structure to count from
0 to 99 and increments of 1: for (int i = 0; i <= 99; i ++) .
Then, I changed the line of the setNumber method to use the
variable i , which is the accountant is :
display.setNumber (i, 0) . Then just make the numbers
shown with display.refreshDisplay () and wait for a
small time (10 milliseconds), so you can see them
change with delay (10) .
Now that we understand how it all works, it's easy.
Let's put it all together and finish our radar!
Let's use the codes of the ultrasonic sensor that we already made
previously with that of the 7-segment display that we just
do:

# include <Ultrasonic.h>
# include <SevSeg.h>
Ultrasonic sensor (3, 2);
SevSeg display;
int button = 4;
previous float = 0;
float distance = 0;
displacement float = 0;
void setup ()
{
pinMode (button, INPUT_PULLUP);
byte digits = 2;
byte pino_digitos [] = {A0, A1};
byte pino_segmentos [] = {5, 6, 7, 8, 9, 10, 11, 12};
display.begin (COMMON_ANODE, digits, pin_digits, pin_segment
s);
}
void loop ()
{
if (digitalRead (button) == LOW) {
long time = sensor.timing ();
measure float = round (sensor.convert (time, Ultrasonic :: CM));
distance = abs (measure - anterior);
displacement = (distance * 10) / 100;
previous = measure;
}
display.setNumber (offset, 1);
display.refreshDisplay ();
}

After compiling and sending to Arduino, you must press the


button and move something in front of the ultrasonic sensor
to see the speed on the 7-segment display. When you release the button,
the number of the last measurement should remain on the display.
Figure 4.16: Everything assembled and working
You can see a video of this project in operation at
https://youtu.be/wOZspVR4sT8 .
All of this became irresistible to put in a pistol from
video game, and let the kids play as I suggested in the introduction:
Figure 4.17: The project mounted on a video game gun

Try to put the whole project inside a pistol, as I did and


I showed you earlier, to mimic the police radars that we see
on Brazilian roads! You can build your own pistol if
you don't have one that fits your remote controls
video game. Thus, your project gains mobility, and for sure
may be useful to explain concepts of physics, in the case of propagation
and speed of sound, at science fairs and classes.
After so much movement in this project, the next one is for
those who like convenience and don't want to move around that much:
how about turning on the lamps in your house with a remote control?

4.3 CHALLENGE
These receivers usually come with the
remote control and can be found in specialty stores
electronics and Arduino. But if you want to use any other
remote control is also possible. So, if you wish,
just get the infrared receiver only. Imagine, you can
use the television control and, with the correct key sequence,
control any light!
Assembly is simple. The receiver has a pin marked with
a letter S , and this is the signal pin. For him, we will receive the
values ​of keys pressed. The middle pin is the + 5V and the
left is the GND.

Figure 5.2: The infrared receiver with the signal pin marked with the letter “S”
The assembly is to connect the signal pin of the receiver to the pin
digital 3 from Arduino; the + 5V pin on the receiver to the 5V pin on the
Arduino; and the GND pin on the receiver to one of the GND pins on the
Arduino.

Figure 5.3: The connection between the infrared receiver and the Arduino
In order to be able to capture the keys on the remote control via
infrared receiver, we will have to use an IRLib library, which
can be obtained at https://github.com/fbryan/irlib . Just do
download the ZIP file and, to include it in the Arduino IDE, make the
same way that was also presented in project nº 02
(chapter 3).
With the library already included in the IDE, let's first test the
receiving the remote control keys you want to use. Each
key sends a different value to the receiver, which needs to be read and
interpreted to perform tasks according to your program
to determine.
We will use the small program below to get these
values ​and write them down, so we can put everything together and make the
program
that will control the light.

# include <IRLib.h>
Decoder IRdecode;
IRrecv receptor (3);
void setup () {
Serial.begin (9600);
receptor.enableIRIn ();
delay (100);
}
void loop () {
if (receiver.GetResults (& decoder)) {
decoder.decode ();
delay (100);
Serial.println (decoder.value, HEX);
receiver.resume ();
}
}

Load it onto the Arduino and open the Serial Monitor. Point the
control to the receiver and start pressing the keys. You will see
the values ​corresponding to each of them after they are
decoded.
Figure 5.4: Key values ​from 0 to 9 on the remote control that came with the receiver

With this program, we can know the value of the any remote control. You
can use it to test with the control of the TV, pay-TV receiver, sound, in short,
from any control. Just test them out.
We started by importing the library we downloaded and we incorporated the
Arduino IDE, IRLib.h . She will give us a series tools that will make work
easier to receive and
decode the signal we are receiving.
With IRdecode decoder , we are instantiating a object called an IRdecode decoder ,
which allows you to decode and interpret various aspects of the received
signal, such as the number of bits, value and protocol.
With IRrecv receiver (3) , we instantiate an object called a receiver that passes
the digital pin as a parameter where the signals from the receiver will be
received. This object is of type
IRrecv which, like IRdecode , allows us to obtain a series of controls on the
receiver, such as initializing or resetting it.
In the setup () function , we initiate a serial communication with Serial.begin
(9600) so that we can then see the values received by the Serial Monitor. We
use receptor.enableIRIn ()
to initialize the infrared receiver, and we give it an
100 milliseconds time to start with delay (100) .
In the loop () function , we use an if selection structure
(receiver.GetResults (& decoder)) to check for
a received signal. If it exists, the Arduino tries to decode it; case
otherwise, he must do nothing. That is, only if there is a
signal to be decoded we will try to decode it.
The decoder.decode () line causes the signal to be decoded and its data stored in a
structure within the decoded object, with some of the fields that can be
accessed are:

Field
Type
description
decode_type
char
Protocol name of the decoded signal (NEC, SONY, RC5
etc.)
value
long
Decoded value
bits
char
Number of bits in the decoded value

You need to allow time for the Arduino to process the


decoding. So, we use delay (100) to give you 100
milliseconds for that, which is enough.
In the line Serial.println (decoder.value, HEX) ,
we show the value field mentioned earlier in Serial Monitor in hexadecimal
format. That is, we show the value of signal corresponding to a key on the
remote control that was
Received. To end the cycle, before starting all over again, restart the receiver
with receiver.resume () , so that it can do the next reading.
Well, we already have the values ​we want, now let's go to program that will
control the lamp. I will use the same strategy as project nº 02 (chapter 3):
first we will make the pin LED
digital 13 lights up when the correct key is pressed, then we will make the
circuit for the relay with the lamp itself.

# include <IRLib.h>
Decoder IRdecode;
IRrecv receptor (3);
int led = 13;
long value = 0;
void setup () {
pinMode (led, OUTPUT);
receptor.enableIRIn ();
delay (100);
}
void loop () {
if (receiver.GetResults (& decoder)) {
decoder.decode ();
delay (100);
value = decoder.value;
if (value == 0xFF4AB5) {
digitalWrite (led, HIGH);
delay (1000);
digitalWrite (led, LOW);
}
receiver.resume ();
}
}

This program is just a change from the previous program,


few changes as you can verify. We just declare variables to identify the
digital pin where the LED is connected, and another to receive the value that
is read by the receiver
infra-red.
In the setup () function, we set the LED digital pin as
output, and we start the infrared receiver, giving it 100
milliseconds to complete the task. In the loop () function , if
we have some signal to be decoded, we do that and
we save the value read in the value variable , with the line value =
decoder.value .
With an if selection structure (value == 0xFF4AB5) ,
we can verify that the zero key on the remote control has pressed. We used
this value because it was read with the program previous where we tested
our keys of interest of the control remote. For your control, it can be a
different value, so the importance of using the test program before.
Well, when the key we want is pressed, we light the LED for a second and
then we leave it off. What, let's face it, it doesn't make any sense: nobody
will want
turn on the light using a remote control so that it stays on only
one second! We will greatly improve our program so
very simple.

# include <IRLib.h>
Decoder IRdecode;
IRrecv receptor (3);
int led = 13;
long value = 0;
void setup () {
pinMode (led, OUTPUT);
receptor.enableIRIn ();
delay (100);
}
void loop () {
if (receiver.GetResults (& decoder)) {
decoder.decode ();
delay (100);
value = decoder.value;
if (value == 0xFF4AB5) {
digitalWrite (led,! digitalRead (led));
delay (1000);
}
receiver.resume ();
}
}
Note that we only switch the lines that were inside the
if selection structure (value == 0xFF4AB5) , in which we verify
if the value read is the zero key on the remote control. We removed
also the lines:

digitalWrite (led, HIGH);


delay (1000);
digitalWrite (led, LOW);

They lit the LED on digital pin 13 for just a second.


So, we add the lines:

digitalWrite (led,! digitalRead (led));


delay (1000);

In them, we read the status of digital pin 13 ( HIGH or LOW ), and


we apply its reverse to itself. For this, we use
! digitalRead (led) , where the exclamation sign means the
logical operator NOT , that is, the inversion of the signal which, if in
HIGH , will be inverted to LOW and vice versa.
Still, we give you a second to wait in case you
keep the button pressed, which would cause the ignition and
repeatedly switching off the light very quickly,
damaging the relay or even burning the lamp. With that, the
minimum time between turning on and off, or between turning off and on,
will be
of a second.
So let's go to the most critical part: turning on a real lamp
and control it with the Arduino through a relay.
Before you start, remember to take all necessary care
when using electricity. Follow all
safety such as carrying out the assembly with all
disconnected equipment, protect and isolate contacts, and do not
touching metal parts and contacts while the equipment
is in operation.
The risks are serious and you should really be careful not to
suffer an accident. If in doubt, review, re-study and
seek help.
How this project works in the same way as project nº 02
(chapter 3), there you already have all the explanations of the operation and
circuit to connect the relay. So, I'm going to skip that part. You
you can re-read it if you don't remember any details.
First, let's connect the TIP102 transistor to the prot-o-board:

Figure 5.5: The TIP102 transistor connected to the prot-o-board and connected to the Arduino
Connect the base terminal of the transistor to a 1KΩ resistor, and the
another terminal of the resistor to the digital pin 13 of the Arduino. Like this,
we will not change anything in the program at all. Note in the figure
previous that I changed the 5V power supply of the
infrared to facilitate feeding the relay as well.
To the emitter terminal of the transistor, connect one of the GND pins of the
Arduino. The collector terminal of the transistor must be connected to one of
the
terminals of the relay coil. And the other terminal of the relay coil
must be connected to the 5V, which can be used on the prot-o-board in
together with infrared sensor power.

Figure 5.6: The transistor connected to the Arduino GND and the relay coil, and the relay connected to the 5V
Arduino
Between the relay contacts for switching normally
open, let's put our lamp. In my case, I will use a
lamp, which is an old companion and which, from now on,
receive an upgrade! I'll put the relay in parallel with the button
turns it on / off.
Figure 5.7: The lamp
With proper care, the wires that go into the relay will be connected
button contacts:
Figure 5.8: The wires that will be connected to the normally open contacts of the relay

Note that I'm using thin, ordinary wires, because the lamp
that is on the lamp is of low power (7W), so the current that
flow through the wires is very low (approximately 0.05A). IT'S
It is strongly recommended that you use suitable wire sizes
for the amount of current that will be used for the type of
lamp you are using in your project.
The connection between the switch and the relay is very simple,
connect the wires to the terminals of the normally open contact of the relay.
Figure 5.9: The switch wires to the normally open contact terminals of the relay

After everything is connected, you can test the general operation.


Now, put the lamp in the socket and connect your Arduino to the
computer. Be careful not to touch any contact that
result in electric shock.
Point the remote control directly at the sensor
infrared and press the zero key. The lampshade lamp should
light up. Wait a second and press the zero key again,
for the lamp shade to go out.
Figure 5.10: Overview of the assembled project

You can now use this same assembly scheme to


automate any lamp in your home, from lamps to
general lighting.
You will find a video of this project in operation
at https://youtu.be/MWAEu2303jM .
The first challenge for everyone is to make this circuit small
enough to be discreetly embedded in lamps or in
home lighting switches. If not, within the
switches, discreetly in a box next to or near
their.
For that, you can use project nº 01 (chapter 2) and start
building your own Arduino. Then you can add the
other components and, of course, create a PCB (Printed Circuit Board

5.3 CHALLENGE
- printed circuit board) specific to all this - which is
always an excellent idea.
Another challenge that can still be tested on the prot-o-board is to create
key combinations to activate the lighting. For example, you uses the TV's
own remote control and, from a combination that doesn't represent a
channel, you turn on the light.
There is also the possibility to activate several lamps from
a single Arduino. In that case, just replicate the set transistor / relay and,
with just one sensor, you can trigger the number of lamps corresponding to
the number of pins
digital devices that are free.
Unleash your imagination. Challenge yourself and good fun!
Do you like playing board games? How about resuming these games,
but with a new attraction: an electronic data? In the next
project, we will develop a data using a matrix of LEDs.
Try to guess what will be the next number drawn, and come on!
The idea is to imitate a given, showing the numbers
(balls) from 1 to 6 and drawing the values ​randomly. But
first of all, you need to build an array of LEDs from
three columns by three rows, that is, 9 LEDs.

Figure 6.1: Possible faces of a four-sided common die. Note the need for a
3x3 matrix

So let's start at the beginning: the LED. With an LED in hand, see
that it has a shorter terminal than the other. This terminal
the shortest is the negative, and the longest is the positive of the LED.

6.2 DEVELOPING THE PROJECT


Figure 6.2: An LED with different sized terminals

You will have to pay attention to connecting the negative terminals without
mix them with the positives, so pay attention to that detail.
We will need to place the LED terminals one for each side, but
this side must be the same for all LEDs. To facilitate, warp
the shortest negative terminal, closer to the LED "head":
Figure 6.3: Negative terminal to one side, with the fold close to the "head" of the LED

Now fold the positive terminal, longer, forming a


90 ° angle to the negative, to visually leave
easier to identify. Make the fold farther from the "head" of the
LED.
Figure 6.4: Positive terminal 90 ° to the other side, with the fold away from the LED "head"

See in the image below the folded terminals, seen from another
angle.
Figure 6.5: Folded LED terminals

Do the same thing for all nine LEDs that will form
our matrix. Then solder the positive terminals of three LEDs,
as in the following figures.
Figure 6.6: The first two LEDs with the positive terminals welded together
Figure 6.7: Now the third LED with the positive terminal soldered to the previous ones

In the following figure, see the three LEDs seen from another angle.
Figure 6.8: The three LEDs with the soldered positive terminals seen from below

Now test the functioning of this first set: place


the resulting positive terminal, which is actually the terminals that
they are welded together, on the prot-o-board. To that terminal, connect a
220Ω resistor and, to the other terminal of the resistor, connect the 5V pin of
the
Arduino. Then switch a wire connected to the Arduino GND pin
to the negative terminals of the LEDs.
Figure 6.9: Assembly test - First LED
Figure 6.10: Assembly test - Second LED
Figure 6.11: Test of the set - Third LED

With that first set working, let's move on.


Make a second set of 3 LEDs and solder the negative terminals
between sets, as in the following figure:
Figure 6.12: A second set of 3 LEDs joined to the first by the negative terminals

Just make sure that the positive and negative terminals do not
lean anywhere.
Figure 6.13: The second set welded to the first, seen from below

Finally, make the third set of our LED array, and

solder the negative terminals of this set to the negative terminals


of the other two sets, as in the figure:
Figure 6.14: The three assemblies joined by the negative terminals

See now from another angle:


Figure 6.15: The three assemblies joined by the negative terminals, seen from below

Finally, at the positive terminals, solder 220Ω resistors,


as in the next figure.
Figure 6.16: Resistors to the positive terminals of the matrix

Now let's go to the connection scheme between the LED matrix and the
Arduino. Connect the positive terminals to digital pins 2, 3 and 4 on the
Arduino. Use a string, but considering that the terminal of the
middle is always the second, and it must be on digital pin 3.
Figure 6.17: Positive terminals of the LED array connected to the Arduino

Next, connect the negative terminals to digital pins 8, 9


and 10 from Arduino. Use a string, but considering that the
middle terminal is always the second, and that must be on the pin
digital 9.
Figure 6.18: Negative terminals of the LED array connected to the Arduino {W = 100%}

To test if everything is working, we will use the following


program:

void setup () {
pinMode (2, OUTPUT);
pinMode (3, OUTPUT);
pinMode (4, OUTPUT);
pinMode (8, OUTPUT);
pinMode (9, OUTPUT);
pinMode (10, OUTPUT);
}
void loop () {
digitalWrite (2, HIGH);
digitalWrite (3, HIGH);
digitalWrite (4, HIGH);
digitalWrite (8, LOW);
digitalWrite (9, LOW);
digitalWrite (10, LOW);
}

It is a very simple program and does not require any


explanation of the commands used. The detail is in using the
pins with HIGH output to supply voltage to the LEDs, and the pins
with LOW output to function as ground, making the
current flow and turn on the LED.
When we have digital pin 2 at HIGH and digital pin 8 at
LOW , we have the positive-negative connection to light all
LEDs of the first line of the LED array. If we put the pin
digital 2 in LOW and / or digital pin 8 in HIGH , the current will flow
unlike the LED, which will be off.
Figure 6.19: All LEDs on

Now let's change this program to show exactly


this operation between HIGH and LOW on the digital pins, to
turn the LEDs on and off:

void setup () {
pinMode (2, OUTPUT);
pinMode (3, OUTPUT);
pinMode (4, OUTPUT);
pinMode (8, OUTPUT);
pinMode (9, OUTPUT);
pinMode (10, OUTPUT);
}
void loop () {
for ( int i = 1; i <= 3; i ++) {
for ( int j = 1; j <= 3; j ++) {
lights (i, j);
delay (500);
}
}
}
void lights up ( int row, int column) {
if (line == 1) digitalWrite (2, HIGH); else digitalWrite (2, LOW);
if (line == 2) digitalWrite (3, HIGH); else digitalWrite (3, LOW);
if (line == 3) digitalWrite (4, HIGH); else digitalWrite (4, LOW);
if (column == 1) digitalWrite (8, LOW); else digitalWrite (8, HIGH);
if (column == 2) digitalWrite (9, LOW); else digitalWrite (9, HIGH);
if (column == 3) digitalWrite (10, LOW); else digitalWrite (10, HIGH)
;
}

The setup () function has not changed, it just adjusts the digital pins
as an output, ie OUTPUT . At the end of the program, I created a
voidfunction lights up (int row, int column) , which is void ,
then it will not return any value and will receive two parameters
integers called row and column .
This function lights a specific LED, in the row and column
desired, checking which line is informed, and places the value
HIGH on the respective digital pin, to turn on the LED. However, if
line is not the one informed by the line parameter , the value on the pin
respective digital will be LOW , extinguishing the LED. The column works as
Similarly.
In the function () loop , created two repeating structure is to
count the three rows and the three columns, and pass the LED exactly
that I want to light up with an interval of 500 milliseconds between
turn each LED on and off.
Watch a first LED matrix test video, available at
https://youtu.be/4KByD_i8E1A .
Since we can turn on a specific LED, we will create the
data numbers with the following program:

void setup () {
pinMode (2, OUTPUT);
pinMode (3, OUTPUT);
pinMode (4, OUTPUT);
pinMode (8, OUTPUT);
pinMode (9, OUTPUT);
pinMode (10, OUTPUT);
}
void loop () {
one (1);
two (1);
three (1);
four (1);
five (1);
six (1);
}
void lights up ( int row, int column) {
if (line == 1) digitalWrite (2, HIGH); else digitalWrite (2, LOW);
if (line == 2) digitalWrite (3, HIGH); else digitalWrite (3, LOW);
if (line == 3) digitalWrite (4, HIGH); else digitalWrite (4, LOW);
if (column == 1) digitalWrite (8, LOW); else digitalWrite (8, HIGH);
if (column == 2) digitalWrite (9, LOW); else digitalWrite (9, HIGH);
if (column == 3) digitalWrite (10, LOW); else digitalWrite (10, HIGH)
;
}
void one ( int t) {
unsigned long time;
unsigned long tempo_anterior = tempo = millis ();
while (time - previous_time <(t * 1000)) {
time = millis ();
lights (2,2);
}
}
void two ( int t) {
unsigned long time;
unsigned long tempo_anterior = tempo = millis ();
while (time - previous_time <(t * 998)) {
time = millis ();
lights (1,1);
delay (1);
lights (3.3);
delay (1);
}
}
void three ( int t) {
unsigned long time;
unsigned long tempo_anterior = tempo = millis ();
while (time - previous_time <(t * 997)) {
time = millis ();
lights (1,1);
delay (1);
lights (2,2);
delay (1);
lights (3.3);
delay (1);
}
}
void four ( int t) {
unsigned long time;
unsigned long tempo_anterior = tempo = millis ();
while (time - previous_time <(t * 996)) {
time = millis ();
lights (1,1);
delay (1);
lights (1,3);
delay (1);
lights up (3.1);
delay (1);
lights (3.3);
delay (1);
}
}
void five ( int t) {
unsigned long time;
unsigned long tempo_anterior = tempo = millis ();
while (time - previous_time <(t * 995)) {
time = millis ();
lights (1,1);
delay (1);
lights (1,3);
delay (1);
lights (2,2);
delay (1);
lights up (3.1);
delay (1);
lights (3.3);
delay (1);
}
}
void six ( int t) {
unsigned long time;
unsigned long tempo_anterior = tempo = millis ();
while (time - previous_time <(t * 994)) {
time = millis ();
lights (1,1);
delay (1);
lights (1,2);
delay (1);
lights (1,3);
delay (1);
lights up (3.1);
delay (1);
lights (3.2);
delay (1);
lights (3.3);
delay (1);
}
}

The setup () function remains the same as before. The function


loop () calls the functions that light specific LEDs for
each data number, passing the time as a parameter, in
seconds, so we want that number to be kept on.
And the function lights up remains the same as before.
In the sequence, we have six void functions , which do not
return value and receive a parameter of type integer, called
of t . This parameter is the number of seconds that the LEDs
must remain lit.
We will not be able to use the delay function to pause the program
with the LEDs on, as we will need to multiplex them. note that
it is not possible to light more than one LED at a time, so in the case of
more than one LED is required for the number, the functions light up
the first, keep it lit for a millisecond, erase it and
light the second, also keeping it lit for a
millisecond - and so on, by the number of LEDs
necessary to form the number on the die.
All of this is done using the millis () function , which returns in
millisecond how long the program has been running. For
To begin, I declare two variables with the largest possible data type:
and unsigned long tempo_anterior .
unsigned long tempo
They start with the same value and, while the difference between
they are less than the time passed by the function parameter
subtracted from a millisecond for each LED, they maintain the
multiplexing between the LEDs. That is, it turns on and off so fast
that the human eye will perceive everyone as lit.
You can see the result of this program in operation
in the video available at https://youtu.be/i0mJV4R2tfw .
To finish the project, we just need to make the data
draw a random value and show the number in the LED array.
Let's go to the last program:

void setup () {
pinMode (2, OUTPUT);
pinMode (3, OUTPUT);
pinMode (4, OUTPUT);
pinMode (8, OUTPUT);
pinMode (9, OUTPUT);
pinMode (10, OUTPUT);
randomSeed (analogRead (A0));
int number = random (1,6);
if (number == 1) one (5);
if (number == 2) two (5);
if (number == 3) three (5);
if (number == 4) four (5);
if (number == 5) five (5);
if (number == 6) six (5);
delete ();
while (1);
}
void loop () {
}
void clears () {
digitalWrite (2, LOW);
digitalWrite (3, LOW);
digitalWrite (4, LOW);
digitalWrite (8, HIGH);
digitalWrite (9, HIGH);
digitalWrite (10, HIGH);
}
void lights up ( int row, int column) {
if (line == 1) digitalWrite (2, HIGH); else digitalWrite (2, LOW);
if (line == 2) digitalWrite (3, HIGH); else digitalWrite (3, LOW);
if (line == 3) digitalWrite (4, HIGH); else digitalWrite (4, LOW);
if (column == 1) digitalWrite (8, LOW); else digitalWrite (8, HIGH);
if (column == 2) digitalWrite (9, LOW); else digitalWrite (9, HIGH);
if (column == 3) digitalWrite (10, LOW); else digitalWrite (10, HIGH)
;
}
void one ( int t) {
unsigned long time;
unsigned long tempo_anterior = tempo = millis ();
while (time - previous_time <(t * 1000)) {
time = millis ();
lights (2,2);
}
}
void two ( int t) {
unsigned long time;
unsigned long tempo_anterior = tempo = millis ();
while (time - previous_time <(t * 998)) {
time = millis ();
lights (1,1);
delay (1);
lights (3.3);
delay (1);
}
}
void three ( int t) {
unsigned long time;
unsigned long tempo_anterior = tempo = millis ();
while (time - previous_time <(t * 997)) {
time = millis ();
lights (1,1);
delay (1);
lights (2,2);
delay (1);
lights (3.3);
delay (1);
}
}
void four ( int t) {
unsigned long time;
unsigned long tempo_anterior = tempo = millis ();
while (time - previous_time <(t * 996)) {
time = millis ();
lights (1,1);
delay (1);
lights (1,3);
delay (1);
lights up (3.1);
delay (1);
lights (3.3);
delay (1);
}
}
void five ( int t) {
unsigned long time;
unsigned long tempo_anterior = tempo = millis ();
while (time - previous_time <(t * 995)) {
time = millis ();
lights (1,1);
delay (1);
lights (1,3);
delay (1);
lights (2,2);
delay (1);
lights up (3.1);
delay (1);
lights (3.3);
delay (1);
}
}
void six ( int t) {
unsigned long time;
unsigned long tempo_anterior = tempo = millis ();
while (time - previous_time <(t * 994)) {
time = millis ();
lights (1,1);
delay (1);
lights (1,2);
delay (1);
lights (1,3);
delay (1);
lights up (3.1);
delay (1);
lights (3.2);
delay (1);
lights (3.3);
delay (1);
}
}

The only thing that changes a bit is the setup () function . In it


we use the randomSeed (analogRead (A0)) command to
initialize the generation of pseudo-random numbers on the Arduino. For
the randomSeed function , we must pass a number that will be used
to generate this seed of random numbers. Like the pin
analog A0 is disconnected from any component, it will
return a noise, making the seed different each time
program execution.
Next, we use int number = random (1.6) to
store in the number variable a random value between 1 and 6,
generated by the random function . Then just use a structure of
if selection to check the number and call the function of the
corresponding number.
Each number will be kept lit for 5 seconds and then matrix will erase,
indicating the end of execution, since the function loop () is empty and has no
command to execute.
To perform a new data draw, simply reset the Arduino.
You will be able to see this finished project working in
https://youtu.be/TzaHFa9i9qQ .
Good moves!
I think the main challenge of this project is to put it in a
box that accommodates the LEDs on display, so that it can be used
effectively as a given.
This may require you to return to project # 01 (chapter
2) and create your own Arduino, so that everything is small or
enough for the data to have, in addition to the LEDs, the Arduino and a
9V battery. It is also interesting to make the LEDs flash in
some sequence when no number is being drawn.
Good fun with your board games! And speaking of
games, how about we create our own video game? Very simple,
clear, but playable enough on a TV with an input
analog type RCA. Here we go?
6 CHALLENGE
Figure 7.1: Components needed to create our video game

Take the two resistors and solder one terminal of each to a


cable routes. You will see in the next figure that I used the wire
red for that.
Figure 7.2: Resistors on one of the cable wires

On the other side of the cable, weld the same wire that received the
resistors to the center of the RCA connector. In my case, I used the wire
red for the resistors, so on the other side of the cable, the wire
red will be welded to the center of the RCA connector. The other wire must
be welded to the other (external) terminal of the RCA connector.
Figure 7.3: Wires soldered to the RCA connector

Now connect the other terminal of the 470Ω resistor to the digital pin
7, and the other terminal of the 1KΩ resistor to digital pin 9 of the
Arduino. The other wire, on the same side of the resistors, goes to the pin
Arduino GND.
Figure 7.4: Connection with Arduino

The RCA connector goes to the video input on your television.


Ready! I said it would be easy, all connections with Arduino and TV's done!
Let's go to the schedule.
You will first need to obtain the TVout library, which is
available at https://github.com/fbryan/tvout . To install it, follow
the procedures of project nº 02 (chapter 3).
Now, let's go to the program:

# include <TVout.h>
# include <video_gen.h>
TVout tv;
int led = 13;
void setup () {
pinMode (led, OUTPUT);
if (tv.begin (NTSC, 128.96) == 0) {
digitalWrite (led, HIGH);
} else {
digitalWrite (led, LOW);
}
delay (1000);
tv.draw_rect (0,0,71,55, WHITE, BLACK);
tv.draw_line (0,0,10,10, WHITE);
tv.draw_circle (36,28,10, WHITE);
tv.set_pixel (36.28, WHITE);
}
void loop () {
}

At the beginning we have the import of the two libraries


necessary to generate images on the TV. We do this with #include
<TVout.h> and #include <video_gen.h> .
The next step is to create an object of type TVout called
tv , which will be used to execute the methods available for
create images on your TV. I also created a variable called
led , of the whole type, that receives the value 13 , to indicate the pin
digital display with a used LED, just to indicate the good
functioning of everything.
In the setup () function , we set the digital LED pin as
output using pinMode (led, OUTPUT) . Then we use
tv.begin (NTSC, 128.96) to start imaging
with the NTSC standard and resolution of 128x96 pixels.
Supported standards are NTSC or PAL and the best resolution
in practice it needs to be discovered empirically. This function
returns 0 if initialization is normal; 1 if the resolution
horizontal is not a multiple of 8; 2 if the vertical resolution does not
be a multiple of 8; and 3 if there is not enough memory in the
Arduino. Therefore, we place it within a structure of
ifselection . If the return is normal startup, we
the LED on digital pin 13 and we move on. If returned
any error code, the LED will be off, indicating something

Figure 7.5: Result of the program on TV

Okay, picture on TV! Time to start creating our game. THE


first step will be to make the asteroids come out of the left of the screen and
go to the right. The program is as follows:

# include <TVout.h>
# include <video_gen.h>
TVout tv;
int led = 13;
int x = 0;
int y [5];
void setup () {
pinMode (led, OUTPUT);
if (tv.begin (NTSC, 128.96) == 0)
digitalWrite (led, HIGH);
else
digitalWrite (led, LOW);
delay (1000);
randomSeed (analogRead (A5));
for ( int i = 0; i <5; i ++) y [i] = random (0, tv.hres ());
}
void loop () {
for ( int i = 0; i <5; i ++) tv.set_pixel (x, y [i], WHITE);
delay (10);
for ( int i = 0; i <5; i ++) tv.set_pixel (x, y [i], BLACK);
delay (10);
if (x> tv.hres ()) {
for ( int i = 0; i <5; i ++) y [i] = random (0, tv.hres ());
x = 0;
} else {
x ++;
}
}

As you can see, importing and initializing the generation


of images are the same. So I’m not going to deal with them
again.
The entire variable x will be the column in which the asteroids should be
be, and the vector y will store the line for each asteroid. Note the
size 5 of the vector, that is, we will only have 5 asteroids at a time.
In the setup () function , we use randomSeed (analogRead (A5))
to initialize the seed of random numbers. We spent as
parameter reading the analog pin A5, which is disconnected and
will generate a random noise, making the seed different
each time the program is started.

With
for (int
i = 0; i <5; i ++)
y [i]
=
random (0, tv.hres ()) , we raffled one row for each asteroid and
we keep it in vector y . In this way, we will maintain the trajectory of
asteroid all the time along the same line, but varying only the
columns.
In the loop () function , we use a repetition structure
for (int i = 0; i <5; i ++) tv.set_pixel (x, y [i], WHITE) for
light the pixels that will be our asteroids. Then we give 10
milliseconds to stay on the screen. Following, we make the
same thing, but to erase them, that way we will have the feeling
of movement.
See excerpt below:

if (x> tv.hres ()) {


for ( int i = 0; i <5; i ++) y [i] = random (0, tv.hres ());
x = 0;
} else {
x ++;
}

In it, we check if the column (variable x ) where the asteroid is


is greater than the horizontal resolution of the screen. If so, you need to
draw a new position for the asteroid lines and return to
variable x to 0. That is, the asteroids will return to the left of the screen
and they will leave for the ship again in new positions of
attack.
If the column is not greater than the horizontal resolution of the screen,
one is added to the variable x so that the asteroid advances to the
right.
Figure 7.6: Asteroids on the screen

You can see a video of this program running at


https://youtu.be/0cNT9CwF3YY .
Now we need to do the control and the ship!
For control, connect the potentiometer to the prot-o-board and a
from its side terminals to the 5V pin, the central one to the analog pin
A0 and the potentiometer terminal on the other side to the GND pin of the
Arduino.
Figure 7.7: Potentiometer connected to Arduino

And to finish, the final program of the game:

# include <TVout.h>
# include <video_gen.h>
TVout tv;
int led = 13;
int x = 0;
int y [5];
int x_nave;
int y_nave;
void setup () {
pinMode (led, OUTPUT);
if (tv.begin (NTSC, 128.96) == 0)
digitalWrite (led, HIGH);
else
digitalWrite (led, LOW);
delay (1000);
randomSeed (analogRead (A5));
for ( int i = 0; i <5; i ++) y [i] = random (0, tv.vres ());
x_nave = tv.hres () - 1;
y_nave = tv.vres () / 2;
}
void loop () {
int ctrl = map (analogRead (A0), 0.1024,0, tv.vres ());
tv.draw_line (x_nave, ctrl-2, x_nave, ctrl + 2, WHITE);
delay (10);
tv.draw_line (x_nave, ctrl-2, x_nave, ctrl + 2, BLACK);
for ( int i = 0; i <5; i ++) tv.set_pixel (x, y [i], WHITE);
delay (10);
for ( int i = 0; i <5; i ++) tv.set_pixel (x, y [i], BLACK);
if (x> tv.hres ()) {
for ( int i = 0; i <5; i ++) y [i] = random (0, tv.hres ());
x = 0;
} else {
x ++;
}
if (x> = x_nave) {
for ( int i = 0; i <5; i ++) {
if ((y [i]> = ctrl-2) && (y [i] <= ctrl + 2)) {
tv.clear_screen ();
for ( int d = 0; d <tv.hres (); d ++) {
tv.draw_circle (tv.hres () / 2, tv.vres () / 2, d, WHITE);
delay (10);
}
delay (15000);
for ( int i = 0; i <5; i ++) y [i] = random (0, tv.hres ());
tv.clear_screen ();
}
}
}
}

As usual, this program is a change from the previous one,


so let's just stick to what has changed. The variables
x_nave and y_nave will be used to store the x and y positions of the
ship.
In the setup () function , the ship's position is one pixel before the
maximum horizontal value defined by x_nave = tv.hres () - 1 , and
in the middle of the screen vertically, defined by y_nave =
tv.vres () / 2 .
In the loop () function , the magic happens! The movement of
asteroids will be the same, but the movement of the ship will be defined
by reading the potentiometer value made with int ctrl =
map (analogRead (A0), 0.1024,0, tv.vres ()) . The entire variable
ctrl (control) will store the reading of analog pin A0, which
returns values ​between 0 and 1024, but will be converted
proportionally between 0 and the total screen resolution -
conversion is done by the map function .
THE
ship
will be
an
line
drawn
with

. Note
tv.draw_line (x_nave, ctrl-2, x_nave, ctrl + 2, WHITE)
that its size is defined by subtracting 2 from the upper limit,
and sum of 2 at the lower limit of the line. When reading the
potentiometer will vary, the ship's position will also vary.
The verification of the collision of the asteroids with the spacecraft is
following block:
if (x> = x_nave) {
for ( int i = 0; i <5; i ++) {
if ((y [i]> = ctrl-2) && (y [i] <= ctrl + 2)) {
tv.clear_screen ();
for ( int d = 0; d <tv.hres (); d ++) {
tv.draw_circle (tv.hres () / 2, tv.vres () / 2, d, WHITE);
delay (10);
}
delay (15000);
for ( int i = 0; i <5; i ++) y [i] = random (0, tv.hres ());
tv.clear_screen ();
}
}
}

The variable x is the position of the asteroid, and x_nave is the position of the
ship. If the asteroid has an x position greater than or equal to that of the ship,
is that they are in the same column, so it may be colliding. Enough
check that they are on the same line.
If the asteroid line is within the ship’s size,
checked with if ((y [i]> = ctrl-2) && (y [i] <= ctrl + 2)) , and
the collision is detected, the sequence will be: clean the screen with
tv.clear_screen () and make a circle grow from the
center
gives
screen,
drawn
with
tv.draw_circle (tv.hres () / 2, tv.vres () / 2, d, WHITE)
,
representing a catastrophic explosion.
Fifteen seconds will pass thanks to the delay (15000) , new
positions for asteroids will be drawn, the screen will be cleared
again and the game will restart.
Figure 7.8: Asteroids towards the ship

Now just have fun!


A video of the game in action can be seen at
https://youtu.be/UDYPNbFKZQ0 .
The sky is the limit! In fact, there are simply no limits! You can
put everything in a box and create your own console. THE
microcontroller can be inside a cartridge, which is
connected to the Arduino as if it were the console. That way, you
can record several different programs on several
different microcontrollers, and have cartridge-shaped games.
For creating games, there are a multitude of possibilities with
plots, movements, drawings, everything different than anybody
never thought, or even playing old games
known and loved. Counting points is also always a good idea
idea! A scoreboard creates the possibility to record records, and challenge
your family and friends to be more agile or faster.
But it's not all fun, you have to monitor and control
some things to avoid unnecessary expenses, for example,
electricity. Therefore, the next project is an alarm in which the
suggestion is to put it in the refrigerator, so as not to allow
forget your open door. Come on!
Figure 8.1: Internal layout of a Reed key

In number 1, we have the terminals; number 2 is the ampoule of


glass; in number 3 we have the contacts, separated by a small
distance; the number 4 represents a magnet that, when approached
key, will make the contacts (3) touch each other, connecting the
circuit, and when the magnet is removed, the contacts will return to the
switching off the circuit.
As I mentioned, inside the magnetic alarm sensor, the
we have is a Reed switch (Reed-switch). So the wires that come out
of the sensor are the switch contacts.
Figure 8.2: A magnetic alarm sensor - inside, there is a Reed switch

All of this makes the connection of the magnetic sensor to the Arduino the
even from a common button. Connect a 1KΩ resistor between the
digital pin 2 and GND, then connect one of the sensor wires to the pin
digital 2 and the other to pin 5V. See how it looks in the figure:
Figure 8.3: The connection of the magnetic sensor to the Arduino

The resistor will function as an external PULL-DOWN resistor.


Note that, in project nº 3 (chapter 4), we use the PULL-UP resistor
internal, but in this case I decided to show how to do it without using it.
PULL-DOWN will guarantee the LOW value on digital pin 2
while the button is not pressed (open). And it will guarantee the
HIGH value when it is closed, that is, pressed.
To test, let's create a code that, when the contacts of the
Reed switches are closed (that is, when the magnet is
next), the LED on digital pin 13 of the Arduino will be on.
When you move the magnet away, the Reed switch contacts will open and
the
LED will go out. With that, we can verify in practice the
functioning of all this.
int led = 13;
int sensor = 2;
void setup () {
pinMode (led, OUTPUT);
pinMode (sensor, INPUT);
}
void loop () {
if (digitalRead (sensor) == HIGH) {
digitalWrite (led, HIGH);
} else {
digitalWrite (led, LOW);
}
}

The entire led variable indicates which digital pin the


LED that we will activate. The sensor variable indicates which pin
digital is linked to our Reed key. In the setup () function , only
we set digital pin 13 (of the LED) as output, and digital pin 2
(from the sensor) as input.
In the loop () function , we use digitalRead (sensor) to read the
state of the digital pin of the button, which is pin 2. It will return the
LOW ( 0 ) values if the switch is open (off), or HIGH
( 1 ) if the key is closed (on). Knowing this, just use
an if selection structure (digitalRead (sensor) == HIGH)
to find out if the key is closed and, if it is, turn on the LED
with digitalWrite (led, HIGH) ; otherwise, we turn off the LED
with digitalWrite (led, LOW) .
After compiling and uploading the program to your
Arduino, you can test the operation of the program and the
sensor bringing the magnet closer to the sensor. When the magnet is
close enough, the LED on digital pin 13 on the Arduino should
light up; otherwise it must remain off. Note that
distance the magnet has an influence on the sensor can vary,
but it is usually approximately 2 centimeters.
Figure 8.4: Magnet influencing the sensor and turning on the digital pin LED 13

Now let's change our code to capture the time when


that the refrigerator door was open:

int led = 13;


int sensor = 2;
int ctrl_abre = 0;
int ctrl_fecha = 0;
unsigned long tempo_abrir = 0;
unsigned long tempo_close = 0;
void setup () {
Serial.begin (9600);
pinMode (led, OUTPUT);
pinMode (sensor, INPUT);
}
void loop () {
if (digitalRead (sensor) == HIGH) {
digitalWrite (led, HIGH);
if (ctrl_abre == 0) {
close_time = millis ();
ctrl_abre = 1;
ctrl_fecha = 0;
Serial.print ( "Door was opened by" );
Serial.print ((closing_time - opening_time) / 1000);
Serial.println ( "seconds" );
}
} else {
digitalWrite (led, LOW);
if (ctrl_fecha == 0) {
open_time = millis ();
ctrl_fecha = 1;
ctrl_abre = 0;
}
}
}

I have declared two variables of the whole type to control whether the port
is open or closed. The variables have obvious names, with the that controls
whether the door is open is the variable ctrl_abre , and the one that controls the
closed door is ctrl_fecha . If ctrl_abre is with zero, the door is closed; if it has a
value of 1, indicates that the door is open.
If the ctrl_fecha variable is zero, the port is
open; if it is 1, it is closed. They work
unlike each other.
I also declared two variables to count the time that the
door stayed open. They are unsigned long variables . THE
open_time variable will store the time the port was opened
open, and the time_close variable will capture the instant when the
door closed.
In the setup () function , in addition to what we've already seen,
I started serial communication with the computer at 9600 baud. At
loop () function , we read the sensor as we did in the previous code and
we control the LED of digital pin 13 in the same way. However,
I added a control structure to know when the door is open
open and closed. To detect the movement of the door, we use the
ctrl_abre and ctrl_fecha variables , as I explained
previously.
Here's how it worked: when the program starts,
it is assumed that the door is closed. So, the digital pin LED
13 lights up and the time_close variable receives the time since the
start of program execution using the millis () function . THE
variable ctrl_abre receives 1, indicating false (that is, the port is not
is open), and ctrl_fecha receives 0, indicating true, since
the door is closed.
The calculation of how long the door was open is on the line
Serial.print ((closing_time - opening_time) / 1000) , which
subtracts from the instant the door closed and the instant
that opened. Everything is divided by 1000, as the measurement is in
milliseconds and we want the result in seconds. The text with the
time is sent to the Serial Monitor.
Pay attention to the millis () function . It returns the time in
millisecond in which the program is running. She bursts
capacity of the variable more or less every 50 days, returning to
the zero. So, for your return, before that happens, we can
count the time without even using an internal or external clock.
Now, when the door is opened, the sensor off, the LED on the
digital pin 13 goes out, and the open_time variable receives the
execution until that moment. The variable ctrl_fecha receives 1 and
ctrl_abre receives 0, indicating that the door is open.
To test, compile and load the program on your Arduino and
open the Serial Monitor. Move the magnet away from the sensor to simulate
opening the door and, after a few seconds, move it closer to
back, simulating the refrigerator door closing.
Figure 8.5: Result of the door opening and closing simulation

Now only three things are missing:


1. Include a buzzer so that an alarm goes off if the door is
open for a long time.
2. Make it possible to store how many times the refrigerator door has been
open since last startup and opening time
maximum. Of course, we will also need a means to
read this information.
3. Install in a real fridge!
Let's go for the buzzer! To save space, we’ll turn on the buzzer
directly to the Arduino. We could put it on the prot-o-board
along with everything else, but we will not let our project
turn a tangle of wires.
Connect the positive terminal of the buzzer to digital pin 11 and the
negative terminal to the Arduino GND.

Figure 8.6: Buzzer connected directly to the Arduino

In the code, I will predict that the maximum time that the
refrigerator may be left open before the buzzer goes off will be 30
seconds. But as you will see, it will be easy to adjust this parameter.

int time = 0;
int max_time = 30;
int led = 13;
int sensor = 2;
int buzzer = 11;
int ctrl_abre = 0;
int ctrl_fecha = 0;
unsigned long tempo_abrir = 0;
unsigned long tempo_close = 0;
void setup () {
Serial.begin (9600);
pinMode (buzzer, OUTPUT);
pinMode (led, OUTPUT);
pinMode (sensor, INPUT);
}
void loop () {
if (digitalRead (sensor) == HIGH) {
digitalWrite (led, HIGH);
if (ctrl_abre == 0) {
close_time = millis ();
ctrl_abre = 1;
ctrl_fecha = 0;
Serial.print ( "Door was opened by" );
Serial.print ((closing_time - opening_time) / 1000);
Serial.println ( "seconds" );
}
} else {
digitalWrite (led, LOW);
time = millis () / 1000;
if (time - (close_time / 1000)> max_time) {
digitalWrite (buzzer, HIGH);
delay (150);
digitalWrite (buzzer, LOW);
delay (150);
}
if (ctrl_fecha == 0) {
open_time = millis ();
ctrl_fecha = 1;
ctrl_abre = 0;
time = 0;
}
}
}
Focusing only on the changes, notice that I have declared two new integer
variables right at the beginning of the program. Are the time variables ,
initialized to zero, which will be used for counting the time until the buzzer
goes off; and tempo_max , initialized to 30, which indicates the maximum time
to be counted, in seconds, until fire the buzzer.
I have also declared a buzzer variable that is initialized with
11, indicating which digital pin on the Arduino the buzzer is connected to.
In the setup () function , I used pinMode (buzzer, OUTPUT) to set the
digital buzzer pin ( 11 ) for output ( OUTPUT ).
In the loop () function , provided that the sensor is open and
returning LOW (after the else ), I use the time variable to
receive the time elapsed to the instant, already in seconds. So the
division by 1000. The line that does this is in time = millis () /
1000 .
With the if selection structure (time - (close_time /
1000)> time_max) , I check if the time elapsed since the
opening of the door is greater than the maximum time determined in the
variable tempo_max . The subtraction time - (close_time /
1000) will return the time elapsed between the recorded time of the
last door closing and the current time in seconds - for
that the division by 1000.
If this condition is true, the buzzer is turned off for 150
milliseconds and then shut down for the same amount of time,
causing an intermittent whistle to occur until the door of the
refrigerator is closed.
We will then save the number of door openings and the
times of these openings. I will use the EEPROM memory of
microcontroller. In the case of ATMEGA328 on Arduino
UNO, we will have 1KiB (kiloByte) available, which is way beyond the
that we therefore need enough.
I'll change the code again:

# include <EEPROM.h>
int time = 0;
int max_time = 30;
int led = 13;
int sensor = 2;
int buzzer = 11;
int ctrl_abre = 0;
int ctrl_fecha = 0;
int counter = -1;
unsigned long tempo_abrir = 0;
unsigned long tempo_close = 0;
void setup () {
Serial.begin (9600);
pinMode (buzzer, OUTPUT);
pinMode (led, OUTPUT);
pinMode (sensor, INPUT);
if (EEPROM.read (0)! = 9) {
EEPROM.write (0.9);
EEPROM.write (1.0);
EEPROM.write (2.0);
}
}
void loop () {
if (digitalRead (sensor) == HIGH) {
digitalWrite (led, HIGH);
if (ctrl_abre == 0) {
close_time = millis ();
ctrl_abre = 1;
ctrl_fecha = 0;
Serial.print ( "Door was opened by" );
Serial.print ((closing_time - opening_time) / 1000);
Serial.println ( "seconds" );
counter ++;
EEPROM.write (1, counter);
if (EEPROM.read (2) <(close_time - open_time) / 1000) {
EEPROM.write (2, round ((closing_time - opening_time) / 1000))
;
}
}
} else {
digitalWrite (led, LOW);
time = millis () / 1000;
if (time - (close_time / 1000)> max_time) {
digitalWrite (buzzer, HIGH);
delay (150);
digitalWrite (buzzer, LOW);
delay (150);
}
if (ctrl_fecha == 0) {
open_time = millis ();
ctrl_fecha = 1;
ctrl_abre = 0;
time = 0;
}
}
if (Serial.available ()> 0) {
char lido = toUpperCase (Serial.read ());
if (read == 'Q' ) {
Serial.println ( "In this cycle the refrigerator door:" );
Serial.print ( "It was opened" );
Serial.print (EEPROM.read (1));
Serial.println ( "times." );
Serial.print ( "It was open for a maximum of" );
Serial.print (EEPROM.read (2));
Serial.println ( "seconds." );
}
if (read == 'R' ) {
Serial.println ( "Values ​reset, new cycle started." );
counter = 0;
EEPROM.write (1.0);
EEPROM.write (2.0);
}
}
}
See that this time the changes were not big either.
I included the line #include <EEPROM.h> right in the first line of the code to
import the EEPROM library, which contains all the methods to facilitate the
use of this memory.
I declared a new variable, of the whole type, with the name of counter ,
initialized to -1 . I gave this value because she is in the same section where
the program goes through where it would detect
closing the door to initialize the time variables in the first time it boots. If
you initialized it to 0, the count would be incorrect, counting a door opening
and closing a
more than the real one.
In the setup () function , I include the if condition (EEPROM.read (0) ! = 9) , which
reads position 0 from the EEPROM memory and checks whether there is the
number 9. The number 9 will be our indicator that this program has been
executed previously and, as such, there is data already
recorded on the EEPROM. If it is not number 9 in position 0 of the
EEPROM, we use the command EEPROM.write (0.9) to put it
over there.
On the next two lines, we use the commands
EEPROM.write (1,0) and EEPROM.write (2,0) , which record the value
zero in positions 1 and 2 of the EEPROM memory. These two positions
will be used to store the number of times the
refrigerator is opened and closed, and what is the maximum time
remained open, respectively.
Most of the changes are in the loop () function . I included
++ counter line to increment each time the door is closed
and then the line EEPROM.write (1, counter) for
store this value in position 1 of the EEPROM memory.
Next, I use the if selection structure (EEPROM.read (2) <
(closing_time - opening_time) / 1000) to check if the
time saved in position 2 of the EEPROM memory is less than
than measured at the door closing. If so, the time
stored in memory needs to be replaced by the current one, since
we are interested in the maximum time the door was open
in the current operating cycle. Otherwise, nothing is changed. The line
to record the time in position 2 of the EEPROM is
EEPROM.write (2, round ((closing_time - opening_time) /
1000)) .
And to be able to see this data recorded on the EEPROM? Enough
open the Serial Monitor and send the letter Q (both capital and
lowercase).
That
it works
thanks
The
verification
if (Serial.available ()> 0) that was placed at the end of
loop () function .
The Serial.available () command returns the amount of
available bytes. So, if there is something sent by the user, he
will execute the command lines within it.
With the line char lido = toUpperCase (Serial.read ()) ,
we created a variable called read of type char , which
will store what is read from the Serial Monitor converted to letter
uppercase. That way, if the user types q (lowercase), or Q
(capital), it will enter the condition, for example.
With if (read == 'Q') , we compare what was read from
Serial monitor with a capital Q. Within this condition,
we show the number of openings and closings of the door of the
refrigerator with the message “In this cycle the door
refrigerator: It was opened ” . Also with the reading of position 1 of the
EEPROM memory made with the command EEPROM.read (1) , “
times ” . Continued with “It was open for a maximum of
“ , With the reading of position 2 of the EEPROM memory made with the
command EEPROM.read (2) , “seconds” .
To test, compile and upload Sketch to your Arduino.
Then, with the Serial Monitor open, open and close the sensor a few
and then send the letter Q or q :
Figure 8.7: The result of accounting for door openings and closings in the Serial Monitor

There is still one last if selection structure (read == 'R') ,


that makes the values ​stored in positions 1 and 2 of the
EEPROM and also the counter variable are reset to zero if you want
start a new refrigerator door check cycle. For what
this happens, just send the letter R or r via Serial Monitor.
Figure 8.8: Resetting the values ​stored in the EEPROM

Now just get a source to plug your Arduino into the outlet
and install the sensor on your refrigerator door. I used a source of
cell phone with 5V 1A and a USB cable with 2 meters to put it in the
place. To read the data, simply disconnect the USB cable from the source
and
put on a computer.
You can see the video of this project installed in a
refrigerator and running at https://youtu.be/KHYyWZxV5lk .
As you may have noticed, I didn't prepare any cases for
no project. So, I think this may be one of the challenges
for this project: find a box that you can stick on
refrigerator, on the furniture or on the wall you have near it.
To put in the box, you will need a prot-o-board
smaller, or build your own printed circuit board. Another
interesting idea is to use a wireless connection to communicate
with Arduino, such as using a Bluetooth module.
In the next project, you can save the paths you take
around town or on trips using a GPS tracker, which
saves your geographical positions on an SD card.

---
Figure 9.2: View of the circuit of a GPS module together with the connector and wires

In the case of the module I'm using, I had to resort to


datasheet to know which pins correspond to which
functionality. To make this very evident, I extended the
connector following the color pattern of the datasheet: red for
5V, black for GND and yellow for serial transmitter (TX).
GPS modules are GPS signal receivers and provide, via
serial communication, the data obtained in the form of lines of text.
Well, let's connect everything and then understand exactly how
geolocation data is read.
Connect the 5V power pin on your GPS to the 5V pin on the
Arduino, the GPS GND pin on one of the Arduino GND pins and
the serial communication pin (TX) to digital pin 2 of the Arduino:

Figure 9.3: GPS module connected to Arduino

Now let's go to the code to read the data that the GPS sends:

# include <SoftwareSerial.h>
SoftwareSerial gps (2,3);
void setup () {
gps.begin (4800);
Serial.begin (9600);
}
void loop () {
char read = 0;
Answer string = "" ;
while ((read = gps.read ())! = 10) {
if (read> 0) {
answer + = read;
}
}
if (! answer.equals ( "" )) {
Serial.println (answer);
}
}

The first thing to do is to import the library


SoftwareSerial , which will allow us to create a serial communication
with any two pins on the Arduino. This is necessary because
we can use digital pins 0 and 1, which are, respectively, RX and
TX native to Arduino. If we do that, we will commit to
ability to see data on the Serial Monitor.
With the SoftwareSerial gps line (2,3) , we indicate that
digital pins 2 and 3 will be used to, respectively, receive
(RX) and transmit (TX) serial data through the virtual serial port,
which will be created and will be called by gps . So we’ll call
the TX (transmitter) pin from the GPS to the RX (receiver) of the serial port
we are creating.
In the setup () function , we use Serial.begin (9600) to
initialize the Arduino physical serial port, on pins 0 (RX) and 1
(TX), with a transfer rate of 9,600bps, as we already did in
almost all other projects. With the gps.begin (4800) line ,
initialize the virtual serial port created on pins 2 (RX) and 3 (TX),
with the transfer rate of 4.800bps, required for this module
GPS.
In the loop () function , I created two variables, being read , that
is of type char and will receive each character sent by GPS; and the
answer , which is of type String and will receive the final string
containing all the geolocation data provided by the GPS. THE
fact is that the GPS sends the data through lines of text, using
as a comma separator and containing all data
geolocation. We will see this in detail shortly.
With the loop while ((read = gps.read ())! =
10) , we make the characters read until the character
ASCII number 10 is found, which is the end of
line. With the if selection (read> 0) , we are only sure that
the character is valid to be stored.
In response + = read , we accumulate the characters for
form the line of text containing all the data in the variable
answer. Finally we use the selection structure
if (! response.equals ("")) to make sure that a
response line was formed (that is, different from empty) and
we show what was read on the Serial Monitor.
To view the data generated by the GPS, load the program at
your Arduino and open the Serial Monitor:
Figure 9.4: The data received by the GPS
Now let's understand all of that.
The lines you see on the Serial Monitor correspond to the
data obtained by satellites. They are shown in NMEA format
(National Marine Electronics Association) that are a set of
specifications of how GPS should be built and how
must present the data.
The NMEA standard says that each line must start with a dollar sign
($), the next 5 characters indicate the origin of the message, being
the first two for the origin (GP for GPS and GL for
GLONASS) and the next three for the message type (GSA,
GSV, RMC and GGA). All fields are separated by commas, and
each type of message has its specific fields, which I will
detail below.
Example line:

$ GPGSA, A, 3,26,21 ,,, 09,17 ,,,,,,, 10.8,02.1,10.6 * 07

Where:
Field
Example
description
1
THE
Operation mode, being:
A - automatic
M - manual
2
3
Correction type, being:
1 - not available
2 - 2D correction
3 - 3D correction
3
26,21 ,,, 09,17 ,,,,,,
Numbers of satellites used, from 1 to 32, maximum 12
by transmission
4
10.8
Dilution of position accuracy from 00.0 to 99.9
5
02.1
Horizontal dilution of position accuracy from 00.0 to
99.9
6
10.6
Vertical dilution of position accuracy from 00.0 to 99.9
7
07
Checksum. Hexadecimal number beginning with *
(asterisk) indicating a logical exclusive OR between
all characters returned between the $ character
(dollar sign) and * (asterisk) of the String.

GSA - General satellite data


Example line:

$ GPGSV, 2,1,08,26,50,016,40,09,50,173,39,21,43,316,38,17,41,144,42 *
7C
Where:
Field
Example
description
1
2
Total number of GSV messages to be transmitted
2
1
Current GSV message number
3
08
Total satellites in sight from 0 to 12
4
26
Satellite number, where:
01 to 32 - GPS
33 to 64 - SBAS
5
50
Satellite elevation from 00 to 99 degrees
6
016
Satellite azimuth from 00 to 359 degrees
7
40
Power from 00 to 99 dB, being null when receiving no data
8
7C
Checksum. Hexadecimal number beginning with * (asterisk) that
indicates a logical exclusive OR among all characters
returned between the $ (dollar sign) and * (asterisk) character of the String.
Example line:

$ GPRMC, 104549.04, A, 2447.2038, N, 12100.4990, E, 016.0,221.0,250304,003


.3, W, A * 22

Where:

Field
Example
description
1
104549.04
Universal time in hhmmss.ss format from 000000.00 to
235959.99
2
THE
Status, being:

GSV - Detailed satellite data


RMC - Minimum data recommended for GPS

A - valid position
V - navigation receiver alert
3
2447,2020
Latitude in ddmm.mmmm format with leading zeros
4
N
Latitudinal hemisphere indicator, N for North and S for South
5
12100.4990
Longitude in ddmm.mmmm format with leading zeros
6
AND
Longitudinal hemisphere indicator, E for East and W for
West
7
016.0
Knot speed from 000.0 to 999.99
8
221.0
Steering in degrees from 000.0 to 359.9
9
250304
Date in ddmmaa format
10
003.3
Magnetic range from 000.0 to 180.00 degrees
11
W
Magnetic variation direction, being:
And to the east
W west
12
THE
Operating mode indicator, being:
N - invalid data
A - self-employed
D - differential
E - estimated
13
22
Checksum. Hexadecimal number beginning with * (asterisk)
which indicates a logical exclusive OR between all characters
returned between the $ (dollar sign) and * (asterisk) character of the
String.
Example line:
$ GPGGA, 104549.04,2447.2038, N, 12100.4990, E, 1,06,01.7,00078.8, M, 0016
.3, M ,, * 5C
Where:

GGA - correction information

Field
Example
description
1
104549.04
Universal time from 000000.00 to 235959.99
2
2447,2020
Latitude in ddmm.mmmm format with leading zeros
3
N
Latitudinal hemisphere indicator, N for North and S for South
4
12100.4990
Longitude in ddmm.mmmm format with leading zeros
5
AND
Longitudinal hemisphere indicator, E for East and W for
West
6
1
Correction indicator for the quality of the position, being:
0 - invalid position
1 - valid position, SPS mode
2 - valid position, differential GPS mode
7
06
Number of satellites in use from 0 to 12
8
01.7
Horizontal dilution of accuracy from 0.0 to 99.9
9
00078.8
Altitude above sea level from -9999.9 to 17999.9
10
0016.3
Geoidal altitude from -999.9 to 9999.9
11
M (ASCII
77)
Time since the last valid transmission in seconds,
null being the case of not using Global Positioning
Differential (DGPS)
12
Differential station identification from 0000 to 1023
13
5C
Checksum. Hexadecimal number beginning with * (asterisk)
which indicates a logical exclusive OR between all characters
returned between the $ (dollar sign) and * (asterisk) character of the
String.

Knowing this, we can change our program to read only


strings of type RMC, which will give us latitude and longitude and other
basic information. We can also read only the strings
valid, that is, with field No. 2 in the letter A.
With the following code, the LED on digital pin 13 will be flashing
until a valid RMC string is read. While they are read
valid strings, the LED will be on constantly:

# include <SoftwareSerial.h>
SoftwareSerial gps (2,3);
int led = 13;
int led_status = LOW;
void setup () {
gps.begin (4800);
Serial.begin (9600);
pinMode (led, OUTPUT);
}
void loop () {
char read = 0;
Answer string = "" ;
while ((read = gps.read ())! = 10) {
if (read> 0) {
answer + = read;
}
}
if (! answer.equals ( "" )) {
if (response.indexOf ( "RMC" )> 0) {
if (response.charAt (17) == 'A' ) {
Serial.println (answer);
led_status = HIGH;
} else {
if (led_status == LOW) {
led_status = HIGH;
} else {
led_status = LOW;
}
}
}
}
digitalWrite (led, led_status);
}

This is an adaptation of the previous code, let's focus


just what has changed. I declared the led variable to indicate in
which digital pin the LED will be on. I also created a variable
called led_status , which will indicate the value sent to the pin
to turn the LED on or off.
In the setup () function , I adjusted the digital LED pin as an output,
using the pinMode line (led, OUTPUT) . The rest has been changed
inside the loop () function , in the selection structure
if (! response.equals ("")) , that is, everything else will only happen
if a row with data is read.
With the if line (response.indexOf ("RMC")> 0) , I use
indexOf (string) method that returns the position where the string
sought was found; otherwise, it returns zero. That is, if
this method returns a value greater than zero, that is to say that
RMC was found in the string.
Then, with the if line (response.charAt (18) == 'A') ,
we check if the character of the 18th position of the answer string is equal to
letter A. The 18th position character is field # 2 of the message
type RMC, which indicates the GPS status, with A indicating that the
issued position is valid.
As the geographic position is valid, we send it to the Monitor
Serial and make the LED ( led_status ) on
all the time. Otherwise the LED will flash, once it has
led_status LOW to delete it, in the next loop led_status will be
HIGH to light it.
Already moving towards recording on the SD card, next
code, we will separate the date, time, latitude, longitude and speed
in variables. In this case, I will use a vector to make things easier.
Soon after, we will connect the SD card module and record the
file with this data on the card.

# include <SoftwareSerial.h>
SoftwareSerial gps (2, 3);
int led = 13;
int led_status = LOW;
String field [13];
void setup () {
gps.begin (4800);
Serial.begin (9600);
pinMode (led, OUTPUT);
}
void loop () {
char read = 0;
Answer string = "" ;
while ((read = gps.read ())! = 10) {
if (read> 0) {
answer + = read;
}
}
if (! response.equals ( "" )) {
if (response.indexOf ( "RMC" )> 0) {
if (response.charAt (17) == 'A' ) {
decodeAnswer (response);
Serial.println (answer);
for ( int i = 0; i <13; i ++) Serial.println (field [i]);
led_status = HIGH;
} else {
if (led_status == LOW) {
led_status = HIGH;
} else {
led_status = LOW;
}
}
}
}
digitalWrite (led, led_status);
}
void decodeAnswer (String r) {
int ant = 0;
int pos = 0;
for ( int i = 0; i <13; i ++) {
pos = r.indexOf ( "," , ant + 1);
field [i] = r.substring (ant, pos);
ant = pos + 1;
}
}

Let's just stick to what was incremented: I created a vector


called a field with 13 positions of type String . Each position
will store a NMEA RMC message field. At the end
of the program I created, a function called decodeResposta , that
receives a String that will be stored in variable r for use
in this function.
The idea is to find the commas, which are the separators of
fields, and save in each position of the vector a clipping of the string
NMEA corresponding to each field. We start with the variable
ant (which indicates the previous comma) with zero, that is, at the beginning
of
string. The pos variable (which indicates the posterior comma) also
starts with zero and will be determined in the for loop .
Since the RMC message has 13 fields, our strength
goes up to 13 (remember that the vector starts at position 0), then
we use for (int i = 0; i <13; i ++) to create this loop.
Next, we use pos = r.indexOf (",", ant + 1) to
determine the position of the posterior comma, which will be the position of
the
occurrence of the first comma after the next position beyond the
previous comma. In field [i] = r.substring (ant, pos) ,
we cut the data from the field, which is between the commas
found.
For the next loop, the position of the previous comma will be the position
of the posterior comma added by a. And so on, 12
times, until all fields are within the field vector.
In the loop () function , I used the function we just created with
decodeAnswer (answer) , then sent it to the Monitor
Serial the string we received from the GPS using the line
Serial.println (answer) . Then with the for (int loop)
i = 1; i <13; i ++) Serial.println (field [i]) , we send each
field separately. That way, we can check if everything is
right.
After sending the program to your Arduino, open the Monitor
Serial and you should see something like the figure:
Figure 9.6: Google Maps showing any position in the middle of the ocean

The URL we formed indicates the Google API address


Maps, and the center variables indicate the geographic position of the
center of the map. size is the pixel size that the map must have
and the zoom index, which in our case is 15.
Now let's convert that latitude and longitude from NMEA to
decimal. For latitude, take the number consisting of the digits
hundredths and add to the number composed of the rest of the
digits divided by 60. See:
NMEA Latitude (GPS) = 2243.8038
Decimal latitude = 22 + (43.8038 / 60) = 22 + 0.7300633 =
22.7300633
For southern latitudinal hemisphere, the value must be negative; case
otherwise, positive.
Final decimal latitude = -22.7300633
Do the same for longitude, but using the digits of the
hundredths to form the first number:
Longitude NMEA (GPS) = 04719.3294
Decimal longitude = 47 + (19.3294 / 60) = 47 + 0.3221566 =
47.3221566
For western longitudinal hemisphere, the value must be negative;
otherwise, positive.
Final Decimal Longitude = -47.3221566
Now replace the latitude and longitude values ​in the URL with
the
what
we are done
in
calculate:
http://maps.googleapis.com/maps/api/staticmap?
center = -22.7, -47.3 & size = 500x500 & zoom = 15 .
Figure 9.7: Map with the correct coordinates, you found me!

Let's translate all of this into code!

# include <SoftwareSerial.h>
SoftwareSerial gps (2, 3);
int led = 13;
int led_status = LOW;
String field [13];
void setup () {
gps.begin (4800);
Serial.begin (9600);
pinMode (led, OUTPUT);
}
void loop () {
char read = 0;
Answer string = "" ;
while ((read = gps.read ())! = 10) {
if (read> 0) {
answer + = read;
}
}
if (! response.equals ( "" )) {
if (response.indexOf ( "RMC" )> 0) {
if (response.charAt (17) == 'A' ) {
decodeAnswer (response);
Serial.println (answer);
Serial.println (FormataHora (field [1]));
Serial.println (formataData (field [9]));
Serial.println (decNMEA (field [3], field [4]), 10);
Serial.println (decNMEA (field [5], field [6]), 10);
Serial.println (speedKM (field [7]));
led_status = HIGH;
} else {
if (led_status == LOW) {
led_status = HIGH;
} else {
led_status = LOW;
}
}
}
}
digitalWrite (led, led_status);
}
void decodeAnswer (String r) {
int ant = 0;
int pos = 0;
for ( int i = 0; i <13; i ++) {
pos = r.indexOf ( "," , ant + 1);
field [i] = r.substring (ant, pos);
ant = pos + 1;
}
}
float velocityKM (String v) {
return v.toFloat () * 1,852;
}
String formataHora (String hr) {
return hr.substring (0, 2) + ":" + hr.substring (2, 4) + ":" + hr.
substring (4, 6);
}
String formataData (String dt) {
return dt.substring (0, 2) + "/" + dt.substring (2, 4) + "/" + dt.
substring (4, 6);
}
double decNMEA (String l, String h) {
int a = int (l.toFloat ()) / 100;
double b = (1.toFloat () - (a * 100)) / 60;
if (h.equals ( "W" ) || h.equals ( "S" )) {
return (a + b) * - 1;
} else {
return a + b;
}
}

In the loop () function , we use the lines:

Serial.println (FormataHora (field [1]));


Serial.println (formataData (field [9]));
Serial.println (decNMEA (field [3], field [4]), 10);
Serial.println (decNMEA (field [5], field [6]), 10);
Serial.println (speedKM (field [7]));

To show the results on the Serial Monitor, we call the


functions that we created at the end of the program. The format function
receives a string and returns the same string, but with a two-
periods ( :) every two characters, so that it is in the format of
hour.
The formatData function is the same as the FormatTime function , or
that is, it receives a string and returns the same string, but with a
slash ( / ) every two characters so that it is in the date format.
The decNMEA function takes two strings. The first is latitude
or longitude, and the second the hemisphere. It performs the conversion
according to the algorithm explained previously, and returns the latitude
or the longitude in decimal ( double ).
The function velocidadeKM takes a string with the speed
in knots obtained with GPS, and converts to a float value in
kilometers per hour.
Figure 9.8: The data converted in the Serial Monitor

Finally, let's go to the SD card module!


You will also need an SD card, of course. He may have the
capacity that you find most convenient, as this will only limit the
amount of data that can be stored. Other than that, no
influences anything else in the project.
Figure 9.10: The SD card module connected to the Arduino

Before we leave recording the GPS data on the card, let's


make a small program to test the module and see how the
recording works:

# include <SD.h>
void setup () {
Serial.begin (9600);
if (! SD.begin (4)) {
Serial.println ( "There was an error initializing the SD module." );
while (1);
}
Serial.println ( "SD module initialized successfully." );
}
void loop () {
String text = "Test recording on SD card" ;
File file = SD.open ( "test.txt" , FILE_WRITE);
if (file) {
file.println (text);
file.close ();
Serial.println ( "Text saved!" );
while (1);
}
}

We will use the SD library already integrated with the Arduino IDE. Per
so, the first thing we do is import it with #include
<SD.h> .
In the setup () function , we start serial communication with
Serial.begin (9600) . Showing data on the Serial Monitor will be
very useful to have a visual feedback of what is being done.
Next, we use a selection structure
if (! SD.begin (4)) . The SD.begin (4) command starts the module
SD card indicating that digital pin 4 is the line selector (CS
- chip select line). It will return true if successful, and false
if not. So, we check with the if and, if the
initialization fails, we send a message to the communication
serial and we use while (1) to interrupt the execution of the
program with an infinite loop. If the initialization has
success, we show a message on the Serial Monitor with
Serial.println ("SD module initialized successfully.") .
In the loop () function , we create a text variable, of type
String , to contain the message "Test recording on
SD card " that will be saved in the file to be created on the SD card.
We created the file variable as of type File . She receives the
pointer that references the file opened with
SD.open ("test.txt", FILE_WRITE) . In it "teste.txt" is the
file name, and FILE_WRITE the opening type, in this case, for
recording.
Keep in mind that files can only have
names in 8.3 format. That is, 8 characters for the name and 3 for the
extension.
The file opening modes are FILE_READ for reading,
and FILE_WRITE for recording. In the case of FILE_WRITE , if the
file already exists, the new content will be placed at the end of it
(append). If the file cannot be opened, the file variable
will receive the logical value FALSE , so we use a
if (file) to verify that the file was opened correctly.
With The archive Open correctly, we use file.println (text) to save the content of
the variable
text in the file. In addition to the println method , which will break
line, it is also possible to use print so that there is no
line break.
Before the file is closed, recording will not take place
physically on the card. Therefore, it is important to remember to use
file.close () . You can always use it at the end, after
send all content. But if you forget it, the data will not be
recorded on the card. The while (1) will create an infinite loop so that
nothing else is sent to the card.
After sending the program to your Arduino, open the Monitor
Serial and you should have a result like the figure below:
Figure 9.11: Messages confirming the message has been saved to the SD card

The two possibilities of error may be that the module is not


functioning, or the file cannot be opened on the card (lack of
card or write protection):
Figure 9.12: Error message due to problems with the module

Well, now that we know everything we need: get the data


and record files to the SD card. So, it's time to join
all!
I will use the latest version of the GPS program and join it with
that recording program on the SD card.

# include <SD.h>
# include <SoftwareSerial.h>
SoftwareSerial gps (2, 3);
int led = 7;
int led_status = LOW;
String field [13];
void setup () {
gps.begin (4800);
Serial.begin (9600);
pinMode (led, OUTPUT);
if (! SD.begin (4)) {
Serial.println ( "There was an error initializing the SD module." );
while (1);
}
}
void loop () {
File file = SD.open ( "log_gps.txt" , FILE_WRITE);
char read = 0;
Answer string = "" ;
while ((read = gps.read ())! = 10) {
if (read> 0) {
answer + = read;
}
}
if (! response.equals ( "" )) {
if (response.indexOf ( "RMC" )> 0) {
if (response.charAt (17) == 'A' ) {
decodeAnswer (response);
Serial.println (answer);
if (file) {
file.print (decNMEA (field [3], field [4]), 10);
file.print ( "," );
file.print (decNMEA (field [5], field [6]), 10);
file.print ( "|" );
file.close ();
Serial.println ( "Text saved!" );
}
led_status = HIGH;
} else {
if (led_status == LOW) {
led_status = HIGH;
} else {
led_status = LOW;
}
}
}
}
digitalWrite (led, led_status);
}
void decodeAnswer (String r) {
int ant = 0;
int pos = 0;
for ( int i = 0; i <13; i ++) {
pos = r.indexOf ( "," , ant + 1);
field [i] = r.substring (ant, pos);
ant = pos + 1;
}
}
float velocityKM (String v) {
return v.toFloat () * 1,852;
}
String formataHora (String hr) {
return hr.substring (0, 2) + ":" + hr.substring (2, 4) + ":" + hr.
substring (4, 6);
}
String formataData (String dt) {
return dt.substring (0, 2) + "/" + dt.substring (2, 4) + "/" + dt.
substring (4, 6);
}
double decNMEA (String l, String h) {
int a = int (l.toFloat ()) / 100;
double b = (1.toFloat () - (a * 100)) / 60;
if (h.equals ( "W" ) || h.equals ( "S" )) {
return (a + b) * - 1;
} else {
return a + b;
}
}

The only changes are: the LED digital pin number, which
I took it out of 13 and put it in 7, since 13 is used for the
SD cards. I did all the initializations to use the card module
SD, including importing the library. Finally, instead of
send the geographic data from the GPS to the Serial Monitor, I am
sending to the SD card.
I am not recording the date, time and speed, as this data
will not be needed to show on the map. But you can
store them without major problems following the same scheme.
I'm also recording latitude and longitude in the ready format
to generate the Google Maps URL, as I showed you earlier.

Figure 9.13: Latitude and longitude recorded in the log_gps.txt file on the SD card.

To display these points on Google Maps, simply assemble the URL gives
Following
form:
http://maps.googleapis.com/maps/api/staticmap?
size = 300x300 & path = content_of_log_gps.txt .
The content_log_log_gps.txt is a copy of the data
the SD card file. If we consider the data in the file
shown in the previous figure, the URL will look like this:
http://maps.googleapis.com/maps/api/staticmap?
size = 300x300 & path = -22.7, -47.3 | -22.7 36, -47.4 | -22.7, -47.5 .
You will see a line on the map indicating the path these
geographical positions indicate:
Figure 9.14: View of the map generated with the previous URL in the internet browser
The only care you need to take is that a URL can be,
maximum 2048 characters. This fact limits the amount of
positions that can be shown. In addition, it is necessary to create a
specific page using the Google Maps API.
Although it is possible to just see the GPS LED flashing,
indicating its operation, a video of this project in
operation can be seen at https://youtu.be/mb2zIKeh-
q0 .
There are so many challenges that you may even think about
something I would never think of, and vice versa. First, you can
put everything in a box that is waterproof, if you are going to
load the tracker on the bike, for example. If you are
car, you can have the Arduino powered on the
12 volt vehicle outlet.
It is possible to go much further by exchanging the SD card for a module
GPRS, and send it directly to the internet, online.
So, start creating your own professional GPS tracker.
You can also put some indicative LEDs to find out if the GPS
is returning valid positions or not, whether the card is inserted or
no, and even if there is any other error or status you want
go along. In order not to record too much data and then fill the card,
you can choose to record only after some time, some
distance or any predetermined change of direction.
In the next project, we will build a toy, because
nobody is iron and we need some fun with the
brothers, sisters or young children. Let's build a potato
hot!
Figure 10.2: A buzzer, which at the top has the indication of the positive pin

In addition to the Arduino and the buzzer, the only things you
you will need will be a support for 9V batteries with plug to connect it
Arduino, and a battery too.
Figure 10.3: The 9V battery plug

To mount the battery holder with the plug, simply solder the wire
positive (red) on the center pin of the plug, as in the figure:
Figure 10.4: Soldering the positive (red) wire on the central pin of the plug and the negative (black) on the
external pin

Remember to leave the cover already on the wires so that it is


affixed to the connector later, that assembled, will be as
in the following figure:
Figure 10.5: Battery clip with the connector mounted

To test that everything is OK, making sure that the positive of the
battery is connected to the center pin of the connector, connect a
battery to the support and the whole set to an Arduino:
Figure 10.6: Set with the battery holder and connector connected to the Arduino!

Assembly will be simple, we will not use extra wires or


anything else. Let's take advantage of the buzzer's own pins
and connect the positive pin of the buzzer to the digital pin 11 of the
Arduino, and the
negative pin from the buzzer to the Arduino GND pin, as in the figure
Following:
Figure 10.7: The buzzer connected directly to the Arduino pins

That way, the project will be compact and can be easily


placed in any casing, as you will see later.
Let's go to the schedule:

int buzzer = 11;


int times = 0;
void setup () {
pinMode (buzzer, OUTPUT);
randomSeed (analogRead (A0));
times = random (10, 100);
for ( int i = 0; i <= times; i ++) {
digitalWrite (buzzer, HIGH);
delay (100);
digitalWrite (buzzer, LOW);
delay (100);
}
digitalWrite (buzzer, HIGH);
delay (1000);
digitalWrite (buzzer, LOW);
}
void loop () {
}

I used two variables of the integer type. One is called a buzzer ,


to store the digital pin to which the buzzer is connected. You
you can change its value if you connect your buzzer to another pin
any. The other, called times , starts with zero and will indicate
the number of times the buzzer will sound.
I put all the code in the setup () function so that, after
each round, it is necessary to press the Arduino reset button.
This makes it possible to control the start and end of each
round of play.
As you’ve noticed, the programming is simple and small, but let's go
to Details same like this.
With The pinMode (buzzer, OUTPUT) , we indicate that the buzzer pin (11)
it will be output, that is, we will put tension on it.
Then I use the command randomSeed (analogRead (A0))
to initialize the seed of pseudo-random numbers from the Arduino.
As we need to pass a number for the function to generate the
numbers, I passed analog pin A0 that is disconnected from
anything. This will result in a noise, increasing the chance
the generated numbers are totally different each time the
program starts running.
In the next line, with times = random (10, 100) , we generate
a random number between 10 and 100 and we store it in the variable
times. This will ensure that the buzzer will sound at least 10 times and at
maximum 100, allowing the potato to be exchanged between those
kidding, but not too short or too long, don't
making people bored.
The repetition structure for will cause the buzzer to be
triggered for 100 milliseconds, generating a short and
acute, and also remaining off for 100 milliseconds.
Thus, each repeat loop will last 200 milliseconds.
After the repetition loops are fulfilled, the buzzer will be
pressed for 1 second and then turned off, indicating the end
of the play round. To start over, just press the button
Arduino reset.
You will find a video of this project in operation
at https://youtu.be/gwo2ChgszKM .
The improvements can be endless, but I leave the challenge to this
project on using their artistic knowledge and building a
wrapper that creates the potato, so that it can be thrown between the
play participants. It will also be a lot of fun if, in
instead of beeps, you can make some melody, maybe some
wheel song that will look much better if you don't use a
buzzer, but a speaker.
You can also join this project to the one where
we built our own Arduino to eliminate the complete board.
This will make electronics more compact and easier to integrate with
wrapper you’ll create.
Now, if you found this project simple and easy, see what comes
next: a robot as easy to build and program as ours
hot potato! That's right, the simplest and easiest spider robot to
build the world without fear of making mistakes. Prepared?
Let's see what this is about!
Like any project, you will need an Arduino Uno:

Figure 11.1: The Arduino UNO

You will also need and two servo motors, which can be
small, as it will not be necessary to carry much weight:
Figure 11.2: Two servo motors

1.2 DEVELOPING THE PROJECT

Servo motors are easy to control using an Arduino,


just use the Servo library that provides all the commands
necessary for this. The Servo library is already integrated with the IDE
Arduino. You can insert it into your project by clicking on the menu
Sketch , selecting the Include Library option and then
by clicking on the Servo option :
Figure 11.3: How to select the Servo library to insert it into your project

A servo motor has 3 wires: two for power and one for

signal. The power cords are usually red for the


+ 5V, and brown for GND. The third, and usually yellow, is
the data wire, ie motor control.
To connect a servo motor to the Arduino, simply connect the wires
described on the correct pins: connect the red wire to a
+ 5V supply, the brown wire on a GND and the yellow wire on the
digital pin 2. It is important to know that the current used by a
servo motor can exceed 1A, that is, be much higher than the
available in Arduino. So never connect more than one servant
engine to your Arduino at the same time. This can damage both the
microcontroller and motors.
We are going to feed our servants through a set of
four batteries, which will result in 6V, within the tolerated by the servos
and also useful for powering the Arduino itself.

Figure 11.4: Support for 4 1.5V batteries totaling 6V

To be able to power the Arduino and the engines, I will use a


plug with terminals. Thus, we will be able to derive the support wires
for batteries for the engines keeping the Arduino on.
Figure 11.5: The terminal plug

So, just connect the battery holder wires and the


wires to power the engines.
Figure 11.6: Battery and wire support for engines

We can now connect the motor control wires to the


Arduino to test them. Connect one of the motors to digital pin 2 and the
another to digital pin 3:
Figure 11.7: Servo motors connected to Arduino

We can now test the operation of the engines with the


following code:

# include <Servo.h>
Servo motor_d;
Servo motor_t;
forward int = 2;
rear int = 3;
int i = 0;
void setup () {
motor_d.attach (front);
motor_t.attach (rear);
}
void loop () {
motor_d.write (i);
motor_t.write (i);
i ++;
if (i> 180) i = 0;
delay (100);
}

In this code, we import the Servo.h library that comes from


many facilities for moving the servo motors. Soon in
We then declare two objects, called motor_d (motor
front) and engine_t (rear engine), as being of the type
Servant .
The integer variables front , which receives 2, and rear ,
receiving 3, indicate the digital pins of the Arduino on which they will be
servo motors are connected. This makes it easier if you want, for a reason
any, change the pin motors.
The entire variable i , which receives 0, will serve as a counter for
we pass the angles to the engines at which we want to position them.
At
occupation
setup ()
,
we use the commands motor_d.attach (front) and motor_t.attach (rear)
to indicate which pin each servo motor is connected to. That
command assigns the digital pin to the object that was assigned to the
servant.
In the loop () function , we use motor_d.write (i) and motor_t.write (i) to send (write)
to the servo motor the angle at which we want to position them. Since
variable i has the initial value zero, after the execution of these lines, the
motors will be positioned at 0 °. This will be abrupt and should make a loud
noise characteristic.
Continuing, we increment a variable i with i ++ . In Then, we check if the
value of this variable is greater than 180 with if (i> 180) . Note that the
maximum angle of a servo motor
is 180 °. If this value is reached, we will return variable i to
zero, its initial value.
The delay (100) is just so that everything doesn't happen too much
fast and you can notice the gradual changes in angle.
As I mentioned, the engine will be positioned at all angles
between 0 ° and 180 ° gradually every 100 milliseconds. But later
reaching the maximum value, it will return to the starting position at once
at 0 °.
Already thinking about the movement of the legs, it would be better if this
back was also gradual. Let's change the previous code:

# include <Servo.h>
Servo motor_d;
Servo motor_t;
forward int = 2;
rear int = 3;
int i = 0;
int meaning = 0;
void setup () {
motor_d.attach (front);
motor_t.attach (rear);
}
void loop () {
motor_d.write (i);
motor_t.write (i);
if (sense == 0) i ++; else i--;
if (i> 180) sense = 1;
if (i <0) sense = 0;
delay (100);
}

We created only the entire variable called sense and


we initialize it with 0. It will indicate in which direction the servo motor
must be moved. It defines that, when it is 0, the angles
will increase, and when it was 1, the angles will decrease.
the objects for the engines, and we determine variables for
represent which digital pins the motors are on. In the function
setup () , we attach the motors to their pins, and use
motor_d.write (90) and motor_t.write (90) to position the
90 ° motors.
All this done, it's time to build your legs! Youre gonna need it of two clips #
10.
Using clips makes everything simpler, as we won't need
run after a piece of wire or iron. It also doesn't have to be
necessarily clips # 10. You can do with smaller clips,
that will make your legs shorter, or with clips
bigger, which will make the legs get longer. Do it
adaptation he deems necessary.

Figure 11.8: Two clips # 10

Open the clips so they are as straight as possible.


Figure 11.9: The open clip

Take the round head of your servo motor and place the clips
over it, so that it is in the middle of the clips.
Figure 11.10: The head in the middle of the clips

Fold the clips and make a point, as in the following figure:


Figure 11.11: Clips folded over the head

You should now attach the clips to the head, which will create the
our legs. You can use tape, glue or, like me, a
small thin copper wire to tie everything.
Figure 11.12: Clips, head and wire to tie everything

Figure 11.13: The first assembled leg

Then repeat again to create a second leg.


Figure 11.14: The two legs assembled

These will be our front legs, which will be placed on what


will be the front and rear engine, placed on what will be the engine
rear.
Figure 11.15: Legs installed on the engines
So let's assemble the body! Using double-sided tape or glue,
we will attach the motors below the Arduino:
Figure 11.16: Motors with double-sided tapes

Figure 11.17: Engines stuck under the Arduino

Time to put your legs on the engines:


Figure 11.18: Legs installed

Now, adjusting your legs so that they are balanced,


put your spider robot on its feet. Remember to screw the head
to the engine so that everything stays assembled when
moving.
The code for the robot to start walking is as follows:

# include <Servo.h>
Servo motor_d;
Servo motor_t;
forward int = 2;
rear int = 3;
int i = 45, j = 90;
int meaning = 0;
void setup () {
motor_d.attach (front);
motor_t.attach (rear);
}
void loop () {
motor_d.write (i);
motor_t.write (j);
if (sense == 0) {
i ++;
j--;
} else {
i--;
j ++;
}
if (i> 90) sense = 1;
if (i <45) sense = 0;
delay (50);
}
Figure 11.19: All standing

You will find a video of this project in operation


at https://youtu.be/q8gRwHqC6No .
He's a little clumsy, right ?! But worth it as a good
study of leg movements for a more elaborate and
complete.
Good challenges for this project are to increase it to make it
more attractive and practical. To start, I think you need to leave it
less clumsy and with more agile and fast movements.
You can also create your own Arduino, to let everything
small so that it can be placed next to the servo motors
inside a small box. Remember the battery, which is
practically the heaviest of the entire project, which should be
also somewhere. The legs may need to be
redesigned to support her weight.
Finally, I think that including two LEDs to create eyes too
will make our little insect more fun, even more in places
dark. Although these LEDs can light up only when the
environment is dark. This will be easy to do using a
luminosity.
With this project, we have reached the end of this book. But not at the end
of the possibilities that the Arduino, when coupled with components
electronics, sensors and a good dose of imagination, in
provide. Move on!
Use these projects as a starting point for others. Create the
yours from just one idea, but don't stop, stay in
movement always.

You might also like