Skip to main content

Reachy Mini × XIAO Screen Motion Control

Combine the Reachy Mini robot with the XIAO ESP32-S3 Plus touch display — using the built-in IMU sensor (LSM6DS3), tilting the screen controls the robot's body sway, head yaw, and head pitch.

Reachy Mini × XIAO Screen Motion Control Demo

PlatformControllerSensorLanguage


Demo​

ActionRobot ResponseScreen Display
Tilt screen left/rightBody sway + head yaw (left/right)Kaomoji tilts with direction
Tilt screen forward/backHead pitch (nodding up/down)—
Screen held stillRobot stays still (manual trigger)Kaomoji returns to center

The screen displays a ≧∇≦ kaomoji, rotated 90° upright, swaying with the tilt direction. The XIAO screen display pattern can be customized — refer to the 1.47 inch Touch Display Getting Started tutorial to compile and flash your own pattern.


Hardware​

HardwareDescription
Reachy Mini Wireless KitUSB connected to PC
1.47 inch Touch Display — XIAO ESP32-S3 PlusBuilt-in LSM6DS3 IMU sensor
PC (Windows)Python 3.11+
USB-C cables ×2One for screen, one for robot

Software Setup​

Step 1. Install Arduino CLI​

Download and install from Arduino CLI Releases.

Step 2. Install ESP32 Board Support​

arduino-cli config init

Edit ~/.arduino15/arduino-cli.yaml and add the ESP32 board URL under board_manager.additional_urls:

board_manager:
additional_urls:
- https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

Install the ESP32 core:

arduino-cli core install esp32:esp32
tip

Select XIAO_ESP32S3_Plus as the board target (fqbn) for the screen.

Step 3. Install Seeed GFX Library​

The screen display depends on the Seeed_GFX library. Install it from GitHub into your Arduino libraries directory.

Step 4. Install Python Dependencies​

pip install reachy-mini pyserial numpy

Step 1: Get the Project Code​

git clone https://github.com/Genie-INSPIRE/reachy-mini-sway-screen.git
cd reachy-mini-sway-screen

Project contents:

FilePurpose
reachy_sway_screen/reachy_sway_screen.inoScreen firmware: reads IMU + serial output + draws kaomoji
reachy_sync/sway_follow.pyMain control program: reads serial + controls robot
reachy_sync/start_daemon.pyReachy Mini daemon launcher

Step 2: Flash the Screen Firmware​

1. Find the Screen COM Port​

Plug in the screen via USB, open Device Manager, and find the USB-Serial/JTAG COM port (VID 0x303A).

note

The screen is auto-detected by VID, so COM port number changes don't matter.

2. Compile and Flash​

arduino-cli compile --fqbn esp32:esp32:XIAO_ESP32S3_Plus -u -p COM9 --warnings none reachy_sway_screen

Replace COM9 with your actual screen COM port.

3. Calibrate Neutral Position​

  1. Place the screen flat on a table (keep it level)
  2. Wait 2 seconds (screen shows hold neutral)
  3. Auto-samples for 0.5 seconds, saves neutral to NVS (persists after power off)
  4. To recalibrate: send the letter c to the screen via a serial tool (115200 baud)
caution

You must calibrate the neutral position on first use or when switching screens, otherwise tilt angles will be off.


Step 3: Start the Robot Daemon​

1. Find the Robot COM Port​

Plug in the robot via USB, find the CH343 chip COM port in Device Manager (VID 0x1A86).

2. Set the COM Port​

Edit reachy_sync/start_daemon.py and change COM14 to your actual robot COM port:

# Open start_daemon.py in an editor, change COM14 to your actual port

3. Start​

cd reachy_sync
python -u start_daemon.py

You should see Uvicorn running on http://127.0.0.1:8000 — success!

tip

Open http://127.0.0.1:8000/ in a browser to confirm the daemon is running.


Step 4: Run the Main Control Program​

cd reachy_sync
python -u sway_follow.py

You should see:

screen connected on COMx
connected
ready: L/R tilt -> body sway + head yaw. F/B tilt -> head pitch.

Tilt the screen, and the robot will follow!


How It Works​

Data Flow​

Screen IMU (LSM6DS3)
ax = left/right tilt, ay = forward/back tilt
tilt = -asinf(ax), pitch = -asinf(ay)
deadband filter + gain + low-pass filter
Serial output: "sway <value> pitch <value> rad" (115200 baud)
↓
Python (sway_follow.py)
Reads serial data
Two-stage low-pass filter (0.22)
Computes body_yaw, head yaw, head pitch
↓
Reachy Mini Daemon (port 8000)
set_target(body_yaw, antennas, head)
↓
Robot motors execute

Screen Firmware Parameters​

ParameterValueDescription
GAIN6.0Tilt amplification factor — higher = more sensitive
FILT0.25Low-pass filter coefficient — lower = smoother but slower
AMP0.7Max output amplitude (rad), ~40°
deadband0.008Dead zone (rad), ignores tilt under 0.5°

Robot-Side Parameters​

ParameterValueDescription
HEAD_K0.40Head yaw gain (left/right)
HEAD_PITCH_K0.65Head pitch gain (up/down)
Filter coefficients0.22 / 0.22Two-stage low-pass — lower = smoother

Antenna Mirroring​

The two antenna motors on Reachy Mini are mirror-mounted:

  • Right antenna (index 0): positive = leans left, negative = leans right
  • Left antenna (index 1): positive = leans right, negative = leans left

To make both antennas lean the same direction, use opposite signs: subtract for right, add for left.


Parameter Tuning​

Too Laggy​

  • Increase screen FILT (e.g. 0.25 → 0.30): stronger filtering on screen side
  • Decrease robot-side filter coefficient (e.g. 0.22 → 0.15): smoother but slower response

Too Slow / Need Large Tilts​

  • Increase screen GAIN (e.g. 6.0 → 8.0): small tilts trigger bigger movements
  • Increase robot-side filter coefficient (e.g. 0.22 → 0.30): faster response

Head Direction Reversed​

ProblemSolution
Left/right reversedFlip tilt sign (tilt = -asinf(ax) in .ino)
Up/down reversedFlip pitch sign (pt = -asinf(ay) in .ino)

Kaomoji Direction Wrong​

ProblemSolution
Rotation angleModify drawFigure(dyn + 1.5708f) — 1.5708 = 90°
Tilt direction reversedChange dyn = kaoDev * 2.0f to dyn = -kaoDev * 2.0f

FAQ​

Q: What to do after power loss?

A: Restart the daemon (python start_daemon.py), then start sway_follow.py. Screen firmware and neutral calibration are saved in NVS and won't be lost.

Q: COM port number changed?

A: The screen is auto-detected by VID (0x303A), no change needed. Update the robot COM port in start_daemon.py.

Q: Robot not moving?

A: Check if the daemon is running on port 8000 (open http://127.0.0.1:8000/ in browser). If not, restart the daemon.

Q: Screen not displaying or not sending data?

A: Check USB cable, reflash firmware, use a serial tool (115200 baud) to verify sway ... pitch ... rad output.

Q: Head direction reversed?

A: Left/right reversed → flip the sign in tilt = -asinf(ax) in the .ino file. Up/down reversed → flip the sign in pt = -asinf(ay).


Tech Support​


References​

Loading Comments...