RoboDuckBuild

The head's code and wiring

The standard XGO-Duck has no screen, camera or voice. Ours has all three, run by a XIAO ESP32-S3 Sense in the head, with the UNO Q in the body moving the neck. Here's what each part does and how it's wired. None of it has met a real servo yet: they're still on their way.

Firmware on the XIAO

Written for the Arduino ESP32 core, with the board's PSRAM switched on because the camera needs it. It uses about a third of the flash and 41% of the memory.

  • The eye. A small driver for the GC9A01 round screen using Waveshare's own start-up sequence, with no graphics library. The eye is drawn pixel by pixel, 20 rows at a time, straight to the screen with no frame buffer: a dark eye-white, an iris with fine radial streaks and a dark rim, the pupil, two highlights, and eyelids whose curves set the mood. Six moods, neutral, happy, sad, angry, surprised and sleepy, each with its own iris colour. It blinks and glances about on its own.
  • The camera streams video on port 81, for a browser or for OpenCV. The control page turns the picture the right way up, because the camera is mounted on its side.
  • Sound. The microphone is on the chip's first audio port (it has to be) and the speaker amplifier on the second. It can play tones, a chirp, WAV and MP3 files, record a few seconds, or record and play straight back.
  • Control comes three ways: a web page and simple web commands at duck-head.local, text commands from the UNO Q over the serial link, or typed over USB.
  • Updates over Wi-Fi after the first USB upload. If it can't join the home network, it makes its own called Duck-Head and serves the page from there. Wi-Fi details live in a separate file that never leaves the workshop.

Web commands

The kind of thing the UNO Q, or anything on the network, can ask the head to do:

  • /eye?mood=happy set the mood
  • /look?x=0.3&y=-0.2 look somewhere
  • /blink, /bright?level=0-255
  • /tone?hz=880&ms=200, /chirp, /play (send a WAV or MP3)
  • /mic?s=3 record three seconds, /echo?s=3 record and play back
  • /capture one photo, /status everything as JSON

Which way up?

The screen and camera both sit on their sides in the face plate, so the picture needs turning, and it's easy to get backwards. At power-up the screen shows a white arrow with a red dot on one side and a green dot on the other. The arrow should point up with red on the left; if not, one setting turns or mirrors the eye's picture. Another turns the camera picture on the web page.

Wiring

The screen cable's jumper ends are cut off and soldered straight to the XIAO's pads, leaving the white plug on the screen. Pins D6 and D7 are kept for the serial link to the UNO Q, and D9 is left free for the microSD slot on the camera board.

BoardPinXIAONotes
ScreenVCC3V3
ScreenGNDGND
ScreenDIND10SPI data
ScreenCLKD8SPI clock
ScreenCSD1
ScreenDCD2
ScreenRST3V3Held high; the driver resets the screen by command
ScreenBLD0Backlight, dimmable
AmplifierVIN5V
AmplifierGNDGND
AmplifierDIND3I2S data
AmplifierBCLKD4I2S bit clock
AmplifierLRCD5I2S word select
UNO Q linkTX / RXD6 / D7Serial, through the neck later

Power. On the bench the XIAO runs from the UNO Q's 5V and GND pins, because the bracket covers its USB-C socket once it's in the face. Never power it from USB and the 5V pin at the same time. In the robot, a small 5 V regulator will feed the head from the battery so it doesn't load the driver board's own supply.

A wiring diagram for the XIAO, the round screen and the speaker amplifier
The wiring diagram from our bench guide.

Python on the UNO Q

Three scripts, for the five neck and head servos on the bench, through Feetech's FE-URT2 USB board.

  • A servo driver for Feetech's serial bus protocol: ping, read, write, move several at once and change an ID. It only needs pyserial, and it was tested against a simulated servo before any real ones arrived.
  • The set-up wizard takes one servo at a time, gives it the ID the build guide expects and parks it at the centre of its travel (step 2047 of 4096) before it goes in the robot. It can also list every servo on the bus with its position, voltage and temperature, or switch them all off.
  • The head script wiggles one joint so you can see which it is, runs a short demo of looking round, nodding, blinking and opening the beak, follows a face with its eye and head using OpenCV, and speaks through the head's speaker with espeak-ng while the beak flaps in time.

Servo IDs

From the XGO-Duck build guide: 10 to 14 and 20 to 24 for the legs, 30 to 34 for the neck and head, with 34 the beak. Each is centred at 2047 and set up alone on the bus. The guide doesn't say which head ID is which joint, so our names are a first guess, and every head joint is limited to a small range until we've found the real limits.

The bench stand and guide

The stand (S1) holds the head and neck by servo 30, between two ears copied from the body shells, with the UNO Q and the servo test board on its base. A ten-page guide covers the wiring, the first upload, fitting the screen and camera, setting servo IDs, the stand, the commands and what to check when something doesn't work. The whole story is in Firmware for a face.

Is the code available?

Not published yet.