| 
									
										
										
										
											2021-07-22 00:40:40 +02:00
										 |  |  | # RPi microcontroller
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | This document describes the process of running Klipper on a RPi and | 
					
						
							|  |  |  | use the same RPi as secondary mcu. | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 00:40:40 +02:00
										 |  |  | ## Why use RPi as a secondary MCU?
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | Often the MCUs dedicated to controlling 3D printers have a limited and | 
					
						
							|  |  |  | pre-configured number of exposed pins to manage the main printing | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | functions (thermal resistors, extruders, steppers ...). Using the RPi | 
					
						
							|  |  |  | where Klipper is installed as a secondary MCU gives the possibility to | 
					
						
							|  |  |  | directly use the GPIOs and the buses (i2c, spi) of the RPi inside | 
					
						
							|  |  |  | klipper without using Octoprint plugins (if used) or external programs | 
					
						
							|  |  |  | giving the ability to control everything within the print GCODE. | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | **Warning**: If your platform is a _Beaglebone_ and you have correctly | 
					
						
							|  |  |  | followed the installation steps, the linux mcu is already installed | 
					
						
							|  |  |  | and configured for your system. | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 00:40:40 +02:00
										 |  |  | ## Install the rc script
 | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | If you want to use the host as a secondary MCU the klipper_mcu process | 
					
						
							|  |  |  | must run before the klippy process. | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | After installing Klipper, install the script. run: | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | cd ~/klipper/ | 
					
						
							| 
									
										
										
										
											2023-01-08 22:13:30 +01:00
										 |  |  | sudo cp ./scripts/klipper-mcu.service /etc/systemd/system/ | 
					
						
							|  |  |  | sudo systemctl enable klipper-mcu.service | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 00:40:40 +02:00
										 |  |  | ## Building the micro-controller code
 | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | To compile the Klipper micro-controller code, start by configuring it | 
					
						
							|  |  |  | for the "Linux process": | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | cd ~/klipper/ | 
					
						
							|  |  |  | make menuconfig | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | In the menu, set "Microcontroller Architecture" to "Linux process," | 
					
						
							|  |  |  | then save and exit. | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | To build and install the new micro-controller code, run: | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | sudo service klipper stop | 
					
						
							|  |  |  | make flash | 
					
						
							|  |  |  | sudo service klipper start | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | If klippy.log reports a "Permission denied" error when attempting to | 
					
						
							|  |  |  | connect to `/tmp/klipper_host_mcu` then you need to add your user to | 
					
						
							|  |  |  | the tty group.  The following command will add the "pi" user to the | 
					
						
							|  |  |  | tty group: | 
					
						
							| 
									
										
										
										
											2020-07-03 07:20:38 -04:00
										 |  |  | ``` | 
					
						
							|  |  |  | sudo usermod -a -G tty pi | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 00:40:40 +02:00
										 |  |  | ## Remaining configuration
 | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | Complete the installation by configuring Klipper secondary MCU | 
					
						
							|  |  |  | following the instructions in | 
					
						
							| 
									
										
										
										
											2020-12-03 15:06:58 -05:00
										 |  |  | [RaspberryPi sample config](../config/sample-raspberry-pi.cfg) and | 
					
						
							|  |  |  | [Multi MCU sample config](../config/sample-multi-mcu.cfg). | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | ## Optional: Enabling SPI
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Make sure the Linux SPI driver is enabled by running | 
					
						
							|  |  |  | `sudo raspi-config` and enabling SPI under the "Interfacing options" | 
					
						
							|  |  |  | menu. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-16 23:19:30 +02:00
										 |  |  | ## Optional: Enabling I2C
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Make sure the Linux I2C driver is enabled by running `sudo raspi-config` | 
					
						
							|  |  |  | and enabling I2C under the "Interfacing options" menu. | 
					
						
							|  |  |  | If planning to use I2C for the MPU accelerometer, it is also required | 
					
						
							|  |  |  | to set the baud rate to 400000 by: adding/uncommenting | 
					
						
							|  |  |  | `dtparam=i2c_arm=on,i2c_arm_baudrate=400000` in `/boot/config.txt` | 
					
						
							|  |  |  | (or `/boot/firmware/config.txt` in some distros). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 00:40:40 +02:00
										 |  |  | ## Optional: Identify the correct gpiochip
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-14 00:38:25 -04:00
										 |  |  | On Raspberry Pi and on many clones the pins exposed on the GPIO belong | 
					
						
							|  |  |  | to the first gpiochip. They can therefore be used on klipper simply by | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | referring them with the name `gpio0..n`. However, there are cases in | 
					
						
							|  |  |  | which the exposed pins belong to gpiochips other than the first. For | 
					
						
							|  |  |  | example in the case of some OrangePi models or if a Port Expander is | 
					
						
							|  |  |  | used. In these cases it is useful to use the commands to access the | 
					
						
							|  |  |  | _Linux GPIO character device_ to verify the configuration. | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | To install the _Linux GPIO character device - binary_ on a debian | 
					
						
							|  |  |  | based distro like octopi run: | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | ``` | 
					
						
							|  |  |  | sudo apt-get install gpiod | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To check available gpiochip run: | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | gpiodetect | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | To check the pin number and the pin availability tun: | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | gpioinfo | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | The chosen pin can thus be used within the configuration as | 
					
						
							|  |  |  | `gpiochip<n>/gpio<o>` where **n** is the chip number as seen by the | 
					
						
							|  |  |  | `gpiodetect` command and **o** is the line number seen by the` | 
					
						
							|  |  |  | gpioinfo` command. | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | ***Warning:*** only gpio marked as `unused` can be used. It is not | 
					
						
							|  |  |  | possible for a _line_ to be used by multiple processes simultaneously. | 
					
						
							| 
									
										
										
										
											2020-06-13 02:32:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | For example on a RPi 3B+ where klipper use the GPIO20 for a switch: | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | $ gpiodetect | 
					
						
							|  |  |  | gpiochip0 [pinctrl-bcm2835] (54 lines) | 
					
						
							|  |  |  | gpiochip1 [raspberrypi-exp-gpio] (8 lines) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | $ gpioinfo | 
					
						
							|  |  |  | gpiochip0 - 54 lines: | 
					
						
							|  |  |  |         line   0:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   1:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   2:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   3:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   4:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   5:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   6:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   7:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   8:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   9:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  10:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  11:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  12:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  13:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  14:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  15:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  16:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  17:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  18:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  19:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  20:      unnamed    "klipper"  output  active-high [used] | 
					
						
							|  |  |  |         line  21:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  22:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  23:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  24:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  25:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  26:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  27:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  28:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  29:      unnamed       "led0"  output  active-high [used] | 
					
						
							|  |  |  |         line  30:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  31:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  32:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  33:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  34:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  35:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  36:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  37:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  38:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  39:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  40:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  41:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  42:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  43:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  44:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  45:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  46:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  47:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  48:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  49:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  50:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  51:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  52:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line  53:      unnamed       unused   input  active-high | 
					
						
							|  |  |  | gpiochip1 - 8 lines: | 
					
						
							|  |  |  |         line   0:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   1:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   2:      unnamed       "led1"  output   active-low [used] | 
					
						
							|  |  |  |         line   3:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   4:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   5:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   6:      unnamed       unused   input  active-high | 
					
						
							|  |  |  |         line   7:      unnamed       unused   input  active-high | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2021-07-15 19:24:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-22 00:40:40 +02:00
										 |  |  | ## Optional: Hardware PWM
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | Raspberry Pi's have two PWM channels (PWM0 and PWM1) which are exposed | 
					
						
							|  |  |  | on the header or if not, can be routed to existing gpio pins.  The | 
					
						
							|  |  |  | Linux mcu daemon uses the pwmchip sysfs interface to control hardware | 
					
						
							|  |  |  | pwm devices on Linux hosts.  The pwm sysfs interface is not exposed by | 
					
						
							|  |  |  | default on a Raspberry and can be activated by adding a line to | 
					
						
							|  |  |  | `/boot/config.txt`: | 
					
						
							| 
									
										
										
										
											2021-07-15 19:24:02 +02:00
										 |  |  | ``` | 
					
						
							|  |  |  | # Enable pwmchip sysfs interface
 | 
					
						
							|  |  |  | dtoverlay=pwm,pin=12,func=4 | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | This example enables only PWM0 and routes it to gpio12. If both PWM | 
					
						
							| 
									
										
										
										
											2023-08-13 21:23:58 +02:00
										 |  |  | channels need to be enabled you can use `pwm-2chan`: | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | # Enable pwmchip sysfs interface
 | 
					
						
							|  |  |  | dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4 | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2023-09-18 22:23:35 +09:00
										 |  |  | This example additionally enables PWM1 and routes it to gpio13. | 
					
						
							| 
									
										
										
										
											2021-07-15 19:24:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | The overlay does not expose the pwm line on sysfs on boot and needs to | 
					
						
							|  |  |  | be exported by echo'ing the number of the pwm channel to | 
					
						
							| 
									
										
										
										
											2023-08-13 21:23:58 +02:00
										 |  |  | `/sys/class/pwm/pwmchip0/export`. This will create device `/sys/class/pwm/pwmchip0/pwm0` in the | 
					
						
							|  |  |  | filesystem. The easiest way to do this is by adding this to | 
					
						
							|  |  |  | `/etc/rc.local` before the `exit 0` line: | 
					
						
							| 
									
										
										
										
											2021-07-15 19:24:02 +02:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2023-08-13 21:23:58 +02:00
										 |  |  | # Enable pwmchip sysfs interface
 | 
					
						
							| 
									
										
										
										
											2021-07-15 19:24:02 +02:00
										 |  |  | echo 0 > /sys/class/pwm/pwmchip0/export | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2023-08-13 21:23:58 +02:00
										 |  |  | When using both PWM channels, the number of the second channel needs to be echo'd as well: | 
					
						
							|  |  |  | ``` | 
					
						
							|  |  |  | # Enable pwmchip sysfs interface
 | 
					
						
							|  |  |  | echo 0 > /sys/class/pwm/pwmchip0/export | 
					
						
							|  |  |  | echo 1 > /sys/class/pwm/pwmchip0/export | 
					
						
							|  |  |  | ``` | 
					
						
							| 
									
										
										
										
											2022-01-28 18:24:25 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | With the sysfs in place, you can now use either the pwm channel(s) by | 
					
						
							|  |  |  | adding the following piece of configuration to your `printer.cfg`: | 
					
						
							| 
									
										
										
										
											2021-07-15 19:24:02 +02:00
										 |  |  | ``` | 
					
						
							|  |  |  | [output_pin caselight] | 
					
						
							|  |  |  | pin: host:pwmchip0/pwm0 | 
					
						
							|  |  |  | pwm: True | 
					
						
							|  |  |  | hardware_pwm: True | 
					
						
							|  |  |  | cycle_time: 0.000001 | 
					
						
							| 
									
										
										
										
											2023-08-13 21:23:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | [output_pin beeper] | 
					
						
							|  |  |  | pin: host:pwmchip0/pwm1 | 
					
						
							|  |  |  | pwm: True | 
					
						
							|  |  |  | hardware_pwm: True | 
					
						
							|  |  |  | value: 0 | 
					
						
							|  |  |  | shutdown_value: 0 | 
					
						
							|  |  |  | cycle_time: 0.0005 | 
					
						
							| 
									
										
										
										
											2021-07-15 19:24:02 +02:00
										 |  |  | ``` | 
					
						
							| 
									
										
										
										
											2023-08-13 21:23:58 +02:00
										 |  |  | This will add hardware pwm control to gpio12 and gpio13 on the Pi (because the | 
					
						
							|  |  |  | overlay was configured to route pwm0 to pin=12 and pwm1 to pin=13). | 
					
						
							| 
									
										
										
										
											2021-07-15 19:24:02 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-29 10:56:50 -04:00
										 |  |  | PWM0 can be routed to gpio12 and gpio18, PWM1 can be routed to gpio13 | 
					
						
							|  |  |  | and gpio19: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | | PWM | gpio PIN | Func | | 
					
						
							|  |  |  | | --- | -------- | ---- | | 
					
						
							|  |  |  | |   0 |       12 |    4 | | 
					
						
							|  |  |  | |   0 |       18 |    2 | | 
					
						
							|  |  |  | |   1 |       13 |    4 | | 
					
						
							|  |  |  | |   1 |       19 |    2 | |