0% found this document useful (0 votes)
4 views316 pages

Tutorial C Code

The document provides an introduction to Freenove products, specifically focusing on the Raspberry Pi and its associated tutorial files for various programming languages. It includes safety precautions, support information, and a detailed contents list for the tutorial, which covers numerous projects and components related to Raspberry Pi. Additionally, it emphasizes the importance of following instructions for safe usage and offers free technical support for users.

Uploaded by

Carlo Sicbaldi
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views316 pages

Tutorial C Code

The document provides an introduction to Freenove products, specifically focusing on the Raspberry Pi and its associated tutorial files for various programming languages. It includes safety precautions, support information, and a detailed contents list for the tutorial, which covers numerous projects and components related to Raspberry Pi. Additionally, it emphasizes the importance of following instructions for safe usage and offers free technical support for users.

Uploaded by

Carlo Sicbaldi
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

█ [Link]  support@freenove.

com I

Getting Started

Thank you for choosing Freenove products!


After you download the ZIP file we provide. Unzip it and you will get a folder contains several files and folders.
There are three PDF files:

⚫ [Link]
It contains basic operations such as installing system for Raspberry Pi.
The code in this PDF is in C.
⚫ Tutorial_GPIOZero.pdf
It contains basic operations such as installing system for Raspberry Pi.
The code in this PDF is in Python.
⚫ [Link] in Freenove_Complete_Starter_Kit_for_Raspberry_Pi\Processing
The code in this PDF is in Java.
⚫ [Link] in Freenove_Complete_Starter_Kit_for_Raspberry_Pi\Pi4j
The code in this PDF is in Java.

We recommend you to start with [Link] or Tutorial_GPIOZero.pdf first.


If you want to start with [Link] or skip some chapters of [Link], you need to finish necessary
steps in Chapter 7 AD/DA of [Link] first.

Remove the Chips

Some chips and modules are inserted into the breadboard to protect their pins.
You need to remove them from breadboard before use. (There is no need to remove GPIO Extension Board.)
Please find a tool (like a little screw driver) to handle them like below:

Step 1, lift one end slightly.

support@[Link] █
II  support@[Link] [Link] █

Step 2, lift another end slightly.

Step 3, take off the chip with hand.

Avoid lifting one end with big angle directly.

█ support@[Link]
█ [Link]  support@[Link] III

Get Support and Offer Input

Freenove provides free and responsive product and technical support, including but not limited to:
⚫ Product quality issues
⚫ Product use and build issues
⚫ Questions regarding the technology employed in our products for learning and education
⚫ Your input and opinions are always welcome
⚫ We also encourage your ideas and suggestions for new products and product improvements
For any of the above, you may send us an email to:

support@[Link]
Safety and Precautions

Please follow the following safety precautions when using or storing this product:
⚫ Keep this product out of the reach of children under 6 years old.
⚫ This product should be used only when there is adult supervision present as young children lack
necessary judgment regarding safety and the consequences of product misuse.
⚫ This product contains small parts and parts, which are sharp. This product contains electrically conductive
parts. Use caution with electrically conductive parts near or around power supplies, batteries and
powered (live) circuits.
⚫ When the product is turned ON, activated or tested, some parts will move or rotate. To avoid injuries to
hands and fingers, keep them away from any moving parts!
⚫ It is possible that an improperly connected or shorted circuit may cause overheating. Should this happen,
immediately disconnect the power supply or remove the batteries and do not touch anything until it
cools down! When everything is safe and cool, review the product tutorial to identify the cause.
⚫ Only operate the product in accordance with the instructions and guidelines of this tutorial, otherwise
parts may be damaged or you could be injured.
⚫ Store the product in a cool dry place and avoid exposing the product to direct sunlight.
⚫ After use, always turn the power OFF and remove or unplug the batteries before storing.

About Freenove

Freenove provides open source electronic products and services worldwide.

Freenove is committed to assist customers in their education of robotics, programming and electronic circuits
so that they may transform their creative ideas into prototypes and new and innovative products. To this end,
our services include but are not limited to:

⚫ Educational and Entertaining Project Kits for Robots, Smart Cars and Drones
⚫ Educational Kits to Learn Robotic Software Systems for Arduino, Raspberry Pi and micro: bit

support@[Link] █
IV  support@[Link] [Link] █

⚫ Electronic Component Assortments, Electronic Modules and Specialized Tools


⚫ Product Development and Customization Services
You can find more about Freenove and get our latest news and updates through our website:
[Link]

Copyright

All the files, materials and instructional guides provided are released under Creative Commons Attribution-
NonCommercial-ShareAlike 3.0 Unported License. A copy of this license can be found in the folder containing
the Tutorial and software files associated with this product.

This means you can use these resource in your own derived works, in part or completely, but NOT for the
intent or purpose of commercial use.

Freenove brand and logo are copyright of Freenove Creative Technology Co., Ltd. and cannot be used without
written permission.

R

Raspberry Pi® is a trademark of Raspberry Pi Foundation ([Link]

█ support@[Link]
█ [Link]  support@[Link] V

Contents
Getting Started ......................................................................................................................................................... I
Remove the Chips .................................................................................................................................................... I
Safety and Precautions ........................................................................................................................................................... III
About Freenove ........................................................................................................................................................................ III
Copyright .................................................................................................................................................................................... IV
Contents .................................................................................................................................................................... V
Preface ....................................................................................................................................................................... 1
Raspberry Pi ............................................................................................................................................................. 2
Chapter 0 Preparation ........................................................................................................................................... 9
Linux Command ........................................................................................................................................................................ 9
Install WiringPi ......................................................................................................................................................................... 12
Obtain the Project Code ....................................................................................................................................................... 14
Chapter 1 LED ........................................................................................................................................................ 16
Project 1.1 Blink ....................................................................................................................................................................... 16
Freenove Car, Robot and other products for Raspberry Pi ...................................................................................... 32
Chapter 2 Buttons & LEDs .................................................................................................................................. 33
Project 2.1 Push Button Switch & LED ............................................................................................................................. 33
Project 2.2 MINI Table Lamp ............................................................................................................................................... 38
Chapter 3 LED Bar Graph .................................................................................................................................... 42
Project 3.1 Flowing Water Light ......................................................................................................................................... 42
Chapter 4 Analog & PWM .................................................................................................................................. 46
Project 4.1 Breathing LED ..................................................................................................................................................... 46
Chapter 5 RGB LED ............................................................................................................................................... 51
Project 5.1 Multicolored LED ............................................................................................................................................... 52
Chapter 6 Buzzer ................................................................................................................................................... 56
Project 6.1 Doorbell ............................................................................................................................................................... 56
Project 6.2 Alertor ................................................................................................................................................................... 61
(Important) Chapter 7 ADC ................................................................................................................................ 64
Project 7.1 Read the Voltage of Potentiometer............................................................................................................ 64
Chapter 8 Potentiometer & LED ....................................................................................................................... 76
Project 8.1 Soft Light.............................................................................................................................................................. 76
Chapter 9 Potentiometer & RGBLED ............................................................................................................... 81
Project 9.1 Colorful Light ...................................................................................................................................................... 81
Chapter 10 Photoresistor & LED ....................................................................................................................... 86
Project 10.1 NightLamp ........................................................................................................................................................ 86
Chapter 11 Thermistor......................................................................................................................................... 92
Project 11.1 Thermometer ................................................................................................................................................... 92
Chapter 12 Joystick .............................................................................................................................................. 98
Project 12.1 Joystick ............................................................................................................................................................... 98
Chapter 13 Motor & Driver ............................................................................................................................. 104
Project 13.1 Control a DC Motor with a Potentiometer ......................................................................................... 104

support@[Link] █
VI  support@[Link] [Link] █

Chapter 14 Relay & Motor .............................................................................................................................. 116


Project 14.1.1 Relay & Motor ........................................................................................................................................... 116
Chapter 15 Servo................................................................................................................................................ 122
Project 15.1 Servo Sweep .................................................................................................................................................. 122
Chapter 16 Stepper Motor .............................................................................................................................. 128
Project 16.1 Stepper Motor .............................................................................................................................................. 128
Chapter 17 74HC595 & Bar Graph LED ........................................................................................................ 136
Project 17.1 Flowing Water Light.................................................................................................................................... 136
Chapter 18 74HC595 & 7-Segment Display ............................................................................................... 142
Project 18.1 7-Segment Display ..................................................................................................................................... 142
Project 18.2 4-Digit 7-Segment Display ...................................................................................................................... 147
Chapter 19 74HC595 & LED Matrix............................................................................................................... 156
Project 19.1 LED Matrix ...................................................................................................................................................... 156
Chapter 20 LCD1602 ......................................................................................................................................... 165
Project 20.1 I2C LCD1602.................................................................................................................................................. 165
Chapter 21 Hygrothermograph DHT11 ....................................................................................................... 173
Project 21.1 Hygrothermograph ..................................................................................................................................... 173
Chapter 22 Matrix Keypad ............................................................................................................................... 178
Project 22.1 Matrix Keypad ............................................................................................................................................... 178
Chapter 23 Infrared Motion Sensor .............................................................................................................. 185
Project 23.1 PIR Infrared Motion Detector with LED Indicator ............................................................................. 185
Chapter 24 Ultrasonic Ranging ...................................................................................................................... 191
Project 24.1 Ultrasonic Ranging ...................................................................................................................................... 191
Chapter 25 Attitude Sensor MPU6050 ......................................................................................................... 197
Project 25.1 Read a MPU6050 Sensor Module .......................................................................................................... 197
Chapter 26 High-sensitivity microphone sensor ....................................................................................... 203
Project 26.1 High-sensitivity microphone sensor and LED.................................................................................... 203
Chapter 27 Touch Sensor TTP223.................................................................................................................. 207
Project 27.1 Touch Sensor and LED ............................................................................................................................... 207
Project 27.2 Touch Sensor and RGB LED ..................................................................................................................... 212
Chapter 28 U-shaped photoelectric sensor ............................................................................................. 217
Project 28.1 U-shaped photoelectric sensor and LED ............................................................................................ 217
Project 28.2 U-shaped photoelectric sensor and buzzer ....................................................................................... 221
Chapter 29 Hall sensor ..................................................................................................................................... 225
Project 29.1 Hall sensor and LED .................................................................................................................................... 225
Project 29.2 Hall Sensor and Buzzer.............................................................................................................................. 229
Chapter 30 Infrared Obstacle Avoidance Sensor ....................................................................................... 233
Project 30.1 Infrared obstacle avoidance sensor and LED ..................................................................................... 233
Project 30.2 Infrared obstacle avoidance sensor and buzzer ............................................................................... 237
Chapter 31 Rotary Encoder ............................................................................................................................. 241
Project 31.1 Rotary Encoder ............................................................................................................................................. 241
Project 31.2 Rotary Encoder and LED ........................................................................................................................... 248
Chapter 32 LEDpixel .......................................................................................................................................... 254
Project 32.1 LEDpixel .......................................................................................................................................................... 254

█ support@[Link]
█ [Link]  support@[Link] VII

Project 32.2 RainbowLight ................................................................................................................................................ 260


Project 32.3 SpiLEDpixel .................................................................................................................................................... 264
Chapter 33 BMP180 Barometric Pressure Sensor...................................................................................... 273
Project 33.1 Barometer ...................................................................................................................................................... 273
Chapter 34 RFID ................................................................................................................................................. 283
Project 34.1 RFID .................................................................................................................................................................. 283
Chapter 35 Soldering a Circuit Board ........................................................................................................... 296
Project 35.1 Soldering a Buzzer ...................................................................................................................................... 296
Project 35.2 Soldering a Flowing Water Light ............................................................................................................ 300
Other Components ............................................................................................................................................ 306
What's Next? ....................................................................................................................................................... 308

support@[Link] █
█ [Link]  support@[Link] 1

Preface
Raspberry Pi is a low cost, credit card sized computer that plugs into a computer monitor or TV, and uses a
standard keyboard and mouse. It is an incredibly capable little device that enables people of all ages to explore
computing, and to learn how to program in a variety of computer languages like Scratch and Python. It is
capable of doing everything you would expect from a desktop computer, such as browsing the internet,
playing high-definition video content, creating spreadsheets, performing word-processing, and playing video
games. For more information, you can refer to Raspberry Pi official website. For clarification, this tutorial will
also reference Raspberry Pi as RPi, RPI and RasPi.

In this tutorial, most chapters consist of Components List, Component Knowledge, Circuit, and Code. We
provide C code for each project in this tutorial. After completing this tutorial, you can learn Java by reading
[Link].

This kit does not contain Raspberry and its accessories. You can also use the components and modules in
this kit to create projects of your own design.

Additionally, if you encounter any issues or have questions about this tutorial or the contents of kit, you can
always contact us for free technical support at:

support@[Link]

support@[Link] █
2  support@[Link] [Link] █

Raspberry Pi
So far, at this writing, Raspberry Pi has advanced to its fifth generation product offering. Version changes are
accompanied by increases in upgrades in hardware and capabilities.

The A type and B type versions of the first generation products have been discontinued due to various reasons.
What is most important is that other popular and currently available versions are consistent in the order and
number of pins and their assigned designation of function, making compatibility of peripheral devices greatly
enhanced between versions.

Below are the raspberry pi pictures and model pictures supported by this product. They have 40 pins.
Practicality picture of Raspberry Pi 5: Model diagram of Raspberry Pi 5:

█ support@[Link]
█ [Link]  support@[Link] 3

Actual image of Raspberry Pi 4 Model B: CAD image of Raspberry Pi 4 Model B:

Actual image of Raspberry Pi 3 Model B+: CAD image of Raspberry Pi 3 Model B+:

support@[Link] █
4  support@[Link] [Link] █

Actual image of Raspberry Pi 3 Model B: CAD image of Raspberry Pi 3 Model B:

Actual image of Raspberry Pi 2 Model B: CAD image of Raspberry Pi 2 Model B:

█ support@[Link]
█ [Link]  support@[Link] 5

Actual image of Raspberry Pi 1 Model B+: CAD image of Raspberry Pi 1 Model B+:

Actual image of Raspberry Pi 3 Model A+: CAD image of Raspberry Pi 3 Model A+:

support@[Link] █
6  support@[Link] [Link] █

Actual image of Raspberry Pi 1 Model A+: CAD image of Raspberry Pi 1 Model A+:

Actual image of Raspberry Pi Zero W: CAD image of Raspberry Pi Zero W:

Actual image of Raspberry Pi Zero: CAD image of Raspberry Pi Zero:

█ support@[Link]
█ [Link]  support@[Link] 7

Below are the raspberry pi pictures and model pictures supported by this product. They have 40 pins.
Hardware interface diagram of RPi 5 is shown below:

GPIO
Connector

USB
PCl Express Connector x4
interfance

On/Off button
Ethernet
Power Connector
Connector

MINI HDMI Camera Display


Connector x2 Connector Connector

Hardware interface diagram of RPi 4B is shown below:

GPIO
Connector Ethernet
Connector

Display
Connector

USB
Power Connector x4
Connector

Micro HDMI Camera Audio


Connector x2 Connector Connector

support@[Link] █
8  support@[Link] [Link] █

Hardware interface diagram of RPi 3B+/3B/2B/1B+:

GPIO
Connector
USB
Connector
Display
Connector

Ethernet
Power Connector
Connector

HDMI Camera Audio


Connector Connector Connector

Hardware interface diagram of RPi 3A+/A+:

GPIO
Connector

USB
Display Connector
Connector

Power
Connector

HDMI Camera Audio


Connector Connector Connector

Hardware interface diagram of RPi Zero/Zero W:

GPIO
Connector

Camera
Connector

HDMI USB Power


Connector Connector Connector

█ support@[Link]
█ [Link]  support@[Link] 9

Chapter 0 Preparation
Why “Chapter 0”? Because in program code the first number is 0. We choose to follow this rule. In this chapter,
we will do some necessary foundational preparation work: Start your Raspberry Pi and install some necessary
libraries.
If you haven't installed the system for Raspberry Pi yet, please refer to:
Freenove_Complete_Starter_Kit_for_Raspberry_Pi/Installing Raspberry Pi [Link]

Linux Command

Raspberry Pi OS is based on the Linux Operation System. Now we will introduce you to some frequently used
Linux commands and rules.
First, open the Terminal. All commands are executed in Terminal.

Terminal

Menu Browser File


manager

When you click the Terminal icon, following interface appears.

support@[Link] █
10  support@[Link] [Link] █

Note: The Linux is case sensitive.


First, type “ls” into the Terminal and press the “Enter” key. The result is shown below:

The ”ls” command lists information about the files (the current directory by default).

Content between “$” and ”pi@raspberrypi:” is the current working path. “~” represents the user directory,
which refers to “/home/pi” here.

“cd” is used to change directory. “/” represents the root directory.

Later in this Tutorial, we will often change the working path. Typing commands under the wrong directory
may cause errors and break the execution of further commands.

Many frequently used commands and instructions can be found in the following reference table.
Command instruction
ls Lists information about the FILEs (the current directory by default) and entries
alphabetically.
cd Changes directory
sudo + cmd Executes cmd under root authority
./ Under current directory
gcc GNU Compiler Collection
git clone URL Use git tool to clone the contents of specified repository, and URL in the repository address.
There are many commands, which will come later. For more details about commands. You can refer to:
[Link]

█ support@[Link]
█ [Link]  support@[Link] 11

Shortcut Key

Now, we will introduce several commonly used shortcuts that are very useful in Terminal.

1. Up and Down Arrow Keys: Pressing “↑” (the Up key) will go backwards through the command history and
pressing “↓” (the Down Key) will go forwards through the command history.

2. Tab Key: The Tab key can automatically complete the command/path you want to type. When there is only
one eligible option, the command/path will be completely typed as soon as you press the Tab key even you
only type one character of the command/path.

As shown below, under the '~' directory, you enter the Documents directory with the “cd” command. After
typing “cd D”, pressing the Tab key (there is no response), pressing the Tab key again then all the files/folders
that begin with “D” will be listed. Continue to type the letters "oc" and then pressing the Tab key, the
“Documents” is typed automatically.

support@[Link] █
12  support@[Link] [Link] █

Install WiringPi

WiringPi is a GPIO access library written in C language for the used in the Raspberry Pi.

WiringPi Installation Steps

To install the WiringPi library, please open the Terminal and then follow the steps and commands below.
Note: For a command containing many lines, execute them one line at a time.
Enter the following commands one by one in the terminal to install WiringPi:
sudo apt-get update
git clone [Link]
cd WiringPi
./build

The following figure shows the successful installation.

█ support@[Link]
█ [Link]  support@[Link] 13

Run the gpio command to check the installation:


gpio -v
That should give you some confidence that the installation was a success.

support@[Link] █
14  support@[Link] [Link] █

Obtain the Project Code

After the above installation is completed, you can visit our official website ([Link] or our
GitHub resources at ([Link] to download the latest available project code. We provide
both C language and Python language code for each project to allow ease of use for those who are skilled
in either language.

This is the method for obtaining the code:


In the pi directory of the RPi terminal, enter the following command.
cd
git clone --depth 1 [Link]
(There is no need for a password. If you get some errors, please check your commands.)

After the download is completed, a new folder "Freenove_Complete_Starter_Kit_for_Raspberry_Pi" is


generated, which contains all of the tutorials and required code.
This folder name seems a little too long. We can simply rename it by using the following command.
mv Freenove_Complete_Starter_Kit_for_Raspberry_Pi/ Freenove_Kit/

█ support@[Link]
█ [Link]  support@[Link] 15

"Freenove_Kit" is now the new and much shorter folder name.

support@[Link] █
16  support@[Link] [Link] █

Chapter 1 LED
This chapter is the Start Point in the journey to build and explore RPi electronic projects. We will start with
simple “Blink” project.

Project 1.1 Blink

In this project, we will use RPi to control blinking a common LED.

Component List

Raspberry Pi GPIO Extension Board & Ribbon Cable


(Recommended: Raspberry Pi 5 / 4B / 3B+ / 3B
Compatible: 3A+ / 2B / 1B+ / 1A+ / Zero W / Zero)

Breadboard x1

█ support@[Link]
█ [Link]  support@[Link] 17

LED x1 Resistor 220Ω x1 Jumper


Specific quantity depends on the circuit.

In the components list, 3B GPIO, Extension Shield Raspberry and Breadboard are necessary for each project.
Later, they will be reference by text only (no images as in above).

GPIO

GPIO: General Purpose Input/Output. Here we will introduce the specific function of the pins on the Raspberry
Pi and how you can utilize them in all sorts of ways in your projects. Most RPi Module pins can be used as
either an input or output, depending on your program and its functions.
When programming GPIO pins there are 3 different ways to reference them: GPIO Numbering, Physical
Numbering and WiringPi GPIO Numbering.

BCM GPIO Numbering


The Raspberry Pi CPU uses Broadcom (BCM) processing chips BCM2835, BCM2836 or BCM2837. GPIO pin
numbers are assigned by the processing chip manufacturer and are how the computer recognizes each pin.
The pin numbers themselves do not make sense or have meaning as they are only a form of identification.
Since their numeric values and physical locations have no specific order, there is no way to remember them
so you will need to have a printed reference or a reference board that fits over the pins.
Each pin’s functional assignment is defined in the image below:

For more details about pin definition of GPIO, please refer to [Link]

support@[Link] █
18  support@[Link] [Link] █

PHYSICAL Numbering
Another way to refer to the pins is by simply counting across and down from pin 1 at the top left (nearest to
the SD card). This is 'Physical Numbering', as shown below:

WiringPi GPIO Numbering


Different from the previous two types of GPIO serial numbers, RPi GPIO serial number of the WiringPi are
numbered according to the BCM chip use in RPi.

(For more details, please refer to [Link] )

█ support@[Link]
█ [Link]  support@[Link] 19

You can also use the following command to view their correlation.
gpio readall

support@[Link] █
20  support@[Link] [Link] █

Circuit

First, disconnect your RPi from the GPIO Extension Shield. Then build the circuit according to the circuit and
hardware diagrams. After the circuit is built and verified correct, connect the RPi to GPIO Extension Shield.
CAUTION: Avoid any possible short circuits (especially connecting 5V or GND, 3.3V and GND)!
WARNING: A short circuit can cause high current in your circuit, create excessive component heat and cause
permanent damage to your RPi!
Schematic diagram
PHYSICAL GPIO Numbering
BCM GPIO Numbering
The code uses this one.

Hardware connection. If you need any support, please contact us via: support@[Link]

Longer Pin

Note:
Do NOT rotate Raspberry Pi to change the way of this connection.
Please plug T extension fully into breadboard.

Youtube video [Link]


The connection of Raspberry Pi T extension board is as below. Don’t reverse the ribbon.

█ support@[Link]
█ [Link]  support@[Link] 21

If you have a fan, you can connect it to 5V GND of breadboard via jumper wires.
How to distinguish resistors?

There are only three kind of resistors in this kit.

The one with 1 red ring is 10KΩ

The one with 2 red rings is 220Ω

The one with 0 red ring is 1KΩ

Future hardware connection diagrams will only show that part of breadboard and GPIO Extension Shield.

support@[Link] █
22  support@[Link] [Link] █

Component knowledge

LED
An LED is a type of diode. All diodes only work if current is flowing in the correct direction and have two Poles.
An LED will only work (light up) if the longer pin (+) of LED is connected to the positive output from a power
source and the shorter pin is connected to the negative (-) output, which is also referred to as Ground (GND).
This type of component is known as “Polar” (think One-Way Street).
All common 2 lead diodes are the same in this respect. Diodes work only if the voltage of its positive electrode
is higher than its negative electrode and there is a narrow range of operating voltage for most all common
diodes of 1.9 and 3.4V. If you use much more than 3.3V the LED will be damaged and burnt out.

Note: LEDs cannot be directly connected to a power supply, which usually ends in a damaged component. A
resistor with a specified resistance value must be connected in series to the LED you plan to use.
Resistor
Resistors use Ohms (Ω) as the unit of measurement of their resistance (R). 1MΩ=1000kΩ, 1kΩ=1000Ω.
A resistor is a passive electrical component that limits or regulates the flow of current in an electronic circuit.
On the left, we see a physical representation of a resistor, and the right is the symbol used to represent the
presence of a resistor in a circuit diagram or schematic.

The bands of color on a resistor is a shorthand code used to identify its resistance value. For more details of
resistor color codes, please refer to the card in the kit package.
With a fixed voltage, there will be less current output with greater resistance added to the circuit. The
relationship between Current, Voltage and Resistance can be expressed by this formula: I=V/R known as
Ohm’s Law where I = Current, V = Voltage and R = Resistance. Knowing the values of any two of these allows
you to solve the value of the third.
In the following diagram, the current through R1 is: I=U/R=5V/10kΩ=0.0005A=0.5mA.

█ support@[Link]
█ [Link]  support@[Link] 23

WARNING: Never connect the two poles of a power supply with anything of low resistance value (i.e. a
metal object or bare wire) this is a Short and results in high current that may damage the power supply and
electronic components.
Note: Unlike LEDs and Diodes, Resistors have no poles and re non-polar (it does not matter which direction
you insert them into a circuit, it will work the same)
Breadboard
Here we have a small breadboard as an example of how the rows of holes (sockets) are electrically attached.
The left picture shows the ways the pins have shared electrical connection and the right picture shows the
actual internal metal, which connect these rows electrically.

GPIO Extension Board


GPIO board is a convenient way to connect the RPi I/O ports to the breadboard directly. The GPIO pin
sequence on Extension Board is identical to the GPIO pin sequence of RPi.

support@[Link] █
24  support@[Link] [Link] █

Code

According to the circuit, when the GPIO17 of RPi output level is high, the LED turns ON. Conversely, when the
GPIO17 RPi output level is low, the LED turns OFF. Therefore, we can let GPIO17 cycle output high and output
low level to make the LED blink. We will use both C code to achieve the target.

C Code 1.1.1 Blink


First, enter this command into the Terminal one line at a time. Then observe the results it brings on your
project, and learn about the code in detail.
If you want to execute it with editor, please refer to section Code Editor to configure.
If you have any concerns, please contact us via: support@[Link]
It is recommended that to execute the code via command line.
1. If you did not update wiring pi, please execute following commands one by one.
sudo apt-get update
git clone [Link]
cd WiringPi
./build
2. Use cd command to enter 01.1.1_Blink directory of C code.
cd ~/Freenove_Kit/Code/C_Code/01.1.1_Blink
3. Use the following command to compile the code “Blink.c” and generate executable file “Blink”.
“l” of “lwiringPi” is low case of “L”.
gcc Blink.c -o Blink -lwiringPi
4. Then run the generated file “blink”.
sudo ./Blink
Now your LED should start blinking! CONGRATUALTIONS! You have successfully completed your first RPi
circuit!

█ support@[Link]
█ [Link]  support@[Link] 25

You can also use the file browser. On the left of folder tree, right-click the folder you want to enter, and click
"Open in Terminal".

You can press “Ctrl+C” to end the program. The following is the program code:
1 #include <wiringPi.h>
2 #include <stdio.h>
3
4 #define ledPin 0 //define the led pin number
5
6 void main(void)
7 {
8 printf("Program is starting ... \n");
9
10 wiringPiSetup(); //Initialize wiringPi.
11
12 pinMode(ledPin, OUTPUT); //Set the pin mode
13 printf("Using pin%d\n",%ledPin); //Output information on terminal
14 while(1){
15 digitalWrite(ledPin, HIGH); //Make GPIO output HIGH level
16 printf("led turned on >>>\n"); //Output information on terminal
17 delay(1000); //Wait for 1 second

support@[Link] █
26  support@[Link] [Link] █

18 digitalWrite(ledPin, LOW); //Make GPIO output LOW level


19 printf("led turned off <<<\n"); //Output information on terminal
20 delay(1000); //Wait for 1 second
21 }
22 }

In the code above, the configuration function for GPIO is shown below as:
void pinMode(int pin, int mode);
This sets the mode of a pin to either INPUT, OUTPUT, PWM_OUTPUT or GPIO_CLOCK. Note that only
wiringPi pin 1 (BCM_GPIO 18) supports PWM output and only wiringPi pin 7 (BCM_GPIO 4) supports CLOCK
output modes.
This function has no effect when in Sys mode. If you need to change the pin mode, then you can do it with
the gpio program in a script before you start your program
void digitalWrite (int pin, int value);
Writes the value HIGH or LOW (1 or 0) to the given pin, which must have been previously set as an output.
For more related wiringpi functions, please refer to [Link]

GPIO connected to ledPin in the circuit is GPIO17 and GPIO17 is defined as 0 in the wiringPi numbering. So
ledPin should be defined as 0 pin. You can refer to the corresponding table in Chapter 0.
#define ledPin 0 //define the led pin number
GPIO Numbering Relationship
WingPi BCM(Extension) Physical BCM(Extension) WingPi
3.3V 3.3V 1 2 5V 5V
8 GPIO2/SDA1 3 4 5V 5V
9 GPIO3/SCL1 5 6 GND GND
7 GPIO4 7 8 GPIO14/TXD0 15
GND GND 9 10 GPIO15/RXD0 16
0 GPIO17 11 12 GPIO18 1
2 GPIO27 13 14 GND GND
3 GPIO22 15 16 GPIO23 4
3.3V 3.3V 17 18 GPIO24 5
12 GPIO10/MOSI) 19 20 GND GND
13 GPIO9/MOIS 21 22 GPIO25 6
14 GPIO11/SCLK 23 24 GPIO8/CE0 10
GND GND 25 26 GPIO7/CE1 11
30 GPIO0/SDA0 27 28 GPIO1/SCL0 31
21 GPIO5 29 30 GND GND
22 GPIO6 31 32 GPIO12 26
23 GPIO13 33 34 GND GND
24 GPIO19 35 36 GPIO16 27
25 GPIO26 37 38 GPIO20 28
GND GND 39 40 GPIO21 29

█ support@[Link]
█ [Link]  support@[Link] 27

In the main function main(), initialize wiringPi first.


wiringPiSetup(); //Initialize wiringPi.

After the wiringPi is initialized successfully, you can set the ledPin to output mode and then enter the while
loop, which is an endless loop (a while loop). That is, the program will always be executed in this cycle, unless
it is ended because of external factors. In this loop, use digitalWrite (ledPin, HIGH) to make ledPin output high
level, then LED turns ON. After a period of time delay, use digitalWrite(ledPin, LOW) to make ledPin output low
level, then LED turns OFF, which is followed by a delay. Repeat the loop, then LED will start blinking.
pinMode(ledPin, OUTPUT);//Set the pin mode
printf("Using pin%d\n",%ledPin); //Output information on terminal
while(1){
digitalWrite(ledPin, HIGH); //Make GPIO output HIGH level
printf("led turned on >>>\n"); //Output information on terminal
delay(1000); //Wait for 1 second
digitalWrite(ledPin, LOW); //Make GPIO output LOW level
printf("led turned off <<<\n"); //Output information on terminal
delay(1000); //Wait for 1 second
}

support@[Link] █
28  support@[Link] [Link] █

Other Code Editors (Optional)

If you want to use other editor to edit and execute the code, you can learn them in this section.
nano
Use the nano editor to open the file "Hello.c", then press " Ctrl+X " to exit.
nano Hello.c

As is shown below:

Use the following command to compile the code to generate the executable file “Hello”.
gcc Hello.c -o Hello
Use the following command to run the executable file “Hello”.
sudo ./Hello
After the execution, "Hello, World!" is printed out in terminal.

█ support@[Link]
█ [Link]  support@[Link] 29

geany
Next, learn to use the Geany editor. Use the following command to open the Geany in the sample file
"Hello.c" file directory path.
geany Hello.c
Or find and open Geany directly in the desktop main menu, and then click File→Open to open the
"Hello.c", Or drag "Hello.c" to Geany directly.

If you want to create a new code, click File→New→File→Save as (name.c or [Link]). Then write the code.

support@[Link] █
30  support@[Link] [Link] █

Generate an executable file by clicking menu bar Build->Build.

Then execute the generated file by clicking menu bar Build->Execute.

After the execution, a new terminal window will output the characters “Hello, World!”, as shown below:

█ support@[Link]
█ [Link]  support@[Link] 31

You can click Build->Set Build Commands to set compiler commands. In later projects, we will use various
compiler command options. If you choose to use Geany, you will need change the compiler command here.
As is shown below:

Here we have identified three code editors: vi, nano and Geany. There are also many other good code editors
available to you, and you can choose whichever you prefer to use.

In later projects, we will only use terminal to execute the project code. This way will not modify the code by
mistake.

support@[Link] █
32  support@[Link] [Link] █

Freenove Car, Robot and other products for Raspberry Pi

We also have car and robot kits for Raspberry Pi. You can visit our website for details.

[Link]

FNK0043 Freenove 4WD Smart Car Kit for Raspberry Pi

[Link]
FNK0050 Freenove Robot Dog Kit for Raspberry Pi

[Link]

FNK0052 Freenove_Big_Hexapod_Robot_Kit_for_Raspberry_Pi
[Link]

█ support@[Link]
█ [Link]  support@[Link] 33

Chapter 2 Buttons & LEDs


Usually, there are three essential parts in a complete automatic control device: INPUT, OUTPUT, and CONTROL.
In last section, the LED module was the output part and RPI was the control part. In practical applications, we
not only make LEDs flash, but also make a device sense the surrounding environment, receive instructions
and then take the appropriate action such as turn on LEDs, make a buzzer beep and so on.

Control:
RPI, Arduino,
MCU and etc.

Input: Output:
buttons, switches, LED, buzzer,
sensors and etc. motor and etc.

Next, we will build a simple control system to control an LED through a push button switch.

Project 2.1 Push Button Switch & LED

In the project, we will control the LED state through a Push Button Switch. When the button is pressed, our
LED will turn ON, and when it is released, the LED will turn OFF. This describes a Momentary Switch.

Component List

Raspberry Pi (with 40 GPIO) x1 LED x1 Resistor 220Ω Resistor 10kΩ Push


GPIO Extension Board & Wire x1 x1 x2 Button
Breadboard x1 Switch x1

Jumper Wire

Please Note: In the code “button” represents switch action.

support@[Link] █
34  support@[Link] [Link] █

Component knowledge

Push Button Switch


This type of Push Button Switch has 4 pins (2 Pole Switch). Two pins on the left are connected, and both left
and right sides are the same per the illustration:

When the button on the switch is pressed, the circuit is completed (your project is Powered ON).

Circuit

Schematic diagram

R3 is used to limit current


to protect GPIO 18,if you
set it to output HIGH level
by mistake.

Hardware connection. If you need any support, please feel free to contact us via:support@[Link]

There are two kinds of push button switch in this kit.


The smaller push button switches are contained in a plastic bag.
Youtube video: [Link]

█ support@[Link]
█ [Link]  support@[Link] 35

This is how it works.


When button switch is released:

When button switch is pressed:

Code

This project is designed for learning how to use Push Button Switch to control an LED. We first need to read
the state of switch, and then determine whether to turn the LED ON in accordance to the state of the switch.
C Code 2.1.1 ButtonLED
First, observe the project result, then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 02.1.1_ButtonLED directory of C code.
cd ~/Freenove_Kit/Code/C_Code/02.1.1_ButtonLED
2. Use the following command to compile the code “ButtonLED.c” and generate executable file “ButtonLED”
gcc ButtonLED.c -o ButtonLED -lwiringPi
3. Then run the generated file “ButtonLED”.
sudo ./ButtonLED
Later, the terminal window continues to print out the characters “led off…”. Press the button, then LED is
turned on and then terminal window prints out the "led on…". Release the button, then LED is turned off and
then terminal window prints out the "led off…". You can press "Ctrl+C" to terminate the program.
The following is the program code:
1 #include <wiringPi.h>

support@[Link] █
36  support@[Link] [Link] █

2 #include <stdio.h>
3
4 #define ledPin 0 //define the ledPin
5 #define buttonPin 1 //define the buttonPin
6
7 void main(void)
8 {
9 printf("Program is starting ... \n");
10
11 wiringPiSetup(); //Initialize wiringPi.
12
13 pinMode(ledPin, OUTPUT); //Set ledPin to output
14 pinMode(buttonPin, INPUT);//Set buttonPin to input
15
16 pullUpDnControl(buttonPin, PUD_UP); //pull up to HIGH level
17 while(1){
18 if(digitalRead(buttonPin) == LOW){ //button is pressed
19 digitalWrite(ledPin, HIGH); //Make GPIO output HIGH level
20 printf("Button is pressed, led turned on >>>\n"); //Output information on
terminal
21 }
22 else { //button is released
23 digitalWrite(ledPin, LOW); //Make GPIO output LOW level
24 printf("Button is released, led turned off <<<\n"); //Output information on
terminal
25 }
26 }
27 }
In the circuit connection, LED and Button are connected with GPIO17 and GPIO18 respectively, which
correspond to 0 and 1 respectively in wiringPI. So define ledPin and buttonPin as 0 and 1 respectively.
#define ledPin 0 //define the ledPin
#define buttonPin 1 //define the buttonPin
In the while loop of main function, use digitalRead(buttonPin) to determine the state of Button. When the
button is pressed, the function returns low level, the result of “if” is true, and then turn on LED. Or, turn off
LED.
if(digitalRead(buttonPin) == LOW){ //button has pressed down
digitalWrite(ledPin, HIGH); //led on
printf("led on...\n");
}
else { //button has released
digitalWrite(ledPin, LOW); //led off
printf("...led off\n");
}

█ support@[Link]
█ [Link]  support@[Link] 37

Reference:
int digitalRead (int pin);
This function returns the value read at the given pin. It will be “HIGH” or “LOW”(1 or 0) depending on the
logic level at the pin.

support@[Link] █
38  support@[Link] [Link] █

Project 2.2 MINI Table Lamp

We will also use a Push Button Switch, LED and RPi to make a MINI Table Lamp but this will function differently:
Press the button, the LED will turn ON, and pressing the button again, the LED turns OFF. The ON switch
action is no longer momentary (like a door bell) but remains ON without needing to continually press on the
Button Switch.
First, let us learn something about the push button switch.

Debounce a Push Button Switch

When a Momentary Push Button Switch is pressed, it will not change from one state to another state
immediately. Due to tiny mechanical vibrations, there will be a short period of continuous buffeting before it
stabilizes in a new state too fast for Humans to detect but not for computer microcontrollers. The same is true
when the push button switch is released. This unwanted phenomenon is known as “bounce”.
press stable release stable

Ideal state

Virtual state

Therefore, if we can directly detect the state of the Push Button Switch, there are multiple pressing and
releasing actions in one pressing cycle. This buffeting will mislead the high-speed operation of the
microcontroller to cause many false decisions. Therefore, we need to eliminate the impact of buffeting. Our
solution: to judge the state of the button multiple times. Only when the button state is stable (consistent) over
a period of time, can it indicate that the button is actually in the ON state (being pressed).
This project needs the same components and circuits as we used in the previous section.

█ support@[Link]
█ [Link]  support@[Link] 39

Code

In this project, we still detect the state of Push Button Switch to control an LED. Here we need to define a
variable to define the state of LED. When the button switch is pressed once, the state of LED will be changed
once. This will allow the circuit to act as a virtual table lamp.
C Code 2.2.1 Tablelamp
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 02.2.1_Tablelamp directory of C code.
cd ~/Freenove_Kit/Code/C_Code/02.2.1_Tablelamp
2. Use the following command to compile “Tablelamp.c” and generate executable file “Tablelamp”.
gcc Tablelamp.c -o Tablelamp -lwiringPi
3. Tablelamp: Then run the generated file “Tablelamp”.
sudo ./Tablelamp
When the program is executed, press the Button Switch once, the LED turns ON. Pressing the Button Switch
again turns the LED OFF.
1 #include <wiringPi.h>
2 #include <stdio.h>
3
4 #define ledPin 0 //define the ledPin
5 #define buttonPin 1 //define the buttonPin
6 int ledState=LOW; //store the State of led
7 int buttonState=HIGH; //store the State of button
8 int lastbuttonState=HIGH;//store the lastState of button
9 long lastChangeTime; //store the change time of button state
10 long captureTime=50; //set the stable time for button state
11 int reading;
12 int main(void)
13 {
14 printf("Program is starting...\n");
15
16 wiringPiSetup(); //Initialize wiringPi.
17
18 pinMode(ledPin, OUTPUT); //Set ledPin to output
19 pinMode(buttonPin, INPUT); //Set buttonPin to input
20
21 pullUpDnControl(buttonPin, PUD_UP); //pull up to high level
22 while(1){
23 reading = digitalRead(buttonPin); //read the current state of button
24 if( reading != lastbuttonState){ //if the button state has changed, record the time
point
25 lastChangeTime = millis();
26 }

support@[Link] █
40  support@[Link] [Link] █

27 //if changing-state of the button last beyond the time we set, we consider that
28 //the current button state is an effective change rather than a buffeting
29 if(millis() - lastChangeTime > captureTime){
30 //if button state is changed, update the data.
31 if(reading != buttonState){
32 buttonState = reading;
33 //if the state is low, it means the action is pressing
34 if(buttonState == LOW){
35 printf("Button is pressed!\n");
36 ledState = !ledState; //Reverse the LED state
37 if(ledState){
38 printf("turn on LED ...\n");
39 }
40 else {
41 printf("turn off LED ...\n");
42 }
43 }
44 //if the state is high, it means the action is releasing
45 else {
46 printf("Button is released!\n");
47 }
48 }
49 }
50 digitalWrite(ledPin,ledState);
51 lastbuttonState = reading;
52 }
53
54 return 0;
55 }

This code focuses on eliminating the buffeting (bounce) of the button switch. We define several variables to
define the state of LED and button switch. Then read the button switch state constantly in while () to determine
whether the state has changed. If it has, then this time point is recorded.
reading = digitalRead(buttonPin); //read the current state of button
if( reading != lastbuttonState){
lastChangeTime = millis();
}

millis()
This returns a number representing the number of milliseconds since your program called one of the
wiringPiSetup functions. It returns to an unsigned 32-bit number value after 49 days because it “wraps”
around and restarts to value 0.

█ support@[Link]
█ [Link]  support@[Link] 41

Then according to the recorded time point, evaluate the duration of the button switch state change. If the
duration exceeds captureTime (buffeting time) we have set, it indicates that the state of the button switch has
changed. During that time, the while () is still detecting the state of the button switch, so if there is a change,
the time point of change will be updated. Then the duration will be evaluated again until the duration is
determined to be a stable state because it exceeds the time value we set.
if(millis() - lastChangeTime > captureTime){
//if button state is changed,update the data.
if(reading != buttonState){
buttonState = reading;

Finally, we need to judge the state of Button Switch. If it is low level, the changing state indicates that the
button Switch has been pressed, if the state is high level, then the button has been released. Here, we change
the status of the LED variable, and then update the state of the LED.
if(buttonState == LOW){
printf("Button is pressed!\n");
ledState = !ledState; //Reverse the LED state
if(ledState){
printf("turn on LED ...\n");
}
else {
printf("turn off LED ...\n");
}
}
//if the state is high, it means the action is releasing
else {
printf("Button is released!\n");
}

support@[Link] █
42  support@[Link] [Link] █

Chapter 3 LED Bar Graph


We have learned how to control one LED to blink. Next, we will learn how to control a number of LEDs.

Project 3.1 Flowing Water Light

In this project, we use a number of LEDs to make a flowing water light.

Component List

Raspberry Pi (with 40 GPIO) x1 Bar Graph LED x1 Resistor 220Ω x10


GPIO Extension Board & Ribbon Cable x1
Breadboard x1

Jumper Wire x 11

Component knowledge

Let us learn about the basic features of these components to use and understand them better.
Bar Graph LED
A Bar Graph LED has 10 LEDs integrated into one compact component. The two rows of pins at its bottom
are paired to identify each LED like the single LED used earlier.

█ support@[Link]
█ [Link]  support@[Link] 43

Circuit

A reference system of labels is used in the circuit diagram below. Pins with the same network label are
connected together.
Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

If LEDbar doesn’t work, rotate LEDbar 180° to try. The label is random.

Youtube video: [Link]


In this circuit, the cathodes of the LEDs are connected to the GPIO, which is different from the previous circuit.
The LEDs turn ON when the GPIO output is low level in the program.

Code

This project is designed to make a flowing water lamp, which are these actions: First turn LED #1 ON, then

support@[Link] █
44  support@[Link] [Link] █

turn it OFF. Then turn LED #2 ON, and then turn it OFF... and repeat the same to all 10 LEDs until the last LED
is turns OFF. This process is repeated to achieve the “movements” of flowing water.
C Code 3.1.1 LightWater
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 03.1.1_LightWater directory of C code.
cd ~/Freenove_Kit/Code/C_Code/03.1.1_LightWater
2. Use the following command to compile “LightWater.c” and generate executable file “LightWater”.
gcc LightWater.c -o LightWater -lwiringPi
3. Then run the generated file “LightWater”.
sudo ./LightWater
After the program is executed, you will see that Bar Graph LED starts with the flowing water pattern flashing
from left to right and then back from right to left.
The following is the program code:
1 #include <wiringPi.h>
2 #include <stdio.h>
3
4 #define ledCounts 10
5 int pins[ledCounts] = {0,1,2,3,4,5,6,8,9,10};
6
7 void main(void)
8 {
9 int i;
10 printf("Program is starting ... \n");
11
12 wiringPiSetup(); //Initialize wiringPi.
13
14 for(i=0;i<ledCounts;i++){ //Set pinMode for all led pins to output
15 pinMode(pins[i], OUTPUT);
16 }
17 while(1){
18 for(i=0;i<ledCounts;i++){ // move led(on) from left to right
19 digitalWrite(pins[i],LOW);
20 delay(100);
21 digitalWrite(pins[i],HIGH);
22 }
23 for(i=ledCounts-1;i>-1;i--){ // move led(on) from right to left
24 digitalWrite(pins[i],LOW);
25 delay(100);
26 digitalWrite(pins[i],HIGH);
27 }
28 }
29 }

█ support@[Link]
█ [Link]  support@[Link] 45

In the program, configure the GPIO0-GPIO9 to output mode. Then, in the endless “while” loop of main
function, use two “for” loop to realize flowing water light from left to right and from right to left.
while(1){
for(i=0;i<ledCounts;i++){ // move led(on) from left to right
digitalWrite(pins[i],LOW);
delay(100);
digitalWrite(pins[i],HIGH);
}
for(i=ledCounts-1;i>-1;i--){ // move led(on) from right to left
digitalWrite(pins[i],LOW);
delay(100);
digitalWrite(pins[i],HIGH);
}
}
}

support@[Link] █
46  support@[Link] [Link] █

Chapter 4 Analog & PWM


In previous chapters, we learned that a Push Button Switch has two states: Pressed (ON) and Released (OFF),
and an LED has a Light ON and OFF state. Is there a middle or intermediated state? We will next learn how to
create an intermediate output state to achieve a partially bright (dim) LED.
First, let us learn how to control the brightness of an LED.

Project 4.1 Breathing LED

We describe this project as a Breathing Light. This means that an LED that is OFF will then turn ON gradually
and then gradually turn OFF like "breathing". Okay, so how do we control the brightness of an LED to create
a Breathing Light? We will use PWM to achieve this goal.

Component List

Raspberry Pi (with 40 GPIO) x1 LED x1 Resistor 220Ω x1


GPIO Extension Board & Ribbon Cable x1
Breadboard x1

Jumper Wire

Component Knowledge

Analog & Digital


An Analog Signal is a continuous signal in both time and value. On the contrary, a Digital Signal or discrete-
time signal is a time series consisting of a sequence of quantities. Most signals in life are analog signals. A
familiar example of an Analog Signal would be how the temperature throughout the day is continuously
changing and could not suddenly change instantaneously from 0℃ to 10℃. However, Digital Signals can
instantaneously change in value. This change is expressed in numbers as 1 and 0 (the basis of binary code).
Their differences can more easily be seen when compared when graphed as below.

█ support@[Link]
█ [Link]  support@[Link] 47

Note that the Analog signals are curved waves and the Digital signals are “Square Waves”.
In practical applications, we often use binary as the digital signal, that is a series of 0’s and 1’s. Since a binary
signal only has two values (0 or 1) it has great stability and reliability. Lastly, both analog and digital signals
can be converted into the other.
PWM
PWM, Pulse-Width Modulation, is a very effective method for using digital signals to control analog circuits.
Digital processors cannot directly output analog signals. PWM technology makes it very convenient to achieve
this conversion (translation of digital to analog signals).
PWM technology uses digital pins to send certain frequencies of square waves, that is, the output of high
levels and low levels, which alternately last for a while. The total time for each set of high levels and low levels
is generally fixed, which is called the period (Note: the reciprocal of the period is frequency). The time of high
level outputs are generally called “pulse width”, and the duty cycle is the percentage of the ratio of pulse
duration, or pulse width (PW) to the total period (T) of the waveform. The longer the output of high levels last,
the longer the duty cycle and the higher the corresponding voltage in the analog signal will be. The following
figures show how the analog signal voltages vary between 0V-5V (high level is 5V) corresponding to the pulse
width 0%-100%:

support@[Link] █
48  support@[Link] [Link] █

The longer the PWM duty cycle is, the higher the output power will be. Now that we understand this
relationship, we can use PWM to control the brightness of an LED or the speed of DC motor and so on.
It is evident, from the above, that PWM is not actually analog but the effective value of voltage is equivalent
to the corresponding analog value. Therefore, by using PWM, we can control the output power of to an LED
and control other devices and modules to achieve multiple effects and actions.
In RPi, GPIO18 pin has the ability to output to hardware via PWM with a 10-bit accuracy. This means that 100%
10
of the pulse width can be divided into 2 =1024 equal parts.
The wiringPi library of C provides both a hardware PWM and a software PWM method.

The hardware PWM only needs to be configured, does not require CPU resources and is more precise in time
control. The software PWM requires the CPU to work continuously by using code to output high level and
low level. This part of the code is carried out by multi-threading, and the accuracy is relatively not high enough.

In order to keep the results running consistently, we will use PWM.

█ support@[Link]
█ [Link]  support@[Link] 49

Circuit

Schematic diagram Hardware connection. If you need any support, please


feel free to contact us via: support@[Link]

Youtube video: [Link]

Code

This project uses the PWM output from the GPIO18 pin to make the pulse width gradually increase from 0%
to 100% and then gradually decrease from 100% to 0% to make the LED glow brighter then dimmer.
C Code 4.1.1 BreathingLED
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 04.1.1_BreathingLED directory of C code.
cd ~/Freenove_Kit/Code/C_Code/04.1.1_BreathingLED
2. Use following command to compile “BreathingLED.c” and generate executable file “BreathingLED”.
gcc BreathingLED.c -o BreathingLED -lwiringPi
3. Then run the generated file “BreathingLED”
sudo ./BreathingLED
After the program is executed, you'll see that LED is turned from on to off and then from off to on gradually
like breathing.
The following is the program code:
1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <softPwm.h>
4 #define ledPin 1
5 void main(void)
6 {

support@[Link] █
50  support@[Link] [Link] █

7 int i;
8
9 printf("Program is starting ... \n");
10
11 wiringPiSetup(); //Initialize wiringPi.
12
13 softPwmCreate(ledPin, 0, 100);//Creat SoftPWM pin
14
15 while(1){
16 for(i=0;i<100;i++){ //make the led brighter
17 softPwmWrite(ledPin, i);
18 delay(20);
19 }
20 delay(300);
21 for(i=100;i>=0;i--){ //make the led darker
22 softPwmWrite(ledPin, i);
23 delay(20);
24 }
25 delay(300);
26 }
27 }
First, create a software PWM pin.
softPwmCreate(ledPin, 0, 100);//Creat SoftPWM pin
There are two “for” loops in the next endless “while” loop. The first loop outputs a power signal to the ledPin
PWM from 0% to 100% and the second loop outputs a power signal to the ledPin PWM from 100% to 0%.
while(1){
for(i=0;i<100;i++){
softPwmWrite(ledPin, i);
delay(20);
}
delay(300);
for(i=100;i>=0;i--){
softPwmWrite(ledPin, i);
delay(20);
}
delay(300);
}
You can also adjust the rate of the state change of LED by changing the parameter of the delay() function in
the “for” loop.
int softPwmCreate (int pin, int initialValue, int pwmRange) ;
This creates a software controlled PWM pin.
void softPwmWrite (int pin, int value) ;
This updates the PWM value on the given pin.
For more details, please refer [Link]

█ support@[Link]
█ [Link]  support@[Link] 51

Chapter 5 RGB LED


In this chapter, we will learn how to control a RGB LED.
An RGB LED has 3 LEDs integrated into one LED component. It can respectively emit Red, Green and Blue
light. In order to do this, it requires 4 pins (this is also how you identify it). The long pin (1) is the common
which is the Anode (+) or positive lead, the other 3 are the Cathodes (-) or negative leads. A rendering of a
RGB LED and its electronic symbol are shown below. We can make RGB LED emit various colors of light and
brightness by controlling the 3 Cathodes (2, 3 & 4) of the RGB LED

Red, Green, and Blue light are called 3 Primary Colors when discussing light (Note: for pigments such as paints,
the 3 Primary Colors are Red, Blue and Yellow). When you combine these three Primary Colors of light with
varied brightness, they can produce almost any color of visible light. Computer screens, single pixels of cell
phone screens, neon lamps, etc. can all produce millions of colors due to phenomenon.

RGB

8 8 8
If we use a three 8 bit PWM to control the RGB LED, in theory, we can create 2 *2 *2 =16777216 (16 million)
colors through different combinations of RGB light brightness.
Next, we will use RGB LED to make a multicolored LED.

support@[Link] █
52  support@[Link] [Link] █

Project 5.1 Multicolored LED

Component List

Raspberry Pi (with 40 GPIO) x1 RGB LED x1 Resistor 220Ω x3


GPIO Extension Board & Wire x1
Breadboard x1

Jumper Wire

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]

In this kit, the RGB led is Common anode. The voltage difference between LED will make it work. There is

█ support@[Link]
█ [Link]  support@[Link] 53

no visible GND. The GPIO ports can also receive current while in output mode.
If circuit above doesn’t work, the RGB LED may be common cathode. Please try following wiring.
There is no need to modify code for random color.

Code

We need to use the software to make the ordinary GPIO output PWM, since this project requires 3 PWM and
in RPi only one GPIO has the hardware capability to output PWM,
C Code 5.1.1 Colorful LED
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 05.1.1_ColorfulLED directory of C code.
cd ~/Freenove_Kit/Code/C_Code/05.1.1_ColorfulLED
2. Use following command to compile “ColorfulLED.c” and generate executable file “ColorfulLED”.
Note: in this project, the software PWM uses a multi-threading mechanism. So “-lpthread” option need
to be add to the compiler.
gcc ColorfulLED.c -o ColorfulLED -lwiringPi -lpthread
3. And then run the generated file “ColorfulLED”.
sudo ./ColorfulLED
After the program is executed, you will see that the RGB LED shows lights of different colors randomly.

The following is the program code:


1 #include <wiringPi.h>
2 #include <softPwm.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5
6 #define ledPinRed 0
7 #define ledPinGreen 1
8 #define ledPinBlue 2
9
10 void setupLedPin(void)
11 {

support@[Link] █
54  support@[Link] [Link] █

12 softPwmCreate(ledPinRed, 0, 100); //Creat SoftPWM pin for red


13 softPwmCreate(ledPinGreen,0, 100); //Creat SoftPWM pin for green
14 softPwmCreate(ledPinBlue, 0, 100); //Creat SoftPWM pin for blue
15 }
16
17 void setLedColor(int r, int g, int b)
18 {
19 softPwmWrite(ledPinRed, r); //Set the duty cycle
20 softPwmWrite(ledPinGreen, g); //Set the duty cycle
21 softPwmWrite(ledPinBlue, b); //Set the duty cycle
22 }
23
24 int main(void)
25 {
26 int r,g,b;
27
28 printf("Program is starting ...\n");
29
30 wiringPiSetup(); //Initialize wiringPi.
31
32 setupLedPin();
33 while(1){
34 r=random()%100; //get a random in (0,100)
35 g=random()%100; //get a random in (0,100)
36 b=random()%100; //get a random in (0,100)
37 setLedColor(r,g,b);//set random as the duty cycle value
38 // If you are using common anode RGBLED,it should be setLedColor(100-r,100-g,100-b)
39 // If you want show red, it should be setLedColor(0,100,100)
40 printf("r=%d, g=%d, b=%d \n",r,g,b);
41 delay(1000);
42 }
43 return 0;
44 }

First, in subfunction of ledInit(), create the software PWM control pins used to control the R, G, B pin
respectively.
void setupLedPin(void)
{
softPwmCreate(ledPinRed, 0, 100); //Creat SoftPWM pin for red
softPwmCreate(ledPinGreen,0, 100); //Creat SoftPWM pin for green
softPwmCreate(ledPinBlue, 0, 100); //Creat SoftPWM pin for blue
}
Then create subfunction, and set the PWM of three pins.
void setLedColor(int r, int g, int b)

█ support@[Link]
█ [Link]  support@[Link] 55

{
softPwmWrite(ledPinRed, r); //Set the duty cycle
softPwmWrite(ledPinGreen, g); //Set the duty cycle
softPwmWrite(ledPinBlue, b); //Set the duty cycle
}
Finally, in the “while” loop of main function, get three random numbers and specify them as the PWM duty
cycle, which will be assigned to the corresponding pins. So RGB LED can switch the color randomly all the
time.
while(1){
r=random()%100; //get a random in (0,100)
g=random()%100; //get a random in (0,100)
b=random()%100; //get a random in (0,100)
setLedColor(r,g,b);//set random as the duty cycle value
printf("r=%d, g=%d, b=%d \n",r,g,b);
delay(1000);
}
The related function of PWM Software can be described as follows:
long random();
This function will return a random number.

For more details about Software PWM, please refer to: [Link]

support@[Link] █
56  support@[Link] [Link] █

Chapter 6 Buzzer
In this chapter, we will learn about buzzers and the sounds they make. And in our next project, we will use an
active buzzer to make a doorbell and a passive buzzer to make an alarm.

Project 6.1 Doorbell

We will make a doorbell with this functionality: when the Push Button Switch is pressed the buzzer sounds
and when the button is released, the buzzer stops. This is a momentary switch function.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper Wire


GPIO Extension Board & Ribbon Cable x1
Breadboard x1
NPN transistorx1 Active buzzer x1 Push Button Resistor 1kΩ x1 Resistor 10kΩ x2
(S8050) Switch x1

█ support@[Link]
█ [Link]  support@[Link] 57

Component knowledge

Buzzer
A buzzer is an audio component. They are widely used in electronic devices such as calculators, electronic
alarm clocks, automobile fault indicators, etc. There are both active and passive types of buzzers. Active
buzzers have oscillator inside, these will sound as long as power is supplied. Passive buzzers require an
external oscillator signal (generally using PWM with different frequencies) to make a sound.

Active buzzer Passive buzzer

Active buzzers are easier to use. Generally, they only make a specific sound frequency. Passive buzzers
require an external circuit to make sounds, but passive buzzers can be controlled to make sounds of various
frequencies. The resonant frequency of the passive buzzer in this Kit is 2kHz, which means the passive
buzzer is the loudest when its resonant frequency is 2kHz.

How to identify active and passive buzzer?


1. As a rule, there is a label on an active buzzer covering the hole where sound is emitted, but there are
exceptions to this rule.
2. Active buzzers are more complex than passive buzzers in their manufacture. There are many circuits and
crystal oscillator elements inside active buzzers; all of this is usually protected with a waterproof coating
(and a housing) exposing only its pins from the underside. On the other hand, passive buzzers do not
have protective coatings on their underside. From the pin holes, view of a passive buzzer, you can see
the circuit board, coils, and a permanent magnet (all or any combination of these components
depending on the model.

Active buzzer bottom Passive buzzer bottom

Transistors
A transistor is required in this project due to the buzzer’s current being so great that GPIO of RPi’s output
capability cannot meet the power requirement necessary for operation. A NPN transistor is needed here to

support@[Link] █
58  support@[Link] [Link] █

amplify the current.


Transistors, full name: semiconductor transistor, is a semiconductor device that controls current (think of a
transistor as an electronic “amplifying or switching device”. Transistors can be used to amplify weak signals,
or to work as a switch. Transistors have three electrodes (PINs): base (b), collector (c) and emitter (e). When
there is current passing between "be" then "ce" will have a several-fold current increase (transistor
magnification), in this configuration the transistor acts as an amplifier. When current produced by "be" exceeds
a certain value, "ce" will limit the current output. at this point the transistor is working in its saturation region
and acts like a switch. Transistors are available as two types as shown below: PNP and NPN,

PNP transistor NPN transistor

In our kit, the PNP transistor is marked with 8550, and the NPN transistor is marked with 8050.

Thanks to the transistor's characteristics, they are often used as switches in digital circuits. As micro-controllers
output current capacity is very weak, we will use a transistor to amplify its current in order to drive components
requiring higher current.
When we use a NPN transistor to drive a buzzer, we often use the following method. If GPIO outputs high
level, current will flow through R1 (Resistor 1), the transistor conducts current and the buzzer will make sounds.
If GPIO outputs low level, no current will flow through R1, the transistor will not conduct currentand buzzer
will remain silent (no sounds).
When we use a PNP transistor to drive a buzzer, we often use the following method. If GPIO outputs low level,
current will flow through R1. The transistor conducts current and the buzzer will make sounds. If GPIO outputs
high level, no current flows through R1, the transistor will not conduct current and buzzer will remain silent
(no sounds). Below are the circuit schematics for both a NPN and PNP transistor to power a buzzer.
NPN transistor to drive buzzer PNP transistor to drive buzzer

█ support@[Link]
█ [Link]  support@[Link] 59

Circuit

Schematic diagram with RPi GPIO Extension Shield

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]
Note: in this circuit, the power supply for the buzzer is 5V, and pull-up resistor of the push button switch is
connected to the 3.3V power feed. Actually, the buzzer can work when connected to the 3.3V power feed
but this will produce a weak sound from the buzzer (not very loud).

Code

In this project, a buzzer will be controlled by a push button switch. When the button switch is pressed, the
buzzer sounds and when the button is released, the buzzer stops. It is analogous to our earlier project that
controlled an LED ON and OFF.

support@[Link] █
60  support@[Link] [Link] █

C Code 6.1.1 Doorbell


First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 06.1.1_Doorbell directory of C code.
cd ~/Freenove_Kit/Code/C_Code/06.1.1_Doorbell
2. Use following command to compile “Doorbell.c” and generate executable file “Doorbell.c”.
gcc Doorbell.c -o Doorbell -lwiringPi
3. Then run the generated file “Doorbell”.
sudo ./Doorbell

After the program is executed, press the push button switch and the will buzzer sound. Release the push
button switch and the buzzer will stop.
The following is the program code:
1 #include <wiringPi.h>
2 #include <stdio.h>
3
4 #define buzzerPin 0 //define the buzzerPin
5 #define buttonPin 1 //define the buttonPin
6
7 void main(void)
8 {
9 printf("Program is starting ... \n");
10
11 wiringPiSetup();
12
13 pinMode(buzzerPin, OUTPUT);
14 pinMode(buttonPin, INPUT);
15
16 pullUpDnControl(buttonPin, PUD_UP); //pull up to HIGH level
17 while(1){
18
19 if(digitalRead(buttonPin) == LOW){ //button is pressed
20 digitalWrite(buzzerPin, HIGH); //Turn on buzzer
21 printf("buzzer turned on >>> \n");
22 }
23 else { //button is released
24 digitalWrite(buzzerPin, LOW); //Turn off buzzer
25 printf("buzzer turned off <<< \n");
26 }
27 }
28 }
The code is exactly the same as when we used a push button switch to control an LED. You can also try using
the PNP transistor to achieve the same results.

█ support@[Link]
█ [Link]  support@[Link] 61

Project 6.2 Alertor

Next, we will use a passive buzzer to make an alarm.


The list of components and the circuit is similar to the doorbell project. We only need to take the Doorbell
circuit and replace the active buzzer with a passive buzzer.

Code

In this project, our buzzer alarm is controlled by the push button switch. Press the push button switch and the
buzzer will sound. Release the push button switch and the buzzer will stop.
As stated before, it is analogous to our earlier project that controlled an LED ON and OFF.
To control a passive buzzer requires PWM of certain sound frequency.
C Code 6.2.1 Alertor
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 06.2.1_Alertor directory of C code.
cd ~/Freenove_Kit/Code/C_Code/06.2.1_Alertor
2. Use following command to compile “Alertor.c” and generate executable file “Alertor”. “-lm” and “-lpthread”
compiler options need to added here.
gcc Alertor.c -o Alertor -lwiringPi -lm -lpthread
3. Then run the generated file “Alertor”.
sudo ./Alertor

After the program is executed, press the push button switch and the buzzer will sound. Release the push
button switch and the buzzer will stop.
The following is the program code:
1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <softTone.h>
4 #include <math.h>
5
6 #define buzzerPin 0 //define the buzzerPin
7 #define buttonPin 1 //define the buttonPin
8
9 void alertor(int pin){
10 int x;
11 double sinVal, toneVal;
12 for(x=0;x<360;x++){ // frequency of the alertor is consistent with the sine wave
13 sinVal = sin(x * (M_PI / 180)); //Calculate the sine value
14 toneVal = 2000 + sinVal * 500; //Add the resonant frequency and weighted sine value
15 softToneWrite(pin,toneVal); //output corresponding PWM
16 delay(1);

support@[Link] █
62  support@[Link] [Link] █

17 }
18 }
19 void stopAlertor(int pin){
20 softToneWrite(pin,0);
21 }
22 int main(void)
23 {
24 printf("Program is starting ... \n");
25
26 wiringPiSetup();
27
28 pinMode(buzzerPin, OUTPUT);
29 pinMode(buttonPin, INPUT);
30 softToneCreate(buzzerPin); //set buzzerPin
31 pullUpDnControl(buttonPin, PUD_UP); //pull up to HIGH level
32 while(1){
33 if(digitalRead(buttonPin) == LOW){ //button is pressed
34 alertor(buzzerPin); // turn on buzzer
35 printf("alertor turned on >>> \n");
36 }
37 else { //button is released
38 stopAlertor(buzzerPin); // turn off buzzer
39 printf("alertor turned off <<< \n");
40 }
41 }
42 return 0;
43 }

The code is the same to the active buzzer but the method is different. A passive buzzer requires PWM of a
certain frequency, so you need to create a software PWM pin though softToneCreate (buzzeRPin). Here
softTone is designed to generate square waves with variable frequency and a duty cycle fixed to 50%, which
is a better choice for controlling the buzzer.
softToneCreate(buzzeRPin);
In the while loop of the main function, when the push button switch is pressed the subfunction alertor() will
be called and the alarm will issue a warning sound. The frequency curve of the alarm is based on a sine curve.
We need to calculate the sine value from 0 to 360 degrees and multiplied by a certain value (here this value
is 500) plus the resonant frequency of buzzer. We can set the PWM frequency through softToneWrite (pin,
toneVal).
void alertor(int pin){
int x;
double sinVal, toneVal;
for(x=0;x<360;x++){ //The frequency is based on the sine curve.
sinVal = sin(x * (M_PI / 180));
toneVal = 2000 + sinVal * 500;

█ support@[Link]
█ [Link]  support@[Link] 63

softToneWrite(pin,toneVal);
delay(1);
}
}

If you want to stop the buzzer, just set PWM frequency of the buzzer pin to 0.
void stopAlertor(int pin){
softToneWrite(pin,0);
}

The related functions of softTone are described as follows:


int softToneCreate (int pin) ;
This creates a software controlled tone pin.
void softToneWrite (int pin, int freq) ;
This updates the tone frequency value on the given pin.
For more details about softTone, please refer to : [Link]

support@[Link] █
64  support@[Link] [Link] █

(Important) Chapter 7 ADC


We have learned how to control the brightness of an LED through PWM and that PWM is not a real analog
signal. In this chapter, we will learn how to read analog values via an ADC Module and convert these analog
values into digital.

Project 7.1 Read the Voltage of Potentiometer

In this project, we will use the ADC function of an ADC Module to read the voltage value of a potentiometer.

Component List

Raspberry Pi x1 Jumper Wire M/M x16


GPIO Extension Board & Ribbon Cable x1
Breadboard x1
Rotary potentiometer x1 ADC module x1 Resistor 10kΩ x2

or
This product contains only one ADC module, there are two types, PCF8591 and ADS7830. For the projects
described in this tutorial, they function the same. Please build corresponding circuits according to the ADC
module found in your Kit.
ADC module: PCF8591 ADC module: ADS7830
Model diagram Actual Picture Model diagram Actual Picture

█ support@[Link]
█ [Link]  support@[Link] 65

Circuit knowledge

ADC
An ADC is an electronic integrated circuit used to convert analog signals such as voltages to digital or
binary form consisting of 1s and 0s. The range of our ADC module is 8 bits, that means the resolution is
2^8=256, so that its range (at 3.3V) will be divided equally to 256 parts.
Any analog value can be mapped to one digital value using the resolution of the converter. So the more bits
the ADC has, the denser the partition of analog will be and the greater the precision of the resulting conversion.

Subsection 1: the analog in range of 0V-3.3/256 V corresponds to digital 0;


Subsection 2: the analog in range of 3.3 /256 V-2*3.3 /256V corresponds to digital 1;

The resultant analog signal will be divided accordingly.
DAC
The reversing this process requires a DAC, Digital-to-Analog Converter. The digital I/O port can output high
level and low level (0 or 1), but cannot output an intermediate voltage value. This is where a DAC is useful.
The DAC module PCF8591 has a DAC output pin with 8-bit accuracy, which can divide VDD (here is 3.3V) into
8
2 =256 parts. For example, when the digital quantity is 1, the output voltage value is 3.3/256 *1 V, and when
the digital quantity is 128, the output voltage value is 3.3/256 *128=1.65V, the higher the accuracy of DAC,
the higher the accuracy of output voltage value will be.

support@[Link] █
66  support@[Link] [Link] █

Component knowledge

Potentiometer
Potentiometer is a resistive element with three Terminal parts. Unlike the resistors that we have used thus far
in our project which have a fixed resistance value, the resistance value of a potentiometer can be adjusted. A
potentiometer is often made up by a resistive substance (a wire or carbon element) and movable contact
brush. When the brush moves along the resistor element, there will be a change in the resistance of the
potentiometer’s output side (3) (or change in the voltage of the circuit that is a part). The illustration below
represents a linear sliding potentiometer and its electronic symbol on the right.

Between potentiometer pin 1 and pin 2 is the resistive element (a resistance wire or carbon) and pin 3 is
connected to the brush that makes contact with the resistive element. In our illustration, when the brush
moves from pin 1 to pin 2, the resistance value between pin 1 and pin 3 will increase linearly (until it reaches
the highest value of the resistive element) and at the same time the resistance between pin 2 and pin 3 will
decrease linearly and conversely down to zero. At the midpoint of the slider the measured resistance values
between pin 1 and 3 and between pin 2 and 3 will be the same.
In a circuit, both sides of resistive element are often connected to the positive and negative electrodes of
power. When you slide the brush “pin 3”, you can get variable voltage within the range of the power supply.

Rotary potentiometer
Rotary potentiometers and linear potentiometers have the same function; the only difference being the
physical action being a rotational rather than a sliding movement.

█ support@[Link]
█ [Link]  support@[Link] 67

PCF8591
The PCF8591 is a single-chip, single-supply low power 8-bit CMOS data acquisition device with four analog
inputs, one analog output and a serial I2C-bus interface. The following table is the pin definition diagram of
PCF8591.
SYMBOL PIN DESCRIPTION TOP VIEW
AIN0 1
AIN1 2
Analog inputs (A/D converter)
AIN2 3
AIN3 4
A0 5
A1 6 Hardware address
A2 7
Vss 8 Negative supply voltage
SDA 9 I2C-bus data input/output
SCL 10 I2C-bus clock input
OSC 11 Oscillator input/output
EXT 12 external/internal switch for oscillator input
AGND 13 Analog ground
Vref 14 Voltage reference input
AOUT 15 Analog output(D/A converter)
Vdd 16 Positive supply voltage
For more details about PCF8591, please refer to the datasheet which can be found on the Internet.
ADS7830
The ADS7830 is a single-supply, low-power, 8-bit data acquisition device that features a serial I2C interface
and an 8-channel multiplexer. The following table is the pin definition diagram of ADS7830.
SYMBOL PIN DESCRIPTION TOP VIEW
CH0 1
CH1 2
Analog input channels
CH2 3
(A/D converter)
CH3 4
CH4 5

support@[Link] █
68  support@[Link] [Link] █

CH5 6
CH6 7
CH7 8
GND 9 Ground
Internal +2.5V Reference,
REF in/out 10
External Reference Input
COM 11 Common to Analog Input Channel
A0 12
Hardware address
A1 13
SCL 14 Serial Clock
SDA 15 Serial Sata
+VDD 16 Power Supply, 3.3V Nominal

I2C communication

I2C (Inter-Integrated Circuit) has a two-wire serial communication mode, which can be used to connect a
micro-controller and its peripheral equipment. Devices using I2C communications must be connected to the
serial data line (SDA), and serial clock line (SCL) (called I2C bus). Each device has a unique address which can
be used as a transmitter or receiver to communicate with devices connected via the bus.

█ support@[Link]
█ [Link]  support@[Link] 69

Circuit with ADS7830

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]
This product contains only one ADC module.

Video: [Link]

support@[Link] █
70  support@[Link] [Link] █

Circuit with PCF8591

Schematic diagram

Hardware connection

Please keep the chip mark consistent to make the chips under right direction and position.

█ support@[Link]
█ [Link]  support@[Link] 71

Configure I2C and Install Smbus

Enable I2C
The I2C interface in Raspberry Pi is disabled by default. You will need to open it manually and enable the I2C
interface as follows:
Type command in the Terminal:
sudo raspi-config
Then open the following dialog box:

Choose “3 Interfacing Options” then “I4 I2C” then “Yes” and then “Finish” in this order and restart your RPi.
The I2C module will then be started.
Type a command to check whether the I2C module is started:
lsmod | grep i2c
If the I2C module has been started, the following content will be shown. “bcm2708" refers to the CPU model.
Different models of Raspberry Pi display different contents depending on the CPU installed:

support@[Link] █
72  support@[Link] [Link] █

Install I2C-Tools
Next, type the command to install I2C-Tools. It is available with the Raspberry Pi OS by default.
sudo apt-get install i2c-tools
I2C device address detection:
i2cdetect -y 1
When you are using the PCF8591 Module, the result should look like this:

Here, 48 (HEX) is the I2C address of ADC Module (PCF8591).

When you are using ADS, the result should look like this:

Here, 4b (HEX) is the I2C address of ADC Module (ADS7830).

Code

C Code 7.1.1 ADC


For C code for the ADC Device, a custom library needs to be installed.
1. Use cd command to enter folder of the ADC Device library.
cd ~/Freenove_Kit/Libs/C-Libs/ADCDevice
2. Execute command below to install the library.
sh ./[Link]
A successful installation, without error prompts, is shown below:

█ support@[Link]
█ [Link]  support@[Link] 73

Next, we will execute the code for this project.


First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 07.1.1_ADC directory of C code.
cd ~/Freenove_Kit/Code/C_Code/07.1.1_ADC
2. Use following command to compile “[Link]” and generate the executable file “ADC”.
g++ [Link] -o ADC -lwiringPi -lADCDevice
3. Then run the generated file “ADC”.
sudo ./ADC
After the program is executed, adjusting the potentiometer will produce a readout display of the
potentiometer voltage values in the Terminal and the converted digital content.

The following is the code:


1 #include <wiringPi.h>
2 #include <wiringPiI2C.h>
3 #include <stdio.h>
4 #include <[Link]>
5
6 ADCDevice *adc; // Define an ADC Device class object
7
8 int main(void){
9 adc = new ADCDevice();
10 printf("Program is starting ... \n");
11
12 if(adc->detectI2C(0x48)){ // Detect the pcf8591.
13 delete adc;
14 adc = new PCF8591(); // If detected, create an instance of PCF8591.
15 }
16 else if(adc->detectI2C(0x4b)){// Detect the ads7830
17 delete adc;
18 adc = new ADS7830(); // If detected, create an instance of ADS7830.

support@[Link] █
74  support@[Link] [Link] █

19 }
20 else{
21 printf("No correct I2C address found, \n"
22 "Please use command 'i2cdetect -y 1' to check the I2C address! \n"
23 "Program Exit. \n");
24 return -1;
25 }
26
27 while(1){
28 int adcValue = adc->analogRead(0); //read analog value of A0 pin
29 float voltage = (float)adcValue / 255.0 * 3.3; // Calculate voltage
30 printf("ADC value : %d ,\tVoltage : %.2fV\n",adcValue,voltage);
31 delay(100);
32 }
33 }

In this code, a custom class library "ADCDevice" is used. It contains the method of utilizing the ADC Module
in this project, through which the ADC Module can easily and quickly be used. In the code, you need to first
create a class pointer adc, and then point to an instantiated object. (Note: An instantiated object is given a
name and created in memory or on disk using the structure described within a class declaration.)

ADCDevice *adc; // Define an ADC Device class object


……
adc = new ADCDevice();
Then use the member function detectIC(addr) in the class to detect the I2C module in the circuit. Different
modules have different I2C addresses. Therefore, according to the different addresses, we can determine what
the ADC module is in the circuit. When the correct module is detected, the pointer adc will point to the address
of the object, and then the previously pointed content will be deleted to free memory. The default address of
ADC module PCF8591 is 0x48, and that of ADC module ADS7830 is 0x4b.
if(adc->detectI2C(0x48)){ // Detect the pcf8591.
delete adc;
adc = new PCF8591(); // If detected, create an instance of PCF8591.
}
else if(adc->detectI2C(0x4b)){// Detect the ads7830
delete adc;
adc = new ADS7830(); // If detected, create an instance of ADS7830.
}
else{
printf("No correct I2C address found, \n"
"Please use command 'i2cdetect -y 1' to check the I2C address! \n"
"Program Exit. \n");
return -1;
}

█ support@[Link]
█ [Link]  support@[Link] 75

When you have a class object pointed to a specific device, you can get the ADC value of the specific channel
by calling the member function analogRead (chn) in this class
int adcValue = adc->analogRead(0); //read analog value of A0 pin

Then according to the formula, the voltage value is calculated and displayed on the Terminal.
float voltage = (float)adcValue / 255.0 * 3.3; // Calculate voltage
printf("ADC value : %d ,\tVoltage : %.2fV\n",adcValue,voltage);

Reference
class ADCDevice
This is a base class. All ADC module classes are its derived classes. It has a real function and a virtual
function.

int detectI2C(int addr);


This is a real function, which is used to detect whether the device with given I2C address exists. If it exists,
return 1, otherwise return 0.

virtual int analogRead(int chn);


This is a virtual function that reads the ADC value of the specified channel. It is implemented in a derived
class.
class PCF8591:public ADCDevice
class ADS7830:public ADCDevice
These two classes are derived from the ADCDevice class and mainly implement the function
analogRead(chn).

int analogRead(int chn);


This returns the value read on the supplied analog input pin.
Parameter chn: For PCF8591, the range of chn is 0, 1, 2, 3. For ADS7830, the range of is 0, 1, 2, 3, 4, 5, 6, 7.

You can find the source file of this library in the folder below:
~/Freenove_Kit/Libs/C-Libs/ADCDevice/

support@[Link] █
76  support@[Link] [Link] █

Chapter 8 Potentiometer & LED


Earlier we learned how to use ADC and PWM. In this chapter, we learn to control the brightness of an LED by
using a potentiometer.

Project 8.1 Soft Light

In this project, we will make a soft light. We will use an ADC Module to read ADC values of a potentiometer
and map it to duty cycle ratio of the PWM used to control the brightness of an LED. Then you can change the
brightness of an LED by adjusting the potentiometer.

Component List

Raspberry Pi x1 Jumper Wire M/M x17


GPIO Extension Board & Ribbon Cable x1
Breadboard x1
Rotary Potentiometer x1 ADC Module x1(Only one) 10kΩ x2 220Ω x1 LED x1

or

█ support@[Link]
█ [Link]  support@[Link] 77

Circuit with ADS7830

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]

support@[Link] █
78  support@[Link] [Link] █

Circuit with PCF8591

Schematic diagram

Hardware connection

█ support@[Link]
█ [Link]  support@[Link] 79

Code

C Code 8.1.1 Softlight


If you did not configure I2C, please refer to Chapter 7. If you did, please move on.
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 08.1.1_Softlight directory of C code.
cd ~/Freenove_Kit/Code/C_Code/08.1.1_Softlight
2. Use following command to compile “[Link]” and generate executable file “Softlight”.
g++ [Link] -o Softlight -lwiringPi -lADCDevice
3. Then run the generated file “Softlight”.
sudo ./Softlight

After the program is executed, adjusting the potentiometer will display the voltage values of the
potentiometer in the Terminal window and the converted digital quantity. As a consequence, the brightness
of LED will be changed.

The following is the code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <softPwm.h>
4 #include <[Link]>
5
6 #define ledPin 0
7
8 ADCDevice *adc; // Define an ADC Device class object
9
10 int main(void){
11 adc = new ADCDevice();
12 printf("Program is starting ... \n");
13
14 if(adc->detectI2C(0x48)){ // Detect the pcf8591.
15 delete adc; // Free previously pointed memory
16 adc = new PCF8591(); // If detected, create an instance of PCF8591.
17 }
18 else if(adc->detectI2C(0x4b)){// Detect the ads7830
19 delete adc; // Free previously pointed memory
20 adc = new ADS7830(); // If detected, create an instance of ADS7830.
21 }
22 else{
23 printf("No correct I2C address found, \n"
24 "Please use command 'i2cdetect -y 1' to check the I2C address! \n"
25 "Program Exit. \n");

support@[Link] █
80  support@[Link] [Link] █

26 return -1;
27 }
28 wiringPiSetup();
29 softPwmCreate(ledPin,0,100);
30 while(1){
31 int adcValue = adc->analogRead(0); //read analog value of A0 pin
32 softPwmWrite(ledPin,adcValue*100/255); // Mapping to PWM duty cycle
33 float voltage = (float)adcValue / 255.0 * 3.3; // Calculate voltage
34 printf("ADC value : %d ,\tVoltage : %.2fV\n",adcValue,voltage);
35 delay(30);
36 }
37 return 0;
38 }

In the code, read the ADC value of potentiometer and map it to the duty cycle of PWM to control LED
brightness.
int adcValue = adc->analogRead(0); //read analog value of A0 pin
softPwmWrite(ledPin,adcValue*100/255); // Mapping to PWM duty cycle

█ support@[Link]
█ [Link]  support@[Link] 81

Chapter 9 Potentiometer & RGBLED


In this chapter, we will use 3 potentiometers to control the brightness of 3 LEDs of RGBLED to create multiple
colors.

Project 9.1 Colorful Light

In this project, 3 potentiometers are used to control the RGB LED and in principle it is the same as with the
Soft Light. project. Namely, read the voltage value of the potentiometer and then convert it to PWM used to
control LED brightness. Difference is that the previous soft light project needed only one LED while this one
required (3) RGB LEDs.

Component List

Raspberry Pi x1 Jumper Wires M/M x17


GPIO Extension Board & Ribbon Cable x1
Breadboard x1
Rotary potentiometer x3 ADC module x1 10kΩ x2 220Ω x3 RGB
LEDx1

or

support@[Link] █
82  support@[Link] [Link] █

Circuit with ADS7830

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

If circuit above doesn’t work, please try following wiring.

█ support@[Link]
█ [Link]  support@[Link] 83

Circuit with PCF8591

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]

support@[Link] █
84  support@[Link] [Link] █

Code

C Code 9.1.1 Colorful Softlight


If you did not configure I2C, please refer to Chapter 7. If you did, please continue.
First, observe the project result, and then learn about the code in detail.

If you have any concerns, please contact us via: support@[Link]


1. Use cd command to enter 09.1.1_ColorfulSoftlight directory of C code.
cd ~/Freenove_Kit/Code/C_Code/09.1.1_ColorfulSoftlight
2. Use following command to compile "[Link]" and generate executable file
"ColorfulSoftlight".
g++ [Link] -o ColorfulSoftlight -lwiringPi -lADCDevice
3. Then run the generated file "ColorfulSoftlight".
sudo ./ColorfulSoftlight

After the program is executed, rotate one of the potentiometers, then the color of RGB LED will change. The
Terminal window will display the ADC value of each potentiometer.

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <softPwm.h>
4 #include <[Link]>
5
6 #define ledRedPin 3 //define 3 pins for RGBLED
7 #define ledGreenPin 2
8 #define ledBluePin 0
9
10 ADCDevice *adc; // Define an ADC Device class object
11
12 int main(void){
13 adc = new ADCDevice();
14 printf("Program is starting ... \n");
15
16 if(adc->detectI2C(0x48)){ // Detect the pcf8591.
17 delete adc; // Free previously pointed memory

█ support@[Link]
█ [Link]  support@[Link] 85

18 adc = new PCF8591(); // If detected, create an instance of PCF8591.


19 }
20 else if(adc->detectI2C(0x4b)){// Detect the ads7830
21 delete adc; // Free previously pointed memory
22 adc = new ADS7830(); // If detected, create an instance of ADS7830.
23 }
24 else{
25 printf("No correct I2C address found, \n"
26 "Please use command 'i2cdetect -y 1' to check the I2C address! \n"
27 "Program Exit. \n");
28 return -1;
29 }
30 wiringPiSetup();
31 softPwmCreate(ledRedPin,0,100); //creat 3 PMW output pins for RGBLED
32 softPwmCreate(ledGreenPin,0,100);
33 softPwmCreate(ledBluePin,0,100);
34 while(1){
35 int val_Red = adc->analogRead(0); //read analog value of 3 potentiometers
36 int val_Green = adc->analogRead(1);
37 int val_Blue = adc->analogRead(2);
38 softPwmWrite(ledRedPin,val_Red*100/255); //map the read value of potentiometers
into PWM value and output it
39 softPwmWrite(ledGreenPin,val_Green*100/255);
40 softPwmWrite(ledBluePin,val_Blue*100/255);
41 //print out the read ADC value
42 printf("ADC value val_Red: %d ,\tval_Green: %d ,\tval_Blue: %d
43 \n",val_Red,val_Green,val_Blue);
44 delay(100);
45 }
46 return 0;
47 }

In the code you can read the ADC values of the 3 potentiometers and map it into a PWM duty cycle to control
the 3 LED elements to vary the color of their respective RGB LED.

support@[Link] █
86  support@[Link] [Link] █

Chapter 10 Photoresistor & LED


In this chapter, we will learn how to use a photoresistor to make an automatic dimming nightlight.

Project 10.1 NightLamp

A Photoresistor is very sensitive to the amount of light present. We can take advantage of the characteristic
to make a nightlight with the following function. When the ambient light is less (darker environment), the LED
will automatically become brighter to compensate and when the ambient light is greater (brighter
environment) the LED will automatically dim to compensate.

Component List

Raspberry Pi x1 Jumper Wires M/M x15


GPIO Extension Board & Ribbon Cable x1
Breadboard x1
Photoresistor x1 ADC module x1 10kΩ x3 220Ω x1 LED x1

or

█ support@[Link]
█ [Link]  support@[Link] 87

Component knowledge
Photoresistor
A Photoresistor is simply a light sensitive resistor. It is an active component that decreases resistance with
respect to receiving luminosity (light) on the component's light sensitive surface. A Photoresistor’s resistance
value will change in proportion to the ambient light detected. With this characteristic, we can use a
Photoresistor to detect light intensity. The Photoresistor and its electronic symbol are as follows.

The circuit below is used to detect the change of a Photoresistor’s resistance value:

In the above circuit, when a Photoresistor’s resistance vale changes due to a change in light intensity, the
voltage between the Photoresistor and Resistor R1 will also change. Therefore, the intensity of the light can
be obtained by measuring this voltage.

support@[Link] █
88  support@[Link] [Link] █

Circuit with ADS7830

The circuit used is similar to the Soft light project. The only difference is that the input signal of the AIN0 pin
of ADC changes from a Potentiometer to a combination of a Photoresistor and a Resistor.
Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]

█ support@[Link]
█ [Link]  support@[Link] 89

Circuit with PCF8591

The circuit used is similar to the Soft light project. The only difference is that the input signal of the AIN0 pin
of ADC changes from a Potentiometer to a combination of a Photoresistor and a Resistor.
Schematic diagram

Hardware connection

support@[Link] █
90  support@[Link] [Link] █

Code

The code used in this project is identical with what was used in the last chapter.
C Code 10.1.1 Nightlamp
If you did not configure I2C, please refer to Chapter 7. If you did, please continue.
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 10.1.1_Nightlamp directory of C code.
cd ~/Freenove_Kit/Code/C_Code/10.1.1_Nightlamp
2. Use following command to compile “[Link]” and generate executable file “Nightlamp”.
g++ [Link] -o Nightlamp -lwiringPi -lADCDevice
3. Then run the generated file “Nightlamp”.
sudo ./Nightlamp

After the program is executed, if you cover the Photoresistor or increase the light shining on it, the brightness
of the LED changes accordingly. As in previous projects the Terminal window will display the current input
voltage value of ADC module A0 pin and the converted digital quantity.
The following is the program code:
1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <softPwm.h>
4 #include <[Link]>
5
6 #define ledPin 0
7
8 ADCDevice *adc; // Define an ADC Device class object
9
10 int main(void){
11 adc = new ADCDevice();
12 printf("Program is starting ... \n");
13
14 if(adc->detectI2C(0x48)){ // Detect the pcf8591.
15 delete adc; // Free previously pointed memory
16 adc = new PCF8591(); // If detected, create an instance of PCF8591.
17 }
18 else if(adc->detectI2C(0x4b)){// Detect the ads7830
19 delete adc; // Free previously pointed memory
20 adc = new ADS7830(); // If detected, create an instance of ADS7830.
21 }
22 else{
23 printf("No correct I2C address found, \n"
24 "Please use command 'i2cdetect -y 1' to check the I2C address! \n"
25 "Program Exit. \n");

█ support@[Link]
█ [Link]  support@[Link] 91

26 return -1;
27 }
28 wiringPiSetup();
29 softPwmCreate(ledPin,0,100);
30 while(1){
31 int value = adc->analogRead(0); //read analog value of A0 pin
32 softPwmWrite(ledPin,value*100/255);
33 float voltage = (float)value / 255.0 * 3.3; // calculate voltage
34 printf("ADC value : %d ,\tVoltage : %.2fV\n",value,voltage);
35 delay(100);
36 }
37 return 0;
38 }

support@[Link] █
92  support@[Link] [Link] █

Chapter 11 Thermistor
In this chapter, we will learn about Thermistors which are another kind of Resistor.

Project 11.1 Thermometer

A Thermistor is a type of Resistor whose resistance value is dependent on temperature and changes in
temperature. Therefore, we can take advantage of this characteristic to make a Thermometer.

Component List

Raspberry Pi x1 Jumper Wire M/M x14


GPIO Extension Board & Ribbon Cable x1
Breadboard x1
Thermistor x1 ADC module x1 Resistor 10kΩ x3

or

Component knowledge

Thermistor
Thermistor is a temperature sensitive resistor. When it senses a change in temperature, the resistance of the
Thermistor will change. We can take advantage of this characteristic by using a Thermistor to detect
temperature intensity. A Thermistor and its electronic symbol are shown below.

█ support@[Link]
█ [Link]  support@[Link] 93

The relationship between resistance value and temperature of a thermistor is:


Rt=R*EXP [B*(1/T2-1/T1)]
Where:
Rt is the thermistor resistance under T2 temperature;
R is in the nominal resistance of thermistor under T1 temperature;
EXP[n] is nth power of e;
B is for thermal index;
T1, T2 is Kelvin temperature (absolute temperature). Kelvin temperature=273.15 + Celsius temperature.
For the parameters of the Thermistor, we use: B=3950, R=10k, T1=25.
The circuit connection method of the Thermistor is similar to photoresistor, as the following:

We can use the value measured by the ADC converter to obtain the resistance value of Thermistor, and then
we can use the formula to obtain the temperature value.
Therefore, the temperature formula can be derived as:
T2 = 1/(1/T1 + ln(Rt/R)/B)

support@[Link] █
94  support@[Link] [Link] █

Circuit with ADS7830

The circuit of this project is similar to the one in last chapter. The only difference is that the Photoresistor is
replaced by the Thermistor.
Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Thermistor has longer pins than the one shown in circuit.

Video: [Link]

█ support@[Link]
█ [Link]  support@[Link] 95

Circuit with PCF8591

The circuit of this project is similar to the one in the last chapter. The only difference is that the Photoresistor
is replaced by the Thermistor.
Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Thermistor has longer pins than the one shown in circuit.

support@[Link] █
96  support@[Link] [Link] █

Code

In this project code, the ADC value still needs to be read, but the difference here is that a specific formula is
used to calculate the temperature value.
C Code 11.1.1 Thermometer
If you did not configure I2C, please refer to Chapter 7. If you did, please continue.
First, observe the project result, and then learn about the code in detail.

If you have any concerns, please contact us via: support@[Link]


1. Use cd command to enter 11.1.1_Thermometer directory of C code.
cd ~/Freenove_Kit/Code/C_Code/11.1.1_Thermometer
2 Use following command to compile “[Link]” and generate executable file “Thermometer”.
g++ [Link] -o Thermometer -lwiringPi -lADCDevice
3 Then run the generated file “Thermometer”.
sudo ./Thermometer

After the program is executed, the Terminal window will display the current ADC value, voltage value and
temperature value. Try to “pinch” the thermistor (without touching the leads) with your index finger and thumb
for a brief time, you should see that the temperature value increases.

The following is the code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <math.h>
4 #include <[Link]>
5
6 ADCDevice *adc; // Define an ADC Device class object
7
8 int main(void){
9 adc = new ADCDevice();
10 printf("Program is starting ... \n");

█ support@[Link]
█ [Link]  support@[Link] 97

11
12 if(adc->detectI2C(0x48)){ // Detect the pcf8591.
13 delete adc; // Free previously pointed memory
14 adc = new PCF8591(); // If detected, create an instance of PCF8591.
15 }
16 else if(adc->detectI2C(0x4b)){// Detect the ads7830
17 delete adc; // Free previously pointed memory
18 adc = new ADS7830(); // If detected, create an instance of ADS7830.
19 }
20 else{
21 printf("No correct I2C address found, \n"
22 "Please use command 'i2cdetect -y 1' to check the I2C address! \n"
23 "Program Exit. \n");
24 return -1;
25 }
26 printf("Program is starting ... \n");
27 while(1){
28 int adcValue = adc->analogRead(0); //read analog value A0 pin
29 float voltage = (float)adcValue / 255.0 * 3.3; // calculate voltage
30 float Rt = 10 * voltage / (3.3 - voltage); //calculate resistance value of thermistor
31 float tempK = 1/(1/(273.15 + 25) + log(Rt/10)/3950.0);//calculate temperature (Kelvin)
32 float tempC = tempK -273.15; //calculate temperature (Celsius)
33 printf("ADC value : %d ,\tVoltage : %.2fV,
34 \tTemperature : %.2fC\n",adcValue,voltage,tempC);
35 delay(100);
36 }
37 return 0;
38 }

In the code, the ADC value of ADC module A0 port is read, and then calculates the voltage and the resistance
of Thermistor according to Ohms Law. Finally, it calculates the temperature sensed by the Thermistor,
according to the formula.

support@[Link] █
98  support@[Link] [Link] █

Chapter 12 Joystick
In an earlier chapter, we learned how to use Rotary Potentiometer. We will now learn about joysticks, which
are electronic modules that work on the same principle as the Rotary Potentiometer.

Project 12.1 Joystick

In this project, we will read the output data of a joystick and display it to the Terminal screen.

Component List

Raspberry Pi x1 Jumper x18


GPIO Extension Board & Ribbon Cable x1
Breadboard x1
Joystick x1 ADC module x1 Resistor
10kΩ x3

or

█ support@[Link]
█ [Link]  support@[Link] 99

Component knowledge

Joystick
A Joystick is a kind of input sensor used with your fingers. You should be familiar with this concept already as
they are widely used in gamepads and remote controls. It can receive input on two axes (Y and or X) at the
same time (usually used to control direction on a two dimensional plane). And it also has a third direction
capability by pressing down (Z axis/direction).

X
Y

This is accomplished by incorporating two rotary potentiometers inside the Joystick Module at 90 degrees of
each other, placed in such a manner as to detect shifts in direction in two directions simultaneously and with
a Push Button Switch in the “vertical” axis, which can detect when a User presses on the Joystick.

When the Joystick data is read, there are some differences between the axes: data of X and Y axes is analog,
which needs to use the ADC. The data of the Z axis is digital, so you can directly use the GPIO to read this
data or you have the option to use the ADC to read this.

support@[Link] █
100  support@[Link] [Link] █

Circuit with ADS7830

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]

█ support@[Link]
█ [Link]  support@[Link] 101

Circuit with PCF8591

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

support@[Link] █
102  support@[Link] [Link] █

Code

In this project’s code, we will read the ADC values of X and Y axes of the Joystick, and read digital quality of
the Z axis, then display these out in Terminal.
C Code 12.1.1 Joystick
If you did not configure I2C, please refer to Chapter 7. If you did, please continue.
First, observe the project result, and then learn about the code in detail.

If you have any concerns, please contact us via: support@[Link]


1. Use cd command to enter 12.1.1_Joystick directory of C code.
cd ~/Freenove_Kit/Code/C_Code/12.1.1_Joystick
2. Use following command to compile "[Link]" and generate executable file "Joystick".
g++ [Link] -o Joystick -lwiringPi -lADCDevice
3. Then run the generated file "Joystick".
sudo ./Joystick

After the program is executed, the terminal window will display the data of 3 axes X, Y and Z. Shifting (moving)
the Joystick or pressing it down will make the data change.

The flowing is the code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <softPwm.h>
4 #include <[Link]>
5
6 #define Z_Pin 1 //define pin for axis Z
7
8 ADCDevice *adc; // Define an ADC Device class object
9
10 int main(void){
11 adc = new ADCDevice();
12 printf("Program is starting ... \n");
13

█ support@[Link]
█ [Link]  support@[Link] 103

14 if(adc->detectI2C(0x48)){ // Detect the pcf8591.


15 delete adc; // Free previously pointed memory
16 adc = new PCF8591(); // If detected, create an instance of PCF8591.
17 }
18 else if(adc->detectI2C(0x4b)){// Detect the ads7830
19 delete adc; // Free previously pointed memory
20 adc = new ADS7830(); // If detected, create an instance of ADS7830.
21 }
22 else{
23 printf("No correct I2C address found, \n"
24 "Please use command 'i2cdetect -y 1' to check the I2C address! \n"
25 "Program Exit. \n");
26 return -1;
27 }
28 wiringPiSetup();
29 pinMode(Z_Pin,INPUT); //set Z_Pin as input pin and pull-up mode
30 pullUpDnControl(Z_Pin,PUD_UP);
31 while(1){
32 int val_Z = digitalRead(Z_Pin); //read digital value of axis Z
33 int val_Y = adc->analogRead(0); //read analog value of axis X and Y
34 int val_X = adc->analogRead(1);
35 printf("val_X: %d ,\tval_Y: %d ,\tval_Z: %d \n",val_X,val_Y,val_Z);
36 delay(100);
37 }
38 return 0;
39 }

In the code, configure Z_Pin to pull-up input mode. In the while loop of the main function, use analogRead
() to read the value of axes X and Y and use digitalRead () to read the value of axis Z, then display them.
while(1){
int val_Z = digitalRead(Z_Pin); //read digital value of axis Z
int val_Y = adc->analogRead(0); //read analog value of axis X and Y
int val_X = adc->analogRead(1);
printf("val_X: %d ,\tval_Y: %d ,\tval_Z: %d \n",val_X,val_Y,val_Z);
delay(100);
}

support@[Link] █
104  support@[Link] [Link] █

Chapter 13 Motor & Driver


In this chapter, we will learn about DC Motors and DC Motor Drivers and how to control the speed and
direction of a DC Motor.

Project 13.1 Control a DC Motor with a Potentiometer

In this project, a potentiometer will be used to control a DC Motor. When the Potentiometer is at the midpoint
position, the DC Motor will STOP, and when the Potentiometer is turned in either direction of this midpoint,
the DC Motor speed increases until it reached the endpoint where the DC Motor achieves its maximum speed.
When the Potentiometer is turned “Left” of the midpoint the DC Motor will ROTATE in one direction and when
turned “Right” the DC Motor will ROTATE in the opposite direction.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper Wires x23


GPIO Extension Board & Ribbon Cable x1
Breadboard x1
Breadboard Power Module x1 9V Battery (you provide) & 9V Battery Cable

Rotary DC Motor x1 10kΩ x2 ADC Module x1 L293D


Potentiometer x1 IC Chip

or

█ support@[Link]
█ [Link]  support@[Link] 105

Component knowledge

Breadboard Power Module


Breadboard Power Module is an independent circuit board, which can provide independent 5V or 3.3V power
to the breadboard when building circuits. It also has built-in power protection to avoid damaging your RPi
module. The schematic diagram below identifies the important features of this Power Module:

Power LED
Power Switch
In
Power Jack USB Output Port

Output voltage selection Output voltage selection

Output port for power Output port for power

Here is an acceptable connection between Breadboard Power Module and Breadboard using a 9V battery
and the provided power harness:

support@[Link] █
106  support@[Link] [Link] █

DC Motor
DC Motor is a device that converts electrical energy into mechanical energy. DC Motors consist of two major
parts, a Stator and the Rotor. The stationary part of a DC Motor is the Stator and the part that Rotates is the
Rotor. The Stator is usually part of the outer case of motor (if it is simply a pair of permanent magnets), and
it has terminals to connect to the power if it is made up of electromagnet coils. Most Hobby DC Motors only
use Permanent Magnets for the Stator Field. The Rotor is usually the shaft of motor with 3 or more
electromagnets connected to a commutator where the brushes (via the terminals 1 & 2 below) supply
electrical power, which can drive other mechanical devices. The diagram below shows a small DC Motor with
two terminal pins.

When a DC Motor is connected to a power supply, it will rotate in one direction. If you reverse the polarity of
the power supply, the DC Motor will rotate in opposite direction. This is important to note.

+ - - +
L293D
L293D is an IC Chip (Integrated Circuit Chip) with a 4-channel motor drive. You can drive a Unidirectional DC
Motor with 4 ports or a Bi-Directional DC Motor with 2 ports or a Stepper Motor (Stepper Motors are covered
later in this Tutorial).

█ support@[Link]
█ [Link]  support@[Link] 107

Port description of L293D module is as follows:


Pin name Pin number Description
In x 2, 7, 10, 15 Channel x digital signal input pin
Out x 3, 6, 11, 14 Channel x output pin, input high or low level according to In x pin, gets
connected to +Vmotor or 0V
Enable1 1 Channel 1 and Channel 2 enable pin, high level enable
Enable2 9 Channel 3 and Channel 4 enable pin, high level enable
0V 4, 5, 12, 13 Power Cathode (GND)
+V 16 Positive Electrode (VCC) of power supply, supply voltage 4.5~36V
+Vmotor 8 Positive Electrode of load power supply, provide power supply for the Out
pin x, the supply voltage is +V~36V
For more details, please see the datasheet for this IC Chip.
When using the L293D to drive a DC Motor, there are usually two connection options.
The following connection option uses one channel of the L239D, which can control motor speed through
the PWM, However the motor then can only rotate in one direction.

The following connection uses two channels of the L239D: one channel outputs the PWM wave, and the other
channel connects to GND. Therefore, you can control the speed of the motor. When these two channel signals
are exchanged, not only controls the speed of motor, but also can control the direction of the motor.

GND

GND

In practical use the motor is usually connected to channel 1 and by outputting different levels to in1 and in2
to control the rotational direction of the motor, and output to the PWM wave to Enable1 port to control the
motor’s rotational speed. If the motor is connected to channel 3 and 4 by outputting different levels to in3
and in4 to control the motor's rotation direction, and output to the PWM wave to Enable2 pin to control the
motor’s rotational speed.

support@[Link] █
108  support@[Link] [Link] █

Circuit with ADS7830

Use caution when connecting this circuit because the DC Motor is a high-power component. Do not use the
power provided by the RPi to power the motor directly, as this may cause permanent damage to your
RPi! The logic circuit can be powered by the RPi’s power or an external power supply, which should share a
common ground with RPi.
Schematic diagram

█ support@[Link]
█ [Link]  support@[Link] 109

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Change the Jumper


Position to Change the
F/M Jumper Wire x2
Motor’s Supply Voltage
(3.3V or 5V)

Select OFF

Press power switch when using.

Video: [Link]

support@[Link] █
110  support@[Link] [Link] █

Circuit with PCF8591

Use caution when connecting this circuit because the DC Motor is a high-power component. Do not use the
power provided by the RPi to power the motor directly, as this may cause permanent damage to your
RPi! The logic circuit can be powered by the RPi’s power or an external power supply, which should share a
common ground with RPi.
Schematic diagram

█ support@[Link]
█ [Link]  support@[Link] 111

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Change the Jumper


F/M Jumper Wire x2 Position to Change the
Motor’s Supply Voltage
(3.3V or 5V)

Select OFF

The Power Switch

support@[Link] █
112  support@[Link] [Link] █

Code

In code for this project, first read the ADC value and then control the rotation direction and speed of the DC
Motor according to the value of the ADC.
C Code 13.1.1 Motor
If you did not configure I2C, please refer to Chapter 7. If you did, please continue.
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 13.1.1_Motor directory of the C code.
cd ~/Freenove_Kit/Code/C_Code/13.1.1_Motor
2. Use the following command to compile “[Link]” and generate the executable file “Motor”.
g++ [Link] -o Motor -lwiringPi -lADCDevice
3. Then run the generated file ”Motor”.
sudo ./Motor
After the program is executed, you can use the Potentiometer to control the DC Motor. When the
Potentiometer is at the midpoint position, the DC Motor will STOP, and when the Potentiometer is turned in
either direction of this midpoint, the DC Motor speed increases until it reaches the endpoint where the DC
Motor achieves its maximum speed. When the Potentiometer is turned “Left” of the midpoint the DC Motor
will ROTATE in one direction and when turned “Right” the DC Motor will ROTATE in the opposite direction.
You will also see the ADC value of the potentiometer displayed in the Terminal with the motor direction and
the PWM duty cycle used to control the DC Motor’s speed.

The following is the code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <softPwm.h>
4 #include <math.h>
5 #include <stdlib.h>
6 #include <[Link]>
7

█ support@[Link]
█ [Link]  support@[Link] 113

8 #define motorPin1 2 //define the pin connected to L293D


9 #define motorPin2 0
10 #define enablePin 3
11
12 ADCDevice *adc; // Define an ADC Device class object
13
14 //Map function: map the value from a range to another range.
15 long map(long value,long fromLow,long fromHigh,long toLow,long toHigh){
16 return (toHigh-toLow)*(value-fromLow) / (fromHigh-fromLow) + toLow;
17 }
18 //motor function: determine the direction and speed of the motor according to the ADC
19 void motor(int ADC){
20 int value = ADC -128;
21 if(value>0){
22 digitalWrite(motorPin1,HIGH);
23 digitalWrite(motorPin2,LOW);
24 printf("turn Forward...\n");
25 }
26 else if (value<0){
27 digitalWrite(motorPin1,LOW);
28 digitalWrite(motorPin2,HIGH);
29 printf("turn Back...\n");
30 }
31 else {
32 digitalWrite(motorPin1,LOW);
33 digitalWrite(motorPin2,LOW);
34 printf("Motor Stop...\n");
35 }
36 softPwmWrite(enablePin,map(abs(value),0,128,0,100));
37 printf("The PWM duty cycle is %d%%\n",abs(value)*100/127);//print the PMW duty cycle
38 }
39 int main(void){
40 adc = new ADCDevice();
41 printf("Program is starting ... \n");
42
43 if(adc->detectI2C(0x48)){ // Detect the pcf8591.
44 delete adc; // Free previously pointed memory
45 adc = new PCF8591(); // If detected, create an instance of PCF8591.
46 }
47 else if(adc->detectI2C(0x4b)){// Detect the ads7830
48 delete adc; // Free previously pointed memory
49 adc = new ADS7830(); // If detected, create an instance of ADS7830.
50 }
51 else{

support@[Link] █
114  support@[Link] [Link] █

52 printf("No correct I2C address found, \n"


53 "Please use command 'i2cdetect -y 1' to check the I2C address! \n"
54 "Program Exit. \n");
55 return -1;
56 }
57 wiringPiSetup();
58 pinMode(enablePin,OUTPUT);//set mode for the pin
59 pinMode(motorPin1,OUTPUT);
60 pinMode(motorPin2,OUTPUT);
61 softPwmCreate(enablePin,0,100);//define PMW pin
62 while(1){
63 int value = adc->analogRead(0); //read analog value of A0 pin
64 printf("ADC value : %d \n",value);
65 motor(value); //make the motor rotate with speed(analog value of A0 pin)
66 delay(100);
67 }
68 return 0;
69 }

Now that we have familiarity with reading ADC values, let’s learn the subfunction void motor (int ADC): first,
compare the ADC value with 128 (value corresponding to midpoint). When the current ADC value is higher,
motoRPin1 outputs high level and motoRPin2 outputs low level to control the DC Motor to run in the “Forward”
Rotational Direction. When the current ADC value is lower, motoRPin1 outputs low level and motoRPin2
outputs high level to control the DC Motor to run in the “Reverse” Rotational Direction. When the ADC value
is equal to 128, motoRPin1 and motoRPin2 output low level, the motor STOPS. Then determine the PWM
duty cycle according to the difference (delta) between ADC value and 128. Because the absolute delta value
stays within 0-128, we need to use the map() subfunction mapping the delta value to a range of 0-255. Finally,
we see a display of the duty cycle in Terminal.
void motor(int ADC){
int value = ADC -128;
if(value>0){
digitalWrite(motoRPin1,HIGH);
digitalWrite(motoRPin2,LOW);
printf("turn Forward...\n");
}
else if (value<0){
digitalWrite(motoRPin1,LOW);
digitalWrite(motoRPin2,HIGH);
printf("turn Backward...\n");
}
else {
digitalWrite(motoRPin1,LOW);
digitalWrite(motoRPin2,LOW);
printf("Motor Stop...\n");

█ support@[Link]
█ [Link]  support@[Link] 115

}
softPwmWrite(enablePin,map(abs(value),0,128,0,100));
printf("The PWM duty cycle is %d%%\n",abs(value)*100/127);// print out PWM duty cycle.
}

support@[Link] █
116  support@[Link] [Link] █

Chapter 14 Relay & Motor


In this chapter, we will learn a kind of special switch module, Relay Module.

Project 14.1.1 Relay & Motor

In this project, we will use a Push Button Switch indirectly to control the DC Motor via a Relay.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper Wire x11


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1

9V battery (prepared by yourself) & battery line

Breadboard Power module x1 Resistor 10kΩ x2 Resistor 1kΩ x1 Resistor 220Ω x1

NPN Relay x1 Motor x1 Push button x1 LED x1 Diode x1


transistor x1

█ support@[Link]
█ [Link]  support@[Link] 117

Component knowledge

Relay
Relays are a type of Switch that open and close circuits electromechanically or electronically. Relays control
one electrical circuit by opening and closing contacts in another circuit using an electromagnet to initiate the
Switch action. When the electromagnet is energized (powered), it will attract internal contacts completing a
circuit, which act as a Switch. Many times Relays are used to allow a low powered circuit (and a small low
amperage switch) to safely turn ON a larger more powerful circuit. They are commonly found in automobiles,
especially from the ignition to the starter motor.
The following is a basic diagram of a common Relay and the image and circuit symbol diagram of the 5V
relay used in this project:
Diagram Feature: Symbol

Pin 5 and pin 6 are internally connected to each other. When the coil pin3 and pin 4 are connected to a 5V
power supply, pin 1 will be disconnected from pins 5 & 6 and pin 2 will be connected to pins 5 & 6. Pin 1 is
called Closed End and pin 2 is called the Open End.
Inductor
The symbol of Inductance is “L” and the unit of inductance is the “Henry” (H). Here is an example of how this
can be encountered: 1H=1000mH, 1mH=1000μH.
An Inductor is a passive device that stores energy in its Magnetic Field and returns energy to the circuit
whenever required. An Inductor is formed by a Cylindrical Core with many Turns of conducting wire (usually
copper wire). Inductors will hinder the changing current passing through it. When the current passing through
the Inductor increases, it will attempt to hinder the increasing movement of current; and when the current
passing through the inductor decreases, it will attempt to hinder the decreasing movement of current. So the
current passing through an Inductor is not transient.

The circuit for a Relay is as follows: The coil of Relay can be equivalent to an Inductor, when a Transistor is
present in this coil circuit it can disconnect the power to the relay, the current in the Relay’s coil does not stop
immediately, which affects the power supply adversely. To remedy this, diodes in parallel are placed on both
ends of the Relay coil pins in opposite polar direction. Having the current pass through the diodes will avoid
any adverse effect on the power supply.

support@[Link] █
118  support@[Link] [Link] █

Circuit

Use caution with the power supply voltage needed for the components in this circuit. The Relay requires a
power supply voltage of 5V, and the DC Motor only requires 3.3V. Additionally, there is an LED present, which
acts as an indicator (ON or OFF) for the status of the Relay’s active status.

Schematic diagram

█ support@[Link]
█ [Link]  support@[Link] 119

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Press replay

for connection.

3.3V

OFF

Video: [Link]

support@[Link] █
120  support@[Link] [Link] █

Code

The project code is in the same as we used earlier in the Table Lamp project. Pressing the Push Button Switch
activates the transistor. Because the Relay and the LED are connected in parallel, they will be powered ON at
the same time. Press the Push Button Switch again will turn them both OFF.
C Code 14.1.1 Relay
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 14.1.1_Relay directory of C code.
cd ~/Freenove_Kit/Code/C_Code/14.1.1_Relay
2. Use following command to compile "Relay.c" and generate executable file "Relay".
gcc Relay.c -o Relay -lwiringPi
3. Run the generated file "Relay".
sudo ./Relay
After the program is executed, pressing the Push Button Switch activates the Relay (the internal switch is
closed), which powers the DC Motor to rotate and simultaneously powers the LED to turn ON. If you press
the Push Button Switch again, the Relay is deactivated (the internal switch opens), the Motor STOPS and the
LED turns OFF.
The following is the program code:
1 #include <wiringPi.h>
2 #include <stdio.h>
3
4 #define relayPin 0 //define the relayPin
5 #define buttonPin 1 //define the buttonPin
6 int relayState=LOW; //store the State of relay
7 int buttonState=HIGH; //store the State of button
8 int lastbuttonState=HIGH;//store the lastState of button
9 long lastChangeTime; //store the change time of button state
10 long captureTime=50; //set the button state stable time
11 int reading;
12 int main(void)
13 {
14 printf("Program is starting...\n");
15
16 wiringPiSetup();
17
18 pinMode(relayPin, OUTPUT);
19 pinMode(buttonPin, INPUT);
20 pullUpDnControl(buttonPin, PUD_UP); //pull up to high level
21 while(1){
22 reading = digitalRead(buttonPin); //read the current state of button
23 if( reading != lastbuttonState){ //if the button state changed ,record the time
point

█ support@[Link]
█ [Link]  support@[Link] 121

24 lastChangeTime = millis();
25 }
26 //if changing-state of the button last beyond the time we set, we considered that
27 //the current button state is an effective change rather than a buffeting
28 if(millis() - lastChangeTime > captureTime){
29 //if button state is changed, update the data.
30 if(reading != buttonState){
31 buttonState = reading;
32 //if the state is low, the action is pressing.
33 if(buttonState == LOW){
34 printf("Button is pressed!\n");
35 relayState = !relayState;
36 if(relayState){
37 printf("turn on relay ...\n");
38 }
39 else {
40 printf("turn off relay ...\n");
41 }
42 }
43 //if the state is high, the action is releasing.
44 else {
45 printf("Button is released!\n");
46 }
47 }
48 }
49 digitalWrite(relayPin,relayState);
50 lastbuttonState = reading;
51 }
52
53 return 0;
54 }
The project code is in the same as we used earlier in the Table Lamp project.

support@[Link] █
122  support@[Link] [Link] █

Chapter 15 Servo
Previously, we learned how to control the speed and rotational direction of a DC Motor. In this chapter, we
will learn about Servos which are a rotary actuator type motor that can be controlled rotate to specific angles.

Project 15.1 Servo Sweep

First, we need to learn how to make a Servo rotate.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper Wire x3


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
Servo x1

█ support@[Link]
█ [Link]  support@[Link] 123

Component knowledge

Servo
Servo is a compact package which consists of a DC Motor, a set of reduction gears to provide torque, a sensor
and control circuit board. Most Servos only have a 180-degree range of motion via their “horn”. Servos can
output higher torque than a simple DC Motor alone and they are widely used to control motion in model cars,
model airplanes, robots, etc. Servos have three wire leads which usually terminate to a male or female 3-pin
plug. Two leads are for electric power: Positive (2-VCC, Red wire), Negative (3-GND, Brown wire), and the
signal line (1-Signal, Orange wire) as represented in the Servo provided in your Kit.

We will use a 50Hz PWM signal with a duty cycle in a certain range to drive the Servo. The lasting time 0.5ms-
2.5ms of PWM single cycle high level corresponds to the Servo angle 0 degrees - 180 degree linearly. Part of
the corresponding values are as follows:
Note: the lasting time of high level corresponding to the servo angle is absolute instead of accumulating. For
example, the high level time lasting for 0.5ms correspond to the 0 degree of the servo. If the high level time
lasts for another 1ms, the servo rotates to 45 degrees.
High level time Servo angle
0.5ms 0 degree
1ms 45 degree
1.5ms 90 degree
2ms 135 degree
2.5ms 180 degree

When you change the Servo signal value, the Servo will rotate to the designated angle.

support@[Link] █
124  support@[Link] [Link] █

Circuit

Use caution when supplying power to the Servo it should be 5V. Make sure you do not make any errors when
connecting the Servo to the power supply.
Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]

█ support@[Link]
█ [Link]  support@[Link] 125

Code

In this project, we will make a Servo rotate from 0 degrees to 180 degrees and then reverse the direction to
make it rotate from 180 degrees to 0 degrees and repeat these actions in an endless loop.
C Code 15.1.1 Sweep
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 15.1.1_Sweep directory of C code.
cd ~/Freenove_Kit/Code/C_Code/15.1.1_Sweep
2. Use following command to compile "Sweep.c" and generate executable file "Sweep".
gcc Sweep.c -o Sweep -lwiringPi
3. Run the generated file "Sweep".
sudo ./Sweep
After the program is executed, the Servo will rotate from 0 degrees to 180 degrees and then reverse the
direction to make it rotate from 180 degrees to 0 degrees and repeat these actions in an endless loop.
The following is the program code:
1 #include <wiringPi.h>
2 #include <softPwm.h>
3 #include <stdio.h>
4 #define OFFSET_MS 3 //Define the unit of servo pulse offset: 0.1ms
5 #define SERVO_MIN_MS 5+OFFSET_MS //define the pulse duration for minimum angle of servo
6 #define SERVO_MAX_MS 25+OFFSET_MS //define the pulse duration for maximum angle of servo
7
8 #define servoPin 1 //define the GPIO number connected to servo
9 long map(long value,long fromLow,long fromHigh,long toLow,long toHigh){
10 return (toHigh-toLow)*(value-fromLow) / (fromHigh-fromLow) + toLow;
11 }
12 void servoInit(int pin){ //initialization function for servo PMW pin
13 softPwmCreate(pin, 0, 200);
14 }
15 void servoWrite(int pin, int angle){ //Specific a certain rotation angle (0-180) for the
servo
16 if(angle > 180)
17 angle = 180;
18 if(angle < 0)
19 angle = 0;
20 softPwmWrite(pin,map(angle,0,180,SERVO_MIN_MS,SERVO_MAX_MS));
21 }
22 void servoWriteMS(int pin, int ms){ //specific the unit for pulse(5-25ms) with specific
duration output by servo pin: 0.1ms
23 if(ms > SERVO_MAX_MS)
24 ms = SERVO_MAX_MS;
25 if(ms < SERVO_MIN_MS)

support@[Link] █
126  support@[Link] [Link] █

26 ms = SERVO_MIN_MS;
27 softPwmWrite(pin,ms);
28 }
29
30 int main(void)
31 {
32 int i;
33
34 printf("Program is starting ...\n");
35
36 wiringPiSetup();
37 servoInit(servoPin); //initialize PMW pin of servo
38 while(1){
39 for(i=SERVO_MIN_MS;i<SERVO_MAX_MS;i++){ //make servo rotate from minimum angle to
maximum angle
40 servoWriteMS(servoPin,i);
41 delay(10);
42 }
43 delay(500);
44 for(i=SERVO_MAX_MS;i>SERVO_MIN_MS;i--){ //make servo rotate from maximum angle to
minimum angle
45 servoWriteMS(servoPin,i);
46 delay(10);
47 }
48 delay(500);
49 }
50 return 0;
51 }
A 50 Hz pulse for a 20ms cycle is required to control the Servo. In function softPwmCreate (int pin, int
initialValue, int pwmRange), the unit of the third parameter pwmRange is 100US, specifically 0.1ms. In order
to get the PWM with a 20ms cycle, the pwmRange shoulde be set to 200. So in the subfunction of servoInit
(), we create a PWM pin with a pwmRange of 200.
void servoInit(int pin){ //initialization function for servo PWM pin
softPwmCreate(pin, 0, 200);
}

Since 0-180 degrees of the Servo’s motion corresponds to the PWM pulse width of 0.5-2.5ms, with a
PwmRange of 200 ms. We then need the function softPwmWrite (int pin, int value) and the scope 5-25 of
the parameter values to correspond to 0-180 degrees’ motion of the Servo. What’s more, the number written
in subfunction servoWriteMS () should be within the range of 5-25. However, in practice, due to the inherent
error manufactured into each Servo, the pulse width will have a deviation. So we need to define a minimum
and maximum pulse width and an error offset (this is essential in robotics).
#define OFFSET_MS 3 //Define the unit of servo pulse offset: 0.1ms
#define SERVO_MIN_MS 5+OFFSET_MS //define the pulse duration for minimum angle of servo

█ support@[Link]
█ [Link]  support@[Link] 127

#define SERVO_MAX_MS 25+OFFSET_MS //define the pulse duration for maximum angle of servo
……
void servoWriteMS(int pin, int ms){
if(ms > SERVO_MAX_MS)
ms = SERVO_MAX_MS;
if(ms < SERVO_MIN_MS)
ms = SERVO_MIN_MS;
softPwmWrite(pin,ms);
}
In subfunction servoWrite (), directly input an angle value (0-180 degrees), map the angle to the pulse width
and then output it.
void servoWrite(int pin, int angle){ //Specif a certain rotation angle (0-180) for the
servo
if(angle > 180)
angle = 180;
if(angle < 0)
angle = 0;
softPwmWrite(pin,map(angle,0,180,SERVO_MIN_MS,SERVO_MAX_MS));
}
Finally, in the "while" loop of the main function, use two "for" cycle to make servo rotate from 0 degrees to
180 degrees, and then from 180 degrees to 0 degrees.
while(1){
for(i=SERVO_MIN_MS;i<SERVO_MAX_MS;i++){ //make servo rotate from minimum angle to
maximum angle
servoWriteMS(servoPin,i);
delay(10);
}
delay(500);
for(i=SERVO_MAX_MS;i>SERVO_MIN_MS;i--){ //make servo rotate from maximum angle to
minimum angle
servoWriteMS(servoPin,i);
delay(10);
}
delay(500);
}

support@[Link] █
128  support@[Link] [Link] █

Chapter 16 Stepper Motor


Thus far, we have learned about DC Motors and Servos. A DC motor can rotate constantly in on direction but
we cannot control the rotation to a specific angle. On the contrary, a Servo can rotate to a specific angle but
cannot rotate constantly in one direction. In this chapter, we will learn about a Stepper Motor which is also a
type of motor. A Stepper Motor can rotate constantly and also to a specific angle. Using a Stepper Motor can
easily achieve higher accuracies in mechanical motion.

Project 16.1 Stepper Motor

In this project, we will learn how to drive a Stepper Motor, and understand its working principle.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper Wire x12


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
Stepper Motor x1 ULN2003 Stepper Motor Driver x1

9V battery (prepared by yourself) & battery line Breadboard Power module x1

█ support@[Link]
█ [Link]  support@[Link] 129

Component knowledge

Stepper Motor
Stepper Motors are an open-loop control device, which converts an electronic pulse signal into angular
displacement or linear displacement. In a non-overload condition, the speed of the motor and the location
of the stops depends only on the pulse signal frequency and number of pulses and is not affected by changes
in load as with a DC Motor. A small Four-Phase Deceleration Stepper Motor is shown here:

The electronic schematic diagram of a Four-Phase Stepper Motor is shown below:

The outside case or housing of the Stepper Motor is the Stator and inside the Stator is the Rotor. There is a
specific number of individual coils, usually an integer multiple of the number of phases the motor has, when
the Stator is powered ON, an electromagnetic field will be formed to attract a corresponding convex
diagonal groove or indentation in the Rotor’s surface. The Rotor is usually made of iron or a permanent
magnet. Therefore, the Stepper Motor can be driven by powering the coils on the Stator in an ordered
sequence (producing a series of “steps” or stepped movements).

support@[Link] █
130  support@[Link] [Link] █

A common driving sequence is shown here:

In the sequence above, the Stepper Motor rotates by a certain angle at once, which is called a “step”. By
controlling the number of rotational steps, you can then control the Stepper Motor’s rotation angle. By
defining the time between two steps, you can control the Stepper Motor’s rotation speed. When rotating
clockwise, the order of coil powered on is: A → B → C → D → A →…… . And the rotor will rotate in accordance
with this order, step by step, called four-steps, four-part. If the coils is powered ON in the reverse order, D →
C → B → A → D →… , the rotor will rotate in counter-clockwise direction.
There are other methods to control Stepper Motors, such as: connect A phase, then connect A B phase, the
stator will be located in the center of A B, which is called a half-step. This method can improve the stability of
the Stepper Motor and reduces noise. Tise sequence of powering the coils looks like this: A → AB → B → BC
→ C → CD → D → DA → A →……, the rotor will rotate in accordance to this sequence ar, a half-step at a
time, called four-steps, eight-part. Conversely, if the coils are powered ON in the reverse order the Stepper
Motor will rotate in the opposite direction.

The stator in the Stepper Motor we have supplied has 32 magnetic poles. Therefore, to complete one full
revolution requires 32 full steps. The rotor (or output shaft) of the Stepper Motor is connected to a speed
reduction set of gears and the reduction ratio is 1:64. Therefore, the final output shaft (exiting the Stepper
Motor’s housing) requires 32 X 64 = 2048 steps to make one full revolution.

█ support@[Link]
█ [Link]  support@[Link] 131

ULN2003 Stepper Motor driver


A ULN2003 Stepper Motor Driver is used to convert weak signals into more powerful control signals in order
to drive the Stepper Motor. In the illustration below, the input signal IN1-IN4 corresponds to the output signal
A-D, and 4 LEDs are integrated into the board to indicate the state of these signals. The PWR interface can
be used as a power supply for the Stepper Motor. By default, PWR and VCC are connected.

Circuit

When building the circuit, note that rated voltage of the Stepper Motor is 5V, and we need to use the
breadboard power supply independently, (Caution do not use the RPi power supply). Additionally, the
breadboard power supply needs to share Ground with Rpi.

Schematic diagram

support@[Link] █
132  support@[Link] [Link] █

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]

█ support@[Link]
█ [Link]  support@[Link] 133

Code

C Code 16.1.1 SteppingMotor


First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 16.1.1_SteppingMotor directory of C code.
cd ~/Freenove_Kit/Code/C_Code/16.1.1_SteppingMotor
2. Use following command to compile "SteppingMotor.c" and generate executable file "SteppingMotor".
gcc SteppingMotor.c -o SteppingMotor -lwiringPi
3. Run the generated file "SteppingMotor".
sudo ./SteppingMotor
After the program is executed, the Stepper Motor will rotate 360° clockwise and then 360° anticlockwise and
repeat this action in an endless loop.
The following is the program code:
1 #include <stdio.h>
2 #include <wiringPi.h>
3
4 const int motorPins[]={1,4,5,6}; //define pins connected to four phase ABCD of stepper
motor
5 const int CCWStep[]={0x01,0x02,0x04,0x08}; //define power supply order for coil for rotating
anticlockwise
6 const int CWStep[]={0x08,0x04,0x02,0x01}; //define power supply order for coil for rotating
clockwise
7 //as for four phase Stepper Motor, four steps is a cycle. the function is used to drive the
Stepper Motor clockwise or anticlockwise to take four steps
8 void moveOnePeriod(int dir,int ms){
9 int i=0,j=0;
10 for (j=0;j<4;j++){ //cycle according to power supply order
11 for (i=0;i<4;i++){ //assign to each pin, a total of 4 pins
12 if(dir == 1) //power supply order clockwise
13 digitalWrite(motorPins[i],(CCWStep[j] == (1<<i)) ? HIGH : LOW);
14 else //power supply order anticlockwise
15 digitalWrite(motorPins[i],(CWStep[j] == (1<<i)) ? HIGH : LOW);
16 printf("motorPin %d, %d \n",motorPins[i],digitalRead(motorPins[i]));
17 }
18 printf("Step cycle!\n");
19 if(ms<3) //the delay can not be less than 3ms, otherwise it will exceed speed
limit of the motor
20 ms=3;
21 delay(ms);
22 }
23 }
24 //continuous rotation function, the parameter steps specifies the rotation cycles, every four

support@[Link] █
134  support@[Link] [Link] █

steps is a cycle
25 void moveSteps(int dir, int ms, int steps){
26 int i;
27 for(i=0;i<steps;i++){
28 moveOnePeriod(dir,ms);
29 }
30 }
31 void motorStop(){ //function used to stop rotating
32 int i;
33 for(i=0;i<4;i++){
34 digitalWrite(motorPins[i],LOW);
35 }
36 }
37 int main(void){
38 int i;
39
40 printf("Program is starting ...\n");
41
42 wiringPiSetup();
43
44 for(i=0;i<4;i++){
45 pinMode(motorPins[i],OUTPUT);
46 }
47
48 while(1){
49 moveSteps(1,3,512); //rotating 360° clockwise, a total of 2048 steps in a circle,
namely, 512 cycles.
50 delay(500);
51 moveSteps(0,3,512); //rotating 360° anticlockwise
52 delay(500);
53 }
54 return 0;
55 }
In the code we define the four pins of the Stepper Motor and the order to supply power to the coils for a
four-step rotation mode.
const int motorPins[]={1,4,5,6}; //define pins connected to four phase ABCD of stepper
motor
const int CCWStep[]={0x01,0x02,0x04,0x08}; //define power supply order for coil for rotating
anticlockwise
const int CWStep[]={0x08,0x04,0x02,0x01}; //define power supply order for coil for rotating
clockwise
Subfunction moveOnePeriod ((int dir,int ms) will drive the Stepper Motor rotating four-step clockwise or
anticlockwise, four-step as a cycle. Where parameter "dir" indicates the rotation direction, if "dir" is 1, the
servo will rotate clockwise, otherwise it rotates to anticlockwise. Parameter "ms" indicates the time between

█ support@[Link]
█ [Link]  support@[Link] 135

each two steps. The "ms" of Stepper Motor used in this project is 3ms (the shortest time period), a value of
less than 3ms will exceed the limits of the Stepper Motor with a result that it does not rotate.
void moveOnePeriod(int dir,int ms){
int i=0,j=0;
for (j=0;j<4;j++){ //cycle according to power supply order
for (i=0;i<4;i++){ //assign to each pin, a total of 4 pins
if(dir == 1) //power supply order clockwise
digitalWrite(motorPins[i],(CCWStep[j] == (1<<i)) ? HIGH : LOW);
else //power supply order anticlockwise
digitalWrite(motorPins[i],(CWStep[j] == (1<<i)) ? HIGH : LOW);
printf("motorPin %d, %d \n",motorPins[i],digitalRead(motorPins[i]));
}
printf("Step cycle!\n");
if(ms<3) //the delay can not be less than 3ms, otherwise it will exceed speed
limit of the motor
ms=3;
delay(ms);
}
}
Subfunction moveSteps (int dir, int ms, int steps) is used to specific cycle number of Stepper Motor.
void moveSteps(int dir, int ms, int steps){
int i;
for(i=0;i<steps;i++){
moveOnePeriod(dir,ms);
}
}
Subfunction motorStop () is used to stop the Stepper Motor.
void motorStop(){ //function used to stop rotating
int i;
for(i=0;i<4;i++){
digitalWrite(motorPins[i],LOW);
}
}
Finally, in the while loop of main function, rotate one revolution clockwise, and then one revolution
anticlockwise. According to the previous material covered, the Stepper Motor one revolution requires 2048
steps, that is, 2048/4=512 cycle.
while(1){
moveSteps(1,3,512); //rotating 360° clockwise, a total of 2048 steps in a
circle, namely, this function(four steps) will be called 512 times.
delay(500);
moveSteps(0,3,512); //rotating 360° anticlockwise
delay(500);
}

support@[Link] █
136  support@[Link] [Link] █

Chapter 17 74HC595 & Bar Graph LED


We have used LED Bar Graph to make a flowing water light, in which 10 GPIO ports of RPi are occupied. More
GPIO ports mean that more peripherals can be connected to RPi, so GPIO resource is very precious. Can we
make flowing water light with less GPIO ports? In this chapter, we will learn a component, 74HC595, which
can achieve the target.

Project 17.1 Flowing Water Light

Now let us learn how to use the 74HC595 IC Chip to make a flowing water light using less GPIO.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x17


GPIO Extension Board & Ribbon Cable x1
Breadboard x1
74HC595 x1 Bar Graph LED x1 Resistor 220Ω x8

█ support@[Link]
█ [Link]  support@[Link] 137

Component knowledge

74HC595
A 74HC595 chip is used to convert serial data into parallel data. A 74HC595 chip can convert the serial data
of one byte into 8 bits, and send its corresponding level to each of the 8 ports correspondingly. With this
characteristic, the 74HC595 chip can be used to expand the IO ports of a Raspberry Pi. At least 3 ports on the
RPI board are required to control the 8 ports of the 74HC595 chip.

The ports of the 74HC595 chip are described as follows:


Pin name Pin number Description
Q0-Q7 15, 1-7 Parallel Data Output
VCC 16 The Positive Electrode of the Power Supply, the Voltage is 2~6V
GND 8 The Negative Electrode of Power Supply
DS 14 Serial Data Input
OE 13 Enable Output,
When this pin is in high level, Q0-Q7 is in high resistance state
When this pin is in low level, Q0-Q7 is in output mode
ST_CP 12 Parallel Update Output: when its electrical level is rising, it will update the
parallel data output.
SH_CP 11 Serial Shift Clock: when its electrical level is rising, serial data input register
will do a shift.
MR 10 Remove Shift Register: When this pin is in low level, the content in shift
register will be cleared.
Q7' 9 Serial Data Output: it can be connected to more 74HC595 chips in series.
For more details, please refer to the datasheet on the 74HC595 chip.

support@[Link] █
138  support@[Link] [Link] █

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]

█ support@[Link]
█ [Link]  support@[Link] 139

Code

In this project we will make a flowing water light with a 74HC595 chip to learn about its functions.
C Code 17.1.1 LightWater02
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 17.1.1_LightWater02 directory of C code.
cd ~/Freenove_Kit/Code/C_Code/17.1.1_LightWater02
2. Use following command to compile “LightWater02.c” and generate executable file “LightWater02”.
gcc LightWater02.c -o LightWater02 -lwiringPi
3. Then run the generated file “LightWater02”.
sudo ./LightWater02
After the program is executed, you will see that Bar Graph LED starts with the flowing water pattern flashing
from left to right and then back from right to left.
The following is the program code:
1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <wiringShift.h>
4
5 #define dataPin 0 //DS Pin of 74HC595(Pin14)
6 #define latchPin 2 //ST_CP Pin of 74HC595(Pin12)
7 #define clockPin 3 //CH_CP Pin of 74HC595(Pin11)
8
9 void _shiftOut(int dPin,int cPin,int order,int val){
10 int i;
11 for(i = 0; i < 8; i++){
12 digitalWrite(cPin,LOW);
13 if(order == LSBFIRST){
14 digitalWrite(dPin,((0x01&(val>>i)) == 0x01) ? HIGH : LOW);
15 delayMicroseconds(10);
16 }
17 else {//if(order == MSBFIRST){
18 digitalWrite(dPin,((0x80&(val<<i)) == 0x80) ? HIGH : LOW);
19 delayMicroseconds(10);
20 }
21 digitalWrite(cPin,HIGH);
22 delayMicroseconds(10);
23 }
24 }
25
26 int main(void)
27 {
28 int i;

support@[Link] █
140  support@[Link] [Link] █

29 unsigned char x;
30
31 printf("Program is starting ...\n");
32
33 wiringPiSetup();
34
35 pinMode(dataPin,OUTPUT);
36 pinMode(latchPin,OUTPUT);
37 pinMode(clockPin,OUTPUT);
38 while(1){
39 x=0x01;
40 for(i=0;i<8;i++){
41 digitalWrite(latchPin,LOW); // Output low level to latchPin
42 _shiftOut(dataPin,clockPin,LSBFIRST,x);// Send serial data to 74HC595
43 digitalWrite(latchPin,HIGH); //Output high level to latchPin, and 74HC595 will
update the data to the parallel output port.
44 x<<=1; //make the variable move one bit to left once, then the bright LED
move one step to the left once.
45 delay(100);
46 }
47 x=0x80;
48 for(i=0;i<8;i++){
49 digitalWrite(latchPin,LOW);
50 _shiftOut(dataPin,clockPin,LSBFIRST,x);
51 digitalWrite(latchPin,HIGH);
52 x>>=1;
53 delay(100);
54 }
55 }
56 return 0;
57 }
In the code, we configure three pins to control the 74HC595 chip and define a one-byte variable to control
the state of the 8 LEDs (in the Bar Graph LED Module) through the 8 bits of the variable. The LEDs light ON
when the corresponding bit is 1. If the variable is assigned to 0x01, that is 00000001 in binary, there will be
only one LED ON.
x=0x01;
In the “while” cycle of main function, use two cycles to send x to 74HC595 output pin to control the LED. In
one cycle, x will shift one bit to the LEFT in one cycle, then when data of x is sent to 74HC595, the LED that is
turned ON will move one bit to the LEFT once.
for(i=0;i<8;i++){
digitalWrite(latchPin,LOW); // Output low level to latchPin
_shiftOut(dataPin,clockPin,LSBFIRST,x);// Send serial data to 74HC595
digitalWrite(latchPin,HIGH); // Output high level to latchPin, and 74HC595 will
update the data to the parallel output port.

█ support@[Link]
█ [Link]  support@[Link] 141

x<<=1; // make the variable move one bit to left once, then the bright LED move
one step to the left once.
delay(100);
}

In second cycle, the situation is the same. The difference is that x is shift from 0x80 to the RIGHT in order.
<< operator
"<<" is the left shift operator, which can make all bits of 1 byte shift by several bits to the left (high) direction
and add 0 on the right (low). For example, shift binary 00000001 by 1 bit to left:
byte x = 1 << 1;
← ← ← ← ← ← ←
← 0 0 0 0 0 0 0 1 ← 0
The result of x is 2(binary 00000010).
0 0 0 0 0 0 1 0

There is another similar operator" >>". For example, shift binary 00000001 by 1 bit to right:
byte x = 1 >> 1;
→ → → → → → →
0 → 0 0 0 0 0 0 0 1 →
The result of x is 0(00000000).
0 0 0 0 0 0 0 0

X <<= 1 is equivalent to x = x << 1 and x >>= 1 is equivalent to x = x >> 1


About shift function
uint8_t shiftIn (uint8_t dPin, uint8_t cPin, uint8_t order) ;
This is used to shift an 8-bit data value in with the data appearing on the dPin and the clock being sent out
on the cPin. Order is either LSBFIRST or MSBFIRST. The data is sampled after the cPin goes high. (So cPin
high, sample data, cPin low, repeat for 8 bits) The 8-bit value is returned by the function.
void shiftOut (uint8_t dPin, uint8_t cPin, uint8_t order, uint8_t val) ;
void _shiftOut (uint8_t dPin, uint8_t cPin, uint8_t order, uint8_t val) ;
This is used to shift an 8-bit data value out with the data being sent out on dPin and the clock being sent
out on the cPin. order is as above. Data is clocked out on the rising or falling edge - ie. dPin is set, then
cPin is taken high then low - repeated for the 8 bits.
For more details about shift function, please refer to: [Link]

support@[Link] █
142  support@[Link] [Link] █

Chapter 18 74HC595 & 7-Segment Display


In this chapter, we will introduce the 7-Segment Display.

Project 18.1 7-Segment Display

We will use a 74HC595 IC Chip to control a 7-Segment Display and make it display sixteen decimal characters
"0” to “F".

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper Wire x18


GPIO Extension Board & Ribbon Cable x1
Breadboard x1
74HC595 x1 7-Segment Display x1 Resistor 220Ω x8

█ support@[Link]
█ [Link]  support@[Link] 143

Component knowledge

7-segment display
A 7-Segment Display is a digital electronic display device. There is a figure "8" and a decimal point represented,
which consists of 8 LEDs. The LEDs have a Common Anode and individual Cathodes. Its internal structure and
pin designation diagram is shown below:

As we can see in the above circuit diagram, we can control the state of each LED separately. Also, by combining
LEDs with different states of ON and OFF, we can display different characters (Numbers and Letters). For
example, to display a “0”: we need to turn ON LED segments A, B, C, D, E and F, and turn OFF LED segments
G and DP.

In this project, we will use a 7-Segment Display with a Common Anode. Therefore, when there is an input low
level to an LED segment the LED will turn ON. Defining segment “A” as the lowest level and segment “DP” as
the highest level, from high to low would look like this: “DP”, “G”, “F”, “E”, “D”, “C”, “B”, “A”. Character "0"
corresponds to the code: 1100 0000b=0xc0.

support@[Link] █
144  support@[Link] [Link] █

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]

█ support@[Link]
█ [Link]  support@[Link] 145

Code

This code uses a 74HC595 IC Chip to control the 7-Segment Display. The use of the 74HC595 IC Chip is
generally the same throughout this Tutorial. We need code to display the characters “0” to “F” one character
at a time, and then output to display them with the 74HC595 IC Chip.
C Code 18.1.1 SevenSegmentDisplay
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 18.1.1_SevenSegmentDisplay directory of C code.
cd ~/Freenove_Kit/Code/C_Code/18.1.1_SevenSegmentDisplay
2. Use following command to compile “SevenSegmentDisplay.c” and generate executable file
“SevenSegmentDisplay”.
gcc SevenSegmentDisplay.c -o SevenSegmentDisplay -lwiringPi
3. Then run the generated file “SevenSegmentDisplay”.
sudo ./SevenSegmentDisplay
After the program is executed, the 7-Segment Display starts to display the characters “0” to “F” in succession.
The following is the program code:
1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <wiringShift.h>
4
5 #define dataPin 0 //DS Pin of 74HC595(Pin14)
6 #define latchPin 2 //ST_CP Pin of 74HC595(Pin12)
7 #define clockPin 3 //CH_CP Pin of 74HC595(Pin11)
8 //encoding for character 0-F of common anode SevenSegmentDisplay.
9 unsigned char
10 num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
11
12 void _shiftOut(int dPin,int cPin,int order,int val){
13 int i;
14 for(i = 0; i < 8; i++){
15 digitalWrite(cPin,LOW);
16 if(order == LSBFIRST){
17 digitalWrite(dPin,((0x01&(val>>i)) == 0x01) ? HIGH : LOW);
18 delayMicroseconds(10);
19 }
20 else {//if(order == MSBFIRST){
21 digitalWrite(dPin,((0x80&(val<<i)) == 0x80) ? HIGH : LOW);
22 delayMicroseconds(10);
23 }
24 digitalWrite(cPin,HIGH);
25 delayMicroseconds(10);
26 }

support@[Link] █
146  support@[Link] [Link] █

27 }
28
29 int main(void)
30 {
31 int i;
32
33 printf("Program is starting ...\n");
34
35 wiringPiSetup();
36
37 pinMode(dataPin,OUTPUT);
38 pinMode(latchPin,OUTPUT);
39 pinMode(clockPin,OUTPUT);
40 while(1){
41 for(i=0;i<sizeof(num);i++){
42 digitalWrite(latchPin,LOW);
43 _shiftOut(dataPin,clockPin,MSBFIRST,num[i]);//Output the figures and the highest
level is transfered preferentially.
44 digitalWrite(latchPin,HIGH);
45 delay(500);
46 }
47 for(i=0;i<sizeof(num);i++){
48 digitalWrite(latchPin,LOW);
49 _shiftOut(dataPin,clockPin,MSBFIRST,num[i] & 0x7f);//Use the "&0x7f" to display
the decimal point.
50 digitalWrite(latchPin,HIGH);
51 delay(500);
52 }
53 }
54 return 0;
55 }
First, we need to create encoding for characters “0” to “F” in the array.
unsigned char
num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
In the “for” loop of loop() function, use the 74HC595 IC Chip to output contents of array “num” successively.
SevenSegmentDisplay can then correctly display the corresponding characters. Pay attention to this in regard
to shiftOut function, the transmission bit, flag bit and highest bit will be transmitted preferentially.
for(i=0;i<sizeof(num);i++){
digitalWrite(latchPin,LOW);
_shiftOut(dataPin,clockPin,MSBFIRST,num[i]);//Output the figures and the highest
level is transfered preferentially.
digitalWrite(latchPin,HIGH);
delay(500);
}

█ support@[Link]
█ [Link]  support@[Link] 147

If you want to display the decimal point, make the highest bit of each array “0”, which can be implemented
easily by num[i]&0x7f.
_shiftOut(dataPin,clockPin,MSBFIRST,num[i] & 0x7f);

Project 18.2 4-Digit 7-Segment Display

Now, let’s try to control more-than-one digit displays by using a Four 7-Segment Display in one project.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper Wire x30


GPIO Expansion Board & Wire x1
Breadboard x1
74HC595 x1 PNP 4-Digit 7-Segment Display x1 Resistor 220Ω Resistor 1KΩ
transistor x4 x8 x4

support@[Link] █
148  support@[Link] [Link] █

Component knowledge

4 Digit 7-Segment Display


A 4 Digit 7-segment display integrates four 7-Segment Displays into one module, therefore it can display
more characters. All of the LEDs contained have a Common Anode and individual Cathodes. Its internal
structure and pin designation diagram is shown below:

The internal electronic circuit is shown below, and all 8 LED cathode pins of each 7-Segment Display are
connected together.

Display method of 4 Digit 7-segment display is similar to 1 Digit 7-segment display. The difference between
them is that the 4-Digit displays each Digit is visible in turn, one by one and not together. We need to first
send high level to the common end of the first Digit Display, and send low level to the remaining three
common ends, and then send content to 8 LED cathode pins of the first Digit Display. At this time, the first 7-
Segment Display will show visible content and the remaining three will be OFF.
Similarly, the second, third and fourth 7-Segment Displays will show visible content in turn by scanning the
display. Although the four number characters are displayed in turn separately, this process is so very fast that
it is unperceivable to the naked eye. This is due to the principle of optical afterglow effect and the vision
persistence effect in human sight. This is how we can see all 4 number characters at the same time. However,
if each number character is displayed for a longer period, you will be able to see that the number characters
are displayed separately.

█ support@[Link]
█ [Link]  support@[Link] 149

Circuit

Schematic diagram

support@[Link] █
150  support@[Link] [Link] █

Hardware connection

█ support@[Link]
█ [Link]  support@[Link] 151

Code

In this code, we use the 74HC595 IC Chip to control the 4-Digit 7-Segment Display, and use the dynamic
scanning method to show the changing number characters.
C Code 18.2.1 StopWatch
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter directory of C code.
cd ~/Freenove_Kit/Code/C_Code/18.2.1_StopWatch
2. Use following command to compile "StopWatch.c" and generate executable file "StopWatch".
gcc StopWatch.c -o StopWatch -lwiringPi
3. Run the generated file "SteppingMotor".
sudo ./StopWatch
After the program is executed, the 4-Digit 7-Segment Display starts displaying a four-digit number
dynamically, and the numeric value of this number will increase by plus 1 each second thereafter.
The following is the program code:
1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <wiringShift.h>
4 #include <signal.h>
5 #include <unistd.h>
6 #define dataPin 5 //DS Pin of 74HC595(Pin14)
7 #define latchPin 4 //ST_CP Pin of 74HC595(Pin12)
8 #define clockPin 1 //CH_CP Pin of 74HC595(Pin11)
9 const int digitPin[]={0,2,3,12}; // Define 7-segment display common pin
10 // character 0-9 code of common anode 7-segment display
11 unsigned char num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
12 int counter = 0; //variable counter,the number will be displayed by 7-segment display
13 //Open one of the 7-segment display and close the remaining three, the parameter digit is
optional for 1,2,4,8
14 void selectDigit(int digit){
15 digitalWrite(digitPin[0],((digit&0x08) == 0x08) ? LOW : HIGH);
16 digitalWrite(digitPin[1],((digit&0x04) == 0x04) ? LOW : HIGH);
17 digitalWrite(digitPin[2],((digit&0x02) == 0x02) ? LOW : HIGH);
18 digitalWrite(digitPin[3],((digit&0x01) == 0x01) ? LOW : HIGH);
19 }
20 void _shiftOut(int dPin,int cPin,int order,int val){
21 int i;
22 for(i = 0; i < 8; i++){
23 digitalWrite(cPin,LOW);
24 if(order == LSBFIRST){
25 digitalWrite(dPin,((0x01&(val>>i)) == 0x01) ? HIGH : LOW);
26 delayMicroseconds(1);

support@[Link] █
152  support@[Link] [Link] █

27 }
28 else {//if(order == MSBFIRST){
29 digitalWrite(dPin,((0x80&(val<<i)) == 0x80) ? HIGH : LOW);
30 delayMicroseconds(1);
31 }
32 digitalWrite(cPin,HIGH);
33 delayMicroseconds(1);
34 }
35 }
36 void outData(int8_t data){ //function used to output data for 74HC595
37 digitalWrite(latchPin,LOW);
38 _shiftOut(dataPin,clockPin,MSBFIRST,data);
39 digitalWrite(latchPin,HIGH);
40 }
41 void display(int dec){ //display function for 7-segment display
42 int delays = 1;
43 outData(0xff);
44 selectDigit(0x01); //select the first, and display the single digit
45 outData(num[dec%10]);
46 delay(delays); //display duration
47
48 outData(0xff);
49 selectDigit(0x02); //select the second, and display the tens digit
50 outData(num[dec%100/10]);
51 delay(delays);
52
53 outData(0xff);
54 selectDigit(0x04); //select the third, and display the hundreds digit
55 outData(num[dec%1000/100]);
56 delay(delays);
57
58 outData(0xff);
59 selectDigit(0x08); //select the fourth, and display the thousands digit
60 outData(num[dec%10000/1000]);
61 delay(delays);
62 }
63 void timer(int sig){ //Timer function
64 if(sig == SIGALRM){ //If the signal is SIGALRM, the value of counter plus 1, and update
the number displayed by 7-segment display
65 counter ++;
66 alarm(1); //set the next timer time
67 printf("counter : %d \n",counter);
68 }
69 }

█ support@[Link]
█ [Link]  support@[Link] 153

70 int main(void)
71 {
72 int i;
73
74 printf("Program is starting ...\n");
75
76 wiringPiSetup();
77
78 pinMode(dataPin,OUTPUT); //set the pin connected to74HC595 for output mode
79 pinMode(latchPin,OUTPUT);
80 pinMode(clockPin,OUTPUT);
81 //set the pin connected to 7-segment display common end to output mode
82 for(i=0;i<4;i++){
83 pinMode(digitPin[i],OUTPUT);
84 digitalWrite(digitPin[i],HIGH);
85 }
86 signal(SIGALRM,timer); //configure the timer
87 alarm(1); //set the time of timer to 1s
88 while(1){
89 display(counter); //display the number counter
90 }
91 return 0;
92 }

First, we define the pin of the 74HC595 IC Chip and the 7-Segment Display Common Anode, use character
encoding and a variable "counter" to enable the counter to be visible on the 7-Segment Display.
#define dataPin 5 //DS Pin of 74HC595(Pin14)
#define latchPin 4 //ST_CP Pin of 74HC595(Pin12)
#define clockPin 1 //CH_CP Pin of 74HC595(Pin11)
const int digitPin[]={0,2,3,12}; //Define the pin of 7-segment display common end
// character 0-9 code of common anode 7-segment display
unsigned char num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
int counter = 0; //variable counter, the number will be displayed by 7-segment display

Subfunction selectDigit (int digit) function is used to open one of the 7-Segment Displays while closing the
other 7-Segment Displays, where the parameter digit value can be 1,2,4,8. Using "|" can open a number of a
7-Segment Display.
void selectDigit(int digit){
digitalWrite(digitPin[0],((digit&0x08) == 0x08) ? LOW : HIGH);
digitalWrite(digitPin[1],((digit&0x04) == 0x04) ? LOW : HIGH);
digitalWrite(digitPin[2],((digit&0x02) == 0x02) ? LOW : HIGH);
digitalWrite(digitPin[3],((digit&0x01) == 0x01) ? LOW : HIGH);
}

support@[Link] █
154  support@[Link] [Link] █

Subfunction outData (int8_t data) is used to make the 74HC595 IC Chip output an 8-bit data immediately.
void outData(int8_t data){ // function used to output data for 74HC595
digitalWrite(latchPin,LOW);
shiftOut(dataPin,clockPin,MSBFIRST,data);
digitalWrite(latchPin,HIGH);
}
Subfunction display (int dec) is used to make a 4-Digit 7-Segment Display a 4-bit integer. First open the
common end of first 7-Segment Display Digit and turn OFF the other three Digits, now it can be used as 1-
Digit 7-Segment Display. The first Digit is used for displaying single digits of "dec", the second Digit is for tens,
the third for hundreds and fourth for thousands respectively. Each digit will be displayed for a period by using
delay (). The time in this code is very brief, so you will see digits all together. If the time is set long enough,
you will see that every digit is displayed independently.
void display(int dec){ //display function for 7-segment display
selectDigit(0x01); //select the first, and display the single digit
outData(num[dec%10]);
delay(1); //display duration
selectDigit(0x02); //Select the second, and display the tens digit
outData(num[dec%100/10]);
delay(1);
selectDigit(0x04); //Select the third, and display the hundreds digit
outData(num[dec%1000/100]);
delay(1);
selectDigit(0x08); //Select the fourth, and display the thousands digit
outData(num[dec%10000/1000]);
delay(1);
}
Subfunction timer (int sig) is the timer function, which will set an alarm to signal. This function will be executed
once at set time intervals. Accompanied by the execution, “1” will be added as the variable counter and then
reset the time of timer to 1s.
void timer(int sig){ //timer function
if(sig == SIGALRM){ //If the signal is SIGALRM, the value of counter plus 1, and update
the number displayed by 7-segment display
counter ++;
alarm(1); //set the next timer time
}
}

█ support@[Link]
█ [Link]  support@[Link] 155

Finally, in the main function, configure the GPIO, and set the timer function.
pinMode(dataPin,OUTPUT); //set the pin connected to74HC595 for output mode
pinMode(latchPin,OUTPUT);
pinMode(clockPin,OUTPUT);
//set the pin connected to 7-segment display common end to output mode
for(i=0;i<4;i++){
pinMode(digitPin[i],OUTPUT);
digitalWrite(digitPin[i],LOW);
}
signal(SIGALRM,timer); //configure the timer
alarm(1); //set the time of timer to 1s

In the while loop, make the digital display variable counter value “1”. The value will change in function timer
(), so the content displayed by the 7-Segment Display will change accordingly.
while(1){
display(counter); //display number counter
}

support@[Link] █
156  support@[Link] [Link] █

Chapter 19 74HC595 & LED Matrix


Thus far we have learned how to use the 74HC595 IC Chip to control the Bar Graph LED and the 7-Segment
Display. We will now use 74HC595 IC Chips to control an LED Matrix.

Project 19.1 LED Matrix

In this project, we will use two 74HC595 IC chips to control a monochrome (one color) (8X8) LED Matrix to
make it display both simple graphics and characters.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x36


GPIO Extension Board & Ribbon Cable x1
Breadboard x1
74HC595 x2 8X8 LEDMatrix x1 Resistor 220Ω x8

█ support@[Link]
█ [Link]  support@[Link] 157

Component knowledge

LED matrix
An LED Matrix is a rectangular display module that consists of a uniform grid of LEDs. The following is an 8X8
monochrome (one color) LED Matrix containing 64 LEDs (8 rows by 8 columns).

In order to facilitate the operation and reduce the number of ports required to drive this component, the
Positive Poles of the LEDs in each row and Negative Poles of the LEDs in each column are respectively
connected together inside the LED Matrix module, which is called a Common Anode. There is another
arrangement type. Negative Poles of the LEDs in each row and the Positive Poles of the LEDs in each column
are respectively connected together, which is called a Common Cathode.
The LED Matrix that we use in this project is a Common Anode LED Matrix.
Connection mode of Common Anode Connection mode of Common Cathode

support@[Link] █
158  support@[Link] [Link] █

Here is how a Common Anode LED Matrix works. First, choose 16 ports on RPI board to connect to the 16
ports of LED Matrix. Configure one port in columns for low level, which makes that column the selected port.
Then configure the eight port in the row to display content in the selected column. Add a delay value and
then select the next column that outputs the corresponding content. This kind of operation by column is
called Scan. If you want to display the following image of a smiling face, you can display it in 8 columns, and
each column is represented by one byte.

1 2 3 4 5 6 7 8
0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 0
0 1 0 0 0 0 1 0
1 0 1 0 0 1 0 1
1 0 0 0 0 0 0 1
1 0 0 1 1 0 0 1
0 1 0 0 0 0 1 0
0 0 1 1 1 1 0 0

Column Binary Hexadecimal


1 0001 1100 0x1c
2 0010 0010 0x22
3 0101 0001 0x51
4 0100 0101 0x45
5 0100 0101 0x45
6 0101 0001 0x51
7 0010 0010 0x22
8 0001 1100 0x1c
To begin, display the first column, then turn off the first column and display the second column. (and so on) ....
turn off the seventh column and display the 8th column, and then start the process over from the first column
again like the control of LED Bar Graph project. The whole process will be repeated rapidly in a loop. Due to
the principle of optical afterglow effect and the vision persistence effect in human sight, we will see a picture
of a smiling face directly rather than individual columns of LEDs turned ON one column at a time (although
in fact this is the reality we cannot perceive).
Scanning rows is another option to display on an LED Matrix (dot matrix grid). Whether scanning by row or
column, 16 GPIO is required. In order to save GPIO ports of control board, two 74HC595 IC Chips are used in
the circuit. Every 74HC595 IC Chip has eight parallel output ports, so two of these have a combined total of
16 ports, which is just enough for our project. The control lines and data lines of the two 74HC595 IC Chips
are not all connected to the RPi, but connect to the Q7 pin of first stage 74HC595 IC Chip and to the data pin
of second IC Chip. The two 74HC595 IC Chips are connected in series, which is the same as using one
"74HC595 IC Chip" with 16 parallel output ports.

█ support@[Link]
█ [Link]  support@[Link] 159

Circuit

In circuit of this project, the power pin of the 74HC595 IC Chip is connected to 3.3V. It can also be connected
to 5V to make LED Matrix brighter.
Schematic diagram

support@[Link] █
160  support@[Link] [Link] █

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Second stage
74HC595:B

First stage
74HC595:A

Video: [Link]

█ support@[Link]
█ [Link]  support@[Link] 161

Code

Two 74HC595 IC Chips are used in this project, one for controlling the LED Matrix’s columns and the other
for controlling the rows. According to the circuit connection, row data should be sent first, then column data.
The following code will make the LED Matrix display a smiling face, and then display characters "0 to F"
scrolling in a loop on the LED Matrix.
C Code 19.1.1 LEDMatrix
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 19.1.1_LEDMatrix directory of C language.
cd ~/Freenove_Kit/Code/C_Code/19.1.1_LEDMatrix
2. Use following command to compile “LEDMatrix.c” and generate executable file “LEDMatrix”.
gcc LEDMatrix.c -o LEDMatrix -lwiringPi
3. Then run the generated file “LEDMatrix”.
sudo ./LEDMatrix
After the program is executed, the LED Matrix display a smiling face, and then display characters "0 to F"
scrolling in a loop on the LED Matrix.
The following is the program code:
1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <wiringShift.h>
4
5 #define dataPin 0 //DS Pin of 74HC595(Pin14)
6 #define latchPin 2 //ST_CP Pin of 74HC595(Pin12)
7 #define clockPin 3 //SH_CP Pin of 74HC595(Pin11)
8 // data of smile face
9 unsigned char pic[]={0x1c,0x22,0x51,0x45,0x45,0x51,0x22,0x1c};
10 unsigned char data[]={ // data of "0-F"
11 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // " "
12 0x00, 0x00, 0x3E, 0x41, 0x41, 0x3E, 0x00, 0x00, // "0"
13 0x00, 0x00, 0x21, 0x7F, 0x01, 0x00, 0x00, 0x00, // "1"
14 0x00, 0x00, 0x23, 0x45, 0x49, 0x31, 0x00, 0x00, // "2"
15 0x00, 0x00, 0x22, 0x49, 0x49, 0x36, 0x00, 0x00, // "3"
16 0x00, 0x00, 0x0E, 0x32, 0x7F, 0x02, 0x00, 0x00, // "4"
17 0x00, 0x00, 0x79, 0x49, 0x49, 0x46, 0x00, 0x00, // "5"
18 0x00, 0x00, 0x3E, 0x49, 0x49, 0x26, 0x00, 0x00, // "6"
19 0x00, 0x00, 0x60, 0x47, 0x48, 0x70, 0x00, 0x00, // "7"
20 0x00, 0x00, 0x36, 0x49, 0x49, 0x36, 0x00, 0x00, // "8"
21 0x00, 0x00, 0x32, 0x49, 0x49, 0x3E, 0x00, 0x00, // "9"
22 0x00, 0x00, 0x3F, 0x44, 0x44, 0x3F, 0x00, 0x00, // "A"
23 0x00, 0x00, 0x7F, 0x49, 0x49, 0x36, 0x00, 0x00, // "B"
24 0x00, 0x00, 0x3E, 0x41, 0x41, 0x22, 0x00, 0x00, // "C"
25 0x00, 0x00, 0x7F, 0x41, 0x41, 0x3E, 0x00, 0x00, // "D"

support@[Link] █
162  support@[Link] [Link] █

26 0x00, 0x00, 0x7F, 0x49, 0x49, 0x41, 0x00, 0x00, // "E"


27 0x00, 0x00, 0x7F, 0x48, 0x48, 0x40, 0x00, 0x00, // "F"
28 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // " "
29 };
30 void _shiftOut(int dPin,int cPin,int order,int val){
31 int i;
32 for(i = 0; i < 8; i++){
33 digitalWrite(cPin,LOW);
34 if(order == LSBFIRST){
35 digitalWrite(dPin,((0x01&(val>>i)) == 0x01) ? HIGH : LOW);
36 delayMicroseconds(10);
37 }
38 else {//if(order == MSBFIRST){
39 digitalWrite(dPin,((0x80&(val<<i)) == 0x80) ? HIGH : LOW);
40 delayMicroseconds(10);
41 }
42 digitalWrite(cPin,HIGH);
43 delayMicroseconds(10);
44 }
45 }
46 int main(void)
47 {
48 int i,j,k;
49 unsigned char x;
50
51 printf("Program is starting ...\n");
52
53 wiringPiSetup();
54
55 pinMode(dataPin,OUTPUT);
56 pinMode(latchPin,OUTPUT);
57 pinMode(clockPin,OUTPUT);
58 while(1){
59 for(j=0;j<500;j++){ //Repeat enough times to display the smiling face a period of
time
60 x=0x80;
61 for(i=0;i<8;i++){
62 digitalWrite(latchPin,LOW);
63 _shiftOut(dataPin,clockPin,MSBFIRST,pic[i]);// first shift data of line
information to the first stage 74HC959
64 _shiftOut(dataPin,clockPin,MSBFIRST,~x);//then shift data of column
information to the second stage 74HC959
65
66 digitalWrite(latchPin,HIGH);//Output data of two stage 74HC595 at the same

█ support@[Link]
█ [Link]  support@[Link] 163

time
67 x>>=1; //display the next column
68 delay(1);
69 }
70 }
71 for(k=0;k<sizeof(data)-8;k++){ //sizeof(data) total number of "0-F" columns
72 for(j=0;j<20;j++){ //times of repeated displaying LEDMatrix in every frame, the
bigger the “j”, the longer the display time
73 x=0x80; //Set the column information to start from the first column
74 for(i=k;i<8+k;i++){
76 digitalWrite(latchPin,LOW);
77 _shiftOut(dataPin,clockPin,MSBFIRST,data[i]);
78 _shiftOut(dataPin,clockPin,MSBFIRST,~x);
79 digitalWrite(latchPin,HIGH);
80 x>>=1;
81 delay(1);
82 }
83 }
84 }
85 }
86 return 0;
87 }

The first “for” loop in the “while” loop is used to display a static smile. Displaying column information from left
to right, one column at a time with a total of 8 columns. This repeats 500 times to ensure sufficient display
time.
for(j=0;j<500;j++){// Repeat enough times to display the smiling face a period of
time
x=0x80;
for(i=0;i<8;i++){
digitalWrite(latchPin,LOW);
shiftOut(dataPin,clockPin,MSBFIRST,pic[i]);
shiftOut(dataPin,clockPin,MSBFIRST,~x);
digitalWrite(latchPin,HIGH);
x>>=1;
delay(1);
}
}

support@[Link] █
164  support@[Link] [Link] █

The second “for” loop is used to display scrolling characters "0 to F", for a total of 18 X 8 = 144 columns.
Displaying the 0-8 column, then the 1-9 column, then the 2-10 column...... and so on…138-144 column in
consecutively to achieve the scrolling effect. The display of each frame is repeated a certain number of times
and the more repetitions, the longer the single frame display will be and the slower the scrolling movement.
for(k=0;k<sizeof(data)-8;k++){ //sizeof(data) total number of "0-F" columns
for(j=0;j<20;j++){// times of repeated displaying LEDMatrix in every frame, the
bigger the “j”, the longer the display time
x=0x80; // Set the column information to start from the first column
for(i=k;i<8+k;i++){
digitalWrite(latchPin,LOW);
shiftOut(dataPin,clockPin,MSBFIRST,data[i]);
shiftOut(dataPin,clockPin,MSBFIRST,~x);
digitalWrite(latchPin,HIGH);
x>>=1;
delay(1);
}
}
}

█ support@[Link]
█ [Link]  support@[Link] 165

Chapter 20 LCD1602
In this chapter, we will learn about the LCD1602 Display Screen,

Project 20.1 I2C LCD1602

There are LCD1602 display screen and the I2C LCD. We will introduce both of them in this chapter. But what
we use in this project is an I2C LCD1602 display screen. The LCD1602 Display Screen can display 2 lines of
characters in 16 columns. It is capable of displaying numbers, letters, symbols, ASCII code and so on. As shown
below is a monochrome LCD1602 Display Screen along with its circuit pin diagram

I2C LCD1602 Display Screen integrates a I2C interface, which connects the serial-input & parallel-output
module to the LCD1602 Display Screen. This allows us to only use 4 lines to operate the LCD1602.

The serial-to-parallel IC chip used in this module is PCF8574T (PCF8574AT), and its default I2C address is
0x27(0x3F). You can also view the RPI bus on your I2C device address through command "i2cdetect -y 1"
(refer to the "configuration I2C" section below).

support@[Link] █
166  support@[Link] [Link] █

Below is the PCF8574 chip pin diagram and its module pin diagram:
PCF8574 chip pin diagram: PCF8574 module pin diagram

PCF8574 module pins and LCD1602 pins correspond to each other and connected to each other:

Because of this, as stated earlier, we only need 4 pins to control the16 pins of the LCD1602 Display Screen
through the I2C interface.
In this project, we will use the I2C LCD1602 to display some static characters and dynamic variables.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper Wire x4


GPIO Extension Board & Ribbon Cable x1
Breadboard x1
I2C LCD1602 Module x1

█ support@[Link]
█ [Link]  support@[Link] 167

Circuit

Note that the power supply for I2C LCD1602 in this circuit is 5V.
Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]
NOTE: It is necessary to configure 12C and install Smbus first (see chapter 7 for details)

Video: [Link]

support@[Link] █
168  support@[Link] [Link] █

Code

This code will have your RPi’s CPU temperature and System Time Displayed on the LCD1602.
C Code 20.1.1 I2CLCD1602
If you did not configure I2C and install Smbus, please refer to Chapter 7. If you did, please continue.
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 20.1.1_ I2CLCD1602 directory of C code.
cd ~/Freenove_Kit/Code/C_Code/20.1.1_I2CLCD1602
2. Use following command to compile “I2CLCD1602.c” and generate executable file “I2CLCD1602”.
gcc I2CLCD1602.c -o I2CLCD1602 -lwiringPi -lwiringPiDev
3. Then run the generated file “I2CLCD1602”.
sudo ./I2CLCD1602
After the program is executed, the LCD1602 Screen will display your RPi’s CPU Temperature and System Time.
So far, at this writing, we have two types of LCD1602 on sale. One needs to adjust the backlight, and the other
does not.
The LCD1602 that does not need to adjust the backlight is shown in the figure below.

The following is the program code:


1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <wiringPi.h>
4 #include <wiringPiI2C.h>
5 #include <pcf8574.h>
6 #include <lcd.h>
7 #include <time.h>
8
9 int pcf8574_address = 0x27; // PCF8574T:0x27, PCF8574AT:0x3F
10 #define BASE 64 // BASE any number above 64
11 //Define the output pins of the PCF8574, which are directly connected to the LCD1602 pin.
12 #define RS BASE+0
13 #define RW BASE+1
14 #define EN BASE+2
15 #define LED BASE+3

█ support@[Link]
█ [Link]  support@[Link] 169

16 #define D4 BASE+4
17 #define D5 BASE+5
18 #define D6 BASE+6
19 #define D7 BASE+7
20
21 int lcdhd;// used to handle LCD
22 void printCPUTemperature(){// sub function used to print CPU temperature
23 FILE *fp;
24 char str_temp[15];
25 float CPU_temp;
26 // CPU temperature data is stored in this directory.
27 fp=fopen("/sys/class/thermal/thermal_zone0/temp","r");
28 fgets(str_temp,15,fp); // read file temp
29 CPU_temp = atof(str_temp)/1000.0; // convert to Celsius degrees
30 printf("CPU's temperature : %.2f \n",CPU_temp);
31 lcdPosition(lcdhd,0,0); // set the LCD cursor position to (0,0)
32 lcdPrintf(lcdhd,"CPU:%.2fC",CPU_temp);// Display CPU temperature on LCD
33 fclose(fp);
34 }
35 void printDataTime(){//used to print system time
36 time_t rawtime;
37 struct tm *timeinfo;
38 time(&rawtime);// get system time
39 timeinfo = localtime(&rawtime);//convert to local time
40 printf("%s \n",asctime(timeinfo));
41 lcdPosition(lcdhd,0,1);// set the LCD cursor position to (0,1)
42
43 lcdPrintf(lcdhd,"Time:%02d:%02d:%02d",timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec);
44 //Display system time on LCD
45 }
46 int detectI2C(int addr){ //Used to detect i2c address of LCD
47 int _fd = wiringPiI2CSetup (addr);
48 if (_fd < 0){
49 printf("Error address : 0x%x \n",addr);
50 return 0 ;
51 }
52 else{
53 if(wiringPiI2CWrite(_fd,0) < 0){
54 printf("Not found device in address 0x%x \n",addr);
55 return 0;
56 }
57 else{
58 printf("Found device in address 0x%x \n",addr);
59 return 1 ;

support@[Link] █
170  support@[Link] [Link] █

60 }
61 }
62 }
63 int main(void){
64 int i;
65 printf("Program is starting ...\n");
66 wiringPiSetup();
67 if(detectI2C(0x27)){
68 pcf8574_address = 0x27;
69 }else if(detectI2C(0x3F)){
70 pcf8574_address = 0x3F;
71 }else{
72 printf("No correct I2C address found, \n"
73 "Please use command 'i2cdetect -y 1' to check the I2C address! \n"
74 "Program Exit. \n");
75 return -1;
76 }
77 pcf8574Setup(BASE,pcf8574_address);//initialize PCF8574
78 for(i=0;i<8;i++){
79 pinMode(BASE+i,OUTPUT); //set PCF8574 port to output mode
80 }
81 digitalWrite(LED,HIGH); //turn on LCD backlight
82 digitalWrite(RW,LOW); //allow writing to LCD
83 lcdhd = lcdInit(2,16,4,RS,EN,D4,D5,D6,D7,0,0,0,0);// initialize LCD and return “handle”
used to handle LCD
84 if(lcdhd == -1){
85 printf("lcdInit failed !");
86 return 1;
87 }
88 while(1){
89 printCPUTemperature();//print CPU temperature
90 printDataTime(); // print system time
91 delay(1000);
92 }
93 return 0;
94 }

█ support@[Link]
█ [Link]  support@[Link] 171

From the code, we can see that the PCF8591 and the PCF8574 have many similarities in using the I2C interface
to expand the GPIO RPI.
First, define the I2C address of the PCF8574 and the Extension of the GPIO pin, which is connected to the
GPIO pin of the LCD1602. LCD1602 has two different i2c addresses. Set 0x27 as default.
int pcf8574_address = 0x27; // PCF8574T:0x27, PCF8574AT:0x3F
#define BASE 64 // BASE any number above 64
//Define the output pins of the PCF8574, which are directly connected to the LCD1602 pin.
#define RS BASE+0
#define RW BASE+1
#define EN BASE+2
#define LED BASE+3
#define D4 BASE+4
#define D5 BASE+5
#define D6 BASE+6
#define D7 BASE+7
Then, in main function, initialize the PCF8574, set all the pins to output mode, and turn ON the LCD1602
backlight (without the backlight the Display is difficult to read).
pcf8574Setup(BASE,pcf8574_address);// initialize PCF8574
for(i=0;i<8;i++){
pinMode(BASE+i,OUTPUT); // set PCF8574 port to output mode
}
digitalWrite(LED,HIGH); // turn on LCD backlight
Then use lcdInit() to initialize LCD1602 and set the RW pin of LCD1602 to 0 (can be written) according to
requirements of this function. The return value of the function called "Handle" is used to handle LCD1602".
lcdhd = lcdInit(2,16,4,RS,EN,D4,D5,D6,D7,0,0,0,0);// initialize LCD and return
“handle” used to handle LCD

Details about lcdInit():


int lcdInit (int rows, int cols, int bits, int rs, int strb,
int d0, int d1, int d2, int d3, int d4, int d5, int d6, int d7) ;
This is the main initialization function and must be executd first before you use any other LCD functions.
Rows and cols are the rows and columns of the Display (e.g. 2, 16 or 4, 20). Bits is the number of how wide
the number of bits is on the interface (4 or 8). The rs and strb represent the pin numbers of the Display’s
RS pin and Strobe (E) pin. The parameters d0 through d7 are the pin numbers of the 8 data pins connected
from the RPi to the display. Only the first 4 are used if you are running the display in 4-bit mode.
The return value is the ‘handle’ to be used for all subsequent calls to the lcd library when dealing with that
LCD, or -1 to indicate a fault (usually incorrect parameter)
For more details about LCD Library, please refer to: [Link]
library/

support@[Link] █
172  support@[Link] [Link] █

In the next “while”, two subfunctions are called to display the RPi’s CPU Temperature and the SystemTime.
First look at subfunction printCPUTemperature(). The CPU temperature data is stored in the
"/sys/class/thermal/thermal_zone0/temp " file. We need to read the contents of this file, which converts it to
temperature value stored in variable CPU_temp and uses lcdPrintf() to display it on LCD.
void printCPUTemperature(){//subfunction used to print CPU temperature

FILE *fp;
char str_temp[15];
float CPU_temp;
// CPU temperature data is stored in this directory.
fp=fopen("/sys/class/thermal/thermal_zone0/temp","r");
fgets(str_temp,15,fp); // read file temp
CPU_temp = atof(str_temp)/1000.0; // convert to Celsius degrees
printf("CPU's temperature : %.2f \n",CPU_temp);
lcdPosition(lcdhd,0,0); // set the LCD cursor position to (0,0)
lcdPrintf(lcdhd,"CPU:%.2fC",CPU_temp);// Display CPU temperature on LCD
fclose(fp);
}
Details about lcdPosition() and lcdPrintf():
lcdPosition (int handle, int x, int y);
Set the position of the cursor for subsequent text entry.
lcdPutchar (int handle, uint8_t data)
lcdPuts (int handle, char *string)
lcdPrintf (int handle, char *message, …)
These output a single ASCII character, a string or a formatted string using the usual print formatting
commands to display individual characters (it is how you are able to see characters on your computer
monitor).
Next is subfunction printDataTime() used to display System Time. First, it gets the Standard Time and stores
it into variable Rawtime, and then converts it to the Local Time and stores it into timeinfo, and finally displays
the Time information on the LCD1602 Display.
void printDataTime(){//used to print system time
time_t rawtime;
struct tm *timeinfo;
time(&rawtime);// get system time
timeinfo = localtime(&rawtime);// convert to local time
printf("%s \n",asctime(timeinfo));
lcdPosition(lcdhd,0,1);// set the LCD cursor position to (0,1)
lcdPrintf(lcdhd,"Time:%d:%d:%d",timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec);
//Display system time on LCD
}

█ support@[Link]
█ [Link]  support@[Link] 173

Chapter 21 Hygrothermograph DHT11


In this chapter, we will learn about a commonly used sensor called a Hygrothermograph DHT11.

Project 21.1 Hygrothermograph

Hygrothermograph is an important tool in our lives to give us data on the temperature and humidity in our
environment. In this project, we will use the RPi to read Temperature and Humidity data of the DHT11 Module.

Component List

Raspberry Pi (with 40 GPIO) x1 DHT11 x1 Resistor 10kΩ x1


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1

Jumper Wire x4

Component knowledge

The Temperature & Humidity Sensor DHT11 is a compound temperature & humidity sensor, and the output
digital signal has been calibrated by its manufacturer.

After being powered up, it will initialize in 1 second. Its operating voltage is within the range of 3.3V-5.5V.
The SDA pin is a data pin, which is used to communicate with other devices.
The NC pin (Not Connected Pin) are a type of pin found on various integrated circuit packages. Those pins
have no functional purpose to the outside circuit (but may have an unknown functionality during
manufacture and test). Those pins should not be connected to any of the circuit connections.

support@[Link] █
174  support@[Link] [Link] █

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]

█ support@[Link]
█ [Link]  support@[Link] 175

Code

The code is used to read the temperature and humidity data of DHT11, and display them.
C Code 21.1.1 DHT11
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 21.1.1_DHT11 directory of C code.
cd ~/Freenove_Kit/Code/C_Code/21.1.1_DHT11
2. The code used in this project contains a custom header file. Use the following command to compile the
code [Link] and [Link] and generate executable file DHT11. The custom header file will be
compiled at the same time.
gcc [Link] [Link] -o DHT11 -lwiringPi
3. Run the generated file "DHT11".
sudo ./DHT11
After the program is executed, the Terminal window will display the current total number of read times, the
read state, as well as temperature and humidity values as is shown below:

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <stdint.h>
4 #include "[Link]"
5
6 #define DHT11_Pin 0 //define the pin of sensor
7
8 int main(){
9 DHT dht; //create a DHT class object
10 int chk, counts; //chk:read the return value of sensor; sumCnt:times of reading
sensor
11
12 printf("Program is starting ...\n");
13

support@[Link] █
176  support@[Link] [Link] █

14 while (1){
15 counts++; //counting number of reading times
16 printf("Measurement counts : %d \n", counts);
17 for (int i = 0; i < 15; i++){
18 chk = dht.readDHT11(DHT11_Pin); //read DHT11 and get a return value. Then
determine whether data read is normal according to the return value.
19 if(chk == DHTLIB_OK){
20 printf("DHT11,OK! \n");
21 break;
22 }
23 delay(100);
24 }
25 printf("Humidity is %.2f %%, \t Temperature is %.2f *C\n\n",[Link],
26 [Link]);
27 delay(2000);
28 }
29 return 1;
30 }
In this project code, we use a custom library file "[Link]". It is located in the same directory with the program
files "[Link]" and "[Link]", and methods for reading DHT sensor are provided in the library file. By
using this library, we can easily read the DHT Sensor. First, we create a DHT class object in the code.
DHT dht;
Then in the "while" loop, use chk = dht.readDHT11 (DHT11_Pin) to read the DHT11, and determine whether
the data read is normal according to the return value "chk". If the value is OK, end for loop and move on.
Otherwise, try 15 times in total. Then use variable counts to record number of times to read.
while (1){
counts++; //counting number of reading times
printf("Measurement counts : %d \n", counts);
for (int i = 0; i < 15; i++){
chk = dht.readDHT11(DHT11_Pin); //read DHT11 and get a return value. Then
determine whether data read is normal according to the return value.
if(chk == DHTLIB_OK){
printf("DHT11,OK! \n");
break;
}
delay(100);
}
printf("Humidity is %.2f %%, \t Temperature is %.2f *C\n\n",[Link],
[Link]);
delay(2000);
}

Finally display the results:


printf("Humidity is %.2f %%, \t Temperature is %.2f *C\n\n",[Link],[Link]);

█ support@[Link]
█ [Link]  support@[Link] 177

Library file "[Link]" contains a DHT class and this public member function int readDHT11 (int pin) is used
to read sensor DHT11 and store the temperature and humidity data read to member variables double
humidity and temperature. The implementation method of the function is included in the file "[Link]".
1 #define _DHT_H_
2
3 #include <wiringPi.h>
4 #include <stdio.h>
5 #include <stdint.h>
6
7 ////read return flag of sensor
8 #define DHTLIB_OK 0
9 #define DHTLIB_ERROR_CHECKSUM -1
10 #define DHTLIB_ERROR_TIMEOUT -2
11 #define DHTLIB_INVALID_VALUE -999
12
13 #define DHTLIB_DHT11_WAKEUP 20
14 #define DHTLIB_DHT_WAKEUP 1
15
16 #define DHTLIB_TIMEOUT 100
17
18 class DHT{
19 public:
20 DHT();
21 double humidity,temperature; //use to store temperature and humidity data read
22 int readDHT11Once(int pin); //read DHT11
23 int readDHT11(int pin); //read DHT11
24 private:
25 uint8_t bits[5]; //Buffer to receiver data
26 int readSensor(int pin,int wakeupDelay); //
27
28 };

support@[Link] █
178  support@[Link] [Link] █

Chapter 22 Matrix Keypad


Earlier we learned about a single Push Button Switch. In this chapter, we will learn about Matrix Keyboards,
which integrates a number of Push Button Switches as Keys for the purposes of Input.

Project 22.1 Matrix Keypad

In this project, we will attempt to get every key code on the Matrix Keypad to work.

Component List

Raspberry Pi (with 40 GPIO) x1 4x4 Matrix Keypad x1


GPIO Expansion Board & Wire x1
Breadboard x1

Jumper wire

Resistor 10kΩ x4

Component knowledge

4x4 Matrix Keypad


A Keypad Matrix is a device that integrates a number of keys in one package. As is shown below, a 4x4 Keypad

█ support@[Link]
█ [Link]  support@[Link] 179

Matrix integrates 16 keys (think of this as 16 Push Button Switches in one module):

Similar to the integration of an LED Matrix, the 4x4 Keypad Matrix has each row of keys connected with one
pin and this is the same for the columns. Such efficient connections reduce the number of processor ports
required. The internal circuit of the Keypad Matrix is shown below.

The method of usage is similar to the Matrix LED, by using a row or column scanning method to detect the
state of each key’s position by column and row. Take column scanning method as an example, send low level
to the first 1 column (Pin1), detect level state of row 5, 6, 7, 8 to judge whether the key A, B, C, D are pressed.
Then send low level to column 2, 3, 4 in turn to detect whether other keys are pressed. Therefore, you can
get the state of all of the keys.

support@[Link] █
180  support@[Link] [Link] █

Circuit

Schematic diagram

Video: [Link]

█ support@[Link]
█ [Link]  support@[Link] 181

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

support@[Link] █
182  support@[Link] [Link] █

Code

This code is used to obtain all key codes of the 4x4 Matrix Keypad, when one of the keys is pressed, the key
code will be displayed in the terminal window.
C Code 22.1.1 MatrixKeypad
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 22.1.1_MatrixKeypad directory of C code.
cd ~/Freenove_Kit/Code/C_Code/22.1.1_MatrixKeypad
2. Code of this project contains a custom header file. Use the following command to compile the code
[Link], [Link] and [Link] generate executable file MatrixKeypad. The custom header
file will be compiled at the same time.
gcc [Link] [Link] [Link] -o MatrixKeypad -lwiringPi
3. Run the generated file "MatrixKeypad".
sudo ./MatrixKeypad
After the program is executed, pressing any key on the MatrixKeypad, will display the corresponding key code
on the Terminal. As is shown below:

The following is the program code:


1 #include "[Link]"
2 #include <stdio.h>
3 const byte ROWS = 4; //four rows
4 const byte COLS = 4; //four columns
5 char keys[ROWS][COLS] = { //key code
6 {'1','2','3','A'},
7 {'4','5','6','B'},
8 {'7','8','9','C'},
9 {'*','0','#','D'}
10 };
11 byte rowPins[ROWS] = {1, 4, 5, 6 }; //define the row pins for the keypad
12 byte colPins[COLS] = {12,3, 2, 0 }; //define the column pins for the keypad

█ support@[Link]
█ [Link]  support@[Link] 183

13 //create Keypad object


14 Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
15
16 int main(){
17 printf("Program is starting ... \n");
18
19 wiringPiSetup();
20
21 char key = 0;
22 [Link](50);
23 while(1){
24 key = [Link](); //get the state of keys
25 if (key){ //if a key is pressed, print out its key code
26 printf("You Pressed key : %c \n",key);
27 }
28 }
29 return 1;
30 }
In this project code, we use two custom library file "[Link]" and "[Link]". They are located in the same
directory with program files "[Link]", "[Link]" and "[Link]". The Library Keypad is
“transplanted” from the Arduino Library Keypad. This library file provides a method to read the Matrix
Keyboard’s input. By using this library, we can easily read the pressed keys of the Matrix Keyboard.
First, we define the information of the Matrix Keyboard used in this project: the number of rows and columns,
code designation of each key and GPIO pin connected to each column and row. It is necessary to include the
header file "[Link]".
#include "[Link]"
#include <stdio.h>
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = { //key code
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {1, 4, 5, 6 }; //connect to the row pinouts of the keypad
byte colPins[COLS] = {12,3, 2, 0 }; //connect to the column pinouts of the keypad
Then, based on the above information, initiates a Keypad class object to operate the Matrix Keyboard.
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
Set the debounce time to 50ms, and this value can be set based on the actual characteristics of the keyboard’s
flexibly, with a default time of 10ms.
[Link](50);

support@[Link] █
184  support@[Link] [Link] █

In the "while" loop, use the function key= [Link] () to read the keyboard constantly. If there is a key
pressed, its key code will be stored in the variable "key", then be displayed.
while(1){
key = [Link](); //get the state of keys
if (key){ // if a key is pressed, print out its key code
printf("You Pressed key : %c \n",key);
}
}
The Keypad Library used for the RPi is transplanted from the Arduino Keypad Library. And the source files can
be obtained by visiting [Link] As for transplanted function library, the
function and method of all classes, functions, variables, etc. are the same as the original library. Partial contents
of the Keypad library are described below:
class Keypad
Keypad(char *userKeymap, byte *row, byte *col, byte numRows, byte numCols);
Constructor, the parameters are: key code of keyboard, row pin, column pin, the number of rows, the
number of columns.
char getKey();
Get the key code of the pressed key. If no key is pressed, the return value is NULL.
void setDebounceTime(uint);
Set the debounce time. And the default time is 10ms.
void setHoldTime(uint);
Set the time when the key holds stable state after pressed.
bool isPressed(char keyChar);
Judge whether the key with code "keyChar" is pressed.
char waitForKey();
Wait for a key to be pressed, and return key code of the pressed key.
KeyState getState();
Get state of the keys.
bool keyStateChanged();
Judge whether there is a change of key state, then return True or False.
For More information about Keypad, please visit: [Link] or through the
opening file "[Link]".

█ support@[Link]
█ [Link]  support@[Link] 185

Chapter 23 Infrared Motion Sensor


In this chapter, we will learn a widely used sensor, Infrared Motion Sensor.

Project 23.1 PIR Infrared Motion Detector with LED Indicator

In this project, we will make a Motion Detector, with the human body infrared pyroelectric sensors.
When someone is in close proximity to the Motion Detector, it will automatically light up and when there is
no one close by, it will be out.
This Infrared Motion Sensor can detect the infrared spectrum (heat signatures) emitted by living humans and
animals.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x5


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
HC SR501 x1 LED x1 Resistor 220Ω x1

Component Knowledge

The following is the diagram of the Infrared Motion Sensor(HC SR-501)a PIR Sensor:
Top Bottom Schematic

Description:
1. Working voltage: 5v-20v(DC) Static current: 65uA.
2. Automatic Trigger. When a living body enters into the active area of sensor, the module will output high

support@[Link] █
186  support@[Link] [Link] █

level (3.3V). When the body leaves the sensor’s active detection area, it will output high level lasting for
time period T, then output low level(0V). Delay time T can be adjusted by the potentiometer R1.
3. Induction block time: the induction will stay in block condition and does not induce external signal at
lesser time intervals (less than delay time) after outputting high level or low level
4. Initialization time: the module needs about 1 minute to initialize after being powered ON. During this
period, it will alternately output high or low level.
5. One characteristic of this sensor is when a body moves close to or moves away from the sensor’s dome
edge, the sensor will work at high sensitively. When a body moves close to or moves away from the
sensor’s dome in a vertical direction (perpendicular to the dome), the sensor cannot detect well (please
take note of this deficiency). Actually this makes sense when you consider that this sensor is usually placed
on a celling as part of a security product. Note: The Sensing Range (distance before a body is detected)
is adjusted by the potentiometer.
We can regard this sensor as a simple inductive switch when in use.

█ support@[Link]
█ [Link]  support@[Link] 187

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

How to use this sensor?


Top Bottom

support@[Link] █
188  support@[Link] [Link] █

Description:
1. You can choose non-repeatable trigger modes or repeatable modes.
L: non-repeatable trigger mode. The module output high level after sensing a body, then when the
delay time is over, the module will output low level. During high level time, the sensor no longer actively
senses bodies.
H: repeatable trigger mode. The distinction from the L mode is that it can sense a body until that body
leaves. After this, it starts to time and output low level after delaying T time.
2. R1 is used to adjust HIGH level lasting time when sensor detects human motion, 1.2s-320s.
3. R2 is used to adjust the maxmum distance the sensor can detect, 3~5m.

Here we connect L and adjust R1 and R2 like below to do this project.

Put you hand close and away from the sensor slowly. Obsever the LED in previous circuit.

It need some time between two detections.

Video: [Link]

Code

In this project, we will use the Infrared Motion Sensor to trigger an LED, essentially making the Infrared Motion
sensor act as a Motion Switch. Therefore, the code is very similar to the earlier project "Push Button Switch
and LED”. The difference is that, when Infrared Motion Sensor detects change, it will output high level; when

█ support@[Link]
█ [Link]  support@[Link] 189

button is pressed, it will output low level. When the sensor output high level, the LED turns ON, or it will turn
OFF.
C Code 23.1.1 SenseLED
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 23.1.1_SenseLED directory of C code.
cd ~/Freenove_Kit/Code/C_Code/23.1.1_SenseLED
2. Use following command to compile "SenseLED.c" and generate executable file "SenseLED".
gcc SenseLED.c -o SenseLED -lwiringPi
3. Run the generated file "SenseLED".
sudo ./SenseLED
After the program is executed, wait 1 minute for initialization. Then move away from or move closer to the
Infrared Motion Sensor and observe whether the LED turns ON or OFF. The Terminal window will continuously
display the state of LED. As is shown below:

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3
4 #define ledPin 1 //define the ledPin
5 #define sensorPin 0 //define the sensorPin
6
7 int main(void)
8 {
9 printf("Program is starting ... \n");
10
11 wiringPiSetup();
12
13 pinMode(ledPin, OUTPUT);
14 pinMode(sensorPin, INPUT);
15
16 while(1){
17
18 if(digitalRead(sensorPin) == HIGH){ //if read value of sensor is HIGH level
19 digitalWrite(ledPin, HIGH); //make led on
20 printf("led turned on >>> \n");
21 }
22 else {
23 digitalWrite(ledPin, LOW); //make led off

support@[Link] █
190  support@[Link] [Link] █

24 printf("led turned off <<< \n");


25 }
26 }
28 return 0;
29 }
It can be seen that the code is based on the same principles of the "ButtonLED" code in addition to
determining the level of the input signal.

█ support@[Link]
█ [Link]  support@[Link] 191

Chapter 24 Ultrasonic Ranging


In this chapter, we learn a module which use ultrasonic to measure distance.

Project 24.1 Ultrasonic Ranging

In this project, we use ultrasonic ranging module to measure distance, and print out the data in the terminal.

Component List

Raspberry Pi (with 40 GPIO) x1 Ultrasonic Module x1


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1

Jumper Wire x4 Resistor 1kΩ x3

Component Knowledge

The Ultrasonic Ranging Module uses the principle that ultrasonic waves will be reflected when they encounter
any obstacles. This is possible by counting the time interval between when the ultrasonic wave is transmitted
to when the ultrasonic wave reflects back after encountering an obstacle. Time interval counting will end after
an ultrasonic wave is received, and the time difference (delta) is the total time of the ultrasonic wave’s journey
from being transmitted to being received. Because the speed of sound in air is a constant, and is about
v=340m/s, we can calculate the distance between the Ultrasonic Ranging Module and the obstacle: s=vt/2.

2S=V·t.
The Ultrasonic Ranging Module integrates a both an ultrasonic transmitter and a receiver. The transmitter is
used to convert electrical signals (electrical energy) into high frequency (beyond human hearing) sound waves
(mechanical energy) and the function of the receiver is opposite of this. The picture and the diagram of the
Ultrasonic Ranging Module are shown below:

support@[Link] █
192  support@[Link] [Link] █

Pin description:
VCC power supply pin
Trig trigger pin
Echo Echo pin
GND GND
Technical specs:
Working voltage: 5V Working current: 12mA
Minimum measured distance: 2cm Maximum measured distance: 200cm
Instructions for Use: output a high-level pulse in Trig pin lasting for least 10uS, the module begins to transmit
ultrasonic waves. At the same time, the Echo pin is pulled up. When the module receives the returned
ultrasonic waves from encountering an obstacle, the Echo pin will be pulled down. The duration of high level
in the Echo pin is the total time of the ultrasonic wave from transmitting to receiving, s=vt/2. This is done
constantly.

█ support@[Link]
█ [Link]  support@[Link] 193

Circuit

Note that the voltage of ultrasonic module is 5V in this circuit.


Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]

support@[Link] █
194  support@[Link] [Link] █

Code

C Code 24.1.1 UltrasonicRanging


First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 24.1.1_UltrasonicRanging directory of C code.
cd ~/Freenove_Kit/Code/C_Code/24.1.1_UltrasonicRanging
2. Use following command to compile "UltrasonicRanging.c" and generate executable file
"UltrasonicRanging".
gcc UltrasonicRanging.c -o UltrasonicRanging -lwiringPi
3. Then run the generated file "UltrasonicRanging".
sudo ./UltrasonicRanging
After the program is executed, aim the Ultrasonic Ranging Module’s detectors (“eyes”) perpendicular to the
surface of an object (try using your hand). The distance between the ultrasonic module and the object will be
displayed in the terminal. As is shown below:

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <sys/time.h>
4
5 #define trigPin 4
6 #define echoPin 5
7 #define MAX_DISTANCE 220 // define the maximum measured distance
8 #define timeOut MAX_DISTANCE*60 // calculate timeout according to the maximum measured
distance
9 //function pulseIn: obtain pulse time of a pin
10 int pulseIn(int pin, int level, int timeout);
11 float getSonar(){ //get the measurement result of ultrasonic module with unit: cm
12 long pingTime;
13 float distance;
14 digitalWrite(trigPin,HIGH); //send 10us high level to trigPin
15 delayMicroseconds(10);
16 digitalWrite(trigPin,LOW);
17 pingTime = pulseIn(echoPin,HIGH,timeOut); //read plus time of echoPin
18 distance = (float)pingTime * 340.0 / 2.0 / 10000.0; //calculate distance with sound speed
340m/s
19 return distance;

█ support@[Link]
█ [Link]  support@[Link] 195

20 }
21
22 int main(){
23 printf("Program is starting ... \n");
24
25 wiringPiSetup();
26
27 float distance = 0;
28 pinMode(trigPin,OUTPUT);
29 pinMode(echoPin,INPUT);
30 while(1){
31 distance = getSonar();
32 printf("The distance is : %.2f cm\n",distance);
33 delay(1000);
34 }
35 return 1;
36 }

First, define the pins and the maximum measurement distance.


#define trigPin 4
#define echoPin 5
#define MAX_DISTANCE 220 //define the maximum measured distance
If the module does not return high level, we cannot wait for this forever, so we need to calculate the time
period for the maximum distance, that is, time Out. timeOut= 2*MAX_DISTANCE/100/340*1000000. The
result of the constant part in this formula is approximately 58.8.
#define timeOut MAX_DISTANCE*60

Subfunction getSonar () function is used to start the Ultrasonic Module to begin measurements and return
the measured distance in cm units. In this function, first let trigPin send 10us high level to start the Ultrasonic
Module. Then use pulseIn () to read the Ultrasonic Module and return the duration time of high level. Finally,
the measured distance according to the time is calculated.
float getSonar(){ // get the measurement results of ultrasonic module, with unit: cm
long pingTime;
float distance;
digitalWrite(trigPin,HIGH); //trigPin send 10us high level
delayMicroseconds(10);
digitalWrite(trigPin,LOW);
pingTime = pulseIn(echoPin,HIGH,timeOut); //read plus time of echoPin
distance = (float)pingTime * 340.0 / 2.0 / 10000.0; // the sound speed is 340m/s, and
calculate distance
return distance;
}

Lastly, in the while loop of main function, get the measurement distance and display it continually.

support@[Link] █
196  support@[Link] [Link] █

while(1){
distance = getSonar();
printf("The distance is : %.2f cm\n",distance);
delay(1000);
}
About function pulseIn():
int pulseIn(int pin, int level, int timeout);
Return the length of the pulse (in microseconds) or 0 if no pulse is completed before the timeout (unsigned
long).

█ support@[Link]
█ [Link]  support@[Link] 197

Chapter 25 Attitude Sensor MPU6050


In this chapter, we will learn about a MPU6050 Attitude sensor, which integrates an Accelerometer and
Gyroscope.

Project 25.1 Read a MPU6050 Sensor Module

In this project, we will read Acceleration and Gyroscope Data of the MPU6050 Sensor.

Component List

Raspberry Pi (with 40 GPIO) x1 MPU6050 x1


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
Jumper Wire x4

support@[Link] █
198  support@[Link] [Link] █

Component knowledge

MPU6050
MPU6050 Sensor Module is a complete 6-axis Motion Tracking Device. It combines a 3-axis Gyroscope, a 3-
axis Accelerometer and a DMP (Digital Motion Processor) all in a small package. The settings of the
Accelerometer and Gyroscope of MPU6050 can be changed. A precision wide range digital temperature
sensor is also integrated to compensate data readings for changes in temperature, and temperature values
can also be read. The MPU6050 Module follows the I2C communication protocol and the default address is
0x68.

The port description of the MPU6050 Module is as follows:


Pin name Pin number Description
VCC 1 Positive pole of power supply with voltage 5V
GND 2 Negative pole of power supply
SCL 3 I2C communication clock pin
SDA 4 I2C communication data pin
XDA 5 I2C host data pin which can be connected to other devices.
XCL 6 I2C host clock pin which can be connected to other devices.
AD0 7 I2C address bit control pin.
Low level: the device address is 0x68
High level: the device address is 0x69
INT 8 Output interrupt pin
For more detail, please refer to the MPU6050 datasheet.

MPU6050 is widely used to assist with balancing vehicles, robots and aircraft, mobile phones and other
products which require stability to control stability and attitude or which need to sense same.

█ support@[Link]
█ [Link]  support@[Link] 199

Circuit

Note that the power supply voltage for MPU6050 module is 5V in this circuit.
Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]

support@[Link] █
200  support@[Link] [Link] █

Code

In this project, we will read the acceleration data and gyroscope data of MPU6050, and print them out.
C Code 25.1.1 MPU6050RAW

First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 25.1.1_MPU6050RAW directory of C code.
cd ~/Freenove_Kit/Code/C_Code/25.1.1_MPU6050
2. Use following command to compile "MPU6050RAW.c", "[Link]" and "[Link]", and generate
executable file "MPU6050RAW".
gcc [Link] [Link] [Link] -o MPU6050RAW
3. Then run the generated file "MPU6050RAW".
sudo ./MPU6050RAW
After the program is executed, the Terminal will display active accelerometer and gyroscope data of the
MPU6050, as well as the conversion to gravity acceleration and angular velocity as units of data. As shown in
the following figure:

The following is the program code:


1 #include <stdio.h>
2 #include <stdint.h>
3 #include <unistd.h>
4 #include "I2Cdev.h"
5 #include "MPU6050.h"
6
7 MPU6050 accelgyro; //creat MPU6050 class object
8
9 int16_t ax, ay, az; //store acceleration data
10 int16_t gx, gy, gz; //store gyroscope data
11
12 void setup() {
13 // initialize device
14 printf("Initializing I2C devices...\n");
15 [Link](); //initialize MPU6050

█ support@[Link]
█ [Link]  support@[Link] 201

16
17 // verify connection
18 printf("Testing device connections...\n");
19 printf([Link]() ? "MPU6050 connection successful\n" : "MPU6050
connection failed\n");
20 }
21
22 void loop() {
23 // read accel/gyro values of MPU6050
24 accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
25 // display accel/gyro x/y/z values
26 printf("a/g: %6hd %6hd %6hd %6hd %6hd %6hd\n",ax,ay,az,gx,gy,gz);
27 printf("a/g: %.2f g %.2f g %.2f g %.2f d/s %.2f d/s %.2f d/s
28 \n",(float)ax/16384,(float)ay/16384,(float)az/16384,
29 (float)gx/131,(float)gy/131,(float)gz/131);
30 }
31
32 int main()
33 {
34 setup();
35 while(1){
36 loop();
37 }
38 return 0;
39 }
Two library files "MPU6050.h" and "I2Cdev.h" are used in the code and will be compiled with others. Class
MPU6050 is used to operate the MPU6050 Sensor. When used, first it initiates an object.
MPU6050 accelgyro;
In the setup function, the MPU6050 is initialized and the result of the initialization will be tested.
void setup() {
// initialize device
printf("Initializing I2C devices...\n");
[Link](); //initialize MPU6050

// verify connection
printf("Testing device connections...\n");
printf([Link]() ? "MPU6050 connection successful\n" : "MPU6050
connection failed\n");
}
In the loop function, read the original data of MPU6050, display them and then convert the original data into
the corresponding acceleration and angular velocity values, then display the converted data out.
void loop() {
// read raw accel/gyro measurements from device
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

support@[Link] █
202  support@[Link] [Link] █

// display accel/gyro x/y/z values


printf("a/g: %6hd %6hd %6hd %6hd %6hd %6hd\n",ax,ay,az,gx,gy,gz);
printf("a/g: %.2f g %.2f g %.2f g %.2f d/s %.2f d/s %.2f d/s
\n",(float)ax/16384,(float)ay/16384,(float)az/16384,
(float)gx/131,(float)gy/131,(float)gz/131);
}
Finally, the main functions, called setup function and loop function respectively.
int main()
{
setup();
while(1){
loop();
}
return 0;
}
About class MPU6050:
Class MPU6050
This is a class library used to operate the MPU6050, which can directly read and set the MPU6050. Here are
its functions:
MPU6050()/MPU6050(uint8_t address):
Constructor. The parameter is I2C address, and the default I2C address is 0x68.
void initialize();
Initialization function, used to wake up MPU6050. Range of accelerometer is ±2g and range of gyroscope
is ±250 degrees/sec.
void getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz);
Get the original data of accelerometer and gyroscope.
int16_t getTemperature();
Get the original temperature data of MPU6050.
For details about more relevant member functions, pleases refer to MPU6050.h or visit:
[Link]

█ support@[Link]
█ [Link]  support@[Link] 203

Chapter 26 High-sensitivity microphone sensor


In this chapter, we will learn how to use High-sensitivity microphone sensor.

Project 26.1 High-sensitivity microphone sensor and LED

This project will use a high-sensitivity microphone sensor to make a sound-controlled light.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x6


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
High-sensitivity microphone sensor x1 LED x1 Resistor 220Ω x1

Component knowledge

High-sensitivity microphone sensor


The high-sensitivity microphone sensor module is a component that accepts sound waves and converts them
into electrical signals, which can detect the sound intensity in the surrounding environment.
When using it, it should be noted that this sensor can only identify the presence or absence of sound
(according to the vibration principle), but cannot identify the size of the sound or the sound of a specific
frequency.
This module has 4 pins: digital output (DO), analog output (AO), power supply positive pin and power supply
negative pin. AO can output the voltage signal of the microphone in real time. When the ambient sound
intensity does not reach the set threshold, the DO outputs a low-level signal, and when the ambient sound
intensity exceeds the set threshold, it outputs a high-level signal, and the sensitivity can be adjusted by a
potentiometer. When in use, adjust the potentiometer to make the sensitivity to sound reach a more
appropriate value, and then read the digital output signal of the module through a pin on the development
board. You can speak to the sensor. When the sensor detects a speaking sound, the DO pin outputs a high
level; when the sensor does not detect a speaking sound, the DO pin outputs a low level.

support@[Link] █
204  support@[Link] [Link] █

Below is the pinout of the high-sensitivity microphone sensor.


Pin description:
symbol Function
DO Digital signal output
VCC Power supply pin, +3.3V~5.0V
GND GND
AO Analog signal output
Since the default sensitivity of the high-sensitivity microphone sensor is high, the two LED lights on the
module are lit up after power-on, and the sensitivity should be adjusted to an appropriate value at this time.
When the potentiometer is adjusted clockwise, the module identification sensitivity increases; When
counterclockwise adjustment potentiometer, module recognition sensitivity decreases. Please adjust the
potentiometer before using the module to make its sensitivity reach the appropriate value. Under normal
circumstances, you need counterclockwise rotation of the potentiometer, so that the output of the module
LED off, when the sensitivity is low can be appropriate clockwise adjustment of the potentiometer, please
ensure that your sensor output LED is extinguished when energized, in order to identify the sound.
Please do not use voltage beyond the power supply range to avoid damage to the high-sensitivity
microphone sensor.

Circuit

Schematic diagram

█ support@[Link]
█ [Link]  support@[Link] 205

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Video: [Link]

Code

C Code 26.1.1 VoiceLamp


First observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 26.1.1_VoiceLamp directory of C code.
cd ~/Freenove_Kit/Code/C_Code/26.1.1_VoiceLamp
2. Use following command to compile " VoiceLamp.c" and generate executable file " VoiceLamp ".
gcc VoiceLamp.c -o VoiceLamp -lwiringPi
3. Run the generated file "VoiceLamp "
sudo ./VoiceLamp
After the program is executed, when you speak to the sensor, the LED will turn on for 5 seconds. After 5
seconds, the LED will turn off. When the sensor does not recognize the sound, the LED will turn off.

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #define ledPin 0 //define the ledPin

support@[Link] █
206  support@[Link] [Link] █

5 #define sensorPin 1 //define the sensorPin


6
7 void main(void)
8 {
9 printf("Program is starting ... \n");
10 wiringPiSetup(); //Initialize wiringPi.
11 pinMode(ledPin, OUTPUT); //Set ledPin to output
12 pinMode(sensorPin, INPUT);//Set sensorPin to input
13 while(1){
14 if(digitalRead(sensorPin) == HIGH){ //The sensor is blocked
15 digitalWrite(ledPin, HIGH); //Make GPIO output HIGH level
16 delay(5000);
17 digitalWrite(ledPin, LOW);
18 printf("led turned on >>>\n"); //Output information on terminal
19 }
20 else { // The sensor is not blocked
21 digitalWrite(ledPin, LOW); //Make GPIO output LOW level
22 printf("led turned off <<<\n"); //Output information on terminal
23 }
24 }
25 }

Read the signal pin of the high-sensitivity microphone sensor, and determine whether the state of the sensor
is high level. If it is high level, the LED will continue to turn on for 5 seconds.
if(digitalRead(sensorPin) == LOW){ //The sensor is blocked
digitalWrite(ledPin, HIGH); //Make GPIO output HIGH level
delay(5000);
digitalWrite(ledPin, LOW);
printf("led turned on >>>\n"); //Output information on terminal
}
else { //The sensor is not blocked
digitalWrite(ledPin, LOW); //Make GPIO output LOW level
printf("led turned off <<<\n"); //Output information on terminal

█ support@[Link]
█ [Link]  support@[Link] 207

Chapter 27 Touch Sensor TTP223


In this chapter, we will learn how to use the touch sensor.

Project 27.1 Touch Sensor and LED

This project will use the touch sensor to control the LED to emit different brightness.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x7


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
TTP223 Touch Sensor x1 LED x1 Resistor 220Ω x1

Component knowledge

Touch Sensor
The touch sensor module is a capacitive touch switch module based on TTP223 chip. Its use is very simple.
This module has 3 pins: signal pin, power positive pin and power negative pin. When the positive and negative
pins of the module are connected to a suitable power supply, the module starts to work. At this time, only
one pin on the development board is needed to read the output signal of the module. For example, you can
touch the front and back of the module. When the touch sensor is touched, the signal pin outputs a high level;
when the touch sensor is not touched, it outputs a low level.

Below is the pinout of the touch sensor.


Pin description:
symbol Function
SIG Output control signal
VCC Power supply pin, +2.0V~5.5V
GND GND
Please do not use voltage beyond the power supply range to avoid damage to the touch sensor.

support@[Link] █
208  support@[Link] [Link] █

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

█ support@[Link]
█ [Link]  support@[Link] 209

Code

C Code 27.1.1 TouchSensor


First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 27.1.1_TouchSensor directory of C code.
cd ~/Freenove_Kit/Code/C_Code/27.1.1_TouchSensor
2. Use following command to compile " TouchSensor.c " and generate executable file " TouchSensor ".
gcc TouchSensor.c -o TouchSensor -lwiringPi
3. Run the generated file "TouchSensor".
sudo ./TouchSensor
In this code, we use the touch sensor to adjust the brightness of the LED. Every time you touch the sensor
with your hand, the brightness of the LED changes.

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <softPwm.h>
4 #define ledPin 0 //define the ledPin
5 #define SensorPin 1 //define the SensorPin
6
7 int SensorState=LOW; //store the State of button
8 int lastSensorState=LOW;//store the lastState of Sensor
9 long lastChangeTime; //store the change time of Sensor state
10 long captureTime=10; //set the stable time for Sensor state
11 int Sensorvalue;
12 int grade=0;
13
14 int main(void)
15 {
16 printf("Program is starting...\n");
17 wiringPiSetup(); //Initialize wiringPi.
18 softPwmCreate(ledPin, 0, 100);//Creat SoftPWM pin
19 pinMode(SensorPin, INPUT); //Set SensorPin to input
20 pullUpDnControl(SensorPin, PUD_DOWN); //pull up to high level
21 while(1){
22 Sensorvalue = digitalRead(SensorPin); //read the current state of Sensor
23 if( Sensorvalue != lastSensorState){ //if the Sensor state has changed, record the
time point
24 lastChangeTime = millis();
25 }
26 //if changing-state of the Sensor last beyond the time we set, we consider that

support@[Link] █
210  support@[Link] [Link] █

27 //the current Sensor state is an effective change rather than a buffeting


28 if(millis() - lastChangeTime > captureTime){
29 //if sensor state is changed, update the data.
30 if(Sensorvalue != SensorState){
31 SensorState = Sensorvalue;
32 //if the state is low, it means the action is pressing
33 if(SensorState == HIGH){
34 grade=grade+1;
35 printf("Sensor is pressed!\n");
36 }
37 }
38 }
39 else if(grade==1){
40 softPwmWrite(ledPin, 35);
41 }
42 else if(grade==2){
43 softPwmWrite(ledPin, 65);
44 }
45 else if(grade==3){
46 softPwmWrite(ledPin, 100);
47 }
48 else if(grade==4){
49 grade=0;
50 }
51 else {
52 softPwmWrite(ledPin, 0);
53 }
54 lastSensorState = Sensorvalue;
55 }
56 return 0;
57 }

Read the signal pin of the touch sensor, and determine whether the state of the touch sensor has changed. If
it has changed, record the time point.
Sensorvalue = digitalRead(SensorPin); //read the current state of Sensor
if( Sensorvalue != lastSensorState){ //if the Sensor state has changed, record the
time point
lastChangeTime = millis();
}

Check whether the state of the touch sensor is consistent with the previous moment every captureTime
milliseconds. If not, assign the state of the touch sensor to the touch sensor variable SensorState.
if(millis() - lastChangeTime > captureTime){
//if sensor state is changed, update the data.

█ support@[Link]
█ [Link]  support@[Link] 211

if(Sensorvalue != SensorState){
SensorState = Sensorvalue;
Each time the sensor is touched, a variable grade is used to record the number of touches.
if(Sensorvalue != SensorState){
SensorState = Sensorvalue;
if(SensorState == HIGH){
grade=grade+1;
printf("Sensor is pressed!\n");
}
}

Set the LED light to emit different brightness according to the value of grade.
if(grade==1){
softPwmWrite(ledPin, 35);
}
else if(grade==2){
softPwmWrite(ledPin, 65);
}
else if(grade==3){
softPwmWrite(ledPin, 100);
}
else if(grade==4){
grade=0;
}
else {
softPwmWrite(ledPin, 0);
}

support@[Link] █
212  support@[Link] [Link] █

Project 27.2 Touch Sensor and RGB LED

This project uses a touch sensor to control RGB LED to emit different colors.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x10


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
TTP223 Touch Sensor x1 RGB LED x1 Resistor 220Ω x3

Circuit

Schematic diagram

█ support@[Link]
█ [Link]  support@[Link] 213

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Code

C Code 27.2.1 Discolor


First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 27.2.1_Discolor directory of C code.
cd ~/Freenove_Kit/Code/C_Code/27.2.1_Discolor
2. Use following command to compile " Discolor.c " and generate executable file " Discolor ".
gcc Discolor.c -o Discolor -lwiringPi
3. Run the generated file "Discolor".
sudo ./Discolor
After the program is executed, we can use the touch sensor to adjust the color change of the RGB LED. Every
time the sensor is touched, the color of the RGB LED changes. Color changes from red to green to blue.

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <softPwm.h>
4 #include <stdlib.h>
5 #define SensorPin 1 //define the SensorPin
6 #define ledPinRed 3
7 #define ledPinGreen 2
8 #define ledPinBlue 0
9

support@[Link] █
214  support@[Link] [Link] █

10 int SensorState=LOW; //store the State of Sensor


11 int lastSensorState=LOW;//store the lastState of Sensor
12 long lastChangeTime; //store the change time of Sensor state
13 long captureTime=10; //set the stable time for Sensor state
14 int Sensorvalue;
15 int grade=0;
16
17 void setupLedPin(void)
18 {
19 softPwmCreate(ledPinRed, 0, 100); //Creat SoftPWM pin for red
20 softPwmCreate(ledPinGreen,0, 100); //Creat SoftPWM pin for green
21 softPwmCreate(ledPinBlue, 0, 100); //Creat SoftPWM pin for blue
22 }
23 void setLedColor(int r, int g, int b)
24 {
25 softPwmWrite(ledPinRed, r); //Set the duty cycle
26 softPwmWrite(ledPinGreen, g); //Set the duty cycle
27 softPwmWrite(ledPinBlue, b); //Set the duty cycle
28 }
29 int main(void)
30 {
31 int r,g,b;
32 printf("Program is starting...\n");
33 wiringPiSetup(); //Initialize wiringPi.
34 pinMode(SensorPin, INPUT); //Set SensorPin to input
35 pullUpDnControl(SensorPin, PUD_DOWN); //pull up to high level
36 setupLedPin();
37 r=100;
38 g=100;
39 b=100;
40 setLedColor(r,g,b); // set the duty cycle value
41 while(1){
42 Sensorvalue = digitalRead(SensorPin); //read the current state of Sensor
43 if( Sensorvalue != lastSensorState){ //if the Sensor state has changed, record the
time point
44 lastChangeTime = millis();
45 }
46 //if changing-state of the Sensor last beyond the time we set, we consider that
47 //the current Sensor state is an effective change rather than a buffeting
48 if(millis() - lastChangeTime > captureTime){
49 //if Sensor state is changed, update the data.
50 if(Sensorvalue != SensorState){
51 SensorState = Sensorvalue;
52 //if the state is low, it means the action is pressing

█ support@[Link]
█ [Link]  support@[Link] 215

53 if(SensorState == HIGH){
54 printf("Sensor is pressed!\n");
55 grade=grade+1;
56 }
57 }
58 }
59 if(grade==1){
60 r=0;
61 g=100;
62 b=100;
63 setLedColor(r,g,b); //set the duty cycle value
64 printf("r=%d, g=%d, b=%d \nThe current color is red\n",r,g,b);
65 }
66 else if(grade==2){
67 r=100;
68 g=0;
69 b=100;
70 setLedColor(r,g,b); //set the duty cycle value
71 printf("r=%d, g=%d, b=%d \nThe current color is green\n",r,g,b);
72 }
73 else if(grade==3){
74 r=100;
75 g=100;
76 b=0;
77 setLedColor(r,g,b); //set the duty cycle value
78 printf("r=%d, g=%d, b=%d \nThe current color is blue\n",r,g,b);
79 }
80 else if(grade==4){
81 grade=0;
82 }
83 else {
84 r=100;
85 g=100;
86 b=100;
87 setLedColor(r,g,b); //set the duty cycle value
88 }
89 lastSensorState = Sensorvalue;
90 }
91 return 0;
92 }

Define a function called setupLedPin() to initialize the PWM configuration of the R, G, and B pins.
void setupLedPin(void)
{

support@[Link] █
216  support@[Link] [Link] █

softPwmCreate(ledPinRed, 0, 100); //Creat SoftPWM pin for red


softPwmCreate(ledPinGreen,0, 100); //Creat SoftPWM pin for green
softPwmCreate(ledPinBlue, 0, 100); //Creat SoftPWM pin for blue
}

Determine the number of times the sensor is pressed, and control the pin R, G, and B to output different PWM
values, thereby controlling the color of the RGB LED.
if(grade==1){
r=0;
g=100;
b=100;
setLedColor(r,g,b); //set the duty cycle value
printf("r=%d, g=%d, b=%d \nThe current color is red\n",r,g,b);
}

█ support@[Link]
█ [Link]  support@[Link] 217

Chapter 28 U-shaped photoelectric sensor


In this chapter, we will learn how to use a U-shaped photoelectric sensor.

Project 28.1 U-shaped photoelectric sensor and LED

This project uses a U-shaped photoelectric sensor to control the state of the LED.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x6


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
U-shaped photoelectric sensor x1 LED x1 Resistor 220Ω x1

or

Component knowledge

U-shaped photoelectric sensor


The U-shaped photoelectric sensor is a through-beam photoelectric sensor, which consists of a transmitting
end and a receiving end. Its working principle is blocking and conducting the infrared emission light will
change the current induced by the infrared receiving tube.
This module has 4 pins: digital output (DO), analog output (AO), power supply positive pin and power supply
negative pin. When the positive and negative pins of the module are connected to a suitable power supply,
the module starts to work. Only one pin on the development board is needed to read the digital output (DO)
signal of the module. When the photoelectric sensor is blocked, the digital signal pin outputs a low level. If
the photoelectric sensor is not blocked, it outputs a high level.
Below is the pinout of the touch sensor.
Pin description:
symbol Function
VCC Power supply pin, +3.3V~5.5V
DO Output control signal(High or low level)
AO Output invalid

support@[Link] █
218  support@[Link] [Link] █

GND GND
Please do not use the voltage beyond the power supply range to avoid damage to the U-shaped photoelectric
sensor.
The difference between the above two U-type photoelectric sensors is that in addition to the different pin
sequence, the output signal is opposite when you block it, that is, there are modules that output high level
and low level U-type photoelectric sensor. The specific module is subject to the one in your hand. Please
check the pin sequence of your U-shaped photoelectric sensor and replace the appropriate wiring to avoid
permanent damage to your raspberry PI.

█ support@[Link]
█ [Link]  support@[Link] 219

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]
Please check the sequence of your U-shaped photoelectric sensor and select the appropriate wiring to
avoid permanent damage to your raspberry PI.

or

support@[Link] █
220  support@[Link] [Link] █

Code

C Code 28.1.1 PhotoSensor


First observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 28.1.1_PhotoSensor directory of C code.
cd ~/Freenove_Kit/Code/C_Code/28.1.1_PhotoSensor
2. Use following command to compile " PhotoSensor.c" and generate executable file "PhotoSensor".
gcc PhotoSensor.c -o PhotoSensor -lwiringPi
3. Run the generated file " PhotoSensor"
sudo ./PhotoSensor
When you use the module whose output signal is low level, after the program is executed, when the
photoelectric sensor is blocked, the LED lights up, when the photoelectric sensor is not blocked, the LED turns
off.
When you use the module with high output signal, the LED will be off when the photoelectric sensor is blocked
and on when the photoelectric sensor is not blocked after the program is executed.
The phenomena are opposite, depending on the module in your hand.
The following is the program code:
1 #include <wiringPi.h>
2 #include <stdio.h>
3 #define ledPin 0 //define the ledPin
4 #define sensorPin 1 //define the sensorPin
5
6 void main(void)
7 {
8 printf("Program is starting ... \n");
9 wiringPiSetup(); //Initialize wiringPi.
10 pinMode(ledPin, OUTPUT); //Set ledPin to output
11 pinMode(sensorPin, INPUT);//Set sensorPin to input
12 while(1){
13 if(digitalRead(sensorPin) == LOW){ // The sensor is blocked
14 digitalWrite(ledPin, HIGH); //Make GPIO output HIGH level
15 printf("The sensor is blocked, led turned on >>>\n"); //Output information on
16 terminal
17 }
18 else { // The sensor is not blocked
19 digitalWrite(ledPin, LOW); //Make GPIO output LOW level
20 printf("The sensor is not blocked, led turned off <<<\n");//Output information on
21 terminal
22 }
23 }
24 }

█ support@[Link]
█ [Link]  support@[Link] 221

Project 28.2 U-shaped photoelectric sensor and buzzer

This project uses U-shaped photoelectric sensor to make a simple sound and light alarm.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x10


GPIO Expansion Board & Ribbon Cable
x1
Breadboard x1
Active buzzer x1 NPN transistorx1 Resistor 1kΩx1
(S8050)

U-shaped photoelectric sensor x1 LED x1 Resistor 220Ωx1

or

support@[Link] █
222  support@[Link] [Link] █

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]
Please check the sequence of your U-shaped photoelectric sensor and select the appropriate wiring to
avoid permanent damage to your raspberry PI.

or

█ support@[Link]
█ [Link]  support@[Link] 223

Code

C Code 28.2.1 Alertor


First observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 28.2.1_Alertor directory of C code.
cd ~/Freenove_Kit/Code/C_Code/28.2.1_Alertor
2. Use following command to compile " Alertor.c" and generate executable file "Alertor".
gcc Alertor.c -o Alertor -lwiringPi
3. Run the generated file " Alertor"
sudo ./Alertor
After the program is executed, every time the U-shaped photoelectric sensor is blocked by hand, the buzzer
will sound an alarm, and the LED will flash to remind.
The following is the program code:
1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #define ledPin 0 //define the ledPin
5 #define sensorPin 1 //define the buttonPin
6 #define buzzerPin 2 //define the buzzerPin
7
8 void alarm(int times){
9 while(times--){
10 digitalWrite(buzzerPin, HIGH);
11 digitalWrite(ledPin, HIGH);
12 delay(50);
13 digitalWrite(buzzerPin, LOW);
14 digitalWrite(ledPin, LOW);
15 delay(50);
16 }
17 }
18
19 void sensorEven(void){
20 alarm(3);
21 }
22 void main(void)
23 {
24 printf("Program is starting ... \n");
25 wiringPiSetup(); //Initialize wiringPi.
26 pinMode(ledPin, OUTPUT); //Set ledPin to output
27 pinMode(sensorPin, INPUT);//Set sensorPin to input
28 pinMode(buzzerPin, OUTPUT);

support@[Link] █
224  support@[Link] [Link] █

29 delay(100);
30 wiringPiISR(sensorPin,INT_EDGE_BOTH,&sensorEven);
31 digitalWrite(buzzerPin, LOW);
32 while(1){
33 }
34 }

The wiringPiISR() function associates the sensor pins with sensorEven().Because there are high level triggering
module and low level triggering module in the U-type photoelectric sensor, we use the double-edge
detection method here to make the program compatible with the module in your hand. When sensorPin
detects low level or high level, it will call and execute the sensorEven() function.
wiringPiISR(sensorPin,INT_EDGE_BOTH,&sensorEven);
void sensorEven(void){
alarm(3);
}

The function alarm() is used to control the active buzzer to emit an alarm sound and control the LED to flash
at the same time. Use variable times to pass in the number of times the alarm sounds and the LED blinks.
void alarm(int times){
while(times--){
digitalWrite(buzzerPin, HIGH);
digitalWrite(ledPin, HIGH);
delay(50);
digitalWrite(buzzerPin, LOW);
digitalWrite(ledPin, LOW);
delay(50);
}
}

int wiringPiISR (int pin, int edgeType, void (*function)(void)) ;


This is an interrupt detection function. The first parameter specifies the IO port to detect. The second
parameter specifies the trigger method to detect. The third parameter specifies the function name. The
function will be executed when the specified action is detected.
The following are common detection triggers:
INT_EDGE_FALLING: falling edge trigger
INT_EDGE_RISING: rising edge trigger
INT_EDGE_BOTH: triggers both up and down

█ support@[Link]
█ [Link]  support@[Link] 225

Chapter 29 Hall sensor


In this chapter, we will learn how to use Hall sensor.

Project 29.1 Hall sensor and LED

This project uses hall sensor to control the state of LED.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x6


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
Hall sensor x1 LED x1 Resistor 220Ω x1 Speaker x1

or

Component knowledge

Hall sensor
Hall sensor is a magnetic field sensor made according to the Hall effect. Based on the Hall effect, Hall voltage
varies with magnetic field strength. Hall sensors can be divided into linear (analog) Hall sensors and switching
Hall sensors. Linear Hall sensors have two outputs: analog output (AO), digital output (DO). Switching Hall
sensors only have digital output (DO) and the analog output (AO) output has no effect. In this project, the
switch Hall sensor is used. Its use is very simple.
This module has 4 pins: digital output (DO), analog output (AO), power supply positive pin and power supply
negative pin. When the positive and negative pins of the module are connected to a suitable power supply,
the module starts to work. Only one pin on the development board is needed to read the digital output (DO)
signal of the module. In the project, the speaker is used as the magnetic field source, when you put the sensor
close to the magnetic field (speaker), the DO outputs low level, and if the sensor does not sense the magnetic
field (speaker), the DO outputs high level.

support@[Link] █
226  support@[Link] [Link] █

Below is the pinout of the Hall sensor.


Pin description:
symbol Function
VCC Power supply pin, +3.3V~5.5V
DO Output control signal
AO Output invalid
GND GND
Please do not use voltage beyond the power supply range to avoid damage to the Hall sensor.
For the above two hall sensors, their difference is only the pin sequence is different, please get the Hall sensor,
check its sequence, change the corresponding wiring, so as not to cause permanent damage to your raspberry
PI.

█ support@[Link]
█ [Link]  support@[Link] 227

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]
Please check the sequence of your Hall sensor and select the appropriate wiring to avoid permanent
damage to your raspberry PI.

or

support@[Link] █
228  support@[Link] [Link] █

Code

C Code 29.1.1 HallSensor


First observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 29.1.1_HallSensor directory of C code.
cd ~/Freenove_Kit/Code/C_Code/29.1.1_HallSensor
2. Use following command to compile " HallSensor.c" and generate executable file "HallSensor".
gcc HallSensor.c -o HallSensor -lwiringPi
3. Run the generated file "HallSensor"
sudo ./HallSensor
After the program is executed, when the sensor is close to the magnetic field (horn) by hand, the LED will turn
on, and if the sensor does not sense the magnetic field (horn), the LED will turn off.

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #define ledPin 0 //define the ledPin
4 #define sensorPin 1 //define the sensorPin
5
6 void main(void)
7 {
8 printf("Program is starting ... \n");
9 wiringPiSetup(); //Initialize wiringPi.
10 pinMode(ledPin, OUTPUT); //Set ledPin to output
11 pinMode(sensorPin, INPUT);//Set sensorPin to input
12 while(1){
13 if(digitalRead(sensorPin) == LOW){ // The sensor is blocked
14 digitalWrite(ledPin, HIGH); //Make GPIO output HIGH level
15 printf("led turned on >>>\n"); //Output information on terminal
16 }
17 else { // The sensor is not blocked
18 digitalWrite(ledPin, LOW); //Make GPIO output LOW level
19 printf("led turned off <<<\n");//Output information on terminal
20 }
21 }
22 }

█ support@[Link]
█ [Link]  support@[Link] 229

Project 29.2 Hall Sensor and Buzzer

This project uses Hall sensor to make a simple magnetic field detection sound and light alarm.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x10


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
Active buzzer x1 NPN transistorx1 LED x1
(S8050)

Hall sensor x1 Resistor 220Ω x1 Resistor 1kΩ x1 Speaker x1

or

For the above two hall sensors, their difference is only the pin sequence is different, please get the Hall sensor,
check its sequence, change the corresponding wiring, so as not to cause permanent damage to your raspberry
PI.

support@[Link] █
230  support@[Link] [Link] █

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]
Please check the sequence of your Hall sensor and select the appropriate wiring to avoid permanent
damage to your raspberry PI.

or

█ support@[Link]
█ [Link]  support@[Link] 231

Code

C Code 29.2.1 Alertor


First observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 29.2.1_Alertor directory of C code.
cd ~/Freenove_Kit/Code/C_Code/29.2.1_Alertor
2. Use following command to compile " Alertor.c" and generate executable file "Alertor".
gcc Alertor.c -o Alertor -lwiringPi
3. Run the generated file " Alertor"
sudo ./Alertor
After the program is executed, every time the sensor is close to the magnetic field (speaker) by hand, the
buzzer will sound an alarm, and the LED will flash to remind.

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #define ledPin 0 //define the ledPin
5 #define sensorPin 1 //define the buttonPin
6 #define buzzerPin 2 //define the buzzerPin
7
8 void alarm(int times){
9 while(times--){
10 digitalWrite(buzzerPin, HIGH);
11 digitalWrite(ledPin, HIGH);
12 delay(50);
13 digitalWrite(buzzerPin, LOW);
14 digitalWrite(ledPin, LOW);
15 delay(50);
16 }
17 }
18
19 void sensorEven(void){
20 alarm(3);
21 }
22 void main(void)
23 {
24 printf("Program is starting ... \n");
25 wiringPiSetup(); //Initialize wiringPi.
26 pinMode(ledPin, OUTPUT); //Set ledPin to output
27 pinMode(sensorPin, INPUT);//Set sensorPin to input

support@[Link] █
232  support@[Link] [Link] █

28 pinMode(buzzerPin, OUTPUT);
29 delay(100);
30 wiringPiISR(sensorPin,INT_EDGE_FALLING,&sensorEven);
31 digitalWrite(buzzerPin, LOW);
32 while(1){
33 }
34 }

█ support@[Link]
█ [Link]  support@[Link] 233

Chapter 30 Infrared Obstacle Avoidance Sensor


In this chapter, we will learn how to use infrared obstacle avoidance sensor.

Project 30.1 Infrared obstacle avoidance sensor and LED

This project uses infrared obstacle avoidance sensor to change the state of LED.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x6


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
Infrared obstacle avoidance sensor x1 LED x1 Resistor 220Ω x1

Component knowledge

Infrared obstacle avoidance sensor


The infrared obstacle avoidance sensor module is a distance adjustable obstacle avoidance sensor. The sensor
has strong adaptability to ambient light and high precision. It has a pair of infrared emitting and receiving
tubes. The transmitting tube emits infrared rays of a certain frequency. When the detection direction
encounters an obstacle (reflecting surface), the infrared rays are reflected back and are received by the
receiving tube. The indicator light is on at this time. After the circuit processing, the signal output pin outputs
digital signal. The detection distance can be adjusted by the potentiometer knob, the effective distance is 2 ~
30cm, and the detection angle is 35°.
This module has 3 pins: signal pin, power positive pin and power negative pin. When the positive and negative
pins of the module are connected to a suitable power supply, the module starts to work. At this time, only
one pin on the development board is needed to read the output signal of the module. When the module is
in use, the detection distance can be adjusted to a suitable value through the potentiometer knob. You can
use your hand to block the module at a certain distance. When the infrared obstacle avoidance sensor is
blocked, the signal pin outputs a low level; if the infrared obstacle avoidance sensor is not blocked, it outputs
a high level.

support@[Link] █
234  support@[Link] [Link] █

Below is the pinout of infrared obstacle avoidance sensor.


Pin description:
symbol Function
OUT Output control signal
VCC Power supply pin, +3.3V~5.0V
GND GND
Please do not use the voltage beyond the power supply range to avoid damage to the infrared obstacle
avoidance sensor.

Circuit

Schematic diagram

█ support@[Link]
█ [Link]  support@[Link] 235

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Code

C Code 30.1.1 InfraredSensor


First observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 30.1.1_InfraredSensor directory of C code.
cd ~/Freenove_Kit/Code/C_Code/30.1.1_InfraredSensor
2. Use following command to compile " InfraredSensor.c" and generate executable file " InfraredSensor ".
gcc InfraredSensor.c -o InfraredSensor -lwiringPi
3. Run the generated file "InfraredSensor "
sudo ./InfraredSensor
After the program is executed, when you block the sensor with your hand at a certain distance or the sensor
encounters an obstacle, the LED will turn on, and when the sensor is not blocked or the sensor does not
encounter an obstacle, the LED will turn off.

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #define ledPin 0 //define the ledPin
4 #define sensorPin 1 //define the sensorPin
5
6 void main(void)

support@[Link] █
236  support@[Link] [Link] █

7 {
8 printf("Program is starting ... \n");
9 wiringPiSetup(); //Initialize wiringPi.
10 pinMode(ledPin, OUTPUT); //Set ledPin to output
11 pinMode(sensorPin, INPUT);//Set sensorPin to input
12 while(1){
13 if(digitalRead(sensorPin) == LOW){
14 digitalWrite(ledPin, HIGH); //Make GPIO output HIGH level
15 printf("led turned on >>>\n"); //Output information on terminal
16 }
17 else {
18 digitalWrite(ledPin, LOW); //Make GPIO output LOW level
19 printf("led turned off <<<\n");//Output information on terminal
20 }
21 }
22 }

█ support@[Link]
█ [Link]  support@[Link] 237

Project 30.2 Infrared obstacle avoidance sensor and buzzer

This project uses an infrared obstacle avoidance sensor to make a simple reminder.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x10


GPIO Expansion Board & Ribbon Cable
x1
Breadboard x1
Active buzzer x1 NPN transistorx1 Resistor 1kΩx1
(S8050)

Infrared obstacle avoidance sensor x1 LED x1 Resistor 220Ωx1

support@[Link] █
238  support@[Link] [Link] █

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

█ support@[Link]
█ [Link]  support@[Link] 239

Code

C Code 30.2.1 Alertor


First observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 30.2.1_Alertor directory of C code.
cd ~/Freenove_Kit/Code/C_Code/30.2.1_Alertor
2. Use following command to compile " Alertor.c" and generate executable file "Alertor".
gcc Alertor.c -o Alertor -lwiringPi
3. Run the generated file " Alertor"
sudo ./Alertor
After the program is executed, when you block the sensor with your hand at a certain distance or the sensor
encounters an obstacle, the buzzer will sound a reminder, and the LED will flash to remind you.

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #define ledPin 0 //define the ledPin
5 #define sensorPin 1 //define the buttonPin
6 #define buzzerPin 2 //define the buzzerPin
7
8 void alarm(int times){
9 while(times--){
10 digitalWrite(buzzerPin, HIGH);
11 digitalWrite(ledPin, HIGH);
12 delay(50);
13 digitalWrite(buzzerPin, LOW);
14 digitalWrite(ledPin, LOW);
15 delay(50);
16 }
17 }
18
19 void sensorEven(void){
20 alarm(3);
21 }
22 void main(void)
23 {
24 printf("Program is starting ... \n");
25 wiringPiSetup(); //Initialize wiringPi.
26 pinMode(ledPin, OUTPUT); //Set ledPin to output
27 pinMode(sensorPin, INPUT);//Set sensorPin to input

support@[Link] █
240  support@[Link] [Link] █

28 pinMode(buzzerPin, OUTPUT);
29 delay(100);
30 wiringPiISR(sensorPin,INT_EDGE_FALLING,&sensorEven);
31 digitalWrite(buzzerPin, LOW);
32 while(1){
33 }
34 }

█ support@[Link]
█ [Link]  support@[Link] 241

Chapter 31 Rotary Encoder


In this chapter, we will learn how to use rotary encoder.

Project 31.1 Rotary Encoder

This project uses a rotary encoder to make a simple counter.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x7


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
Rotary encoder x1

Component knowledge

Rotary Encoder
A rotary encoder is a rotary sensor that converts the rotational displacement into a periodic electrical signal,
and then converts the electrical signal into a count pulse, and uses the number of pulses to indicate the
magnitude of the rotational displacement. It drives the internal grating disc to rotate through the rotation of
the knob. Many slits are preset on the grating disc. The rotation of the grating disc causes the light passing
through the slits to produce pulse changes. After the signal is processed by the subsequent circuit, it is output
as a pulse signal. Finally, The rotary displacement of the knob can be obtained through the output of the
signal pin. The encoder generates pulse signals through the configuration of the internal light source and
photosensitive element.
The working principle of the encoder and the schematic diagram of the output waveform are as follows:

support@[Link] █
242  support@[Link] [Link] █

A rotary encoder gives two-phase square waves, which are 90° out of phase, commonly referred to as A
channel and B channel. One of the channels gives the information related to the rotation speed. The
information of the rotation direction is obtained by sequentially comparing the signals of the two channels.
There is also a special signal called Z or zero channel, which gives the absolute zero position of the encoder.
This signal is a square wave that coincides with the center line of the A channel square wave.
The following is the internal cross-sectional structure diagram of the encoder:

The number of pulses per revolution of the rotary encoder in this project is 20. Its working voltage is 5V. The
sensor has 5 pins: SW, CLK, DT, power supply positive pin and power supply negative pin. Among them, the
SW pin is the input signal pin, the rotary encoder sensor itself is also a button, when the button is pressed,
the SW pin will jump from high level to low level. The CLK pin is a rotation signal pin. When not rotating, this
pin outputs a high level, and when rotating, it outputs a low level. The DT pin is used to determine the direction
of rotation. If this pin is high when it is not rotating, and becomes low when it is rotating, it means that
clockwise rotation has occurred. When this pin is high when it is rotating, it means that counterclockwise
rotation has occurred. When the positive and negative pins of the module are connected to a suitable power
supply, the module starts to work. At this time, three pins on the development board need to be used to read
the SW, CLK and DT of the module respectively. Then according to the above principle, the state of the rotary
encoder can be determine.
For example, when you turn the encoder clockwise by hand, the CLK outputs low level, and the DT changes
from high level to low level. When you rotate the encoder counterclockwise by hand, the CLK outputs low

█ support@[Link]
█ [Link]  support@[Link] 243

level, and the DT changes from low level to high level. When you press the rotary encoder by hand, the SW
signal outputs low level.

support@[Link] █
244  support@[Link] [Link] █

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

█ support@[Link]
█ [Link]  support@[Link] 245

Code

C Code 31.1.1 RotaryEncoder


First observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 31.1.1_RotaryEncoder directory of C code.
cd ~/Freenove_Kit/Code/C_Code/31.1.1_RotaryEncoder
2. Use following command to compile " RotaryEncoder.c" and generate executable file "RotaryEncoder".
gcc RotaryEncoder.c -o RotaryEncoder -lwiringPi
3. Run the generated file "RotaryEncoder".
sudo ./RotaryEncoder
After the program is executed, the rotary encoder can count the number of output pulses during the forward
and reverse rotation. When the rotary encoder is rotated clockwise by hand, the count value will increase.
When the rotary encoder is rotated counterclockwise by hand , the count value will decrease. When the rotary
encoder is pressed by hand, it can be reset to the initial state, that is, the count starts from 0.

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3
4 #define clkPin 0 //define the clkPin
5 #define dtPin 1 //define the dtPin
6 #define swPin 2 //define the swPin
7
8 int symbol = 0;
9 int lastDTStatus = 0;
10 int currentDTStatus = 0;
11 int previousCounterValue= 0;
12 int currentCounterValue=0;
13 void rotaryDeal(){
14 int symbol= 0;
15 int lastDTStatus= 0;
16 int currentDTStatus= 0;
17 lastDTStatus =digitalRead(dtPin);
18 while(digitalRead(clkPin) == LOW){
19 // When not rotating, the value of [Link] (clkPin) is 1, and it will become 0 when
rotating.
20 currentDTStatus = digitalRead(dtPin); //Record the current value when rotating
21 symbol = 1;
22 }
23 if(symbol==1){ // When rotating the encoder by hand
24 symbol = 0;

support@[Link] █
246  support@[Link] [Link] █

25 if ((lastDTStatus == 1) && (currentDTStatus == 0)){


26 //When rotate clockwise, the angular displacement increases, and the count value increases.
27 previousCounterValue=previousCounterValue+1;
28 }
29 if ((lastDTStatus == 0) && (currentDTStatus == 1)){
30 // When rotate counterclockwise, the angular displacement decreases, and the count value
decreases.
31 previousCounterValue=previousCounterValue-1;
32 }
33 }
34 }
35
36 void main(void)
37 {
38 printf("Program is starting...\n");
39 wiringPiSetup(); //Initialize wiringPi.
40 pinMode(clkPin, INPUT); //Set clkPin to input
41 pinMode(dtPin, INPUT); //Set dtPin to input
42 pinMode(swPin, INPUT); //Set swPin to input
43 pullUpDnControl(swPin, PUD_UP); //pull up to high level
44
45 while(1){
46 rotaryDeal();
47 if(digitalRead(swPin) == LOW){
48 delay(120);
49 if(digitalRead(swPin) == LOW){
50 // When the rotary encoder is pressed by hand, the count value is reset to zero.
51 previousCounterValue=0;
52 }
53 }
54 if(currentCounterValue != previousCounterValue){
55 printf("Counter= %d\n" , previousCounterValue);//
56 currentCounterValue = previousCounterValue;
57 }
58 }
59 }

Function rotaryDeal() is used to determine whether the rotary encoder is rotating, and when there is rotation,
determine whether it is rotating clockwise or counterclockwise. Use variable previousCounterValue to record
the number of rotations. When rotating clockwise, the variable increases, and when rotating counterclockwise,
the variable decreases.

void rotaryDeal(){
int symbol= 0;

█ support@[Link]
█ [Link]  support@[Link] 247

int lastDTStatus= 0;
int currentDTStatus= 0;
lastDTStatus =digitalRead(dtPin);

while(digitalRead(clkPin) == LOW){
// When not rotating, the value of [Link] (clkPin) is 1, and it will become 0 when
rotating.
currentDTStatus = digitalRead(dtPin); //Record the current value when rotating
symbol = 1;
}
if(symbol==1){ // When rotating the encoder by hand
symbol = 0;
if ((lastDTStatus == 1) && (currentDTStatus == 0)){
//When rotate clockwise, the angular displacement increases, and the count value increases.
previousCounterValue=previousCounterValue+1;
}
if ((lastDTStatus == 0) && (currentDTStatus == 1)){
// When rotate counterclockwise, the angular displacement decreases, and the count value
decreases.
previousCounterValue=previousCounterValue-1;
}
}
}

Read the SW signal pin of the rotary encoder, and determine whether the rotary encoder is pressed. If it is
pressed, the variable previousCounterValue is cleared.
if(digitalRead(swPin) == LOW){
delay(120);
if(digitalRead(swPin) == LOW){
// When the rotary encoder is pressed by hand, the count value is reset to zero.
previousCounterValue=0;
}
}

support@[Link] █
248  support@[Link] [Link] █

Project 31.2 Rotary Encoder and LED

This project uses a rotary encoder to adjust the LEDs to emit different brightness.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x8


GPIO Expansion Board & Ribbon Cable
x1
Breadboard x1
Rotary encoder x1 LED x1 Resistor 220Ω x1

█ support@[Link]
█ [Link]  support@[Link] 249

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

support@[Link] █
250  support@[Link] [Link] █

Code

C Code 31.2.1 Dimmable


First observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 30.2.1_Dimmable directory of C code.
cd ~/Freenove_Kit/Code/C_Code/31.2.1_Dimmable
2. Use following command to compile "Dimmable.c" and generate executable file "Dimmable".
gcc Dimmable.c -o Dimmable -lwiringPi
3. Run the generated file "Dimmable"
sudo ./Dimmable
After the program is executed, the rotary encoder can count the number of output pulses during forward and
reverse rotation. Adjust the LED to emit different brightness by the number of rotations. When the rotary
encoder is rotated clockwise by hand, the brightness of the led will increase, when the rotary encoder is
rotated counterclockwise by hand, the brightness of the led will decrease, and when the rotary encoder is
pressed by hand, the led will turn off.

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <softPwm.h>
4
5 #define clkPin 0 // define the clkPin
6 #define dtPin 1 // define the dtPin
7 #define swPin 2 // define the swPin
8 #define ledPin 3 //define the ledPin
9
10 int symbol = 0;
11 int lastDTStatus = 0;
12 int currentDTStatus = 0;
13 int previousCounterValue= 0;
14 int currentCounterValue=0;
15
16 void rotaryDeal(){
17 int symbol= 0;
18 int lastDTStatus= 0;
19 int currentDTStatus= 0;
20 lastDTStatus =digitalRead(dtPin);
21
22 while(digitalRead(clkPin) == LOW){
23 // When not rotating, the value of [Link] (clkPin) is 1, and it will become 0 when
rotating.

█ support@[Link]
█ [Link]  support@[Link] 251

24 currentDTStatus = digitalRead(dtPin); // Record the current value when rotating.


25 symbol = 1;
26 }
27 if(symbol==1){ // When rotating the encoder by hand
28 symbol = 0;
29 if((lastDTStatus == 1) && (currentDTStatus == 0)){
30 //When rotate clockwise, the angular displacement increases, and the count value increases.
31 previousCounterValue=previousCounterValue+1;
32 }
33 if ((lastDTStatus == 0) && (currentDTStatus == 1)){
34 // When rotate counterclockwise, the angular displacement decreases, and the count value
decreases.
35 previousCounterValue=previousCounterValue-1;
36 }
37 }
38 }
39
40 void main(void){
41 printf("Program is starting...\n");
42 wiringPiSetup(); //Initialize wiringPi.
43 pinMode(clkPin, INPUT); //Set buttonPin to input
44 pinMode(dtPin, INPUT); //Set buttonPin to input
45 pinMode(swPin, INPUT); //Set buttonPin to input
46 pullUpDnControl(swPin, PUD_UP); //pull up to high level
47 softPwmCreate(ledPin,0,100);
48
49 while(1){
50 rotaryDeal();
51 if(digitalRead(swPin) == LOW){
52 delay(120);
53 if(digitalRead(swPin) == LOW){
54 // When the rotary encoder is pressed by hand, the count value is cleared.
55 previousCounterValue=0;
56 }
57 }
58 if(previousCounterValue>=100){
59 previousCounterValue=100;
60 }
61 if(previousCounterValue<=0){
62 previousCounterValue=0;
63 }
64 if(currentCounterValue != previousCounterValue){
65 printf("Counter= %d\n" , previousCounterValue);//
66 currentCounterValue = previousCounterValue;

support@[Link] █
252  support@[Link] [Link] █

67 }
68 softPwmWrite(ledPin,previousCounterValue); //Mapping to PWM duty cycle
69 }
70 }

Function rotaryDeal() is used to determine whether the rotary encoder is rotating, and when there is rotation,
determine whether it is rotating clockwise or counterclockwise. Use variable previousCounterValue to record
the number of rotations. When rotating clockwise, the variable increases, and when rotating counterclockwise,
the variable decreases.
void rotaryDeal(){
int symbol= 0;
int lastDTStatus= 0;
int currentDTStatus= 0;
lastDTStatus =digitalRead(dtPin);

while(digitalRead(clkPin) == LOW){
// When not rotating, the value of [Link] (clkPin) is 1, and it will become 0 when
rotating.
currentDTStatus = digitalRead(dtPin); // Record the current value when rotating.
symbol = 1;
}
if(symbol==1){ // When rotating the encoder by hand
symbol = 0;
if((lastDTStatus == 1) && (currentDTStatus == 0)){
//When rotate clockwise, the angular displacement increases, and the count value increases.
previousCounterValue=previousCounterValue+1;
}
if ((lastDTStatus == 0) && (currentDTStatus == 1)){
// When rotate counterclockwise, the angular displacement decreases, and the count value
decreases.
previousCounterValue=previousCounterValue-1;
}
}
}

Read the SW signal pin of the rotary encoder, and determine whether the rotary encoder is pressed. If it is
pressed, the variable previousCounterValue is cleared.
if(digitalRead(swPin) == LOW){
delay(120);
if(digitalRead(swPin) == LOW){
//When the rotary encoder is pressed by hand, the count value is cleared.
previousCounterValue=0;
}
}

█ support@[Link]
█ [Link]  support@[Link] 253

The variable previousCounterValue is limited here, and the PWM duty cycle of ledPin is set to
previousCounterValue. The duty cycle of PWM should be less than or equal to 100.
if(previousCounterValue>=100){
previousCounterValue=100;
}
if(previousCounterValue<=0){
previousCounterValue=0;
}
softPwmWrite(ledPin,previousCounterValue); //Mapping to PWM duty cycle

support@[Link] █
254  support@[Link] [Link] █

Chapter 32 LEDpixel
In this chapter, we will learn Freenove 8 RGB LED Module.
Note: if your Raspberry PI is Raspberry Pi5, skip 32.1 and 32.2 and look at 32.3 instead. Because 32.1
and 32.2 use the rpi_ws2812 library, they are not compatible with Raspberry Pi5.

Project 32.1 LEDpixel

This project will achieve an Freenove 8 RGB LED Module flowing water.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x4


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
Freenove 8 RGB LED Module x1

Component knowledge

Freenove 8 RGB LED Module


The Freenove 8 RGB LED Module is as below. You can use only one data pin to control the eight LEDs on the
module. As shown below:

And you can also control many modules at the same time. Just connect OUT pin of one module to IN pin of

█ support@[Link]
█ [Link]  support@[Link] 255

another module. In such way, you can use one data pin to control 8, 16, 32 … LEDs.

Pin description:
(IN) (OUT)
symbol Function symbol Function
S Input control signal S Output control signal
V Power supply pin, +3.5V~5.5V V Power supply pin, +3.5V~5.5V
G GND G GND

Circuit

Schematic diagram

support@[Link] █
256  support@[Link] [Link] █

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Additional supplement

Raspbery Pi, other than 4B and 400, nees to disable the audio module, othewise the LED will not work properly.
1. Create a new [Link] and open it for editing
sudo nano /etc/modprobe.d/[Link]
Add following content: After adding the contents, you need to press Ctrl+O, Enter, Ctrl+Z.
blacklist snd_bcm2835

2. We also need to edit config file.


sudo nano /boot/firmware/[Link]
Find the contents of the following two lines (with Ctrl + W you can search):
# Enable audio (loads snd_bcm2835)
dtparam=audio=on
Add # to comment out the second line. Press Ctrl+O, Enter, Ctrl+X.
# Enable audio (loads snd_bcm2835)
# dtparam=audio=on

█ support@[Link]
█ [Link]  support@[Link] 257

It will take effect after restarting, restart your RPi.


If you want to restart the audio module, just restore the content modified in the above two steps.

support@[Link] █
258  support@[Link] [Link] █

Code

C Code 32.1.1 Ledpixel


Before running C code, please install WS281X library.
1. Enter the directory where the library locates:
cd ~/Freenove_Kit/Libs/C-Libs/libWS281X
2. Run the program
sudo sh ./[Link]
The installation is completed as shown in the figure below

First, observe the project result, and then learn about the code in detail.
If you have any concerns, please send an email to: support@[Link]
1. Use cd command to enter 32.1.1_Ledpixel directory of C code.
cd ~/Freenove_Kit/Code/C_Code/32.1.1_Ledpixel
2. Use following command to compile " [Link]" and generate executable file "Ledpixel".
sudo g++ [Link] -o Ledpixel -lwiringPi -lWS281X
3. Run the generated file " Ledpixel".
sudo ./Ledpixel
After the program runs, the LEDpixel will emit red, blue and green colors in turn like flowing water. If your
Freenove 8 RGB LED Module doesn’t work, you can try additional supplements to solve.
The following is the program code:
1 #include <wiringPi.h>
2 #include "Freenove_WS2812_Lib_for_Raspberry_Pi.hpp"
3 Freenove_WS2812 *a;
4 int constrain(int value,int min,int max){
5 if (value>max){
6 return max;
7 }
8 else if (value<min){
9 return min;
10 }
11 else {
12 return value;
13 }
14 }
15 int main(){
16 printf("Program is starting ...\n");
17 while(1){
18 int i;
19 a= new Freenove_WS2812(18,8,GRB);//pin led_count type

█ support@[Link]
█ [Link]  support@[Link] 259

20 a->set_Led_Brightness(50);
21 for(i=0;i<8;i++){
22 a->set_Led_Color(i,255,0,0);
23 a->show();
24 delay(100);
25 }
26 for(i=0;i<8;i++){
27 a->set_Led_Color(i,0,255,0);
28 a->show();
29 delay(100);
30 }
31 for(i=0;i<8;i++){
32 a->set_Led_Color(i,0,0,255);
33 a->show();
34 delay(100);
35 }
36 a->clear();
37 }
38 return 0;
39 }
Include "Freenove_WS2812_Lib_for_Raspberry_Pi.hpp"
1 #include "Freenove_WS2812_Lib_for_Raspberry_Pi.hpp"
Create the object of the class and set the brightness to 50%. The eight LEDs will then light up red, green and
blue in turn.
17 int i;
18 a= new Freenove_WS2812(18,8,GRB);//pin led_count type
19 a->set_Led_Brightness(50);
20 for(i=0;i<8;i++){
21 a->set_Led_Color(i,255,0,0);
22 a->show();
23 delay(100);
24 }
25 for(i=0;i<8;i++){
26 a->set_Led_Color(i,0,255,0);
27 a->show();
28 delay(100);
29 }
30 for(i=0;i<8;i++){
31 a->set_Led_Color(i,0,0,255);
32 a->show();
33 delay(100);
34 }
35 a->clear();

support@[Link] █
260  support@[Link] [Link] █

Project 32.2 RainbowLight

In this project, we will learn to control the LED module with a potentiometer.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x13


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
Freenove 8 RGB LED Module x1 Rotary Potentiometer x1 ADC Module x1

Circuit

Schematic diagram

█ support@[Link]
█ [Link]  support@[Link] 261

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Code

C Code 32.2.1 RainbowLight


If you did not configure I2C, please refer to Chapter 7. If you did, please continue.
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please send an email to: support@[Link]
1. Use cd command to enter 32.2.1_RainbowLight directory of C code.
cd ~/Freenove_Kit/Code/C_Code/32.2.1_RainbowLight
2. Use following command to compile " [Link] " and generate executable file " RainbowLight ".
sudo g++ [Link] -o RainbowLight -lADCDevice -lWS281X -lwiringPi
3. Run the generated file " RainbowLight ".
sudo ./RainbowLight
After running the program, you can change the color of the LED module by rotating the potentiometer.
The following is the program code:
1 #include <stdio.h>
2 #include <wiringPi.h>
3 #include <[Link]>
4 #include "Freenove_WS2812_Lib_for_Raspberry_Pi.hpp"
5 Freenove_WS2812 *led;
6 ADCDevice *adc;
7 int red,green,blue;
8 void HSL_RGB(int degree){
9 degree=degree/360.0*255;
10 if (degree < 85){

support@[Link] █
262  support@[Link] [Link] █

11 red = 255 - degree * 3;


12 green = degree * 3;
13 blue = 0;
14 }
15 else if (degree < 170){
16 degree = degree - 85;
17 red = 0;
18 green = 255 - degree * 3;
19 blue = degree * 3;
20 }
21 else{
22 degree = degree - 170;
23 red = degree * 3;
24 green = 0;
25 blue = 255 - degree * 3;
26 }
27 }
28 int main(){
29 printf("Program is starting ...\n");
30 adc = new ADCDevice();
31 int i;
32 led= new Freenove_WS2812(18,8,GRB);//pin led_count type
33 led->set_Led_Brightness(50);
34 if(adc->detectI2C(0x4b)){ // Detect the ads7830
35 delete adc; // Free previously pointed memory
36 adc = new ADS7830(0x4b); // If detected, create an instance of ADS7830.
37 }
38 else if(adc->detectI2C(0x48)){ // Detect the pcf8591.
39 delete adc; // Free previously pointed memory
40 adc = new PCF8591(); // If detected, create an instance of PCF8591.
41 }
42 else{
43 printf("No correct I2C address found, \n"
44 "Please use command 'i2cdetect -y 1' to check the I2C address! \n"
45 "Program Exit. \n");
46 return -1;
47 }
48 while(1){
49 for(i=0;i<8;i++){
50 int degree = (int)(adc->analogRead(2)/255.0*360+i*45); //read analog value of
A2 pin
51 if (degree > 360){
52 degree=degree-360;
53 }

█ support@[Link]
█ [Link]  support@[Link] 263

54 HSL_RGB(degree);
55 led->set_Led_Color(i,red,green,blue);
56 led->show();
57 }
58 }
59 return 0;
60 }
This function converts HSL colors to RGB colors.
8 void HSL_RGB(int degree){
9 degree=degree/360.0*255;
10 if (degree < 85){
11 red = 255 - degree * 3;
12 green = degree * 3;
13 blue = 0;
14 }
15 else if (degree < 170){
16 degree = degree - 85;
17 red = 0;
18 green = 255 - degree * 3;
19 blue = degree * 3;
20 }
21 else{
22 degree = degree - 170;
23 red = degree * 3;
24 green = 0;
25 blue = 255 - degree * 3;
26 }
27 }
Read the ADC value of channel 2 in an infinite loop. Let the color of the eight LEDs change according to the
value of the ADC.
48 while(1){
49 for(i=0;i<8;i++){
50 int degree = (int)(adc->analogRead(2)/255.0*360+i*45); //read analog value of
A2 pin
51 if (degree > 360){
52 degree=degree-360;
53 }
54 HSL_RGB(degree);
55 led->set_Led_Color(i,red,green,blue);
56 led->show();
57 }
58 }

support@[Link] █
264  support@[Link] [Link] █

Project 32.3 SpiLEDpixel

This project will control ledpixel to display any color by the Raspberry Pi’s SPI.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x4


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
Freenove 8 RGB LED Module x1

Component knowledge

Freenove 8 RGB LED Module


The Freenove 8 RGB LED Module is as below. You can use only one data pin to control the eight LEDs on the
module. As shown below:

And you can also control many modules at the same time. Just connect OUT pin of one module to IN pin of
another module. In such way, you can use one data pin to control 8, 16, 32 … LEDs.

█ support@[Link]
█ [Link]  support@[Link] 265

Pin description:
(IN) (OUT)
symbol Function symbol Function
S Input control signal S Output control signal
V Power supply pin, +3.5V~5.5V V Power supply pin, +3.5V~5.5V
G GND G GND

Circuit

Schematic diagram

support@[Link] █
266  support@[Link] [Link] █

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

Before you run your python code, check that the spidev library exists.
Enter the following command to install.
pip list
The spidev is installed on Raspberry PI by default. As shown in the figure below.

█ support@[Link]
█ [Link]  support@[Link] 267

If your Raspberry PI system does not have this library, you can find [Link] in
Freenove_Kit/Libs/Python-Libs.
Enter the following instructions to install spidev.
cd Freenove_Kit/Libs/Python-Libs
tar –zxvf [Link]
cd spidev-3.6
sudo python [Link] install
The installation is complete as shown in the following figure.

If you have any concerns, please send an email to: support@[Link]

Additional supplement

Note that the frequency of the SPI changes as the CPU frequency self-regulates, so we need to fix the cpu
frequency before we start using the code. Please refer to the following operations.
1. Open the [Link] file and prepare to edit it.
sudo nano /boot/firmware/[Link]
2, If your Raspberry PI is Raspberry PI 4 or Raspberry PI 5, please add at the bottom:
force_turbo=1
If your Raspberry PI is Raspberry PI 3, add it at the bottom:
core_freq=250
3, Save the file.
4, Turn on the spi feature of the Raspberry PI.
sudo raspi-config
5, Select Interface Options, then SPI, and turn it on.

support@[Link] █
268  support@[Link] [Link] █

6, Select Finish.
7, Reboot the Raspberry PI.
sudo reboot

Code

C Code 32.3.1 SpiLedpixel


Use cd command to enter 32.3.1_SpiLedpixel directory of C code.
cd ~/Freenove_Kit/Code/C_Code/32.3.1_SpiLedpixel
Use following command to compile " [Link]" and generate executable file "Ledpixel".
g++ [Link] Freenove_WS2812_SPI.cpp –o main
Run the generated file "main". Please use one of the following commands to control the ledpixel.
sudo ./main RGB
After the program runs, the led pixels will emit red, blue and green three colors in turn like water. If your
Freenove 8 RGB LED module is not working, you can try additional supplements to fix it.
sudo ./main Rainbow
After the program runs, the led pixels will emit a rainbow of colors and slowly rotate.
sudo ./main Breathing
After the program runs, the led will slowly turn on and then slowly turn off.

█ support@[Link]
█ [Link]  support@[Link] 269

The following is the program code:


1 #include "Freenove_WS2812_SPI.h"
2
3 //Freenove_WS2812_SPI strip = Freenove_WS2812_SPI(8, TYPE_GRB);//led_count, led_type
4 Freenove_WS2812_SPI strip = Freenove_WS2812_SPI();//led_count=8, led_type=TYPE_GRB
5
6 void Ctrl_C_Handler(int value){
7 [Link]();
8 exit(0);
9 }
10
11 int main(int argc, char *argv[]){
12 //Ctrl+C Event
13 signal(SIGINT, Ctrl_C_Handler);
14
15 //Init ledpixel
16 [Link]();
17 [Link](20);
18 [Link]((LED_TYPE)2);
19
20 while(true){
21 //some tips
22 if(argc == 1){
23 printf("The use of ledpixel:\n");
24 printf(" please enter ./main RGB\n");
25 printf(" please enter ./main Rainbow\n");
26 printf(" please enter ./main Breathing\n\n");
27 exit(0);
28 }
29 else if(argc == 2 && strncmp(argv[1], "RGB", 3) == 0){
30 unsigned int i = 0, color_index = 0;
31 unsigned int
colors[]={0xFF0000,0x00FF00,0x0000FF,0xFFFF00,0xFF00FF,0x00FFFF,0xFFFFFF};
32 for(color_index=0; color_index < sizeof(colors)/sizeof(colors[0]);
color_index++){
33 for(i=0;i<[Link]();i++){
34 [Link](i, colors[color_index]);
35 usleep(10000);
36 }
37 [Link]();
38 usleep(500000);
39 }
40 }
41 else if(argc == 2 && strncmp(argv[1], "Rainbow", 7) == 0){

support@[Link] █
270  support@[Link] [Link] █

42 for (int j = 0; j < 255; j += 2) {


43 for (int i = 0; i < [Link](); i++) {
44 [Link](i, [Link]((i * 256 /
[Link]() + j) & 255));
45 }
46 [Link]();
47 usleep(10000);
48 }
49 }
50 else if(argc == 2 && strncmp(argv[1], "Breathing", 9) == 0){
51 unsigned int
colors[]={0xFF0000,0x00FF00,0x0000FF,0xFFFF00,0xFF00FF,0x00FFFF,0xFFFFFF};
52 for(unsigned int color_index=0; color_index <
sizeof(colors)/sizeof(colors[0]); color_index++){
53 for(unsigned int br=0;br<50;br++){
54 [Link](br);
55 [Link](colors[color_index]);
56 [Link]();
57 usleep(10000);
58 }
59 for(unsigned int br=50;br>0;br--){
60 [Link](br);
61 [Link](colors[color_index]);
62 [Link]();
63 usleep(10000);
64 }
65 }
66 }
67 }
68 return 0;
69 }
Include "Freenove_WS2812_SPI.h".
1 #include "Freenove_WS2812_SPI.h"
To create Ledpixel objects, you can use the default parameters or you can use custom parameters.
3 //Freenove_WS2812_SPI strip = Freenove_WS2812_SPI(8, TYPE_GRB);//led_count, led_type
4 Freenove_WS2812_SPI strip = Freenove_WS2812_SPI();//led_count=8, led_type=TYPE_GRB
Create an interrupt event if the user presses Ctrl+C to turn off the lights before exiting the program.
6 void Ctrl_C_Handler(int value){
7 [Link]();
8 exit(0);
9 }
……
12 //Ctrl+C Event
13 signal(SIGINT, Ctrl_C_Handler);

█ support@[Link]
█ [Link]  support@[Link] 271

Initialize ledpixel, set the brightness value of the color light to 20, set the type of the color light to GRB type.
15 //Init ledpixel
16 [Link]();
17 [Link](20);
18 [Link]((LED_TYPE)TYPE_GRB);
Determine the number of parameters when the executable file is invoked. If no parameters are specified, a
message is displayed.
21 //some tips
22 if(argc == 1){
23 printf("The use of ledpixel:\n");
24 printf(" please enter ./main RGB\n");
25 printf(" please enter ./main Rainbow\n");
26 printf(" please enter ./main Breathing\n\n");
27 exit(0);
28 }
If the parameter is RGB, let the ledpixel display color one by one, and then switch to another color in turn,
and continue to repeat the process.
29 else if(argc == 2 && strncmp(argv[1], "RGB", 3) == 0){
30 unsigned int i = 0, color_index = 0;
31 unsigned int
colors[]={0xFF0000,0x00FF00,0x0000FF,0xFFFF00,0xFF00FF,0x00FFFF,0xFFFFFF};
32 for(color_index=0; color_index < sizeof(colors)/sizeof(colors[0]);
color_index++){
33 for(i=0;i<[Link]();i++){
34 [Link](i, colors[color_index]);
35 usleep(10000);
36 }
37 [Link]();
38 usleep(500000);
39 }
40 }
If the parameter is Rainbow, let the ledpixel display a rainbow of colors and turn slowly.
41 else if(argc == 2 && strncmp(argv[1], "Rainbow", 7) == 0){
42 for (int j = 0; j < 255; j += 2) {
43 for (int i = 0; i < [Link](); i++) {
44 [Link](i, [Link]((i * 256 /
[Link]() + j) & 255));
45 }
46 [Link]();
47 usleep(10000);
48 }
49 }
If the parameter is Breathing, let the ledpixel gradually turn on one color, slowly turn off, then switch to
another color, and repeat the process.

support@[Link] █
272  support@[Link] [Link] █

50 else if(argc == 2 && strncmp(argv[1], "Breathing", 9) == 0){


51 unsigned int
colors[]={0xFF0000,0x00FF00,0x0000FF,0xFFFF00,0xFF00FF,0x00FFFF,0xFFFFFF};
52 for(unsigned int color_index=0; color_index <
sizeof(colors)/sizeof(colors[0]); color_index++){
53 for(unsigned int br=0;br<50;br++){
54 [Link](br);
55 [Link](colors[color_index]);
56 [Link]();
57 usleep(10000);
58 }
59 for(unsigned int br=50;br>0;br--){
60 [Link](br);
61 [Link](colors[color_index]);
62 [Link]();
63 usleep(10000);
64 }
65 }
66 }

█ support@[Link]
█ [Link]  support@[Link] 273

Chapter 33 BMP180 Barometric Pressure Sensor


In this chapter, we will learn how to use BMP180 barometric pressure sensor.

Project 33.1 Barometer

This project uses the BMP180 barometric pressure sensor to display real-time barometric pressure,
temperature conditions and current altitude.

Component List

Raspberry Pi (with 40 GPIO) x1 Jumper x6


GPIO Expansion Board & Ribbon Cable x1
Breadboard x1
BMP180 barometric pressure sensor x1

Component knowledge

BMP180 barometric pressure sensor


The BMP180 barometric pressure sensor module is a high-precision barometric pressure sensor, which can
detect temperature and barometric pressure, and through these two data, the current altitude can be
calculated. Its pressure measurement range is from 300 to 1100 hPa (altitude 9000m to -500m), and
temperature from -40°C to 85°C with an accuracy of ±1.0°C. Using the BMP180 module to get altitude and
barometric pressure requires math.
The BMP180 is designed to connect directly to the microcontroller via the IIC bus. The pressure and
temperature data must be compensated by the BMP180's E2PROM calibration data. The BMP180 consists of
a piezoresistive sensor, an analog-to-digital converter and a control unit with E2PROM and serial IIC interface.
The BMP180 provides uncompensated pressure and temperature values. The E2PROM stores 176 bits of
individual calibration data, which is used to compensate sensor for offset, temperature dependence and other
parameters.

support@[Link] █
274  support@[Link] [Link] █

The general process of BMP180 reading data and the calculation of each data are as follows:

Among them, UT is temperature data (16 bits), and UP is pressure data (16 to 19 bits).
Calculate temperature:

Calculate pressure:

Calculate absolute altitude. According to the measured air pressure p and sea level air pressure po (for
example, 1013.25hPa), the altitude in meters can be calculated via the following international pressure formula:

█ support@[Link]
█ [Link]  support@[Link] 275

Below is the pinout of BMP180 barometric pressure sensor.


Pin description:
symbol Function
VIN Power supply pin, +1.6V~3.6V
GND GND
SCL Serial clock pin of I2C interface
SDA Serial data pin of I2C interface
Please do not use voltage beyond the power supply range to avoid damage to the BMP180 barometric
pressure sensor.

support@[Link] █
276  support@[Link] [Link] █

Circuit

Schematic diagram

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

█ support@[Link]
█ [Link]  support@[Link] 277

Code

C Code 33.1.1 Barometer


If you did not configure I2C and Install Smbus, please refer to Chapter 7. If you did, please move on.
First observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 33.1.1_Barometer directory of C code.
cd ~/Freenove_Kit/Code/C_Code/33.1.1_Barometer
2. Use following command to compile "Barometer.c" and generate executable file "Barometer ".
gcc -o Barometer ./smbus.c ./Barometer.c -lm
3. Run the generated file "Barometer "
sudo ./Barometer
After the program is executed, the terminal will display the current air pressure value, temperature value and
altitude.

The following is the program code:


1 #include <stdio.h>
2 #include <stdint.h>
3 #include <fcntl.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <linux/i2c-dev.h>
7 #include <linux/i2c.h>
8 #include <sys/ioctl.h>
9 #include "smbus.h"
10 #include <math.h>
11
12 #define bmp180_I2C_ADDRESS 0x77
13 const unsigned char bmp180_OVERSAMPLING_SETTING = 3;
14
15 // Calibration values - These are stored in the BMP180
16 short int ac1;
17 short int ac2;
18 short int ac3;
19 unsigned short int ac4;
20 unsigned short int ac5;
21 unsigned short int ac6;
22 short int b1;
23 short int b2;
24 short int mb;
25 short int mc;
26 short int md;

support@[Link] █
278  support@[Link] [Link] █

27 int b5;
28 unsigned int temperature, pressure, altitude;
29
30 // Open a connection to the bmp180
31 // Returns a file id
32 int bmp180_i2c_Begin(){
33 int fd;
34 char *fileName = "/dev/i2c-1";
35 // Open port for reading and writing
36 if ((fd = open(fileName, O_RDWR)) < 0)
37 exit(1);
38 // Set the port options and set the address of the device
39 if (ioctl(fd, I2C_SLAVE, bmp180_I2C_ADDRESS) < 0){
40 close(fd);
41 exit(1);
42 }
43 return fd;
44 }
45 // Read two words from the bmp180 and supply it as a 16 bit integer
46 __s32 bmp180_i2c_Read_Int(int fd, __u8 address){
47 __s32 res = i2c_smbus_read_word_data(fd, address);
48 if (res < 0){
49 close(fd);
50 exit(1);
51 }
52 // Convert result to 16 bits and swap bytes
53 res = ((res<<8) & 0xFF00) | ((res>>8) & 0xFF);
54 return res;
55 }
56 //Write a byte to the bmp180
57 void bmp180_i2c_Write_Byte(int fd, __u8 address, __u8 value){
58 if (i2c_smbus_write_byte_data(fd, address, value) < 0) {
59 close(fd);
60 exit(1);
61 }
62 }
63 // Read a block of data bmp180
64 void bmp180_i2c_Read_Block(int fd, __u8 address, __u8 length, __u8 *values){
65 if(i2c_smbus_read_i2c_block_data(fd, address,length,values)<0){
66 close(fd);
67 exit(1);
68 }
69 }
70 void bmp180_Calibration(){

█ support@[Link]
█ [Link]  support@[Link] 279

71 int fd = bmp180_i2c_Begin();
72 ac1 = bmp180_i2c_Read_Int(fd,0xAA);
73 ac2 = bmp180_i2c_Read_Int(fd,0xAC);
74 ac3 = bmp180_i2c_Read_Int(fd,0xAE);
75 ac4 = bmp180_i2c_Read_Int(fd,0xB0);
76 ac5 = bmp180_i2c_Read_Int(fd,0xB2);
77 ac6 = bmp180_i2c_Read_Int(fd,0xB4);
78 b1 = bmp180_i2c_Read_Int(fd,0xB6);
79 b2 = bmp180_i2c_Read_Int(fd,0xB8);
80 mb = bmp180_i2c_Read_Int(fd,0xBA);
81 mc = bmp180_i2c_Read_Int(fd,0xBC);
82 md = bmp180_i2c_Read_Int(fd,0xBE);
83 close(fd);
84 }
85 // Read the uncompensated temperature value
86 unsigned int bmp180_ReadUT(){
87 unsigned int ut = 0;
88 int fd = bmp180_i2c_Begin();
89 // Write 0x2E into Register 0xF4
90 // This requests a temperature reading
91 bmp180_i2c_Write_Byte(fd,0xF4,0x2E);
92 // Wait at least 5ms
93 usleep(5000);
94 // Read the two byte result from address 0xF6
95 ut = bmp180_i2c_Read_Int(fd,0xF6);
96 // Close the i2c file
97 close (fd);
98 return ut;
99 }
100 // Read the uncompensated pressure value
101 unsigned int bmp180_ReadUP(){
102 unsigned int up = 0;
103 int fd = bmp180_i2c_Begin();
104 // Write 0x34+(bmp180_OVERSAMPLING_SETTING<<6) into register 0xF4
105 // Request a pressure reading w/ oversampling setting
106 bmp180_i2c_Write_Byte(fd,0xF4,0x34 + (bmp180_OVERSAMPLING_SETTING<<6));
107 // Wait for conversion, delay time dependent on oversampling setting·
108 usleep((2 + (3<<bmp180_OVERSAMPLING_SETTING)) * 1000);
109 // Read the three byte result from 0xF6
110 // 0xF6 = MSB, 0xF7 = LSB and 0xF8 = XLSB
111 __u8 values[3];
112 bmp180_i2c_Read_Block(fd, 0xF6, 3, values);
113 up = (((unsigned int) values[0] << 16) | ((unsigned int) values[1] << 8) | (unsigned int)
values[2]) >> (8-bmp180_OVERSAMPLING_SETTING);

support@[Link] █
280  support@[Link] [Link] █

114 return up;


115 }
116 // Calculate pressure given uncalibrated pressure
117 unsigned int bmp180_GetPressure(unsigned int up){
118 int x1, x2, x3, b3, b6, p;
119 unsigned int b4, b7;
120 b6 = b5 - 4000;
121 // Calculate B3
112 x1 = (b2 * (b6 * b6)>>12)>>11;
113 x2 = (ac2 * b6)>>11;
114 x3 = x1 + x2;
115 b3 = (((((int)ac1)*4 + x3)<<bmp180_OVERSAMPLING_SETTING) + 2)>>2;
116 // Calculate B4
117 x1 = (ac3 * b6)>>13;
118 x2 = (b1 * ((b6 * b6)>>12))>>16;
119 x3 = ((x1 + x2) + 2)>>2;
120 b4 = (ac4 * (unsigned int)(x3 + 32768))>>15;
121 b7 = ((unsigned int)(up - b3) * (50000>>bmp180_OVERSAMPLING_SETTING));
122 if (b7 < 0x80000000)
123 p = (b7<<1)/b4;
124 else
125 p = (b7/b4)<<1;
126 x1 = (p>>8) * (p>>8);
127 x1 = (x1 * 3038)>>16;
128 x2 = (-7357 * p)>>16;
129 p += (x1 + x2 + 3791)>>4;
130 return p;
131 }
132 // Calculate temperature given uncalibrated temperature
133 // Value returned will be in units of 0.1 deg C
134 unsigned int bmp180_GetTemperature(unsigned int ut){
135 int x1, x2;
136 x1 = (((int)ut - (int)ac6)*(int)ac5) >> 15;
137 x2 = ((int)mc << 11)/(x1 + md);
138 b5 = x1 + x2;
139 unsigned int result = ((b5 + 8)>>4);
140 return result;
141 }
142 // Arduino library. The number divided into pressure for
143 // float A is derived from the local pressure as explained
144 // at [Link]
145 unsigned int bmp180_Altitude(float pressure){
146 float A = pressure/101325.0;
147 float B = 1/5.25588;

█ support@[Link]
█ [Link]  support@[Link] 281

148 float C = pow(A,B);


149 C = 1 - C;
150 C = C / 0.0000225577;
151 return C;
152 }
153 int main(int argc, char **argv){
154 printf("Program is starting ... \n");
155 while(1){
156 bmp180_Calibration();
157 temperature = bmp180_GetTemperature(bmp180_ReadUT());
158 pressure = bmp180_GetPressure(bmp180_ReadUP());
159 altitude = bmp180_Altitude(pressure);
160 printf("Temperature\t%0.1f ℃\n", ((double)temperature)/10);
161 printf("Pressure\t%0.2f hPa\n", ((double)pressure)/100);
162 printf("Altitude\t%0.1f m\n\n", (double)altitude);
163 usleep(2000*1000);
164 }
165 return 0;
166 }

The function bmp180_GetTemperature() is used to calculate the current temperature value.


unsigned int bmp180_GetTemperature(unsigned int ut){
int x1, x2;
x1 = (((int)ut - (int)ac6)*(int)ac5) >> 15;
x2 = ((int)mc << 11)/(x1 + md);
b5 = x1 + x2;
unsigned int result = ((b5 + 8)>>4);
return result;
}

The function bmp180_GetPressure() is used to calculate the current pressure value.


unsigned int bmp180_GetPressure(unsigned int up){
int x1, x2, x3, b3, b6, p;
unsigned int b4, b7;
b6 = b5 - 4000;
// Calculate B3
x1 = (b2 * (b6 * b6)>>12)>>11;
x2 = (ac2 * b6)>>11;
x3 = x1 + x2;
b3 = (((((int)ac1)*4 + x3)<<bmp180_OVERSAMPLING_SETTING) + 2)>>2;
// Calculate B4
x1 = (ac3 * b6)>>13;
x2 = (b1 * ((b6 * b6)>>12))>>16;
x3 = ((x1 + x2) + 2)>>2;

support@[Link] █
282  support@[Link] [Link] █

b4 = (ac4 * (unsigned int)(x3 + 32768))>>15;


b7 = ((unsigned int)(up - b3) * (50000>>bmp180_OVERSAMPLING_SETTING));
if (b7 < 0x80000000)
p = (b7<<1)/b4;
else
p = (b7/b4)<<1;
x1 = (p>>8) * (p>>8);
x1 = (x1 * 3038)>>16;
x2 = (-7357 * p)>>16;
p += (x1 + x2 + 3791)>>4;
return p;
}

The function bmp180_Altitude() is used to calculate the current altitude.


unsigned int bmp180_Altitude(float pressure){
float A = pressure/101325.0;
float B = 1/5.25588;
float C = pow(A,B);
C = 1 - C;
C = C / 0.0000225577;
return C;
}

█ support@[Link]
█ [Link]  support@[Link] 283

Chapter 34 RFID
In this chapter, we will learn how to use RFID.

Project 34.1 RFID

In this project, we will use RC522 RFID card reader to read and write the M1-S50 card.

Component List

Raspberry Pi 3B x1 RC522 module x1


GPIO Extension Board & Wire x1
Breadboard x1
Jumper M/F x7

Mifare1 S50 Standard card x1 Mifare1 S50 Non-standard card x1

support@[Link] █
284  support@[Link] [Link] █

Component Knowledge

RFID
RFID(Radio Frequency Identification)is a form of wireless communication technology. A complete RFID
system is generally composed of a transponder and a reader. Generally, the transponder may be known as a
tag, and each tag has a unique code, which is attached to an object to identify the target object. The reader
is a device that reads (or writes) information in the tag.
Products derived from RFID technology can be divided into three categories: passive RFID products, active
RFID products and semi active RFID products, among which, Passive RFID products are the earliest, the most
mature and most widely used products in the market. It can be seen everywhere in our daily life such as, the
bus card, dining card, bank card, hotel access cards, etc., and all of them are classified as close-range contact
recognition. The main operating frequency of Passive RFID products are: 125KHZ (low frequency), 13.56MHZ
(high frequency), 433MHZ (ultrahigh frequency), 915MHZ (ultrahigh frequency). Active and semi active RFID
products work at higher frequencies.
The RFID module we use is a passive RFID product with the operating frequency of 13.56MHz.

MFRC522
The MFRC522 is a highly integrated reader/writer IC for contactless communication at 13.56MHz.
The MFRC522’s internal transmitter is able to drive a reader/writer antenna designed to communicate with
ISO/IEC 14443 A/MIFARE cards and transponders without additional active circuitry. The receiver module
provides a robust and efficient implementation for demodulating and decoding signals from ISO/IEC 14443
A/MIFARE compatible cards and transponders. The digital module manages the complete ISO/IEC 14443A
framing and error detection (parity and CRC) functionality
This RFID Module uses MFRC522 as the control chip, and SPI (Peripheral Interface Serial) as the reserved
interface.
Technical specs:
Operating Voltage 13-26mA(DC)\3.3V
Idle current 10-13mA(DC)\3.3V
Sleep current in the <80uA
Peak current <30mA
Operating frequency 13.56MHz
Mifare1 S50、Mifare1 S70、Mifare Ultralight、
Supported card type
Mifare Pro、Mifare Desfire
Size 40mmX60mm
Operation temperature 20-80 degrees(Celsius)
Storage temperature 40-85 degrees (Celsius)
Operation humidity 5%-95%(Relative humidity)

Mifare1 S50 Card


Mifare S50 is often called Mifare Standard with the capacity of 1K bytes. And each card has a 4-bytes global
unique identifier number (USN/UID), which can be rewritten 100 thousand times and read infinite times. Its
storage period can last for 10 years.

█ support@[Link]
█ [Link]  support@[Link] 285

The Mifare S50 capacity (1K byte) is divided into 16 sectors (Sector0-Sector15). Each sector contains 4 data
block (Block0-Block3. 64 blocks of 16 sectors will be numbered according absolute address, from 0 to 63).

And each block contains 16 bytes (Byte0-Byte15), 64*16=1024. As is shown in the following table:
Sector No. Block No. Storage area Block type Absolute
block No.
sector 0 block 0 vendor code vendor block 0
block 1 data block 1
block 2 data block 2
block 3 Password A-access control-password B control block 3
sector 1 block 0 data block 4
block 1 data block 5
block 2 data block 6
block 3 Password A-access control-password B control block 7
…… …… …… ……
sector 15 block 0 data block 60
block 1 data block 61
block 2 data block 62
block 3 Password A-access control-password B control block 63
Each sector has a set of independent password and access control put in its last block, that is, Block 3, which
is also known as sector trailer. Sector 0, block 0 (namely absolute address 0) of S50 is used to store the card
serial number and vendor code, which has been solidified and can’t be changed. Except the manufacturer
and the control block, the rest of the cards are data blocks, which can be used to store data. Data block can
be used for two kinds of applications:
(1) used as general data storage and can be operated for reading and writing data.
(2) used as data value, and can be operated for initializing, adding, subtracting and reading the value.
The sector trailer block in each sector is the control block, including a 6-byte password A, a 4-byte access
control and a 6-byte password B. For example, the control block of a brand new card is as follows:
A0 A1 A2 A3 A4 A5 FF 07 80 69 B0 B1 B2 B3 B4 B5
password A access control password B

The default password of a brand new card is generally 0A1A2A3A4A5 for password A and B0B1B2B3B4B5 for
password B, or both the password A and password B are 6 FF. Access control is used to set the access
conditions for each block (including the control block itself) in a sector.
Blocks of S50 are divided into data blocks and control blocks. There are four operations, "read", "write", "add
value", "subtract value (including transmission and storage)" for data blocks, and there are two operations,
"read" and "write" for control blocks.
For more details about how to set data blocks and control blocks, please refer to Datasheet.
By default, after verifying password A or password B, we can do reading or writing operation to data blocks.
And after verifying password A, we can do reading or writing operation to control blocks. But password A can
never be read, so if you choose to verify password A but forget the password A, the block will never be able
to read again. It is highly recommended that beginners should not try to change the contents of control
blocks.
For Mifare1 S50 card equipped in Freenove RFID Kit, the default password A and B are both FFFFFFFFFFFF.

support@[Link] █
286  support@[Link] [Link] █

Circuit

Schematic diagram:

Hardware connection. If you need any support, please feel free to contact us via: support@[Link]

█ support@[Link]
█ [Link]  support@[Link] 287

Configure SPI

Enable SPI
The SPI interface of raspberry pi is closed by default. You need to open it manually. You can enable the SPI
interface in the following way.
Type the following command in the terminal:
sudo raspi-config
Then open the following dialog box:

Choose “5 Interfacing Options”→“P4 SPI”→“Yes”→“Finish” in order and then restart your RPi. Then the SPI
module is started.
Type the following command to check whether the module SPI is loaded successfully:
ls /dev/sp*
The following result indicates that the module SPI has been loaded successfully:

support@[Link] █
288  support@[Link] [Link] █

Code

The project code uses human-computer interaction command line mode to read and write the M1-S50 card.

C Code 34.1.1 RFID


First observe the running result, and then learn about the code in detail.
If you need any support, please contact us via: support@[Link]
1. Use cd command to enter RFID directory of C code.
cd ~/Freenove_Kit/Code/C_Code/34.1.1_RFID
2. Use the following command to compile and generate executable file "RFID".
sudo sh ./[Link]
3. Then run the generated file "RFID".
sudo ./RFID
After the program is executed, the following contents will be displayed in the terminal:

Here, type the command “quit” to exit the program.


Type command "scan", and then the program begins to detect whether there is a card close to the sensing
area of MFRC522 reader. Place a M1-S50 card in the sensing area. The following results indicate that the M1-
S50 card has been detected, the UID of which is E6CF5C8EFB (HEX).

When the Card is placed in the sensing area, you can read and write the card with the following command.

█ support@[Link]
█ [Link]  support@[Link] 289

In the command read<blockstart>, the parameter blockstart is the address of the data block, and the range
is 0-63. This command is used to display all the data from blockstart address to the end of the sector. For
example, sector 0 contains data block 0,1,2,3. Using the command “read 0” can display all contents of data
block 0,1,2,3. Using the command “read 1” can display all contents of data block 1,2,3. As is shown below:

Command “dump” is used to display the content of all data blocks in all sectors.
Command <address> <data> is used to write “data" to data block with address “address”, where the address
range is 0-63 and the data length is 0-16. For example, if you want to write the string "Freenove" to the data
block with address “1”, you can type the following command.
write 1 Freenove

Read the contents of this sector and check the data just written.
read 0
The following results indicate that the string "Freenove" has been written successfully into the data block 1.

Command “clean <address>” is used to remove the contents of the data block with address "address". For
example, if you want to clear the contents of the data block 1 that has just been written, you can type the
following command.
clean 1

support@[Link] █
290  support@[Link] [Link] █

Read the contents of data blocks in this sector again to check whether the data is erased. The following
results indicate that the contents of data block 1 have been erased.

Command “halt” is used to quit the selection state of the card.

The following is the program code:


1 #include <stdio.h>
2 #include <stdint.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <getopt.h>
6 #include <stdlib.h>
7 #include "mfrc522.h"
8 #define DISP_COMMANDLINE() printf("RC522>")
9
10 int scan_loop(uint8_t *CardID);
11 int tag_select(uint8_t *CardID);
12 int main(int argc, char **argv) {
13 MFRC522_Status_t ret;
14 //Recognized card ID
15 uint8_t CardID[5] = { 0x00, };
16 static char command_buffer[1024];
17
18 ret = MFRC522_Init('B');
19 if (ret < 0) {
20 perror("Failed to initialize");
21 exit(-1);
22 }
23
24 printf("User Space RC522 Application\r\n");
25
26 while (1) {
27 /*Main Loop Start*/
28 DISP_COMMANDLINE();
29

█ support@[Link]
█ [Link]  support@[Link] 291

30 scanf("%s", command_buffer);
31 if (strcmp(command_buffer, "scan") == 0) {
32 puts("Scanning");
33 while (1) {
34 ret = MFRC522_Check(CardID);
35 if (ret != MI_OK) {
36 printf(".");
37 fflush(stdout);
38 continue;
39 }
40 ret |= tag_select(CardID);
41 if (ret == MI_OK) {
42 ret = scan_loop(CardID);
43 if (ret < 0) {
44 goto END_SCAN;
45 } else if (ret == 1) {
46 goto HALT;
47 }
48 }
49 }
50 END_SCAN: printf("Card error...");
51 HALT: puts("Halt");
52 } else if (strcmp(command_buffer, "quit") == 0
53 || strcmp(command_buffer, "exit") == 0) {
54 return 0;
55 } else {
56 puts("Unknown command");
57 puts("scan:scan card and dump");
58 puts("quit:exit program");
59 }
60 /*Main Loop End*/
61 }
62 }
63 int scan_loop(uint8_t *CardID) {
64
65 while (1) {
66
67 char input[32];
68 int block_start;
69 DISP_COMMANDLINE();
70 printf("%02X%02X%02X%02X>", CardID[0], CardID[1], CardID[2], CardID[3]);
71 scanf("%s", input);
72 puts((char*)input);
73 if (strcmp(input, "halt") == 0) {

support@[Link] █
292  support@[Link] [Link] █

74 return 1;
75 } else if (strcmp(input, "dump") == 0) {
76 if (MFRC522_Debug_CardDump(CardID) < 0)
77 return -1;
78 } else if (strcmp(input, "read") == 0) {
79 scanf("%d", &block_start);
80 if (MFRC522_Debug_DumpSector(CardID, block_start) < 0) {
81 return -1;
82 }
83 } else if(strcmp(input, "clean") == 0){
84 char c;
85 scanf("%d", &block_start);
86 while ((c = getchar()) != '\n' && c != EOF)
87 ;
88 if (MFRC522_Debug_Clean(CardID, block_start)) {
89 return -1;
90 }
91
92 } else if (strcmp(input, "write") == 0) {
93 char write_buffer[256];
94 size_t len = 0;
95 scanf("%d", &block_start);
96 scanf("%s",write_buffer);
97 if (len >= 0) {
98 if (MFRC522_Debug_Write(CardID, block_start, write_buffer,
99 strlen(write_buffer)) < 0) {
100 return -1;
101 }
102 }
103 } else {
104
105 printf(
106 "Usage:\r\n" "\tread <blockstart>\r\n" "\tdump\r\n" "\thalt\r\n" "\tclean
<blockaddr>\r\n" "\twrite <blockaddr> <data>\r\n");
107 return 0;
108 }
109 }
110 return 0;
111
112 }
113 int tag_select(uint8_t *CardID) {
114 int ret_int;
115 printf(
116 "Card detected 0x%02X 0x%02X 0x%02X 0x%02X, Check Sum = 0x%02X\r\n",

█ support@[Link]
█ [Link]  support@[Link] 293

117 CardID[0], CardID[1], CardID[2], CardID[3], CardID[4]);


118 ret_int = MFRC522_SelectTag(CardID);
119 if (ret_int == 0) {
120 printf("Card Select Failed\r\n");
121 return -1;
122 } else {
123 printf("Card Selected, Type:%s\r\n",
124 MFRC522_TypeToString(MFRC522_ParseType(ret_int)));
125 }
126 ret_int = 0;
127 return ret_int;
128 }
In the code, first initialize the MFRC522. If the initialization fails, the program will exit.
ret = MFRC522_Init('B');
if (ret < 0) {
perror("Failed to initialize");
exit(-1);
}
In the main function, wait for the command input. If command "scan" is received, the function will begin to
detect whether there is a card close to the sensing area. If a card is detected, the card will be selected and
card UID will be acquired. Then enter the function scan_loop (). If command "quit" or "exit" is received, the
program will exit.
scanf("%s", command_buffer);
if (strcmp(command_buffer, "scan") == 0) {
puts("Scanning");
while (1) {
ret = MFRC522_Check(CardID);
if (ret != MI_OK) {
printf(".");
fflush(stdout);
continue;
}
ret |= tag_select(CardID);
if (ret == MI_OK) {
ret = scan_loop(CardID);
if (ret < 0) {
goto END_SCAN;
} else if (ret == 1) {
goto HALT;
}
}
}
END_SCAN: printf("Card error...");
HALT: puts("Halt");

support@[Link] █
294  support@[Link] [Link] █

} else if (strcmp(command_buffer, "quit") == 0


|| strcmp(command_buffer, "exit") == 0) {
return 0;
} else {
puts("Unknown command");
puts("scan:scan card and dump");
puts("quit:exit program");
}
/*Main Loop End*/
}
The function scan_loop() will detect command read, write, clean, halt, dump and do the corresponding
processing to each command. The functions of each command and the method have been introduced before.
int scan_loop(uint8_t *CardID) {

while (1) {

char input[32];
int block_start;
DISP_COMMANDLINE();
printf("%02X%02X%02X%02X>", CardID[0], CardID[1], CardID[2], CardID[3]);
scanf("%s", input);
puts((char*)input);
if (strcmp(input, "halt") == 0) {
return 1;
} else if (strcmp(input, "dump") == 0) {
if (MFRC522_Debug_CardDump(CardID) < 0)
return -1;
} else if (strcmp(input, "read") == 0) {
scanf("%d", &block_start);
if (MFRC522_Debug_DumpSector(CardID, block_start) < 0) {
return -1;
}
} else if(strcmp(input, "clean") == 0){
char c;
scanf("%d", &block_start);
while ((c = getchar()) != '\n' && c != EOF)
;
if (MFRC522_Debug_Clean(CardID, block_start)) {
return -1;
}

} else if (strcmp(input, "write") == 0) {


char write_buffer[256];
size_t len = 0;

█ support@[Link]
█ [Link]  support@[Link] 295

scanf("%d", &block_start);
scanf("%s",write_buffer);
if (len >= 0) {
if (MFRC522_Debug_Write(CardID, block_start, write_buffer,
strlen(write_buffer)) < 0) {
return -1;
}
}
} else {

printf(
"Usage:\r\n" "\tread <blockstart>\r\n" "\tdump\r\n" "\thalt\r\n"
"\tclean <blockaddr>\r\n" "\twrite <blockaddr> <data>\r\n");
return 0;
}
}
return 0;
}
The header file "mfrc522.h" contains the associated operation method for the MFRC522. You can open the
file to view all the definitions and functions.

support@[Link] █
296  support@[Link] [Link] █

Chapter 35 Soldering a Circuit Board


From previous chapters, we have learned about electronic circuits and components and have built a variety
of circuits using a Breadboard device, which is not designed to be used permanently. We now will take a
further step to make permanent projects using a Perfboard (a type of Prototype Circuit Board). Note:
Perfboard is a stiff, thin sheet of insulated material with holes bored on a grid. The grid is usually a squared
off shape with a spacing of 0.1 inches. Square copper pads cover these holes to make soldering electronic
components easier.
To finish this chapter, you need to prepare the necessary soldering equipment, including an electric soldering
iron (or soldering pencil) and solder. We have already prepared the Perfboard for you.
CAUTION: Please use extreme caution and attention to safety when you operate soldering tools used
in these projects.

Project 35.1 Soldering a Buzzer

You should be familiar with the Buzzer from our previous project. We will solder a permanent circuit that
when a Push Button Switch is pressed a Buzzer sounds
Note: This circuit does not require programming and will work when it is powered ON. When the button is
not pressed and the Buzzer is not in use, there is no power consumption.
You can install it on your bicycle, your bedroom door or any other place where you want a Buzzer.

Component list

Female Pin Header LED x1 Resistor 220Ω x1 Active buzzer x1 Push button x1
x2

AA Battery Holder x1 and AA Batteries x2

█ support@[Link]
█ [Link]  support@[Link] 297

Circuit

We will solder the following circuit on the Perfboard.


Schematic diagram Hardware connection.
If you need any support, please feel free to contact
us via: support@[Link]

Note: If you are new to soldering electronic components on any type of circuit board we strongly recommend
that you watch some instructional How-To videos by doing an Internet search and practice your soldering
technique before attempting to solder the following projects. Some components can be damaged by
exposure to excessive heat for prolonged times and there are various techniques you can learn that will help
with making neater solder joints.

Solder the Circuit

Insert the components in the Perfboard following the Hardware Connection image as a general visual guide.
Insert the pins of the components (all from the same side) so that you have only the components on one side
of the Perfboard and the pins on the other. Then from the side with the pins carefully solder the circuit on the
backside without having excess solder shorting out any portions of the circuit.

support@[Link] █
298  support@[Link] [Link] █

Here is a diagram after soldering from both sides of the Perfboard:


Front Back

█ support@[Link]
█ [Link]  support@[Link] 299

Test the Circuit

Connect the circuit board to a power supply (3~5V). You can use Raspberry Pi board or your 2 AA Cell
Battery Box as the power supply.

Tear the label off


Anode (-)

Cathode (+)

Press the Push Button Switch after connecting the power and then the buzzer will sound.

support@[Link] █
300  support@[Link] [Link] █

Project 35.2 Soldering a Flowing Water Light

You should be familiar with the Flowing Water Light from our previous project. We will solder a permanent
circuit using improved code to make a more interesting Flowing Water Light.

Component List

Female Pin Header x5 Resistor 220Ω x8 LED x8 74HC595 x1

Circuit

Solder the following circuit on the Perfboard.


Schematic diagram Hardware connection

Soldering the Circuit

Insert the components in the Perfboard, and solder the circuit on the back per earlier instructions.

█ support@[Link]
█ [Link]  support@[Link] 301

Here is a diagram after soldering from both sides of the Perfboard:


Front Back

Connecting the Circuit

Connect the board to Raspberry Pi with jumper wire in the following way.

support@[Link] █
302  support@[Link] [Link] █

VCC —3.3V/5V
GND —GND
SH_CP—GPIO22
ST_CP —GPIO27
DS —GPIO.17

█ support@[Link]
█ [Link]  support@[Link] 303

Code

This now will be the third time we have made the Flowing Water Light. In this project, we will solder a
completely new circuit for Flowing Water Light. Additionally, the program is also different from the previous
ones we have used. When this light flows, it will have a long “tail”.
C Code 35.2.1 LightWater03
First, observe the project result, and then learn about the code in detail.
If you have any concerns, please contact us via: support@[Link]
1. Use cd command to enter 35.2.1_LightWater03 directory of C code.
cd ~/Freenove_Kit/Code/C_Code/35.2.1_LightWater03
2. Use following command to compile “LightWater03.c” and generate executable file “LightWater03”.
gcc LightWater03.c -o LightWater03 -lwiringPi
3. Then run the generated file “LightWater03”.
sudo ./LightWater03
After the program is executed, the LEDs will light up in the form of flowing water with a long “tail”.

The following is the program code:


1 #include <wiringPi.h>
2 #include <stdio.h>
3 #include <wiringShift.h>
4 #include <unistd.h>
5
6 #define dataPin 0 //DS Pin of 74HC595(Pin14)
7 #define latchPin 2 //ST_CP Pin of 74HC595(Pin12)
8 #define clockPin 3 //SH_CP Pin of 74HC595(Pin11)
9 //Define an array to store the pulse width of LED, which will be output to the 8 LEDs in
order.
10 const int pluseWidth[]={0,0,0,0,0,0,0,0,64,32,16,8,4,2,1,0,0,0,0,0,0,0,0};
11 void outData(int8_t data){
12 digitalWrite(latchPin,LOW);
13 shiftOut(dataPin,clockPin,LSBFIRST,data);
14 digitalWrite(latchPin,HIGH);
15 }
16
17 void shiftOut(int dPin, int cPin, int order, int val){
18 int i;
19 for(i = 0; i <8; i++){
20 digitalWrite(cPin,LOW);
21 if (order == LSBFIRST){
22 digitalWrite(dPin, ((0x01&(val>>i)) == 0x01) ? HIGH : LOW);
23 delayMicroseconds(10); // 10 times longer then earlier exercise
24 }
25 else { // if (order == MSBFIRST) {

support@[Link] █
304  support@[Link] [Link] █

26 digitalWrite(dPin, ((0x80&(val<<i)) == 0x80) ? HIGH : LOW);


27 delayMicroseconds(10); // 10 times longer then earlier exercise
28 }
29 digitalWrite(cPin,HIGH);
30 delayMicroseconds(10); // 10 times longer than earlier exercise
31 }
32 }
33
34 int main(void)
35 {
36 int i,j,index; //index:current position in array pluseWidth
37 int moveSpeed = 100; //It works as a delay. The larger, the slower
38 long lastMove; //Record the last time point of the led move
39
40 printf("Program is starting ...\n");
41
42 wiringPiSetup();
43
44 pinMode(dataPin,OUTPUT);
45 pinMode(latchPin,OUTPUT);
46 pinMode(clockPin,OUTPUT);
47 index = 0; //Starting from the array index 0
48 lastMove = millis(); // record the start time
49 while(1){
50 if(millis() - lastMove > moveSpeed) { //speed control
51 lastMove = millis(); //Record the time point of the move
52 index++; //move to next
53 if(index > 15) index = 0; //index to 0
54 }
55 for(i=0;i<64;i++){ //The cycle of PWM is 64 cycles
56 int8_t data = 0;
57 for(j=0;j<8;j++){ //Calculate the output state
58 if(i < pluseWidth[index+j]){ //Calculate the LED state according to the
pulse width
59 data |= 0x01<<j ; //Calculate the data
60 }
61 }
62 outData(data); //Send the data to 74HC595
63 }
64 }
65 return 0;
66 }

We can see that this program is different from the previous one that we had used. We define an array to

█ support@[Link]
█ [Link]  support@[Link] 305

modulate different PWM pulse widths for LEDs, in doing so different LEDs can emit varied brightness. Starting
from the array index 0, take an array of 8 adjacent numbers as the LED duty cycle and output it one at a time.
Increasing the starting index number in turn, then it will create a flowing effect.
const int pluseWidth[]={0,0,0,0,0,0,0,0,64,32,16,8,4,2,1,0,0,0,0,0,0,0,0};

By recording the moving time point to control the speed of the movement of index number, controls the
speed of the Flowing Water Light. Variable moveSpeed saves the time interval of each move, and the greater
the value is, the slower the rate of the flowing movement (the reverse creates faster flowing movement).
if(millis() - lastMove > moveSpeed) { //speed control
lastMove = millis(); //Record the time point of the move
index++; //move to next
if(index > 15) index = 0; //index to 0
}

Finally, in a “for” loop with i=64, modulate the output pulse width of the PWM square wave. The process, from
the beginning of implementing the for loop to the end, is a PWM cycle. In the loop, there is another for loop
with j=8 and in this loop, it compares the number “i” to the value of the array to determine output high or
low level. Then, the data will be sent to the 74HC595 IC Chip.
for(i=0;i<64;i++){ //The cycle of PWM is 64 cycles
int8_t data = 0; //This loop of output data
for(j=0;j<8;j++){ //Calculate the output state of this loop
if(i < pluseWidth[index+j]){ //Calculate the LED state according to the
pulse width
data |= 0x01<<j ; //Calculate the data
}
}
outData(data); //Send the data to 74HC595
}

support@[Link] █
306  support@[Link] [Link] █

Other Components
This kit also includes other common components that can help your ideas come true. Now we will introduce
components not mentioned in the previous section.

Component Knowledge

Toggle switch
Like push button switch, toggle switch is also a kind of switching devices. The difference is that toggle switch
is suitable for long-time open or close circuits.

When the lever is moved to the left, pin 1, 2 get conducted, and pin 2, 3 are disconnected from each other;
When the lever is moved to the right, pin 2,3 get conducted, and pin 1,2 are disconnected from each other;

Switch diode
There are several types of diodes. We have used 1N4001 before, which is a common rectifier diode and
commonly used in ac rectifier.
Here is 1N4148, which is a kind of high-speed switching diodes and is characterized by a relatively rapid
switching.

For the switching diode, the changing time from conduction to cut off or from cut off to conduction is shorter
than general diode and it is mainly used in electronic computer, pulse and switching circuits.
9V battery cable
A 9V battery cable can connect a 9 V battery, which can supply power for control board.

█ support@[Link]
█ [Link]  support@[Link] 307

The installation of 9V battery cable is as follows:

Power supply module for breadboard


The following is the power supply module for breadboard. This module can provide the breadboard with
two-channel power supply separately, and each can be configured to 3.3 V or 5 V separately through a jumper.

Power Switch Power Indicator

Power Jack USB Jack

Output voltage option Output voltage option

Power output pin Power output pin

We can build a circuit conveniently by using this module. You only need to provide power supply for this
module, and then insert it on the breadboard.

support@[Link] █
308  support@[Link] [Link] █

What's Next?
THANK YOU for participating in this learning experience! If you have completed all of the projects successfully
you can consider yourself a Raspberry Pi Master.

We have reached the end of this Tutorial. If you find errors, omissions or you have suggestions and/or
questions about the Tutorial or component contents of this Kit, please feel free to contact us:
support@[Link]
We will make every effort to make changes and correct errors as soon as feasibly possible and publish a
revised version.

If you are interesting in processing, you can study the [Link] in the unzipped folder.

If you want to learn more about Arduino, Raspberry Pi, Smart Cars, Robotics and other interesting products
in science and technology, please continue to visit our website. We will continue to launch fun, cost-effective,
innovative and exciting products.
[Link]

Thank you again for choosing Freenove products.

█ support@[Link]

You might also like