Hacking the HiWonder MasterPi!
For Lucas' birthday, he got a HiWonder MasterPi robotic arm. He wanted to learn to code and wanted a robotic arm, so this is the one I found. It's a VERY cool product, however out of the box it had a LOT of issues. We did NOT get the included RaspberryPi, meaning we had to get and provision one ourselves (we got a 4b, and I strongly recommend this over a 5 as a python package is not yet built for the 5), and it was a mess out of the box. I googled a lot, but didn't find a lot of resources about this product, so I figured I would make a guide to help other people who want to go on this journey.
IMPORTANT NOTE: it's impossible to get to the sdcard of the pi once it's assembled, so do all the pi provisioning first. At least get it onto the internet so you can ssh/vnc into it later.
When you get this, some instructions come pointing you to this google drive with the system images: https://drive.google.com/drive/folders/1HFL5PVNSByu93iu684BVlrJzYYIZY8RH We downloaded this and flashed it to an sd card with dd, then went through the instructions. This didn't work well at all; it never joined our wifi, and when in direct connect mode the app didn't do what it was supposed to. We plugged the pi into an ethernet wire and an hdmi screen with a USB keyboard and learned that it is VERY localized to China; this localization became a pain because the desktop is difficult to navigate to change it (and connecting to the desktop over VNC is part of the project as provided), the wifi region code wouldn't stay changed since their python code manages the wifi, and ultimately we couldn't get it to stay on a 5GHz wifi and had to provision a 2.4 network. All in all, this wasn't a great situation.
So we pivoted. We got rpi-imager and prepped a new sdcard with regular old Raspbian bookworm. Using rpi-imager, we gave it a hostname, provisioned the wifi, and changed the default username from pi to something else (this matters later). We also enabled SSH and set all the Locale stuff. Once this was all done, we provisioned the Pi and were able to connect over ssh (and confirmed over hdmi/usb).
Once in over ssh, we ran "sudo raspi-config", went to "Interface Options" and enabled VNC and I2C.
WayVNC, raspbian's VNC Server, uses a self-signed certificate, and most linux VNC clients use libvncserver which will fail the check for self signed certificates. The only easy fix is to edit "/etc/wayvnc/config" and change "enable_auth=true" to "enable_auth=false" but this disables ALL VNC authentication, so use extreme caution! For this application, a battery powered toy likely only used on the LAN, it's probably reasonable, but in general it's an insecure idea. Additionally, if you need ipv4 edit "/etc/wayvnc/config" and change "address=::" to "address=0.0.0.0". After those changes, restart wayvnc with "systemctl restart wayvnc". You can now connect to the pi over VNC (I like remmina as a VNC client on Ubuntu).
Once in VNC, download the MasterPi software from the Source Code directory of your pi version from the link in the packaged instructions: https://drive.google.com/drive/folders/1HFL5PVNSByu93iu684BVlrJzYYIZY8RH All 3 of the folders need to be in the raspberry pi's main user's home folder, downloaded using the browser from the vnc ui.
- hiwonder-toolbox
- MasterPi
- MasterPi_PC_Software
From the terminal or ssh, install some dependencies:
sudo apt -y install python3-opencv python3-yaml python3-jsonrpc python3-matplotlib python3-pandas python3-pyqt5.qtsql
sudo pip3 install rpi_ws281x --break-system-packages # As of 2024.09.18 this is unsupported on the Pi5: [https://github.com/jgarff/rpi_ws281x/issues/528](https://github.com/jgarff/rpi_ws281x/issues/528 "https://github.com/jgarff/rpi_ws281x/issues/528")
Next, move the folders to /etc
sudo mv ~/hiwonder-toolbox /etc/
sudo mv ~/MasterPi /etc/
sudo mv ~/MasterPi_PC_Software /etc/
The software as provided hardcodes a lot of paths to /home/pi/ which we need to change to /etc/
sudo find /etc/MasterPi/ -type f -exec sed -i 's/\/home\/pi\//\/etc\//g' {} +
sudo find /etc/MasterPi_PC_Software/ -type f -exec sed -i 's/\/home\/pi\//\/etc\//g' {} +
HiWonder's image comes with 5 systemd services; we will be installing 4 of them (two are connected to their wifi AP service which we won't be using).
- /etc/systemd/system/hw_button_scan.service
[Unit]
Description=key_control
[Service]
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/bin/python3 /etc/hiwonder-toolbox/hw_button_scan.py
ExecStop=/bin/systemctl kill hw_button_scan
[Install]
WantedBy=multi-user.target
- /etc/systemd/system/hw_find.service
[Unit]
Description=find wifi
[Service]
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/bin/python3 /etc/hiwonder-toolbox/hw_find.py -t MasterPi
ExecStop=/bin/systemctl kill hw_find
[Install]
WantedBy=multi-user.target
- /etc/systemd/system/hw_remote.service
[Unit]
Description=remote
[Service]
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/bin/python3 /etc/hiwonder-toolbox/hw_remote.py
ExecStop=/bin/systemctl kill hw_remote
[Install]
WantedBy=multi-user.target
- /etc/systemd/system/masterpi.service
[Unit]
Description=Start MasterPi
[Service]
Type=simple
Restart=always
RestartSec=5
ExecStart=/usr/bin/python3 /etc/MasterPi/MasterPi.py
StandardOutput=null
StandardError=null
[Install]
WantedBy=multi-user.target
Scan services, enable them, and start them
systemctl daemon-reload
systemctl enable hw_button_scan.service
systemctl start hw_button_scan.service
systemctl enable hw_find.service
systemctl start hw_find.service
systemctl enable hw_remote.service
systemctl start hw_remote.service
systemctl enable masterpi.service
systemctl start masterpi.service
Create a folder on the user's desktop called "Arm" with the following contents
[Desktop Entry]
Name=Arm
Comment=Arm Program
Encoding=UTF-8
Exec= /usr/bin/python3 /etc/MasterPi_PC_Software/Arm.py
Terminal=false
MultipleArgs=false
Type=Application
Categories=Application;Development;
StartupNotify=true
Icon=/etc/MasterPi_PC_Software/images/Arm.ico
And with that, we can now do most of the things we want to do. The Android app now discovers the camera and lets us connect to it, and if we load the vnc session and double click the desktop icon the program opens up. From both the Android App and the desktop program, we can view the camera, and from the Android app we can change the RGB lights!
That I have found, the system exposes 2 web endpoints; one is a raw output of mjpeg streamer, and the other is a JSON API entrypoint.
- MJPG Streamer: http://
:8080 - JSON Entrypoint: http://
:9030
If it is useful, here are the listening ports:
# netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:9030 0.0.0.0:* LISTEN 571/python3
tcp 0 0 0.0.0.0:9026 0.0.0.0:* LISTEN 570/python3
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 751/cupsd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 793/sshd: /usr/sbin
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 571/python3
tcp 0 0 0.0.0.0:5900 0.0.0.0:* LISTEN 774/wayvnc
udp 0 0 0.0.0.0:5353 0.0.0.0:* 557/avahi-daemon: r
udp 0 0 0.0.0.0:51201 0.0.0.0:* 557/avahi-daemon: r
udp 0 0 0.0.0.0:631 0.0.0.0:* 1186/cups-browsed
udp 0 0 0.0.0.0:9027 0.0.0.0:* 569/python3
It's not all roses though. The android app works and the wheels are controllable and the camera is visible, however the controls for the arm itself appear to be non-functional. Then when you go to the VNC app, the controls are only for the arm, which all work (confirming we don't have a wiring issue). The desktop app doesn't expose GUI controls for the wheels at all that I've found yet, though I haven't looked much. There must be something wrong with the API call from the android app controlling the arm motors. I am suspecting I could build a small app to send the correct API calls to the API entrypoint, then control all functions with a single pane of glass, but that's a near-future project.
I grabbed some other debug by stopping the services and running the code manually, this may lead to some further troubleshooting:
# /usr/bin/python3 /etc/MasterPi/MasterPi.py
/etc/MasterPi/MasterPi.py:66: DeprecationWarning: setDaemon() is deprecated, set the daemon attribute instead
VD.setDaemon(True)
RemoteControl Init
server started
[ WARN:0@2.349] global ./modules/imgcodecs/src/loadsave.cpp (239) findDecoder imread_('/etc/MasterPi/MiniPi/CameraCalibration/loading.jpg'): can't open/read file: check file path/integrity
[ WARN:0@2.637] global ./modules/videoio/src/cap_gstreamer.cpp (2401) handleMessage OpenCV | GStreamer warning: Embedded video playback halted; module v4l2src0 reported: Cannot identify device '/dev/video-1'.
[ WARN:0@2.638] global ./modules/videoio/src/cap_gstreamer.cpp (1356) open OpenCV | GStreamer warning: unable to start pipeline
[ WARN:0@2.638] global ./modules/videoio/src/cap_gstreamer.cpp (862) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created
Voltage: 7.08
Voltage: 7.12