Miscellaneous
Manless Aerial Device
This is an Arduino library to build ESP32 / ESP32-S3 / RP2350 / RP2040 / STM32 flight controllers. A functional DIY flight controller can be build for under $10 from readily available development boards and sensor breakout boards. Ideal if you want to try out new flight control concepts, without first having to setup a build environment and without having to read through thousands lines of code to find the spot where you want to change something.
Quadcopter.ino
is a 1000 line demo program for a quadcopter. It has been flight tested on ESP32, ESP32-S3, RP2040, and STM32F405 microcontrollers with the Arduino IDE. The program can be easily adapted to control your plane or VTOL craft. The source code has extensive documentation explaning what the settings and functions do.
I enjoy hacking with electronics and I'm attempting to write some decent code for this project. If you enjoy it as well, please leave some feedback in the form of Stars, Issues, Pull Requests, or Discussions. Thanks!
For full documention see madflight.com and the source code itself.
Required Hardware
Getting Started
Safety First
ESP32 / ESP32-S3 Setup and Pinout
RP2350 / RP2040 Setup and Pinout
STM32 Setup and Pinout
Connecting the IMU Sensor
Software Design
Changes from dRehmFlight
Flight Controllers on Github
Disclaimer
help
to see the available CLI commands.pimu
, pgyro
, proll
to Check that IMU sensor and AHRS are working correctly.calimu
and calmag
to calibate the sensors.ppwm
and pradio
to show pwm and scaled radio values.pmot
to show motor output.By default madflight has these safety features enabled:
madflight works with Arduino-ESP32 v3.x.x
madflight v1.1.2 and earlier works with Arduino-ESP32 v2.x.x
ESP32 and ESP32-S3 have dual core CPU, but single core FPU. ESP-IDF implementation limits float usage to a single core, and float can not be used in interrupts. FreeRTOS is always enabled and a watchdog limits interrupt execution time.
madflight uses float and is therefor limited to single core operation. The IMU loop runs as a high priorty task, triggered by the IMU interrupt.
Arduino-ESP32 v2.0.17 has an I2C bug which causes the bus to hang for 1 second after a failed read, which can happen a couple times per minute. This makes Wire I2C for IMU not a real option...
A workaround is to use #define USE_ESP32_SOFTWIRE which enables software I2C, but this does not work well with all sensors.
(!) So, until a better I2C solution is available: use an SPI IMU sensor on ESP32.
NOTE: as of June 2024 this bug is apparently fixed, but not yet confirmed with madflight.
This is the default pinout for ESP32. It is optimized for the Espressiv ESP32 DevKitC (38 pin) board. This pinout is defined in madflight_board_default_ESP32.h, but can be modified with #define HW_PIN_XXX
in your program.
Function | GPIO | Board | GPIO | Function |
---|---|---|---|---|
3V3 out | 3V3 | Antenna side | GND | GND |
reset button | EN | 23 | I2C_SDA | |
SPI_MISO | VP 36 input only | 22 | I2C_SCL | |
IMU_EXTI | VN 39 input only | 1 TX | USB Serial Debug TX | |
BAT_V | 34 input only | 3 RX | USB Serial Debug RX | |
RCIN_RX | 35 input only | 21 | SPI_MOSI | |
RCIN_TX | 32 | GND | GND | |
PWM1 | 33 | 19 | SPI_SCLK | |
PWM2 | 25 | 18 | IMU_CS | |
PWM3 | 26 | strap 5 | GPS_TX | |
PWM4 | 27 | 17 | GPS_RX | |
PWM5 | 14 | 16 | PWM11 | |
PWM6 | 12 | 4 | PWM10 | |
GND | GND | boot 0 | PWM9 | |
PWM7 | 13 | strap 2 | LED | |
nc | D2 9 flash | strap 15 | PWM8 | |
nc | D3 10 flash | flash 8 D1 | nc | |
nc | CMD 11 flash | flash 7 D0 | nc | |
5V input (*) | 5V | USB connector | flash 6 CLK | nc |
Note: During boot the input voltage levels (pull up/pull down) on strap pins have a configuration function, therefor these pins are used as output only.
(*) 5V input via diode from BEC. Without a diode take care not connect USB and the battery at the same time!
This is the default pinout for ESP32-S3. It is optimized for the Espressiv ESP32-S3 DevKitC-1 (44 pin) board. This pinout is defined in madflight_board_default_ESP32-S3.h, but can be modified with #define HW_PIN_XXX
in your program.
Function | GPIO | Board | GPIO | Function |
---|---|---|---|---|
3V3 out | 3V3 | Antenna side | G | GND |
3V3 out | 3V3 | 43 | TX serial debug UART port | |
reset button | RST | 44 | RX serial debug UART port | |
PWM1 | 4 | 1 | - | |
PWM2 | 5 | 2 | - | |
PWM3 | 6 | 42 | - | |
PWM4 | 7 | 41 | - | |
PWM5 | 15 | 40 | - | |
PWM6 | 16 | 39 | - | |
RCIN_TX | 17 | 38 | LED | |
RCIN_RX | 18 | 37 | - | |
I2C_SDA | 8 | 36 | - | |
GPS_RX | 3 | 35 | - | |
GPS_TX | 46 | 0 | boot button | |
I2C_SCL | 9 | 45 | - | |
IMU_CS | 10 | 48 | RGB_LED | |
SPI_MOSI | 11 | 47 | - | |
MISO | 12 | 21 | - | |
SCLK | 13 | 20 | USB_D+ (serial debug alternate) | |
IMU_EXTI | 14 | 19 | USB_D- (serial debug alternate) | |
5V in (*) | 5V | G | GND | |
GND | G | USB connector | G | GND |
(*) 5V input via diode from BEC. Without a diode take care not connect USB and the battery at the same time!
madflight works with arduino-pico v4.x.x
RP2350 (Pico2) has dual core, dual FPU, but no FreeRTOS (arduino pico v4.0.1)
RP2040 (Pico) has dual core, no FPU, and FreeRTOS is optional.
madflight uses float and is much happier with RP2350 over RP2040.
madflight on RP2040 uses FreeRTOS and executes the 1000Hz IMU loop on the second core, which is 80% loaded at default 133MHz CPU speed. You can overclock the CPU to get some more headroom.
Consecutive even/odd PWM pins (e.g. pins 2,3 or 10,11) share the same timer and have the same frequency.
madflight uses a custom high performance SerialIRQ library.
This is the default pinout for RP2040. It is optimized for the Raspberry Pi Pico (40 pin) board. This pinout is defined in madflight_board_default_RP2040.h, but can be modified with #define HW_PIN_XXX
in your program.
Function | GPIO | Board | GPIO | Function |
---|---|---|---|---|
RCIN_TX | 0 | USB connector | VBUS | nc |
RCIN_RX | 1 | VSYS | 5V input via diode (*) | |
GND | GND | GND | GND | |
PWM1 | 2 | EN | nc | |
PWM2 | 3 | 3.3V out | 3V3 | |
PWM3 | 4 | VREF | nc | |
PWM4 | 5 | 28_A2 | BAT_V | |
GND | GND | GND | GND | |
PWM5 | 6 | 27_A1 | - | |
PWM6 | 7 | 26_A0 | - | |
GPS_TX | 8 | RUN | reset button to GND | |
GPS_RX | 9 | 22 | IMU_EXTI | |
GND | GND | GND | GND | |
PWM7 | 10 | 21 | I2C_SCL | |
PWM8 | 11 | 20 | I2C_SDA | |
PWM9 | 12 | 19 | SPI_MOSI | |
PWM10 | 13 | 18 | SPI_SCLK | |
GND | GND | GND | GND | |
PWM11 | 14 | 17 | IMU_CS | |
PWM12 | 15 | JTAG pins | 16 | SPI_MISO |
(*) 5V input via diode from BEC. Without a diode take care not connect USB and the battery at the same time!
This pinout is optimized for the RP2040-Zero (21 pin) board. This pinout is defined in madflight_board_RP2040-Zero.h, but can be modified with #define HW_PIN_XXX
in your program.
Function | GPIO | Board | GPIO | Function |
---|---|---|---|---|
5V input (*) | 5V | USB connector | 0 | RCIN_TX |
GND | GND | 1 | RCIN_RX | |
3V3 out | 3V3 | 2 | PWM1 | |
- | 29 | 3 | PWM2 | |
BAT_V | 28 | 4 | PWM3 | |
I2C1_SCL | 27 | 5 | PWM4 | |
I2C1_SDA | 26 | 6 | PWM5 | |
IMU_EXTI | 15 | 7 | PWM6 | |
14 | 8 | GPS_TX | ||
9 | GPS_RX | |||
10 | SPI1_SCLK | |||
11 | SPI1_MISO | |||
12 | SPI1_MOSI | |||
13 | IMU_CS |
(*) 5V input via diode from BEC. Without a diode take care not connect USB and the battery at the same time!
madflight works with stm32duino Arduino Core for STM32 v2.x.x
Most supported STM32 targets have a single cores with FPU. FreeRTOS support optional.
madflight runs the IMU loop in interrupt context.
In the src
directory you'll find 400+ Betaflight configuration files for commercial flight controllers. Include the madflight_board_betaflight_XXX.h header file of your board, and in your program set '#define HW_USE_XXX' to match your board.
This is the default pinout for STM32. It is optimized for the WeAct STM32F411 Black Pill (40 pin) board. This pinout is defined in madflight_board_default_STM32.h, but can be modified with #define HW_PIN_XXX
in your program.
Function | GPIO | Board | GPIO | Function |
---|---|---|---|---|
nc | VB | SWD pins | 3V3 | 3V3 out |
LED | C13 | G | GND | |
- | C14 | 5V | 5V input (*) | |
- | C15 | B9 | PWM10(t4) | |
nc | R | B8 | PWM9(t4) | |
- | A0 | B7 | I2C_SCL | |
- | A1 | B6 | I2C_SDA | |
GPS_TX | A2 | B5 | PWM8(t3) | |
GPS_RX | A3 | B4 | PWM7(t3) | |
IMU_CS | A4 | B3 | RCIN_RX | |
SPI_SCLK | A5 | A15 | RCIN_TX | |
SPI_MISO | A6 | A12 | USB_DP | |
SPI_MOSI | A7 | A11 | USB_DN | |
BAT_I | B0 | A10 | PWM6(t1) | |
BAT_V | B1 | A9 | PWM5(t1) | |
- | B2 | A8 | PWM4(t1) | |
IMU_EXTI | B10 | B15 | PWM3(t1) | |
3V3 out | 3V3 | B14 | PWM2(t1) | |
GND | G | B13 | PWM1(t1) | |
5V input (*) | 5V | USB connector | B12 | - |
Internally connected: C13 - LED, A0 - key button
PWM1-6 are connected to timer1, PWM7-8 to timer3 and PWM9-10 to timer4. PWM pins connected to the same timer operate at the same frequency.
(*) 5V input via diode from BEC. Without a diode take care not connect USB and the battery at the same time!
SPI sensor: (highly recommended over I2C)
Sensor Dev Board
SCL/SCLK <---> SPI_SCLK
SDA/SDI <---> SPI_MOSI
ADD/SDO <---> SPI_MISO
NCS <---> IMU_CS
INT <---> IMU_EXTI
VCC <---> 3V3
GND <---> GND
I2C sensor:
Sensor Dev Board
SCL <---> I2C_SCL
SDA <---> I2C_SDA
INT <---> IMU_EXTI
VCC <---> 3V3
GND <---> GND
src/madflight
directory.setup()
and loop()
.imu
Inertial Measurement Unit, retrieves accelerometer, gyroscope, and magnetometer sensor dataahrs
Attitude Heading Reference System, estimates roll, yaw, pitchrcin
RC INput, retrieves RC receiver datacontrol
PID controller and output mixerout
Output to motors and servosmag
Magnetometer (external)baro
Barometergps
GPS receiverbb
Black Box data loggercli
Command Line Interface for debugging, configuration and calibrationcfg
Read and save configuration to flashhw
Hardware specific code for STM32, RP2040 and ESP32imu
object has property imu.gx
which is the current gyro x-axis rate in degrees per second for the selected IMU chip.src/madflight/interfaces.h
which defines the module interfaces.src/madflight
directory. Here you find the module header file, e.g. src/madflight/imu/imu.h
. In the extras
directory your find test programs for the modules, e.g. extras/TestMadflight/imu.ino
.In (approximate) increasing order of complexity.
Flight Controller | Features | Development Environment | Microcontroller |
---|---|---|---|
drone-flight-controller | Single 700 line ino file, no libs | Arduino | ATmega328P |
dRehmFlight | Quad, Plane, VTOL | Arduino | Arduino Teensy 4 |
madflight | Quad, Plane, VTOL, based on dRehmFlight | Arduino | ESP32, RP2040, and STM32 |
esp-fc | FPV Quad | PlatformIO | ESP32 |
Crazyflie | FPV Quad | STM32F405 | |
esp-drone | FPV Quad, based on Crazyflie | ESP32 | |
Betaflight | FPV Quad, based on cleanflight | STM32 F4/F7/H7 | |
EmuFlight | Multi-rotor, based on cleanflight | STM32 F4/F7 | |
inav | Plane, based on cleanflight | STM32 F4/F7/H7 | |
Ardupilot | Quad, Plane, VTOL | Linux waf | STM32 F4/F7/H7 or Linux based |
PX4-Autopilot | Quad, Plane, VTOL | STM32 F4/F7/H7 |
This code is a shared, open source flight controller for small micro aerial vehicles and is intended to be modified to suit your needs. It is NOT intended to be used on manned vehicles. I do not claim any responsibility for any damage or injury that may be inflicted as a result of the use of this code. Use and modify at your own risk. More specifically put:
THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Logo image copyright (c) 1975 Deutsches MAD Magazine. This project is not associated with MAD Magazine.