Peterson, Kathleen - Arduino Projects - The Ultimate Guide For Making The Best of Your Arduino Programming Projects, 1st Edition (2020)
Peterson, Kathleen - Arduino Projects - The Ultimate Guide For Making The Best of Your Arduino Programming Projects, 1st Edition (2020)
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.
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
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.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.
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.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:
# 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
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!
# 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);
}
# 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;
}
# 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).
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.
# 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);
}
}
# 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 ();
}
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
# 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 ();
}
}
# 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:
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
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.
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
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
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
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
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);
}
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);
}
}
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);
}
}
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
# 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 () {
}
# 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 ++;
}
}
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:
# 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 ();
}
}
}
}
. 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
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
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
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
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
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);
}
}
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.
$ 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:
Where:
Field
Example
description
1
104549.04
Universal time in hhmmss.ss format from 000000.00 to
235959.99
2
THE
Status, being:
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:
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.
# 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);
}
# 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;
}
}
# 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;
}
}
# 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
# 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
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!
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
A servo motor has 3 wires: two for power and one for
# 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);
}
# 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);
}
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
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
# 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