Hardware

LEDs

Every LED group of the NAO6, every single LED's index from the robot API down to the driver chip's channel, the colour order, the value conversion and how to set them.

A NAO6 has 2 × 8 RGB eye segments, 2 × 10 ear LEDs, 12 skull LEDs, an RGB chest LED and an RGB LED in each foot. The head LEDs sit on the head's I2C bus, the chest and foot LEDs behind the chest board.

The groups

GroupLEDsColourDriven byRobot API fieldRuntime command
Left eye8 segmentsRGB3 LED driver chips, one per colourleft_eye: 8 × Rgbleft_eye: [f32; 24]
Right eye8 segmentsRGBthe same 3 chipsright_eye: 8 × Rgbright_eye: [f32; 24]
Left ear10one colourLED driver at 0x61left_ear: 10 × brightnessleft_ear: [f32; 10]
Right ear10one colourLED driver at 0x60right_ear: 10 × brightnessright_ear: [f32; 10]
Skull12one colourLED driver at 0x65not settableskull: [f32; 12]
Chest1RGBchest boardchest: Rgbchest: [f32; 3]
Left foot, right foot1 eachRGBfoot boardsleft_foot, right_foot: Rgbleft_foot, right_foot: [f32; 3]

The runtime's commands use LoLA's arrays, so software written for LoLA sets the LEDs unchanged. The robot API sits on top of them and converts.

Values and colour order

WhereValueColour order
Robot API, Rgbthree bytes, 0..255red, green, blue
Robot API, ears0..1, limited to that rangebrightness only
Runtime, eyes0..1 per LEDplanar: all 8 reds (indices 0..7), then all 8 greens (8..15), then all 8 blues (16..23)
Runtime, chest and feet0..1 per channelred, green, blue
Runtime, ears and skull0..1 per LEDbrightness only

A runtime value becomes one byte without a gamma curve and without clamping, exactly as LoLA and HAL do it: the head LEDs take value × 255 truncated toward zero, the chest and foot LEDs value × 255 rounded to the nearest whole number. 1.0 gives 255 either way. Values above 1 or below 0 wrap around in the byte (1.5 gives 126 on a head LED), so keep runtime values within 0..1. The robot API can't produce such values: it sends bytes divided by 255 and limits ear values to 0..1.

Eyes

Each eye has 8 segments around it. In the robot API, segment i is at i × 45°: segment 0 at the top, then clockwise as seen from the front of the robot.

The three eye chips each drive one colour of both eyes: the chip at 0x62 red, 0x64 green, 0x66 blue. Channels 0 to 7 belong to the left eye, 8 to 15 to the right eye.

Left eye

API segmentAngleRuntime index (red, green, blue)Chip channel
00°1, 9, 170
145°0, 8, 161
290°7, 15, 232
3135°6, 14, 223
4180°5, 13, 214
5225°4, 12, 205
6270°3, 11, 196
7315°2, 10, 187

Right eye

API segmentAngleRuntime index (red, green, blue)Chip channel
00°0, 8, 168
145°1, 9, 179
290°2, 10, 1810
3135°3, 11, 1911
4180°4, 12, 2012
5225°5, 13, 2113
6270°6, 14, 2214
7315°7, 15, 2315

The left eye's runtime array is ordered differently from the right eye's (it comes from LoLA's own key order), but on the chips both run in angle order.

Ears

Each ear has 10 LEDs in a ring, one every 36°. In the robot API, LED i of either ear is the one at i × 36°.

AngleAPI indexLeft ear runtime indexLeft ear chip channelRight ear runtime indexRight ear chip channel
0°00599
36°11688
72°22777
108°33866
144°44955
180°55044
216°66133
252°77222
288°88311
324°99400

The right ear's runtime array runs backwards relative to the API. Channels 10 to 15 of the ear chips are unused and stay off.

Skull

Runtime indexChip channel
0, 1, 2, 3, 4, 5, 6, 7, 88, 7, 6, 5, 4, 3, 2, 1, 0
9, 10, 1111, 10, 9

The robot API can't set the skull today. hulk shows the battery on it: the LEDs light up to the charge level and run an animation while the robot charges.

Chest and feet

The chest LED goes to the chest board every cycle as one message (red, green, blue), except in a cycle that changes the chest board's client state; the foot LEDs go to the two foot boards (red, green, blue each).

Who sets them

SituationEyesEarsSkullChestFeet
The runtime before its controller sends anythingwhite (as LoLA without a client)onoffoffoff
hulk's own status, robot unstiffrainbowhottest motor (full below 65 °C, dark from 74 °C)batteryblinking blue
hulk's own status, playingwhitehottest motorbatterygreen
hulk's own status, robot API linkdark before a client connected, green while connected, red after it was lost
Robot API Leds messageper group: a group set to None keeps hulk's statusnot settable

A Leds message with every group None, or Leds(None), hands all LEDs back to hulk.

Setting them

From the robot API, send a Leds message (MessagePack, see Robot API). Example, as JSON for readability: a red left eye and a green chest, everything else left to hulk:

{
  "Leds": {
    "left_eye": [[255,0,0],[255,0,0],[255,0,0],[255,0,0],[255,0,0],[255,0,0],[255,0,0],[255,0,0]],
    "right_eye": null,
    "left_ear": null,
    "right_ear": null,
    "chest": [0, 255, 0],
    "left_foot": null,
    "right_foot": null
  }
}

From Rust, in the runtime, set the arrays of robot::Commands and pass them to Robot::command. The runtime forwards the head LEDs to the head thread and the chest and foot LEDs to the chest board:

let mut commands = robot::Commands::default();
commands.chest = [0.0, 0.0, 1.0];          // blue
for i in 8..16 {                            // green, every segment
    commands.left_eye[i] = 1.0;
    commands.right_eye[i] = 1.0;
}
robot.command(&commands);

To test the head LEDs on the robot, with hulk stopped: naoctl head 10 cycles the eyes through red, green and blue and turns the ears and the skull on for 10 seconds.

From the REST API, with a lease (see REST API):

curl -X PUT -H "Authorization: Bearer $TOKEN" -H "Nao-Lease: $LEASE" \
  -H 'Content-Type: application/json' -d '{"color": "#0055ff"}' \
  http://$ROBOT:7702/v1/leds/eyes

It knows the same groups plus eyes, ears and feet for both sides at once, single LEDs (/v1/leds/left_eye/0), presets, and animations computed on the robot at 20 Hz: breathe, blink, rainbow (not on the ears) and progress. Any LED write to a group cancels its animation, animations end with the lease, and their frames don't count as a heartbeat. Colours are "#rrggbb". See LEDs in the REST API.

On this page