Flight Controller Board: KIWI F405 12S Configuration

Overview
KIWI F4.0 is a versatile flight controller based on the STM32F405, designed for FPV, wings, and autonomous platforms. The controller combines precision inertial sensing, OSD support, built-in Blackbox, and relay outputs for controlling external modules. Support for both Betaflight and ArduPilot allows this board to be used in a wide range of applications.
KIWI F4.0 is a reliable platform for building FPV drones, aircraft, and specialized autonomous systems with full support for Betaflight and ArduPilot. Thanks to flexible relay, sensor, and telemetry connectivity, the controller is ready for real-world mission use.
Firmware
- ArduPilot 4.6.2 KiwiF405-12S.zip
- Betaflight 4.5.3 BF-4.5.3.zip
- Betaflight 2025.12.0 BF-2025.12.0-beta.zip
- Betaflight 2026.12.3 BF-2026.12.3-alpha.zip
Pinout and Diagrams
Features
- Industrial-grade IMU Invensense ICM-42688P with external clock
- Bosch BMP388 barometer for altitude measurement
- Integrated 128Mbit Blackbox flash memory (W25Q128FV)
- MAX7456 OSD chip for overlaying telemetry on analog video
- High-precision voltage and current monitoring via ADC (VBAT, CURRENT)
- GPIO-controlled relay outputs for powering VTX, cameras, or pyrotechnic systems
- 4 motor PWM outputs (DShot, bidirectional on M1 & M3) + 6 auxiliary channels
- USB Type-C with DFU firmware flashing support
- Full CRSF / ELRS telemetry support (RSSI, LQ, SNR, Power)
Technical Specifications
- MCU: STM32F405RG (168 MHz, 1024 KB flash)
- Crystal: 16 MHz external oscillator
- IMU: ICM-42688P (SPI2, rotation ROLL_180_YAW_90)
- Barometer: BMP388 (I2C1, address 0x76)
- OSD: MAX7456 (SPI1)
- Flash Memory: W25Q128FV 128 Mbit (SPI3)
- Dimensions: 36×36 mm, mounting 30.5×30.5 mm
- LED: PC2 (active low)
Serial Ports
| Port | ArduPilot | Default Protocol | Pins | Notes |
|---|---|---|---|---|
| USB | SERIAL0 | MAVLink | PA11, PA12 | OTG FS, Type-C |
| USART1 | SERIAL1 | RC Input | PB6, PB7 | |
| USART2 | SERIAL2 | MAVLink2 (460800) | PA2, PA3 | Alt: RC via TIM9 |
| USART3 | SERIAL3 | GPS (115200) | PC10, PC11 | |
| UART4 | SERIAL4 | SmartAudio | PA0, PA1 | VTX control |
| UART5 | SERIAL5 | ESC Telemetry | PC12, PD2 | NODMA |
GPIOs, Relays, and AUX
Dedicated GPIO Pads
| Pad | Pin | GPIO | Default | ArduPilot Relay Config |
|---|---|---|---|---|
| F+ | PC14 | 103 | RELAY1 | RELAY1_PIN=103 (hwdef default) |
| U1 | PA4 | 100 | Output LOW | RELAY2_PIN=100, RELAY2_FUNC=1 |
| U3 | PC15 | 101 | Output LOW | RELAY3_PIN=101, RELAY3_FUNC=1 |
| U2 | PA10 | 102 | Output LOW | RELAY4_PIN=102, RELAY4_FUNC=1 |
| LED | PC2 | 90 | Status LED | — |
RELAY1 (F+ pad) works out of the box — pre-configured in hwdef. U1/U2/U3 need params set to use as relays.
PWM Outputs
| Output | Pin | GPIO | Timer | Function | DShot Bidir |
|---|---|---|---|---|---|
| PWM1 | PC9 | 50 | TIM8_CH4 | Motor 1 | Yes |
| PWM2 | PC8 | 51 | TIM8_CH3 | Motor 2 | No |
| PWM3 | PC7 | 52 | TIM8_CH2 | Motor 3 | Yes |
| PWM4 | PC6 | 53 | TIM8_CH1 | Motor 4 | No |
| PWM5 | PA8 | 54 | TIM1_CH1 | AUX 1 | No |
| PWM6 | PA9 | 55 | TIM1_CH2 | AUX 2 | No |
| PWM7 | PB11 | 56 | TIM2_CH4 | AUX 3 | No |
| PWM8 | PB10 | 57 | TIM2_CH3 | AUX 4 | No |
| PWM9 | PB1 | — | TIM3_CH4 | AUX 5 | No |
| PWM10 | PB0 | — | TIM3_CH3 | AUX 6 | No |
PWM9/PWM10 have no GPIO ID in hwdef — PWM only. Other PWM pins can be reassigned to GPIO via
SERVOn_FUNCTION=0+RELAYn_PIN=<gpio>.
Relay Usage
MAVProxy:
param set RELAY2_PIN 100
param set RELAY2_FUNC 1
relay set 0 1 # RELAY1 ON (F+ pad HIGH)
relay set 0 0 # RELAY1 OFF
relay set 1 1 # RELAY2 ON (U1 pad HIGH)
Mission waypoint: DO_SET_RELAY — relay number 0-based (0=RELAY1), setting 1=ON / 0=OFF.
Lua:
relay:toggle(0) -- toggle RELAY1
relay:on(1) -- RELAY2 ON
relay:off(1) -- RELAY2 OFF
All GPIO pads default LOW on boot. Use RELAY_DEFAULT params to set initial state.
Power Monitoring
- Battery Voltage: PC0 (ADC1 IN10)
- Battery Current: PC1 (ADC1 IN11)
- Default monitor type: Analog (type 4)
Sensor Calibration
| Parameter | ArduPilot | Betaflight |
|---|---|---|
| Voltage scale | BATT_VOLT_MULT = 21.0 | voltage_meter_scale = 210 |
| Current scale | BATT_AMP_PERVLT = 142.9 | current_meter_scale = 1052 |
Battery Voltage Thresholds (ArduPilot)
| Parameter | 6S | 8S | 12S |
|---|---|---|---|
| Full charge | 25.2 V | 33.6 V | 50.4 V |
BATT_ARM_VOLT | 22.2 | 29.6 | 44.4 |
BATT_LOW_VOLT | 21.0 | 28.0 | 42.0 |
BATT_CRT_VOLT | 19.8 | 26.4 | 39.6 |
SPI Bus Assignment
| Bus | Device | Chip Select | Speed |
|---|---|---|---|
| SPI1 | MAX7456 | PC3 | 10 MHz |
| SPI2 | ICM-42688P | PC5 | 2/8 MHz |
| SPI3 | W25Q128FV | PC13 | 104 MHz |
I2C Bus
- I2C1: PB8 (SCL), PB9 (SDA) — BMP388 barometer at 0x76, external compass probing
Debug
- SWDIO: PA13
- SWCLK: PA14
Premium Features
Kiwi OSD Pinio Elements (Betaflight 2025.12+)
Custom OSD text elements that change based on PINIO switch state (User 1–4 boxes). Each element displays configurable ON/OFF text labels, useful for showing relay status, arming indicators, or mission state on the OSD.
CLI Settings
| Setting | Description |
|---|---|
kiwi_osd_pinioN_text_on | Text shown when User N switch is active |
kiwi_osd_pinioN_text_off | Text shown when User N switch is inactive (use - to hide) |
kiwi_osd_pinioN_pos | OSD screen position (341 = hidden) |
Where N is 1–4 corresponding to PINIO1–PINIO4.
Example Setup
# Show SAFE/ARMED on OSD driven by User 2 switch
set kiwi_osd_pinio2_text_on = ARMED
set kiwi_osd_pinio2_text_off = SAFE
set kiwi_osd_pinio2_pos = 2242
# Show PARACHUTE only when User 3 switch is active, hidden when off
set kiwi_osd_pinio3_text_on = PARACHUTE
set kiwi_osd_pinio3_text_off = -
set kiwi_osd_pinio3_pos = 2274
# Assign User 2 to AUX3 switch (high position)
aux 3 41 3 1700 2100 0 0
# Assign User 3 to AUX2 switch (high position)
aux 4 42 2 1700 2100 0 0
save
Hardware Notes
On the KIWI F405 12S, only PINIO4 (PA4 / RELAY1) has a physical GPIO pin. PINIO1–3 are defined as NONE in the hardware config, but the OSD elements still work — the User box toggles the logical state, and the OSD text updates accordingly. No physical pin is needed for OSD-only use.
Camera Gimbal Support
KIWI F405 supports camera gimbals out of the box — both servo-based and MAVLink protocol gimbals (CADDX GM3 V2 and compatible).
MAVLink Gimbal
Wire gimbal UART to any free serial port (gimbal TX → FC RX, gimbal RX → FC TX, GND).
| Param | Value | Notes |
|---|---|---|
SERIALx_PROTOCOL | 2 | MAVLink2 |
SERIALx_BAUD | 115 | 115200 bps |
MNT1_TYPE | 6 | Gremsy (reboot after setting) |
MNT1_PITCH_MIN | -120 | GM3 V2 spec: ±120° |
MNT1_PITCH_MAX | 120 | |
MNT1_YAW_MIN | -160 | GM3 V2 spec: ±160° |
MNT1_YAW_MAX | 160 | |
MNT1_RC_RATE | 60 | deg/s for rate control, 0 for angle |
RC Control
Assign RC channels to control gimbal axes:
| Param | Value | Notes |
|---|---|---|
RC6_OPTION | 213 | Mount1 Pitch |
RC7_OPTION | 214 | Mount1 Yaw |
RC8_OPTION | 212 | Mount1 Roll (3-axis gimbals only) |
Example: with MNT1_RC_RATE=60, moving the RC6 stick deflects pitch at 60°/s. Set MNT1_RC_RATE=0 for direct angle control (stick position = gimbal angle).
Gimbal firmware must be V2.0 or higher.
Servo Gimbal
Connect pitch/yaw servos to AUX PWM outputs (PWM5–PWM8).
| Param | Value | Notes |
|---|---|---|
MNT1_TYPE | 1 | Servo |
SERVOx_FUNCTION | 6 | Mount1 Pitch (assign to desired output) |
SERVOx_FUNCTION | 8 | Mount1 Yaw (assign to desired output) |
MNT1_PITCH_MIN | -90 | |
MNT1_PITCH_MAX | 90 | |
MNT1_YAW_MIN | -170 | |
MNT1_YAW_MAX | 170 | |
MNT1_RC_RATE | 60 | deg/s for rate control, 0 for angle |
Default Parameters
- Frame: Quadcopter (FRAME_CLASS=1, FRAME_TYPE=3 BetaFlight X reversed)
- Motor protocol: DShot (MOT_PWM_TYPE=5)
- BLHeli passthrough: enabled (SERVO_BLH_AUTO=1, mask=15)
- Flight mode channel: CH8
- VTX: enabled, band 6, channel 4, freq 1240

