The MPG (Manual Pulse Generator) module allows you to use rotary encoders (hand wheels) to manually jog machine axes. This provides precise manual control similar to professional CNC machines, making it ideal for:
An MPG typically consists of:
Each encoder pulse translates to a small step movement on the configured axis, allowing very precise positioning control.
| Specification | Typical Value |
|---|---|
| Type | Incremental quadrature encoder |
| Resolution | 100 PPR (common for hand wheels) |
| Output | A, B quadrature channels |
| Voltage | 5V or 3.3V |
Connect the encoder to the Smoothieboard:
| Encoder Wire | Connection |
|---|---|
| A channel | Interrupt-capable GPIO pin |
| B channel | Interrupt-capable GPIO pin (different EXTI line) |
| VCC | 3.3V or 5V (depending on encoder) |
| GND | Ground |
If using 5V encoders, level shifting may be required for the signal pins.
Configure one MPG per axis, or configure one shared MPG and select its active axis with M922. Do not mix shared and per-axis instances.
[mpg]
x.enable = true
x.enca_pin = PF10^ # Encoder A channel (^ enables pull-up)
x.encb_pin = PF6^ # Encoder B channel
x.mmperpulse = 0.01 # Optional; defaults to the axis resolution
[mpg]
# X-axis MPG
x.enable = true
x.enca_pin = PF10^
x.encb_pin = PF6^
x.mmperpulse = 0.01
# Y-axis MPG
y.enable = true
y.enca_pin = PA3^
y.encb_pin = PA4^
y.mmperpulse = 0.01
# Z-axis MPG
z.enable = true
z.enca_pin = PB7^
z.encb_pin = PD2^
z.mmperpulse = 0.005
| Option | Description | Values |
|---|---|---|
name |
Axis controlled by this instance | x, y, z, a, b, c, or shared |
name.enable |
Enable this MPG instance | true / false; default false |
name.enca_pin |
Encoder A channel pin | Pin specification |
name.encb_pin |
Encoder B channel pin | Pin specification |
name.mmperpulse |
Distance moved for each encoder count | Positive millimetres; defaults to rounded motor resolution |
^ suffix for internal pull-up (recommended for open-collector outputs)! suffix for inverted logic if neededM922 before turning the wheelmmperpulse; if omitted, Smoothie derives it from the axis steps/mm and rounds it to four decimal placesM922, or prevent access to per-axis hand wheels, before starting an automated job.
With typical configurations:
| Steps/mm | Step Distance |
|---|---|
| 80 | 0.0125mm (12.5µm) |
| 100 | 0.01mm (10µm) |
| 200 | 0.005mm (5µm) |
| 400 | 0.0025mm (2.5µm) |
Configure the reserved shared instance when one hand wheel must control several axes:
[mpg]
shared.enable = true
shared.enca_pin = PF10^
shared.encb_pin = PF6^
Select one axis and its distance per encoder count with M922:
M922 X0.01 ; select X at 0.01 mm per count
M922 Y0.01 ; switch to Y
M922 Z0.005 ; switch to Z at a finer increment
M922 ; disable all axes
Only one axis argument is allowed. The selected axis stays active until another M922 changes it or an argument-free M922 disables the hand wheel.
A Button Box can provide physical selectors:
[button box]
select_x.pin = PA5^
select_x.press = M922 X0.01
select_y.pin = PA6^
select_y.press = M922 Y0.01
select_z.pin = PA7^
select_z.press = M922 Z0.005
disable_mpg.pin = PA8^
disable_mpg.press = M922
x, y, z, a, b, c, or shared; arbitrary names such as xaxis are rejectedM922 X<distance> or another valid axis first! suffix), or[actuator] sectionThe pins you specified don’t support interrupts or share the same EXTI line:
This complete configuration gives a 3-axis CNC mill one hand wheel per axis:
[mpg]
# X-axis hand wheel
x.enable = true
x.enca_pin = PF10^
x.encb_pin = PF6^
x.mmperpulse = 0.01
# Y-axis hand wheel
y.enable = true
y.enca_pin = PA3^
y.encb_pin = PA4^
y.mmperpulse = 0.01
# Z-axis hand wheel
z.enable = true
z.enca_pin = PB7^
z.encb_pin = PD2^
z.mmperpulse = 0.005