PX4 Build & Configuration Walkthrough
This is the whole job, in order: a bare frame and a box of parts at one end, a multirotor hovering under PX4 at the other. It covers the assembly decisions that matter, then every parameter QGroundControl needs to be told before the aircraft will fly, and why each one exists.
PX4 is one of the two major open-source autopilot firmwares. Where ArduPilot grew out of hobby aviation and carries a great deal of configuration in a flat parameter list, PX4 grew out of academic robotics: it is the firmware you meet most often in research labs, in ROS-based work, and on aircraft with a companion computer on board. The configuration ideas are different enough that being fluent in one does not make you fluent in the other, and this guide points out where they diverge.
The example build is a small research quad — the sort of thing this firmware is most often used for:
| Part | Choice |
|---|---|
| Flight controller | NxtPX4 V2 — 20 × 20 mm, STM32H743, dual BMI088 |
| ESC | 4-in-1, 6S, 50 A, Bluejay firmware |
| Frame | 3.5-inch cinewhoop-style with ducts |
| Motors | 2004, 1750 KV |
| Propellers | 3.5-inch three-blade |
| Battery | 6S |
| Receiver | TRS — RC and telemetry in one |
| GPS | M10 module with compass |
Nothing below is specific to those parts except where it says so.
Propellers stay off until motor order and direction have been verified. A quad with its mixing wrong does not wobble — it flips instantly and at full power.
Check the ESC connector pinout against the flight controller's before you plug them together. The 8-pin connector between a 4-in-1 ESC and a flight controller carries battery voltage on one pin and low-voltage signals on the others, and the pin order is not standardised between brands. Plugging a mismatched cable in puts battery voltage straight onto a signal pin and destroys the flight controller the instant you connect the battery. If the two boards did not come as a set, compare both pinouts and make a cable, rather than assuming.
Assembly
Order matters here mostly because some things become unreachable once other things are fitted.
Motors first. Screw the four motors down with their wires pointing towards the centre of the frame. Check screw length against the motor — a screw that is a millimetre too long reaches the stator windings and shorts the motor, and it will look perfectly fine from the outside.
Then the ESC, on the 20 × 20 mm mounting pattern, with its connector facing the nose. Nylon standoffs are fine; M2 screws through rubber anti-vibration grommets are better, because the flight controller's accelerometers are measuring the frame's vibration whether you want them to or not.
Trim the motor wires to length and solder them to the ESC pads in any order. The order gets fixed later from the software side, and guessing now just means unsoldering later.
Solder the battery leads and the filter capacitor. The capacitor is not optional on a build with a long battery lead: it absorbs the voltage spikes the ESC's switching produces, which are the main cause of both electrical noise in the gyros and dead ESCs.
Then the flight controller, on standoffs above the ESC, connected with the ESC's own 8-pin cable (having checked the pinout, as above).
Mount the board any way round you like — PX4 can be told about it — but mounting it the default way, arrow or connector towards the nose, saves a step and one opportunity for error.
Outputs: the ESC protocol and motor order
Connect the flight battery and USB, and open QGroundControl. The Actuators page is where PX4 keeps everything about outputs.
Protocol
PX4 defaults its outputs to PWM at 400 Hz. Set them to DShot300.
PWM_MAIN_TIMn | Protocol |
|---|---|
| −5 | DShot150 |
| −4 | DShot300 |
| −3 | DShot600 |
| −1 | OneShot |
| 50 / 100 / 200 / 400 | PWM at that rate (400 is the default) |
The Actuators page sets these for you; the parameter is worth knowing because the timers are grouped, so one parameter usually covers several outputs and which outputs depends on the board.
DShot is digital: the throttle command travels as a number rather than as a pulse length. Three consequences follow. It cannot drift out of calibration, so there is no ESC calibration step — ignore any tutorial that tells you to do one. It is immune to the timing noise that affects analogue PWM. And it is what modern 4-in-1 ESCs running Bluejay or AM32 expect; many are configured for DShot only and will sit silently ignoring PWM.
A reboot is required before the new protocol takes effect.
Motor order and direction
Now the reason the motor wires were soldered in any order. In the Actuators page, each output can be assigned to a motor number, so you fix the order in software instead of with a soldering iron. On the example build the assignment came out as 3-2-1-4 — which is not a mistake, just what that particular combination of frame, ESC and wiring produced.
With propellers off and the safety switch released, spin each motor individually from the same page and check:
- Order — the motor PX4 calls 1 is the one that spins when you test motor 1.
- Direction — each motor turns the way the diagram on the page shows.
Order is fixed by reassigning outputs. Direction cannot be — swap any two of the three motor wires at the ESC, or reverse that motor in an ESC configurator over passthrough.
Receiver
External devices — receiver, GPS, anything on a 5 V rail — are powered from the battery, not from USB. Configure them with the flight battery connected, or they will simply not be there.
Two parameters set this up, and a handful of others have to be left alone.
RC_INPUT_PROTO says what the receiver speaks:
| Value | Protocol |
|---|---|
| −1 | Auto — scan for it (the default) |
| 0 | None |
| 1 | PPM |
| 2 | SBUS |
| 3 | DSM |
| 4 | ST24 |
| 5 | SUMD |
| 6 | CRSF |
| 7 | GHST |
Auto works, and setting it explicitly is faster and more predictable. SBUS for a classic receiver; CRSF for ELRS or Crossfire.
RC_PORT_CONFIG says which port the RC input driver listens on. It defaults to 300, "Radio Controller" — the connector marked RC on most boards — so if that is where your receiver is plugged in, it is already correct.
That is the whole configuration. The trap is a second set of parameters that look like they are also needed:
| Parameter | Default | Leave it at |
|---|---|---|
RC_SBUS_PRT_CFG | Disabled | Disabled |
RC_CRSF_PRT_CFG | Disabled | Disabled |
RC_GHST_PRT_CFG | Disabled | Disabled |
RC_DSM_PRT_CFG | Disabled | Disabled |
These are separate standalone drivers, one per protocol, for cases where you want that protocol on a port of its own. They are not the second half of RC_INPUT_PROTO.
RC_CRSF_PRT_CFG for a CRSF receiver will stop it workingThis is the counter-intuitive one, and it catches almost everybody. If you are running an ELRS or Crossfire receiver on the RC connector, RC_INPUT_PROTO = CRSF and RC_PORT_CONFIG = Radio Controller is the complete answer, and RC_CRSF_PRT_CFG stays Disabled. Setting it to Radio Controller as well puts two drivers on the same port, and the result is no RC input at all.
That pattern is the thing to internalise about PX4, and it is genuinely different from ArduPilot. On ArduPilot you go to a port and say what it is for. On PX4 you go to a feature and say which port it should use. Every feature that needs a serial port has a ..._CONFIG or ..._PRT_CFG parameter naming the port, and the port has its own SER_..._BAUD parameter for speed.
Reboot. With the receiver powered and bound, the Radio page should now show channels moving. Calibrate it: press the calibrate button and follow the instructions, moving every stick to its limits and every switch through every position.
Switches
On the Flight Modes page, assign:
- Mode channel → a three-position switch. A good first set is Stabilized, Altitude and Position.
- Arm switch → a two-position switch.
- Emergency kill switch → its own switch, and set this one up before the first flight rather than after. It cuts the motors immediately and unconditionally. It is the control you will want at the moment you have no time to think.
GPS and compass
On most boards these need no configuration at all — PX4 detects a GPS module on the GPS connector by itself. The parameters are worth knowing anyway, because they are what you check when it does not:
| Parameter | Should be | Meaning |
|---|---|---|
SYS_HAS_GPS | Enabled (default) | the system is expected to have a GPS |
GPS_1_CONFIG | 201 — GPS 1 (default) | which port the main GPS is on |
GPS_1_PROTOCOL | 1 — u-blox (default) | or 0 to auto-detect, which is slower |
SER_GPS1_BAUD | 0 — Auto (default) | the GPS driver finds the rate itself |
SYS_HAS_MAG | 1 (default) | how many magnetometers must be present for pre-flight checks to pass |
EKF2_MAG_TYPE | Automatic (0) | heading-only fusion on the ground, full 3-axis in flight |
SYS_HAS_MAG is a count, not a yes/no — that is the one that surprises people. Set it to 0 on an aircraft with no compass at all, and the pre-flight check stops demanding one.
Confirm it with the data, not the icons
Open MAVLink Inspector in QGroundControl's analyse tools. This lists every message arriving from the aircraft, live:
- A
GPS_RAW_INTmessage means the GPS is recognised and reporting. - Magnetometer values changing inside the scaled IMU messages mean the compass is being read.
Looking at the messages is a better answer than looking at the status icons, because you are seeing the actual data rather than something's opinion about it. Tilt the aircraft and watch the magnetometer numbers move.
Orientation
On the Sensors page, under orientations, there are two separate settings:
Flight controller orientation (SENS_BOARD_ROT) — leave at No rotation if you mounted the board facing forward the default way. Otherwise pick the rotation that matches.
Compass orientation (CAL_MAG0_ROT for the first compass) — this one almost always needs setting, because it depends on both the module's internal layout and how you mounted it. On the example build, an M10 GPS module fitted the usual way needed Pitch 180° (12).
An onboard compass cannot have its orientation changed — it is fixed to the board and rotates with it. QGroundControl reflects that by not offering the option.
Getting compass orientation wrong gives an aircraft that flies fine in manual modes and then circles, drifts or flies away in position modes, because the heading it believes and the heading it has are different. External Compass Orientation covers how to work the value out rather than guess it.
Calibration
Three, in this order.
Gyroscope. Put the aircraft down, leave it alone, press OK. It measures the zero offset of each gyro axis and takes a few seconds.
Accelerometer. The six-position calibration: level, both sides, nose down, tail down, inverted. Hold it still in each until the on-screen box turns green. Three axes measured in two directions each is where "six" comes from. "Level" must genuinely be level, because everything PX4 later believes about which way is down starts here.
Compass. Pick the aircraft up and calibrate it in the air, away from the ground — a desk with a steel frame, a car roof or a floor with rebar in it all have magnetic fields of their own, and calibrating against one bakes that distortion into the correction. Rotate the aircraft through the orientations the screen asks for until each turns green.
Set the compass orientation before calibrating, not after. Calibration corrects for the interference your aircraft produces; orientation tells PX4 which way the sensor is facing. Calibrating with the orientation wrong produces a correction fitted to a lie.
First flight
Fit the propellers. They come in clockwise and counter-clockwise versions and each has to match the direction of the motor it goes on — the test is simply that every propeller blows air downwards. A propeller on backwards produces a fraction of the thrust and a lot of noise, and the aircraft will fight itself off the ground.
Go somewhere open. Power up, and check QGroundControl reports the aircraft as ready to fly.
Fly the first flight in Stabilized. It self-levels but leaves the throttle entirely to you. Nothing automatic happens, which means nothing unexpected happens, and you can take over instantly. Altitude and Position modes are easier to fly and will hide a problem you would much rather meet at 30 centimetres.
Throttle to minimum, flip the arm switch, wait for the motors to reach idle, and raise the throttle smoothly. Hover low. Land. Check nothing is hot.
Telemetry radio
A telemetry radio removes the USB cable, which makes calibrating sensors and adjusting parameters in the field very much easier.
Wire the radio to a TELEM port, then:
| Parameter | Set to | Why |
|---|---|---|
MAV_0_CONFIG | the port used — 101 is TELEM 1 | claims the port for MAVLink |
MAV_0_MODE | 0 — Normal | the standard message set |
MAV_0_RATE | 0, or a value the radio can carry | bytes per second cap |
MAV_0_FORWARD | Disabled | stops MAVLink relaying traffic between links |
SER_TEL1_BAUD | whatever the radio is set to | must match exactly |
Two things to know.
Reboot after setting MAV_0_CONFIG, then set the baud rate. The port's baud parameter does not appear in the list until something has claimed the port. Looking for SER_TEL1_BAUD before that reboot and not finding it is a very common half-hour.
MAV_0_RATE is a cap in bytes per second. If the enabled streams would exceed it, PX4 slows them rather than overwhelming the radio. 0 means "use half the theoretical maximum", which is the baud rate divided by 20 — about 2880 B/s on a 57600 link. That is the right answer unless you have measured your radio and know better.
MAV_0_FORWARD defaults to enabled and passes messages between links so that, for example, a ground station can talk to a camera connected to the autopilot. On a simple aircraft it is traffic you are paying for and not using.
RSSI on the ground station
If your receiver reports link quality on a spare RC channel — the TRS puts RSSI on channel 12 — PX4 can display it.
Set RC_RSSI_PWM_CHAN to that channel number (12). The range is defined by RC_RSSI_PWM_MIN and RC_RSSI_PWM_MAX, which default to 1000 and 2000.
Signal strength then appears on QGroundControl's main screen. It is the single most useful number to have in front of you when deciding how much further to fly.
Battery monitoring
On the Power page, set the source to the power module and the cell count to your battery — 6 for a 6S pack.
Two scaling numbers turn what the board measures into volts and amps:
- Voltage divider (
BAT1_V_DIV) — the ratio between battery voltage and the voltage the flight controller's ADC sees. Most flight controllers measure voltage themselves through an onboard divider. - Amps per volt (
BAT1_A_PER_V) — current is usually measured by a shunt on the 4-in-1 ESC, which outputs a voltage proportional to current. This number converts it back.
Both default to −1, meaning "use the board's built-in value". The built-in value is a reasonable starting point and rarely exact, particularly for current, which depends on the ESC rather than the flight controller. QGroundControl has a calculate button for each: measure the real value with a multimeter or a watt meter, type it in, and it works out the correct coefficient. Your board's manual — for example the NxtPX4 V2 — gives the figures it ships with.
Getting these right matters more than it sounds. Battery percentage, remaining flight time and low-battery failsafe are all computed from them.
Optical flow and rangefinders
Position modes need a position source. Outdoors that is GPS. Indoors, or under a roof, an optical flow and laser rangefinder module can provide one instead — see the Optical Flow Setup Guide for the PX4 parameters.
How this differs from ArduPilot
Worth naming, because most people arrive at one of these firmwares already knowing the other:
| PX4 | ArduPilot | |
|---|---|---|
| Serial ports | the feature names its port (MAV_0_CONFIG) | the port names its function (SERIAL1_PROTOCOL) |
| Frame layout | chosen as an airframe type, then motors assigned per output | FRAME_CLASS and FRAME_TYPE |
| Motor order | reassign outputs in software on the Actuators page | pick the frame type that matches, or rewire |
| Compass fusion | EKF2_MAG_TYPE | COMPASS_USE, EKF source parameters |
| Ground station | QGroundControl | Mission Planner |
| First-flight mode | Stabilized | Stabilize |
Neither is better. PX4's feature-claims-port model scales more cleanly to aircraft with many peripherals; ArduPilot's is easier to picture when you have four things plugged in.
Easily confused points
The per-protocol RC driver parameters are a trap, not a second step. RC_INPUT_PROTO plus RC_PORT_CONFIG is the whole receiver configuration. Enabling RC_CRSF_PRT_CFG because you are using CRSF puts two drivers on one port and stops RC working.
The ESC's 8-pin connector is not a standard. Compare pinouts before plugging two brands together, every time.
USB does not power anything external. Receiver, GPS and ESCs all need the flight battery.
SYS_HAS_MAG is a count, not a switch. It is how many magnetometers must be present.
Set compass orientation before calibrating, not after.
SER_TEL1_BAUD does not exist until a feature has claimed TELEM 1 and the board has rebooted.
There is no ESC calibration on DShot. The step does not exist.
A propeller on backwards still spins. It just blows air the wrong way. Check every one.
Troubleshooting
| Symptom | Where to look |
|---|---|
| No motors in the Actuators test | Output protocol still PWM; flight battery not connected; safety switch not released. |
| Receiver not detected | Check RC_PORT_CONFIG names the right port, and that every RC_*_PRT_CFG is Disabled. Then wiring — CRSF needs both wires, crossed. |
| GPS not detected | Flight battery connected? Check GPS_1_CONFIG points at the right port and nothing else claims it. |
| Compass missing | Check the magnetometer data in MAVLink Inspector. SYS_HAS_MAG at 0 will also hide it. |
Cannot find SER_TEL1_BAUD | Set MAV_0_CONFIG first and reboot. The parameter appears once the port is claimed. |
| Telemetry connects then drops | Baud rate mismatch between radio and SER_TEL1_BAUD, or MAV_0_RATE set higher than the link can carry. |
| Flies fine manually, drifts in Position | Compass orientation. It is almost always compass orientation. |
| Battery percentage obviously wrong | Cell count, then the voltage divider, then amps per volt — in that order. |
| Aircraft struggles to lift off | A propeller fitted to the wrong rotation. |
Related guides
- ArduPilot Basic Configuration
- Flight Controller Firmware Flashing Guide
- NxtPX4 V2 — User Manual
- PX4 — Telemetry Setup Guide
- External Compass Orientation
- Flight Controller Board Orientation
- Optical Flow Setup Guide
Where to buy
Shipped from Canada with free Canada-wide shipping:
- NxtPX4 V2 — the 20 × 20 mm PX4 research board used in this walkthrough
- MicoAir H743 V2 — a full-size alternative that also runs PX4
Written and maintained by the Robofusion engineering team.