I2C PWM servo multiplexing is a communication and control architecture where a microcontroller offloads precise pulse-width timing to a dedicated driver chip over a two-wire bus, allowing simultaneous control of multiple servos without blocking the main CPU. When you unbox a Petoi robot dog Bittle, you aren't just getting a bionic toy; you are holding a masterclass in this exact embedded design. By offloading the 50Hz pulse-width modulation (PWM) generation to an I2C driver, the ESP32 at the heart of Bittle is freed up to handle complex inverse kinematics and IMU sensor fusion without missing a beat.
The Core Architecture: What I2C PWM Multiplexing Actually Is
In a real circuit, I2C PWM multiplexing fundamentally changes the interrupt and timer load on your microcontroller. Standard direct-drive PWM requires the MCU's internal hardware timers to toggle GPIO pins at precise microsecond intervals. If you try to bit-bang or use hardware timers for 12 servos on an ESP32, you will quickly exhaust the available LEDC (LED Control) channels and starve the CPU cycles needed for other tasks.
By inserting an I2C PWM driver (like the NXP PCA9685 or its integrated equivalent on Petoi's NyBoard V2) between the MCU and the servos, the architecture shifts. The ESP32 only needs to send a few bytes over the I2C bus to say, "Set channel 4 to 1500µs." The driver chip's internal 25MHz oscillator then handles the actual pin toggling in the background.
Makers frequently confuse standard GPIO hardware PWM with I2C offloaded PWM. This leads to a classic beginner mistake: trying to wire 9 servos directly to ESP32 GPIO pins, wondering why the onboard MPU6050 IMU stutters, and experiencing massive servo jitter. The I2C offload is what prevents this resource collision.
Inside the Petoi Bittle: A Worked Numeric Example
Let's look at the actual math happening inside the Bittle's NyBoard V2 when it commands a leg joint to move. The board drives standard 3-pin hobby servos (typically the P1S-9G or similar 9g micro servos) which expect a 50Hz signal. This means the total period is 20ms (20,000µs), with the active pulse width varying between 500µs and 2500µs to dictate the angle.
The I2C PWM driver uses a 12-bit resolution, meaning the 20ms period is divided into 4096 discrete steps.
If the Bittle's inverse kinematics engine calculates that the front-right knee needs to be at its exact center position (1500µs pulse width), the ESP32 doesn't send "1500". It sends the step count:
- Target Pulse: 1500µs
- Step Calculation: 1500 / 4.88 = 307.37
- Register Value: 307 (Hexadecimal
0x0133)
The ESP32 writes this 12-bit value across the I2C bus to the driver's ON/OFF registers. At Fast I2C speeds (400kHz), transmitting the 4 bytes required to update a single servo channel takes roughly 0.08ms. Updating all 9 active servos on Bittle takes less than 0.75ms. This leaves 19.25ms of the 20ms cycle completely free for the ESP32 to read the IMU, calculate the next gait trajectory, and process wireless commands. For deeper technical specifications on the driver chip's internal timing, refer to the NXP PCA9685 datasheet.
Where You Meet This in Practice: Bittle Modding and Debugging
When you start modifying your Petoi robot dog Bittle—perhaps adding a LiDAR puck for SLAM or upgrading to higher-torque metal-gear servos—you will directly interact with the physical realities of this I2C architecture.
If your Bittle's legs twitch randomly while standing still, do not immediately blame the code. 90% of the time, this is an I2C bus noise issue or a power rail brownout. The NyBoard V2 separates the 6V servo power from the 3.3V logic, but if you add long I2C jumper wires for an external sensor, you increase the bus capacitance. Standard I2C limits are around 400pF. Exceeding this rounds off the square-wave clock edges, causing the PWM driver to misinterpret commands. The fix: Drop the I2C pull-up resistors from the standard 4.7kΩ down to 2.2kΩ to sharpen the edges.
Another practical encounter is the IMU interrupt line. The Bittle relies on the IMU's data-ready interrupt to trigger a sensor read exactly when the servo PWM cycle is stable. If you write custom firmware via the official Petoi documentation and forget to configure the ESP32's interrupt pin as open-drain, the IMU and the I2C bus will fight for the line, resulting in a locked-up robot.
Decision Tree: Upgrading or Replacing Bittle's Servo Brain
As of 2026, the maker community has heavily modded the Bittle platform. If you are pushing the limits of the stock NyBoard V2 and ESP32-WROOM-32, use this decision path to determine your next hardware upgrade.
| If Your Goal Is... | And Your Constraint Is... | Then Choose This Concrete Pick |
|---|---|---|
| Running ROS2 vision processing and SLAM | Must keep real-time servo jitter under 5µs | Raspberry Pi 5 (4GB) as a companion computer. Wire it to the NyBoard via UART. Let the Pi handle OpenCV/ROS2 and send high-level gait commands to the ESP32. |
| Upgrading to 20kg high-voltage servos (e.g., PDI-HV5523) | Stock NyBoard 6V 5A BEC will instantly brownout under load | Hobbywing 10A UBEC (5V/6V switchable). Wire it directly to the servo power pins on the NyBoard, completely bypassing the onboard buck converter. |
| Adding 4+ extra I2C sensors (LiDAR, ToF, BNO055) | Hitting the 400pF I2C bus capacitance limit | Adafruit I2C Bus Extender (PCA9615). This splits your bus into differential pairs, allowing you to run long sensor cables without signal degradation. |
| Replacing the ESP32 for a custom PCB design | Need native USB and more flash for audio barks | ESP32-S3-WROOM-1 (N16R8). It offers native USB for faster firmware flashing and 16MB flash to store uncompressed WAV files for Bittle's speaker module. |
For most users looking to add advanced autonomy without redesigning the robot from scratch, adding the Raspberry Pi 5 as a companion brain is the definitive path. It preserves the rock-solid real-time I2C PWM control of the NyBoard while providing the teraflops of compute needed for modern machine learning models. For more on ESP32 peripheral limits, consult the Espressif ESP32 Technical Reference Manual.
Frequently Asked Questions
Can I power Bittle's servos directly from the ESP32's 5V pin?
Absolutely not. A single 9g servo can draw 800mA under stall conditions. Bittle has 9 servos. If two legs slip simultaneously, the current spike will exceed 3A, instantly tripping the USB port's overcurrent protection or frying the ESP32's internal voltage regulator. Always use the dedicated servo power rail fed by a high-current BEC or LiPo battery.
Why does Petoi use I2C PWM instead of serial bus servos?
Serial bus servos (like the DSS-M15 or Dynamixel) communicate via UART and offer positional feedback, which is excellent for advanced robotics. However, they cost $20 to $50 each. By using I2C PWM multiplexing with standard $3 hobby servos, Petoi keeps the Bittle kit under $300 while still achieving highly coordinated gaits through open-loop inverse kinematics.
My Bittle's I2C bus scans as empty when I connect a new sensor. What's wrong?
Check the logic voltage levels. The NyBoard V2 runs the ESP32 at 3.3V, meaning the I2C SDA/SCL lines are pulled up to 3.3V. If you connect a 5V-only I2C sensor module that requires a 4V minimum to recognize a logic HIGH, it will ignore the ESP32. Use a bidirectional logic level shifter (like the BSS138-based Adafruit modules) to bridge the 3.3V and 5V domains safely.






