Tutorial
Tutorial
Tutorial
com List 1
Welcome
Thank you for choosing Freenove products!
About Battery
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
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
Welcome ............................................................................................................................................................................................... 1
Contents ................................................................................................................................................................................................ 1
List ........................................................................................................................................................................................................... 3
Robot Expansion Board for ESP32 ...................................................................................................................................... 3
ESP32............................................................................................................................................................................................. 4
Machinery .................................................................................................................................................................................... 4
Transmission ............................................................................................................................................................................... 5
Acrylic ............................................................................................................................................................................................ 5
Electronic...................................................................................................................................................................................... 6
Tools .............................................................................................................................................................................................. 6
Calibration ................................................................................................................................................................................... 7
Required but NOT Included Parts ....................................................................................................................................... 7
Preface ................................................................................................................................................................................................... 8
ESP32............................................................................................................................................................................................. 9
Pins Used for the Robot ........................................................................................................................................................ 10
Robot Expansion Board for ESP32 .................................................................................................................................... 12
Chapter 0 Install CH340 and Burn Firmware ........................................................................................................................... 13
Check Firmware ....................................................................................................................................................................... 13
Install CH340 Driver................................................................................................................................................................ 14
Burn the Firmware .................................................................................................................................................................. 22
Chapter 1 Install Freenove App ................................................................................................................................................... 31
Install Freenove App .............................................................................................................................................................. 31
IOS................................................................................................................................................................................................ 33
Introduction to Freenove App ............................................................................................................................................ 34
Chapter 2 Robot Assembly ........................................................................................................................................................... 35
Step 1 Assembly of Disc Servo Arms................................................................................................................................ 35
Step 2 Assembly of Body Bracket ...................................................................................................................................... 37
Step 3 Assembly of Legs....................................................................................................................................................... 40
Step 4 Adjustment of Servo Angles .................................................................................................................................. 43
Step 5 Assembly of Legs to Body ...................................................................................................................................... 47
Step 6 Assembly of Head and Wire .................................................................................................................................. 53
Step 7 Assembly of the Cover ............................................................................................................................................ 57
Step 8 Servo Wiring................................................................................................................................................................ 59
Step 9 Assembly of Calibration Bracket .......................................................................................................................... 60
Step 10 Calibration ................................................................................................................................................................. 61
Chapter 3 Functions of Freenove App ...................................................................................................................................... 67
Introduction to Main Interface............................................................................................................................................ 67
Wi-Fi Configuration................................................................................................................................................................ 68
RGB LED Control ..................................................................................................................................................................... 71
Interaction Function ............................................................................................................................................................... 72
Chapter 4 Q&A ................................................................................................................................................................................. 73
List
If you have any concerns, please feel free to contact us at support@freenove.com
Top
Bottom
ESP32
ESP32 OV2640
Machinery
Transmission
Acrylic
Acrylic x1
Electronic
Tools
Calibration
Calibration graph
Preface
Welcome to use Freenove Robot Dog Kit for ESP32. Following this tutorial, you can make a very cool robot
dog with many functions.
This kit is based on ESP32, a popular control panel, so you can exchange your experience and design ideas
with many enthusiasts all over the world. The parts in this kit include all electronic components, modules, and
mechanical components required for making the robot dog. And all of them are packaged individually. There
are detailed assembly and commissioning instructions in this book.
If you encounter any problems, please feel free to contact us for quick and free technical support.
support@freenove.com
This book aims to help enthusiasts assemble the robot dog and download related codes. You can read and
download the codes via the link below:
https://github.com/Freenove/Freenove_ESP32_Dog_Firmware
You can refer to another esp32 kit designed for starters: Freenove_Ultimate_Starter_Kit_for_ESP32.
https://www.freenove.com/store.html
ESP32
ESP32-Wrover comes with two different antenna packages, PCB (on-board) antenna and IPEX™ antenna. 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 connector, derived from the integrated antenna of the chip
module itself, which is used to enhance the signal of the ESP32 module.
PCB on-board antenna IPEX antenna
In this tutorial, the ESP32-WROVER is designed based on PCB on-board antenna packaged ESP32-WROVER
module.
To learn what each GPIO corresponds to, please refer to the following table.
The functions of the pins are allocated as follows:
Pins of ESP32 Functions Description
GPIO36 CSI_Y6
GPIO39 CSI_Y7
GPIO34 CSI_Y8
GPIO35 CSI_Y9
GPIO25 CSI_VYSNC
GPIO26 SIOD
GPIO27 SIOC
Camera interface
GPIO4 CSI_Y2
GPIO5 CSI_Y3
GPIO18 CSI_Y4
GPIO19 CSI_Y5
GPIO21 XCLK
GPIO22 PCLK
GPIO23 HREF
GPIO13 SDA
I2C port
GPIO14 SCL
GPIO32 Battery detection / Ultrasonic-Trig port A6 / Trig
GPIO12 Ultrasonic-Echo port Echo
GPIO33 Buzzer port Buzzer
GPIO15 Touch Sensor port Touch
GPIO0 WS2812 port WS2812
GPIO1 TX
Serial port
GPIO3 RX
Compare the left and right images. We have boxed off the resources on the ESP32 in different colors to
facilitate its understanding.
Box color Corresponding resources introduction
GPIO pin
LED indicator
Camera interface
USB port
WS2812 WS2812
Touch Sensor
Buzzer Connector
WS2812
WS2812
Power
Power
Indicator
Servo Servo
Connector Connector
Ultrasonic
Connector
Servo Servo
Connector Connector
Note: Please refer to the marks on the battery holder to install batteries; otherwise, the circuit will not work.
Check Firmware
Please note that the firmware has been burnt by default, so generally, you do not need to burn it again.
Please follow the steps below to check whether firmware has been burnt:
1. Plug the ESP32 to the expansion board.
Buzzer
LED
Indicators
USB Port
Pay attention to the orientation of the ESP32 and make sure it is plugged in correctly; otherwise, it may
damage the robot.
2. Connect ESP32 to your computer with a USB cable.
After connecting, you can see the yellow LED on ESP32 stay ON and the blue LED blink twice every second.
Meanwhile, the buzzer makes 4 warning sounds to tell you the camera has not yet been installed and then
a pleasant sound to indicate the finish of initialization.
If the above phenomenas happen, it means the firmware has been burnt.
If the firmware has been burnt on your robot, please skip to Chapter 1.
Otherwise, please continue with the following steps.
Please send emails to us (support@freenove.com) if you have any questions regarding the robot.
Need support? support@freenove.com
14 Chapter 0 Install CH340 and Burn Firmware www.freenove.com █
The computer uploads codes to ESP32 via CH340, so we need to install CH340 driver on our computer before
using.
1. First, download the 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_Robot_Dog_Kit_for_ESP32/CH340”. We have prepared the installation package.
Next, we will explain how to install CH340 on different operating systems including Windows, Mac OS and
Linux.
Windows
3. Click on “Device Manager” on the left of the pop-up window, and then click on “Ports” on the right. If
your computer has installed CH340 driver, you can see the port: USB-SERIAL CH340 (COMx).
CH340 Port
6. Make sure ESP32 has connected to your computer and then click “INSTALL”. Wait for the installation to
finish.
7. After installation, open device manager again and you can see the port USB-SERIAL CH340 (COMx).
Mac OS
If your Terminal prints the message similar to the above, then your computer has installed the CH340. You
can click here to move to the next step.
Otherwise, please continue with the following the steps.
Install CH340
If you would not like to download the installation package, you can open
“Freenove_Robot_Dog_Kit_for_ESP32/CH340”. We have prepared the installation package.
Open the folder “Freenove_Robot_Dog_Kit_for_ESP32/CH340/MAC/”
Run it.
Click Continue.
If CH340 is still not installed after the above steps, please refer to the ReadMe.pdf to install.
ReadMe
For this product, ESP32 has burned the required firmware by default. If your ESP32 does not have the firmware
or the firmware does not work, please re-burn the firmware with the following steps.
We will explain respectively for Windows, Mac OS and Linux systems.
Linux
If the driver has been installed, you can determine the port used by ESP32 to communicate with your computer
in this way:
1. When ESP32 is not connected to your computer, open system terminal and type in the command ls
/dev/tty*
2. Connect ESP32 to your computer with a USB cable and type in the command ls /dev/tty* again.
Compare the results. As shown below, /dev/ttyUSB0 is the port that ESP32 communicates with your computer.
If your computer has installed CH340, you can click here to skip to the next step.
Install CH340
If you connect the ESP32 to your computer but it does not detect /dev/ttyUSB0, then it has not installed
CH340 yet.
Please follow the steps below to install CH340 driver.
We have prepared the installation package for you: “Freenove_Robot_Dog_Kit_for_ESP32/CH340/LINUX/”.
3. Enter the unzipped folder and type in the command sudo make to compile and generate the file
ch34x.ko.
4. Use the ls command to check the file. As you can see below, the ch34.ko has been generated under the
current directory.
5. Type in the command to upload the file to the system: sudo make load
Windows
Mac OS
1. Open Terminal on your computer and type in the command python3 --version to check whether
python3 has been installed on your computer.
If your computer has not yet installed python3, please type in the command to install: brew install python3
2. Type in the command pip3 --version to check whether python3 has integrated with pip3. If it has not,
please type in the command curl https://bootstrap.pypa.io/get-pip.py | python3 to install.
6. Open Mac OS Terminal and type in the command to check whether ESP32 can be detected:
ls /dev/cu.usb*
The port number may vary among different computers. Here we take “/dev/cu.usbserial-14130” as an example.
Copy the serial number.
7. Open mac.py under the directory of Freenove_Robot_Dog_Kit_for_ESP32/Firmware/MAC OS/ with txt
editor, and modify the port number to that of your computer. Save it and exit.
Note: Please make sure only the port number is changed and other information, including space is not
changed; otherwise, the firmware may fail to burn.
Linux
1. Check whether your computer has installed python3. If it has, please skip to the next step.
2. Check whether pip3 has been installed on your computer. If it has, please move on to the next step.
Otherwise, please run the following commands to install:
sudo apt update&
sudo apt install python3-pip
Note: The above command is to give permission to/dev/ttyUSB0. Without this, the code may fail to download.
Method 1
Method 2
Visit the website https://www.freenove.com/app.html with your computer and choose the one corresponding
to your phone system to download, and then transfer it to your phone to install.
Method 3
IOS
Open the iPhone’s APP Store, search Freenove and install it.
Freenove
Install
Click it
Before using the phone App to control the robot dog, we need to understand the interface first.
Distance
Screenshot
Servo Speed and
Video Buzzer
Calibration Video Transmission
Transmission
Interface Settings Interaction
Servo
Switch
1. Take out 8 disc servo arms and 32 M1.4*8 screws from servo packages.
M1.4*8screws
Disc servo arm
2. Mount two disc servo arms to the acrylic part with The front and back after assembly are as shown
eight M1.4*8 screws. below.
Below is a perspective view of the front and back.
Note: The distance between the two sets of holes is different. Please use the ones with longer distance.
Short distance
Attach this
side to the
Long distance acrylic part.
4. Mount two disc servo arms with eight M1.4*8 screws to the head board.
5. Mount two disc servo arms with eight M1.4*8 screws to the rear board.
1. Mount the below two acrylic parts to the bottom body bracket with M3*12 screws and M3 nuts.
Bottom body
bracket
Front board
Rear board
It should look as below after assembly. Pay attention to the direction of the rear board.
Front board
M3 nut
M3*12 screw
丝
Rear board
2. Mount four M3*5+8 and four M3*10 brass standoffs to the top body bracket.
Head Rear
Top body
bracket
3. Mount the board to the top body bracket with four M3*4 screws.
Head Rear
After assembly:
Head Rear
Rear
Head
1. Mount four servos to four shanks with M2*10 screws and M2 nuts.
M2*10 screw
M2 nut
2. Mount two servos to the below acrylic parts with M2*10 screws and M2 nuts.
M2x10 screw
M2 nut
3. Mount two servos to the below acrylic parts with M2*10 screws and M2 nuts.
Assembly diagram After assembly
M2*10 screw
M2 nut
4. Mount the two set of acrylic parts above with M3*12 screws and M3 nuts.
5. Mount two servos to the below acrylic parts with M2*10 screws and M2 nuts.
Note: The direction is different from that in No.2!
Assembly diagram After assembly
M2x10 screw
M2 nut
6. Mount two servos to the below acrylic parts with M2*10 screws and M2 nuts.
Note: The direction is different from that in No.3!
Assembly diagram After assembly
M2*10 screw
M2nut
7. Mount the two set of acrylic parts abovw with M3*12 screws and M3 nuts.。
Usb port
Buzzer
Pay attention to the orientation of the ESP32. Wrong installation may lead to damage.
2. Install the batteries.
+ -
Put in the batteries according to the silkscreen. Wrong installation may result in malfunction.
Power switch
6. Turn ON Bluetooth of your phone and tap the Connect button on the app.
Connection
7. Select “Freenove-Dog-XXXXXXXX”.
Calibration
9. Tap Installation Position and all the servos will rotate to 90 degrees.
Initial position
Note: The purpose of adjusting the angle of the servos is to ensure that there will not be too much deviation
after assembly to avoid malfunction. Therefore, this step is very important.
Please keep power ON and all the servo cables connecting to the board during assembly.
We need to ensure servos remain at 90 degrees when assembling. (Servo cables are not shown in the following
instructions.)
1. Assemble the servos to the acrylic parts with black screws in servo packages.
Assemble them as close to 90 degrees as possible. Angles at 70 – 110 degrees are acceptable.
2. Assemble the servos to the acrylic parts with black screws in servo packages.
Assemble them as close to 90 degrees as possible. Angles at 70 – 110 degrees are acceptable.
4. Mount one left and one right legs to the rear board with black screws in the servo package.
Head
Right leg
Left leg
Assemble them as close to 90 degrees as possible. Angles at 70 – 110 degrees are acceptable.
90 degrees 90 degrees
5. Mount the rear board to the rear of the brackets with two M3*12 screws and two M3 nuts.
6. Mount one left and one right leg to the front board with black servo screws in the servo package.
Assemble them as close to 90 degrees as possible. Angles at 70 – 110 degrees are acceptable.
90 degrees
Note: After installing all Servo at 90 degrees, power can be turned off.
7. Mount two M3*10 standoffs to the front board with two M3*8 screws.
8. Mount the front board to the head of body bracket with a M3*12 screw and a M3 nut.
9. Fix the body brackets with eight M3*8 screws and four M3*20 brass standoffs.
3.
Plug one end of the camera cable into the camera extension board. Pay attention to blue side.
√ ×
Need support? support@freenove.com
54 Chapter 2 Robot Assembly www.freenove.com █
√ ×
4. Connect the ultrasonic module to driver board with the 4P DuPont cable.
5. Mount the two acrylic parts for head to the body with two M3*12 screws.
1. Mount the touch sensor to the cover with four M1.4*5 screws.
2. Use a 3P wire to connect the touch module to the robot dog drive board. The figure below does not
show the acrylic part.
14 1
13 15 0 2
9 6
10 8 7 5
At this point, the robot dog has been assembled and can walk, but because it has not been calibrated, it
cannot walk properly. Calibration is a very important task that determines whether your robot dog can walk
perfectly. Please be patient with the next steps.
1. Assemble the calibration bracket with two M3*12 screws and two M3 nuts.
2. Insert the calibration bracket into the robot dog to suspend the four legs.
Step 10 Calibration
Head
Calibration
bracket
Calibration
bracket
Head
Calibration bracket
3. Turn ON the power switch on the driver board. (Batteries are not included. Please buy them yourself.)
Power switch
5. Turn ON Bluetooth of your phone and tap the Connect button on the app.
Connection
6. Select “Freenove-Dog-XXXXXXXX”.
If you do not turn ON the power or upload code to ESP32, you cannot find the Bluetooth of robot dog.
Need support? support@freenove.com
64 Chapter 2 Robot Assembly www.freenove.com █
Calibration
8. Tap Installation Position and all the servos will rotate to 90 degrees.
Initial position
9. The robot dog turns all Servo into 90 degree position. As shown in the figure below.
Note: after pressing the button, if the Servo position in a different position from the following image,
disassemble the Servo and install it in the correct position. The smaller the deviation Angle, the better.
11. Select the leg to calibrate. Calibrate the legs by adjusting the X, Y and Z axes to make the tiptoe match
the point on the calibration graph.
3. Tap the
calibration
button
1. Select
By now, all the preparation work for robot dog has been done. You can now play the robot for fun.
Distance Measured
Screenshot
Wi-Fi Configuration
STAMode Bluetooth
and WiFi
information
APMode
3. Tap NewConn button to enter the Scan interface. Tap Scan button and select the Wi-Fi to be
connected.
5. To use APMode, please tap the switch below and then connect your phone to the Wi-Fi shown on
the right.
7. After the robot dog connects to Wi-Fi network, tap the video transmission and your phone will
display the frames captured by the robot.
Video Transmission
Interface Setting
Tip: Tap the Interface Settings button and you can adjust the frames displayed on the phone.
Note: Do not use speed above class 6 for long periods of time as there is a risk of damage to Servo.
2. The left and right arrows are used to switch the LED modes, the slider to control the brightness and
the color palette to set the color.
Interaction Function
Tip: Tapping the up and down arrow icon can make the robot dog lie down and unload the servos.
2. The robot dog can do different actions with different actions being tapped.
Chapter 4 Q&A
1. The buzzer makes four warning sound after powered ON.
Reason: The robot makes the sounds indicating that data cannot be obtained from the camera.
Troubleshooting:
a. The camera does not contact well with the extension board.
Please remove and reconnect the camera to try again.
b. The FPC cable does not contact well with the extension board.
Please remove and reconnect the cable.
c. The FPC cable does not contact well with the extension board.
Please remove and reconnect the cable.
d. The camera may be damaged. Please try to connect the camera to esp32 directly to test.
If the issue remains, then the camera module is damaged.
Please send us an email (support@freenove.com) to solve the issue.
Reason: As the Bluetooth and WIFI of ESP32 share the same antenna and a large amount of data is
transmitted through WIFI during video transmission, turning off Bluetooth can better reduce the
interference with WIFI communication. Therefore, once the video transmission function is used, the robot’s
Bluetooth is turned off by default, and both commands and video transmission are communicated through
WIFI.
3. When using the video transmission function, sometimes the response of the robot dog is not timely.
Reason: When the robot dog uses video transmission, only WIFI is enabled for communication. Whether it
has a lag depends on whether the signal of the router connected to the robot dog is stable. If the WIFI
signal is poor at some point, it will cause the robot dog to be stuck.
4. It is better to control the robot dog using Bluetooth rather than WIFI when not using video transmission.
Reason: When not transmitting videos, little data is transferred between the mobile APP and the robot dog.
In this case, both WIFI and Bluetooth can control the robot dog well, but the WIFI function may be affected
by the router signal, while the Bluetooth function does not have such problem, as it is directly sent by the
robot dog to the mobile phone. Therefore, it is strongly recommended to use the Bluetooth function to
control the robot dog, and turn off WIFI to increase the stability of the Bluetooth function when video
transmission is not used.
5. Q: Which mode is better? Can both modes be enabled simultaneously?
A: When not using video transmission, you can turn on Bluetooth and WIFI at the same time. However, they
share the same control commands, so we recommend turning off WIFI and only enabling Bluetooth, which
almost causes no lag.
When using video transmission, the robot’s Bluetooth is turned off by default to avoid interference to the
WIFI function.
6. Q: The WIFI has STA and AP modes, which one should I choose when using video transmission?
A: If there is a router with great signal available, we recommend using STA mode; otherwise, AP mode is
recommended.
Note: In AP mode, you need to connect your phone to the robot’s hotspot, whose SSID and password are
as follows:
Arduino 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 and install the driver correctly.
After the download completes, run the installer. For Windows users, there may pop up an installation dialog
during the installation. When it popes up, please allow the installation.
After installation is completed, 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.
Upload Compile your code and upload them to the configured board.
Serial Plotter The data received by the serial port is drawn as a line graph.
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: "Arduino Uno", and then select "Boards Manager".
Fifth, input "esp32" in the window below, and press Enter. Select version 2.0.2. 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.
Chapter 6 Battery
If you have any concerns, please feel free to contact us via support@freenove.com
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
Schematic
As we can see, the robot reads the voltage of the batteries through GPIO32 of ESP32. Because the battery
voltage is not read frequently, this GPIO is also used to control the Ultrasonic.
As shown in the figure above, the positive pole Vm of the power supply is controlled by the switch.
1. When the switch is turned on, the voltage value of VM is the voltage value of the battery.
2. Battery/Trig is connected to GPIO32 pin of ESP32.
3. The voltage acquisition range of GPIO32 on ESP32 is 0-3.3V, while the robot dog is powered by two 18650
lithium batteries, and the voltage is 8.4V when fully charged, which exceeds the voltage acquisition range of
ESP32. Therefore, after passing through the voltage divider circuit composed of R3 and R4, the voltage at
Battery/Trig is about 1/4 of the battery voltage, 8.4 / 4 = 2.1V, which is within the voltage acquisition range
of GPIO32.
Sketch
In this section, we will use GPIO32 of ESP32 to read the voltage value of the batteries and print it on serial
monitor. Open “Sketch_01_Battery” folder in “Freenove_Robot_Dog_Kit_for_ESP32\Sketches” and then
double-click “Sketch_01_Battery.ino”.
Sketch_01_Battery
Click the upload button in the upper left corner to upload the code to esp32. Open the serial monitor in the
upper right corner and set the baud rate to 115200.
BatteryPower.cpp
1 #include "BatteryPower.h"
2
3 void setupAdc(){
4 analogReadResolution(12);
5 analogSetAttenuation(ADC_11db);
6 adcAttachPin(PIN_ANALOG_IN);
7 }
8
9 uint32_t getBatteryVoltage(){
10 uint32_t adc_reading = 0;
11 for (int i = 0; i < NUM_OF_SAMPLES; i++){
12 adc_reading += analogRead(PIN_ANALOG_IN);
13 }
14 adc_reading /= NUM_OF_SAMPLES;
15 uint32_t voltage = adc_reading*3300/4096;
16 return voltage * VOLATAGE_RATIO;
17 }
ADC data sampling accuracy setting. Here it is set to 12 bits. 2^12=4096, so the sampling data range of ADC
is 0-4095.
4 analogReadResolution(12);
ADC sampling voltage range setting of ESP32, which is 0-3.3V. ADC_11db represents the maximum range.
Combined with the above analogReadResolution() function, when the voltage of the ADC collection point is
0V, the value collected by the ADC is 0; when the voltage of the ADC collection point is 3.3V, the value
collected by the ADC is 4095.
5 analogSetAttenuation(ADC_11db);
Associate the ADC configuration to the pin.
6 adcAttachPin(PIN_ANALOG_IN);
Use analogRead(PIN_ANALOG_IN) to capture the ADC value at the ESP32 pin.
Continuously collect NUM_OF_SAMPLES ADC values at the ESP32 pins and calculate the average.
10 uint32_t adc_reading = 0;
11 for (int i = 0; i < NUM_OF_SAMPLES; i++){
12 adc_reading += analogRead(PIN_ANALOG_IN);
13 }
14 adc_reading /= NUM_OF_SAMPLES;
Convert the ADC value to the actual measured voltage value. The unit is millivolts.
15 uint32_t voltage = adc_reading*3300/4096;
We know from the previous introduction that the voltage at the ESP32 pin is 1/4 of the battery voltage.
Therefore, the voltage value of the battery can be obtained by multiplying the voltage value measured by the
ADC by VOLATAGE_RATIO(4).
16 return voltage * VOLATAGE_RATIO;
Schematic
There are four LED lights on the ESP32 development board. ON is the power indicator, TX and RX are
indicators for communication or code upload status, and IO2 is the onboard indicator light., which is
connected on the GPIO2 pin of the ESP32.
As shown in the figure above, when the ESP32 outputs a high level, the onboard indicator will light up. When
the ESP32 outputs a low level, the onboard indicator light will be off. We can use it to indicate the running
state of our code.
Sketch
Sketch_02_BuiltInLed
Click the upload button in the upper left corner to upload the code to esp32. The LED on the ESP32 board
will turn on and off every 1 second for 5 times, and enter the flash mode.
BuiltInLed.h
1 #ifndef _BUILTINLED_h
2 #define _BUILTINLED_h
3
4 #include "Arduino.h"
5 #define LED_BUILT_IN 2
6 void setupBuiltInLed();
7 void setBuiltInLed(bool state);
8
9 void task_showBuiltInLed(void *pvParameters);
10
11 #endif
BuiltInLed.cpp
1 #include "BuiltInLed.h"
2
3 uint32_t sqValue = 0b00000101;
4 uint32_t lastLedUpdateTime = 0;
5 uint16_t intervalTime = 100; // ms
6 bool ledStatus = false;
7 bool lastLedStatus = true;
8 uint8_t ledRunnigStatus = 0;
9
10 void setupBuiltInLed(){
11 pinMode(LED_BUILT_IN, OUTPUT);
12 }
13
14 void setBuiltInLed(bool state){
15 digitalWrite(LED_BUILT_IN, state);
16 }
17
18 void task_showBuiltInLed(void *pvParameters){
19 static uint8_t bitIndex = 0;
20 static uint8_t bitDiff = 0;
21 if (millis() - lastLedUpdateTime > intervalTime){
22 switch (ledRunnigStatus){
23 case 0: // running
24 ledStatus = ((sqValue >> bitIndex) & 0x01) ? true : false;
25 if (ledStatus != lastLedStatus){
26 digitalWrite(LED_BUILT_IN, (uint8_t)ledStatus);
27 lastLedStatus = ledStatus;
28 bitDiff++;
29 }
30 bitIndex++;
31 if (bitIndex >= 10){
32 intervalTime = 600;
33 ledRunnigStatus = 1;
34 bitDiff = 0;
35 bitIndex = 0;
36 }
37 break;
38 case 1: // off
39 intervalTime = 100;
40 ledRunnigStatus = 0;
41 break;
42 default:
43 break;
44 }
45 lastLedUpdateTime = millis();
46 }
47 }
Onboard LED initialization function.
10 void setupBuiltInLed(){
11 pinMode(LED_BUILT_IN, OUTPUT);
12 }
The function that controls the on-board LED to turn on or off.
14 void setBuiltInLed(bool state){
15 digitalWrite(LED_BUILT_IN, state);
16 }
Enter the if statement every occasionally. This usage has the same effect as the delay() function, but it will not
cause the code to be pause.
21 if (millis() - lastLedUpdateTime > intervalTime){
Control the LED's on and off states by shifting a variable, sqValue, and taking the least significant bit as the
control signal.
If the current state of the LED is different from the previous state, control the LED to change its current state
and update the previous state to the current state.
24 ledStatus = ((sqValue >> bitIndex) & 0x01) ? true : false;
25 if (ledStatus != lastLedStatus){
26 digitalWrite(LED_BUILT_IN, (uint8_t)ledStatus);
27 lastLedStatus = ledStatus;
28 bitDiff++;
29 }
Introducing a variable called bitIndex to control the shift amount, so as to change the number of shifts
performed on sqValue each time,. If the number of shifts exceeds 9, the next time entering the if condition
will be delayed by 600ms, and sqValue starts shifting from the 0th bit again.
30 bitIndex++;
31 if (bitIndex >= 10){
32 intervalTime = 600;
33 ledRunnigStatus = 1;
34 bitDiff = 0;
35 bitIndex = 0;
36 }
If the previous shift cycle is completed, set the time for entering the if condition to 100ms each time and
proceed to the next shift cycle.
38 case 1: // off
39 intervalTime = 100;
40 ledRunnigStatus = 0;
41 break;
Chapter 8 Buzzer
If you have any concerns, please feel free to contact us via support@freenove.com
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 Passive buzzer
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.
Schematic
As shown in the figure below, we connect a buzzer to GPIO33 of ESP32. When GPIO33 outputs high level, the
buzzer circuit is turned on; when GPIO33 outputs low level, the buzzer circuit is turned off. Since the buzzer
is a passive buzzer, when we switch quickly between high and low levels, we can control the passive buzzer
to make a sound. The frequency of the sound depends on the duration of the high and low levels (f=1/T,
T=t1+t2).
Sketch
Sketch_03_Buzzer
Upload the sketch and the buzzer will beep three times at a fixed frequency and then emit a pleasant sound.
Buzzer.h
1 #ifndef _BUZZER_h
2 #define _BUZZER_h
3
4 #include "NoteFrequency.h"
5 #include "Arduino.h"
6
7 #define MELODY_POWER_UP 0
8 #define MELODY_LOW_POWER 1
9 #define MELODY_NO_POWER 2
10 #define MELODY_WIFI_CONNECT_SUCCESS 3
11 #define MELODY_WIFI_CONNECT_FAILED 4
12 #define MELODY_WIFI_DISCONNECT 5
13 #define MELODY_BLE_CONNECT_SUCCESS 6
14 #define MELODY_BLE_DISCONNECT 7
15 #define MELODY_CAM_CONNECT_SUCCESS 8
16 #define MELODY_CAM_DISCONNECT 9
17 #define MELODY_CAM_FAILURE 10
18 #define MELODY_BEEP_1 11
19 #define MELODY_BEEP_2 12
Need support? support@freenove.com
█ www.freenove.com Chapter 8 Buzzer 95
20 #define MELODY_DHTG 13
21 #define MELODY_BB_CLEAR_1 14
22 #define MELODY_BB_CLEAR_2 15
23 ……
24 void setupBuzzer();
25 void setBuzzer(uint16_t freq);
26 void setMelodyToPlay(int m);
27 void task_Buzzered(void *pvParameters);
28
29 #endif
Buzzer.cpp
1 #include "Buzzer.h"
2
3 #define BUZZER_PIN (33)
4 #define BUZZER_CHN (0)
5 #define BUZZER_BIT (10)
6 #define BUZZER_FREQ (5000)
7
8 int melody = -1;
9
10 void setupBuzzer() {
11 ledcSetup(BUZZER_CHN, BUZZER_FREQ, BUZZER_BIT); // setup pwm channel
12 ledcAttachPin(BUZZER_PIN, BUZZER_CHN);
13 ledcWrite(BUZZER_CHN, 0);
14 ledcWriteTone(BUZZER_CHN, 0);
15 }
16
17 void setBuzzer(uint16_t freq) {
18 if (freq != 0) {
19 ledcWrite(BUZZER_CHN, 512);
20 ledcWriteTone(BUZZER_CHN, freq);
21 } else {
22 ledcWrite(BUZZER_CHN, 0);
23 ledcWriteTone(BUZZER_CHN, 0);
24 }
25 }
26
27 template<int N> //Non-type template parameters
28 void playMelody(const int (&tune)[N], const float (&beat)[N], float speed) {
29 for (int i = 0; i < N; i++) {
30 setBuzzer(tune[i]);
31 delay(beat[i] * speed);
32 setBuzzer(0);
33 }
34 setBuzzer(0);
35 }
36
37 bool enableBuzzered = false;
38 TaskHandle_t taskHandle_Buzzered;
39
40 void setMelodyToPlay(int m) {
41 melody = m;
42 enableBuzzered = true;
43 xTaskCreateUniversal(task_Buzzered, "task_Buzzered", 2048, NULL, 1, &taskHandle_Buzzered, 0);
44 }
45
46 void task_Buzzered(void *pvParameters) {
47 if (enableBuzzered) {
48 switch (melody) {
49 case MELODY_POWER_UP:
50 playMelody(tunePowerUp, beatPowerUp, 300);
51 break;
52 case MELODY_LOW_POWER:
53 playMelody(tuneLowPower, beatLowPower, 300);
54 break;
55 case MELODY_NO_POWER:
56 playMelody(tuneNoPower, beatNoPower, 500);
57 break;
58 case MELODY_WIFI_CONNECT_SUCCESS:
59 playMelody(tuneWifiSucc, beatWifiSucc, 300);
60 break;
61 case MELODY_WIFI_CONNECT_FAILED:
62 playMelody(tuneWifiFailed, beatWifiFailed, 300);
63 break;
64 case MELODY_WIFI_DISCONNECT:
65 playMelody(tuneWifiDis, beatWifiDis, 300);
66 break;
67 case MELODY_BLE_CONNECT_SUCCESS:
68 playMelody(tuneBleSucc, beatBleSucc, 100);
69 break;
70 case MELODY_BLE_DISCONNECT:
71 playMelody(tuneBleDis, beatBleDis, 100);
72 break;
73 case MELODY_CAM_CONNECT_SUCCESS:
74 playMelody(tuneCamSucc, beatCamSucc, 100);
75 break;
76 case MELODY_CAM_DISCONNECT:
19 ledcWrite(BUZZER_CHN, 512);
20 ledcWriteTone(BUZZER_CHN, freq);
21 } else {
22 ledcWrite(BUZZER_CHN, 0);
23 ledcWriteTone(BUZZER_CHN, 0);
24 }
25 }
The melody playback function. Every time this function is called, a thread will be created to control the buzzer
to play the tune with the specified frequency.
40 void setMelodyToPlay(int m) {
41 melody = m;
42 enableBuzzered = true;
43 xTaskCreateUniversal(task_Buzzered, "task_Buzzered", 2048, NULL, 1, &taskHandle_Buzzered, 0);
44 }
Buzzer thread callback function. Each time the thread is executed, the
vTaskDelete(xTaskGetCurrentTaskHandle()) function is automatically called to close its own thread.
void task_Buzzered(void *pvParameters) {
if (enableBuzzered) {
switch (melody) {
……
}
}
vTaskDelete(xTaskGetCurrentTaskHandle());
}
Chapter 9 WS2812
If you have any concerns, please feel free to contact us via support@freenove.com
Schematic
As shown in the figure below, we connect the WS2812 to GPIO0 of ESP32. In this way, we can havel the
WS2812 to display various colors by controlling GPIO0.
Sketch
This code uses a library named "Freenove_WS2812_Lib_for_ESP32". If you have not installed it, please do so
first.
How to install the library
Click Library Manager on the left,enter “Freenove” in the search bar.
Sketch_04_WS2812
Upload the sketch to the esp32, the four WS2812 LEDs on the robot board will switch a colored light display
mode every 5 seconds.
RGBLED_WS2812.h
1 #ifndef _RGBLED_WS2812_h
2 #define _RGBLED_WS2812_h
3
4 #if defined(ARDUINO) && ARDUINO >= 100
5 #include "Arduino.h"
6 #else
7 #include "WProgram.h"
8 #endif
9
10 #include "Freenove_WS2812_Lib_for_ESP32.h"
11
12 #define LEDS_COUNT 4
13 #define LEDS_PIN 0
14 #define CHANNEL 0
15
Need support? support@freenove.com
102 Chapter 9 WS2812 www.freenove.com █
16 #define LED_MODE_OFF 0
17 #define LED_MODE_RGB 1
18 #define LED_MODE_FOLLOWING 2
19 #define LED_MODE_BLINK 3
20 #define LED_MODE_BREATHING 4
21 #define LED_MODE_RAINBOW 5
22
23 void setupRGBLED();
24 void setRGBLED(uint8_t mode, uint8_t r, uint8_t g, uint8_t b);
25
26 void task_showRGBLeds(void *pvParameters);
27 void task_RGBLeds(void *pvParameters);
28
29 #endif
RGBLED_WS2812.cpp
1 #include "RGBLED_WS2812.h"
2
3 Freenove_ESP32_WS2812 strip = Freenove_ESP32_WS2812(LEDS_COUNT, LEDS_PIN, CHANNEL, TYPE_GRB);
4
5 struct LedConfig {
6 uint8_t mode;
7 uint8_t r;
8 uint8_t g;
9 uint8_t b;
10 } ledConfig_t;
11
12 int followingColorStep = 0;
13 int breathingStep = 2;
14 int rainbowStep = 2;
15 bool blinkStateUp = true;
16 bool breathingStateUp = true;
17 u32 lastStripUpdateTime = 0;
18
19 void setupRGBLED() {
20 strip.begin();
21 strip.setBrightness(255);
22 xTaskCreateUniversal(task_RGBLeds, "task_RGBLeds", 4096, NULL, 1, NULL, 1);
23 }
24
25 void setRGBLED(uint8_t mode, uint8_t r, uint8_t g, uint8_t b) {
26 ledConfig_t.mode = mode;
27 ledConfig_t.r = r;
28 ledConfig_t.g = g;
29 ledConfig_t.b = b;
30 }
31
32 void task_showRGBLeds(void *pvParameters) {
33 switch (ledConfig_t.mode) {
34 case LED_MODE_OFF:
35 if (millis() - lastStripUpdateTime > 500) {
36 for (int i = 0; i < LEDS_COUNT; i++) {
37 strip.setLedColorData(i, 0, 0, 0);
38 }
39 strip.show();
40 lastStripUpdateTime = millis();
41 }
42 break;
43 case LED_MODE_RGB:
44 if (millis() - lastStripUpdateTime > 10) {
45 for (int i = 0; i < LEDS_COUNT; i++) {
46 strip.setLedColorData(i, ledConfig_t.r, ledConfig_t.g, ledConfig_t.b);
47 }
48 strip.show();
49 lastStripUpdateTime = millis();
50 }
51 break;
52 case LED_MODE_FOLLOWING:
53 if (millis() - lastStripUpdateTime > 100) {
54 followingColorStep += 5;
55 int j = followingColorStep;
56 strip.setLedColor(j % 4, strip.Wheel((j / 4 * 86) & 255));
57 lastStripUpdateTime = millis();
58 }
59 break;
60 case LED_MODE_BLINK:
61 if (millis() - lastStripUpdateTime > 500) {
62 if (blinkStateUp) {
63 blinkStateUp = false;
64 for (int i = 0; i < LEDS_COUNT; i++) {
65 strip.setLedColorData(i, ledConfig_t.r, ledConfig_t.g, ledConfig_t.b);
66 }
67 strip.show();
68 } else {
69 blinkStateUp = true;
70 for (int i = 0; i < LEDS_COUNT; i++) {
71 strip.setLedColorData(i, 0, 0, 0);
72 }
73 strip.show();
74 }
75 lastStripUpdateTime = millis();
76 }
77 break;
78 case LED_MODE_BREATHING:
79 if (millis() - lastStripUpdateTime > 10) {
80 if (breathingStateUp) {
81 breathingStep += 10;
82 if (breathingStep >= 255) {
83 breathingStep = 255;
84 breathingStateUp = false;
85 }
86 } else {
87 breathingStep -= 10;
88 if (breathingStep <= 0) {
89 breathingStep = 0;
90 breathingStateUp = true;
91 }
92 }
93 int j = breathingStep;
94 strip.setBrightness(j);
95 for (int i = 0; i < LEDS_COUNT; i++) {
96 strip.setLedColorData(i, ledConfig_t.r, ledConfig_t.g, ledConfig_t.b);
97 }
98 strip.show();
99 lastStripUpdateTime = millis();
100 }
101 break;
102 case LED_MODE_RAINBOW:
103 if (millis() - lastStripUpdateTime > 10) {
104 rainbowStep += 2;
105 if (rainbowStep >= 255) {
106 rainbowStep = 0;
107 }
108 int j = rainbowStep;
109 for (int i = 0; i < LEDS_COUNT; i++) {
110 strip.setLedColorData(i, strip.Wheel((i * 256 / LEDS_COUNT + j) & 255));
111 }
112 strip.show();
113 lastStripUpdateTime = millis();
114 }
115 break;
116 default:
117 break;
118 }
119 }
120
121 void task_RGBLeds(void *pvParameters) {
122 while (1) {
123 task_showRGBLeds(NULL);
124 }
125 }
Apply for a colored light control object and configure this object.
3 Freenove_ESP32_WS2812 strip = Freenove_ESP32_WS2812(LEDS_COUNT, LEDS_PIN, CHANNEL, TYPE_GRB);
Initialize the RGB LEDs, and set their brightness to the maximum value. Start a thread and set task_RGBLeds()
as the callback function of the thread.
19 void setupRGBLED() {
20 strip.begin();
21 strip.setBrightness(255);
22 xTaskCreateUniversal(task_RGBLeds, "task_RGBLeds", 4096, NULL, 1, NULL, 1);
23 }
RGB LEDs configuration function. Call this function to set the colored light mode and the red, green, and blue
color values of the LEDs.
25 void setRGBLED(uint8_t mode, uint8_t r, uint8_t g, uint8_t b) {
26 ledConfig_t.mode = mode;
27 ledConfig_t.r = r;
28 ledConfig_t.g = g;
29 ledConfig_t.b = b;
30 }
LED display function. The thread will control the RGB LEDs to emit different colors and phenomena according
to the configuration information of ledConfig_t.
32 void task_showRGBLeds(void *pvParameters) {
33 switch (ledConfig_t.mode) {
34 case LED_MODE_OFF:
… ……
42 break;
43 case LED_MODE_RGB:
… ……
51 break;
52 case LED_MODE_FOLLOWING:
… ……
59 break;
60 case LED_MODE_BLINK:
… ……
77 break;
78 case LED_MODE_BREATHING:
… ……
Need support? support@freenove.com
106 Chapter 9 WS2812 www.freenove.com █
101 break;
102 case LED_MODE_RAINBOW:
… ……
115 break;
116 default:
117 break;
118 }
119 }
Thread callback function, when the thread starts, it will execute the color light display function cyclically.
121 void task_RGBLeds(void *pvParameters) {
122 while (1) {
123 task_showRGBLeds(NULL);
124 }
125 }
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.
Sketch
In this chapter, we use GPIO32 of ESP32 as the Trig pin of the ultrasonic module, and GPIO12 as the Echo pin
of the ultrasonic module.
Open “Sketch_05_Ultrasonic” folder in “Freenove_Robot_Dog_Kit_for_ESP32\Sketches” and then double-
click “Sketch_05_Ultrasonic.ino”.
Sketch_05_Ultrasonic
Upload the sketch to ESP32 and the robot will acquire ultrasonic data every 500 milliseconds and prints
them out through the serial port.
UltrasonicRanging.h
1 #ifndef _ULTRASONICRANGING_h
2 #define _ULTRASONICRANGING_h
3
4 #if defined(ARDUINO) && ARDUINO >= 100
5 #include "Arduino.h"
6 #else
7 #include "WProgram.h"
8 #endif
9
10 #define PIN_TRIG 32 //Ultrasonic trig pin
11 #define PIN_ECHO 12 //Ultrasonic echo pin
12
13 void setupSonar();
14 float getSonar();
15
16 #endif
UltrasonicRanging.cpp
1 #include "UltrasonicRanging.h"
2
3 constexpr int MAX_DISTANCE = 300; // Maximum sensor distance is rated at 400-500cm.
4 constexpr float timeOut = MAX_DISTANCE * 60; // timeOut= 2*MAX_DISTANCE /100 /340 *1000000 =
MAX_DISTANCE*58.8
5 constexpr int soundVelocity = 340; // define sound speed=340m/s
6
7 void setupSonar() {
8 pinMode(PIN_TRIG, OUTPUT); // set trigPin to output mode
9 pinMode(PIN_ECHO, INPUT); // set echoPin to input mode
10 }
11 float getSonar() {
12 unsigned long pingTime, t0, t1;
13 float distance;
14 // make PIN_TRIG output high level lasting for 10μs to triger HC_SR04
15 digitalWrite(PIN_TRIG, HIGH);
16 delayMicroseconds(10);
17 digitalWrite(PIN_TRIG, LOW);
18 // Wait HC-SR04 returning to the high level and measure out this waitting time
19 t0 = micros();
20 pingTime = pulseIn(PIN_ECHO, HIGH, timeOut); // unit: us
21 t1 = micros() - t0;
22 // calculate the distance according to the time
23 if (t1 < timeOut) {
24 distance = (float)pingTime * soundVelocity / 2 / 10000;
25 } else {
26 distance = MAX_DISTANCE;
27 }
28 return distance; // return the distance value
29 }
Ultrasonic module initialization function.
7 void setupSonar() {
8 pinMode(PIN_TRIG, OUTPUT); // set trigPin to output mode
9 pinMode(PIN_ECHO, INPUT); // set echoPin to input mode
10 }
Chapter 11 Touch
If you have any concerns, please feel free to contact us via support@freenove.com
Component 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.
In this chapter, we use the GPIO15 pin of ESP32 to simulate the touch function and read it.
Sketch
Sketch_06_Touch
Upload the code to esp32, and the robot dog obtains the status of the touch sensor every 100 milliseconds
and prints it out through the serial port. Touch the position circled in the figure below with your finger, and
observe the changes in the content printed by the serial port.
TouchPad.cpp
1 #include "TouchPad.h"
2
3 static uint32_t s_pad_init_val;
4 static void tp_example_set_thresholds(void) {
5 uint16_t touch_value;
6 // read filtered value
7 touch_pad_read_filtered(PIN_TOUCH_PAD, &touch_value);
8 s_pad_init_val = touch_value;
9 // set interrupt threshold.
10 touch_pad_set_thresh(PIN_TOUCH_PAD, touch_value * 4 / 5);
11 }
12 bool touchPadVal = false;
13 void isr_touchpad(void *arg) {
14 // uint16_t touchVal = 0;
15 uint32_t touchStatus = 0;
16 touchStatus = touch_pad_get_status(); // TOUCHPAD3 : 0000 1000 = 0x08
17 if (touchStatus == 0x08) // TOUCHPAD3
18 {
19 touchPadVal = true;
20 }
21 touch_pad_clear_status();
22 }
23
24 void setupTouchPad(void) {
25 // Initialize touch pad peripheral, it will start a timer to run a filter
26 ESP_ERROR_CHECK(touch_pad_init());
27 // If use interrupt trigger mode, should set touch sensor FSM mode at 'TOUCH_FSM_MODE_TIMER'.
28 touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
29 // Set reference voltage for charging/discharging
30 // For most usage scenarios, we recommend using the following combination:
31 // the high reference valtage will be 2.7V - 1V = 1.7V, The low reference voltage will be 0.5V.
32 touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
33 // Init touch pad IO
34 touch_pad_config(PIN_TOUCH_PAD, TOUCH_THRESH_NO_USE);
35 // Initialize and start a software filter to detect slight change of capacitance.
36 touch_pad_filter_start(TOUCHPAD_FILTER_TOUCH_PERIOD);
37 // Set thresh hold
38 tp_example_set_thresholds();
39 // set isr trigger mode
40 touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW);
41 // Register touch interrupt ISR
42 touch_pad_isr_register(isr_touchpad, NULL);
43 // enable isr
44 touch_pad_intr_enable();
45
46 xTaskCreateUniversal(task_Touch, "task_Touch", 4096, NULL, 1, NULL, 1);
47 }
48
49 uint8_t touchMechineStatus = 0;
50 uint32_t t0 = millis(), // start time point
51 t1 = 0, // update time point
52 t2 = 0, // release time
53 t3 = 0; // pressed time
54 void task_TouchPad(void *pvParameters) {
55 switch (touchMechineStatus) {
56 case 0: // Idle , Wait for the button to press.
57 if (touchPadVal) {
58 t0 = millis();
59 t1 = t0;
60 touchPadVal = false;
61 touchMechineStatus = 1;
62 }
63 break;
64 case 1: // short press or long press ?
65 if (touchPadVal) {
66 t1 = millis();
67 touchPadVal = false;
68 }
69 t2 = millis() - t1; // Time since the last press signal was detected
70 t3 = t1 - t0; // calculate pressed time.
71 if (t3 > 700) // long pressed
72 {
73 Serial.printf("long press: %dms\n", t3);
74 touchMechineStatus = 3; // wait release
75 }
76 if (t2 > 50) // release time > 50, press time < 700, short press, enter short pressed state
77 {
78 touchMechineStatus = 2;
79 }
80 break;
81 case 2: // short press
82 Serial.printf("short press: %dms\n", t3);
83 touchMechineStatus = 0;
84 break;
85 case 3: // Wait for release after long press.
86 if (touchPadVal) {
87 t1 = millis();
88 touchPadVal = false;
89 }
90 t2 = millis() - t1;
91 if (t2 > 50) // release time > 50
92 {
93 touchMechineStatus = 0;
94 }
95 break;
96 default:
97 break;
98 }
99 }
100
101 void task_Touch(void *pvParameters) {
102 Serial.printf("task_Touch is running...\r\n");
103 while (1) {
104 task_TouchPad(NULL);
105 }
106 }
107
108 int getTouch(void) {
109 return touchMechineStatus;
110 }
ESP32 touch function pin initialization.
24 void setupTouchPad(void) {
25 // Initialize touch pad peripheral, it will start a timer to run a filter
26 ESP_ERROR_CHECK(touch_pad_init());
27 // If use interrupt trigger mode, should set touch sensor FSM mode at 'TOUCH_FSM_MODE_TIMER'.
28 touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
29 // Set reference voltage for charging/discharging
30 // For most usage scenarios, we recommend using the following combination:
31 // the high reference valtage will be 2.7V - 1V = 1.7V, The low reference voltage will be 0.5V.
32 touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
33 // Init touch pad IO
34 touch_pad_config(PIN_TOUCH_PAD, TOUCH_THRESH_NO_USE);
35 // Initialize and start a software filter to detect slight change of capacitance.
36 touch_pad_filter_start(TOUCHPAD_FILTER_TOUCH_PERIOD);
37 // Set thresh hold
38 tp_example_set_thresholds();
39 // set isr trigger mode
40 touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW);
41 // Register touch interrupt ISR
42 touch_pad_isr_register(isr_touchpad, NULL);
43 // enable isr
44 touch_pad_intr_enable();
45
46 xTaskCreateUniversal(task_Touch, "task_Touch", 4096, NULL, 1, NULL, 1);
47 }
Touch sensor thread callback function.
101 void task_Touch(void *pvParameters) {
102 Serial.printf("task_Touch is running...\r\n");
103 while (1) {
104 task_TouchPad(NULL);
105 }
106 }
Touch function threshold setting function. When the sensor is touched, the internal capacitor discharges,
and the data change can be detected at the touch pin. Here, 4/5 of the value of the touch sensor without
contact is set as the threshold trigger range.
3 static uint32_t s_pad_init_val;
4 static void tp_example_set_thresholds(void) {
5 uint16_t touch_value;
6 // read filtered value
7 touch_pad_read_filtered(PIN_TOUCH_PAD, &touch_value);
8 s_pad_init_val = touch_value;
9 // set interrupt threshold.
10 touch_pad_set_thresh(PIN_TOUCH_PAD, touch_value * 4 / 5);
11 }
Touch sensor interrupt trigger function. Execute this function every time the touch sensor is triggered, to set
touchPadVal to true.
12 bool touchPadVal = false;
13 void isr_touchpad(void *arg) {
14 // uint16_t touchVal = 0;
15 uint32_t touchStatus = 0;
16 touchStatus = touch_pad_get_status(); // TOUCHPAD3 : 0000 1000 = 0x08
17 if (touchStatus == 0x08) // TOUCHPAD3
18 {
19 touchPadVal = true;
20 }
21 touch_pad_clear_status();
22 }
Schematic
As shown in the picture, we connect the SDA and SCL pins of PCA9685 chip to GPIO13 and GPIO14 of ESP32
respectively. In this way, we can communicate with PCA9685 through IIC, and control the servo through
PCA9685 to rotate to any angle.
Sketch
Sketch_07_Action
Upload the code to esp32 and the robot dog will make various actions.
Please note: If your robot dog has not been calibrated, please navigate back to Chapter 2 to calibrate the
robot dog first.
2
3 /*
4 Please note that the following functions are based on the premise that the robot dog has been calibrated.
5 If your robot dog has not been calibrated yet, calibrate before learning.
6 Otherwise, the steering gear may be damaged, or the machine action cannot achieve the desired purpose.
7 */
8
9 void setup() {
10 Serial.begin(115200);
11 Serial.println("\n\nProgram begin ... ");
12 prefs.begin(NMSPC_STORAGE);
13 pca.begin();
14 pca.releaseAllServo();
15 getServoOffsetFromStorage();
16
17 standUp();
18 delay(3000);
19
20 const uint8_t repeatCounts = 3;
21 const int8_t acts[][2][3] = {
22 { { 0, 0, 10 }, { 0, 0, -10 } }, //Rotate horizontally clockwise, counterclockwise horizontal rotation.
23 { { 0, 10, 0 }, { 0, -10, 0 } }, //High on the left and low on the right, low on the left and high on the right.
24 { { 10, 0, 0 }, { -10, 0, 0 } } //High at the front and low at the back, low at the front and high at the back.
25 };
26 for (uint8_t i = 0; i < sizeof(acts) / sizeof(acts[0]); i++) {
27 for (int k = 0; k < repeatCounts; k++) {
28 for (int j = 0; j < 2; j++) {
29 twist_any(acts[i][j][0], acts[i][j][1], acts[i][j][2]);
30 delay(20);
31 }
32 }
33 }
34
35 //Rotate horizontally clockwise, and high at the front and low at the back, low at the front and high at the
36 back.
37 int8_t x = 0, y = 0, z = 0;
38 for (uint8_t j = 0; j < repeatCounts; j++) {
39 for (int i = 0; i < 360; i += 30) {
40 x = 10 * sin((double)i * PI / 180);
41 z = 10 * cos((double)i * PI / 180);
42 twist_any(x, y, z);
43 }
44 }
45 twist_any(0, 0, 0); //Normal standing
46
47 //The whole body goes up and down.
48 for (int i = 0; i < repeatCounts; i++) {
49 setBodyHeight(BODY_HEIGHT_MIN);
50 delay(200);
51 setBodyHeight(BODY_HEIGHT_MAX);
52 delay(200);
53 }
54
55 //Move forward (10*10)mm in the positive direction of the x axis
56 for (int i = 0; i < 10; i++) {
57 move_any(0, 10, 0);
58 }
59 //Move back (10*10)mm in the positive direction of the x axis
60 for (int i = 0; i < 10; i++) {
61 move_any(0, -10, 0);
62 }
63
64 //Control the robot dog to sit down and disable all servoes to reduce power consumption
65 setBodyHeight(BODY_HEIGHT_MIN);
66 pca.releaseAllServo();
67 }
68
69 void loop() {
70 delay(10000);
71 }
Before controlling the robot dog to make various actions, you need to initialize the robot dog first, and get
the calibration data of the servos from NVS If your robot dog has not been calibrated, please navigate back
to Chapter 2 to calibrate the robot dog first.
12 prefs.begin(NMSPC_STORAGE);
13 pca.begin();
14 pca.releaseAllServo();
15 getServoOffsetFromStorage();
The robot dog action speed setting function, with the parameter ranging from 1 to 8. The larger the value,
the faster the robot dog.
void setMoveSpeed(int spd);
The robot dog twisting function. By modifying different parameters, you can make the robot dog perform
various body twisting movements.
void twist_any(int alpha, int beta, int gama);
Robot dog movement function, by modifying the parameters, control the robot dog to go forward at any
direction, any step length, any rotation Angle, and any speed.
* @brief Walk command, any direction, any step length, any spin angle, any speed
*
* @param alpha is the moving direction, with the x-axis direction as 0 degrees, counterclockwise as positive,
clockwise as negative, and the unit is angle, [0-360]. The x direction is the direction of forward movement.
* @param stepLength The length of each step (<=20).
* @param gama Spin angle, in-situ rotation, positive counterclockwise, negative clockwise, in degrees. [0-
360].
* @param spd Movement speed, unit:mm / 10ms. [1,8]
void move_any(int alpha, float stepLength, int gama, int spd = 5);
Robot dog height setting function. The value ranges from 55 to 120.
void setBodyHeight(int h);
Servo unloading function. Each time this function is called, the servos will lose torque
pca.releaseAllServo();
Robot dog standing function. Every time this function is called, the robot dog will return to the standing
position.
standUp();
Chapter 13 BLE
If you have any concerns, please feel free to contact us via support@freenove.com
Sketch
Sketch_08_BLE
Upload the code to esp32. Open the serial monitor and set the baud rate to 115200. Connect the mobile
APP to the robot dog, and you can see all the commands sent by the mobile terminal on the serial monitor.
BluetoothService.h
1 #ifndef __BLUETOOTHSERVICE_H
2 #define __BLUETOOTHSERVICE_H
3
4 #include "Arduino.h"
5
6 #include <BLEDevice.h>
7 #include <BLEServer.h>
8 #include <BLEUtils.h>
9 #include <BLE2902.h>
10
11 class BLEServer;
12 class BLECharacteristic;
13 class BLEServerCallbacks;
14
15 void bleSetup();
16 void bleStop();
17 void bleSend(std::string msg);
18 extern void onBleReceived(BLECharacteristic *pCharacteristic);
19
20 #endif
BluetoothService.cpp
1 #include "BluetoothService.h"
2
3 // See the following for generating UUIDs:
4 // https://www.uuidgenerator.net/
5
6 #define SERVICE_UUID "0000ffe0-0000-1000-8000-00805f9b34fb" // UART service UUID
7 #define CHARACTERISTIC_UUID_RX "0000ffe1-0000-1000-8000-00805f9b34fb"
8 #define CHARACTERISTIC_UUID_TX "0000ffe1-0000-1000-8000-00805f9b34fb"
9
10 BLEServer *pServer = NULL;
11 BLECharacteristic *pTxCharacteristic;
12 bool isBleConnected = false;
13 bool oldBleConnected = false;
14 uint8_t txValue = 0;
15
16 class MyServerCallbacks : public BLEServerCallbacks {
17 void onConnect(BLEServer *pServer) {
18 isBleConnected = true;
19 // connecting
20 if (isBleConnected && !oldBleConnected) {
21 // do stuff here on connecting
22 oldBleConnected = isBleConnected;
23 Serial.println("Ble Connect");
24 }
25 };
26
27 void onDisconnect(BLEServer *pServer) {
28 isBleConnected = false;
29 // disconnecting
30 if (!isBleConnected && oldBleConnected) {
31 oldBleConnected = isBleConnected;
32 Serial.println("Ble Disconnect");
33 delay(500); // give the bluetooth stack the chance to get things ready
34 pServer->startAdvertising(); // restart advertising
35 }
36 }
37 };
38
39 class MyCallbacks : public BLECharacteristicCallbacks {
40 void onWrite(BLECharacteristic *pCharacteristic) {
41 onBleReceived(pCharacteristic);
42 }
43 };
44
45 void bleSetup() {
46 // Create the BLE Device
47 String s = String("Freenove-Dog");
48 BLEDevice::init(std::string(s.c_str()));
49 BLEDevice::setMTU(512);
50 // Create the BLE Server
51 pServer = BLEDevice::createServer();
52 pServer->setCallbacks(new MyServerCallbacks());
53 // Create the BLE Service
54 BLEService *pService = pServer->createService(SERVICE_UUID);
55 // Create a BLE Characteristic
56 pTxCharacteristic = pService->createCharacteristic(
57 CHARACTERISTIC_UUID_TX,
58 BLECharacteristic::PROPERTY_NOTIFY);
59 pTxCharacteristic->addDescriptor(new BLE2902());
60 BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(
61 CHARACTERISTIC_UUID_RX,
62 BLECharacteristic::PROPERTY_WRITE);
63 pRxCharacteristic->setCallbacks(new MyCallbacks());
64 // Start the service
65 pService->start();
66 // Start advertising
67 pServer->getAdvertising()->start();
68 Serial.println("Bluetooth initialization complete, Waiting a client connection to notify...");
69 }
70
71 void bleStop() {
72 BLEDevice::deinit();
73 }
74
75 void bleSend(std::string msg) {
76 if (isBleConnected) {
77 pTxCharacteristic->setValue(msg);
78 pTxCharacteristic->notify();
79 }
80 }
Sketch
Sketch_09_Camera
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.
If your Arduino IDE prompts you that your sketch is out of your project's storage space, compile the code
again as configured below.
Need support? support@freenove.com
130 Chapter 14 Camera Web Server www.freenove.com █
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 //
5 // WARNING!!! PSRAM IC required for UXGA resolution and high JPEG quality
6 // Ensure ESP32 Wrover Module or other board with PSRAM is selected
7 // Partial images will be transmitted if image exceeds buffer size
8 //
9
10 // Select camera model
11 #define CAMERA_MODEL_WROVER_KIT // Has PSRAM
12 //#define CAMERA_MODEL_ESP_EYE // Has PSRAM
13 //#define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM
14 //#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM
15 //#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM
16 //#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM
17 //#define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM
18 //#define CAMERA_MODEL_AI_THINKER // Has PSRAM
19 //#define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM
20
21 #include "camera_pins.h"
22
23 const char* ssid = "********";
24 const char* password = "********";
25
26 void startCameraServer();
27
28 void setup() {
29 Serial.begin(115200);
30 Serial.setDebugOutput(true);
31 Serial.println();
32
33 camera_config_t config;
34 config.ledc_channel = LEDC_CHANNEL_0;
35 config.ledc_timer = LEDC_TIMER_0;
36 config.pin_d0 = Y2_GPIO_NUM;
37 config.pin_d1 = Y3_GPIO_NUM;
38 config.pin_d2 = Y4_GPIO_NUM;
39 config.pin_d3 = Y5_GPIO_NUM;
40 config.pin_d4 = Y6_GPIO_NUM;
41 config.pin_d5 = Y7_GPIO_NUM;
42 config.pin_d6 = Y8_GPIO_NUM;
43 config.pin_d7 = Y9_GPIO_NUM;
44 config.pin_xclk = XCLK_GPIO_NUM;
45 config.pin_pclk = PCLK_GPIO_NUM;
46 config.pin_vsync = VSYNC_GPIO_NUM;
47 config.pin_href = HREF_GPIO_NUM;
48 config.pin_sccb_sda = SIOD_GPIO_NUM;
49 config.pin_sccb_scl = SIOC_GPIO_NUM;
50 config.pin_pwdn = PWDN_GPIO_NUM;
51 config.pin_reset = RESET_GPIO_NUM;
52 config.xclk_freq_hz = 20000000;
53 config.pixel_format = PIXFORMAT_JPEG;
54
55 // if PSRAM IC present, init with UXGA resolution and higher JPEG quality
56 // for larger pre-allocated frame buffer.
57 if(psramFound()){
58 config.frame_size = FRAMESIZE_UXGA;
59 config.jpeg_quality = 10;
60 config.fb_count = 2;
61 } else {
62 config.frame_size = FRAMESIZE_SVGA;
63 config.jpeg_quality = 12;
64 config.fb_count = 1;
65 }
66
67 #if defined(CAMERA_MODEL_ESP_EYE)
68 pinMode(13, INPUT_PULLUP);
69 pinMode(14, INPUT_PULLUP);
70 #endif
71
72 // camera init
73 esp_err_t err = esp_camera_init(&config);
74 if (err != ESP_OK) {
75 Serial.printf("Camera init failed with error 0x%x", err);
76 return;
77 }
78
79 sensor_t * s = esp_camera_sensor_get();
80 // initial sensors are flipped vertically and colors are a bit saturated
81 if (s->id.PID == OV3660_PID) {
82 s->set_vflip(s, 1); // flip it back
83 s->set_brightness(s, 1); // up the brightness just a bit
84 s->set_saturation(s, -2); // lower the saturation
85 }
86 // drop down frame size for higher initial frame rate
87 s->set_framesize(s, FRAMESIZE_QVGA);
88
89 #if defined(CAMERA_MODEL_M5STACK_WIDE) || defined(CAMERA_MODEL_M5STACK_ESP32CAM)
90 s->set_vflip(s, 1);
91 s->set_hmirror(s, 1);
92 #endif
93
94 WiFi.begin(ssid, password);
95 while (WiFi.status() != WL_CONNECTED) {
96 delay(500);
97 Serial.print(".");
98 }
99 Serial.println("");
100 Serial.println("WiFi connected");
101
102 startCameraServer();
103
104 Serial.print("Camera Ready! Use 'http://");
105 Serial.print(WiFi.localIP());
106 Serial.println("' to connect");
107 }
108
109 void loop() {
110 // put your main code here, to run repeatedly:
111 delay(10000);
112 }
Add procedure files and API interface files related to ESP32 camera.
1 #include "esp_camera.h"
2 #include <WiFi.h>
3
4 //
5 // WARNING!!! PSRAM IC required for UXGA resolution and high JPEG quality
6 // Ensure ESP32 Wrover Module or other board with PSRAM is selected
7 // Partial images will be transmitted if image exceeds buffer size
8 //
9
10 // Select camera model
11 #define CAMERA_MODEL_WROVER_KIT // Has PSRAM
12 //#define CAMERA_MODEL_ESP_EYE // Has PSRAM
13 //#define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM
14 //#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM
15 //#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM
16 //#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM
17 //#define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM
Open the video streams server function of the camera and print its IP address via serial port.
102 startCameraServer();
103
104 Serial.print("Camera Ready! Use 'http://");
105 Serial.print(WiFi.localIP());
106 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.
79 sensor_t * s = esp_camera_sensor_get();
80 // initial sensors are flipped vertically and colors are a bit saturated
81 if (s->id.PID == OV3660_PID) {
82 s->set_vflip(s, 1); // flip it back
83 s->set_brightness(s, 1); // up the brightness just a bit
84 s->set_saturation(s, -2); // lower the saturation
85 }
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.
58 config.frame_size = FRAMESIZE_UXGA;
59 config.jpeg_quality = 10;
60 config.fb_count = 2;
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
Chapter 15 Dog
If you have any concerns, please feel free to contact us via support@freenove.com
Environment Installation
Install python3
Download and install Python3 package.
https://www.python.org/downloads/release/python-381/
Choose the one matching to your computer version to download and install.
Please note that “Add Python 3.8. to PATH” MUST be check.
Here you can select the installation path of Python. We install it at D drive. If you are a novice, you can select
the default path.
Type cmd in the address bar and press Enter. If you are on a Linux or Mac computer, you can use the terminal
to enter the file directory.
Sketch
Sketch_10_Dog
Upload the sketch to esp32 and you can control the robot dog to make any action as shown in Chapter 3.
Please note: If your robot dog has not been calibrated, please navigate back to Chapter 2 to calibrate the
robot dog first.
27 if (!cs.isCameraNormal) {
28 setMelodyToQueue(MELODY_CAM_FAILURE);
29 }
30 setMelodyToQueue(MELODY_POWER_UP);
31 standUp();
32 }
33
34 void loop() {
35 task_CommandService(NULL);
36 task_BleUploadService(NULL);
37 task_showBuiltInLed(NULL);
38 vTaskDelay(20);
39 static uint32_t lastT = 0;
40 if (millis() - lastT > 1000) {
41 // Serial.printf("Total heap: %d\r\n", ESP.getHeapSize());
42 // Serial.printf("Free heap: %d\r\n", ESP.getFreeHeap());
43 lastT = millis();
44 }
45 }
46
47 void loopSecondary(void *pvParameters) {
48 while (1) {
49 task_BatteryPowerListener(NULL);
50 task_showRGBLeds(NULL);
51 task_AutoWalking(NULL);
52 task_BuzzerService(NULL);
53
54 task_TouchPad(NULL);
55 vTaskDelay(50);
56 }
57 vTaskDelete(xTaskGetCurrentTaskHandle());
58 }
59
60 void serialEventRun() {
61 static String serialInputString = "";
62 while (Serial.available()) {
63 char inChar = (char)Serial.read();
64 serialInputString += inChar;
65 if (inChar == '\n') {
66 enterMessageQueue(serialInputString);
67 serialInputString = "";
68 }
69 }
70 }
71
72 void onBleReceived(BLECharacteristic *pCharacteristic) {
73 std::string rxValue = pCharacteristic->getValue();
74 static String bleInputString = "";
75 if (rxValue.length() > 0) {
76 for (int i = 0; i < rxValue.length(); i++) {
77 bleInputString += rxValue[i];
78 if (rxValue[i] == '\n') {
79 enterMessageQueue(bleInputString);
80 bleInputString = "";
81 }
82 }
83 }
84 }
85
86 void onWiFiCmdReceived(WiFiClient *client) {
87 static String wifiInputString = "";
88 while (client->available()) {
89 char rv[1024];
90 int ret = client->read((uint8_t *)rv, sizeof(rv));
91 for (int i = 0; i < ret; i++) {
92 wifiInputString += rv[i];
93 if (rv[i] == '\n') {
94 Serial.print(wifiInputString);
95 enterMessageQueue(wifiInputString);
96 wifiInputString = "";
97 }
98 }
99 }
100 }
101
102 void onWiFiCmdTrasmit(WiFiClient *client) {
103 if (!mqTx.isEmpty()) {
104 client->write(mqTx.out().c_str());
105 }
106 }
107
108 void enterMessageQueue(String msg) {
109 Serial.print("msg : ");
110 Serial.print(msg);
111 switch (msg.charAt(0)) {
112 case ACTION_INSTALLATION:
113 case ACTION_CALIBRATE:
114 case ACTION_UP_DOWN:
69 }
70 }
Receive commands by BLE.
72 void onBleReceived(BLECharacteristic *pCharacteristic) {
73 std::string rxValue = pCharacteristic->getValue();
74 static String bleInputString = "";
75 if (rxValue.length() > 0) {
76 for (int i = 0; i < rxValue.length(); i++) {
77 bleInputString += rxValue[i];
78 if (rxValue[i] == '\n') {
79 enterMessageQueue(bleInputString);
80 bleInputString = "";
81 }
82 }
83 }
84 }
Receive commands by WiFi.
86 void onWiFiCmdReceived(WiFiClient *client) {
87 static String wifiInputString = "";
88 while (client->available()) {
89 char rv[1024];
90 int ret = client->read((uint8_t *)rv, sizeof(rv));
91 for (int i = 0; i < ret; i++) {
92 wifiInputString += rv[i];
93 if (rv[i] == '\n') {
94 Serial.print(wifiInputString);
95 enterMessageQueue(wifiInputString);
96 wifiInputString = "";
97 }
98 }
99 }
100 }
Divide the commands into robot dog action commands and other commands according to the types and
send them into the corresponding message queue.
108 void enterMessageQueue(String msg) {
109 Serial.print("msg : ");
110 Serial.print(msg);
111 switch (msg.charAt(0)) {
112 case ACTION_INSTALLATION:
113 case ACTION_CALIBRATE:
114 case ACTION_UP_DOWN:
115 case ACTION_BODY_HEIGHT:
116 case ACTION_MOVE_ANY:
117 case ACTION_TWIST:
Development
Code Repository
The main purpose of this tutorial is to explain how to assemble and use the robot dog. If you want to learn
more about the code, please visit:
https://github.com/Freenove/Freenove_ESP32_Dog_Firmware
There is a more detailed explanation of the code in the code repository, please download and learn by yourself.
Communication Command
If you do not want to understand the underlying code of the robot dog, but want to develop a control
platform software for the robot dog, you can refer to the following communication commands, which
explain each control command of the robot dog in detail.
Ways of Communication
The robot support three ways of communication, namely, serial port, Bluetooth Low Energy (BLE) and TCP
Socket communication, as follows:
Ways Description
Serial Port Baud rate 115200
BLE Bluetooth GATT
TCP Socket Port 5000 is the command transmission port, and port 8000 is the video transmission
port.
Note: All commands are valid once they are sent. It is recommended not to send too many commands
repeatedly in a short period as the processing capacity of the robot dog is limited. All commands only need
to be sent once.
1. Each command consists of four parts: command word, delimiter, parameter and terminator, among
which, the number of command word is one and the parameters is variable, from 0 to n, depending on
the specific command.
A. The first character of each command is the command word, used to distinguish the major category
of the command, such as "A".
B. The character "#" is the delimiter between the command word and the parameter, used to separate
the string.
C. Each command is terminated with "\n", which is used to separate each command.
Example: “A#10#20#30#40#50#\n”
2. Parse of Commands
Need support? support@freenove.com
150 Development www.freenove.com █
When parsing commands, first separate the commands with "\n", and then separate the command word
and parameters of each command with“#”. The characters after "\n" are divided to the next command for
parsing.
Command Words
ACTION_UP_DOWN
Control the robot to stand up or lie down with one parameter. When lying down, the servos will be unloaded
to reduce battery power consumption
App command Action
A#0#\n Switch between standing up and lying down
A#1#\n Stand up
A#2#\n Lie down
No return,
ACTION_BODY_HEIGHT
Set the robot dog's body to any height. This function has not been added to the app yet, but the robot dog
can receive this command.
App command Action
B#50#\n Make the robot stand up and set the height to 50 cm.
ACTION_RGB
Set the running mode and color of the LEDs on the robot dog.
App command Action
C#mode#red#green#blue#\n Set the RGB LEDs to “mode” mode and specify the color values of
the three channels(0-255)
C#1#255#0#0#\n
The value range and meaning of #define LED_MODE_OFF 0
mode, among which, in modes 2 and #define LED_MODE_RGB 1
5, the color cannot be changed. The #define LED_MODE_FOLLOWING 2
parameters can be any value in the #define LED_MODE_BLINK 3
range of 0-255. #define LED_MODE_BREATHING 4
#define LED_MODE_RAINBOW 5
Introduction to “mode” function
Macro Definition Parameter Description
LED_MODE_OFF 0 Turn OFF LEDs
LED_MODE_RGB 1 Static LEDs display. Color and brightness can be adjusted through
the parameters.
LED_MODE_FOLLOWING 2 The LEDs alternately display four colors of red, green, yellow and
blue.
LED_MODE_BLINK 3 LEDs blink. Color and brightness can be adjusted through the
parameters.
LED_MODE_BREATHING 4 LEDs ON and OFF like breathing. Color and brightness can be
adjusted through the parameters.
LED_MODE_RAINBOW 5 LEDs show the color of rainbow and change slowly.
ACTION_BUZZER
Set the frequency of the buzzer.
App command Action
D#freq#\n “freq” refers to the frequency of the buzzer.
D#2000#\n Make the buzzer sound at the frequency of 2000
D#0#\n Stop the buzzer.
ACTION_TWIST
Make the robot twist itself.
App command Action
E#pitch#roll#yaw#\n
E#20#0#0#\n The robot is tilted by 20 degrees in the pitch direction.
E#10#10#10#\n The robot is tilted by 10 degrees in three directions.
Unit: degree, ranging from 0 to 20 degrees.
ACTION_MOVE_ANY
F#alpha#stepLength#gama#spd#\n
Make the robot move sideways for alpha degrees counterclockwise in its forward direction while rotating
alpha degrees at each step, with the step length of stepLength and the speed of spd.
/**
* @brief The command for walking, in any direction, at any step length and any
speed, with any rotation angle.
*
* @param alpha The moving direction, with the x-axis direction as 0 degrees,
counterclockwise as positive and clockwise as negative. Unit: degree [0-360]. The x-
direction means moving forward .
* @param stepLength The length of each step (<=20)
* @param gama The rotation angle. Rotate in place with Rotate in place, with
counterclockwise as positive and clockwise as negative, and the unit is degrees. [0-
360].
* @param spd The moving speed. Unit: mm / 10ms [1, 8]
*/
App command Action
F#0#20#0#5#\n Moving forward at the speed of 5 and step length of 20mm.
F#90#10#-10#5#\n The robot moves sideways to the left while rotating 10 degrees to
the right at each step, with a step length of 10 and speed of 5.
F#0#0#0#5#\n Stop moving
This command also only needs to be sent once. Once commanded, the robot keeps walking until it receives
a new command, such as a command to stop walking or to twist its body.
ACTION_CAMERA
This is the command sent to the app to determine whether the camera is malfunctioned. The phone app
receives and parses the command.
Robot command Action
ACTION_ULTRASONIC
Once the obstacle avoidance mode is turned ON, the robot will actively send the current distance measured
by the ultrasonic wave to the app and the app needs to parse this command.
The App can also actively send this command for the robot dog to print out the distance measured by the
ultrasonic wave through the serial port. Note that the command does not contain parameters, and there is
currently no Action.
App command Action
The robot obtains the distance measured by the ultrasonic module
H#\n
once, and prints it out through serial port.
ACTION_GET_VOLTAGE
The robot actively sends the current voltage value and battery percentage to the app every 3 seconds without
the need of the app to inquire.
The unit of voltage is mV.
Robot command Action
I#voltage#percent#\n “voltage” refers to the current voltage of the batteries, and
“percent” is the battery percentage.
I#8400#100%\nI The current voltage is 8400mV, 100%.
ACTION_CALIBRATE
Calibrate the robot. This command must contain only five parameters.
Parameters Action
J#legn#SSC#x#y#z#\n
Legn Leg number, numbered counterclockwise from left front to right
front, 0,1,2,3
S:Select 1: Set the position of the legs without overlaying calibration
S:Set information.
C:Confirm 2: Confirm the calibration information.
3: Select one leg to calibrate.
x、y、z They refer to the coordinates of the tiptoe of the robot dog, with
the calibration point as the relative value of the origin. If the leg
does not need calibration, then it is 0 0 0.
Examples:
App command Action
J#2#3#0#0#0#\n Leg 2 is selected to calibrate and the other legs are unloaded to
prevent interference.
J#2#1#10#20#-10#\n Set leg 2 to the relative position of 10 20 -10
J#2#2#10#20#-10#\n Confirm and save the calibration information of 10 20 -20 to the
robot.
ACTION_SET_NVS
Save data. This command is a debug command without the need to be sent by the app.
App command Action
K#1#\n Save the mode and color of the LEDs
K#2#\n Clear all data in NVS.
ACTION_INSTALLATION
Put the robot into an installation or calibration pose.
App command Action
L#1#\n Put the robot in the installation pose, and place all servos at 90
degrees
L#2#\n Put the robot in the calibration pose without overlaying the
calibration information.
ACTION_AUTO_WALKING
Put the robot into automatic obstacle avoidance mode.
App command Action
M#0#\n Turn OFF obstacle avoidance mode.
M#1#\n Turn ON obstacle avoidance mode.
ACTION_NETWORK
The robot’s network related commands.
App sending
App command Action
N#0#\n The robot starts to scan WIFI and returns the results one by one in
the following form:
N#0#SSID#\n
N#1#ssid#psd#\n The robot uses the password psd to connect to the WIFI hotspot
named SSID and returns the result:
Success: N#103#\n
Failure: N#104#\n
Later, regardless of success or failure, the WIFI status is sent again.
(see the robot sending below)
N#2#\n Disconnect the robot’s WIFI connection, and then send the WIFI
status.
N#3#\n Establish a WIFI hotspot on the robot with the SSID as
"FreenoveDog-RobotId” and the password as 12345678. Without
this it will not success, The following results will be returned:
N#301#AP_SSID#IP#Password#\n
The above parameters are hotspot name, robot IP address and
hotspot password respectively.
N#4#\n Turn OFF the robot’s hotspot.
N#5#\n Obtain the robot WIFI and camera status and return them once.
Robot sending:
Robot command Action
N#0#SSID#\n Return the robot’s WIFI scanning results one by one.
N#101#SSID#IP#\n Robot’s WIFI status: WIFI is connected. The parameters are the WIFI
SSID and IP address of the robot in STA mode
N#102#\n Robot’s WIFI status: WIFI is not connected.
N#103#\n The robot connects to WIFI successfully.
N#104#\n The robot fails to connect to WIFI.
N#301#AP_SSID#IP#Password#\n The robot’s WIFI status: AP has been established. The parameters are
the robot’s WIFI SSID, IP address and password in AP mode.
N#302#\n The robot’s WIFI hotspot has been turned OFF.
N#5#\n Obtain the robot WIFI and camera status and return them once.
ACTION_DANCING
Make the robot dance at some fixed actions.
App command Action
O#n#\n n refers to the fixed action modes.
O#0#\n Say hello
O#1#\n Push up
O#2#\n Stretch itself
O#3#\n Turn around
O#4#\n Sit down
O#5#\n Dance
The value and meanings of parameter n are as follows
#define DANCE_SAY_HELLO 0
#define DANCE_PUSH_UP 1
#define DANCE_STRETCH_SELF 2
#define DANCE_TURN_AROUND 3
#define DANCE_SIT_DOWN 4
#define DANCE_DANCING 5
ACTION_SET_ROBOT
Reserved.
ACTION_TEST
Reserved. Develop to use.
ID_CHECK
Check the basic information of the robot, which is used for verification in the future.
App command Action
W#0#\n Obtain the firmware version and robot name. The result returned are as follows:
W#0#100#FREENOVE-DOG#\n
among which,
100 refers to the version of V1.0.0 and the name of FREENOVE-DOG.
W#1#\n Obtain the robot’s firmware version with the result returned as follows:
W#1#100#\n
among which,
100 refers to the version of V1.0.0
W#2#\n Obtain the robot’s name with the result returned as follows:
W#2#FREENOVE-DOG#\n
referring to the name as FREENOVE-DOG
W#3#\n Obtain the internal code with the current result returned as follows
W#3#FNK006201#\n
W#4#FREENOVE#\n Fixed command to check whether the source of the controller is valid.
What's Next?
THANK YOU for participating in this learning experience!
We have reached the end of this Tutorial. If you find errors, omissions or you have suggestions and/or
questions about the Tutorial or component contents of this Kit, please feel free to contact us:
support@freenove.com
We will make every effort to make changes and correct errors as soon as feasibly possible and publish a
revised version.
If you want to learn more about Arduino, Raspberry Pi, Smart Cars, Robotics and other interesting products
in science and technology, please continue to visit our website. We will continue to launch fun, cost-effective,
innovative and exciting products.
http://www.freenove.com/