Assembly instructions
List of components
- StarTech UNISLDSHF192 2U shelf
- About 1.2 kg Ultimaker Tough PLA
- TESmart HKS1601A1U-EUBK KVM Switch (The Elder Scrolls, for those in the know 🤣 )
- Raspberry Pi 4 4Gb
- PiKVM HAT
- Servo Driver HAT
- I2C OLED Display Module 0.91 Inch for PiKVM
- Raspberry pi 4 GPIO Extension (2×20 female header (pin length: 5.5 mm))
- 2x 19″ rack PDU with 9 power sockets each
- Original power adapter for Raspberry Pi
- MicroSD Sandisk 64GB Max Endurance
- 30x30x7mm 5v Fan
- Small radiator for Raspberry Pi CPU
- 16x Slim HDMI Cables 1m
- 16x 1m USB 2.0 Cable – USB-C to USB-B
- 16x Slim (~28AWG) Ethernet Network Patch Cable, for example
- 8x Servo MG996R (DM996)
- Servo drives cable extensions like this one. Not all servos will need to do this. Better to get some kit and find the best length options by spot
- A metal rod (I think a normal paper clip will do). Needed for connecting levers and servo drives
On github.com, you can put a star (✰) and then clone the repository or download the archive. It contains the necessary models for printing and my scripts, which I will tell you about below.
I hope you read the article carefully first. You may want to change some steps or add your own. The main thing is to be careful with servos if you hurry – they can break something or themselves.
3D printing
Let’s start by printing large components. You need eight double stands.
Printing without supports, layer 0.2mm. Ultimaker Tough PLA filament. I think a good analog would be any PETG plastic. 5-10% infill density with 0.8mm shells should be fine.
On a large printer, you can print like this. Ultimaker S5 build volume is 11.8” (30 cm) tall, 13” (33 cm) wide, 9.84” (25 cm) deep.
On a small one, it’s also possible, but it’ll take longer. Ultimaker 3 build volume is 7.9″ (20 cm) tall, 8.5” (21.6 cm) wide, 8.5” (21.6 cm) deep.
Then you need 16 arms. They have this bulge on one side. It’s better printed like this. Without supports, 0.15mm layer
7 such pins for connecting the stands
And 7 cable organizers can also be printed without supports.
You can already assemble the stand itself using the printed pins using M3 screws 16-18mm
Do not forget to install cable organizers between the stands
On the back side
Now let’s install the arms and servos. But don’t be in a hurry
I used lubricant because lubrication is good wherever there is friction.
The servo drive can be fixed with M3 bolts of approximately this length (you can use a longer one, the length of the hole will be sufficient.). The arms are identical, and despite displacement due to the bulged part, it does not affect the functionality in any way.
Afterwards you can put on the original servo arm and assemble the construction in this way. You can use a metal bar or just an unbent paper clip. The rod should go all the way to the bottom of the lever, with a rod length of about 38mm.
Note that there are 2 holes from the lever to the servo arm on each side.
Do not attach the black lever to the servo. Leave it like this until the initial setting (we will come back to this later in the text)
The next step is to assemble the push part. I have tried several options:
The idea is for the spring to compensate for excessive pressing force so that the lever doesn’t move the Mac mini when the button is pressed.
In the latest versions, I just used a bolt spring and a nut like this, with no extra nuts in the middle, because the fine-tuning is done in the script.
The final construction is pretty solid.
That is an important point! You didn’t attach the lever to the servos, did you? This will need to be done after the initial calibration of the servos! The actuators are powerful enough to break themselves, plastic parts, and possibly push through a button on a Mac mini (and break it).
You can print the case for Raspberry Pi and the front panel (in the repository in the relevant folder).
And its stand
Shelf
Now, more about the shelf. Unfortunately, this installation would take another unit under the shelf. However, it may be possible to reposition the rails, I’ll try that next time. This is just my recommendation on how to mount. It may seem right to you to assemble it differently. I advise you to see it on-site. I also had to flip the wire guide mount to get it to work right, I believe if you’ve gotten to this step, you’ll do fine.
The article comes out pretty long. I hope it’s worth it.
Well, now you need to keep building. I used double-sided tape to secure the whole stand to the shelf (but there are holes in the plastic parts for bolts to screw through the shelf if you want).
Time for initial setup and testing of the Raspberry Pi
Assemble PiKVM (docs link) and add Servo HAT (Using GPIO Extender). You can add an OLED screen right away. And don’t forget the USB-C adapter on the side!
Follow the official documentation and flash the SD card, link.
Connecting in this way (the sequence of servos is not important yet; the main thing is to occupy ports 0-7)
Remove the levers from the servos and run Raspberry Pi. I am using the original Raspberry Pi power supply.
If all is well, you should be able to find pikvm online and connect via SSH.
Activate i2c for Servo HAT operation and watchdog so that the device can restart automatically in case of malfunctions:
rw
echo 'dtparamw=watchdog=on' >> /boot/config.txt
echo 'dtparam=i2c_arm=on' >> /boot/config.txt
Reboot
Put my scripts in the user folder on pikvm and make them executable:
rw
chmod u+x kvmctl.sh
chmod u+x servo.py
chmod u+x servo_all.py
- servo_all.py
Activates all servos to press all 16 buttons, one by one. Accepts the press delay as an argument - servo.py
Presses the button on the selected Mac mini, the Mac mini number (1-16) and the delay in seconds as arguments - kvmctl.sh
I slightly modified the original script for managing the selected KVM switch. We don’t use feedback (we don’t know which Mac mini is currently selected), so I turned off everything unnecessary, which speeds up KVM switch port switching.
Double-check that the levers are off the servos!
Install pip first:
rw
pacman -S python-pip
or
wget https://bootstrap.pypa.io/get-pip.py --no-check-certificatepython get-pip.py
chmod u+x get-pip.py
./get-pip.py
Install adafruit-circuitpython-servokit:
rw
pip install adafruit-circuitpython-servokit
or (in case of errors)
rw
pip install adafruit-circuitpython-servokit --break-system-packages
Run a script that will set all servos in zero position (All the servos will rotate back and forth and stand at 100°):
./servo_all.py 1
If they all turn, all is well, and the plastic levers can now be installed. Do not turn the servos! They may not fit perfectly, but a few degrees can be set as an adjustment later in the servo_parameters.py file.
Cabling
You can turn everything off and continue assembling
KVM switch stands do not require additional fixing or gluing.
Cable management can be performed as follows:
Here you will need servo cable extensions (the connection points can be wrapped with duct tape, but it is better to put on heat shrink). Also, install the network, power, USB cables, and HDMI. Don’t forget to label the cables! This is critical for servo drive cables.
Now, you need to connect the KVM switch to the PiKVM serial port. To do this, you need to make a cable adapter. Or use the Cisco/Mikrotik-style cable:
The KVM switch comes with a suitable green connector. You will need a piece of network cable. It is better to use a rigid one with single wires; it is easier to work with.
So, the cable plugs into the 8p8c (RJ45) port above the Ethernet port on the Raspberry Pi. And the other end is plugged into the KVM switch.
Finally, we’re done with the cables.
Let’s put it all together, but don’t attach the front panel yet.
The servos are connected from left to right from 0 to 7 to servo HAT. Zero is closer to the front panel, 7 is the one closest to the Raspberry here. (I’m counting from 1 to 8, but the ports on the servo HAT are signed from 0, so here they are named from zero)
The Raspberry has a stand like this installed underneath it to plug the cables into it without any problems
You can also use a 90-degree adapter for HDMI in PiKVM to make the port from PiKVM look up, but it may not be necessary.
The finish line
At this point, everything is assembled and ready for final and precise tuning.
Turn on the Raspberry Pi and connect to it via SSH.
Install the latest updates:
rw
pacman -Syu
Change hostname:
rw
hostnamectl set-hostname yournewhostname.domain
And edit /etc/kvmd/meta.yaml to alter the displayed server name in the web UI
Changing passwords
rw
passwd root
kvmd-htpasswd set admin
Tune-up
Install socat, it is needed to run the KVM switch management script
pacman -S socat
Set up watchdog (it will reboot the Raspberry in case of hang-up or network loss, for example).
sudo nano /etc/watchdog.conf
min-memory = 1280
max-load-1 = 24
max-load-5 = 18
max-load-15 = 12
watchdog-device = /dev/watchdog
watchdog-timeout = 15
interval = 1
realtime = yes
priority = 1
ping = 8.8.8.8
Ping is probably better to do to some server nearby, well you know
sudo systemctl enable watchdog
sudo systemctl start watchdog
sudo systemctl status watchdog
Timezone:
timedatectl set-timezone Europe/Berlin
A couple of important file moves:
- move override.yaml to the folder /etc/kvmd/
This file is responsible for adding custom components to the UI. It adds the necessary drivers and activates the necessary scripts by pressing buttons in the web-UI. 436 lines! - move custom_commands to the folder /etc/sudoers.d/
Adds the ability to run necessary scripts as administrator (this is necessary to work with servoHAT).
After that, you can reboot the Raspberry
The final setting of the servo drives
Basically, you can already try to connect to the WebUI, and there will already be buttons to control your Mac mini. If you were careful during assembly, you can proceed; if you’re worried, you can temporarily remove the Mac mini from the rack.
After pressing the button in the interface, the servo will rotate to press the button on the Mac Mini and then return to the 100-degree position.
If it didn’t return accurately, you need to edit the file:
servo_parameters.py
rw
nano servo_parameters.py
"""
Just a separate file with values to fine-tune
for each individual servo. But not the Mac mini!
"""
servo_adjustment = [0, 0, 0, 0, 0, 0, 0, 0]
If the servo drive is to be turned to the right, enter positive values. To the left, enter negative values. Add 1-2 digits at a time! And each servo separately.
An example of a final file might be:
servo_adjustment = [1, -4, 0, 8, -1, 6, 2, -3]
P.S. There were ideas to optimize the initial setup with some wizard, but I’m afraid the article wouldn’t have seen the light of day this year. Yes, and in general, it should be done once, so I consider it unnecessary and really over-engineering. But maybe later….
How to rename Mac mini in the PiKVM interface?
You need to edit their names at the end of the file override.yaml
The main thing is not to break the file structure – it will break the UI
After editing this file, you need to restart WebUI with the command
systemctl restart kvmd
Well, that’s it.
I hope you had fun!
I’d appreciate it if you’d join our Discord server, and subscribe to my Instagram and/or X (Twitter). It will be the best “thanks” if you liked the article 🙂 Thank you, and May the Force be with you!
Oh, and of course feel free to drop a comment! I read everything, there’s usually not a lot of them here )
Appendix. The beauty (or overengineering) of scripts
Part of the problem was how to implement the servo control so that it would control 2 Mac minis. Below, I give the main script that is responsible for this.
In the UI, we pass the Mac mini number and the delay in seconds. Selecting the correct servo and adding a correction is implemented inside the script.
#! /usr/bin/python
"""
The number of Mac mini (from 1 to 16) and
the number of seconds for which the button
will be pressed on each mac are taken as arguments
"""
from sys import argv
import time
from adafruit_servokit import ServoKit
from servo_parameters import *
script, mac, delay = argv
mac = int(mac)
delay = float(delay)
port = mac // 2 + mac % 2 - 1 # for macs 1,2 servoHAT port is 0; 2,3 = 1; 3,4 = 2; etc..
zero_angle = 100
adj = servo_adjustment[port]
kit = ServoKit(channels=16)
print("Mac: ", mac, "; Delay: ", delay)
if mac % 2 != 0:
angle = 80
else:
angle = 120
print("Port: ", port, " ; Angle: ", angle)
kit.servo[port].angle = angle + adj
time.sleep(delay)
kit.servo[port].angle = zero_angle + adj
time.sleep(1)
kit.servo[port].angle = None
Calling this script is done quite simply via override.yaml (more about CMD driver by the link docs.pikvm.org)
Calling the script that switches ports on the KVM switch is done in the same way, after the comma – parameters.
Maybe I didn’t choose the best way, but it works well. In the first versions of KVMac16, all settings were done through override.yaml file, and it was very time-consuming.
I’m a systems engineer in JetBrains company. Uptime Lab founder. I’m glad to see you on my website! I hope you find my content useful. Please subscribe to my Instagram and Twitter. I post the newest updates there.
Imagine if apple, Knowing these mini would sell like got cakes. Imagine if they put an external way to power them on remotely. Or even crazier never will happen out of band management.