The Printer Pi Pro is a Raspberry Pi HAT for a Klipper or Octoprint 3D printer host. The HAT controls things like servos, an accelerometer, a fan for cooling the pi, and more. It also controls a relay that can turn your printer on or off!
- A raspberry pi (duh) with Klipper or Octoprint installed (all features are compatible with both!)
- The Printer Pi Pro PCB
If you aren't controlling anything with the PCB, that's all you need! However, you likely won't just make the PCB solely to put it on the Pi and not plug anything into it. So here's what you can do with it:
- Onboard passive buzzer: can create little tunes and jingles when your print starts, finishes, cancels, or anything else you want!
- 5V Fan port: for active cooling your Raspberry Pi. You can code this to turn on when the Pi starts getting hot.
- Two servo ports: perfect for pitch and yaw of a webcam! or anything else really
- ADXL345 port: for an accelerometer and input shaping!
- Relay port: to control an AC or DC relay. This can be for lights, or to turn on/off the printer. More on this later.
| Part | Pins |
|---|---|
| Buzzer | PWM GPIO3 |
| Fan | PWM GPIO18 |
| Servo 1 | PWM GPIO13 |
| Servo 2 | PWM GPIO19 |
| ADXL | SPI Interface |
| Relay | GPIO2 (Not PWM) |
How to play music with the passive buzzer on the Pi with a script: https://www.circuitbasics.com/how-to-use-buzzers-with-raspberry-pi/ However, 3D printer firmware doesn't natively support running Raspberry Pi scripts using Gcode. In Klipper firmware, you can do it with Gcode with the Gcode Shell Commands extension. In Octoprint + Marlin, use this. The buzzer here is connected to GPIO 3.
The fan port is connected to a transistor circuit which turns the two-pin 5V fan on or off using GPIO 18. Additionally, using GPIO 18's PWM signal, you can put the fan at a percentage of speed, for example 25% speed when the Pi is at 40°C, 50% at 45°C, and so on. To change the PWM frequency via a Raspberry Pi script, simply use something like:
import RPi.GPIO as GPIO
import time
FAN_PIN = 18 # we're using GPIO 18
FREQ = 25000 # 25khz PWM frequency makes the fan smooth
GPIO.setmode(GPIO.BCM)
GPIO.setup(FAN_PIN, GPIO.OUT)
pwm = GPIO.PWM(FAN_PIN, FREQ)
pwm.start(0) # Start with fan off
pwm.ChangeDutyCycle(25) # 25% speed
time.sleep(3)
pwm.ChangeDutyCycle(50) # 50% speed
time.sleep(3)
pwm.ChangeDutyCycle(75) # 75% speed
time.sleep(3)
pwm.ChangeDutyCycle(100) # 100% speed
pwm.ChangeDutyCycle(0)
pwm.stop()
GPIO.cleanup()
top()
GPIO.cleanup()
There are more example scripts in the example_scripts folder!
Servos are quite easy to control! Here's a good instructables guide: https://www.instructables.com/Controlling-Servo-Motor-Sg90-With-Raspberry-Pi-4/ You can control your shell scripts the same way you do with the buzzer scripts. You can use the servos to extend a Klicky docking arm, move a webcam, or clear the build plate. Servo 1 is connected to GPIO 13, and Servo 2 is connected to GPIO 19, which are both PWM pins.
If you don't already know, input shaping is the method of using an accelerometer to measure vibrations when moving the 3D printer parts at high speeds. Normally, these vibrations can cause ringing issues in the print, but with input shaping, the printer is able to compensate and use the vibrations and minimize ringing substantially. The ADXL345 connector on the board uses the same pinout as both of the below links do.
Input shaping for Octoprint + Marlin: https://community.octoprint.org/t/octoprint-pinput-shaping-a-plugin-to-test-input-shaping-with-marlin/63089
Input shaping for Klipper: https://www.klipper3d.org/Resonance_Compensation.html
The relay port simply outputs 5V from the main power source, meaning it can draw up to 800mA through the 2N2222A transistor. You could actually use it for any low-power 5V device you wish, but I think most people will use it for a relay. You can use it to switch 24V from the PSU using a DC-DC relay, or, like I am, you can use it to switch an AC relay. Simply connect 5V to the input voltage on your relay, and GPIO2 to the ground. Note that this does not go straight to GPIO2. I labelled it that simply as a reference as to which GPIO you should set in your script. In reality, it goes through a transistor circuit just like the fan's.
This port, however, does not have a PWM output like the fan does. You could attach a fan to it, but it could only run at 0% or 100%. So the on/handle-interupts script (we'll call it relay-service.py) could look something like:
import RPi.GPIO as GPIO
import time
import signal
import sys
RELAY_PIN = 2 # we're using GPIO 2
def cleanup(sig, frame)
GPIO.cleanup() # this sets everything low, turning off the relay
sys.exit(0) # exits with success
GPIO.setmode(GPIO.BCM)
GPIO.setup(RELAY_PIN, GPIO.OUT)
GPIO.output(RELAY_PIN, GPIO.HIGH) # switch the relay on
signal.signal(signal.SIGINT, cleanup) # this handles Ctrl+C's and other interruptions
signal.signal(signal.SIGTERM, cleanup) # this handles systemd's termination signals
while True: # this doesn't let the script turn off until it's interrupted or ended
time.sleep(1) # wait for one second between loops, so as not to overload the system lol
oad the system lol
You could put this simply in a folder like /home/pi/relay/ for easy access.
Next, we have to make an off script, like the following:
import RPi.GPIO as GPIO
RELAY_PIN = 2 # we're using gpio 2
GPIO.setmode(GPIO.BCM) # use gpio numbers instead of pin numbers
GPIO.setup(RELAY_PIN, GPIO.OUT) # set it to be an output
GPIO.output(RELAY_PIN, GPIO.LOW) # turn it off
GPIO.cleanup() # clean up and exit gracefully
fully
Now, make the systemd service. You can make the relay start up when the Pi powers on, so that you only have to turn on the Pi and the printer turns on afterwards. First, open /etc/systemd/system/ and create a new file such as relay-control.service. Paste the following:
[Unit]
Description=GPIO2 Relay Controller
After=network.target
[Service]
Type=simple
Restart=always
RestartSec=1
User=pi
ExecStart=/usr/bin/python3 /home/pi/relay/relay-service.py
ExecStop=/usr/bin/python3 /home/pi/relay/relay-off.py
[Install]
WantedBy=multi-user.target
-user.target
What the above does is setup a service, just like Klipper is a service and Crowsnest is a service. It sets it to be simple, meaning it doesn't fork. It always restarts if it stops or crashes, and waits a second between attempts. It runs the script as the user pi (replace this with your admin user) and when starting, runs relay-service.py, and when it's stopped it runs relay-off.py. This means that when you first start the script, i.e., on boot, it runs relay-service.py, turning on the relay, and when you run the command to stop it, sudo systemctl stop relay-control, or if you power off the pi, it powers off the relay using relay-off.py or through relay-service.py's cleanup() function.
Now, if you want to, you can first reload systemd with sudo systemctl daemon-reload, and then enable the service to start up every time the Pi boots! You can do this with sudo systemctl enable relay-control. This won't start it immediately after running; to do that you can run sudo systemctl start relay-control.
However, the on script is actually only a failsafe. GPIO2, which controls the relay, is actually pulled-up by default, meaning that by default it turns on at boot, without any script. It's still a good idea to have the script, in case the default had been accidentally overriden. If you'd like to override this and not turn on the relay with the Pi, simply edit /boot/firmware/config.txt and add the line gpio=2=pd somewhere without a [bracketed] header.
Pretty straightforward! However, where this feature can shine the most, is turning the printer on or off remotely. To do this, simply use this extension for Klipper: Gcode Shell Commands extension, or in Octoprint + Marlin, use this one. You can add the commands sudo systemctl start relay-control to turn it on and sudo systemctl stop relay-control to turn it off as GCode commands in your printer's interface. But the issue here is, you can't run GCode while the printer is off! In this case, you'd have to SSH into the Pi and turn it on by manually running the script, or simply reboot the Pi if you've configured the service to start on boot.
if you do decide to use an AC relay with this, always be sure that shorts can never occur! AC voltage is really really powerful, and you could get badly injured if you don't wire it correctly. That's all!
The PCB Gerber files, BOM, and CPL (Pick-in-place) file are all in the PCB_Files folder. What I did was order just the PCB (not assembled) through JLCPCB, then combine it with an LCSC order as described here. Alternatively, you could order an assembled PCB or buy a PCB with the parts not assembled. Unfortunately, JLC only gives you the parts if you buy the PCB assembled. All the parts can be ordered from LCSC; you can also download the cart from the PCB_Files folder.
You'll also need some JST-XH wire housings to fit into the ports on the PCB. If you're combining an LCSC order and a JLCPCB order as mentioned above, you can simply add these to the cart. For example, this is a 6-pin housing to fit into the ADXL345 port. If you're getting an assembled PCB from JLCPCB, you'll have to buy the housings separately, whether through JLCPCB's part cart or a seller such as AliExpress or Amazon.
Also, keep in mind that there's only one component on the bottom side of the PCB: the Raspberry Pi pinheader. This was another reason I bought from LCSC and combined the shipping with JLCPCB, because if I had gotten an assembled PCB from JLC, I would've had to either get a double-sided PCB or put the header on the front, desolder it, and re-solder it onto the back. The PCB also has 4 SMD components. They aren't anything super hard to solder, just two 0805 size resistors and two SOD123F size diodes.
This is a pretty simple project, but if you have any ideas on things to add, anything in here that could be updated, etc, feel free to make an issue on this repo or email me! (email is in my profile)