> For the complete documentation index, see [llms.txt](https://guide.petoi.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://guide.petoi.com/product/quaddle-under-construction/control-and-program/controller.md).

# Controller

{Game controller operation demonstration video}

<figure><img src="https://4130507397-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXLpFdG7mubqEHWylLK3w%2Fuploads%2FowlQGHyiQgoGhlfz0Bjw%2Fimage.png?alt=media&amp;token=3d434859-8a04-4f66-8113-9777ee7e991c" alt=""><figcaption></figcaption></figure>

Quaddle is compatible with firmware-supported BM769, GamepadSpace-Q34B, and GamepadSpace-Q37 Bluetooth gamepads.

Before powering on the controller, please dial the mode switch on the back of the controller to the **D** position.

{Image of the mode switch on the back of the controller}

{% hint style="info" %}
The raw A/B and X/Y bits on the Q37 differ from those on the Q34B. The firmware automatically swaps them before mapping the controls to the physical labels printed on the gamepad. Users can therefore always follow the A, B, X, and Y labels shown on the gamepad itself.
{% endhint %}

## Connecting and Getting Started

{% stepper %}
{% step %}

### Power on

Press the **Home** button (![](https://4130507397-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXLpFdG7mubqEHWylLK3w%2Fuploads%2FmibA8TfJBN3NZ41Afp2m%2Fimage.png?alt=media\&token=fb649ab8-e81b-429a-bb3b-cff4f1ef3fdf)) to turn on the controller and make it discoverable, then start the robot. At startup, the robot scans for a supported controller for approximately 1 second. When one is found, the robot automatically enters **GamepadClient** mode and connects. Simultaneously, the controller will emit vibration feedback.
{% endstep %}

{% step %}

### Finishing control

Return the left stick to the center to stop any movement it initiated and restore the standing posture. Click the **Pair** button at the top of the controller to power it off. If the controller disconnects unexpectedly, the robot program also automatically sends the "**kup**" safe-standing command.
{% endstep %}
{% endstepper %}

{% hint style="info" %}

### Note

**Wait for the gamepad to connect**

A previously saved gamepad is given priority when reconnecting. Once connected, the sticks and buttons can directly control the robot.

**No gamepad is found during startup**

Bluetooth enters mobile App Server mode. If the mobile app is not connected, briefly press the mainboard BOOT button to clear the old gamepad information, return to gamepad scanning, and pair the current gamepad.

**How to connect to the other gamepad**&#x20;

When the robot successfully connects to a controller for the first time, it saves the controller information. Upon the next power-up, it will connect only to the controller that was saved via Bluetooth and will not connect to other controllers. If you are sure you want to connect to another controller in this case, without connecting to the mobile app, first press the **Home** button on the new controller to power it on, and then briefly press the **Boot** button on the side of the robot. This will clear the previously saved controller Bluetooth information and then establish a Bluetooth connection with the new controller.
{% endhint %}

{% hint style="warning" %}
Holding the **Boot** button on the side of the robot for 2 seconds clears Wi-Fi configuration; it is not a gamepad-pairing operation.&#x20;

If the mobile app is connected, briefly pressing **Boot** on the side of the robot will **not** interrupt the app session (just clear the previously saved controller Bluetooth information) or switch to gamepad mode.
{% endhint %}

## Basic Functions

The image below shows all the function joysticks and buttons, and their functions after individual movement, long press, or click:

<figure><img src="https://4130507397-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXLpFdG7mubqEHWylLK3w%2Fuploads%2FSt1Ealu2JdOOx1aOm0kF%2Fimage.png?alt=media&amp;token=81801ac5-0feb-43ea-96b0-59cc4f21042d" alt=""><figcaption><p>Model: Q34B</p></figcaption></figure>

{% hint style="success" %}
The left pad functions (UP, LEFT, RIGHT) are used only on the Quaddle Scout.
{% endhint %}

#### Macro Recording and Playback

| Stage              | Gamepad Operation                                                                              | Result                                                                                                                                 |
| ------------------ | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| Start recording    | Hold the **Program** button for at least 1 second                                              | Clears the old macro and starts recording. The serial output displays `[MACRO] recording`.                                             |
| Record actions     | Operate the sticks and buttons normally                                                        | Records up to 48 robot commands that were actually accepted, including the interval between adjacent commands.                         |
| Stop and save      | Briefly press the **Program** button                                                           | Stops recording and retains the macro in runtime memory. The serial output displays the number of saved steps.                         |
| Start playback     | Briefly press the **Program** button again                                                     | Plays from the first step using the recorded timing intervals.                                                                         |
| Interrupt playback | Briefly press the **Program** button during playback, or execute another valid gamepad command | Stops the current playback immediately.                                                                                                |
| Clear the macro    | Hold the **Program** button again, disconnect/re-pair, or restart                              | A long press clears the old macro and starts a new recording. Resetting the connection state or restarting clears the in-memory macro. |

{% hint style="info" %}
The BM769 right trigger (RT on the Q34B) is reported as R2 in firmware events, while the internal button-bit enum calls it `ZR`. ZR and R2 therefore refer to the same right trigger in this document. In the current code, pressing it first toggles R2 gyroscope balancing once. Continuing to use the left stick or D-pad while holding it also executes the corresponding combination action. O and T are additional face buttons on the Q34B/Q37 and are generally not present on the BM769.
{% endhint %}

## Combination control functions

The image below shows the combination control functions:

{% hint style="success" %}
**Tips:**&#x20;

To trigger the combined control function, first press and hold the button, then immediately move the joystick or press the directional buttons on the left pad.
{% endhint %}

<figure><img src="https://4130507397-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FXLpFdG7mubqEHWylLK3w%2Fuploads%2FIlpv6emxwbRKOfucqN5E%2Fimage.png?alt=media&amp;token=08afbf77-0b6f-4028-95cd-e012fcf8435e" alt=""><figcaption></figcaption></figure>

### L2/LT(ZL) + Right Stick: Screen Expressions and Eye Color

Start with the right stick centered, hold L2/LT (named `ZL` in the code) button, and then move the right stick. As soon as the stick enters a direction, the firmware automatically switches to the eye view and applies the corresponding display effect.

| Combination                    | Screen Effect             | Behavior                                                                                                                                                                   | Serial Command                |
| ------------------------------ | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| Hold L2/LT + right stick up    | Select the next eye color | Changes color once each time the stick enters the up direction. While continuing to hold L2, return the stick to center and move it up again to keep cycling.              | `vc*`                         |
| Hold  L2/LT + right stick left | Listening expression      | Makes the eye-socket outline thicker and changes it to a pale version of the active palette. The effect ends when the stick leaves the left direction or L2 is released.   | `veL` / `vel`                 |
| Hold L2/LT+ right stick right  | Talking expression        | Displays an animated pink mouth at the bottom of the screen and adds randomized eye movement. The effect ends when the stick leaves the right direction or L2 is released. | `veT` / `vet`                 |
| Hold L2/LT + right stick down  | Cycle the eye mood        | Each center-to-down movement advances through squint → happy → sad → normal. Returning to center or releasing L2 does not cancel the selected mood.                        | `veP` → `veH` → `veS` → `ves` |

The colors cycle in this fixed order: **blue → orange → pink → green → red → yellow → purple → blue**.&#x20;

The corresponding serial commands are: `vcb` (Blue), `vco` (Orange), `vcp` (Pink), `vcg` (Green), `vcr` (Red), `vcy` (Yellow), and `vcv` (Purple).

The selected color is saved in the robot's persistent configuration and remains selected after a restart.

{% hint style="info" %}
Squint reduces the eye height to approximately one-half. Happy and sad reduce it to approximately two-thirds and reshape the upper and lower eye corners, respectively; happy also widens the eyes. These three moods are mutually exclusive, but the active mood can be combined with listening or talking. Listening and talking are temporary direction-held effects, and switching between left and right cancels the previous effect first. A mood remains active until the next downward cycle or another command resets it.
{% endhint %}

{% hint style="info" %}
The right stick uses dominant-direction classification: for diagonal movements, the axis with the greater absolute displacement determines the selected action. The entry threshold is approximately 50, and the return-to-center threshold is approximately 30, which prevents jitter near a boundary. After L2/LT(ZL) has been used as a right-stick modifier, releasing it does not trigger its individual short- or long-press step-climbing action.&#x20;
{% endhint %}

## Operating Precautions

<table data-search="false"><thead><tr><th width="338.800048828125">Scenario</th><th>Recommendation or Firmware Behavior</th></tr></thead><tbody><tr><td>Performing rolls, jumps, handstands, step climbing, or similar actions</td><td>Place the robot on an open, level, non-slip surface, away from table edges, people, and fragile objects.</td></tr><tr><td>Using button combinations</td><td>Hold A/B/X/Y/ZR/R1 before moving the left stick or tapping the D-pad. Moving the stick first may initiate normal walking. </td></tr><tr><td>Rapidly changing the left-stick direction</td><td>The firmware discards older unexecuted stick-movement states and retains the latest direction, reducing control lag.</td></tr><tr><td>Gamepad disconnects or is turned off</td><td>The firmware clears pending gamepad commands and macro state, then queues <code>kup</code> for a safe standing posture. New input is required after reconnecting.</td></tr><tr><td>During Wi-Fi provisioning</td><td>If a gamepad is connected, the firmware may disconnect it temporarily to avoid BLE/Wi-Fi coexistence congestion. It scans and reconnects automatically after provisioning.</td></tr><tr><td>A D-pad module shortcut has no effect</td><td>Check that the corresponding sensor module is installed, its build option is enabled, and its interface is connected correctly.</td></tr><tr><td>An action name is unavailable on a particular robot model</td><td>The mapping sends the same action ID, but actual availability depends on the current robot model and its skill table.</td></tr></tbody></table>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://guide.petoi.com/product/quaddle-under-construction/control-and-program/controller.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
