
Multicdc
ondras12345/multicdc
RP2040-based 6-channel USB to UART converter with Zephyr RTOS

Some notes + hardware designs for my OpenMower Mowgli build
Mower is an open-source printed circuit board by ondras12345, from the ondras12345/mower repository on GitHub, published under the MIT licence. It is a 2-layer board of 71.1 × 38.1 mm with 28 parts on 15 nets, routed with 77 tracks and 0 vias.
It is built around the NID65-5, Π122M30 and P4SMAJ5.0A. Its parts include 13 connectors, 4 capacitors, 2 resistors, 2 ICs and 2 diodes.
This repository contains various notes about my Mowgli OpenMower build.
I bought two broken mowers:
Yardforce 500
Yardforce 500 B
~/Downloads/NAS/completed/2025-05-13-raspios-bookworm-arm64-lite.img.xzopenmower.localsudoedit /etc/ssh/sshd_config: PasswordAuthentication nosudo apt update && sudo apt upgradesudo apt install tmux vim zsh git minicom etckeepersudo reboot# https://docs.docker.com/engine/install/debian/#install-using-the-repository
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
#sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt install -y docker-ce docker-compose-pluginSet docker to also log through standard systemd facilities:
sudo tee /etc/docker/daemon.json >/dev/null << "EOF"
{
"log-driver": "journald"
}
EOF
sudo systemctl restart docker.servicesudo apt install ufw
sudo ufw allow ssh
sudo ufw enable
# 4006 = mowgli GUI, 9002 = xbot_remote
sudo tee /etc/ufw/applications.d/openmower >/dev/null << "EOF"
[openmower]
title=openmower
description=Some openmower services, others need to be listed in /etc/ufw/after.rules
ports=4006/tcp|9002/tcp
EOF
sudo ufw app update openmower
sudo ufw allow in to any app openmower from 192.168.1.4 comment "ondra-lab"
sudo ufw allow in to any app openmower from 192.168.1.5 comment "ondra mobil"
sudo ufw allow in to any app openmower from 192.168.1.55 comment "tablet"
sudo ufw allow in to any app openmower from 192.168.54.111 comment "wg ondra-TP"
sudo ufw allow in to any app openmower from 192.168.54.112 comment "wg ondra mobil"Restrict traffic to docker containers not unit --network=host:
EDITOR=vi sudoedit /etc/ufw/after.rules
# ondra: filter traffic to docker containers
#-I DOCKER-USER -i wlan+ -j DROP
#-I DOCKER-USER -i wlan+ -s 192.168.1.5 -j RETURN
#-I DOCKER-USER -i wlan+ -s 192.168.1.4 -j RETURN
#-I DOCKER-USER -i wlan+ -s 192.168.1.55 -j RETURN
#-I DOCKER-USER -i wlan+ -s 192.168.1.114 -j RETURN
#-I DOCKER-USER -i wlan+ -s 192.168.54.111 -j RETURN
#-I DOCKER-USER -i wlan+ -s 192.168.54.112 -j RETURN
sudo ufw reloadsudo apt install borgmatic
sudo mkdir /etc/systemd/system/borgmatic.timer.d/
sudo tee /etc/systemd/system/borgmatic.timer.d/atnight.conf >/dev/null <<"EOF"
[Timer]
OnCalendar=
OnCalendar=*-*-* 00:30:00
RandomizedDelaySec=0
EOF
sudo systemctl daemon-reload
sudo generate-borgmatic-config
sudoedit /etc/borgmatic/config.yaml
sudo tee /root/.ssh/config <<"EOF"
Host rpi-borgbackup
User ondra
Hostname rpi.lab.lan
IdentityFile ~/.ssh/id_borgbackup_ed25519
EOF
sudo ssh-keygen -t ed25519 -f /root/.ssh/id_borgbackup_ed25519 -C "borgbackup mower"
sudo borgmatic init --encryption repokey-blake2
sudo systemctl edit borgmatic.service
#[Unit]
#OnFailure=notify-email@%i.service
#
#[Service]
#TimeoutStartSec=6hsudo tee /etc/udev/rules.d/50-mowgli.rules >/dev/null <<"EOF"
SUBSYSTEM=="tty" ATTRS{product}=="Mowgli", SYMLINK+="mowgli"
# simpleRTK USB
SUBSYSTEM=="tty" ATTRS{idVendor}=="1546" ATTRS{idProduct}=="01a9", SYMLINK+="gps"
# ESP USB CDC - RTK1010Board
SUBSYSTEM=="tty" ATTRS{idVendor}=="303a" ATTRS{idProduct}=="4001", SYMLINK+="gps"
# ondra
# Mowgli debug
SUBSYSTEM=="tty" KERNEL=="ttyAMA5", SYMLINK+="mowgli_debug"
# WTRTK-960 GPS - uses generic CH340 :-(
SUBSYSTEM=="tty" ATTRS{idVendor}=="1a86" ATTRS{idProduct}=="7523", SYMLINK+="gps"
# same GPS, but via GPIO UART
SUBSYSTEM=="tty" KERNEL=="ttyAMA2", SYMLINK+="gps2"
EOF
cd
git clone https://github.com/cedbossneo/mowgli-docker # 0ab26b9
cd mowgli-docker
sudo docker compose pull
vi .env # set both IPs to 127.0.0.1
sudo docker compose up -d
# see mowgli gui @ port 4006
# openmower web @ port 4005Back up mainboard firmware via stlink:
sudo apt install openocd
lsusb | grep ST-LINK # note the Bus xxx Device yyy
sudo chmod 666 /dev/bus/usb/001/003 # xxx/yyy
mkdir ~/firmware_backup
cd ~/firmware_backup
tee yardforce500.cfg >/dev/null <<"EOF"
source [find interface/stlink.cfg]
source [find target/stm32f1x.cfg]
transport select hla_swd
#reset_config srst_only srst_nogate
#program "firmware.bin" 0x08000000 verify reset; shutdown;
EOF
openocd -f yardforce500.cfg -c "init" -c "reset halt" -c " dump_image firmware_backup.bin 0x08000000 0x40000" -c "reset" -c shutdown
# connect ST-LINK to display panel
# Disconnect ribbon cable from main unit, power the target from ST-LINK.
# is seems to have a fake stm32, -c set CPUTAPID 0x2ba01477 is needed
# Not sure what ram backup is for. It is different each time.
openocd -c "set CPUTAPID 0x2ba01477" -f yardforce500.cfg -c "init" -c "reset halt" -c " dump_image panel_controller_ram.bin 0x20000000 0x10000" -c "reset" -c shutdown
openocd -c "set CPUTAPID 0x2ba01477" -f yardforce500.cfg -c "init" -c "reset halt" -c " dump_image panel_controller_backup.bin 0x08000000 0x10000" -c "reset" -c shutdownFirmware version:
$ sha256sum firmware_backup.bin panel_controller_backup.bin
875bedb32ccb62ee23453581c8af13e61a523bfe758120564d6bdb27cf641998 firmware_backup.bin
b3b1142bf84e09fd506bf4b399632b60d2a6ae3a520c685d3fdbca08e2c1fb88 panel_controller_backup.binThe upload tool does not work, build firmware manually:
cd
curl -fsSL -o get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py
python3 get-platformio.py
mkdir ~/bin
cd ~/bin
ln -s ~/.platformio/penv/bin/pio .
# start a new shell
cd
git clone https://github.com/cedbossneo/mowgli
cd ~/mowgli/stm32/ros_usbnode
pio run -e Yardforce500
lsusb | grep ST-LINK # note the Bus xxx Device yyy
sudo chmod 666 /dev/bus/usb/001/003 # xxx/yyy
pio run -e Yardforce500 -t uploadsudoedit /boot/firmware/config.txt
# # Mowgli debug UART
# dtoverlay=uart5
# # GPS UART
# dtoverlay=uart2
minicom -D /dev/ttyAMA5
# see udev rules above
minicom -D /dev/mowgli_debugsudoedit /boot/firmware/config.txt
# # onewire temperature sensor
# dtoverlay=w1-gpio
# set resolution
echo 11 | sudo tee /sys/bus/w1/devices/28-000000108239/w1_slave
echo 0 | sudo tee /sys/bus/w1/devices/28-000000108239/w1_slave
# read temperature
cat /sys/bus/w1/devices/28-000000108239/temperaturesudoedit /boot/firmware/config.txt
# [all]
# dtoverlay=disable-bt
# dtparam=audio=off
# hdmi_blanking=1
# hdmi_ignore_hotplug=1
# # comment out dtoverlay=vc4-kms-v3d
# [pi4]
# dtparam=pwr_led_trigger=none
# dtparam=pwr_led_activelow=off# test
sudo gpioset gpiochip0 18=1 # fan on
# sudo raspi-config
# 4 Performance options > Fan > Yes, 18, 75degCpython -m serial.tools.miniterm /dev/gps 115200 -eThe UART on the bottom row of pins and USB are both COM1.
The UART on the top row of pins (/dev/gsp2) is COM2.
FRESET
CONFIG COM1 921600
CONFIG COM2 115200
CONFIG COM3 115200
MODE ROVER SURVEY MOW
GPGGA COM1 0.1
GPGSV COM1 2
GPRMC COM1 1
GPGSA COM1 1
GPVTG COM1 1
GPGST COM1 1
GPGGA COM2 1
GNGSV COM2 1
GNGSA COM2 1
GNRMC COM2 1
JAMSTATUSA COM2 1
FREQJAMSTATUSA COM2 1
BESTNAVA COM2 1
ADRNAVA COM2 1
RTCMSTATUSA COM2 ONCHANGED
SAVECONFIGHere they recommend GPGGA 0.2 and GPGSV 2: https://openmower.de/latest/docs/step-by-step/2-robot-modification/prepare-the-parts/prepare-the-gps/
They seem to recommend MODE ROVER UAV, but let's try MODE ROVER SURVEY MOW
instead.
Let's try CONFIG RTK RELIABILITY 3 1.
It confidently drove ~1m too far. Let's try CONFIG RTK RELIABILITY 3 2.
Drove into the ditch. Let's try CONFIG RTK RELIABILITY 4 2.
Why is the default CONFIG RTK RELIABILITY 10 1? That is undocumented.
BESTNAV contains diff_age (age of RTK data from base station)
CONFIG dump before enabling COM2 messages (old, I changed stuff since then):
CONFIG
$command,CONFIG,response: OK*54
$CONFIG,ANTENNA,CONFIG ANTENNA POWERON*7A
$CONFIG,NMEAVERSION,CONFIG NMEAVERSION V410*47
$CONFIG,SCENE,CONFIG SCENE DISABLE*70
$CONFIG,RTK,CONFIG RTK TIMEOUT 40 20*79
$CONFIG,RTK,CONFIG RTK RELIABILITY 10 1*44
$CONFIG,RTK,CONFIG RTK MMPL 1*29
$CONFIG,BASE2,CONFIG BASE2 DISABLE*70
$CONFIG,BESTPARA,CONFIG BESTPARA 0 16.00 10.00 10.00 0.00 3.00 0 0 40*3A
$CONFIG,BESTPARA,CONFIG BESTPARA 1 -1.00 4.40 0.00 0.00 6 20 20 0*3F
$CONFIG,FITBESTPOS,CONFIG FITBESTPOS 1 20 3 100 1 1 0*25
$CONFIG,SCENEREG,CONFIG SCENEREG DISABLE*70
$CONFIG,SCENEREGPARA,CONFIG SCENEREGPARA 1.80 40.00 38.00 36.50 51652382 1264872960*3D
$CONFIG,MVTHD,CONFIG MVTHD 20 7.840 6.250 0.250 85 120 2 65*2A
$CONFIG,DGPS,CONFIG DGPS TIMEOUT 300*6C
$CONFIG,RTCMB1CB2A,CONFIG RTCMB1CB2A ENABLE*25
$CONFIG,ANTENNADELTAHEN,CONFIG ANTENNADELTAHEN 0.0000 0.0000 0.0000*3A
$CONFIG,RTK,CONFIG RTK MODE 0 0*27
$CONFIG,RTK,CONFIG RTK CN0THD 0*51
$CONFIG,CHECK,CONFIG CHECK 0 0.000 0.000 0.000 0.000 0 0.000*0A
$CONFIG,PPS,CONFIG PPS ENABLE GPS POSITIVE 500000 1000 0 0*6E
$CONFIG,SIGNALGROUP,CONFIG SIGNALGROUP 2*16
$CONFIG,ANTIJAM,CONFIG ANTIJAM AUTO*2B#VERSION,62,GPS,FINE,2426,121153300,16528,0,18,92;UM960,R4.10Build16528,HRPT00-S10-C-P,2310415000017-MH23C6251910901,ff3b3d643ae0ff0d,2024/10/14*7233682dSet up gpsd
sudo apt install ser2net
sudoedit /etc/ser2net.yaml
sudo systemctl restart ser2net
sudo apt install netcat-openbsd
# nc -C localhost 5015 # raw connection to gps2 (both rx and tx; gpsd.service can be left running)
sudo apt install gpsd
sudoedit /etc/default/gpsd
# DEVICES="tcp://127.0.0.1:5015"
# GPSD_OPTIONS="-n -b"Discord c.ez:
set export OM_ANTENNA_OFFSET_X=1.234 export OM_ANTENNA_OFFSET_Y=1.234 in your mower config file. (0/0) is the point between the wheels of your mower, X is to the front and Y is to the left, unit is m. So if your antenna is 10cm to the front relative to the origin, and centered left/right, then you would put 0.1 and 0.0
Setting
export OM_ANTENNA_OFFSET_X=0.290
export OM_ANTENNA_OFFSET_Y=-0.030TODO rtkbase sucks, just use str2str as packaged by debian. TODO set base cable length 10m (for PPS timing absolute accuracy)
sudo tee /etc/udev/rules.d/50-rear-panel-getty.rules >/dev/null <<"EOF"
SUBSYSTEM=="tty", ATTRS{busnum}=="1", ATTRS{devpath}=="1.1", SYMLINK+="rear_panel_tty", TAG+="systemd", ENV{SYSTEMD_WANTS}+="serial-getty@rear_panel_tty.service"
EOF
sudo udevadm control --reload-rules
sudo EDITOR=vi systemctl edit serial-getty@rear_panel_tty.service
# [Service]
# ExecStart=
# ExecStart=-/sbin/agetty -o '-p -- \\u' - 115200 $TERM
# Restart=always
# RestartSec=1
sudo systemctl enable serial-getty@rear_panel_tty.servicesudo apt install dma mailutils
sudoedit /etc/dma/dma.conf
sudo tee -a /etc/aliases >/dev/null << "EOF"
# catch-all alias, but only for local users
*: root
root: REDACTED
EOF
sudo newaliases
sudo tee "/etc/systemd/system/notify-email@.service" >/dev/null <<"EOF"
[Unit]
Description=Send email to root
[Service]
Type=oneshot
ExecStart=sh -c 'systemctl status %i | mail -s "[mower SYSTEMD] Failed service: %i" root'
# workaround:
# https://serverfault.com/questions/982318/mail-stuck-in-exim-queue-for-no-reason
# https://systemd-devel.freedesktop.narkive.com/nV1QMO8j/exim4-only-queues-mails-sent-by-systemd-service
KillMode=process
EOF
sudo systemctl daemon-reloadUsage:
[Unit]
OnFailure=notify-email@%i.serviceThe SD card is extremely slow. If we ever need more mem, zram would be a better choice.
sudo systemctl disable --now dphys-swapfile.service
sudo rm /var/swap# installed in ~/rtkrover_influx1
sudo tee /etc/systemd/system/rtkrover_influx1.service >/dev/null <<"EOF"
[Unit]
Description=Log GPS and system stats to influxdb
After=ser2net.service
Wants=ser2net.service
OnFailure=notify-email@%i.service
[Service]
Restart=on-failure
RestartSec=30
User=openmower
Environment="INFLUX_DSN=influxdb://mowgli1:REDACTED@192.168.1.110:8086/rtkrover"
WorkingDirectory=/home/openmower/rtkrover_influx1/
ExecStart=/home/openmower/rtkrover_influx1/gps_log.py
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now rtkrover_influx1.serviceconfig/om/rosconsole.config: set log4j.threshold=INFO (was OFF).
Now it logs both to docker compose logs and rostopic echo /rosout (with
details like line numbers).
| Qty | Value | Footprint | References |
|---|---|---|---|
| 13 | Conn_01x01 | Connector_Wire:SolderWire-0.25sqmm_1x01_D0.65mm_OD1.7mm_Relief | J1, J2, J3, J4, J5, J6, J7, J8, J9, J10, J11, J12, J13 |
| 4 | MountingHole | MountingHole:MountingHole_3.2mm_M3 | H1, H2, H3, H4 |
| 2 | 100n | Capacitor_SMD:C_1206_3216Metric_Pad1.33x1.80mm_HandSolder | C1, C3 |
| 2 | 1k | Resistor_SMD:R_1206_3216Metric_Pad1.30x1.75mm_HandSolder | R1, R2 |
| 1 | 22u / 25V X5R | Capacitor_SMD:C_1206_3216Metric_Pad1.33x1.80mm_HandSolder | C4 |
| 1 | EKM227M1HG1BRRSHP | Capacitor_THT:CP_Radial_D10.0mm_P5.00mm | C2 |
| 1 | NID65-5 | ondra:Converter_DCDC_MeanWell_NID65_THT | U2 |
| 1 | P4SMAJ5.0A | Diode_SMD:D_SMA_Handsoldering | D1 |
| 1 | PTF/15 | Fuse:Fuseholder_Cylinder-5x20mm_Stelvio-Kontek_PTF78_Horizontal_Open | F1 |
| 1 | SMAJ28A-13-F | Diode_SMD:D_SMA_Handsoldering | D2 |
| 1 | Π122M30 | Package_SO:SOIC-8_3.9x4.9mm_P1.27mm | U1 |
It measures 71.1 × 38.1 mm and has 2 copper layers, 1.6 mm thick.
28 parts, built around the NID65-5, Π122M30 and P4SMAJ5.0A. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the ondras12345/mower repository on GitHub, at the commit this page was made from: the board is hardware/mower/mower.kicad_pcb and its schematic hardware/mower/mower.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository publishes it under the MIT licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).

ondras12345/multicdc
RP2040-based 6-channel USB to UART converter with Zephyr RTOS

Kofen/PoE_Ethernet_GPIB_Adapter
This folder contains the necessary hardware files for the PoE Ethernet GPIB Adapter project.

RichardRozehnal/Atari-SIO2SD-Mini
Atari SIO2SD disk drive emulator for 8bit Atari.


joeycastillo/Sensor-Watch
A board replacement for the classic Casio F-91W wristwatch

TalismanDesign/PocketMage_PDA
An E-Ink PDA device using the ESP32 S3.

rusefi/rusefi
rusefi - GPL internal combustion engine control unit

hackclub/OnBoard
💡 Join 1,000 teenagers and make your first PCB with a $100 grant!