Hi there,
I’m working on a project to manipulate the feedrate on my CNC machine, but unfortunately, the controller doesn’t have built-in support for this feature. To work around this, I’m trying to build a custom solution using a Raspberry Pi Pico and a potentiometer to control the feedrate externally.
The controller supports feedrate adjustments through keyboard inputs like F11 for increasing and decreasing feedrate (+/-), so my idea is to simulate a keyboard using the Pico. The plan is to detect changes in the potentiometer (I’m using a 10K ohm pot) and then send simulated keypresses (either “+” or “-”) to the controller whenever the potentiometer moves by 1% or more. If the potentiometer is not moved, no input should be sent.
I’ve written some code to handle this, but I’m struggling with reliability. The current implementation doesn’t work as expected. The goal is for the code to accurately detect changes and send the “+” or “-” keypress immediately when the potentiometer is adjusted by 1%. However, it sometimes sends the wrong inputs or doesn’t react quickly enough.
Here’s the code I’ve written so far. I’d really appreciate any advice or suggestions to improve its accuracy and reliability.
Thanks in advance for your help!
import time
import analogio
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
import board
# Setup potentiometer for feedrate pin and HID keyboard
pot_feedrate = analogio.AnalogIn(board.GP26_A0) # Using only feedrate potentiometer
kbd = Keyboard(usb_hid.devices)
# Function to map potentiometer values to a percentage
def get_percentage(pin):
return (pin.value / 65535) * 100
# Parameters for adjustments
change_threshold = 2.4 # Sensitivity with a 2.4% deviation trigger
step_size = 2.4 # Adjustments made in 2.4% increments
debounce_time = 0.3 # Debounce time for avoiding rapid changes
dead_zone = 1.5 # Small dead zone to ignore small changes
feedrate_values = []
moving_average_length = 10
# Moving average calculation
def moving_average(values, new_value, length):
values.append(new_value)
if len(values) > length:
values.pop(0)
return sum(values) / len(values)
last_feedrate_time = time.monotonic()
while True:
# Read current value from potentiometer
current_feedrate = get_percentage(pot_feedrate)
# Calculate moving average
avg_feedrate = moving_average(feedrate_values, current_feedrate, moving_average_length)
# Output feedrate change only when it exceeds the change threshold
if abs(current_feedrate - avg_feedrate) > change_threshold:
steps = int((current_feedrate - avg_feedrate) / step_size)
if abs(current_feedrate - avg_feedrate) > dead_zone:
if current_feedrate > avg_feedrate:
print(f"Increasing feedrate by {steps * step_size:.2f}% +")
for _ in range(steps):
kbd.press(Keycode.KEYPAD_PLUS)
time.sleep(0.05)
kbd.release_all()
elif current_feedrate < avg_feedrate:
print(f"Decreasing feedrate by {abs(steps) * step_size:.2f}% -")
for _ in range(abs(steps)):
kbd.press(Keycode.KEYPAD_MINUS)
time.sleep(0.05)
kbd.release_all()
last_feedrate_time = time.monotonic()
# Debug output showing feedrate and average
if time.monotonic() - last_feedrate_time > debounce_time:
print(f"Feedrate: {current_feedrate:.2f}% (Avg: {avg_feedrate:.2f}%)")
last_feedrate_time = time.monotonic()
time.sleep(0.1)