A drone with 2 propellers, commonly known in robotics as a bicopter, is a twin-rotor aerial platform that achieves pitch and yaw control by physically tilting its motors via servos rather than relying solely on differential motor speeds. While a standard quadcopter simply spins two diagonal motors faster to induce yaw torque, a 2-propeller build forces your microcontroller to manage a hybrid mixing matrix, outputting both high-torque ESC signals and high-frequency servo PWM simultaneously. This fundamentally changes your embedded circuit architecture: you can no longer rely on a single power rail or a single timer peripheral, and you must allocate dedicated high-current BECs (Battery Eliminator Circuits) to prevent logic brownouts. Builders frequently confuse this configuration with a coaxial helicopter (two stacked props on a single shaft) or a twin-engine fixed-wing, but the bicopter is unique because its servos act as the primary flight control surfaces in hover.

The Mixing Matrix: Math Behind the Tilt

In a quadcopter, the mixing matrix maps PID outputs (Roll, Pitch, Yaw, Throttle) directly to four motor speeds. In a drone with 2 propellers, Yaw and Pitch are decoupled from motor RPM and mapped instead to servo angles. Roll is achieved by differential motor thrust, while Yaw is achieved by differential servo tilt.

Let us look at a worked numeric example using standard RC PWM microsecond (µs) pulse widths, where 1500µs is the center/neutral position.

Worked Numeric Example: Yaw Command
Assume the drone is hovering. Base Throttle = 1500µs. The PID controller calculates a Yaw error and outputs a corrective demand of +200µs.

Motor Allocation:
Left Motor = Throttle + (Roll * 0) = 1500µs
Right Motor = Throttle - (Roll * 0) = 1500µs
(Motors do not change speed for yaw).

Servo Allocation (Yaw Mix Factor = 0.5):
Left Servo = Center + (Yaw * 0.5) = 1500 + 100 = 1600µs (Tilts forward 5°)
Right Servo = Center - (Yaw * 0.5) = 1500 - 100 = 1400µs (Tilts backward 5°)

The physical vectoring of the thrust creates a rotational moment around the Z-axis, yawing the drone without altering the total vertical lift.

If you are writing your own flight controller firmware on an ESP32 or Arduino, you must implement this matrix in your main control loop, ensuring the servo outputs are constrained to your mechanical limits (usually ±30 degrees, or roughly 1100µs to 1900µs) to prevent the servos from stalling against the frame.

Where You Meet This in Practice

When transitioning from theory to the workbench, a drone with 2 propellers introduces three major embedded systems constraints that do not exist on standard multirotors:

  1. Timer Peripheral Conflicts: Standard analog servos require a 50Hz PWM signal (20ms period). Brushless ESCs running DShot600 or OneShot125 require much higher frequencies (e.g., 4kHz to 375kHz). On the ESP32-S3, you cannot easily run both from the same LEDC (LED Control) timer group without resolution loss. You must route servos to the LEDC peripheral and ESCs to the MCPWM (Motor Control PWM) peripheral.
  2. Power Distribution Asymmetry: A 12g servo can draw 600mA to 1.2A at stall. If your flight controller's onboard 5V regulator is rated for 1A, commanding an aggressive yaw maneuver will stall both servos, pull 2.4A, and instantly sag the logic rail.
  3. I2C Bus Vulnerability: Because the servos are physically mounted near the center of mass (and thus near the IMU), the high-current PWM switching and motor EMI can induce noise on the I2C SDA/SCL lines, causing the MPU6050 or BNO085 to drop off the bus mid-flight.

For deeper integration details on handling these peripheral conflicts, refer to the Espressif MCPWM API documentation and the ArduPilot Bicopter configuration guide.

Real-World Scenario Walkthrough: The Brownout Yaw Spin

To understand why power rail isolation is non-negotiable, consider this real-world bench test that went wrong during a prototype build.

The Setup: An ESP32-S3 DevKit mounted on a carbon fiber bicopter frame. Two 2205 2300KV motors driven by 30A ESCs. Two MG90S metal-gear servos for tilting. The IMU was an I2C MPU6050. The builder powered the ESP32 and both servos from a single 5V 3A UBEC wired directly to the microcontroller's 5V and GND pins.

The Numbers: The UBEC was rated for 3A continuous. The MG90S servos have a stall current of roughly 1.1A each. The ESP32-S3 draws about 250mA. Total theoretical max draw: 2.45A. This appeared to be safely within the 3A UBEC limit.

The Outcome: During a bench test with props off, the builder commanded a rapid, full-stick yaw sweep. The ESP32 output the correct 1100µs and 1900µs pulses. The servos snapped to their mechanical limits and stalled. Instantly, the ESP32 rebooted, and the motors spun up to 100% throttle (the default failsafe state of the ESCs when PWM is lost).

What Went Wrong: The 3A UBEC rating was a peak marketing spec, not a transient response spec. When both servos hit mechanical stall simultaneously, they drew a combined transient inrush of nearly 3.5A. The UBEC's output voltage sagged from 5.0V down to 3.6V for roughly 40 milliseconds. The ESP32-S3's internal brownout detector (BOD) tripped at 3.3V, resetting the chip. Furthermore, the I2C pull-up resistors lost their voltage potential, causing the IMU to throw a bus error right before the reset. The fix was straightforward: run a dedicated 5V 2A BEC exclusively for the servos, and power the ESP32 and IMU from a separate, clean 5V rail, joining only the ground planes.

ESP32-S3 Hardware Mapping and Refresh Rates

If you are wiring this up today, use the following pin mapping and peripheral allocation to ensure your PID loop runs cleanly without timer interrupts colliding.

Component ESP32-S3 Pin Peripheral Frequency / Protocol Resolution
Left Servo (Tilt) GPIO 4 LEDC Channel 0 50 Hz 14-bit (16384)
Right Servo (Tilt) GPIO 5 LEDC Channel 1 50 Hz 14-bit (16384)
Left ESC (Motor) GPIO 18 MCPWM Operator 0 DShot600 (375 kHz) N/A (Digital)
Right ESC (Motor) GPIO 19 MCPWM Operator 1 DShot600 (375 kHz) N/A (Digital)
IMU (MPU6050) GPIO 1 (SDA) / 2 (SCL) I2C Master 400 kHz (Fast Mode) N/A

By keeping the 50Hz analog servo signals on the LEDC peripheral and the high-speed digital ESC signals on the MCPWM peripheral, you prevent the ESP32's internal timer mux from dropping PWM pulses during high CPU load states.

Frequently Asked Questions

Can I use standard analog servos for a 2-propeller drone, or do I need digital?
You can use analog servos for initial prototyping, but they suffer from a deadband (usually ±5µs) and slower transit times. For a stable hover, you should upgrade to digital servos (like the KST X12 or similar 12g digital models) which respond to 1µs changes and hold their position much more rigidly against the torque of the brushless motors.

Why does my drone oscillate in yaw but not in roll? Yaw oscillation in a bicopter is almost always caused by servo linkage slop or PID derivative (D) gain being too high on the yaw axis. Because the servos act as a physical lever arm, any mechanical play in the ball links translates directly into IMU noise. Tighten your linkages, apply a slight low-pass filter to your gyro data (around 30Hz), and reduce your Yaw D-term.

How do I handle the center of gravity (CG) shifting as the servos tilt?
Unlike a quadcopter, the physical mass of the motors and props moves forward and backward as the servos tilt, shifting the CG. In practice, this shift is minor on small frames (under 250g), but on larger builds, you must mount the battery on a sliding rail and tune your pitch PID to account for the slight coupling between throttle and pitch angle.