> For the complete documentation index, see [llms.txt](https://docs.theseus.us/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.theseus.us/cyclops/cyclops-computer/example-pi-5-setup/hardware-configuration.md).

# Hardware configuration

Cyclops requires a **storage device**, a **camera**, and a **serial connection** to the flight controller.

## UART Serial Setup

Your device needs a serial connection to communicate with the flight controller using MAVLink. There are many ways to set this up. You can find docs on the manufacturer's website for your specific hardware setup.

For some computers such as the NanoPi R6C, you can buy a serial hat for UART connections. In the case of the Pi 5, you can read their [docs](https://www.raspberrypi.com/documentation/computers/configuration.html#configure-uarts) on configuring a serial port, or use our script below for easy setup.

#### Manual setup of MAVLink serial

UART0 is used for the MAVLink serial connection between the Pi 5 and the flight controller at 921600 baud.

Pinout: ([Pi 5 pinout diagram](https://vilros.com/pages/raspberry-pi-5-pinout))

| Function | GPIO | Header Pin | Connects To |
| -------- | ---- | ---------- | ----------- |
| TX       | 14   | Pin 8      | FC RX       |
| RX       | 15   | Pin 10     | FC TX       |
| GND      | —    | Any GND    | FC GND      |

{% hint style="info" %}
Both the Pi 5 and flight controller operate at 3.3V logic. No level shifting required.
{% endhint %}

#### Pi 5 UART naming

On Pi 5, GPIO 14/15 are driven by a PL011 UART in the RP1 southbridge, which shows up at MMIO `0x1f00030000`. The device node it enumerates to depends on the OS image:

* **Ubuntu 24.04 Desktop (Pi 5):** `/dev/ttyAMA0` (with a `/dev/serial0` symlink in some releases)
* **Ubuntu 24.04 Server (recommended for 2GB Pi 5):** `/dev/ttyAMA0`, no `/dev/serial0` symlink
* A second node `/dev/ttyAMA10` (at `0x107d001000`) will also appear — this is an internal SoC UART, **not** GPIO 14/15. Ignore it.

To confirm which node is GPIO 14/15, check `dmesg`:

```bash
sudo dmesg | grep -iE 'pl011|107d001|1f00030'
```

The line containing `1f00030000.serial` identifies the GPIO header UART (typically `ttyAMA0`).

**Setup:**

1. Disable the serial console if active (Desktop images sometimes enable this; Server typically does not):

```bash
    sudo systemctl disable serial-getty@ttyAMA0.service
    sudo systemctl stop serial-getty@ttyAMA0.service
```

2. Remove `console=ttyAMA0,115200` or `console=serial0,115200` from `/boot/firmware/cmdline.txt` if present:

```bash
    sudo nano /boot/firmware/cmdline.txt
```

{% code overflow="wrap" %}

```
The file should be a single line. Remove only the `console=ttyAMA0,...` or `console=serial0,...` token (leave everything else intact). Save with `Ctrl+O`, Enter, `Ctrl+X`.
```

{% endcode %}

3\. Edit `/boot/firmware/config.txt`. Under the `[all]` section, ensure the following are set:

```bash
    sudo nano /boot/firmware/config.txt
```

```
    enable_uart=1
    dtoverlay=uart0-pi5
```

{% code overflow="wrap" %}

```
Note: on Ubuntu for Pi 5, `enable_uart=1` alone is **not** sufficient — the `uart0-pi5` overlay is required to instantiate the PL011 on GPIO 14/15.
```

{% endcode %}

4\. Reboot. UART is available at `/dev/ttyAMA0`.

**Verification:**

Connect the Pi to the flight controller and ensure the corresponding serial port is configured to output MAVLink2 at 921600 baud. Then:

```bash
sudo stty -F /dev/ttyAMA0 921600 raw -echo
sudo cat /dev/ttyAMA0 | head -c 200 | xxd
```

You should see binary output with recurring `fd` bytes (MAVLink2 start byte) followed by a length byte and incrementing sequence numbers. Example:

```
00000000: fd1c 0000 d901 0121 0000 4704 1200 5d2c  .......!..G...],
00000010: 0000 18ae 0000 6a04 0000 6904 0000 0000  ......j...i.....
```

This confirms MAVLink data is flowing and the serial link is working. `Ctrl+C` to stop.

**Troubleshooting:**

* `cat: /dev/ttyAMA0: No such file or directory` → `uart0-pi5` overlay not loaded. Verify `config.txt` and reboot.
* Only `/dev/ttyAMA10` exists → same cause; the GPIO UART hasn't been instantiated.
* No `0x1f00030000.serial` line in `dmesg` → overlay didn't apply; check for typos in `config.txt`.
* Data flowing but garbled even at correct baud → check TX/RX aren't swapped, and confirm FC is set to MAVLink2 (not MAVLink1, which starts with `fe`).

### MAVLink over UDP/TCP

{% hint style="warning" %}
Cyclops has migrated from MAVProxy to MAVLink Router. `vns-config` commands still say `mavproxy`, but the service running is `mavlink-router.service`
{% endhint %}

For Cyclops v1.20.0 and later, MAVLink connection to the flight controller over UDP/TCP is supported. The CLI tool `vns-config` on the edge device is the only way to configure an IP MAVLink connection.

{% code title="On the edge device" %}

```bash
vns-config add mavproxy.device <mavproxy-endpoint>
```

{% endcode %}

Do not provide a baudrate for UDP or TCP endpoints. Supported endpoint settings:

<table><thead><tr><th width="310">Endpoint</th><th width="323">Use</th></tr></thead><tbody><tr><td><code>udpin:HOST:PORT</code></td><td>Listen for UDP (FC sends to Cyclops computer)</td></tr><tr><td><code>udpout:HOST:PORT</code> or <code>udp:HOST:PORT</code></td><td>Send UDP to that address</td></tr><tr><td><code>tcp:HOST:PORT</code> or <code>tcpout:HOST:PORT</code></td><td>Connect as a TCP client</td></tr></tbody></table>

{% hint style="info" %}
`tcpin` is not supported
{% endhint %}

When you add an endpoint that already exists, `vns-config` updates that entry. Adding an existing network endpoint without a baudrate clears any baudrate from that endpoint.

After changing endpoints, restart the MAVLink Router service and verify the active configuration:

```bash
sudo systemctl restart mavlink-router.service
vns-config list mavproxy.devices
journalctl -u mavlink-router.service -f
```

#### **Example: UDP MAVLink from a Flight Controller**

Configure the Pi to listen for MAVLink on UDP port `14550`:

```bash
vns-config add mavproxy.device udpin:0.0.0.0:14550
sudo systemctl restart mavlink-router.service
```

Point the flight controller or network sender at the Pi's IP address on port `14550`.

#### **Example: TCP MAVLink Server**

Configure MAVLink Router to connect to a TCP MAVLink server at `192.168.1.10:5760`:

```bash
vns-config add mavproxy.device tcp:192.168.1.10:5760
sudo systemctl restart mavlink-router.service
```

#### **Example: Replace Serial with Ethernet**

Remove the default serial ports and add a UDP network endpoint:

```bash
vns-config remove mavproxy.device /dev/ttyS4
vns-config remove mavproxy.device /dev/ttyS5
vns-config add mavproxy.device udpin:0.0.0.0:14550
sudo systemctl restart mavlink-router.service
```

## Enable USB Port Full Power

When powering the Pi 5 via the GPIO header (pins 2/4 for 5V, bypassing the USB-C PMIC), USB ports default to a 600mA total current budget. Override this to provide full power to USB peripherals.

Edit **`/boot/firmware/config.txt`:**

```bash
sudo nano /boot/firmware/config.txt
```

Add this line under the `[all]` section:

```
usb_max_current_enable=1
```

Save with `Ctrl+O`, Enter, `Ctrl+X`. Reboot to apply:

```bash
sudo reboot
```

This raises the total USB port current budget to 1.6A.

#### Recap

We have now set up all of our hardware. Your addresses may vary, but we have:

```
Recording drive at /mnt/t9
Serial connections at /dev/ttySC0 and /dev/ttySC1
Video device at /dev/video0
```
