C Tutorial
C Tutorial
com
Important Information
Thank you for choosing Freenove products!
Getting Started
First, please read the Read Me First.pdf document in the unzipped folder you created.
If you have not yet downloaded the zip file, associated with this kit, please do so now and unzip it.
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@freenove.com
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 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
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:
http://www.freenove.com
sale@freenove.com
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.
TM
Contents
Important Information....................................................... 1
Contents ................................................................................. 1
Preface .................................................................................... 1
ESP32-WROVER ........................................................................................................................................................................ 2
Extension board of the ESP32-WROVER .......................................................................................................................... 5
CH340 ........................................................................................................................................................................................... 6
Programming Software ......................................................................................................................................................... 16
Environment Configuration ................................................................................................................................................. 19
Notes for GPIO......................................................................................................................................................................... 23
Chapter 7 Buzzer.............................................................. 75
Project 7.1 Doorbell................................................................................................................................................................ 75
Project 7.2 Alertor ................................................................................................................................................................... 81
Preface
ESP32 is a micro control unit with integrated Wi-Fi launched by Espressif, which features strong properties
and integrates rich peripherals. It can be designed and studied as an ordinary Single Chip Micyoco(SCM) chip,
or connected to the Internet and used as an Internet of Things device.
ESP32 can be developed using the Arduino platform, which will definitely make it easier for people who have
learned arduino to master. Moreover, the code of ESP32 is completely open-source, so beginners can quickly
learn how to develop and design IOT smart household products including smart curtains, fans, lamps and
clocks.
Generally, ESP32 projects consist of code and circuits. Don't worry even if you've never learned code and
circuits, because we will gradually introduce the basic knowledge of C programming language and electronic
circuits, from easy to difficult. Our products contain all the electronic components and modules needed to
complete these projects. It's especially suitable for beginners.
We divide each project into four parts, namely Component List, Component Knowledge, Circuit and Code.
Component List helps you to prepare material for the experiment more quickly. Component Knowledge allows
you to quickly understand new electronic modules or components, while Circuit helps you understand the
operating principle of the circuit. And Code allows you to easily master the use of SEP32 and accessory kit.
After finishing all the projects in this tutorial, you can also use these components and modules to make
products such as smart household, smart cars and robots to transform your creative ideas into prototypes
and new and innovative products.
In addition, if you have any difficulties or questions with this tutorial or toolkit, feel free to ask for our quick
and free technical support through support@freenove.com
ESP32-WROVER
ESP32-WROVER has launched a total of two antenna packages, PCB on-board antenna and IPEX antenna
respectively. The PCB on-board antenna is an integrated antenna in the chip module itself, so it is convenient
to carry and design. The IPEX antenna is a metal antenna derived from the integrated antenna of the chip
module itself, which is used to enhance the signal of the module.
PCB on-board antenna IPEX antenna
In this tutorial, the ESP32-WROVER is designed based on the PCB on-board antenna-packaged ESP32-
WROVER module.
ESP32-WROVER
Compare the left and right images. We've boxed off the resources on the ESP32-WROVER in different colors
to facilitate your understanding of the ESP32-WROVER.
Box color Corresponding resources introduction
GPIO pin
LED indicator
Camera interface
USB port
And we also design an extension board, so that you can use the ESP32 more easily in accordance with the
circuit diagram provided. The followings are their photos.
The hardware interfaces of ESP32-WROVER are distributed as follows:
We've boxed off the resources on the ESP32-WROVER in different colors to facilitate your understanding of
the ESP32-WROVER.
Box color Corresponding resources introduction
GPIO pin
LED indicator
GPIO interface of development board
power supplied by the extension board
External power supply
In ESP32, GPIO is an interface to control peripheral circuit. For beginners, it is necessary to learn the
functions of each GPIO. The following is an introduction to the GPIO resources of the ESP32-WROVER
development board.
In the following projects, we only use USB cable to power ESP32-WROVER by default.
In the whole tutorial, we don’t use T extension to power ESP32-WROVER. So 5V and 3.3V (including EXT 3.3V)
on the extension board are provided by ESP32-WROVER.
We can also use DC jack of extension board to power ESP32-WROVER.In this way, 5v and EXT 3.3v on
extension board are provided by external power resource.
CH340
ESP32 uses CH340 to download codes. So before using it, we need to install CH340 driver in our computers.
Windows
2. Turn to the main interface of your computer, select “This PC” and right-click to select “Manage”.
3. Click “Device Manager”. If your computer has installed CH340, you can see“USB-SERIAL CH340 (COMx)”.
And you can click here to move to the next step.
CH340 Port
Installing CH340
1. First, download CH340 driver, click http://www.wch-ic.com/search?q=CH340&t=downloads to download
the appropriate one based on your operating system.
Windows
Linux
MAC
If you would not like to download the installation package, you can open
“Freenove_Ultimate_Starter_Kit_for_ESP32/CH340”, we have prepared the installation package.
6. When ESP32 is connected to computer, select “This PC”, right-click to select “Manage” and click “Device
Manager” in the newly pop-up dialog box, and you can see the following interface.
7. So far, CH340 has been installed successfully. Close all dialog boxes.
MAC
Windows
Linux
MAC
If you would not like to download the installation package, you can open
“Freenove_Ultimate_Starter_Kit_for_ESP32/CH340”, we have prepared the installation package.
Second, open the folder “Freenove_Ultimate_Starter_Kit_for_ESP32/CH340/MAC/”
Run it.
If you still haven't installed the CH340 by following the steps above, you can view readme.pdf to install it.
ReadMe
Programming Software
Arduino Software (IDE) is used to write and upload the code for Arduino Board.
First, install Arduino Software (IDE): visit https://www.arduino.cc, click "Download" to enter the download page.
Select and download corresponding installer according to your operating system. If you are a windows user,
please select the "Windows Installer" to download to install the driver correctly.
After the download completes, run the installer. For Windows users, there may pop up an installation dialog
box of driver during the installation process. When it popes up, please allow the installation.
After installation is complete, an Arduino Software shortcut will be generated in the desktop. Run the Arduino
Software.
Menus
Toolbar
Text editor
Message
area
Console
Configured board
and serial port
Programs written with Arduino Software (IDE) are called sketches. These sketches are written in the text
editor and saved with the file extension.ino. The editor has features for cutting/pasting and
searching/replacing text. The message area gives feedback while saving and exporting and also displays
errors. The console displays text output by the Arduino Software (IDE), including complete error messages
and other information. The bottom right-hand corner of the window displays the configured board and
serial port. The toolbar buttons allow you to verify and upload programs, create, open, and save sketches,
and open the serial monitor.
Verify
Check your code for compile errors .
Upload
Compile your code and upload them to the configured board.
New
Create a new sketch.
Open
Present a menu of all the sketches in your sketchbook. Clicking one will open it within the
current window and overwrite its content.
Save
Save your sketch.
Serial Monitor
Open the serial monitor.
Additional commands are found within the five menus: File, Edit, Sketch, Tools, Help. The menus are context
sensitive, which means only those items relevant to the work currently being carried out are available.
Environment Configuration
First, open the software platform arduino, and then click File in Menus and select Preferences.
Fourth, click Tools in Menus, select Board:"ArduinoUno", and then select "Boards Manager".
Fifth, input "esp32" in the window below, and press Enter. click "Install" to install.
When finishing installation, click Tools in the Menus again and select Board: "Arduino Uno", and then you
can see information of ESP32-WROVER. click "ESP32-WROVER" so that the ESP32 programming
development environment is configured.
Strapping Pin
If you have any questions about the information of GPIO, you can click here to go back to ESP32-WROVER
to view specific information about GPIO.
If you have any difficulties or questions with this tutorial or toolkit, feel free to ask for our quick and free
technical support through support@freenove.com at any time.
or check: https://www.espressif.com/sites/default/files/documentation/esp32-wrover_datasheet_en.pdf
Flash Pin
GPIO6-11 has been used to connect the integrated SPI flash on the module, and is used when GPIO 0 is
power on and at high level. Flash is related to the operation of the whole chip, so the external pin GPIO6-11
cannot be used as an experimental pin for external circuits, otherwise it may cause errors in the operation of
the program.
GPIO16-17 has been used to connect the integrated PSRAM on the module.
Because of external pull-up, MTDI pin is not suggested to be used as a touch sensor. For details, please refer
to Peripheral Interface and Sensor chapter in "ESP32 Data_Sheet".
For more relevant information, please check:
https://www.espressif.com/sites/default/files/documentation/esp32-wrover_datasheet_en.pdf.
Cam Pin
When using the camera of our ESP32-WROVER, please check the pins of it. Pins with underlined numbers
are used by the camera function, if you want to use other functions besides it, please avoid using them.
CAM_Pin GPIO_pin
I2C_SDA GPIO26
I2C_SCL GPIO27
CSI_VYSNC GPIO25
CSI_HREF GPIO23
CSI_Y9 GPIO35
XCLK GPIO21
CSI_Y8 GPIO34
CSI_Y7 GPIO39
CSI_PCLK GPIO22
CSI_Y6 GPIO36
CSI_Y2 GPIO4
CSI_Y5 GPIO19
CSI_Y3 GPIO5
CSI_Y4 GPIO18
If you have any questions about the information of GPIO, you can click here to go back to ESP32-WROVER
to view specific information about GPIO.
or check: https://www.espressif.com/sites/default/files/documentation/esp32-wrover_datasheet_en.pdf.
Chapter 0 LED
This chapter is the Start Point in the journey to build and explore ESP32 electronic projects. We will start with
simple “Blink” project.
Component List
Power
ESP32-WROVER needs 5v power supply. In this tutorial, we need connect ESP32-WROVER to computer via
USB cable to power it and program it. We can also use other 5v power source to power it.
In the following projects, we only use USB cable to power ESP32-WROVER by default.
In the whole tutorial, we don’t use T extension to power ESP32-WROVER. So 5V and 3.3V (includeing EXT
3.3V) on the extension board are provided by ESP32-WROVER.
We can also use DC jack of extension board to power ESP32-WROVER.In this way, 5v and EXT 3.3v on
extension board are provided by external power resource.
Sketch
According to the circuit, when the GPIO2 of ESP32-WROVER output level is high, the LED turns ON.
Conversely, when the GPIO2 ESP32-WROVER output level is low, the LED turns OFF. Therefore, we can let
GPIO2 circularly output high and low level to make the LED blink.
Upload the following Sketch:
Freenove_Ultimate_Starter_Kit_for_ESP32\Sketches\Sketch_01.1_Blink.
Before uploading the code, click "Tools", "Board" and select "ESP32 Wrover Module".
Note: For macOS users, if the uploading fails, please set the baud rate to 115200 before clicking
“Upload Using Programmer”.
Sketch_01.1_Blink
Click “Upload”,Download the code to ESP32-WROVER and your LED in the circuit starts Blink.
The Arduino IDE code usually contains two basic functions: void setup() and void loop().
After the board is reset, the setup() function will be executed firstly, and then the loop() function.
setup() function is generally used to write code to initialize the hardware. And loop() function is used to write
code to achieve certain functions. loop() function is executed repeatedly. When the execution reaches the end
of loop(), it will jump to the beginning of loop() to run again.
Reset 1 // the setup function runs once when you press reset or power the board
2 void setup() {
… …
5 }
6
7 // the loop function runs over and over again forever
8 void loop() {
… …
13 }
Reset
Reset operation will lead the code to be executed from the beginning. Switching on the power, finishing
uploading the code and pressing the reset button will trigger reset operation.
In the circuit, ESP32-WROVER's GPIO2 is connected to the LED, so the LED pin is defined as 2.
1 #define PIN_LED 2
This means that after this line of code, all PIN_LED will be treated as 2.
In the setup () function, first, we set the PIN_LED as output mode, which can make the port output high level
or low level.
4 // initialize digital pin PIN_LED as an output.
5 pinMode(PIN_LED, OUTPUT);
Then, in the loop () function, set the PIN_LED to output high level to make LED light up.
10 digitalWrite(PIN_LED, HIGH); // turn the LED on (HIGH is the voltage level)
Wait for 1000ms, that is 1s. Delay () function is used to make control board wait for a moment before executing
the next statement. The parameter indicates the number of milliseconds to wait for.
11 delay(1000); // wait for a second
Then set the PIN_LED to output low level, and LED light off. One second later, the execution of loop () function
will be completed.
12 digitalWrite(PIN_LED, LOW); // turn the LED off by making the voltage LOW
13 delay(1000); // wait for a second
The loop() function is constantly being executed, so LED will keep blinking.
Reference
void pinMode(int pin, int mode);
Configures the specified pin to behave either as an input or an output.
Parameters
pin: the pin number to set the mode of.
mode: INPUT, OUTPUT, INPUT_PULLDOWM, or INPUT_PULLUP.
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 functions, please refer to https://www.arduino.cc/reference/en/
Chapter 1 LED
This chapter is the Start Point in the journey to build and explore ESP32 electronic projects. We will start with
simple “Blink” project.
Component List
Breadboard x1
Component knowledge
LED
A LED is a type of diode. All diodes only work if current is flowing in the correct direction and have two poles.
A 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 (-). Negative output is also referred to as Ground
(GND). This type of component is known as “diodes” (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 burn 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 appendix of this tutorial.
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.
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 way to connect pins. The right picture shows the practical internal structure.
Power
ESP32-WROVER needs 5v power supply. In this tutorial, we need connect ESP32-WROVER to computer via
USB cable to power it and program it. We can also use other 5v power source to power it.
In the following projects, we only use USB cable to power ESP32-WROVER by default.
In the whole tutorial, we don’t use T extension to power ESP32-WROVER. So 5V and 3.3V (includeing EXT
3.3V) on the extension board are provided by ESP32-WROVER.
We can also use DC jack of extension board to power ESP32-WROVER.In this way, 5v and EXT 3.3v on
extension board are provided by external power resource.
Circuit
First, disconnect all power from the ESP32-WROVER. Then build the circuit according to the circuit and
hardware diagrams. After the circuit is built and verified correct, connect the PC to ESP32-WROVER.
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, generate excessive component heat and cause permanent
damage to your hardware!
Schematic diagram
Hardware connection. If you need any support, please contact us via: support@freenove.com
Longer Pin
Sketch
According to the circuit, when the GPIO2 of ESP32-WROVER output level is high, the LED turns ON.
Conversely, when the GPIO2 ESP32-WROVER output level is low, the LED turns OFF. Therefore, we can let
GPIO2 circularly output high and low level to make the LED blink.
Upload the following Sketch:
Freenove_Ultimate_Starter_Kit_for_ESP32\Sketches\Sketch_01.1_Blink.
Before uploading the code, click "Tools", "Board" and select "ESP32 Wrover Module".
Note: For macOS users, if the uploading fails, please set the baud rate to 115200 before clicking
“Upload Using Programmer”.
Sketch_01.1_Blink
Click “Upload”,Download the code to ESP32-WROVER and your LED in the circuit starts Blink.
Control:
ESP32,
RPI, Arduino,
MCU and etc.
Input: Output:
switches, sensors LED, buzzer,
and etc. motor and etc.
Next, we will build a simple control system to control a LED through a push button switch.
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.
Component List
Breadboard x1
Component knowledge
Push button
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
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
This project is designed for learning how to use push button switch to control a 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.
Upload following sketch:
Freenove_Ultimate_Starter_Kit_for_ESP32\Sketches\Sketch_02.1_ButtonAndLed.
Sketch_02.1_ButtonAndLed
Download the code to ESP32-WROVER, then press the key, the LED turns ON, release the switch, the LED
turns OFF.
In the circuit connection, LED and button are connected with GPIO2 and GPIO13 respectively, so define ledPin
and buttonPin as 2 and 13 respectively.
1 #define PIN_LED 2
2 #define PIN_BUTTON 13
In the while cycle 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. Otherwise,
turn off LED.
11 void loop() {
12 if (digitalRead(PIN_BUTTON) == LOW) {
13 digitalWrite(PIN_LED,HIGH);
14 }else{
15 digitalWrite(PIN_LED,LOW);
16 }
17 }
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.
We will also use a push button switch, LED and ESP32 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.
The moment when a 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
completely reaches another 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.
Sketch
Sketch_02.2_Tablelamp
Download the code to the ESP32-WROVER, press the button, the LED turns ON, and press the button again,
the LED turns OFF.
When judging the push button state, if it is detected as "pressed down", wait for a certain time to detect again
to eliminate the effect of bounce. When confirmed, flip the LED on and off. Then it starts to wait for the
pressed button to be released, and waits for a certain time to eliminate the effect of bounce after it is released.
12 if (digitalRead(PIN_BUTTON) == LOW) {
13 delay(20);
14 if (digitalRead(PIN_BUTTON) == LOW) {
15 reverseGPIO(PIN_LED);
16 }
17 while (digitalRead(PIN_BUTTON) == LOW);
18 delay(20);
19 while (digitalRead(PIN_BUTTON) == LOW);
20 }
The subfunction reverseGPIO() means reading the state value of the specified pin, taking the value back and
writing it to the pin again to achieve the function of flipping the output state of the pin.
23 void reverseGPIO(int pin) {
24 digitalWrite(pin, ! digitalRead(pin));
25 }
Component List
Breadboard x1
Component knowledge
Let’s learn about the basic features of these components to use and understand them better.
LED bar
A LED bar graph 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.
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
If LED bar does not work, try to rotate it for 180°. The label is random.
Sketch
This project is designed to make a flowing water lamp. Which are these actions: First turn LED #1 ON, then
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.
Upload following sketch:
Freenove_Ultimate_Starter_Kit_for_ESP32\Sketches\Sketch_03.1_FlowingLight.
Sketch_03.1_FlowingLight
Download the code to ESP32-WROVER and LED bar graph will light up from left to right and from right to
left.
Breathing light, that is, LED is turned from off to on gradually, and gradually from on to off, just like "breathing".
So, how to control the brightness of a LED? We will use PWM to achieve this target.
Component List
Breadboard x1
Related knowledge
In practical application, 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.
Common 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 outputs 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%:
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 a LED or the speed of DC motor and so on.
It is evident from the above that PWM is not real analog, and the effective value of the voltage is equivalent
to the corresponding analog. Therefore, we can control the output power of the LED and other output
modules to achieve different effects.
80,000,000
Freqmax =
1≪𝑏𝑖𝑡
8
For example, generate a PWM with an 8-bit precision (2 =256. Values range from 0 to 255) with a maximum
frequency of 80,000,000/255 = 312,500Hz.)
Circuit
Hardware connection. If you need any support, please contact us via: support@freenove.com
Sketch
This project is designed to make PWM output GPIO2 with pulse width increasing from 0% to 100%, and then
reducing from 100% to 0% gradually.
Sketch_04.1_BreathingLight
Download the code to ESP32-WROVER, and you'll see that LED is turned from on to off and then from off to
on gradually like breathing.
The PWM pin output mode of ESP32 is not the same as the traditional controller. It controls each parameter
of PWM by controlling the PWM channel. Any number of GPIO can be connected with the PWM channel to
output PWM. In setup(), you first configure a PWM channel and set the frequency and precision.
6 ledcSetup(CHN, FRQ, PWM_BIT); //setup pwm channel
In the loop(), There are two “for” loops. The first makes the ledPin output PWM from 0% to 100% and the
second makes the ledPin output PWM from 100% to 0%. This allows the LED to gradually light and extinguish。
11 for (int i = 0; i < 255; i++) { //make light fade in
12 ledcWrite(CHN, i);
13 delay(10);
14 }
15 for (int i = 255; i > -1; i--) { //make light fade out
16 ledcWrite(CHN, i);
17 delay(10);
18 }
You can also adjust the rate of the state change of LED by changing the parameters of the delay() function in
the “for” loop.
Parameters
chan: channel index. Value range :0-15
freq: frequency, it could be a decimal.
bit_num: precision of values.
After learning about PWM, we can use it to control LED bar graph and realize a cooler flowing light.
The component list, circuit, and hardware are exactly consistent with the project Flowing Light.
Sketch
Download the code to ESP32-WROVER, and LED bar graph will gradually light up and out from left to right,
then light up and out from right to left.
In setup(), set the frequency of 10 PWM channels to 1000Hz, the accuracy to 10bits, and the maximum
pulse width to 1023. Attach GPIO to these PWM channels.
for (int i = 0; i < ledCounts; i++) { //setup the pwm channels
ledcSetup(chns[i], 1000, 10);
ledcAttachPin(ledPins[i], chns[i]);
}
In loop(), a nested for loop is used to control the pulse width of the PWM, and LED bar graph moves one grid
after each 1 is added in the first for loop, gradually changing according to the values in the array duties. As
shown in the table below, the value of the second row is the value in the array duties, and the 10 green
squares in each row below represent the 10 LEDs on the LED bar graph. Every 1 is added to I, the value of the
LED bar graph will move to the right by one grid, and when it reaches the end, it will move from the end to
the starting point, achieving the desired effect.
0 1 2 3 4 5 7 8 9 1 11 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3
0 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
d 0 0 0 0 0 0 0 0 0 10 5 2 1 6 3 1 8 4 2 0 0 0 0 0 0 0 0 0 0
23 1 5 2 4 2 6
i 2 6 8
0
1
2
3
…
1
8
1
9
2
0
In the code, two nested for loops are used to achieve this effect.
for (int i = 0; i < 20; i++) { //flowing one side to other side
for (int j = 0; j < ledCounts; j++) {
ledcWrite(chns[j], dutys[i + j]);
}
delay(delayTimes);
}
for (int i = 0; i < 20; i++) { //flowing from one side to the other
for (int j = ledCounts - 1; j > -1; j--) {
ledcWrite(chns[j], dutys[i + (ledCounts - 1 - j)]);
}
delay(delayTimes);
}
In this project, we will make a multicolored LED. And we can control RGB LED to switch different colors
automatically.
Component List
Breadboard x1
Related knowledge
RGB LED has integrated 3 LEDs that can respectively emit red, green and blue light. And it has 4 pins. The
long pin (1) is the common port, that is, 3 LED 's positive or negative port. The RGB LED with common positive
port and its symbol is shown below. We can make RGB LED emit various colors of light by controlling these 3
LEDs to emit light with different brightness,
Red, green, and blue are known as three primary colors. When you combine these three primary-color lights
with different brightness, it can produce almost all kinds of visible lights. Computer screens, single pixel of cell
phone screen, neon, and etc. are working under this principle.
RGB
8 8 8
If we use three 8-bit PWMs to control the RGB LED, in theory, we can create 2 *2 *2 =16777216 (16 million)
colors through different combinations.
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
We need to create three PWM channels and use random duty cycle to make random RGB LED color.
Sketch_05.1_ColorfulLight
With the code downloaded to ESP32-WROVER, RGB LED begins to display random colors.
Define the PWM channel and associate it with the pin connected to RGB LED, and define the variable to hold
the color value and initialize it in setup().
1 const byte ledPins[] = {15, 2, 4}; //define red, green, blue led pins
2 const byte chns[] = {0, 1, 2}; //define the pwm channels
3 int red, green, blue;
4 void setup() {
5 for (int i = 0; i < 3; i++) { //setup the pwm channels,1KHz,8bit
6 ledcSetup(chns[i], 1000, 8);
7 ledcAttachPin(ledPins[i], chns[i]);
8 }
9 }
In setColor(), this function controls the output color of RGB LED by the given color value. Because the circuit
uses a common anode, the LED lights up when the GPIO outputs low power. Therefore, in PWM, low level is
the active level, so 255 minus the given value is necessary.
19 void setColor(byte r, byte g, byte b) {
20 ledcWrite(chns[0], 255 - r); //Common anode LED, low level to turn on the led.
21 ledcWrite(chns[1], 255 - g);
22 ledcWrite(chns[2], 255 - b);
23 }
In loop(), get three random Numbers and set them as color values.
12 red = random(0, 256);
13 green = random(0, 256);
14 blue = random(0, 256);
15 setColor(red, green, blue);
16 delay(200);
In the previous project, we have mastered the usage of RGB LED, but the random display of colors is rather
stiff. This project will realize a fashionable light with soft color changes.
Component list and the circuit are exactly the same as the random color light.
Using a color model, the color changes from 0 to 255 as shown below.
In this code, the color model will be implemented and RGB LED will change colors along the model.
Sketch_05.2_SoftColorfulLight
The following is the program code:
1 const byte ledPins[] = {15, 2, 4}; //define led pins
2 const byte chns[] = {0, 1, 2}; //define the pwm channels
3
4 void setup() {
5 for (int i = 0; i < 3; i++) { //setup the pwm channels
6 ledcSetup(chns[i], 1000, 8);
7 ledcAttachPin(ledPins[i], chns[i]);
8 }
9 }
10
11 void loop() {
12 for (int i = 0; i < 256; i++) {
13 setColor(wheel(i));
14 delay(20);
15 }
16 }
17
18 void setColor(long rgb) {
19 ledcWrite(chns[0], 255 - (rgb >> 16) & 0xFF);
20 ledcWrite(chns[1], 255 - (rgb >> 8) & 0xFF);
21 ledcWrite(chns[2], 255 - (rgb >> 0) & 0xFF);
22 }
23
24 long wheel(int pos) {
25 long WheelPos = pos % 0xff;
26 if (WheelPos < 85) {
27 return ((255 - WheelPos * 3) << 16) | ((WheelPos * 3) << 8);
28 } else if (WheelPos < 170) {
29 WheelPos -= 85;
30 return (((255 - WheelPos * 3) << 8) | (WheelPos * 3));
31 } else {
32 WheelPos -= 170;
33 return ((WheelPos * 3) << 16 | (255 - WheelPos * 3));
34 }
35 }
In setColor(), a variable represents the value of RGB, and a hexadecimal representation of color is a common
representation, such as 0xAABBCC, where AA represents the red value, BB represents the green value, and
CC represents the blue value. The use of a variable can make the transmission of parameters more convenient,
in the split, only a simple operation can take out the value of each color channel
18 void setColor(long rgb) {
19 ledcWrite(chns[0], 255 - (rgb >> 16) & 0xFF);
20 ledcWrite(chns[1], 255 - (rgb >> 8) & 0xFF);
21 ledcWrite(chns[2], 255 - (rgb >> 0) & 0xFF);
22 }
The wheel() function is the color selection method for the color model introduced earlier. The pos parameter
ranges from 0 to 255 and outputs a color value in hexadecimal.
Chapter 6 LEDPixel
This chapter will help you learn to use a more convenient RGB LED lamp, which requires only one GPIO
control and can be connected in infinite series in theory. Each LED can be controlled independently.
Learn the basic usage of LEDPixel and use it to flash red, green, blue and white.
Component List
Breadboard x1
Related knowledge
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 this 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
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
This code uses a library named "Freenove_WS2812_Lib_for_ESP32", if you have not installed it, please do so
first.
Library is an important feature of the open source world, and we know that Arduino is an open source platform
that everyone can contribute to. Libraries are generally licensed under the LGPL, which means you can use
them for free to apply to your creations.
How to install the library
There are two ways to add libraries.
The first way, open the Arduino IDE, click Tools Manager Libraries.
In the pop-up window, Library Manager, search for the name of the Library, “Freenove WS2812 Lib for ESP32”.
Then click Install.
The second way,open Arduino IDE,click SketchInclude LibraryAdd .ZIP Library,In the pop-up window,
find the file named “./Libraries/Freenove_WS2812_Lib_for_ESP32.Zip” which locates in this directory,and
click OPEN.
Sketch_06.1_LEDPixel
Download the code to ESP32-WROVER and RGB LED begins to light up in red, green, blue, white and black.
14 strip.setBrightness(10);
15 }
16 void loop() {
17 for (int j = 0; j < 5; j++) {
18 for (int i = 0; i < LEDS_COUNT; i++) {
19 strip.setLedColorData(i, m_color[j][0], m_color[j][1], m_color[j][2]);
20 strip.show();
21 delay(delayval);
22 }
23 delay(500);
24 }
25 }
To use some libraries, first you need to include the library's header file.
1 #include "Freenove_WS2812_Lib_for_ESP32.h"
Define the pins connected to the ring, the number of LEDs on the ring, and RMT channel values。
3 #define LEDS_COUNT 8 // The number of led
4 #define LEDS_PIN 2 // define the pin connected to the Freenove 8 led strip
5 #define CHANNEL 0 // RMT channel
Use the above parameters to create a LEDPixel object strip.
7 Freenove_ESP32_WS2812 strip = Freenove_ESP32_WS2812(LEDS_COUNT, LEDS_PIN, CHANNEL, TYPE_GRB);
Define the color values to be used, as red, green, blue, white, and black.
9 u8 m_color[5][3] = { {255, 0, 0}, {0, 255, 0}, {0, 0, 255}, {255, 255, 255}, {0, 0, 0} };
Define a variable to set the time interval for each led to light up. The smaller the value is, the faster it will
light up.
10 int delayval = 50;
Initialize strip() in setup() and set the brightness.
13 strip.begin();
14 strip.setBrightness(10);
In the loop(), there are two “for” loops, the internal for loop to light the LED one by one, and the external for
loop to switch colors. strip.setLedColorData() is used to set the color, but it does not change immediately.
Only when strip.show() is called will the color data be sent to the LED to change the color.
17 for (int j = 0; j < 5; j++) {
18 for (int i = 0; i < LEDS_COUNT; i++) {
19 strip.setLedColorData(i, m_color[j][0], m_color[j][1], m_color[j][2]);
20 strip.show();
21 delay(delayval);
22 }
23 delay(500);
24 }
Reference
Freenove_ESP32_WS2812(u16 n = 8, u8 pin_gpio = 2, u8 chn = 0, LED_TYPE t = TYPE_GRB)
Constructor to create a LEDPixel object.
Before each use of the constructor, please add “#include "Freenove_WS2812_Lib_for_ESP32.h”
Parameters
n:The number of led.
pin_gpio:A pin connected to an led.
Chn: RMT channel, which uses channel 0 by default, has a total of eight channels, 0-7. This means that you
can use eight LEDPixel modules for the display at the same time, and these modules do not interfere with
each other
t:Types of LED.
TYPE_RGB:The sequence of LEDPixel module loading color is red, green and blue.
TYPE_RBG:The sequence of LEDPixel module loading color is red, blue and green.
TYPE_GRB:The sequence of LEDPixel module loading color is green, red and blue.
TYPE_GBR:The sequence of LEDPixel module loading color is green, blue and red.
TYPE_BRG:The sequence of LEDPixel module loading color is blue, red and green.
TYPE_BGR:The sequence of LEDPixel module loading color is blue,g reen and red.
void begin(void);
Initialize the LEDPixel object
void setLedColorData (u8 index, u8 r, u8 g, u8 b);
void setLedColorData (u8 index, u32 rgb);
void setLedColor (u8 index, u8 r, u8 g, u8 b);
void setLedColor (u8 index, u32 rgb);
Set the color of led with order number n.
void show(void);
Send the color data to the led and display the set color immediately.
void setBrightness(uint8_t);
Set the brightness of the LED.
If you want to learn more about this library, you can visit the following website:
https://github.com/Freenove/Freenove_WS2812_Lib_for_ESP32
In the previous project, we have mastered the use of LEDPixel. This project will realize a slightly complicated
rainbow light. The component list and the circuit are exactly the same as the project fashionable light.
Sketch
Continue to use the following color model to equalize the color distribution of the 8 LEDs and gradually
change.
Sketch_06.2_RainbowLight
Download the code to ESP32-WROVER, and the Freenove 8 RGB LED Strip displays different colors and the
color changes gradually.
In the loop(), two “for” loops are used, the internal “for” loop(for-j) is used to set the color of each LED, and
the external “for” loop(for-i) is used to change the color, in which the self-increment value in i+=1 can be
changed to change the color step distance. Changing the delay parameter changes the speed of the color
change. Wheel(i * 256 / LEDS_COUNT + j) & 255) will take color from the color model at equal intervals
starting from i.
14 for (int j = 0; j < 255; j += 1) {
15 for (int i = 0; i < LEDS_COUNT; i++) {
16 strip.setLedColorData(i, strip.Wheel((i * 256 / LEDS_COUNT + j) & 255));
17 }
18 strip.show(); // Send color data to LED, and display.
19 delay(5);
20 }
Chapter 7 Buzzer
In this chapter, we will learn about buzzers that can make sounds.
We will make this kind of doorbell: when the button is pressed, the buzzer sounds; and when the button is
released, the buzzer stops sounding.
Component List
Breadboard x1
Jumper M/M x6
NPN transistorx1 Active buzzer x1 Push button x1 Resistor 1kΩ x1 Resistor 10kΩ x2
(S8050)
Component knowledge
Buzzer
Buzzer is a sounding component, which is widely used in electronic devices such as calculator, electronic
warning clock and alarm. Buzzer has two types: active and passive. Active buzzer has oscillator inside, which
will sound as long as it is supplied with power. Passive buzzer requires external oscillator signal (generally use
PWM with different frequency) to make a sound.
Active buzzer is easy to use. Generally, it can only make a specific frequency of sound. Passive buzzer
requires an external circuit to make a sound, but it can be controlled to make a sound with different
frequency. The resonant frequency of the passive buzzer is 2kHz, which means the passive buzzer is loudest
when its resonant frequency is 2kHz.
Next, we will use an active buzzer to make a doorbell and a passive buzzer to make an alarm.
Transistor
Because the buzzer requires such large current that GPIO of ESP32 output capability cannot meet the
requirement, a transistor of NPN type is needed here to amplify the current.
Transistor, the full name: semiconductor transistor, is a semiconductor device that controls current. Transistor
can be used to amplify weak signal, or works as a switch. It has three electrodes(PINs): base (b), collector (c)
and emitter (e). When there is current passing between "be", "ce" will allow several-fold current (transistor
magnification) pass, at this point, transistor works in the amplifying area. When current between "be" exceeds
a certain value, "ce" will not allow current to increase any longer, at this point, transistor works in the saturation
area. Transistor has two types as shown below: PNP and NPN,
In our kit, the PNP transistor is marked with 8550, and the NPN transistor is marked with 8050.
Based on the transistor's characteristics, it is often used as a switch in digital circuits. As micro-controller's
capacity to output current is very weak, we will use transistor to amplify current and drive large-current
components.
When use NPN transistor to drive buzzer, we often adopt the following method. If GPIO outputs high level,
current will flow through R1, the transistor will get conducted, and the buzzer will sound. If GPIO outputs low
level, no current flows through R1, the transistor will not be conducted, and buzzer will not sound.
When use PNP transistor to drive buzzer, we often adopt the following method. If GPIO outputs low level,
current will flow through R1, the transistor will get conducted, and the buzzer will sound. If GPIO outputs high
level, no current flows through R1, the transistor will not be conducted, and buzzer will not sound.
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Note: in this circuit, the power supply for buzzer is 5V, and pull-up resistor of the button connected to the
power 3.3V. The buzzer can work when connected to power 3.3V, but it will reduce the loudness.
Sketch
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 a LED ON and OFF.
Sketch_07.1_Doorbell
Download the code to ESP32-WROVER, press the push button switch and the buzzer will sound. Release the
push button switch and the buzzer will stop.
Sketch
In this project, the buzzer alarm is controlled by the button. Press the button, then buzzer sounds. If you
release the button, the buzzer will stop sounding. It is logically the same as using button to control LED, but
in the control method, passive buzzer requires PWM of certain frequency to sound.
Sketch_07.2_Alertor
Download the code to ESP32-WROVER, press the button, then alarm sounds. And when the button is released,
the alarm will stop sounding.
The code is the same as the active buzzer logically, but the way to control the buzzer is different. Passive
buzzer requires PWM of certain frequency to control, so you need to create a PWM channel through
ledcSetup(). Here ledcWriteTone() is designed to generating square wave with variable frequency and duty
cycle fixed to 50%, which is a better choice for controlling the buzzer.
8 ledcSetup(CHN, 0, 10); //setup pwm channel
9 ledcAttachPin(PIN_BUZZER, CHN); //attach the led pin to pwm channel
10 ledcWriteTone(CHN, 2000); //Sound at 2KHz for 0.3 seconds
In the while cycle of main function, when the button is pressed, subfunction alert() will be called and the alertor
will issue a warning sound. The frequency curve of the alarm is based on the sine curve. We need to calculate
the sine value from 0 to 360 degree and multiply a certain value (here is 500) and plus the resonant frequency
of buzzer.
22 void alert() {
23 float sinVal; // Define a variable to save sine value
24 int toneVal; // Define a variable to save sound frequency
25 for (int x = 0; x < 360; x += 10) { // X from 0 degree->360 degree
26 sinVal = sin(x * (PI / 180)); // Calculate the sine of x
27 toneVal = 2000 + sinVal * 500; //Calculate sound frequency according to the sine of x
28 ledcWriteTone(CHN, toneVal);
29 delay(10);
30 }
31 }
If you want to close the buzzer, just set PWM frequency of the buzzer pin to 0.
18 ledcWriteTone(CHN, 0);
Reference
double ledcWriteTone(uint8_t channel, double freq);
This updates the tone frequency value on the given channel.
This function has some bugs in the current version (V1.0.4): when the call interval is less than 20ms, the
resulting PWM will have an exception. We will get in touch with the authorities to solve this problem and
give solutions in the following two projects.
Due to some bugs in the function ledcWriteTone(), this project uses timer to generate software PWM to
control the buzzer. The circuit is exactly the same as the last project.
Sketch
The core of the code of this project is to create a timer to change the GPIO state to generate 50% pulse width
PWM, and change the PWM frequency by changing the timing time of the timer.
Sketch_07.3_Alertor
Download the code to ESP32-WROVER, press the button, then the alarm sounds. And when the button is
released, the alarm will stop sounding.
In the code, first define a timer variable, timer, and then create the timer in setup(), setting the function
onTimer() that the timer will execute.
3 hw_timer_t * timer = NULL;
4
5 // Set 80 divider for prescaler (see ESP32 Technical Reference Manual for more info).
6 timer = timerBegin(0, 80, true);
7 // Attach onTimer function to our timer.
8 timerAttachInterrupt(timer, &onTimer, true);
In the loop(), use the timerAlarmWrite() to set the timer time and use timerAlarmEnable() to start the timer.
Using the flag bit isAlerting, the code to set and start the timer is executed only when the key is pressed.
22 if (! isAlerting) {
23 isAlerting = true;
24 // Set alarm, 1ms, repeat
25 timerAlarmWrite(timer, 1000, true);
26 // Start an alarm
27 timerAlarmEnable(timer);
28 }
After the key is released, stop the timer and make the buzzer's GPIO output low.
31 if (isAlerting) {
32 isAlerting = false;
33 timerAlarmDisable(timer);
34 digitalWrite(BUZZER_PIN, LOW);
35 }
Reference
typedef struct hw_timer_s hw_timer_t;
Timer type, used to define a timer variable.
hw_timer_t * timerBegin(uint8_t timer, uint16_t divider, bool countUp);
Initialize the timer.
parameters
timer: The timer to initialize
divider: The frequency divider coefficient of the timer, the value range is 2-65535. The default clock
frequency is 80MHz.
countUp: true means counter up technique and false means counter down.
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge);
Bind the function to execute when the interrupt is generated for the timer.
void timerAlarmWrite(hw_timer_t *timer, uint64_t interruptAt, bool autoreload);
Set the timer time.
void timerAlarmEnable(hw_timer_t *timer);
void timerAlarmDisable(hw_timer_t *timer);
Start/stop the timer.
Although using software “timer” to generate PWM is to achieve our purpose, but frequent interruption will
reduce the execution efficiency of the main program code, and when the project is too large, this problem
will be more serious. Obviously, software PWM is not the optimal choice.
This project uses the function in esp-idf-sdk code base to make the hardware PWM with adjustable frequency,
and then control the buzzer.
Because the code of this project applies the functions in the esp-idf-sdk code base, which is beyond the
scope of "Arduino", and there are many unfamiliar functions, it will be more complex.
Sketch
Sketch_07.4_Alertor
Download the code to ESP32-WROVER, press the button, then the alarm sounds. And when the button is
released, the alarm will stop sounding.
The project code uses a lot of new functions, which are standard functions from the idf-sdk library. The code
logic of the project is the same, but the method of generating PWM is different.
Functionality Overview
Getting LED to work on a specific channel in either high or low speed mode requires three steps:
1. Configure Timer by specifying the PWM signal’s frequency and duty cycle resolution.
2. Configure Channel by associating it with the timer and GPIO to output the PWM signal.
3. Change PWM Signal that drives the output in order to change LED’s intensity. This can be done under
the full control of software or with hardware's fading functions.
This project uses ESP32's serial communicator to send data to the computer and print it on the serial monitor.
Component List
Related knowledge
Serial communication
Serial communication generally refers to the Universal Asynchronous Receiver/Transmitter (UART), which is
commonly used in electronic circuit communication. It has two communication lines, one is responsible for
sending data (TX line) and the other for receiving data (RX line). The serial communication connections of
two devices is as follows:
Device 1 Device 2
RX RX
TX TX
Before serial communication starts, the baud rate of both sides must be the same. Communication between
devices can work only if the same baud rate is used. The baud rates commonly used is 9600 and 115200.
UART
UART COM
USB
Arduino Software also uploads code to Freenove ESP32 through the serial connection.
Your computer identifies serial devices connecting to it as COMx. We can use the Serial Monitor window of
Arduino Software to communicate with Freenove ESP32, connect Freenove ESP32 to computer through the
USB cable, choose the correct device, and then click the Serial Monitor icon to open the Serial Monitor
window.
Interface of serial monitor window is as follows. If you can't open it, make sure Freenove ESP32 has been
connected to the computer, and choose the right serial port in the menu bar "Tools".
Title bar
Data-
Data- sending
sending button
area
Data-
receiving
area
Configure
bar
Circuit
Sketch
Sketch_08.1_SerialPrinter
Download the code to ESP32-WROVER, open the serial port monitor, set the baud rate to 115200, and press
the reset button. As shown in the following figure:
As shown in the image above, "ESP32 initialization completed! " The previous is the printing message when
the system is started, it uses the baud rate of 120,000, which is incorrect, so the garbled code is displayed.
The user program is then printed at a baud rate of 115200.
Reference
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1,
int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL);
Initializes the serial port. Parameter baud is baud rate, other parameters generally use the default value.
size_t println( arg );
Print to the serial port and wrap. The parameter arg can be a number, a character, a string, an array of
characters, etc.
size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
Print formatted content to the serial port in the same way as print in standard C.
unsigned long millis();
Returns the number of milliseconds since the current system was booted.
From last section, we use serial port on Freenove ESP32 to send data to a computer, now we will use that to
receive data from computer.
Sketch
Sketch_08.2_SerialRW
Download the code to ESP32-WROVER, open the serial monitor, and set the bottom to Newline, 115200. As
shown in the following figure:
Then type characters like 'ABCDEG' into the data sent at the top and click the Send button to print out the
data ESP32 receives.
In loop(), determine whether the serial port has data, if so, read and save the data, and if the newline
character is read, print out all the data that has been read.
Reference
String();
Constructs an instance of the String class.
For more information, please visit
https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/
int available(void);
Get the number of bytes (characters) available for reading from the serial port. This is data that’s already
arrived and stored in the serial receive buffer.
Serial.read();
Reads incoming serial data.
In this project, we will use the ADC function of ESP32 to read the voltage value of potentiometer. And then
output the voltage value through the DAC to control the brightness of LED.
Component List
Breadboard x1
Related 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 on ESP32 is 12 bits, that means the resolution is
2^12=4096, and it represents a range (at 3.3V) will be divided equally to 4096 parts. The rage of analog values
corresponds to ADC values. So the more bits the ADC has, the denser the partition of analog will be and the
greater the precision of the resulting conversion.
Analog Voltage
𝐴𝐷𝐶 𝑉𝑎𝑙𝑢𝑒 = ∗ 4095
3.3
DAC
The reversing of 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. ESP32 has two DAC output pins with 8-bit accuracy, GPIO25 and GPIO26, which can divide VDD
(here is 3.3V) into 2*8=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.
DAC Value
𝐴𝑛𝑎𝑙𝑜𝑔 𝑉𝑜𝑙𝑡𝑎𝑔𝑒 = ∗ 3.3 (V)
255
ADC on ESP32
ESP32 has two digital analog converters with successive approximations of 12-bit accuracy, and a total of 16
pins can be used to measure analog signals. GPIO pin sequence number and analog pin definition are
shown in the following table.
Pin number in Arduino GPIO number ADC channel
A0 GPIO 36 ADC1_CH0
A3 GPIO 39 ADC1_CH3
A4 GPIO 32 ADC1_CH4
A5 GPIO 33 ADC1_CH5
A6 GPIO 34 ADC1_CH6
A7 GPIO 35 ADC1_CH7
A10 GPIO 4 ADC2_CH0
A11 GPIO 0 ADC2_CH1
A12 GPIO 2 ADC2_CH2
A13 GPIO 15 ADC2_CH3
A14 GPIO 13 ADC2_CH4
A15 GPIO 12 ADC2_CH5
A16 GPIO 14 ADC2_CH6
A17 GPIO 27 ADC2_CH7
A18 GPIO 25 ADC2_CH8
A19 GPIO 26 ADC2_CH9
The analog pin number is also defined in ESP32's code base. For example, you can replace GPIO36 with A0
in the code.
Note: ADC2 is disabled when ESP32's WiFi function is enabled.
DAC on ESP32
ESP32 has two 8-bit digital analog converters to be connected to GPIO25 and GPIO26 pins, respectively, and
it is immutable. As shown in the following table.
Simulate pin number GPIO number
DAC1 25
DAC2 26
The DAC pin number is already defined in ESP32's code base; for example, you can replace GPIO25 with DAC1
in the code.
Note: In this ESP32, GPIO26 is used as the camera's IIC-SDA pin, which is connected to 3.3V through a
resistor.Therefore, DAC2 cannot be used.
Component knowledge
Potentiometer
A potentiometer is a three-terminal resistor. 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.
What between potentiometer pin 1 and pin 2 is the resistor body, and pins 3 is connected to brush. When
brush moves from pin 1 to pin 2, the resistance between pin 1 and pin 3 will increase up to body resistance
linearly, and the resistance between pin 2 and pin 3 will decrease down to 0 linearly.
In the circuit. The both sides of resistance body are often connected to the positive and negative electrode of
the power. When you slide the brush pin 3, you can get a certain voltage in the range of the power supply.
Rotary potentiometer
Rotary potentiometer and linear potentiometer have similar function; their only difference is: the resistance
is adjusted by rotating the potentiometer.
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
Sketch_09.1_ADC_DAC
Download the code to ESP32-WROVER, open the serial monitor, and set the baud rate to 115200. As shown
in the following figure,
The serial monitor prints ADC values, DAC values, and the output voltage of the potentiometer. In the code,
we made the voltage output from the DAC pin equal to the voltage input from the ADC pin. Rotate the handle
of the potentiometer and the print will change. When the voltage is greater than 1.6V (voltage needed to turn
on red LED), LED starts emitting light. If you continue to increase the output voltage, the LED will become
more and more brighter. When the voltage is less than 1.6v, the LED will not light up, because it does not
reach the voltage to turn on LED, which indirectly proves the difference between DAC and PWM. (if you have
an oscilloscope, you can check the waveform of the DAC output through it.)
The following is the code:
1 #define PIN_ANALOG_IN 4
2
3 void setup() {
4 Serial.begin(115200);
5 }
6
7 void loop() {
8 int adcVal = analogRead(PIN_ANALOG_IN);
9 int dacVal = map(adcVal, 0, 4095, 0, 255);
10 double voltage = adcVal / 4095.0 * 3.3;
11 dacWrite(DAC1, dacVal);
12 Serial.printf("ADC Val: %d, \t DAC Val: %d, \t Voltage: %.2fV\n", adcVal, dacVal, voltage);
13 delay(200);
14 }
In loop(),the analogRead() function is used to obtain the ADC value, and then the map() function is used to
convert the value into an 8-bit precision DAC value. The function dacWrite() is used to output the value. The
input and output voltage are calculated according to the previous formula, and the information is finally
printed out.
8 int adcVal = analogRead(PIN_ANALOG_IN);
9 int dacVal = map(adcVal, 0, 4095, 0, 255);
10 double voltage = adcVal / 4095.0 * 3.3;
11 dacWrite(DAC1, dacVal);
12 Serial.printf("ADC Val: %d, \t DAC Val: %d, \t Voltage: %.2fV\n", adcVal, dacVal, voltage);
Reference
uint16_t analogRead(uint8_t pin);
Reads the value from the specified analog pin. Return the analog reading on the pin. (0-4095 for 12 bits).
void dacWrite(uint8_t pin, uint8_t value);
This writes the given value to the supplied analog pin.
long map(long value,long fromLow,long fromHigh,long toLow,long toHigh);
Re-maps a number from one range to another. That is, a value of fromLow would get mapped to toLow, a
value of fromHigh to toHigh, values in-between to values in-between, etc.
If you have a voltmeter, in the previous project, you may discover there is a slight error between the voltage
values for ESP32 and the voltmeter values.
ESP32 provides ADC calibration, but the Arduino code base doesn't use it. The functions in the IDF-SDK library
help to obtain more accurate ADC and voltage values.
Related Knowledge
Minimizing Noise
The ESP32 ADC’s sensitive to noise will lead to large discrepancies in ADC readings. To minimize noise, users
may connect a 0.1uF capacitor to the ADC input pad in use. Multisampling may also be used to further
mitigate the effects of noise.
ADC Calibration
The esp_adc_cal/include/esp_adc_cal.h API provides functions to correct for differences in measured voltages
caused by variation of ADC reference voltages (Vref) between chips. The designed ADC reference voltage is
1100mV, however the true reference voltage can range from 1000mV to 1200mV amongst different ESP32s.
Graph illustrating the effect of differing reference voltages on the ADC voltage curve.
Correcting ADC readings using this API involves characterizing one of the ADCs at a given attenuation to
obtain a characteristics curve (ADC-Voltage curve) that takes into account the difference in ADC reference
voltage. The characteristics curve is in the form of y = coeff_a * x + coeff_b and is used to convert ADC
readings to voltages in mV. Calculation of the characteristics curve is based on calibration values, which can
be stored in eFuse or provided by the user.
PIN Numbering
ADC serial pin number of Arduino pin number of IDF- GPIO number
number SDK
A0 ADC1_CHANNEL_0 GPIO 36
A1 ADC1_CHANNEL_1 GPIO 37
A2 ADC1_CHANNEL_2 GPIO 38
A3 ADC1_CHANNEL_3 GPIO 39
ADC1 A4 ADC1_CHANNEL_4 GPIO 32
A5 ADC1_CHANNEL_5 GPIO 33
A6 ADC1_CHANNEL_6 GPIO 34
A7 ADC1_CHANNEL_7 GPIO 35
A10 ADC2_CHANNEL_0 GPIO 4
A11 ADC2_CHANNEL_1 GPIO 0
A12 ADC2_CHANNEL_2 GPIO 2
A13 ADC2_CHANNEL_3 GPIO 15
A14 ADC2_CHANNEL_4 GPIO 13
ADC2 A15 ADC2_CHANNEL_5 GPIO 12
A16 ADC2_CHANNEL_6 GPIO 14
A17 ADC2_CHANNEL_7 GPIO 27
A18 ADC2_CHANNEL_8 GPIO 25
A19 ADC2_CHANNEL_9 GPIO 26
Sketch
Sketch_09.2_ADC
Download the code to ESP32-WROVER, open the serial monitor, and set the baud rate to 115200. As shown
in the following illustration,
By rotating the handle of the potentiometer, the voltage value printed by the serial monitor will change. If
you have a voltmeter, you can verify that this value is more accurate than the value using analogRead(), but
there are some limits to the range.
For most ADC related applications, analogRead() is sufficient. This method can be used in applications where
ADC conversion accuracy is required.
About the project used in the IDF API, here is a detailed description:
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/adc.html
This project reads the value of the touch sensor and prints it out.
Component List
Breadboard x1
Jumper M/M x1
Related knowledge
Touch sensor
ESP32's touch sensor supports up to 10 GPIO channels as capacitive touch pins. Each pin can be used
separately as an independent touch switch or be combined to produce multiple touch points. The following
table is a list of available touch pins on ESP32.
Name of touch sensing signal Functions of pins GPIO number
T0 GPIO4 GPIO4
T1 GPIO0 GPIO0
T2 GPIO2 GPIO2
T3 MTDO GPIO15
T4 MTCK GPIO13
T5 MTDI GPIO12
T6 MTMS GPIO14
T7 GPIO27 GPIO27
T8 32K_XN GPIO33
T9 32K_XP GPIO32
The touch pin number is already defined in ESP32's code base. For example, in the code, you can use T0 to
represent GPIO4.
The electrical signals generated by touch are analog data, which are converted by an internal ADC converter.
You may have noticed that all touch pins have ADC functionality.
The hardware connection method is shown in the following figure.
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
Sketch_10.1_TouchRead
Download the code to ESP32-WROVER, open the serial monitor, and set the baud rate to 115200. As shown
in the following figure,
Touched by hands, the value of the touch sensor will change. The closer the value is to zero, the more
obviously the touch action will be detected. The value detected by the sensor may be different in different
environments or when different people touch it. The code is very simple, just look at Reference.
Reference
uint16_t touchRead(uint8_t pin);
Read touch sensor value. (values close to 0 mean touch detected)
In this project, we will use ESP32's touch sensor to create a touch switch lamp.
Component List
Breadboard x1
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
Sketch_10.2_TouchLamp
Download the code to ESP32-WROVER, open the serial monitor, and set the baud rate to 115200. As shown
in the following figure,
With a touch pad, the state of the LED changes with each touch, and the detection state of the touch sensor
is printed in the serial monitor.
25 }
26
27 void reverseGPIO(int pin) {
28 digitalWrite(pin, ! digitalRead(pin));
29 }
The closer the return value of the function touchRead() is to 0, the more obviously the touch is detected. This
is not a fixed value, so you need to define a threshold that is considered valid (when the value of the sensor
is less than this threshold). Similarly, a threshold value is to be defined in the release state, and a value in
between is considered an invalid disturbance value.
2 #define PRESS_VAL 14 //Set a threshold to judge touch
3 #define RELEASE_VAL 25 //Set a threshold to judge release
In loop(), first determine whether the touch was detected. If yes, print some messages, flip the state of the
LED, and set the flag bit isProcessed to true to avoid repeating the program after the touch was successful.
11 if (touchRead(T0) < PRESS_VAL) {
12 if (! isProcessed) {
13 isProcessed = true;
14 Serial.println("Touch detected! ");
15 reverseGPIO(PIN_LED);
16 }
17 }
It then determines if the touch key is released, and if so, prints some messages and sets the isProcessed to
false to avoid repeating the process after the touch release and to prepare for the next touch probe.
19 if (touchRead(T0) > RELEASE_VAL) {
20 if (isProcessed) {
21 isProcessed = false;
22 Serial.println("Released! ");
23 }
24 }
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 of the PWM used to control the brightness of a LED. Then you can change the
brightness of a LED by adjusting the potentiometer.
Component List
Breadboard x1
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
Sketch_11.1_Softlight
Download the code to ESP32-WROVER, by turning the adjustable resistor to change the input voltage of
GPIO25, ESP32 changes the output voltage of GPIO4 according to this voltage value, thus changing the
brightness of the LED.
The following is the code:
1 #define PIN_ANALOG_IN 4
2 #define PIN_LED 25
3 #define CHAN 0
4 void setup() {
5 ledcSetup(CHAN, 1000, 12);
6 ledcAttachPin(PIN_LED, CHAN);
7 }
8
9 void loop() {
10 int adcVal = analogRead(PIN_ANALOG_IN); //read adc
11 int pwmVal = adcVal; // adcVal re-map to pwmVal
12 ledcWrite(CHAN, pwmVal); // set the pulse width.
13 delay(10);
14 }
In the code, read the ADC value of potentiometer and map it to the duty cycle of PWM to control LED
brightness.
In this project, 3 potentiometers are used to control the RGB LED and in principle it is the same as 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 original project only controlled one LED, but this project required (3)
RGB LEDs.
Component List
Breadboard x1
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
Sketch_11.2_SoftColorfulLight
Download the code to ESP32-WROVER, rotate one of the potentiometers, then the color of RGB LED will
change.
If you have any concerns, please contact us via: support@freenove.com
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.
Component List
Breadboard x1
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
Sketch_11.3_Soft_Rainbow_Light
Download the code to ESP32-WROVER, rotate the handle of the potentiometer, and the color of the lamp
ring will change.
The overall logical structure of the code is the same as the previous project rainbow light, except that the
starting point of the color in this code is controlled by potentiometer.
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
Breadboard x1
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.
Circuit
The circuit of this project is similar to project Soft Light. The only difference is that the input signal is changed
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@freenove.com
Sketch
The circuit used is similar to the project Soft Light. 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.
Sketch_12.1_Nightlamp
Download the code to ESP32-WROVER, if you cover the photoresistor or increase the light shining on it, the
brightness of the LED changes accordingly.
If you have any concerns, please contact us via: support@freenove.com
Reference
constrain(amt,low,high)
#define constrain(amt,low,high) ((amt)<(low)? (low):((amt)>(high)? (high):(amt)))
Constrain the value amt between low and high.
Chapter 13 Thermistor
In this chapter, we will learn about thermistors which are another kind of resistor
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
Breadboard x1
Component knowledge
Thermistor
A 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.
1 1
Rt = R ∗ EXP[ B ∗ ( − ) ]
T2 T1
Where:
Rt is the thermistor resistance under T2 temperature;
R is 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:
1 𝑅𝑡
T2 = 1/( + ln( )/𝐵)
T1 R
Circuit
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@freenove.com
Sketch
Sketch_13.1_Thermometer
Download the code to ESP32-WROVER, 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.
If you have any concerns, please contact us via: support@freenove.com
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.
This project uses the function in esp-idf to get more accurate temperature value. The circuit is exactly the
same as the last project.
Sketch
Sketch_13.2_Thermometer
Download the code to ESP32-WROVER, 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.
If you have any concerns, please contact us via: support@freenove.com
22 adc2_config_channel_atten((adc2_channel_t)channel, atten);
23 }
24
25 //Characterize ADC
26 adc_chars = (esp_adc_cal_characteristics_t*)calloc(1,
27 sizeof(esp_adc_cal_characteristics_t));
28 esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, ADC_WIDTH_BIT_12,
29 DEFAULT_VREF, adc_chars);
30
31 }
32
33 void loop() {
34 uint32_t adc_reading = 0;
35 //Multisampling
36 for (int i = 0; i < NO_OF_SAMPLES; i++) {
37 if (unit == ADC_UNIT_1) {
38 adc_reading += adc1_get_raw((adc1_channel_t)channel);
39 }
40 else {
41 int raw;
42 adc2_get_raw((adc2_channel_t)channel, ADC_WIDTH_BIT_12, &raw);
43 adc_reading += raw;
44 }
45 }
46 adc_reading /= NUM_OF_SAMPLES;
47 //Convert adc_reading to voltage in mV
48 uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars);
49 //printf("Raw: %d\tVoltage: %dmV\n", adc_reading, voltage);
50
51 double vol = voltage / 1000.0f;
52 double Rt = 10 * vol / (3.3 - vol); //calculate resistance value of thermistor
53 double tempK = 1 / (1 / (273.15 + 25) + log(Rt / 10) / 3950.0); //calculate temperature
54 (Kelvin)
55 double tempC = tempK - 273.15; //calculate temperature (Celsius)
56 Serial.printf("ADC value : %d,\tVoltage : %.2fV, \tTemperature : %.2fC\n", adc_reading,
vol, tempC);
57
58 delay(1000);
59 }
The part of the code that captures the ADC is consistent with the previous potentiometer section, and the
part that calculates the temperature is consistent with the previous project.
Chapter 14 Joystick
In the previous chapter, we have learned how to use rotary potentiometer. Now, let's learn a new electronic
module joystick which working on the same principle as rotary potentiometer.
In this project, we will read the output data of a joystick and display it to the Terminal screen.
Component List
Breadboard x1
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.
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
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.
Sketch_14.1_Joystick
Download the code to ESP32-WROVER, open the serial port monitor, the baud rate is 115200, as shown in
the figure below, shift (moving) the joystick or pressing it down will make the data change.
In the code, configure xyzPins[2] to pull-up input mode. In loop(), use analogRead () to read the value of
axes X and Y and use digitalRead () to read the value of axis Z, then display them.
8 int xVal = analogRead(xyzPins[0]);
9 int yVal = analogRead(xyzPins[1]);
10 int zVal = digitalRead(xyzPins[2]);
11 Serial.printf("X,Y,Z: %d,\t%d,\t%d\n", xVal, yVal, zVal);
12 delay(500);
Now let’s learn how to use the 74HC595 IC chip to make a flowing water light using less GPIO.
Component List
Breadboard x1
Related 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 ESP32. At least 3 ports are required
to control the 8 ports of the 74HC595 chip.
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
In this project, we will make a flowing water light with a 74HC595 chip to learn about its functions.
Sketch_15.1_FlowingLight2
Download the code to ESP32-WROVER. You will see that LED bar graph starts with the flowing water pattern
flashing from left to right and then back from right to left.
If you have any concerns, please contact us via: support@freenove.com
13 // Define a one-byte variable to use the 8 bits to represent the state of 8 LEDs of LED bar
14 graph.
15 // This variable is assigned to 0x01, that is binary 00000001, which indicates only one LED
16 light on.
17 byte x = 0x01; // 0b 0000 0001
18 for (int j = 0; j < 8; j++) { // Let led light up from right to left
19 writeTo595(LSBFIRST, x);
20 x <<= 1; // make the variable move one bit to left once, then the bright LED move one step
21 to the left once.
22 delay(50);
23 }
24 delay(1000);
25 x = 0x80; //0b 1000 0000
26 for (int j = 0; j < 8; j++) { // Let led light up from left to right
27 writeTo595(LSBFIRST, x);
28 x >>= 1;
29 delay(50);
30 }
31 delay(1000);
32 }
33 void writeTo595(int order, byte _data ) {
34 // Output low level to latchPin
35 digitalWrite(latchPin, LOW);
36 // Send serial data to 74HC595
37 shiftOut(dataPin, clockPin, order, _data);
38 // Output high level to latchPin, and 74HC595 will update the data to the parallel output
39 port.
40 digitalWrite(latchPin, HIGH);
41 }
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 LED bar graph 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.
17 x=0x01;
In the loop(), use “for” loop to send x to 74HC595 output pin to control the LED. In "for" loop, 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.
18 for (int j = 0; j < 8; j++) { // Let led light up from right to left
19 writeTo595(LSBFIRST, x);
20 x <<= 1;
21 delay(50);
22 }
In second “for” loop, the situation is the same. The difference is that x is shift from 0x80 to the RIGHT in order.
The subfunction writeTo595() is used to write data to 74HC595 and immediately output on the port of
74HC595.
Reference
<< 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
Parameters
dataPin: the pin on which to output each bit. Allowed data types: int.
clockPin: the pin to toggle once the dataPin has been set to the correct value. Allowed data types: int.
bitOrder: which order to shift out the bits; either MSBFIRST or LSBFIRST. (Most Significant Bit First, or, Least
Significant Bit First).
value: the data to shift out. Allowed data types: byte.
We will use 74HC595 to control 7-segment display and make it display hexadecimal character "0-F".
Component List
Breadboard x1
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 a 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.
For detailed code values, please refer to the following table (common anode).
CHAR DP G F E D C B A Hex ASCII
0 1 1 0 0 0 0 0 0 0xc0 1100 0000
1 1 1 1 1 1 0 0 1 0xf9 1111 1001
2 1 0 1 0 0 1 0 0 0xa4 1010 0100
3 1 0 1 1 0 0 0 0 0xb0 1011 0000
4 1 0 0 1 1 0 0 1 0x99 1001 1001
5 1 0 0 1 0 0 1 0 0x92 1001 0010
6 1 0 0 0 0 0 1 0 0x82 1000 0010
7 1 1 1 1 1 0 0 0 0xf8 1111 1000
8 1 0 0 0 0 0 0 0 0x80 1000 0000
9 1 0 0 1 0 0 0 0 0x90 1001 0000
A 1 0 0 0 1 0 0 0 0x88 1000 1000
B 1 0 0 0 0 0 1 1 0x83 1000 0011
C 1 1 0 0 0 1 1 0 0xc6 1100 0110
D 1 0 1 0 0 0 0 1 0xa1 1010 0001
E 1 0 0 0 0 1 1 0 0x86 1000 0110
F 1 0 0 0 1 1 1 0 0x8e 1000 1110
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
In this section, the 74HC595 is used in the same way as in the previous section, but with different values
transferred. We can learn how to master the digital display by sending the coded value of "0" - "F".
Sketch_16.1_7_Segment_Display
Verify and upload the code, and you'll see a 1-bit, 7-segment display displaying 0-f in a loop.
Component List
Breadboard x1
Component knowledge
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 fast that it is
imperceptible 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.
Circuit
Schematic diagram
Hardware connection:
Sketch
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.
Sketch_16.2_4_Dight_7-Segment_Display
Compile and upload code to ESP32-WROVER, then the digital tube displays as shown.
The usage of the writeData function is the same as in the previous two sections, so it won't be covered again
here.
41 void writeData(int value) {
42 // Make latchPin output low level
43 digitalWrite(latchPin, LOW);
44 // Send serial data to 74HC595
45 shiftOut(dataPin, clockPin, LSBFIRST, value);
46 // Make latchPin output high level, then 74HC595 will update data to parallel output
47 digitalWrite(latchPin, HIGH);
48 }
In the loop function, because there are four digital tubes, a “for loop” is used to display the values of each
one in turn. For example, when i =0, turn ON the first digital tube to display the first value, then turn ON the
second digital tube to display the second value, until all four digital tubes display their own values. Because
the displaying time from the first number to the fourth number is so short, it may display many times in one
second, but our eyes can't keep up with the speed of the digital tube, so we look as if the digital tube is
displaying different Numbers at the same time.
20 void loop() {
21 for (int i = 0; i < 4; i++) {
22 // Select a single 7-segment display
23 electDigitalDisplay(i);
24 // Send data to 74HC595
25 writeData(num[i]);
26 delay(5);
27 // Clear the display content
28 writeData(0xff);
29 }
30 }
If you want to display the decimal point, make the highest bit of each array become 0, which can be
implemented easily by num[i]&0x7f.
45 shiftOut(dataPin,clockPin, LSBFIRST, value & 0x7f);
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
Breadboard x1
Component knowledge
LED Matrix
A 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
Here is how a common anode LED matrix works. First, choose 16 ports on ESP32 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
Then, to save the number of GPIO, we use a 74HC595. When the first column is turned ON, set the lights that
need to be displayed in the first column to "1", otherwise to "0", as shown in the above example, where the
value of the first column is 0x1c. This value is sent to 74HC595 to control the display of the first column of the
LED matrix. Following the above idea, turn OFF the display of the first column, then turn ON the second
column, and then send the value of the second column to 74HC595 ...... Until each column is displayed, the
LED matrix is displayed again from the first column.
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
Hardware connection:
Sketch
The following code will make LED matrix display a smiling face, and then display scrolling character "0-F".
Download the code to ESP32-WROVER, and the LED matrix display a smiling face, and then display characters
"0 to F" scrolling in a loop on the LED matrix.
Sketch_16.3_LED_Matrix
The following is the program code:
1 int latchPin = 2; // Pin connected to ST_CP of 74HC595(Pin12)
2 int clockPin = 4; // Pin connected to SH_CP of 74HC595(Pin11)
3 int dataPin = 15; // Pin connected to DS of 74HC595(Pin14)
4
5 // Define the pattern data for a smiling face
6 const int smilingFace[] = { //"^ⅴ^"
7 0x1C, 0x22, 0x51, 0x45, 0x45, 0x51, 0x22, 0x14
8 };
9 // Define the data of numbers and letters, and save them in flash area
10 const int data[] PROGMEM = {
11 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // " "
12 0x00, 0x00, 0x21, 0x7F, 0x01, 0x00, 0x00, 0x00, // "1"
13 0x00, 0x00, 0x23, 0x45, 0x49, 0x31, 0x00, 0x00, // "2"
14 0x00, 0x00, 0x22, 0x49, 0x49, 0x36, 0x00, 0x00, // "3"
15 0x00, 0x00, 0x0E, 0x32, 0x7F, 0x02, 0x00, 0x00, // "4"
16 0x00, 0x00, 0x79, 0x49, 0x49, 0x46, 0x00, 0x00, // "5"
17 0x00, 0x00, 0x3E, 0x49, 0x49, 0x26, 0x00, 0x00, // "6"
18 0x00, 0x00, 0x60, 0x47, 0x48, 0x70, 0x00, 0x00, // "7"
19 0x00, 0x00, 0x36, 0x49, 0x49, 0x36, 0x00, 0x00, // "8"
20 0x00, 0x00, 0x32, 0x49, 0x49, 0x3E, 0x00, 0x00, // "9"
21 0x00, 0x00, 0x3E, 0x41, 0x41, 0x3E, 0x00, 0x00, // "0"
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"
26 0x00, 0x00, 0x7F, 0x49, 0x49, 0x41, 0x00, 0x00, // "E"
27 0x00, 0x00, 0x7F, 0x48, 0x48, 0x40, 0x00, 0x00 // "F"
28 };
29
30 void setup() {
31 // set pins to output
32 pinMode(latchPin, OUTPUT);
33 pinMode(clockPin, OUTPUT);
34 pinMode(dataPin, OUTPUT);
35 }
36
37 void loop() {
38 // Define a one-byte variable (8 bits) which is used to represent the selected state of 8
39 column.
40 int cols;
41 // Display the static smiling pattern
42 for (int j = 0; j < 500; j++ ) { // repeat 500 times
43 cols = 0x01;
44 for (int i = 0; i < 8; i++) { // display 8 column data by scanning
45 matrixRowsVal(smilingFace[i]);// display the data in this column
46 matrixColsVal(~cols); // select this column
47 delay(1); // display them for a period of time
48 matrixRowsVal(0x00); // clear the data of this column
49 cols <<= 1; // shift "cols" 1 bit left to select the next column
50 }
51 }
52 // Display the dynamic patterns of numbers and letters
53 for (int i = 0; i < 128; i++) {
54 for (int k = 0; k < 10; k++) { // repeat image of each frame 10 times.
55 cols = 0x01; // Assign binary 00000001. Means the first column is selected.
56 for (int j = i; j < 8 + i; j++) { // display image of each frame
57 matrixRowsVal(pgm_read_word_near(data + j));// display the data in this column
58 matrixColsVal(~cols); // select this column
59 delay(1); // display them for a period of time
60 matrixRowsVal(0x00); // close the data of this column
61 cols <<= 1; // shift "cols" 1 bit left to select the next column
62 }
63 }
64 }
65 }
66
67 void matrixRowsVal(int value) {
68 // make latchPin output low level
69 digitalWrite(latchPin, LOW);
70 // Send serial data to 74HC595
71 shiftOut(dataPin, clockPin, LSBFIRST, value);
72 // make latchPin output high level, then 74HC595 will update the data to parallel output
73 digitalWrite(latchPin, HIGH);
74 }
76
77 void matrixColsVal(int value) {
78 // make latchPin output low level
79 digitalWrite(latchPin, LOW);
80 // Send serial data to 74HC595
81 shiftOut(dataPin, clockPin, MSBFIRST, value);
82 // make latchPin output high level, then 74HC595 will update the data to parallel output
83 digitalWrite(latchPin, HIGH);
84 }
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.
40 int cols;
41 // Display the static smiling pattern
42 for (int j = 0; j < 500; j++ ) { // repeat 500 times
43 cols = 0x01; // Assign 0x01(binary 00000001) to the variable, which represents the first
44 column is selected.
45 for (int i = 0; i < 8; i++) { // display 8 column data by scanning
46 matrixRowsVal(smilingFace[i]); // display the data in this column
47 matrixColsVal(~cols); // select this column
48 delay(1); // display them for a period of time
49 cols <<= 1; // shift "cols" 1 bit left to select the next column
50 }
51 }
The second “for” loop is used to display scrolling characters "0 to F", for a total of 17* 8 = 144 columns.
Displaying the 0-8 column, then the 1-9 column, then the 2-10 column...... and so on…128-136 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.
52 // Display the dynamic patterns of numbers and letters
53 for (int i = 0; i < 128; i++) {
54 for (int k = 0; k < 10; k++) { // repeat image of each frame 10 times.
55 cols = 0x01; // Assign binary 00000001. Means the first column is selected.
56 for (int j = i; j < 8 + i; j++) { // display image of each frame
57 matrixRowsVal(pgm_read_word_near(data + j));// display the data in this column
58 matrixColsVal(~cols); // select this column
59 delay(1); // display them for a period of time
60 matrixRowsVal(0x00); // close the data of this column
61 cols <<= 1; // shift "cols" 1 bit left to select the next column
62 }
63 }
64 }
The amount of pins of ESP32 is limited, so you need to find ways to save pins. If you use ESP32’s GPIO to
control the lattice without using 74HC595, you need 16 pins for the use of LED matrix. In this example, we
use two 74HC595 to drive the LED matrix, requiring only three pins, so that we could save the rest of 13
pins.
In this project, we will use a push button switch indirectly to control the motor via a relay.
Component List
Breadboard x1
Component knowledge
Relay
A relay is a safe switch which can use low power circuit to control high power circuit. It consists of
electromagnet and contacts. The electromagnet is controlled by low power circuit and contacts are used in
high power circuit. When the electromagnet is energized, it will attract contacts.
The following is a schematic diagram of a common relay and the feature and circuit symbol of a 5V relay used
in this project:
Diagram Feature: Symbol
Pin 5 and pin 6 are connected to each other inside. When the coil pins 3 and 4 get connected to 5V power
supply, pin 1 will be disconnected to pin 5&6 and pin 2 will be connected to pin 5&6. So pin 1 is called close
end, pin 2 is called 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 an energy storage device that converts electrical energy into magnetic energy. Generally, it
consists of winding coil, with a certain amount of inductance. Inductors hinder the change of current passing
through it. When the current passing through it increases, it will attempt to hinder the increasing trend of
current; and when the current passing through it decreases, it will attempt to hinder the decreasing trend of
current. So the current passing through inductor is not transient.
The reference circuit for relay is as follows. The coil of relays can be equivalent to that of inductors, when the
transistor disconnects power supply of the relay, the current in the coil of the relay can't stop immediately,
causing an impact on power supply. So a parallel diode will get connected to both ends of relay coil pin in
reversing direction, then the current will pass through diode, avoiding the impact on power supply.
Motor
A motor is a device that converts electrical energy into mechanical energy. Motor consists of two parts: stator
and rotor. When motor works, the stationary part is stator, and the rotating part is rotor. Stator is usually the
outer case of motor, and it has terminals to connect to the power. Rotor is usually the shaft of motor, and can
drive other mechanical devices to run. Diagram below is a small DC motor with two pins.
When a motor gets connected to the power supply, it will rotate in one direction. Reverse the polarity of
power supply, then the motor rotates in opposite direction.
+ - - +
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Note: the motor circuit uses A large current, about 0.2-0.3A without load.We recommend that you
use a 9V battery to power the extension board.
Sketch
Download the code to ESP32-WROVER. When the 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.
+ - - +
The following is the program code:
1 int relayPin = 13; // the number of the relay pin
2 int buttonPin = 15; // the number of the push button pin
3
4 int buttonState = HIGH; // Record button state, and initial the state to high level
5 int relayState = LOW; // Record relay state, and initial the state to low level
6 int lastButtonState = HIGH; // Record the button state of last detection
7 long lastChangeTime = 0; // Record the time point for button state change
8
9 void setup() {
10 pinMode(buttonPin, INPUT_PULLUP); // Set push button pin into input mode
11 pinMode(relayPin, OUTPUT); // Set relay pin into output mode
12 digitalWrite(relayPin, relayState); // Set the initial state of relay into "off"
13 }
14 void loop() {
15 int nowButtonState = digitalRead(buttonPin);// Read current state of button pin
16 // If button pin state has changed, record the time point
17 if (nowButtonState ! = lastButtonState) {
18 lastChangeTime = millis();
19 }
20 // If button state changes, and stays stable for a while, then it should have skipped the
21 bounce area
22 if (millis() - lastChangeTime > 10) {
23 if (buttonState ! = nowButtonState) { // Confirm button state has changed
24 buttonState = nowButtonState;
25 if (buttonState == LOW) { // Low level indicates the button is pressed
26 relayState = ! relayState; // Reverse relay state
27 digitalWrite(relayPin, relayState); // Update relay state
28 }
29 }
30 }
31 lastButtonState = nowButtonState; // Save the state of last button
32 }
In Chapter 2, the pressing and releasing of the button will result in mechanical vibrating. If we don't solve this
problem, some unexpected consequences may happen to the procedure. Click here to return to Chapter 2
Button & LED
To eliminate the vibrating, we record the electrical level of the button with nowButtonState, and the time point
for the last change of pin level with lastChangeTime If the state of the button changes, it will record the time
point of the change.
15 int nowButtonState = digitalRead(buttonPin);// Read current state of button pin
16 // If button pin state has changed, record the time point
17 if (nowButtonState ! = lastButtonState) {
18 lastChangeTime = millis();
19 }
If the state of the pin changes and keeps stable for a period of time, it can be considered as a valid key state
change, update the key state variable buttonState, and determine whether the key is pressed or released
according to the current state.
15 // If button state changes, and stays stable for a while, then it should have skipped the
16 bounce area
17 if (millis() - lastChangeTime > 10) {
18 if (buttonState ! = nowButtonState) { // Confirm button state has changed
19 buttonState = nowButtonState;
20 if (buttonState == LOW) { // Low level indicates the button is pressed
21 relayState = ! relayState; // Reverse relay state
22 digitalWrite(relayPin, relayState); // Update relay state
23 }
24 }
25 }
26 lastButtonState = nowButtonState; // Save the state of last button
Component List
Breadboard x1
Component knowledge
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).
When using L293D to drive 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 steering of the motor.
GND
GND
In practical use the motor is usually connected to channel 1 and 2 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.
Circuit
Use caution when connecting this circuit, because the DC motor is a high-power component, do not use the
power provided by the ESP32 to power the motor directly, which may cause permanent damage to your
ESP32! The logic circuit can be powered by the ESP32 power or an external power supply, which should share
a common ground with ESP32.
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Note: the motor circuit uses A large current, about 0.2-0.3A without load.We recommend that you
use a 9V battery to power the extension board.
Sketch
Sketch_17.2_Control_Motor_by_L293D
Download code to ESP32-WROVER, rotate the potentiometer in one direction and the motor speeds up
slowly in one direction. And then rotate the potentiometer in the other direction and the motor will slow down
to stop. And then rotate it in an inverse direction to accelerate the motor.
2048
number 2048 as the midpoint. If the value of ADC is less than 2048, make the motor rotate in one direction.
If the value of ADC is greater than 2048, make the motor rotate in the other direction. Subtract 2048 from the
ADC value and take the absolute value and use this result as the speed of the motor.
20 int potenVal = analogRead(A0);// Convert the voltage of rotary potentiometer into digital
21 rotationSpeed = potenVal - 2048;
22 if (potenVal > 2048)
23 rotationDir = true;
24 else
25 rotationDir = false;
26 // Calculate the motor speed
27 rotationSpeed = abs(potenVal - 2048);
28 //Control the steering and speed of the motor
29 driveMotor(rotationDir, constrain(rotationSpeed,0,2048));
30 }
Set the accuracy of the PWM to 11 bits and range from 0 to 2047 to control the rotation speed of the motor.
15 ledcSetup(channel,1000,11); //Set PWM to 11 bits, range is 0-2047
Function driveMotor is used to control the rotation direction and speed of the motor. The dir represents
direction while spd refers to speed.
34 void driveMotor(boolean dir, int spd) {
35 // Control motor rotation direction
36 if (rotationDir) {
37 digitalWrite(in1Pin, HIGH);
38 digitalWrite(in2Pin, LOW);
39 }
40 else {
41 digitalWrite(in1Pin, LOW);
42 digitalWrite(in2Pin, HIGH);
43 }
44 // Control motor rotation speed
45 ledcWrite(channel, spd);
46 }
Chapter 18 Servo
Previously, we learned how to control the speed and rotational direction of a motor. In this chapter, we will
learn about servos which are a rotary actuator type motor that can be controlled to rotate to specific angles.
Component List
Breadboard x1
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 of
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:
High level time Servo angle
0.5ms 0 degree
1ms 45 degree
1.5ms 0 degree
2ms 45 degree
2.5ms 180 degree
When you change the servo signal value, the servo will rotate to the designated angle.
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@freenove.com
Sketch
Use the ESP32Servo library to control the servo motor and let the servo motor rotate back and forth.
Sketch_18.1_Servo_Sweep
Compile and upload the code to ESP32-WROVER, 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.
Component List
Breadboard x1
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@freenove.com
Sketch
Sketch_18.2_Servo_Sweep
Compile and upload the code to ESP32-WROVER, twist the potentiometer back and forth, and the servo
motor rotates accordingly.
Component List
Breadboard x1
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 outside case or housing of the stepper motor is the stator and inside the stator is the rotor. There are 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).
In the course above, the stepper motor rotates a certain angle once, which is called a step. By controlling the
number of rotation steps, you can control the stepper motor rotation angle. By controlling the time between
two steps, you can control the stepper motor rotation speed. When rotating clockwise, the order of coil
powered on is: ABCDA…… . And the rotor will rotate in accordance with the order, step by step
down, called four steps four pats. If the coils is powered on in the reverse order, DCBAD… , the
rotor will rotate in anti-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. The sequence of powering the coils looks like this: A ABB BCC
CDDDAA……, the rotor will rotate in accordance to this sequence at 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.
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. Additionally, the breadboard power supply needs to share Ground
with ESP32.
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
This code uses the four-step, four-part mode to drive the stepper motor in the clockwise and anticlockwise
directions.
Sketch_19.1_Drive_Stepper_Motor
Compile and upload the code to the ESP32-WROVER, the stepper motor will rotate 360° clockwise and stop
for 1s, and then rotate 360° anticlockwise and stop for 1s. And it will repeat this action in an endless loop.
The moveSteps function can control the direction of the stepper motor, the number of rotation steps, and the
speed of rotation. According to the previous knowledge, the stepper motor needs 32*64 steps for one
revolution. The speed of rotation is determined by the parameter ms. The larger the ms is, the slower the
rotation speed is. There is a range for the speed of the motor, which is determined by the motor itself and
according to our test, the value of ms is limited to 3-20.
20 //Suggestion: the motor turns precisely when the ms range is between 3 and 20
21 void moveSteps(bool dir,int steps, byte ms) {
22 for (unsigned long i = 0; i < steps; i++) {
23 moveOneStep(dir); // Rotate a step
24 delay(constrain(ms,3,20)); // Control the speed
25 }
26 }
The function moveTurns() is a further package of moveSteps(), which is used to control the stepper motor to
rotate a specified number of turns. The parameter "turns" represents the number of turns that need to be
rotated.
44 void moveAround(bool dir, int turns, byte ms){
45 for(int i=0;i<turns;i++)
46 moveSteps(dir,32*64,ms);
47 }
The function moveAround () is a further package of moveSteps (), which is used to control the stepper motor
to rotate by a specified angle, and the parameter "angle" represents the angle to be rotated.
48 void moveAngle(bool dir, int angle, byte ms){
49 moveSteps(dir,(angle*32*64/360),ms);
50 }
In the loop function, call the moveSteps function to loop the stepper motor: rotate clockwise one turn and
stop for 1s, then rotate counterclockwise one turn and stop for 1s.
11 void loop(){
12 // Rotate a full turn
13 moveSteps(true, 32 * 64, 3);
14 delay(1000);
15 // Rotate a full turn towards another direction
16 moveSteps(false, 32 * 64, 3);
17 delay(1000);
18 }
Chapter 20 LCD1602
In this chapter, we will learn about the LCD1602 Display Screen
Component List
Breadboard x1
Component knowledge
I2C communication
I2C (Inter-Integrated Circuit) is a two-wire serial communication mode, which can be used for the connection
of micro controllers and their peripheral equipment. Devices using I2C communication must be connected to
the serial data (SDA) line, and serial clock (SCL) line (called I2C bus). Each device has a unique address and
can be used as a transmitter or receiver to communicate with devices connected to the bus.
LCD1602 communication'
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 the 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 ESP32 bus on your I2C device address through command "i2cdetect -y 1".
Below is the PCF8574 pin schematic diagram and the block pin diagram:
PCF8574 chip pin diagram: PCF8574 module pin diagram
PCF8574 module pin and LCD1602 pin are corresponding to each other and connected with each other:
So we only need 4 pins to control the 16 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.
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
Sketch_20.1_Display_the_string_on_LCD1602
Compile and upload the code to ESP32-WROVER and the LCD1602 displays characters.
If you cannot see anything on the display or the display is not clear, try rotating the white knob on back of
LCD1602 slowly, which adjusts the contrast, until the screen can display clearly.
In this project, we use ultrasonic ranging module to measure distance, and print out the data in the terminal.
Component List
Breadboard x1
Component Knowledge
The ultrasonic ranging module uses the principle that ultrasonic waves will be sent back when encounter
obstacles. We can measure the distance by counting the time interval between sending and receiving of the
ultrasonic waves, and the time difference 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, about v=340m/s, we can
calculate the distance between the ultrasonic ranging module and the obstacle: s=vt/2.
2S=V·t.
The HC-SR04 ultrasonic ranging module integrates 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 HC SR04 ultrasonic ranging module are shown below:
Pin description:
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.
Circuit
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
Sketch_21.1_Ultrasonic_Ranging
Download the code to ESP32-WROVER, open the serial port monitor, set the baud rate to 115200 and you
can use it to measure the distance between the ultrasonic module and the object. As shown in the following
figure:
25 digitalWrite(trigPin, HIGH);
26 delayMicroseconds(10);
27 digitalWrite(trigPin, LOW);
28 // Wait HC-SR04 returning to the high level and measure out this waiting time
29 pingTime = pulseIn(echoPin, HIGH, timeOut);
30 // calculate the distance according to the time
31 distance = (float)pingTime * soundVelocity / 2 / 10000;
32 return distance; // return the distance value
33 }
First, define the pins and the maximum measurement distance.
1 #define trigPin 13 // define trigPin
2 #define echoPin 14 // define echoPin.
3 #define MAX_DISTANCE 700 //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.
5 float timeOut = MAX_DISTANCE * 60;
Subfunction getSonar () function is used to start the ultrasonic module to begin measuring, 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.
21 float getSonar() {
22 unsigned long pingTime;
23 float distance;
24 // make trigPin output high level lasting for 10μs to triger HC_SR04?
25 digitalWrite(trigPin, HIGH);
26 delayMicroseconds(10);
27 digitalWrite(trigPin, LOW);
28 // Wait HC-SR04 returning to the high level and measure out this waitting time
29 pingTime = pulseIn(echoPin, HIGH, timeOut);
30 // calculate the distance according to the time
31 distance = (float)pingTime * soundVelocity / 2 / 10000;
32 return distance; // return the distance value
33 }
Lastly, in loop() function, get the measurement distance and display it continually.
14 void loop() {
15 delay(100); // Wait 100ms between pings (about 20 pings/sec).
16 Serial.printf("Distance: ");
17 Serial.print(getSonar()); // Send ping, get distance in cm and print result
18 Serial.println("cm");
19 }
Component List and Circuit are the same as the previous section.
Sketch
Sketch_21.2_Ultrasonic_Ranging
Download the code to ESP32-WROVER, open the serial port monitor, set the baud rate to 115200. Use the
ultrasonic module to measure distance. As shown in the following figure:
In this project, we will attempt to get every key code on the matrix keypad to work.
Component List
Breadboard x1
Component knowledge
Similar to the integration of a 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 usage is similar to the LED matrix, 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.
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
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 printed out via serial port.
Sketch_22.1_Get_Input_Characters
Download the code to ESP32-WROVER, open the serial port monitor, set the baud rate to 115200, press the
keyboard, the value of the pressed keys will be printed out via the serial port. As shown in the following
figure:
First, add header file, define 4*4 matrix keyboard key value and the matrix keyboard pin.
1 #include <Keypad.h>
2 // define the symbols on the buttons of the keypad
3 char keys[4][4] = {
4 {'1', '2', '3', 'A'},
5 {'4', '5', '6', 'B'},
6 {'7', '8', '9', 'C'},
7 {'*', '0', '#', 'D'}
8 };
9 byte rowPins[4] = {14, 27, 26, 25}; // connect to the row pinouts of the keypad
10 byte colPins[4] = {13, 21, 22, 23}; // connect to the column pinouts of the keypad
Second, define a matrix keyboard object and associate the keys and pins with it.
13 Keypad myKeypad = Keypad(makeKeymap(keys), rowPins, colPins, 4, 4);
Finally, get the key value and print it out via the serial port.
20 void loop() {
21 // Get the character input
22 char keyPressed = myKeypad.getKey();
23 // If there is a character input, sent it to the serial port
24 if (keyPressed) {
25 Serial.println(keyPressed);
26 }
27 }
Reference
class Keypad You need to add the library each time you use the 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 with a default time of 10ms.
void setHoldTime(uint);
Set the duration for the key to keep 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 the 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: http://playground.arduino.cc/Code/Keypad
In this project, we use keypad as a keyboard to control the action of the servo motor.
Component List
Breadboard x1
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
Sketch_22.2_Keypad_Door
Verify and upload the code to the ESP32-WROVER and press the keypad to input password with 4 characters.
If the input is correct, the servo will move to a certain degree, then return to the original position. If the input
is wrong, an input error alarm will be generated.
Third, if the button has been pressed for four times, ESP32 begins to judge if the password is correct.
47 if (keyInNum == 4) {
48 bool isRight = true; // Save password is correct or not
49 for (int i = 0; i < 4; i++) { // Judge each character of the password is correct or
50 not
51 if (keyIn[i] ! = passWord[i])
52 isRight = false; // Mark wrong password if there is any wrong character.
53 }
54
If the password is correct, control the servo motor to open the lock and wait for 2 seconds before closing the
lock. If it is not correct, the buzzer makes a long sound and prints the error message through the serial port.
55 if (isRight) { // If the input password is right
56 myservo.write(90); // Open the switch
57 delay(2000); // Delay a period of time
58 myservo.write(0); // Close the switch
59 Serial.println("passWord right! ");
60 }
61 else { // If the input password is wrong
62 digitalWrite(buzzerPin, HIGH);// Make a wrong password prompt tone
63 delay(1000);
64 digitalWrite(buzzerPin, LOW);
65 Serial.println("passWord error! ");
66 }
Finally, remember to empty the keyInNum every time.
67 keyInNum = 0; // Reset the number of the input characters to 0
For More information about Keypad, please visit: http://playground.arduino.cc/Code/Keypad .
First, we need to understand how infrared remote control works, then get the command sent from infrared
remote control.
Component List
Breadboard x1
Component knowledge
Infrared Remote
An infrared(IR) remote control is a device with a certain number of buttons. Pressing down different buttons
will make the infrared emission tube, which is located in the front of the remote control, send infrared ray with
different command. Infrared remote control technology is widely used in electronic products such as TV, air
conditioning, etc. Thus making it possible for you to switch TV programs and adjust the temperature of the
air conditioning when away from them. The remote control we use is shown below:
Pull out
Infrared receiver
An infrared(IR) receiver is a component which can receive the infrared light, so we can use it to detect the
signal emitted by the infrared remote control. DATA pin here outputs the received infrared signal.
When you use the infrared remote control, the infrared remote control sends a key value to the receiving
circuit according to the pressed keys. We can program the ESP32-WROVER to do things like lighting, when a
key value is received.
The following is the key value that the receiving circuit will receive when each key of the infrared remote
control is pressed.
ICON KEY Value ICON KEY Value
FFA25D FFB04F
FFE21D FF30CF
FF22DD FF18E7
FF02FD FF7A85
FFC23D FF10EF
FFE01F FF38C7
FFA857 FF5AA5
FF906F FF42BD
FF6897 FF4AB5
FF9867 FF52AD
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
This sketch uses the infrared receiving tube to receive the value sent form the infrared remote control, and
print it out via the serial port.
Sketch_23.1_Infrared_Remote_Control
Download the code to ESP32-WROVER, open the serial port monitor, set the baud rate to 115200, press the
IR remote control, the pressed keys value will be printed out through the serial port. As shown in the
following figure: (Note that when the remote control button is pressed for a long time, the infrared receiving
circuit receives a continuous high level, that is, it receives a hexadecimal "F")
Normal
Abnormal
First, include header file. Each time you use the infrared library, you need to include the header file at the
beginning of the program.
1 #include <Arduino.h>
2 #include <IRremoteESP8266.h>
3 #include <IRrecv.h>
4 #include <IRutils.h>
Second, define an infrared receive pin and associates it with the receive class. Apply a decode_results to
decode the received infrared value.
6 const uint16_t RecvPin = 15; // Infrared receiving pin
7 IRrecv irrecv(RecvPin); // Create a class object used to receive class
8 decode_results results; // Create a decoding results class object
Third, enable infrared reception function, if you do not use this function, you won't receive the value from the
infrared remote control.
12 irrecv.enableIRIn(); // Start the receiver
Finally, put the received data into the results class and print out the data through the serial port. Note that
you must use resume() to release the infrared receive function every time when you receive data, otherwise
you can only use the infrared receive function once and cannot receive the data next time.
20 void loop() {
21 if (irrecv.decode(&results)) { // Waiting for decoding
22 serialPrintUint64(results.value, HEX); // Print out the decoded results
23 Serial.println("");
24 irrecv.resume(); // Release the IRremote. Receive the next value
25 }
26 delay(1000);
27 }
Reference
class IRrecv You need to add the library each time you use the Infrared Reception.
IRrecv irrecv(Pin):Create a class object used to receive class, and associated with Pin.
enableIRIn():Before using the infrared decoding function, enable the infrared receiving function. Otherwise the
correct data will not be received.
decode(&results): Determine whether the infrared has received data, and if so, return true and store the data
in the decode_results class. If no data is received, false is returned.
resume():Release the IRremote. Or, the infrared reception and decoding function cannot be used again.
For more information about Infrared Remote Control, please visit:
https://github.com/crankyoldgit/IRremoteESP8266/tree/master/src
In this project, we will control the brightness of LED lights through an infrared remote control.
Component List
Breadboard x1
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
The sketch controls the brightness of the LED by determining the key value of the infrared received.
Sketch_23.2_Control_LED_through_Infrared_Remote
Compile and upload the code to the ESP32-WROVER. When pressing "0", "1", "2", "3" of the infrared remote
control, the buzzer will sound once, and the brightness of the LED light will change correspondingly.
rendering
47 }
48 }
Each time when the command is received, the function above will be called in the loop() function.
22 void loop() {
23 if (irrecv.decode(&results)) { // Waiting for decoding
24 handleControl(results.value); // Handle the commands from remote control
25 irrecv.resume(); // Receive the next value
26 }
27 }
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 ESP32 to read temperature and humidity data of the DHT11
Module.
Component List
Breadboard x1
Component knowledge
The temperature & humidity sensor DHT11 is a compound temperature & humidity sensor, and the output
digital signal has been calibrated by its manufacturer.
DHT11 uses customized single-line communication protocol, so we can use the library to read data more
conveniently.
After being powered up, it will initialize in 1s. 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) is 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.
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
Sketch_24.1_Temperature_and_Humidity_Sensor
Compile and upload the code to the ESP32-WROVER, turn on the serial monitor, and set the baud rate to
115200. Print out data of temperature and humidity sensor via the serial port.
In this project code, we use a third party library, DHTesp, and we need to define the objects for it first;
Otherwise we could not use its functionality.
1 #include "DHTesp.h"
3 DHTesp dht; //Define the DHT object
Initialize the connection pin of DHT and select the type of temperature and humidity sensor as DHT11. If the
temperature and humidity sensor is DHT12, we can also change it to DHT12.
7 dht.setup(dhtPin, DHTesp::DHT11);//Initialize the dht pin and dht object
Due to the use of the single-line protocol, data may be lost in the transmission process. So each time when
getting the data of the temperature and humidity sensor, we need to call the getStatus function to determine
whether the data is normal. If not, use goto to go back to line 12 and re-execute the program.
12 flag:TempAndHumidity newValues = dht.getTempAndHumidity();//Get the Temperature and
13 humidity
14 if (dht.getStatus() ! = 0) { //Judge if the correct value is read
15 goto flag; //If there is an error, go back to the flag and re-read
16 the data
17 }
Get the temperature and humidity data and store it in a TempAndHumidity class called newValues.
12 TempAndHumidity newValues = dht.getTempAndHumidity(); //Get the Temperature and humidity
Reference
class DHTesp
Make sure that the library and header files are added before using the object every time.
setup(Pin, DHTesp::DHTxx): Select the type of DHTxx and associate Pin with the DHTesp class.
Parameter 1: the pin to be associated.
Parameter 2: select the type of sensor, DHT11 or DHT12.
getTempAndHumidity():Obtain temperature and humidity data. The received data must be stored in the
‘TempAndHumidity’ class.
getStatus():To judge whether the obtained data format is normal, the return value of 0 means the data is normal,
and the return value of non-0 means the data is abnormal or the data fails to be obtained.
Component List
Breadboard x1
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
This code uses the DHTesp and LiquidCrystal_I2C libraries, so make sure the relevant library files are added
before writing the program.
Sketch_24.2_Temperature_and_Humidity_Sensor
Download the code to ESP32-WROVER. The first line of LCD1602 shows the temperature value, and the
second line shows the humidity value. Try to “pinch” the thermistor (without touching the leads) with your
index finger and thumb for a brief time to observe the change in the LCD display value.
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
Breadboard x1
Component knowledge
Description:
Working voltage: 5v-20v(DC) Static current: 65uA.
Automatic Trigger. When a living body enters into the active area of sensor, the module will output high
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.
According to the position of jumper cap, you can choose non-repeatable trigger mode or repeatable
mode.
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 during the period of high level output. After this, it starts to time and output low level after delaying T
time.
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
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.
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 sensitivity. When a body moves close to or moves away from the sensor’s
dome in a vertical direction, the sensor cannot detect well (please take note of this deficiency). 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.
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
In this project, we will use the infrared motion sensor to trigger a 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
button is pressed, it will output low level. When the sensor output high level, the LED turns ON, or it will turn
OFF.
Sketch_25.1_Infrared_Motion_Sensor
Verify and upload the code, and put the sensor on a stationary table and wait for about a minute. Then try to
move away from or move closer to the infrared motion sensor and observe whether the LED turns ON or OFF
automatically.
You can rotate the potentiometer on the sensor to adjust the detection effect, or use different modes by
changing the jumper.
Apart from that, you can also use this sensor to control some other modules to implement different functions
by reediting the code, such as the induction lamp, induction door.
In this project, we will read acceleration and gyroscope data of the MPU6050 sensor
Component List
Breadboard x1
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.
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.
Circuit
Note that the power supply voltage for MPU6050 module is 5V in the circuit.
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
Sketch_26.1_Acceleration_Detection
Download the code to ESP32-WROVER, open the serial port monitor, set the baud rate to 115200 and you
can use it to measure the distance between the ultrasonic module and the object. As shown in the following
figure:
48 }
Finally, the original data of the gyroscope is updated and acquired every second, and the original data, the
processed acceleration and angular velocity data are printed out through the serial port.
20 void loop() {
21 if(millis() - timer > 1000){ //each second print the data
22 mpu6050.update(); //update the MPU6050
23 getMotion6(); //gain the values of Acceleration and Gyroscope value
24 Serial.print("\na/g:\t");
25 Serial.print(ax); Serial.print("\t");
26 Serial.print(ay); Serial.print("\t");cc
27 Serial.print(az); Serial.print("\t");
28 Serial.print(gx); Serial.print("\t\t");
29 Serial.print(gy); Serial.print("\t\t");
30 Serial.println(gz);
31 Serial.print("a/g:\t");
32 Serial.print((float)ax / 16384); Serial.print("g\t");
33 Serial.print((float)ay / 16384); Serial.print("g\t");
34 Serial.print((float)az / 16384); Serial.print("g\t");
35 Serial.print((float)gx / 131); Serial.print("d/s \t");
36 Serial.print((float)gy / 131); Serial.print("d/s \t");
37 Serial.print((float)gz / 131); Serial.print("d/s \n");
38 timer = millis();
39 }
40 }
Reference
Class MPU6050
This is a class library used to operate MPU6050, which can directly read and set MPU6050. Here are some
member functions:
MPU6050 mpu6050(Wire): Associate MPU6050 with IIC.
begin(): Initialize the MPU6050.
calcGyroOffsets(true): If the parameter is true, get the gyro offset and automatically correct the offset.
If the parameter is false, the offset value is not obtained and the offset is not corrected.
getRawAccX():Gain the values of X axis acceleration raw data.
getRawAccY():Gain the values of Y axis acceleration raw data.
getRawAccZ():Gain the values of Z axis acceleration raw data.
getRawGyroX():Gain the values of X axis Gyroscope raw data.
getRawGyroY():Gain the values of Y axis Gyroscope raw data.
getRawGyroZ():gain the values of Z axis Gyroscope raw data.
getTemp():Gain the values of MPU6050’temperature data.
update():Update the MPU6050. If the updated function is not used, the IIC will not be able to retrieve the
new data.
Chapter 27 Bluetooth
This chapter mainly introduces how to make simple data transmission through Bluetooth of ESP32-WROVER
and mobile phones.
Project 27.1 is classic Bluetooth and Project 27.2 is low power Bluetooth.If you are an iPhone user, please start
with Project 27.2.
Component List
In this tutorial we need to use a Bluetooth APP called Serial Bluetooth Terminal to assist in the experiment. If
you've not installed it yet, please do so by clicking: https://www.appsapk.com/serial-bluetooth-terminal/ The
following is its logo.
Component knowledge
ESP32's integrated Bluetooth function Bluetooth is a short-distance communication system, which can be
divided into two types, namely Bluetooth Low Energy(BLE) and Classic Bluetooth. There are two modes for
simple data transmission: master mode and slave mode.
Master mode
In this mode, works are done in the master device and it can connect with a slave device. And we can search
and select slave devices nearby to connect with. When a device initiates connection request in master mode,
it requires information of the other Bluetooth devices including their address and pairing passkey. After
finishing pairing, it can connect with them directly.
Slave mode
The Bluetooth module in slave mode can only accept connection request from a host computer, but cannot
initiate a connection request. After connecting with a host device, it can send data to or receive from the host
device.
Bluetooth devices can make data interaction with each other, as one is in master mode and the other in slave
mode. When they are making data interaction, the Bluetooth device in master mode searches and selects
devices nearby to connect to. When establishing connection, they can exchange data. When mobile phones
exchange data with ESP32, they are usually in master mode and ESP32 in slave mode.
Circuit
Sketch
Sketch_27.1_SerialToSerialBT
Compile and upload the code to the ESP32-WROVER, open the serial monitor, and set the baud rate to
115200. When you see the serial printing out the character string as below, it indicates that the Bluetooth of
ESP32 is ready and waiting to connect with the mobile phone.
Make sure that the Bluetooth of your phone has been turned on and Serial Bluetooth Terminal has been
installed.
Click "Search" to search Bluetooth devices nearby and select "ESP32 test" to connect to.
Turn on software APP, click the left of the terminal. Select "Devices"
Select ESP32test in classic Bluetooth mode, and a successful connecting prompt will appear as shown on the
right illustration.
And now data can be transferred between your mobile phone and computer via ESP32-WROVER.
Send 'Hello!'' from your phone, when the computer receives it, reply "Hi" to your phone.
Reference
Class BluetoothSerial
This is a class library used to operate BluetoothSerial, which can directly read and set BluetoothSerial.
Here are some member functions:
begin(localName,isMaster): Initialization function of the Bluetooth
name: name of Bluetooth module; Data type: String
isMaster: bool type, whether to set Bluetooth as Master. By default, it is false.
available(): acquire digits sent from the buffer, if not, return 0.
read(): read data from Bluetooth, data type of return value is int.
readString(): read data from Bluetooth, data type of return value is String.
write(val): send an int data val to Bluetooth.
write(str): send an Srtring data str to Bluetooth.
write(buf, len): Sends the first len data in the buf Array to Bluetooth.
setPin(const char *pin): set a four-digit Bluetooth pairing code. By default, it is 1234
connet(remoteName): connect a Bluetooth named remoteName, data type: String
connect(remoteAddress[]): connect the physical address of Bluetooth, data type: uint8-t.
disconnect():disconnect all Bluetooth devices.
end(): disconnect all Bluetooth devices and turn off the Bluetooth, release all occupied space
Component List
Circuit
Sketch
Sketch_27.2_BLE
Serial Bluetooth
Compile and upload code to ESP32, the operation is similar to the last section.
First, make sure you've turned on the mobile phone Bluetooth, and then open the software.
Click "Search" to search Bluetooth devices nearby and select "ESP32 test" to connect to.
Turn on software APP, click the left of the terminal. Select "Devices"
Select BLUETOOTHLE, click SCAN to scan Low Energy Bluetooth devices nearby.
Select"ESP32-Bluetooth"
Lightblue
If you can't install Serial Bluetooth on your phone, try LightBlue.If you do not have this software installed on
your phone, you can refer to this link:
https://apps.apple.com/us/app/lightblue/id557428110#?platform=iphone.
1 2
In the Scan page, swipe down to refresh the name of Bluetooth that the phone searches for. Click
ESP32_Bluetooth.
Receive
Click “Receive”. Select the appropriate Data format in the box to the right of Data Format. For example, HEX
for hexadecimal, utf-string for character, Binary for Binary, etc. Then click SUBSCRIBE.
Back to the serial monitor on your computer. You can type anything in the left border of Send, and then click
Send.
And then you can see the mobile Bluetooth has received the message.
Similarly, you can select “Send” on your phone. Set Data format, and then enter anything in the sending box
and click Write to send.
Send
And the computer will receive the message from the mobile Bluetooth.
And now data can be transferred between your mobile phone and computer via ESP32-WROVER.
The following is the program code:
1 #include <BLEDevice.h>
2 #include <BLEServer.h>
3 #include <BLEUtils.h>
4 #include <BLE2902.h>
5 #include <String.h>
6
7 BLECharacteristic *pCharacteristic;
8 bool deviceConnected = false;
9 uint8_t txValue = 0;
10 long lastMsg = 0;
11 String rxload="Test\n";
12
13 #define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
14 #define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
15 #define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
16
17 class MyServerCallbacks: public BLEServerCallbacks {
18 void onConnect(BLEServer* pServer) {
19 deviceConnected = true;
20 };
21 void onDisconnect(BLEServer* pServer) {
22 deviceConnected = false;
23 }
24 };
25
26 class MyCallbacks: public BLECharacteristicCallbacks {
27 void onWrite(BLECharacteristic *pCharacteristic) {
28 std::string rxValue = pCharacteristic->getValue();
29 if (rxValue.length() > 0) {
30 rxload="";
31 for (int i = 0; i < rxValue.length(); i++){
32 rxload +=(char)rxValue[i];
33 }
34 }
35 }
36 };
37
38 void setupBLE(String BLEName){
39 const char *ble_name=BLEName.c_str();
40 BLEDevice::init(ble_name);
41 BLEServer *pServer = BLEDevice::createServer();
42 pServer->setCallbacks(new MyServerCallbacks());
Component List
Breadboard x1
Circuit
Schematic diagram
Hardware connection. If you need any support, please contact us via: support@freenove.com
Sketch
Sketch_27.3_Bluetooth_Control_LED
Compile and upload code to ESP32. The operation of the APP is the same as 27.1, you only need to change
the sending content to "LED on" and "LED off" to operate LEDs on the ESP32-WROVER.
Data sent from mobile APP:
Send:“led_on”
Send:“led_off”
Attention: If the sending content isn't "led-on' or "led-off", then the state of LED will not change. If the LED is
on, when receiving irrelevant content, it keeps on; Correspondingly, if the LED is off, when receiving irrelevant
content, it keeps off.
When receive data, read the Bluetooth data and store it into buffer array.
15 while(SerialBT.available()){
16 buffer[count] = SerialBT.read();
17 count++;
18 }
Compare the content in buffer array with "led_on" and "led_off" to see whether they are the same. If yes,
execute the corresponding operation.
22 if(strncmp(buffer,"led_on",6)==0){
23 digitalWrite(LED,HIGH);
24 }
25 if(strncmp(buffer,"led_off",7)==0){
26 digitalWrite(LED,LOW);
27 }
After comparing the content of array, to ensure successful transmission next time, please empty the array
and set the count to zero.
28 count=0;
29 memset(buffer,0,20);
Reference
strncmp() functions are often used for string comparisons, which are accurate and stable.
int strncmp(const char *str1, const char *str2, size_t n)
str1: the first string to be compared
str2: the second string to be compared
n: the biggest string to be compared
Return value: if stir1>str2, then return value>0.
If return value is 0, then the contents of str1 and str2 are the same.
If str1< str2, then return value<0.
Function memset is mainly used to clean and initialize the memory of array
void *memset(void *s, int c, unsigned long n)
Function memset() is to set the content of a certain internal storage as specified value.
*s: the initial address of the content to clear out.
c:to be replaced as specified value
n: the number of byte to be replaced
Use the Bluetooth audio receiving function of ESP32 to transcode the audio data from mobile phones and
play the music through DAC output pin.
The accuracy of ESP32's DAC is only eight bits, so the music would be distorted to some extent using this
tutorial.
Component List
Component knowledge
signal conversion
Bluetooth devices receive music data from mobile devices, which cannot play through earphones and
speakers directly. To output DAC signal, Bluetooth devices need to decode these data with I2S decoding
chip. The power of these audio signals is so small that it can only drives low-power music listening devices,
such as earphone. Amplify the power of these DAC signals with power amplifier chip, so that it can drive
relatively bigger-power music playing devices, such as speakers.
In this chapter, we use ESP32-WROVER's built-in audio decoding feature to convert the received Bluetooth
data directly into an audio signal and output it via ESP32-WROVER's DAC pin.
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
Before compiling the code, follow these steps for the setting:
1,“Tools”“Partition Scheme””Huge APP (3MB No OTA/1MB SPIFFS)”;
2,“Tools”“Flash Mode””DOUT”;
3,“Tools”“Flash Frequency””80MHz”;
You can refer to the following picture for configuration
Sketch_28.1_Bluetooth_Music_by_DAC
Note: ESP32 board support packages are different and will cause compilation failures. We provide
two codes, if you can't use it, please change another code.
Compile and upload the code to the ESP32-WROVER and open the serial monitor. ESP32 takes a few
seconds to initialize the program. When you see the prompt as shown in the figure below, it means that the
Bluetooth function of ESP32 is ready and waiting for the connection of other Bluetooth devices.
Please use your mobile phone to search and connect a Bluetooth device named "ESP32". After the
connection is successful, you can use ESP32 to play the audio files in your mobile phone.
21 if(event==0) {
22 /* initialize A2DP sink */
23 esp_a2d_register_callback(&bt_app_a2d_cb);
24 esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb);
25 esp_a2d_sink_init();
26 /* initialize AVRCP controller */
27 esp_avrc_ct_init();
28 esp_avrc_ct_register_callback(bt_app_rc_ct_cb);
29 /* set discoverable and connectable mode, wait to be connected */
30 esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
31 }
32 }
33
34 void setup() {
35 Serial.begin(115200);
36 SerialBT.begin("ESP32");
37 Serial.println("Init seccess! ");
38
39 esp_err_t err = nvs_flash_init();
40 if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
41 ESP_ERROR_CHECK(nvs_flash_erase());
42 err = nvs_flash_init();
43 }
44 i2s_config_t i2s_config;
45 i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN);
46 i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_24BIT;
47 i2s_config.sample_rate = 44100;
48 i2s_config.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT; //2-channels
49 i2s_config.communication_format = I2S_COMM_FORMAT_I2S_MSB;
50 i2s_config.intr_alloc_flags = 0;
51 i2s_config.dma_buf_count = 6;
52 i2s_config.dma_buf_len = 60;
53 i2s_config.tx_desc_auto_clear = true;
54 i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
55 i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
56 i2s_set_pin(I2S_NUM_0, NULL);
57
58 esp_bluedroid_init();
59 esp_bluedroid_enable();
60 bt_app_task_start_up();
61 bt_app_work_dispatch(bt_av_hdl_stack_evt, 0, NULL, 0, NULL);
62 Serial.println("Please use your Bluetooth device to connect the ESP32! ");
63 }
64
65 void loop(){
66 ;
67 }
Bluetooth thread task: Set Bluetooth to slave mode; initialize Bluetooth command resolution function; set
Bluetooth to be visible to other devices and in waiting for connection mode.
20 static void bt_av_hdl_stack_evt(uint16_t event, void *p_param){
21 if(event==0) {
22 /* initialize A2DP sink */
23 esp_a2d_register_callback(&bt_app_a2d_cb);
24 esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb);
25 esp_a2d_sink_init();
26 /* initialize AVRCP controller */
27 esp_avrc_ct_init();
28 esp_avrc_ct_register_callback(bt_app_rc_ct_cb);
29 /* set discoverable and connectable mode, wait to be connected */
30 esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
31 }
32 }
In this project, we will use PCM5102A chip to transcode audio data into stereo and output it.
Component List
Jumper F/M x4
Jumper F/F x2
Component knowledge
The front and reverse view of Audio Converter & Amplifier module.
front view reverse view schematic diagram
Speaker Headphone
interface interface
I2S input
interface
External audio
input interface
Power
interface
Speaker interface: Connect left channel speaker and right channel speaker. Group L: L+ & L-; Group R:
R+& R-. The two interfaces of the speaker can be connected to the interfaces of group L or group R. But
when one interface is connected to group L, the other cannot be connected to group R. Doing so may cause
the module to malfunction.
Headphone interface: the interface to connect the headphones.
I2S input interface: connect to the device with I2S. Used to transcode audio data into DAC audio signals.
External audio input interface: connect to external audio equipment. Used to amplify externally input
audio signals.
Power interface: connect to external power supply. External power supply selection range: 3.3V-5.0V.
Circuit
Schematic diagram
Hardware connection. If you need any support, please feel free to contact us via: support@freenove.com
Sketch
Before compiling and upload the program, please check whether your configuration conforms with the
following illustration.
Sketch_29.1_Bluetooth_Music_by_PCM5102A
Note: ESP32 board support packages are different and will cause compilation failures. We provide two
codes, if you can't use it, please change another code.
Compile and upload the code to the ESP32-WROVER and open the serial monitor. ESP32 takes a few
seconds to initialize the program. When you see the prompt as shown in the figure below, it means that the
Bluetooth function of ESP32 is ready and waiting for the connection of other Bluetooth devices.
Please use your mobile phone to search and connect a Bluetooth device named "ESP32". After the
connection is successful, you can use ESP32 to play the audio files in your mobile phone.
34 i2s_config.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT;
35 i2s_config.communication_format = I2S_COMM_FORMAT_I2S_MSB;
36 i2s_config.intr_alloc_flags = 0;
37 i2s_config.dma_buf_count = 6;
38 i2s_config.dma_buf_len = 60;
39 i2s_config.tx_desc_auto_clear = true;
40 i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
41 i2s_pin_config_t pin_config;
42 pin_config.bck_io_num = CONFIG_I2S_BCK_PIN;
43 pin_config.ws_io_num = CONFIG_I2S_LRCK_PIN;
44 pin_config.data_out_num = CONFIG_I2S_DATA_PIN;
45 pin_config.data_in_num = -1;
46 i2s_set_pin(I2S_NUM_0, &pin_config);
47
48 bt_app_task_start_up();
49
50 /* initialize A2DP sink */
51 esp_a2d_register_callback(&bt_app_a2d_cb);
52 esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb);
53 esp_a2d_sink_init();
54 /* initialize AVRCP controller */
55 esp_avrc_ct_init();
56 esp_avrc_ct_register_callback(bt_app_rc_ct_cb);
57 /* set discoverable and connectable mode, wait to be connected */
58 esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
59 Serial.println("Please use your Bluetooth device to connect the ESP32! ");
60 }
61
62 void loop(){
63 ;
64 }
Define an I2S configuration class and initialize it; define an I2S pin configuration class and associate I2S signals
with these pins.
30 i2s_config_t i2s_config;
31 i2s_config.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX);
32 i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT;
33 i2s_config.sample_rate = 44100;
34 i2s_config.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT;
35 i2s_config.communication_format = I2S_COMM_FORMAT_I2S_MSB;
36 i2s_config.intr_alloc_flags = 0;
37 i2s_config.dma_buf_count = 6;
38 i2s_config.dma_buf_len = 60;
39 i2s_config.tx_desc_auto_clear = true;
40 i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);//
41 i2s_pin_config_t pin_config;
42 pin_config.bck_io_num = CONFIG_I2S_BCK_PIN;
43 pin_config.ws_io_num = CONFIG_I2S_LRCK_PIN;
44 pin_config.data_out_num = CONFIG_I2S_DATA_PIN;
45 pin_config.data_in_num = -1;
46 i2s_set_pin(I2S_NUM_0, &pin_config);
In this chapter, the procedure is very similar to the previous section. The difference only lies in the I2S
configuration. The audio quality of the DAC output from the PCM5102 chip after decoding is significantly
higher than that of the ESP32's own 8-bit precision DAC.
Component List
Component knowledge
Station mode
When ESP32 selects Station mode, it acts as a WiFi client. It can connect to the router network and
communicate with other devices on the router via WiFi connection. As shown below, the PC is connected to
the router, and if ESP32 wants to communicate with the PC, it needs to be connected to the router.
Circuit
Sketch
Sketch_30.1_Station_mode
Because the names and passwords of routers in various places are different, before the Sketch runs, users
need to enter the correct router’s name and password in the box as shown in the illustration above.
After making sure the router name and password are entered correctly, compile and upload codes to ESP32-
WROVER, open serial monitor and set baud rate to 115200. And then it will display as follows:
When ESP32-WROVER successfully connects to “ssid_Router”, serial monitor will print out the IP address
assigned to ESP32-WROVER by the router.
The following is the program code:
1 #include <WiFi.h>
2
3 const char *ssid_Router = "********"; //Enter the router name
4 const char *password_Router = "********"; //Enter the router password
5
6 void setup(){
7 Serial.begin(115200);
8 delay(2000);
9 Serial.println("Setup start");
10 WiFi.begin(ssid_Router, password_Router);
11 Serial.println(String("Connecting to ")+ssid_Router);
12 while (WiFi.status() != WL_CONNECTED){
13 delay(500);
14 Serial.print(".");
15 }
16 Serial.println("\nConnected, IP address: ");
17 Serial.println(WiFi.localIP());
18 Serial.println("Setup End");
19 }
20
21 void loop() {
22 }
Component knowledge
AP mode
When ESP32 selects AP mode, it creates a hotspot network that is separate from the Internet and waits for
other WiFi devices to connect. As shown in the figure below, ESP32 is used as a hotspot. If a mobile phone or
PC wants to communicate with ESP32, it must be connected to the hotspot of ESP32. Only after a connection
is established with ESP32 can they communicate.
Circuit
Sketch
Before the Sketch runs, you can make any changes to the AP name and password for ESP32 in the box as
shown in the illustration above. Of course, you can leave it alone by default.
Compile and upload codes to ESP32-WROVER, open the serial monitor and set the baud rate to 115200. And
then it will display as follows.
When observing the print information of the serial monitor, turn on the WiFi scanning function of your phone,
and you can see the ssid_AP on ESP32, which is called "WiFi_Name" in this Sketch. You can enter the password
"12345678" to connect it or change its AP name and password by modifying Sketch.
Sketch_30.2_AP_mode
The following is the program code:
1 #include <WiFi.h>
2
3 const char *ssid_AP = "WiFi_Name"; //Enter the router name
4 const char *password_AP = "12345678"; //Enter the router password
5
6 IPAddress local_IP(192,168,1,100);//Set the IP address of ESP32 itself
7 IPAddress gateway(192,168,1,10); //Set the gateway of ESP32 itself
8 IPAddress subnet(255,255,255,0); //Set the subnet mask for ESP32 itself
9
10 void setup(){
11 Serial.begin(115200);
12 delay(2000);
13 Serial.println("Setting soft-AP configuration ... ");
14 WiFi.disconnect();
15 WiFi.mode(WIFI_AP);
16 Serial.println(WiFi.softAPConfig(local_IP, gateway, subnet) ? "Ready" : "Failed!");
17 Serial.println("Setting soft-AP ... ");
18 boolean result = WiFi.softAP(ssid_AP, password_AP);
19 if(result){
20 Serial.println("Ready");
21 Serial.println(String("Soft-AP IP address = ") + WiFi.softAPIP().toString());
22 Serial.println(String("MAC address = ") + WiFi.softAPmacAddress().c_str());
23 }else{
24 Serial.println("Failed!");
25 }
26 Serial.println("Setup End");
27 }
28
29 void loop() {
30 }
Include WiFi Library header file of ESP32.
1 #include <WiFi.h>
Enter correct AP name and password.
3 const char *ssid_AP = "WiFi_Name"; //Enter the router name
4 const char *password_AP = "12345678"; //Enter the router password
Set ESP32 in AP mode.
15 WiFi.mode(WIFI_AP);
Configure IP address, gateway and subnet mask for ESP32.
16 WiFi.softAPConfig(local_IP, gateway, subnet)
Turn on an AP in ESP32, whose name is set by ssid_AP and password is set by password_AP.
18 WiFi.softAP(ssid_AP, password_AP);
Check whether the AP is turned on successfully. If yes, print out IP and MAC address of AP established by
ESP32. If no, print out the failure prompt.
19 if(result){
20 Serial.println("Ready");
21 Serial.println(String("Soft-AP IP address = ") + WiFi.softAPIP().toString());
22 Serial.println(String("MAC address = ") + WiFi.softAPmacAddress().c_str());
23 }else{
24 Serial.println("Failed!");
25 }
26 Serial.println("Setup End");
Reference
Class AP
Every time when using WiFi, you need to include header file "WiFi.h.".
softAP(ssid, password, channel, ssid_hidden, max_connection):
ssid: WiFi hotspot name
password: WiFi hotspot password
channel: Number of WiFi connection channels, range 1-13. The default is 1.
ssid_hidden: Whether to hide WiFi name from scanning by other devices. The default is not hide.
max_connection: Maximum number of WiFi connected devices. The range is 1-4. The default is 4.
softAPConfig(local_ip, gateway, subnet): set static local IP address.
local_ip: station fixed IP address.
Gateway: gateway IP address
subnet:subnet mask
softAP(): obtian IP address in AP mode
softAPdisconnect (): disconnect AP mode.
Component List
Component knowledge
AP+Station mode
In addition to AP mode and station mode, ESP32 can also use AP mode and station mode at the same time.
This mode contains the functions of the previous two modes. Turn on ESP32's station mode, connect it to the
router network, and it can communicate with the Internet via the router. At the same time, turn on its AP
mode to create a hotspot network. Other WiFi devices can choose to connect to the router network or the
hotspot network to communicate with ESP32.
Circuit
Sketch
Sketch_30.3_AP_Station_mode
It is analogous to project 30.1 and project 30.2. Before running the Sketch, you need to modify ssid_Router,
password_Router, ssid_AP and password_AP shown in the box of the illustration above.
After making sure that Sketch is modified correctly, compile and upload codes to ESP32-WROVER, open serial
monitor and set baud rate to 115200. And then it will display as follows:
When observing the print information of the serial monitor, turn on the WiFi scanning function of your phone,
and you can see the ssid_AP on ESP32.
12 WiFi.mode(WIFI_AP);
13 Serial.println("Setting soft-AP ... ");
14 boolean result = WiFi.softAP(ssid_AP, password_AP);
15 if(result){
16 Serial.println("Ready");
17 Serial.println(String("Soft-AP IP address = ") + WiFi.softAPIP().toString());
18 Serial.println(String("MAC address = ") + WiFi.softAPmacAddress().c_str());
19 }else{
20 Serial.println("Failed!");
21 }
22
23 Serial.println("\nSetting Station configuration ... ");
24 WiFi.begin(ssid_Router, password_Router);
25 Serial.println(String("Connecting to ")+ ssid_Router);
26 while (WiFi.status() != WL_CONNECTED){
27 delay(500);
28 Serial.print(".");
29 }
30 Serial.println("\nConnected, IP address: ");
31 Serial.println(WiFi.localIP());
32 Serial.println("Setup End");
33 }
34
35 void loop() {
36 }
Chapter 31 TCP/IP
In this chapter, we will introduce how ESP32 implements network communications based on TCP/IP protocol.
There are two roles in TCP/IP communication, namely Server and Client, which will be implemented
respectively with two projects in this chapter.
In this section, ESP32 is used as Client to connect Server on the same LAN and communicate with it.
Component List
Component knowledge
TCP connection
Before transmitting data, TCP needs to establish a logical connection between the sending end and the
receiving end. It provides reliable and error-free data transmission between the two computers. In the TCP
connection, the client and the server must be clarified. The client sends a connection request to the server,
and each time such a request is proposed, a "three-times handshake" is required.
Three-times handshake: In the TCP protocol, during the preparation phase of sending data, the client and the
server interact three times to ensure the reliability of the connection, which is called "three-times handshake".
The first handshake, the client sends a connection request to the server and waits for the server to confirm.
The second handshake, the server sends a response back to the client informing that it has received the
connection request.
The third handshake, the client sends a confirmation message to the server again to confirm the connection.
TCP is a connection-oriented, low-level transmission control protocol. After TCP establishes a connection, the
client and server can send and receive messages to each other, and the connection will always exist as long
as the client or server does not initiate disconnection. Each time one party sends a message, the other party
will reply with an ack signal.
Install Processing
In this tutorial, we use Processing to build a simple TCP/IP communication platform.
If you've not installed Processing, you can download it by clicking https://processing.org/download/. You can
choose an appropriate version to download according to your PC system.
Unzip the downloaded file to your computer. Click "processing.exe" as the figure below to run this software.
Stop
Run
The new pop-up interface is as follows. If ESP32 is used as client, select TCP SERVER mode for sketchWiFi.
Server mode
Receiving
Local IP address
box
Local port
number
Clear receive
Send box
Listening
Clear send
Send button
When sketchWiFi selects TCP SERVER mode, ESP32 Sketch needs to be changed according to sketchWiFi's
displaying of LOCAL IP or LOCAL PORT.
Client mode
Remote IP
address
Remote port
number
When sketchWiFi selects TCP CLIENT mode, the LOCAL IP and LOCAL PORT of sketchWiFi need to be
changed according to the IP address and port number printed by the serial monitor.
Circuit
Sketch
Before running the Sketch, please open “sketchWiFi.pde.” first, and click “Run”.
The newly pop up window will use the computer’s IP address by default and open a data monitor port.
Next, open Sketch_31.1_WiFiClient.ino. Before running it, please change the following information based on
"LOCAL IP" and "LOCAL PORT" in the figure above.
REMOTE_IP needs to be filled in according to the interface of sketchWiFi.pde. Taking this tutorial as an
example, its REMOTE_IP is “192.168.1.133”. Generally, by default, the ports do not need to change its value.
Click LISTENING, turn on TCP SERVER's data listening function and wait for ESP32 to connect.
Click it
Compile and upload code to ESP32-WROVER, open the serial monitor and set the baud rate to 115200. ESP32
connects router, obtains IP address and sends access request to server IP address on the same LAN till the
connection is successful. When connect successfully, ESP32 can send messages to server.
ESP32 connects with TCP SERVER, and TCP SERVER receives messages from ESP32, as shown in the figure
below.
Sketch_31.1_As_Client
The following is the program code:
1 #include <WiFi.h>
2
3 const char *ssid_Router = "********"; //Enter the router name
4 const char *password_Router = "********"; //Enter the router password
5 #define REMOTE_IP "********" //input the remote server which is you want to connect
#define REMOTE_PORT 8888 //input the remote port which is the remote provide
6 WiFiClient client;
7
8 void setup() {
9 Serial.begin(115200);
10 delay(10);
11
12 WiFi.begin(ssid_Router, password_Router);
13 Serial.print("\nWaiting for WiFi... ");
14 while (WiFi.status() != WL_CONNECTED) {
15 Serial.print(".");
16 delay(500);
17 }
18 Serial.println("");
19 Serial.println("WiFi connected");
20 Serial.println("IP address: ");
21 Serial.println(WiFi.localIP());
22 delay(500);
23
24 Serial.print("Connecting to ");
25 Serial.println(REMOTE_IP);
26
27 while (!client.connect(REMOTE_IP, REMOTE_PORT)) {
28 Serial.println("Connection failed.");
29 Serial.println("Waiting a moment before retrying...");
30 }
31 Serial.println("Connected");
32 client.print("Hello\n");
33 client.print("This is my IP.\n");
34 }
35
36 void loop() {
37 if (client.available() > 0) {
38 delay(20);
39 //read back one line from the server
40 String line = client.readString();
41 Serial.println(REMOTE_IP + String(":") + line);
42 }
43 if (Serial.available() > 0) {
44 delay(20);
45 String line = Serial.readString();
46 client.print(line);
47 }
48 if (client.connected () == 0) {
49 client.stop();
50 WiFi.disconnect();
51 }
52 }
Add WiFi function header file.
1 #include <WiFi.h>
Enter the actual router name, password, remote server IP address, and port number.
3 const char *ssid_Router = "********"; //Enter the router name
4 const char *password_Router = "********"; //Enter the router password
5 #define REMOTE_IP "********" //input the remote server which is you want to connect
6 #define REMOTE_PORT 8888 //input the remote port which is the remote provide
Apply for the method class of WiFiClient.
7 WiFiClient client;
Connect specified WiFi until it is successful. If the name and password of WiFi are correct but it still fails to
connect, please push the reset key.
13 WiFi.begin(ssid_Router, password_Router);
14 Serial.print("\nWaiting for WiFi... ");
15 while (WiFi.status() ! = WL_CONNECTED) {
16 Serial.print(".");
17 delay(500);
18 }
Send connection request to remote server until connect successfully. When connect successfully, print out the
connecting prompt on the serial monitor and send messages to remote server.
28 while (!client.connect(REMOTE_IP, REMOTE_PORT)) {//Connect to Server
29 Serial.println("Connection failed.");
30 Serial.println("Waiting a moment before retrying...");
31 }
32 Serial.println("Connected");
33 client.print("Hello\n");
When ESP32 receive messages from servers, it will print them out via serial port; Users can also send messages
to servers from serial port.
37 if (client.available() > 0) {
38 delay(20);
39 //read back one line from the server
40 String line = client.readString();
41 Serial.println(REMOTE_IP + String(":") + line);
42 }
43 if (Serial.available() > 0) {
44 delay(20);
45 String line = Serial.readString();
46 client.print(line);
47 }
If the server is disconnected, turn off WiFi of ESP32.
48 if (client.connected () == false) {
49 client.stop();
50 WiFi.disconnect();
51 }
Reference
Class Client
Every time when using Client, you need to include header file "WiFi.h."
connect(ip, port, timeout)/connect(*host, port, timeout): establish a TCP connection.
ip, *host:ip address of target server
port: port number of target server
timeout: connection timeout
connected(): judge whether client is connecting. If return value is 1, then connect successfully; If return
value is 0, then fail to connect.
stop(): stop tcp connection
print(): send data to server connecting to client
available(): return to the number of bytes readable in receive buffer, if no, return to 0 or -1.
read(): read one byte of data in receive buffer
readString(): read string in receive buffer
In this section, ESP32 is used as a server to wait for the connection and communication of client on the same
LAN.
Component List
Circuit
Sketch
Before running Sketch, please modify the contents of the box below first.
Sketch_31.2_As_Server
Compile and upload code to ESP32-WROVER board, open the serial monitor and set the baud rate to
115200. Turn on server mode for ESP32, waiting for the connection of other devices on the same LAN. Once
a device connects to server successfully, they can send messages to each other.
If the ESP32 fails to connect to router, press the reset button as shown below and wait for ESP32 to run again.
Serial Monitor
IP address and
serial port
Processing:
Open the “Freenove_Ultimate_Starter_Kit_for_ESP32\Sketches\Sketches\Sketch_31.2_WiFiServer\
sketchWiFi\sketchWiFi.pde”.
Based on the messages printed by the serial monitor, enter correct IP address and serial port in Processing to
establish connection and make communication.
42 }
43 }
44 client.stop(); // stop the client connecting.
45 Serial.println("Client Disconnected.");
46 }
47 }
Apply for method class of WiFiServer.
6 WiFiServer server(port); //Apply for a Server object whose port number is 80
Connect specified WiFi until it is successful. If the name and password of WiFi are correct but it still fails to
connect, please push the reset key.
13 WiFi.disconnect();
14 WiFi.begin(ssid_Router, password_Router);
15 delay(1000);
16 while (WiFi.status() != WL_CONNECTED) {
17 delay(500);
18 Serial.print(".");
19 }
20 Serial.println("");
21 Serial.println("WiFi connected.");
Print out the IP address and port number of ESP32.
22 Serial.print("IP address: ");
23 Serial.println(WiFi.localIP()); //print out IP address of ESP32
24 Serial.printf("IP port: %d\n",port); //Print out ESP32's port number
Turn on server mode of ESP32, start automatic connection and turn on automatic reconnection.
25 server.begin(); //Turn ON ESP32 as Server mode
26 WiFi.setAutoConnect(true);
27 WiFi.setAutoReconnect(true);
When ESP32 receive messages from servers, it will print them out via serial port; Users can also send messages
to servers from serial port.
35 if (client.available()) { // if there's bytes to read from the
client
36 Serial.println(client.readStringUntil('\n')); // print it out the serial monitor
37 while(client.read()>0); // clear the wifi receive area cache
38 }
39 if(Serial.available()){ // if there's bytes to read from the
serial monitor
40 client.print(Serial.readStringUntil('\n')); // print it out the client.
41 while(Serial.read()>0); // clear the wifi receive area cache
42 }
Reference
Class Server
Every time use Server functionality, we need to include header file"WiFi.h".
WiFiServer(uint16_t port=80, uint8_t max_clients=4): create a TCP Server.
port: ports of Server; range from 0 to 65535 with the default number as 80.
max_clients: maximum number of clients with default number as 4.
begin(port): start the TCP Server.
port: ports of Server; range from 0 to 65535 with the default number as 0.
setNoDelay(bool nodelay): whether to turn off the delay sending functionality.
nodelay: true stands for forbidden Nagle algorithm.
close(): close tcp connection.
stop(): stop tcp connection.
Connect ESP32 using USB and check its IP address through serial monitor. Use web page to access IP address
to obtain video and image data.
Component List
Circuit
Sketch
Click Tools in the menu bar, select Flash Mode: "QIO", and select Partition Scheme:" Huge APP (3MB No
OTA/1MB SPIFFS) “, as shown in the figure below.
The reason for this configuration is that the Sketch occupies about 2MB of program storage, while in the
previous default mode, it was about 1.2M. Therefore, we need to choose a more appropriate partitioning
scheme for ESP32.
Sketch_32.1_As_CameraWebServer
Before running the program, please modify your router’s name and password in the box shown in the
illustration above to make sure that your Sketch can compile and work successfully.
Compile and upload codes to ESP32, open the serial monitor and set the baud rate to 115200, and the serial
monitor will print out a network link address.
If your ESP32 has been in the process of connecting to router, but the information above has not been printed
out, please re-check whether the router name and password have been entered correctly and press the reset
key on ESP32-WROVER to wait for a successful connection prompt.
Open a web browser, enter the IP address printed by the serial monitor in the address bar, and access it.
Taking the Google browser as an example, here's what the browser prints out after successful access to
ESP32's IP.
enter IP address
Note: If sketch compilation fails due to ESP32 support package, follow the steps of the image to open
the CameraWebServer. This sketch is the same as described in the tutorial above.
The following is the main program code. You need include other code files in the same folder when write
your own code.
1 #include "esp_camera.h"
2 #include <WiFi.h>
3
4 // Select camera model
5 #define CAMERA_MODEL_WROVER_KIT
6 //#define CAMERA_MODEL_ESP_EYE
7 //#define CAMERA_MODEL_M5STACK_PSRAM
8 //#define CAMERA_MODEL_M5STACK_WIDE
9 //#define CAMERA_MODEL_AI_THINKER
10
11 #include "camera_pins.h"
12
13 const char *ssid_Router = "********"; //input your wifi name
14 const char *password_Router = "********"; //input your wifi passwords
15 camera_config_t config;
16
17 void startCameraServer();
18 void config_init();
19
20 void setup() {
21 Serial.begin(115200);
22 Serial.setDebugOutput(true);
23 Serial.println();
24
25 config_init();
26 config.frame_size = FRAMESIZE_VGA;
27 config.jpeg_quality = 10;
28
29 // camera init
30 esp_err_t err = esp_camera_init(&config);
31 if (err != ESP_OK) {
32 Serial.printf("Camera init failed with error 0x%x", err);
33 return;
34 }
35
36 sensor_t * s = esp_camera_sensor_get();
37 s->set_vflip(s, 1); //flip it back
38 s->set_brightness(s, 1); //up the blightness just a bit
39 s->set_saturation(s, -1); //lower the saturation
40
41 WiFi.begin(ssid_Router, password_Router);
42 while (WiFi.status() != WL_CONNECTED) {
43 delay(500);
44 Serial.print(".");
45 }
46 Serial.println("");
47 Serial.println("WiFi connected");
48
49 startCameraServer();
50
51 Serial.print("Camera Ready! Use 'http://");
52 Serial.print(WiFi.localIP());
53 Serial.println("' to connect");
54 }
55
56 void loop() {
57 ;
58 }
59
60 void config_init(){
61 config.ledc_channel = LEDC_CHANNEL_0;
62 config.ledc_timer = LEDC_TIMER_0;
63 config.pin_d0 = Y2_GPIO_NUM;
64 config.pin_d1 = Y3_GPIO_NUM;
65 config.pin_d2 = Y4_GPIO_NUM;
66 config.pin_d3 = Y5_GPIO_NUM;
67 config.pin_d4 = Y6_GPIO_NUM;
68 config.pin_d5 = Y7_GPIO_NUM;
69 config.pin_d6 = Y8_GPIO_NUM;
70 config.pin_d7 = Y9_GPIO_NUM;
71 config.pin_xclk = XCLK_GPIO_NUM;
72 config.pin_pclk = PCLK_GPIO_NUM;
73 config.pin_vsync = VSYNC_GPIO_NUM;
74 config.pin_href = HREF_GPIO_NUM;
75 config.pin_sscb_sda = SIOD_GPIO_NUM;
76 config.pin_sscb_scl = SIOC_GPIO_NUM;
77 config.pin_pwdn = PWDN_GPIO_NUM;
78 config.pin_reset = RESET_GPIO_NUM;
79 config.xclk_freq_hz = 20000000;
80 config.pixel_format = PIXFORMAT_JPEG;
81 config.fb_count = 1;
82 }
Add procedure files and API interface files related to ESP32 camera.
1 #include "esp_camera.h"
2 #include <WiFi.h>
3
4 // Select camera model
5 #define CAMERA_MODEL_WROVER_KIT
6 //#define CAMERA_MODEL_ESP_EYE
7 //#define CAMERA_MODEL_M5STACK_PSRAM
8 //#define CAMERA_MODEL_M5STACK_WIDE
9 //#define CAMERA_MODEL_AI_THINKER
10
11 #include "camera_pins.h"
Enter the name and password of the router
13 const char *ssid_Router = "********"; //input your wifi name
14 const char *password_Router = "********"; //input your wifi passwords
Initialize serial port, set baud rate to 115200; open the debug and output function of the serial.
21 Serial.begin(115200);
22 Serial.setDebugOutput(true);
23 Serial.println();
Configure parameters including interface pins of the camera. Note: It is generally not recommended to change
them.
60 void config_init(){
61 config.ledc_channel = LEDC_CHANNEL_0;
62 config.ledc_timer = LEDC_TIMER_0;
63 config.pin_d0 = Y2_GPIO_NUM;
64 config.pin_d1 = Y3_GPIO_NUM;
65 config.pin_d2 = Y4_GPIO_NUM;
66 config.pin_d3 = Y5_GPIO_NUM;
67 config.pin_d4 = Y6_GPIO_NUM;
68 config.pin_d5 = Y7_GPIO_NUM;
69 config.pin_d6 = Y8_GPIO_NUM;
70 config.pin_d7 = Y9_GPIO_NUM;
71 config.pin_xclk = XCLK_GPIO_NUM;
72 config.pin_pclk = PCLK_GPIO_NUM;
73 config.pin_vsync = VSYNC_GPIO_NUM;
74 config.pin_href = HREF_GPIO_NUM;
75 config.pin_sscb_sda = SIOD_GPIO_NUM;
76 config.pin_sscb_scl = SIOC_GPIO_NUM;
77 config.pin_pwdn = PWDN_GPIO_NUM;
78 config.pin_reset = RESET_GPIO_NUM;
79 config.xclk_freq_hz = 20000000;
80 config.pixel_format = PIXFORMAT_JPEG;
81 config.fb_count = 1;
82 }
ESP32 connects to the router and prints a successful connection prompt. If it has not been successfully
connected, press the reset key on the ESP32-WROVER.
41 WiFi.begin(ssid_Router, password_Router);
42 while (WiFi.status() ! = WL_CONNECTED) {
43 delay(500);
44 Serial.print(".");
45 }
46 Serial.println("");
47 Serial.println("WiFi connected");
Open the video streams server function of the camera and print its IP address via serial port.
49 startCameraServer();
50
51 Serial.print("Camera Ready! Use 'http://");
52 Serial.print(WiFi.localIP());
53 Serial.println("' to connect");
Configure the display image information of the camera.
The set_vflip() function sets whether the image is flipped 180°, with 0 for no flip and 1 for flip 180°.
The set_brightness() function sets the brightness of the image, with values ranging from -2 to 2.
The set_saturation() function sets the color saturation of the image, with values ranging from -2 to 2.
36 sensor_t * s = esp_camera_sensor_get();
37 s->set_vflip(s, 1); //flip it back
38 s->set_brightness(s, 1); //up the blightness just a bit
39 s->set_saturation(s, -1); //lower the saturation
Modify the resolution and sharpness of the images captured by the camera. The sharpness ranges from 10 to
63, and the smaller the number, the sharper the picture. The larger the number, the blurrier the picture. Please
refer to the table below.
26 config.frame_size = FRAMESIZE_VGA;
27 config.jpeg_quality = 10;
Reference
Image resolution Sharpness Image resolution Sharpness
FRAMESIZE_QQVGA 160x120 FRAMESIZE_VGA 640x480
FRAMESIZE_QQVGA2 128x160 FRAMESIZE_SVGA 800x600
FRAMESIZE_QCIF 176x144 FRAMESIZE_XGA 1024x768
FRAMESIZE_HQVGA 240x176 FRAMESIZE_SXGA 1280x1024
FRAMESIZE_QVGA 320x240 FRAMESIZE_UXGA 1600x1200
FRAMESIZE_CIF 400x296 FRAMESIZE_QXGA 2048x1536
Connect ESP32 using USB and check its IP address through serial monitor. Use a mobile phone to obtain
video and image data.
Component List
There are three ways to install app, you can choose any one.
Method 1
Use Google play to search “Freenove”, download and install.
Method 2
Visit https://play.google.com/store/apps/details?id=com.freenove.suhayl.Freenove, and click install.
Method 3
Visit https://github.com/Freenove/Freenove_app_for_Android, download the files in this library, and install
freenove.apk to your Android phone manually.
Click here to
download.
Menu
Open application “Freenove”, as shown below:
MENU
Device
Selection
Area
Connect
Set
Circuit
Sketch
Click Tools in the menu bar, select Flash Mode: "QIO", and select Partition Scheme:" Huge APP (3MB No
OTA/1MB SPIFFS) “, as shown in the figure below.
After making sure the Tools is configured correctly, don’t run Sketch. Due to WiFi, we need to modify Sketch
a little bit based on physical situation.
In the box in the figure above, ssid_Router and password_Router are the user's Router name and password,
which need to be modified according to the actual name and password. ssid_AP and password_AP are name
and password of a AP created by ESP32, and they are freely set by the user. When all settings are correct,
compile and upload the code to ESP32, turn on the serial port monitor, and set the baud rate to 115200. The
serial monitor will print out two IP addresses.
There are two methods for you to check camera data of ESP32 via mobile phone APP.
Method 1:
Using your phone's WiFi function, select the WiFi name represented by ssid_AP in Sketch and enter the
password “password_AP” to connect.
Next, open Freenove app and select 4WD Car for Raspberry Pi mode.
Enter the IP address printed by serial port in the new interface, which generally is “192.168.4.1”
Click “Connect”.
Method 2:
Using your phone's WiFi function, select the router named ssid_Router and enter the password “ssid_password”
to connect. And then open Freenove app and select 4WD Car for Raspberry Pi mode. The operation is similar
to Method 1.
Enter the IP address printed by serial port in the new interface, which generally is not “192.168.4.1” but
another one. The IP address in this example is “192.168.1.100”. After entering the IP address, click “Connect”.
The following is the main program code. You need include other code files in the same folder when write
your own code.
Sketch_33.1_Camera_Tcp_Server
1 #include "esp_camera.h"
2 #include <WiFi.h>
3 #include <WiFiClient.h>
4 #include <WiFiAP.h>
5
6 #define CAMERA_MODEL_WROVER_KIT
7 #include "camera_pins.h"
8 #define LED_BUILT_IN 2
9
10 const char *ssid_Router = "********";
11 const char *password_Router = "********";
12 const char *ssid_AP = "********";
13 const char *password_AP = "********";
14
15 WiFiServer server_Cmd(5000);
16 WiFiServer server_Camera(8000);
17 extern TaskHandle_t loopTaskHandle;
18
19 void setup() {
20 Serial.begin(115200);
21 Serial.setDebugOutput(false);
22 Serial.println();
23 pinMode(LED_BUILT_IN, OUTPUT);
24 cameraSetup();
25
26 WiFi.softAP(ssid_AP, password_AP);
27 IPAddress myIP = WiFi.softAPIP();
28 Serial.print("AP IP address: ");
29 Serial.println(myIP);
30 server_Camera.begin(8000);
31 server_Cmd.begin(5000);
32 /////////////////////////////////////////////////////
33 WiFi.begin(ssid_Router, password_Router);
34 Serial.print("Connecting ");
35 Serial.print(ssid_Router);
36 while (WiFi.status() != WL_CONNECTED) {
37 delay(500);
38 Serial.print(".");
39 WiFi.begin(ssid_Router, password_Router);
40 }
41 Serial.println("");
42 Serial.println("WiFi connected");
43 /////////////////////////////////////////////////////
44 Serial.print("Camera Ready! Use '");
45 Serial.print(WiFi.softAPIP());
46 Serial.print(" or ");
47 Serial.print(WiFi.localIP());
48 Serial.println("' to connect in Freenove app.");
49
50 disableCore0WDT();
Loop function will constantly send camera data obtained to mobile phone APP.
62 while (client.connected()) { // loop while the client's connected
63 camera_fb_t * fb = NULL;
64 while (client.connected()) {
65 fb = esp_camera_fb_get();
66 if (fb != NULL) {
67 uint8_t slen[4];
68 slen[0] = fb->len >> 0;
69 slen[1] = fb->len >> 8;
70 slen[2] = fb->len >> 16;
71 slen[3] = fb->len >> 24;
72 client.write(slen, 4);
73 client.write(fb->buf, fb->len);
74 }
75 else {
76 Serial.println("Camera Error");
77 }
78 }
79 }
The loopTask_Cmd() function sends the received instruction back to the phone app and prints it out through
a serial port.
86 void loopTask_Cmd(void *pvParameters) {
87 Serial.println("Task Cmd_Server is starting ... ");
88 while (1) {
89 WiFiClient client = server_Cmd.available(); // listen for incoming clients
90 if (client) { // if you get a client,
91 Serial.println("Command Server connected to a client.");// print a message out
the serial port
92 String currentLine = ""; // make a String to hold incoming data from the client
93 while (client.connected()){ // loop while the client's connected
94 if (client.available()) { // if there's bytes to read from the client,
95 char c = client.read(); // read a byte, then
96 client.write(c);
97 Serial.write(c); // print it out the serial monitor
98 if (c == '\n') { // if the byte is a newline character
99 currentLine = "";
100 }
101 else {
102 currentLine += c; // add it to the end of the currentLine
103 }
104 }
105 }
106 // close the connection:
107 client.stop();
We have tried to use a buzzer in a previous chapter, and now we will solder a circuit that when the button is
pressed, the buzzer sounds.
This circuit does not need programming and can work when it is powered on. And when the button is not
pressed, there is no power consumption.
You can install it on your bike, bedroom door or any other places where it is needed.
Component List
AA Battery Holder x1
Circuit
Insert the components on the main board and solder the circuit on its back.
Testing circuit
Connect the circuit board to power supply (3~5V). You can use ESP32 board or battery box as the power
supply.
Anode
Cathode
Press the push button after connecting the power, and then the buzzer will make a sound.
From previous chapter, we have learned to make a flowing water light with LED. Now, we will solder a circuit
board, and use the improved code to make a more interesting flowing water light.
Component List
Circuit
Insert the components on the main board and solder the circuit on its back.
Connect the board to ESP32 with jumper wire in the following way.
VCC —3.3V/5V
GND —GND
SH_CP—GPIO13
ST_CP —GPIO12
DS —GPIO14
Sketch
14 graph.
15 // This variable is assigned to 0x01, that is, binary 00000001, which indicates only one LED light
16 on.
17 byte x = 0x01; // 0b 0000 0001
18 for (int j = 0; j < 8; j++) { // Let LED light up from right to left
19 writeTo595(LSBFIRST, x);
20 x <<= 1; // make the variable move one bit to left once, then the bright LED move one step
21 to the left once.
22 delay(50);
23 }
24 delay(100);
25 x = 0x80; //0b 1000 0000
26 for (int j = 0; j < 8; j++) { // Let LED light up from left to right
27 writeTo595(LSBFIRST, x);
28 x >>= 1;
29 delay(50);
30 }
31 delay(100);
32 }
33 void writeTo595(int order, byte _data ) {
34 // Output low level to latchPin
35 digitalWrite(latchPin, LOW);
36 // Send serial data to 74HC595
37 shiftOut(dataPin, clockPin, order, _data);
38 // Output high level to latchPin, and 74HC595 will update the data to the parallel output
39 port.
40 digitalWrite(latchPin, HIGH);
41 }
In fact, this code is copied from chapter 15. If you have any questions for the code, please click "Chapter 15
74HC595 & LED Bar Graph" to return to Chapter 15 to study again.
What’s next?
Thanks for your reading. This tutorial is all over here. If you find any mistakes, omissions or you have other
ideas and questions about contents of this tutorial or the kit and etc., please feel free to contact us:
support@freenove.com
We will check and correct it as soon as possible.
If you are interesting in processing, you can learn the Processing.pdf in:
Freenove_Ultimate_Starter_Kit_for_ESP32\C\Processing.pdf
If you want to learn more about Arduino, Raspberry Pi, smart cars, robots and other interesting products in
science and technology, please continue to focus on our website. We will continue to launch cost-effective,
innovative and exciting products.
http://www.freenove.com/