> Documentation index: https://nao-rs.lukaloehr.com/llms.txt, a list of every page in this documentation.

# Temperatures, fan and thermal protection

> The head fan curve, the CPU alert and halt, the motor stop at 75 °C, and every temperature nao-rs reads, with its unit and source.

The NAO6 has two thermal concerns: the head computer's CPU, which a fan in
the head cools, and the motors in the joints. nao-rs watches both.

## The head fan

On HULKs-OS nothing controls the head fan: Aldebaran's fan daemon `alfand` is
installed but not started. nao-rs runs alfand's control law inside the
runtime, on its own thread, with the settings of the robot's own
`alfand.conf`. The law is identical to Aldebaran's library on 300,000 random
configurations (60.1 million steps).

At start-up the fan is set to **30 %**. Then, every **10 seconds**, one round:

1. read the CPU temperature;
2. above **94 °C**: log an alert;
3. above **95 °C**: trip the death switch (`Overtemperature`), wait, and halt
   the system;
4. otherwise move along the fan curve by at most one step and set the speed.

The curve has trip points at 65 and 70 °C with 1 °C of hysteresis on each
side:

| Speed | Reached when the temperature | Left when the temperature |
| --- | --- | --- |
| 50 % | starts here | reaches 66 °C (to 70 %) |
| 70 % | reaches 66 °C | reaches 71 °C (to 100 %) or falls below 64 °C (to 50 %) |
| 100 % | reaches 71 °C | falls below 69 °C (to 70 %) |

The fan curve and limits can't be changed through the runtime today. The
ported `alfand` program (below) reads an alfand key file with `-c`.

> **Info:** One deviation from alfand
>
> Aldebaran's alfand runs on with all-zero settings when its key file is
> missing or broken, which halts the system at the first reading above 0 °C.
> nao-rs refuses such a file instead.

## The motors

| Limit | Value | What happens |
| --- | --- | --- |
| Runtime motor stop | any joint at **75 °C** or more | The death switch trips (`Overtemperature`): all motors limp, latched |
| Temperature status per joint | from the motor board | 0 normal, 1 above the minimum, 2 near the maximum, 3 at the maximum, with hysteresis, as HAL computes it |
| HAL's motor temperature model | per joint | **Planned**: being ported, not yet in the runtime |
| HAL's battery over-current limit | 4.5 A battery current | In every frame: stiffness lowered to as little as 24 % while the battery current is above the limit, recovering after |

> **Warning:** Joint temperatures need accepted motor boards
>
> Joint temperatures come from the motor boards. Until nao-rs accepts the
> version 11 boards (the motor session, **planned**), they are not measured with
> real data, and the 75 °C stop has nothing to act on yet. The motors are limp
> in that state anyway.

The robot's ear LEDs show the hottest motor while `hulk` controls the LEDs, so
the warning comes before the stop: fully lit below 65 °C, two thirds from
65 °C, one third from 70 °C, dark from 74 °C. At 75 °C the death switch stops
the motors.

## Every temperature nao-rs reads

| Value | Source | Unit | How often |
| --- | --- | --- | --- |
| CPU (silicon) | Board controller of the head's CPU module, through `/dev/cgos` | °C, whole degrees | Every 10 s, by the fan thread; each reading is also written to `/var/run/alfand/cputemp` in thousandths of a degree |
| CPU, as the REST API reports it (`cpu_temperature` in `/v1/hardware`) | The hottest CPU core from Linux's `coretemp` sensors, the SoC's thermal sensors as the fallback | °C | About once a second |
| Face board | TMP100 on the head I2C bus | °C | About every 300 ms |
| Joints | Motor boards, through the chest board | °C, in steps of 2 °C | Every cycle (needs accepted boards) |
| Battery | Battery, through the chest board | See below | A few times a second, in turn with the battery's other registers |

The runtime and the MessagePack robot API report the battery temperature in
**LoLA's scale**: Aldebaran rounds it down to whole degrees and applies the
factor 0.1 twice, so 28.5 °C reads as 2.8. nao-rs keeps that value there, so
existing software reads the same numbers; multiply by 10 for whole degrees
Celsius. The [REST API](https://nao-rs.lukaloehr.com/reference/rest-api.md) converts it back and reports whole
degrees Celsius (28).

## Fan tools

The `fan` crate also builds ports of Aldebaran's tools. They are not in the
robot bundle yet; build them from the drivers repository.

| Tool | What it does |
| --- | --- |
| `alfand [-d] [-c file]` | The fan daemon. Without `-c` it uses the robot's settings built in |
| `fanspeed [0-100]` | Without an argument prints the fan speed, with one sets it |
| `faninfo` | Read-only: driver version, board, CPU temperature and fan state |

Don't run `alfand` or `fanspeed` while the runtime runs: the runtime already
controls the fan.

## Related topics

- [Safety model](https://nao-rs.lukaloehr.com/safety.md)
- [The death switch in detail](https://nao-rs.lukaloehr.com/safety/death-switch.md)
- Previous: [The death switch in detail](https://nao-rs.lukaloehr.com/safety/death-switch.md)
- Next: [The brain](https://nao-rs.lukaloehr.com/brain.md)
