Guides
Gorilla Whoop Whoop Guide: Setting Up a BetaFPV Air75 on Linux
This guide gets a BetaFPV Air75 flashed with Betaflight 2026.6.2 and flying, from a Linux machine. I used Arch, but everything except the package commands works on any distro.
It's the guide I wish I'd had. I made every mistake in it at least once, so you don't have to. The short version of what goes wrong:
- Linux won't let the browser talk to the drone until you fix USB permissions.
- There are three revisions of the Air75's flight controller with the same name. Pick the wrong one and half your motors stop working.
- A fresh flash erases everything, and several settings the Air75 needs aren't defaults.
The story behind all of this is in Episodes 0 and 1. This post is just the steps.
What you need
| Item | Notes |
|---|---|
| BetaFPV Air75 | Analog version, built-in ExpressLRS receiver |
| USB adapter | Comes in the box with the Air75 |
| 1S battery | Motors and video transmitter don't power up on USB alone |
| ExpressLRS radio | I use a RadioMaster Pocket (EdgeTX) |
| Chromium-based browser | Chrome, Chromium, Brave or Edge. Firefox can't do WebSerial or WebUSB |
| Betaflight App | app.betaflight.com, runs in the browser |
| Linux with sudo access | Arch here; adapt pacman commands for your distro |
Optional: base-devel and git if you want to compile the firmware yourself. You don't have to.
Step 1: Fix Linux USB permissions
The drone shows up two ways over USB. In normal mode it's a serial port (/dev/ttyACM0). In flashing mode, called DFU, it's a raw USB device. Linux blocks regular users from both by default.
Run this once:
# serial port access (Arch uses the uucp group; Debian/Ubuntu use dialout)
sudo usermod -aG uucp $USER
# let regular users flash the STM32 in DFU mode
echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="df11", MODE="0664", GROUP="uucp"' | sudo tee /etc/udev/rules.d/45-stdfu.rules
sudo udevadm control --reload-rulesThen log out and back in so the group change takes effect. Skipping this is the number one reason flashing hangs forever with no error.
Step 2: Back up before you touch anything
Flashing wipes every setting on the flight controller. Save them first:
- Plug in the Air75 over USB and click Connect in the Betaflight App.
- Open the CLI tab, type
diff all, and press Enter. - Copy everything it prints into a text file, like
air75-backup.txt.
The most useful line is board_name near the top. It tells you which firmware target the drone shipped with. Write it down for Step 3.
Step 3: Identify your board revision
This is the step that cost me a whole evening. Betaflight has three targets for this flight controller: BETAFPVG473, BETAFPVG473_V2 and BETAFPVG473_V3. They share a processor but wire the gyro, motors and battery sensor to different pins. Flash the wrong one and something important quietly stops working.
The pin maps, from the Betaflight config files:
| Target | Gyro CS / interrupt | Motor 3 | Motor 4 | Battery voltage | Symptom if wrong |
|---|---|---|---|---|---|
| BETAFPVG473 (V1) | PA4 / PC4 | PB6 | PC13 | PA0 | GYRO: None, board won't arm |
| BETAFPVG473_V2 | PC14 / PC15 | PC6 | PA4 | PA0 | (mine: everything works) |
| BETAFPVG473_V3 | PC14 / PC15 | PB6 | PB9 | PA4 | Gyro fine, motors 3 and 4 dead, wrong battery reading |
How to tell which one you have:
- Best: the
board_namefrom your Step 2 backup. Build that exact target. - No backup? Look at the gyro chip on the board. Mine reads BMI270, which V2 supports.
- Already flashed something? In the CLI, run
status. IfGYRO:says None, the gyro pins are wrong. Then runresourceand test motors. If motors 3 and 4 are dead, you're on V3 and need V2, or the other way round.
My Air75 turned out to be V2. Yours may not be. Check before you flash.
Step 4: Get the firmware
Use a stable release. I used 2026.6.2. Don't build from the master branch: that's the development version, and the regular Betaflight App will warn that it doesn't support it.
Option A: let the app build it (recommended)
In the Betaflight App, disconnect, then open Firmware Flasher:
- Board: pick your target by hand, e.g.
BETAFPVG473_V2. Don't trust auto-detect here. - Version: 2026.6.2
- Radio protocol: CRSF · Telemetry: CRSF · OSD: Analog (MAX7456) · Motor protocol: DSHOT
- Click Load Firmware [Online].
This always includes the board config, so you can't end up with an unconfigured board.
Option B: compile it yourself
For the curious, or people who distrust buttons:
sudo pacman -S --needed base-devel git python
mkdir -p ~/src && cd ~/src
git clone https://github.com/betaflight/betaflight.git
cd betaflight
make arm_sdk_install # downloads the exact ARM compiler; run inside the repo
git fetch --tags
git checkout 2026.6.2 # stable release, not master
make configs # downloads board definitions
make clean
make BETAFPVG473_V2 # your target from Step 3
ls obj/*.hexIf you see No rule to make target 'arm_sdk_install', you're not in the betaflight folder. If git checkout mentions "detached HEAD," that's normal. It just means you're on a release instead of a branch.
Step 5: Flash it
The app is supposed to reboot the drone into flashing mode (DFU) by itself. On my setup it didn't, and the flash sat there waiting forever. Doing it by hand works every time:
- Connect, open the CLI, type
bland press Enter. The drone disconnects. That's expected. - Check that Linux sees it in DFU mode:
lsusb | grep 0483You want
0483:df11 ... DFU Mode. If it says0483:5740, it's still in normal mode; repeat step 1. - In Firmware Flasher (only visible while disconnected), turn on No reboot sequence.
- Load the firmware: [Online] from Step 4 Option A, or [Local] and pick your
.hexfrom~/src/betaflight/obj/. - Click Flash Firmware. When the browser asks for a device, pick STM32 BOOTLOADER.
- Wait for Programming: SUCCESSFUL, usually under a minute.
If the device picker is empty, go back to Step 1. In Brave, also try turning off Shields for the site. An interrupted flash won't brick the board. Just put it back in DFU and flash again.
Step 6: Restore and configure
First, confirm the right firmware landed. Connect, open the CLI and run status. You want CONFIG: CONFIGURED, a gyro listed (mine: BMI270), and OSD: MAX7456. On V2, resource should show MOTOR 3 C06 and MOTOR 4 A04.
Restore your backup, carefully
Open your Step 2 backup in a text editor and delete these lines before pasting it into the CLI:
board_name,manufacturer_id,mcu_id,signature- any
resourceandtimerlines, which belong to the old target acc_calibration, so you can recalibrate fresh- anything the CLI marked
###ERROR IN diff: CORRUPTED CONFIG### align_board_yaw, unless you set it on purpose
Paste the rest, then type save.
Settings the Air75 needs
If you're starting fresh, here's the minimum. Paste into the CLI:
serial UART2 2048 115200 57600 0 115200
set yaw_motors_reversed = ON
saveWhat that does, and what to set in the app:
| Where | Setting | Why |
|---|---|---|
| Ports | UART2 Peripherals = VTX (SmartAudio) | Lets Betaflight control the video transmitter |
| Ports | UART3 Serial RX = on | The built-in ExpressLRS receiver |
| Receiver | Serial (via UART), provider CRSF | How ExpressLRS talks to Betaflight |
| Motors | Motor direction reversed = on | The Air75 flies props-out |
| Setup | Calibrate Accelerometer, drone flat | Required after every flash |
| Modes | ARM on a 2-position switch, ANGLE/HORIZON on a 3-position switch | Don't put ARM on a momentary button |
| Video Transmitter | Band, channel, power, then Save | Battery must be plugged in for the VTX to respond |
Two gotchas:
- The VTX table. The stock one has power levels 1/2/3/4 = 25/100/200/400 mW. Level 4 is 400 mW, not 200.
- ExpressLRS VTX Administrator. If you set VTX options in the radio's ExpressLRS menu, the radio pushes them to the drone every time it connects and silently undoes your Betaflight changes. Set its Band to Off, or make it match. Pick one boss.
Also, in the US, analog FPV at these power levels generally needs a ham radio license. Some Raceband channels sit outside the license-free 5.8 GHz band.
Step 7: Pre-flight checks, props off
Do all of these with the props removed and a battery plugged in. I found a reversed throttle this way. Full power at "zero throttle" is a much better discovery without props.
- ☐ Receiver tab: throttle stick down reads about 1000, up about 2000. Roll, pitch and yaw move the right way. If one is backwards, fix it on the radio (EdgeTX: MDL → OUTPUTS → that channel → Direction).
- ☐ Modes tab: the ARM marker sits inside the range only when the switch is in your armed position.
- ☐ Motors tab: all four spin, in the right corner (1 rear right, 2 front right, 3 rear left, 4 front left) and the direction the diagram shows.
- ☐ Arm test: unplug USB, throttle down, arm. Motors idle slowly and speed up with throttle.
- ☐ Failsafe test: while armed, switch the radio off. Motors must stop within a second or two.
- ☐ Battery reading: a charged 1S pack reads about 4.2 to 4.35 V.
- ☐ Props on, each matched to its motor's spin direction.
First flight: ANGLE mode, open room, gentle throttle, finger on the arm switch.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
No rule to make target 'arm_sdk_install' | Not in the repo folder | cd ~/src/betaflight first |
| App warns it doesn't support the firmware | Development build from master | Build a stable release tag |
| Flash hangs waiting for the device | Drone never entered DFU, or no USB permission | CLI bl, check lsusb for df11, redo Step 1 |
CONFIG: UNCONFIGURED, GYRO: None | Generic or wrong-target firmware | Flash the board-specific target (Step 3) |
| Motors 3 and 4 don't spin | V3 firmware on a V2 board | Flash BETAFPVG473_V2 |
| No motors spin in the Motors tab | No battery, or safety toggle off | Plug in a battery; turn on "I understand the risks" |
| All motors spin backwards | Props-out setting lost in the flash | set yaw_motors_reversed = ON |
| VTX tab: "not configured or not supported" | No battery, or UART2 not set to SmartAudio | Battery in; Ports → UART2 → VTX (SmartAudio) |
| VTX settings revert after unplugging | Radio's ExpressLRS VTX Administrator | Set its Band to Off, or match it |
| Receiver tab shows no movement | Wrong receiver mode, or not bound | Serial (via UART) + CRSF; check the receiver LED is solid |
Won't arm, only CLI and MSP flags | ARM range doesn't match the switch | Move the range to where the switch actually sits |
| Full power at zero throttle | Throttle channel reversed on the radio | Flip CH3 direction on the radio; never arm with props on until fixed |
| Bounces on the ground at idle | Air mode fighting the floor | Lower dshot_idle_value a little; disarm on landing |
| Video full of static | 5 GHz Wi-Fi on your channel | Move channels; I found one that works for me |
Sources
- Building in Arch Linux, Betaflight docs (partly out of date; this guide corrects it)
- Betaflight tools.mk:
arm_sdk_installtarget and required GCC version - Betaflight releases: 2026.6.2 stable
- Pin maps: the
BEFH/BETAFPVG473*board configs downloaded bymake configs, read on my machine