Espressif Docs Readthedocs Hosted Com Espressif Esp Drone en Latest
Espressif Docs Readthedocs Hosted Com Espressif Esp Drone en Latest
1 Get Started 3
1.1 ESP-Drone Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 ESP-IDF Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 Crazyflie Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.4 Preparations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.5 ESP-Drone APP Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.6 PC cfclient Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.7 Propeller Direction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.8 Preflight Check . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3 Develop Guide 23
3.1 Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.2 Flight Control System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.3 Communication Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
3.4 Hardware Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
4 Third-Party Codes 79
5 Acknowledgement 81
i
ii
ESP-Drone
[ ]
ESP-Drone is an open source drone solution based on Espressif ESP32/ESP32-S2 Wi-Fi chip, which can be controlled
over a Wi-Fi network using a mobile APP or gamepad. ESP-Drone supports multiple flight modes, including Stabilize
mode, Height-hold mode, and Position-hold mode. With simple hardware, clear and extensible code architecture,
ESP-Drone can be used in STEAM education and other fields. The main code is ported from Crazyflie open source
project with GPL3.0 protocol.
This document describes the development guide for ESP-Drone project.
CONTENTS 1
ESP-Drone
2 CONTENTS
CHAPTER
ONE
GET STARTED
[ ]
ESP-Drone is an ESP32/ESP32-S2 based flying development board provided by Espressif. ESP-Drone is equipped with
Wi-Fi key features, which allows this drone to be connected to and controlled by an APP or a gamepad over a Wi-Fi
network. This drone comes with simple-structured hardware, clear codes, and supports functional extension. Therefore,
ESP-Drone can be used in STEAM education. Part of the codes is from Crazyflie open source project under GPL3.0
license.
Fig. 1: ESP-Drone
3
ESP-Drone
Fig. 2: A swarm of drones exploring the environment, avoiding obstacles and each other. (Guus Schoonewille, TU Delft)
1.4 Preparations
For iOS, please search and download the ESP-Drone APP in App Store.
iOS APP source code: ESP-Drone-iOS
Android APP source code: ESP-Drone-Android
1.2 Navigate to the source code directory, and install the requirements
pip3 install -e .
2. Install cfclient
2.1 Download the source code
2.2 Navigate to the source code directory, and install the requirements
pip3 install -e .
python3 ./bin/cfclient
1.4. Preparations 7
ESP-Drone
• Scan Wi-Fi AP on your mobile. ESP-Drone device works as a Wi-Fi AP with the following SSID:
In this step, you can customize the flight settings according to your application scenarios, or use the default configuration
below.
```
Default configuration:
• Click “Connect” button/icon at your APP. When the connection is established successfully between your drone and
APP, the LED on the drone blinks GREEN.
• Slide “Thrust” slightly to take off the drone.
• Control the flight by moving your fingers on the APP.
Cfclient is the PC client for Crazeflie source project, which has fully implemented the functions defined in CRTP
and makes the drone debugging faster. ESP-Drone customizes this cfclient to meet functional design needs.
In this project, we have configuration files and cache files. JSON file is used to store configuration information. For more
information about the configuration, please refer to User Configuration File.
3. Trim
• Roll Trim: trim the rotation around a horizontal axis going through the drone from back to front. This rotation
literally rolls the drone and moves it left and right. Roll trim is used to compensate for the level installation
deviation of sensors.
• Pitch Trim: trim the rotation around a horizontal axis going through the drone from left to right. This rotation
tilts the drone and moves it forwards or backwards. Pitch trim is used to compensate for the level installation
deviation of sensors.
Note that in assisted mode, the thrust controller works as a height controller.
1. Max angle: set the maximum pitch and roll rotation: roll/pitch.
2. Max yaw rate: set the allowed yaw: yaw.
3. Max thrust: set the maximum thrust.
4. Min thrust: set the minimum thrust.
5. Slew limit: prevent sudden drop of thrust. When the thrust drops below this limit, the rates below Slew rate
will not be allowed.
6. Slew rate: this is the maximum rate when the thrust is below slew limit.
Flight Data
On the tab “Flight Control” of cfclient, you can check the drone status. The detailed information is shown at the bottom
right, including:
1. Target: target angle
2. Actual: measured angle
3. Thrust: current thrust value
4. M1/M2/M3/M4: actual output of motors
Configure the parameters to monitor at Tab Log configuration and Tab Log Blocks:
Configure real-time waveform drawing at Tab Plotter, to monitor gyro accelerometer data.
• Place the drone with its head on the front, and its tail (i.e. the antenna part) at the back.
• Place the drone on a level surface and power it up when the drone stays still.
• Check on the cfclient if the drone is placed level.
• After the communication is established, check if the LED at the drone tail blinks GREEN fast.
• Check if the LED on the drone head blinks RED, which indicates battery LOW.
• Slide forward the Trust controller slightly at the left side of your APP (i.e. the commands controlled by your left
finger), to check if the drone can respond the command quickly.
• Move your finger at the right command area of the APP (i.e. the commands controlled by your right finger), to
check if the direction control works well.
• Go fly and have fun!
TWO
[ ]
Please refer to ESP-IDF Programming Guide and set up ESP-IDF environmnet step by step.
• ESP-IDF branch release /v4.2 is suggested.
• Please follow and complete all setup steps.
• Build a example of ESP-IDF to make sure the setup is successful.
The above code can place variables with .param.* or .log.* segment attributes at continuous storage area so as to
speed up variable traversal.
19
ESP-Drone
The project software mainly consists of a flight control kernel, hardware drivers, and dependency libraries:
• The flight control kernel is from Crazyflie, mainly including hardware abstraction layer and flight control program.
• Hardware drivers are structured in files according to hardware interfaces, including I2C devcies and SPI devices.
• Dependency libraries include the default components provided by ESP-IDF, as well as DSP from third parties.
The code file structure is as follows:
.
├── components | project components directory
│ ├── config | system task configuration
│ │ └── include
│ ├── core | system kernel directory
│ │ └── crazyflie | Crazyflie kernel
│ │ ├── hal | hardware abstraction code
│ │ └── modules | flight control code
│ ├── drivers | hardware driver directory
│ │ ├── deck | hardware extention interface driver
(continues on next page)
#ifdef SENSOR_INCLUDED_BMI088_SPI_BMP388
SensorImplementation_bmi088_spi_bmp388,
(continues on next page)
#ifdef SENSOR_INCLUDED_MPU9250_LPS25H
SensorImplementation_mpu9250_lps25h,
#endif
#ifdef SENSOR_INCLUDED_MPU6050_HMC5883L_MS5611
SensorImplementation_mpu6050_HMC5883L_MS5611,
#endif
#ifdef SENSOR_INCLUDED_BOSCH
SensorImplementation_bosch,
#endif
SensorImplementation_COUNT,
} SensorImplementation_t;
struct cppmEmuPacket_s {
struct {
uint8_t numAuxChannels : 4; // Set to 0 through MAX_AUX_RC_CHANNELS
uint8_t reserved : 4;
} hdr;
uint16_t channelRoll;
uint16_t channelPitch;
uint16_t channelYaw;
uint16_t channelThrust;
uint16_t channelAux[MAX_AUX_RC_CHANNELS];
} __attribute__((packed));
The purpose of __attribute__ ((packed)) is to disable the optimized alignment when compiling struct. By
such way, struct is aligned based on its actual bytes. This is a syntax specific to GCC, which has nothing to do with
your operating system but has to do with compiler. In Windows operating system, GCC and VC compiler do not support
packed mode while TC compiler supports such mode.
THREE
DEVELOP GUIDE
[ ]
3.1 Drivers
[ ]
This section covers I2C drivers and SPI drivers used in ESP-Drone.
I2C drivers include MPU6050 sensor driver and VL53LXX sensor driver. The following part describes the two sensors
in their main features, key registers and programming notes, etc.
MPU6050 Sensor
Overview
The MPU6050 is a 6-axis Motion Tracking device that combines a 3-axis gyroscope, a 3-axis accelerometer, and a Digital
Motion Processor (DMP).
How It Works
• Gyroscope: vibration occurs due to Coriolis effect when the gyroscope rotates around any sensing axis. Such
vibration can be detected by a capacitive sensor. This capacitive sensor can amplify, demodulate, and filter such
vibration signal, then generate a voltage proportional to the angular velocity.
• Accelerometer: when displacement accelerates along a specific axis over the corresponding detection mass, the
capacitive sensor detects a change in capacitance.
23
ESP-Drone
Measure Range
• Gyroscope full-scale range: ±250 °/sec, ±500 °/sec, ±1000 °/sec, ±2000 °/sec
• Accelerometer full-scale range: ±2 g, ±4 g, ±8 g, ±16 g
• MPU6050 has an auxiliary I2C bus for communication with external 3-Axis magnetometer or other sensors.
• The AUX I2C interface supports two operation modes: I2C Master mode or Pass-Through mode.
MPU6050 FIFO
The MPU6050 contains a 1024-byte FIFO register that is accessible via the Serial Interface. The FIFO configuration
register determines which data is written into the FIFO. Possible choices include gyroscope data, accelerometer data,
temperature readings, auxiliary sensor readings, and FSYNC input.
The MPU6050 has its own low-pass filter. Users can configure Register 26 CONFIG - Configure DLPF to control band-
width, to lower high-frequency interference, but the configuration may reduce sensor input rate. Enable the DLPF:
accelerometer outputs 1 kHz signal; disable the DLPF: accelerometer outputs 8 kHz signal.
The field EXT_SYNC_SET in Register 26 is used to configure the external Frame Synchronization (FSYNC) pin sam-
pling.
• The MPU6050 has its own DMP inside, which can be used to calculate quaternion to offload processing power
from the main CPU.
• The DMP can trigger an interrupt via a pin.
MPU6050 Orientation
3.1. Drivers 25
ESP-Drone
MPU6050 Initialization
Bits [6:1] store the device address, and default to 0x68. The value of the AD0 pin is not reflected in this register.
• DEVICE_RESET: if this bit is set, the register will use the default value.
• SLEEP: if this bit is set, MPU6050 will be put into sleep mode.
• CYCLE: when this bit (CYCLE) is set to 1 while SLEEP is disabled, the MPU6050 will be put into Cycle mode.
In Cycle mode, the MPU6050 cycles between sleep mode and waking up to take a single sample of data from active
sensors at a rate determined by LP_WAKE_CTRL (Register 108).
The DLPF is configured by DLPF_CFG. The accelerometer and gyroscope are filtered according to the value of
DLPF_CFG as shown in the table below.
3.1. Drivers 27
ESP-Drone
Users can configure the full-scale range for the accelerometer according to the table below.
The register specifies the divider from the gyroscope output rate used to generate the Sample Rate for the MPU6050. The
sensor register output, FIFO output, and DMP sampling are all based on the Sample Rate. The Sample Rate is generated
by dividing the gyroscope output rate by (1 + SMPLRT_DIV).
Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)
Gyroscope Output Rate = 8 kHz when the DLPF is disabled (DLPF_CFG = 0 0r 7), and 1 kHz when the DLPF is enabled
(see Register 26). Note: if SMPLRT_DIV is set to 7 when the DLPF is disabled, the chip can generate an interrupt signal
of 1 kHz.
3.1. Drivers 29
ESP-Drone
• Save data in big-endian: higher data bits are stored at low address, and lower bits at high address.
• Save data in complement: the measurement value is a signed integer, so it can be stored in complement.
VL53LXX Sensor
Overview
VL53L1X is a Time-of-Flight ranging and gesture detection sensor provided by ST.
How It Works
The VL53L0X/VL53L1X chip is internally integrated with a laser transmitter and a SPAD infrared receiver. By de-
tecting the time difference between photon sending and receiving, the chip calculates the flight distance of photons, and
Fig. 3: VL53LXX
the maximum measuring distance can reach two meters, which is suitable for short- and medium-range measurement
applications.
Measurement Area - Region-of-Interest (ROI)
The VL53L0X/VL53L1X measures the shortest distance in the measurement area, which can be zoomed in or out de-
pending on actual scenario. But a large detection range may cause fluctuations in the measurement.
For more information about configuration on measurement area, see the sections 2.4 Ranging Description and 2.8 Sensing
Array Optical Center in VL53LXX Datasheet.
Fig. 4: ROI
Measure Distance
• The VL53L0X sensor has a blind spot of 3 ~ 4 cm, with an effective measurement range of 3 ~ 200 cm and an
accuracy of ±3%.
• The VL53L1X is an upgraded version of the VL53L0X with a detection distance of up to 400 cm.
3.1. Drivers 31
ESP-Drone
• VL53LXX measurement distance/performance is related to the environment. The detection distance is farther
in the dark conditions. But in outdoor bright conditions, the laser sensor may be subject to a lot of interference,
resulting in reduced measurement accuracy. For such reason, the height should be set based on the outdoor air
pressure.
Measurement Frequency
• The VL53L0X ranging frequency is up to 50 Hz, with a measurement error of ±5%.
• The VL53L1X I2C has a maximum clock frequency of 400 kHz, and the pull-up resistor needs to be selected based
on voltage and bus capacitance values. For more information, see VL53LXX Datasheet.
• XSHUT, input pin for mode selection (sleep), must always be driven to avoid leakage current. A pull-up resistor is
needed.
• GPIO1, interrupt output pin for measuring dataready interrupts.
Work Mode
By setting the level of the XSHUT pin, the sensor can be switched into HW Standby mode or SW Standby mode for
conditional boot and for lowering the standby power consumption. If the host gives up the management of sensor modes,
the XSHUT pin can be set to pull up by default.
• HW Standby: XSHUT pulls down and the sensor power is off.
• SW Standby: XSHUT pulls up, then the sensor enters Boot and SW Standby modes.
Fig. 5: VL53L1X
Fig. 6: HW Standby
3.1. Drivers 33
ESP-Drone
Fig. 7: SW Standby
VL53LXX Initialization
Note: except the step VL53L1_SetUserROI, the other initialization steps can not be skipped.
The ranging can be done in two kinds of modes: polling mode and interrupt mode.
Polling Mode Workflow
Note:
• Each time when the measurement and value reading are done, clear the interrupt flag using
VL53L1_ClearInterruptAndStartMeasurement, and then start the measurement again.
• Polling mode provides two methods as shown in the figure above: Drivers polloing mode and Host polling mode.
We take the Drivers polling mode as an example.
if(!status) {
status = VL53L1_GetRangingMeasurementData(Dev, &RangingData); //␣
,→Get a single measurement data
if(status==0) {
if (roi & 1) {
left = RangingData.RangeMilliMeter;
printf("L %3.1f R %3.1f\n", right/10.0, left/10.0);
} else
right = RangingData.RangeMilliMeter;
}
if (++roi & 1) {
status = VL53L1_SetUserROI(Dev, &Roi1);
(continues on next page)
3.1. Drivers 35
ESP-Drone
}
}
while (1);
}
// return status;
}
If a mask is installed over the sensor receiver, or if the sensor is mounted behind a transparent cover, the sensor needs
to be calibrated due to changes in the transmission rate. You can write a calibration program and call APIs based on the
calibration process, or you can measure the calibration value directly using the official PC GUI.
Use Official APIs to Write Calibration Program
Calibration process is shown below. The order of calls should be exactly the same.
/* VL53L1 Module Calibration*/
static VL53L1_CalibrationData_t vl53l1_calibration(VL53L1_Dev_t *dev)
{
int status;
int32_t targetDistanceMilliMeter = 703;
VL53L1_CalibrationData_t calibrationData;
status = VL53L1_WaitDeviceBooted(dev);
(continues on next page)
3.1. Drivers 37
ESP-Drone
status = VL53L1_SetPresetMode(dev,VL53L1_PRESETMODE_AUTONOMOUS);
status = VL53L1_PerformRefSpadManagement(dev);
status = VL53L1_PerformOffsetCalibration(dev,targetDistanceMilliMeter);
status = VL53L1_PerformSingleTargetXTalkCalibration(dev,targetDistanceMilliMeter);
status = VL53L1_GetCalibrationData(dev,&calibrationData);
if (status)
{
ESP_LOGE(TAG, "vl53l1_calibration failed \n");
calibrationData.struct_version = 0;
return calibrationData;
}else
{
ESP_LOGI(TAG, "vl53l1_calibration done ! version = %u \n",calibrationData.
,→struct_version);
return calibrationData;
}
VL53L1X Example
Example Description
• Implementation: VL53L1X detects the height changes (last for 1 second) and the red light turns on. Height returns
to normal value (last for 1 second), and the green light turns on.
• Parameters: set the I2C number, port number, LED port number via make menuconfig.
• Example analysis can be found in code notes and user manual.
Notes
• This example applies only to VL53L1X, not to its older version hardware VL53L0X.
• According to STM document, the measurement distance is 400 cm in dark environment. In indoor environment,
the measurement distance can be 10 to 260 cm.
• Some of the parameters in the initialization function vl53l1\_init (VL53L1\_Dev\_t \*) need to be
determined according to the actual usage environment, and there is room for optimization.
• Make sure the sensor is installed right above the detection position.
3.1. Drivers 39
ESP-Drone
• Base height is automatically calibrated when the module is powered on. If the base height changes, the parameters
need to be reset again.
Example Repository
Click esp32-vl53l1x-test to check the example, or download the example using git tool:
PMW3901 Sensor
Overview
The PMW3901 is PixArt’s latest high-precision, low-power optical navigation module that provides X-Y motion infor-
mation with a wide range of 8 cm to infinity. The PWM3901 works with an operating current of less than 9 mA, an
operating voltage of VDD (1.8 to 2.1 V), a VDDIO (1.8 to 3.6 V), and uses a 4-wire SPI interface for communication.
Main Parameters
Parameter Value
Supply voltage (V) VDD: 1.8 ~ 2.1 V; VDDIO: 1.8 ~ 3.6 V
Working range (mm) 80 ~ +∞
Interface 4-line SPI @ 2 MHz
Package 28-pin COB package, size: 6 x 6 x 2.28 mm
The sensor works at a low operating voltage and to communicates with the ESP32 at 3.3 V requires different voltages
from VDD and VDDIO.
3.1. Drivers 41
ESP-Drone
Power-Up Sequence
Although PMW3901MB performs an internal power up self-reset, it is still recommended that the Power_Up_Reset
register is written every time power is applied. The appropriate sequence is as follows:
1. Apply power to VDDIO first and followed by VDD, with a delay of no more than 100 ms in between each supply.
Ensure all supplies are stable.
2. Wait for at least 40 ms.
3. Drive NCS high, and then low to reset the SPI port.
4. Write 0x5A to Power_Up_Reset register (or alternatively, toggle the NRESET pin).
5. Wait for at least 1 ms.
6. Read from registers 0x02, 0x03, 0x04, 0x05, and 0x06 one time regardless of the motion pin state.
7. Refer to PWM3901MB Datasheet Section 8.2 Performance Optimization Registers to configure the required reg-
isters to achieve optimum performance of the chip.
Power-Down Sequence
PMW3901MB can be set to Shutdown mode by writing to Shutdown register. The SPI port should not be accessed when
Shutdown mode is asserted, except the power-up command (writing 0x5A to register 0x3A). Other ICs on the same SPI
bus can be accessed, as long as the chip’s NCS pin is not asserted.
To de-assert Shutdown mode:
1. Drive NCS high, and then low to reset the SPI port.
2. Write 0x5A to Power_Up_Reset register (or alternatively, toggle the NRESET pin).
3. Wait for at least 1 ms.
4. Read from registers 0x02, 0x03, 0x04, 0x05, and 0x06 one time regardless of the motion pin state.
5. Refer to PWM3901MB Datasheet Section 8.2 Performance Optimization Registers to configure the required reg-
isters for optimal chip performance.
For more information, see Connected Home Appliances and IoT.
Code Interpretation
Key Structs
typedef struct opFlow_s
{
float pixSum[2]; /*accumulated pixels*/
float pixComp[2]; /*pixel compensation*/
float pixValid[2]; /*valid pixels*/
float pixValidLast[2]; /*last valid pixel*/
float deltaPos[2]; /*displacement between 2 frames, unit: cm*/
float deltaVel[2]; /*velocity, unit: cm/s*/
float posSum[2]; /*accumulated displacement, unit: cm*/
float velLpf[2]; /*low-pass velocity, unit cm/s*/
bool isOpFlowOk; /*optical flow*/
bool isDataValid; /* valid data */
} opFlow_t;
uint8_t observation;
(continues on next page)
3.1. Drivers 43
ESP-Drone
uint8_t squal;
uint8_t rawDataSum;
uint8_t maxRawData;
uint8_t minRawData;
uint16_t shutter;
} __attribute__((packed)) motionBurst_t;
• motion: motion information, can be obtained according to the bits frame detection (frameFrom0), operating mode
(runMode) and motion detection (motionOccured).
• observation: to check if the IC has EFT/B or ESD issues. When the sensor works properly, the value should be
0xBF.
• deltaX and deltaY: the sensor has detected the motion of the image at X and Y directions.
• squal: the quality of motion information, i.e, the credibility of motion information;
• rawDataSum: the sum of raw data, can be used to average the data of a frame.
• maxRawData and minRawData: the maximum and minimum of the raw data;
• shutter: a real-time auto-adjusted value, to ensure that the average motion data remains within the normal operating
range. Shutter can be used together with squal to check whether the motion information is available.
Programming Notes
• If the sensor data is 0 and lasts for 1 second, it indicates that an error occurs. If so, optical flow tasks should be
suspended.
• The sensor lens must be mounted facing down. Due to relative motion, the displacement data collected by the
sensor is opposite to the actual motion direction of the drone.
• Enable position-hold mode only when the height-hold mode test is stable. Accurate height information is used to
determine the relation between image pixels and actual distance.
• Manual test on tilt compensation can remain the sensor output nearly unchanged even when the drone tilts on certain
direction.
• With tilt compensation and motion accumulated pixels, the actual accumulated pixels can be obtained. After several
calculations, you can get:
– Pixel changes between 2 frames = actual accumulated pixels - last actual pixels;
– Displacement changes between 2 frames = Pixel changes between 2 frames x coefficient. Note when the
height is less than 5 cm, the optical flow will stop working, so the coefficient should be set to 0;
– Integrate on the above displacement changes, to obtain the displacement from the four axes to the take-
off point. Differentiate on the above displacement changes, to obtain the instantaneous velocity. Conduct
low-pass operation on velocity, to increase data smoothness. Limit amplitude on velocity, to enhance data
security.
• The position and velocity information of the four axes are obtained through the optical flow, and then:
– The above location and speed information together with the accelerometer (state_estimator.c) can be used to
estimate the position and speed;
– Estimated position and speed are involved in PID operations and can be used for horizontal position control.
Refer to position_pid.c to see how the position ring and speed ring PID are handled.
Finally, horizontal position-hold control can be achieved through the above process.
[ ]
Tasks
The following TASKs are started when the system is operating properly.
• Load: CPU occupancy
• Stack Left: remaining stack space
• Name: task name
• PRI: task priority
TASKs are described as follows:
• PWRMGNT: monitor system voltage
• CMDHL: application layer - process advanced commands based on CRTP protocol
• CRTP-RX: protocol layer - decode CRTP flight protocol
• CRTP-TX: protocol layer - decode CRTP flight protocol
• UDP-RX: transport layer - receive UDP packet
• UDP-TX: Transport Layer - send UDP packet
• WIFILINK: work with CRTP protocol layer and UDP transport layer
• SENSORS: read and pre-process sensor data
• KALMAN: estimate the drone’s status according to sensor data, including the drone’s angle, angular velocity, and
spatial position. This TASK consumes a large amount of CPU resources on the ESP chip and users should be
careful about its priority allocation.
• PARAM: modify variables remotely according to CRTP protocol
• LOG: monitor variables on real-time according to CRTP protocol
• MEM: modify memory remotely according to CRTP protocol
• STABILIZER: self stabilize its thread, and control the process of flight control program
• SYSTEM: control system initialization and self-test process
The priority of system tasks can be configured in components/config/include/config.h. ESP32, for its
dual-core advantage, has more computing resources than ESP32-S2, therefore, its time-consuming KALMAN_TASK can
be set to a higher priority. But if the target is ESP32-S2, please lower the priority of the KALMAN_TASK, otherwise
task watchdog will be triggered due to the failure of releasing enough CPU resources.
//Task priority: the higher the number, the higher the priority.
#define STABILIZER_TASK_PRI 5
#define SENSORS_TASK_PRI 4
#define ADC_TASK_PRI 3
#define FLOW_TASK_PRI 3
#define MULTIRANGER_TASK_PRI 3
#define SYSTEM_TASK_PRI 2
#define CRTP_TX_TASK_PRI 2
#define CRTP_RX_TASK_PRI 2
#define EXTRX_TASK_PRI 2
#define ZRANGER_TASK_PRI 2
#define ZRANGER2_TASK_PRI 2
#define PROXIMITY_TASK_PRI 0
#define PM_TASK_PRI 0
#define USDLOG_TASK_PRI 1
#define USDWRITE_TASK_PRI 0
#define PCA9685_TASK_PRI 2
#define CMD_HIGH_LEVEL_TASK_PRI 2
#define BQ_OSD_TASK_PRI 1
#define GTGPS_DECK_TASK_PRI 1
#define LIGHTHOUSE_TASK_PRI 3
#define LPS_DECK_TASK_PRI 5
#define OA_DECK_TASK_PRI 3
#define UART1_TEST_TASK_PRI 1
#define UART2_TEST_TASK_PRI 1
//if task watchdog triggered, KALMAN_TASK_PRI should set lower or set lower flow␣
,→frequency
#ifdef TARGET_MCU_ESP32
#define KALMAN_TASK_PRI 2
#define LOG_TASK_PRI 1
#define MEM_TASK_PRI 1
#define PARAM_TASK_PRI 1
#else
#define KALMAN_TASK_PRI 1
#define LOG_TASK_PRI 2
#define MEM_TASK_PRI 2
#define PARAM_TASK_PRI 2
(continues on next page)
#define SYSLINK_TASK_PRI 3
#define USBLINK_TASK_PRI 3
#define ACTIVE_MARKER_TASK_PRI 3
#define AI_DECK_TASK_PRI 3
#define UART2_TASK_PRI 3
#define WIFILINK_TASK_PRI 3
#define UDP_TX_TASK_PRI 3
#define UDP_RX_TASK_PRI 3
#define UDP_RX2_TASK_PRI 3
Except the system default enabled tasks, such as Wi-Fi TASK, the task with the highest priority is STABILIZER_TASK,
highlighting the importance of this task. STABILIZER_TASK controls the entire process from sensor data reading,
attitude calculation, target receiving, to final motor power output, and drives the algorithms at each stage.
The sensor driver code can be found in components\drivers. drivers applies a file structure similar to that
used in esp-iot-solution. In such structure, drivers are classified by the bus they belong to, including i2c_devices,
spi_devices, and general. For more information, please refer to Drivers.
typedef struct {
SensorImplementation_t implements;
void (*init)(void);
bool (*test)(void);
bool (*areCalibrated)(void);
bool (*manufacturingTest)(void);
void (*acquire)(sensorData_t *sensors, const uint32_t tick);
void (*waitDataReady)(void);
bool (*readGyro)(Axis3f *gyro);
bool (*readAcc)(Axis3f *acc);
bool (*readMag)(Axis3f *mag);
bool (*readBaro)(baro_t *baro);
void (*setAccMode)(accModes accMode);
void (*dataAvailableCallback)(void);
} sensorsImplementation_t;
#ifdef SENSOR_INCLUDED_MPU6050_HMC5883L_MS5611
{
.implements = SensorImplementation_mpu6050_HMC5883L_MS5611,
.init = sensorsMpu6050Hmc5883lMs5611Init,
.test = sensorsMpu6050Hmc5883lMs5611Test,
.areCalibrated = sensorsMpu6050Hmc5883lMs5611AreCalibrated,
.manufacturingTest = sensorsMpu6050Hmc5883lMs5611ManufacturingTest,
.acquire = sensorsMpu6050Hmc5883lMs5611Acquire,
.waitDataReady = sensorsMpu6050Hmc5883lMs5611WaitDataReady,
.readGyro = sensorsMpu6050Hmc5883lMs5611ReadGyro,
.readAcc = sensorsMpu6050Hmc5883lMs5611ReadAcc,
.readMag = sensorsMpu6050Hmc5883lMs5611ReadMag,
.readBaro = sensorsMpu6050Hmc5883lMs5611ReadBaro,
.setAccMode = sensorsMpu6050Hmc5883lMs5611SetAccMode,
.dataAvailableCallback = nullFunction,
}
#endif
Gyroscope Calibration
Due to large temperature drift, the gyroscope needs to be calibrated before each use, to calculate its reference values
in current environment. ESP-Drone continues the gyroscope calibration scheme provided by Crazyflie 2.0. At the first
power-up, the variance and average at the three axes of the gyroscope are calculated.
The detailed gyroscope calibration is as follows:
1. Store the latest 1024 sets of gyroscope measurements into a ring buffer with a maximum length of 1024.
2. Calculate the variance of the gyroscope output values, to check whether the drone is placed level and gyroscope is
working properly.
3. If Step 2 is OK, calculate the average of the 1024 sets of the gyroscope output values as its calibration value.
Below is the source code for gyroscope base calculation:
/**
* Adds a new value to the variance buffer and if it is full
* replaces the oldest one. Thus a circular buffer.
*/
static void sensorsAddBiasValue(BiasObj* bias, int16_t x, int16_t y, int16_t z)
{
bias->bufHead->x = x;
bias->bufHead->y = y;
bias->bufHead->z = z;
bias->bufHead++;
/**
* Checks if the variances is below the predefined thresholds.
(continues on next page)
if (bias->isBufferFilled)
{
sensorsCalculateVarianceAndMean(bias, &bias->variance, &bias->mean);
return foundBias;
}
Accelerometer Calibration
The values of g are generally different at various latitudes and altitudes of the Earth, so an accelerometer is required to
measure the actual g. The accelerometer calibration scheme provided by Crazyflie 2.0 can be your reference, and its
g-value calibration process is as follows:
1. Once the gyroscope calibration is complete, the accelerometer calibration is performed immediately.
2. Store 200 sets of accelerometer measurements to the Buffer.
3. Calculate the value of g at rest by synthesizing the weight of g on three axes.
For more information, see g Values at Various Latitudes and Altitudes.
Calculate g values at rest
/**
* Calculates accelerometer scale out of SENSORS_ACC_SCALE_SAMPLES samples. Should be␣
,→called when
* platform is stable.
*/
static bool processAccScale(int16_t ax, int16_t ay, int16_t az)
{
static bool accBiasFound = false;
static uint32_t accScaleSumCount = 0;
if (!accBiasFound)
{
accScaleSum += sqrtf(powf(ax * SENSORS_G_PER_LSB_CFG, 2) + powf(ay * SENSORS_
,→G_PER_LSB_CFG, 2) + powf(az * SENSORS_G_PER_LSB_CFG, 2));
accScaleSumCount++;
if (accScaleSumCount == SENSORS_ACC_SCALE_SAMPLES)
{
accScale = accScaleSum / SENSORS_ACC_SCALE_SAMPLES;
accBiasFound = true;
}
}
return accBiasFound;
}
Ideally, the accelerometer is installed horizontally on the drone, allowing the 0 position to be used as the drone’s horizontal
surface. However, due to the inevitable inclination of the accelerometer when installed, the flight control system can
not estimate the horizontal position accurately, resulting in the drone flying in a certain direction. Therefore, a certain
calibration strategy needs to be set to balance this error.
1. Place the drone on a horizontal surface, and calculate cosRoll, sinRoll, cosPitch, and sinPitch. Ide-
ally, cosRoll and cosPitch are 1. sinPitch and sinRoll are 0. If the accelerometer is not installed
horizontally, sinPitch and sinRoll are not 0. cosRoll and cosPitch are not 1.
2. Store the cosRoll, sinRoll, cosPitch, and sinPitch obtained in Step 1, or the corresponding Roll
and Pitch to the drone for calibration.
Use the calibration value to trim accelerometer measurements:
/**
* Compensate for a miss-aligned accelerometer. It uses the trim
* data gathered from the UI and written in the config-block to
* rotate the accelerometer to be aligned with gravity.
*/
static void sensorsAccAlignToGravity(Axis3f *in, Axis3f *out)
{
//TODO: need cosPitch calculate firstly
(continues on next page)
out->x = ry.x;
out->y = ry.y;
out->z = ry.z;
}
The above process can be deduced via the resolution of a force and Pythagorean Theorem.
• Complementary filtering
• Kalman filtering
Attitude calculation used in ESP-Drone is from Crazyflie. ESP-Drone firmware has been tested for complementary
filtering and Kalman filtering to efficiently calculate flight attitudes, including the angle, angular velocity, and spatial
position, providing a reliable state input for the control system. Note that in position-hold mode, you must switch to
Kalman filtering algorithm to ensure proper operation.
Crazyflie Status Estimation can be found in State estimation: To be or not to be!
Complementary Filtering
Kalman Filtering
Supported Controller
The control system code used in ESP-Drone is from Crazyflie, and continues all its algorithms. Please note that ESP-
Drone has only tested and tuned the parameters for PID controller. When using other controllers, tune your parameters
while ensuring safety.
For more information, please refer to Out of Control.
In the code, you can modify the input parameters of controllerInit(ControllerType controller) to
switch the controller.
Customized controllers can also be added by implementing the following controller interfaces.
};
PID Controller
Implementation Code
void controllerPid(control_t *control, setpoint_t *setpoint,
const sensorData_t *sensors,
const state_t *state,
const uint32_t tick)
{
if (RATE_DO_EXECUTE(ATTITUDE_RATE, tick)) { // This macro controls PID calculation␣
,→frequency based on the interrupts triggered by MPU6050
if (RATE_DO_EXECUTE(POSITION_RATE, tick)) { ␣
,→ //Position control
positionController(&actuatorThrust, &attitudeDesired, setpoint, state);
}
if (RATE_DO_EXECUTE(ATTITUDE_RATE, tick)) {
// Switch between manual and automatic position control
if (setpoint->mode.z == modeDisable) {
actuatorThrust = setpoint->thrust;
}
if (setpoint->mode.x == modeDisable || setpoint->mode.y == modeDisable) {
attitudeDesired.roll = setpoint->attitude.roll;
attitudeDesired.pitch = setpoint->attitude.pitch;
}
attitudeControllerCorrectAttitudePID(state->attitude.roll, state->attitude.pitch,␣
,→state->attitude.yaw,
attitudeDesired.roll, attitudeDesired.pitch,␣
,→attitudeDesired.yaw,
// For roll and pitch, if velocity mode, overwrite rateDesired with the setpoint
// value. Also reset the PID to avoid error buildup, which can lead to unstable
// behavior if level mode is engaged later
if (setpoint->mode.roll == modeVelocity) {
rateDesired.roll = setpoint->attitudeRate.roll;
attitudeControllerResetRollAttitudePID();
}
if (setpoint->mode.pitch == modeVelocity) {
rateDesired.pitch = setpoint->attitudeRate.pitch;
attitudeControllerResetPitchAttitudePID();
}
attitudeControllerGetActuatorOutput(&control->roll,
&control->pitch,
&control->yaw);
control->yaw = -control->yaw;
}
if (tiltCompensationEnabled)
{
control->thrust = actuatorThrust / sensfusion6GetInvThrustCompensationForTilt();
}
else
{
control->thrust = actuatorThrust;
(continues on next page)
if (control->thrust == 0)
{
control->thrust = 0;
control->roll = 0;
control->pitch = 0;
control->yaw = 0;
attitudeControllerResetAllPID();
positionControllerResetAllPID();
Mellinger Controller
Mellinger controller is an all-in-one controller that directly calculates the required thrust allocated to all motors, based
on the target position and the speed vector on the target position.
For your reference: Minimum snap trajectory generation and control for quadrotors.
INDI Controller
An INDI controller is a controller that immediately processes angle rates to determine data reliability. This controller
can be used together with a traditional PID controller, which provides a faster angle processing than a string-level PID
controller.
For your reference: Adaptive Incremental Nonlinear Dynamic Inversion for Attitude Control of Micro Air Vehicles.
10. Adjust KI to eliminate steady-state errors. If only with proportional adjustment, but without this parameter, the
drone may swing up and down at Position 0 due to the interference such as gravity. Set the initial value of KI to
50% of KP.
11. When the KI increases to certain value, the drone starts shaking. But compared with the shake caused by KI, that
caused by KP is more low-frequency. Keep in mind the point when the drone starts shaking, and mark this KI as
the critical point. The final KI should be 5%-10% lower than this critical point.
12. Tune the roll and yaw in the same way.
13. In general, the value of KI should be over 80% of the KP.
Rate PID parameter tuning is done now.
Let’s start the tuning of Attitude PID
1. First ensure that Rate PID tuning is completed.
2. Adjust rollType, pitchType, and yawType to ANGLE, i.e. the drone is in attitude mode now.
3. Set the KI and KD of roll and pitch to 0.0, and then set the KP, KI, and KDof Yaw to 0.0.
4. Burn the code and start the KP tuning online using the param function of cfclient.
5. Set the KP of roll and pitch to 3.5. Check for any existing instability, such as shakes. Keep increasing the
KP until the limit is reached;
6. If the KP already is causing drone instability, or the value is over 4, please lower the KP and KI of RATE mode by
5% ~ 10%. By such way, we have more freedom to tune the Attitude mode.
7. If you still need to adjust the KI, please slowly increase KI again. If some low-frequency shakes occur, it indicates
that your drone is in an unstable state.
[ ]
Wi-Fi Performance
Item Parameter
Mode STA mode, AP mode, STA+AP mode
Protocol IEEE 802.11b/g/n, and 802.11 LR (Espressif). Support switching over software
Security WPA, WPA2, WPA2-Enterprise, WPS
Main Feature AMPDU, HT40, QoS
Supported Distance 1 km under the Exclusive Agreement of Espressif
Transfer Rate 20 Mbit/s TCP throughput, 30 Mbit/s UDP
Item Parameter
Mode STA mode, AP mode, STA+AP mode
Protocol IEEE 802.11b/g/n. Support switch over software
Security WPA, WPA2, WPA2-Enterprise, WPS
Main Feature AMPDU, HT40, QoS
Supported Distance 1 km under the Exclusive Agreement of Espressif
Transfer Rate 20 Mbit/s TCP throughput, 30 Mbit/s UDP
3. Network interface component esp_netif provides the handle program associated with the Wi-Fi driver event
by default. For example, when ESP32 works as an AP, and a user connects to this AP, esp_netif will automatically
start the DHCP service.
For the detailed usage, please refer to the code \components\drivers\general\wifi\wifi_esp32.c.
Note: Before Wi-Fi initialization, please use WIFI_INIT_CONFIG_DEFAULT to obtain the initialization config-
uration struct, and customize this struct first, then start the initialization. Be aware of problems caused by unitialized
members of the struct, and pay special attention to this issue when new structure members are added to the ESP-IDF
during update.
AP Mode Workflow
Navigate to Component config>>PHY>>Max WiFi TX power (dBm), and update Max WiFi TX power
to 20. This configuration increases the PHY gain and Wi-Fi communication distance.
UDP Port
/* Frame format:
* +=============+-----+-----+
* | CRTP | CKSUM |
* +=============+-----+-----+
*/
#take python as an example: Calculate the raw cksum and add it to the end of the␣
,→packet
The ESP-Drone project continues the CRTP protocol used by the Crazyflie project for flight instruction sending, flight
data passback, parameter settings, etc.
CRTP implements a stateless design that does not require a handshake step. Any command can be sent at any time,
but for some log/param/mem commands, the TOC (directory) needs to be downloaded to assist the host in sending
the information correctly. The implemented Python API (cflib) can download param/log/mem TOC to ensure that all
functions are available.
The 32-byte CRTP packet contains one byte of Header and 31 bytes of Payload. Header records the information about
the ports (4 bits), channels (2 bits), and reserved bits (2 bits).
7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+
| Port | Res. | Chan. |
+---+---+---+---+---+---+---+---+
| DATA 0 |
+---+---+---+---+---+---+---+---+
: : : : : : : : :
+---+---+---+---+---+---+---+---+
| DATA 30 |
+---+---+---+---+---+---+---+---+
Port Allocation
Most of the modules in the firmware that are connected to the port are implemented as tasks. If an incoming CRTP
packet is delivered in the messaging queue, the task is blocked in the queue. At startup, each task and other modules need
to be registered for a predefined port at the communication link layer.
Details of the use of each port can be found at CRTP - Communicate with Crazyflie.
cflib is a Python package supported by CRTP protocol, and provides an application-layer interface for communication
protocols that can be used to build an upper PC, to communicate with Crazyflie and Crazyflie 2.0 quadcopters. Each
component in the firmware that uses the CRTP protocol has a script corresponding to it in cflib.
• Source repository: crazyflie-lib-python.
• cflib repository specially for ESP-Drone: qljz1993/crazyflie-lib-python. Please checkout to esplane branch.
1. crazyflie2-ios-client
2. crazyflie2-windows-uap-client
3. crazyflie-android-client
4. User Guide on Android
5. Development Guide on Android
cfclient
cfclient is the upper PC for Crazeflie project, which has fully implemented the functions defined in CRTP Protocol,
and speeds up the debug process for the drone. The ESP-Drone project tailors and adjusts the upper PC to meet functional
design needs.
For detailed information about cfclient, please refer to cfclient.
[ ]
• Code in esp_drone repository supports a wide variety of hardware, which can be changed through menucon-
fig.
• By default, when set set-target as esp32s2, target hardware will be changed to ESP32_S2_Drone_V1_2
automatically.
• By default, when set set-target as esp32, target hardware will be changed to ESPlane_FC_V1 automati-
cally.
Notes
1. ESPlane-FC-V1 is an old version hardware.
2. To use ESP-Drone new version code on ESPlane-FC-V1, please connect GPIO14 of ESP32-WROOM-32D to
INT pin of MPU6050 by a jumper.
3. To avoid flash voltage switching triggered by IO12 when ESPlane-FC-V1 is powered on, please fix the flash voltage
to 3.3 V by running espefuse.py script
espefuse.py --port /dev/ttyUSB0 set_flash_voltage 3.3V
note * Only the first device attaching to the bus can use CS0 pin.
Basic Component
Note: Set motor type as brushed 720 motor through menuconfig->ESPDrone Config->motors
config if you use 720 motor.
Main Controller
Sensor
LEDs
Buttons
Buttons IO Function
SW1 GPIO1 Boot, Normal
SW2 EN Reset
Camera Interface
Pins Function
GPIO13 CAM_VSYNC
GPIO14 CAM_HREF
GPIO15 CAM_Y9
GPIO16 CAM_XCLK
GPIO17 CAM_Y8
GPIO18 CAM_RESET
GPIO19 CAM_Y7
GPIO20 CAM_PCLK
GPIO21 CAM_Y6
GPIO33 CAM_Y2
GPIO45 CAM_Y4
GPIO46 CAM_Y3
Extension Components
3.4.3 ESPlane-V2-S2
3.4.4 ESPlane-FC-V1
Basic Component
Sensor
LEDs
FOUR
THIRD-PARTY CODES
[ ]
The third-party codes adopted in ESP-Drone project and the licenses are as follows:
79
ESP-Drone
FIVE
ACKNOWLEDGEMENT
81