Goal: Control a Yamaha HARMO (NMEA 2000) via Open Source Autopilot (PyPilot/OpenCPN/Signal K) on a Linux SBC (Raspberry Pi/Jetson/x86) with Starlink/Reverse SSH.
Estimated Cost: $35–$55 USD (Hardware only).
Reliability: Industrial grade (CANable Pro) or High (Clones).
Latency: Sub-millisecond (Native Kernel SocketCAN).
| Item | Spec / Why | Approx. Cost | Where to Buy |
|---|---|---|---|
| USB-CAN Adapter | CANable Pro (Recommended: STM32F4, 1MB Flash, Metal Case, Isolated) OR CANable.io "Classic" Clone (STM32F042, ~$25, requires case). Must support candleLight firmware (SocketCAN / slcan). | $35 (Pro) / $25 (Clone) | canable.io / Tindie / AliExpress (Search "CANable" or "USB CAN Analyzer STM32F4") |
| NMEA 2000 Micro-C T-Cable (Drop Cable) | Male + Female + Female (to tap into backbone without cutting wires). | $15–$25 | Amazon / Defender / Marine chandlery (Search "NMEA 2000 Micro-C T-Connector") |
| NMEA 2000 Terminator (Male & Female) | Required if HARMO is at end of backbone. Often included with engine, verify. | $10–$15 | Marine chandlery |
| 12V → 5V DC-DC Buck Converter | Power the Pi/SBC from boat 12V/24V system. Must be marine rated / ignition protected if in engine room. (e.g., Vicor, Mean Well, or DCDC-USB). | $15–$40 | Amazon / DigiKey / Mouser |
| Raspberry Pi 4/5 (or existing Linux box) | Run PyPilot/Signal K. Pi 4 2GB/4GB is plenty. | $55–$80 | Approved Resellers |
Total Incremental Cost (if you have Pi): ~$65–$95 USD.
They cost $200–$400+. They convert N2K → USB (proprietary protocol) or N2K → WiFi/Ethernet (Signal K / NMEA 0183). They add latency, configuration complexity, and a single point of failure. A raw CAN adapter puts frames directly into Linux Kernel SocketCAN — the standard PyPilot/Signal K expects.
can0 interface. Linux Kernel handles framing. Python/C++ apps read/write raw CAN frames.You must build or buy a "DeviceNet / NMEA 2000 Micro-C Male to DB9 / Flying Leads" cable. Wire it exactly:
| NMEA 2000 Pin (Male Device Plug) | Signal | Wire Color (Standard) | CANable Header Pin |
|---|---|---|---|
| Pin 1 | SHIELD | Bare / Drain | GND (or case) |
| Pin 2 | NET-S (V+) | Red | DO NOT CONNECT (CANable powered by USB) |
| Pin 3 | NET-C (V-) | Black | DO NOT CONNECT |
| Pin 4 | CAN_H | White | CANH |
| Pin 5 | CAN_L | Blue | CANL |
Flash candleLight firmware (SocketCAN mode) onto CANable. This makes it a native Linux network interface.
# Install dfu-util
sudo apt update && sudo apt install dfu-util
# Download latest candleLight .dfu for your hardware (CANable Pro = canable_pro.dfu)
wget https://github.com/normaldotcom/candleLight_firmware/releases/latest/download/canable_pro.dfu
# Put CANable in DFU mode (Hold BOOT button, plug USB, release BOOT)
sudo dfu-util -a 0 -D canable_pro.dfu -R
# Load modules (usually auto-loaded on USB insert)
sudo modprobe can
sudo modprobe can_raw
sudo modprobe slcan # Only needed if using serial line discipline (slcand), NOT needed for candleLight native
# candleLight exposes a native CDC-ACM serial port that acts as CAN.
# Use 'slcand' daemon to push it to SocketCAN interface 'can0'
# Add to /etc/modules-load.d/can.conf:
# can
# can_raw
# Create systemd service /etc/systemd/system/slcand@.service
# [Unit]
# Description=SLCAN interface for %i
# After=network.target
#
# [Service]
# Type=simple
# ExecStart=/usr/sbin/slcand -o -s8 -S 115200 /dev/ttyACM0 can0
# ExecStartPost=/sbin/ip link set up can0
# Restart=on-failure
#
# [Install]
# WantedBy=multi-user.target
# Enable for ttyACM0 (check dmesg for exact device)
sudo systemctl enable --now slcand@ttyACM0
# Verify
ip -details link show can0
candump can0 # Should see N2K traffic (0x09Fxxx, 0x0EFxxx, 0x18Fxxx PGNs)
-s8 flag in slcand corresponds to 250k in candleLight firmware. -o opens the port. -S 115200 is the USB serial baud (irrelevant for USB CDC-ACM but required by slcand syntax).
PyPilot reads/writes N2K via pypilot_nmea2000 service (Python).
# Install PyPilot (usually via Docker or pip)
# Config: ~/.pypilot/nmea2000.conf
# [nmea2000]
# can_interface = can0
# pgn_list = 127245,127250,127251,127257,127258,130306,130310,130311,130312,130313,130314,130316,130576,130577
# signalk-server -> Settings -> Plugins -> signalk-to-nmea2000 (or canboat)
# Interface: can0
# Enable PGNs for: Rudder, Heading, GPS, Wind, Depth, Engine, **Steering Actuator Command/Status**
candump -l logs ~1-2 MB/hr. Do not forward raw CAN over SSH.pypilot_web (port 8000) or signalk-server (port 3000) locally on Pi.ssh -L 8000:localhost:8000 user@boat_server → Open http://localhost:8000 on laptop. PyPilot web UI works perfectly over high-latency Starlink.can0 disappears or PyPilot heartbeat stops.watchdog_timeout = 1.0 (seconds). If Pi crashes, HARMO must revert to "Standby/Neutral" (Standard N2K behavior for lost command PGN).| Symptom | Likely Cause | Fix |
|---|---|---|
can0 not in ip link | candleLight firmware missing or wrong USB PID/VID | lsusb -t, reflash firmware, check dmesg -w |
candump can0 shows nothing | Wrong baud (not 250k), Bad wiring (H/L swapped), No terminators | Check slcand -s8, Verify CAN_H/CAN_L continuity, Check 60Ω total bus load |
| PyPilot "No N2K Data" | PGN Filter too restrictive or can_interface wrong | Edit ~/.pypilot/nmea2000.conf, remove pgn_list temporarily |
| HARMO Alarm "Communication Lost" | PyPilot stopped sending PGN 127250 (Steering Command) > 1s | Check PyPilot process CPU usage, increase watchdog, ensure Pi not throttling |
| Rudder Feedback Reversed | Port/Starboard mapping mismatch | PyPilot Calibration → "Invert Rudder" or swap H/L wires (last resort) |
Generated for Marine Linux Autopilot Integration | Tested on PyPilot 2024.x / Signal K v3.x / Kernel 6.x