Robot Button Presser for Keurig

by kostert in Circuits > Assistive Tech

13 Views, 1 Favorites, 0 Comments

Robot Button Presser for Keurig

IMG_5206.jpeg
Assistive Tech Keurig Button Presser

This project is an open-source, Wi-Fi-connected assistive technology tool that enables users to remotely press the brew button on a Keurig coffee machine using standard 3.5mm assistive switches. Designed with accessibility and modularity in mind, it allows individuals with mobility impairments or limited reach to activate a Keurig from across the room — or anywhere with network access.


The system consists of two custom enclosures, each built around a Raspberry Pi Pico W. One enclosure acts as a remote trigger, while the other controls a servo motor equipped with a 3D-printed arm that physically presses the brew button. In addition to the mechanical action, each activation plays a sound (“Brewing.wav”) through a speaker and pulses a NeoPixel LED strip to provide both auditory and visual feedback.


Each box includes an audio jack input, allowing users to connect their own assistive switches. If either switch is pressed — local or remote — the servo fires, the lights flash red, and the brewing sound plays. The two devices communicate via Adafruit IO MQTT, making the system entirely wireless and responsive.


All code, design files, and setup instructions are fully documented and freely available. The project repository includes:


  1. code.py files for both devices
  2. CircuitPython library requirements
  3. A 3D model for the servo arm (sourced from this Printables model)
  4. Laser-cut enclosure files
  5. Wiring diagrams and build notes



Access the full repository here:

https://github.com/koster51/Keurig-button-clicker


This project is ideal for makerspaces, rehab centers, or caregivers looking to build low-cost, customizable, assistive tools for clients. It’s also a great introduction to IoT, accessible design, and physical computing with CircuitPython.

Supplies

IMG_5206.jpeg

Below is the complete list of components, tools, and fabrication materials required to build the project. The quantities reflect a two-device system: one remote trigger box and one actuator box.


Electronics

  1. 2x Raspberry Pi Pico W
  2. Microcontroller with built-in Wi-Fi. One per box.
  3. 2x Half-size breadboards
  4. For prototyping and wiring each device.
  5. ~30x Male-to-Male jumper wires
  6. For connecting components on the breadboard.
  7. 2x 3.5mm audio jack breakout boards (TRS or TRRS)
  8. Used for assistive switch inputs; must be breadboard-compatible.
  9. 1x 180° Metal Gear Servo
  10. Controls the mechanical pressing of the Keurig brew button.
  11. 1x NeoPixel LED Strip (30 pixels)
  12. For visual feedback using red pulsing effects.
  13. 1x Mini Oval Speaker – 8 Ohm 1W
  14. Plays a short sound when the system is triggered.
  15. 1x Adafruit Mono 2.5W Class D Audio Amplifier – PAM8302
  16. Powers the speaker from a GPIO audio pin.
  17. 2x Micro USB cables
  18. Used for power and programming. (This may come for free with your pico w)

️ Fabrication Materials

  1. Laser-cut enclosure material (e.g., 3mm acrylic, wood, or cardboard)
  2. Enough for two enclosures.
  3. 1x 3D printed servo arm
  4. Mounts to the servo to physically press the Keurig button.
  5. Mounting hardware (screws, tape, Velcro, etc.)
  6. For securing servo and enclosures to surfaces.


Tools Required

  1. Soldering iron and solder
  2. Wire strippers and flush cutters
  3. Laser cutter
  4. 3D printer
  5. Computer with USB ports and internet access


Optional / Assistive Accessories

  1. Assistive button switches with 3.5mm plugs
  2. USB battery packs for portable power
  3. Mounting brackets or custom enclosures

Setup Pico Software and Adafruit IO

This project uses Adafruit IO to enable wireless communication between the two devices. Device A (remote trigger) publishes a message to the cloud when its button is pressed. Device B (the actuator) listens for that message and responds by pressing the Keurig button, playing a sound, and flashing lights.


Follow these steps to get Adafruit IO and your boards set up:

1. Create an Adafruit IO Account

Go to https://io.adafruit.com and sign up for a free account if you don’t already have one.

2. Create a Feed

This is the MQTT feed used to pass button press messages between the two devices.

  1. Navigate to Feeds in the left sidebar
  2. Click + New Feed
  3. Set the feed name to: button-press (no quotes, use lowercase with a dash)
  4. Click Create

3. Get Your Adafruit IO Credentials

You’ll need your Adafruit IO username and your AIO key to connect the Pico W devices.

  1. In the top-right menu, click My Key
  2. Copy your:
  3. Username
  4. AIO Key

You’ll use these in the next step after flashing the boards.


4. Flash CircuitPython on Each Raspberry Pi Pico W

You must install CircuitPython before the board can run your code or accept settings.toml.

  1. Download the latest .uf2 CircuitPython file for the Pico W from:
  2. https://circuitpython.org/board/raspberry_pi_pico_w/
  3. Plug in the Pico W while holding the BOOTSEL button
  4. It will appear as a USB drive called RPI-RP2
  5. Drag and drop the .uf2 file onto the RPI-RP2 drive
  6. It will reboot and appear as a new drive called CIRCUITPY


5. Create a settings.toml File

Once CircuitPython is installed and CIRCUITPY appears:

  1. Create a file called settings.toml in the root of the CIRCUITPY drive
  2. Paste the following (with your actual info):
CIRCUITPY_WIFI_SSID = "YourWiFiNetwork"
CIRCUITPY_WIFI_PASSWORD = "YourWiFiPassword"

ADAFRUIT_AIO_USERNAME = "your_username"
ADAFRUIT_AIO_KEY = "your_aio_key"

Setting Up the Boards With Project Code


With CircuitPython installed and your settings.toml file in place, you’re now ready to upload the project code to each board. Each board plays a different role and needs a slightly different code.py file.


1. Prepare the CircuitPython Libraries

Before uploading code, make sure the required libraries are installed in the /lib folder on each CIRCUITPY drive.

You can download the full Adafruit CircuitPython Bundle here:

https://circuitpython.org/libraries

From the bundle, copy the following folders/modules into the /lib folder of each Pico W:


Required Libraries (both devices):

  1. adafruit_minimqtt
  2. adafruit_io
  3. adafruit_requests
  4. neopixel
  5. adafruit_motor


Also required for Device B only (audio/servo/light device):

  1. audiopwmio (built-in on Pico W)
  2. audiocore (used by WaveFile)


2. Download and Upload the Code

Download the project files from the GitHub repository:

https://github.com/koster51/Keurig-button-clicker

Inside the repo, you’ll find:

  1. code_device_a.py — for the remote trigger board
  2. code_device_b.py — for the servo/audio/LED board
  3. settings.toml — example (you already added this in Step 3)
  4. Brewing.wav — sound file to play
  5. STL and laser cut files

Rename the correct file to code.py before uploading it to each board:

  1. For the remote trigger device (Device A):
  2. Rename code_device_a.py → code.py
  3. Upload it to the CIRCUITPY drive of the first Pico W
  4. For the Keurig actuator device (Device B):
  5. Rename code_device_b.py → code.py
  6. Upload it to the CIRCUITPY drive of the second Pico W
  7. Also copy Brewing.wav to the root of this CIRCUITPY drive


3. Reboot the Boards and Confirm Behavior

  1. Both boards should auto-start running code.py when powered or rebooted
  2. Device A will wait for button input and publish to Adafruit IO
  3. Device B will listen for remote or local button presses and:
  4. Move the servo once
  5. Pulse the NeoPixel lights red three times
  6. Play Brewing.wav three times through the speaker


You can open the serial console on each board using Tio via pycharm or another REPL-compatible tool to view real-time output and debug messages.


Once the code is running on both boards, you’re ready to move on to the physical wiring and breadboard setup.

Build and Wire Device a (Remote Trigger)

IMG_5208.jpeg

Device A is a compact switch box that allows a user to trigger the Keurig remotely. It includes a 3.5mm audio jack for assistive switch input and a Raspberry Pi Pico W that sends a wireless message via Adafruit IO when the button is pressed.


This device does not include any servo, LEDs, or speaker — its only function is to detect a button press and transmit the event to Device B.


1. Audio Jack Wiring

You’ll connect a standard 3.5mm audio jack to a GPIO pin so that pressing the external switch will pull the pin low. Most assistive switches simply connect ground to signal when activated.

  1. Connect the tip or ring of the audio jack (usually the red wire) to GP15
  2. Connect the sleeve (usually black or bare wire) to GND

This forms a basic pull-down switch circuit, where pressing the button connects GP15 to ground.


2. CircuitPython Code Behavior

The CircuitPython code sets up GP15 as an input with an internal pull-up resistor. When the pin goes from high to low (button press), it publishes a “pressed” message to the button-press feed on Adafruit IO.

This event is then received by Device B, which handles all output actions.

3. Test the Device

  1. Plug in your assistive switch via the 3.5mm jack
  2. Open a serial console to monitor output
  3. Press the switch
  4. You should see a message like:
  5. Switch pressed, publishing...


If everything is working, Device B should respond automatically when this message is received.


Once Device A is successfully detecting button presses and sending messages, you’re ready to build Device B — the actuator that presses the Keurig brew button.

Build and Wire Device B (Servo + Audio + NeoPixels)

Device B is the actuator and output hub of the system. When a button is pressed—either locally or remotely—it responds by:

  1. Physically pressing the Keurig brew button using a servo and 3D-printed arm
  2. Playing a custom sound through a speaker and amplifier
  3. Flashing a NeoPixel LED strip red for visual feedback


1. Audio Jack (Local Switch) Wiring

Device B includes its own audio jack so a second assistive switch can be used directly at the Keurig machine.

  1. Connect the tip or ring of the audio jack (usually red) to GP14
  2. Connect the sleeve (usually black or bare wire) to GND

The switch is wired as a basic pull-down circuit using an internal pull-up resistor. When the button is pressed, the input is pulled low and triggers the activation routine.



2. Servo Wiring

A 180° metal gear servo is used to press the Keurig button. The servo is powered directly from USB and controlled via PWM from the Pico W.

  1. Signal (yellow/orange)GP15
  2. Power (red)VBUS
  3. Ground (black/brown)GND

The servo should be mounted securely above the Keurig using tape, brackets, or a 3D-printed mount. The servo arm should be aligned to press the brew button when it moves forward.


3. NeoPixel LED Strip Wiring

The NeoPixel strip provides a red pulsing effect during activation for visual feedback.

  1. Data InGP1
  2. Power (5V)VBUS
  3. GroundGND

Ensure all components share a common ground with the Pico W. The NeoPixel brightness and pulse timing can be adjusted in the code if needed.


4. Audio Output: Speaker and Amplifier Wiring

Device B plays a sound file called Brewing.wav three times every time the button is activated. The audio is played through a speaker using a PAM8302 amplifier and the Pico W’s PWM audio output.

Follow the wiring guidance from this Adafruit tutorial:

https://learn.adafruit.com/mp3-playback-rp2040/pico-mp3


Basic wiring:

  1. GP0 (audio output)Amp A+
  2. Amp A–GND
  3. Amp VDD3.3V
  4. Amp GNDGND
  5. Speaker terminalsAmp output + / –

Mount the speaker where it can be clearly heard—either inside the enclosure or externally.


5. Creating and Formatting the Sound File

The sound used in this project (“Brewing.wav”) was generated using ElevenLabs’ text-to-speech platform:

https://elevenlabs.io/app/speech-synthesis/text-to-speech


This allows you to generate a custom AI voice that says anything you like. Once you generate the audio, you must convert it to a microcontroller-compatible .wav format.


To do this, use Audacity to adjust the sample rate, bit depth, and mono channel. A detailed tutorial is available here:

https://learn.adafruit.com/microcontroller-compatible-audio-file-conversion


Make sure the final audio file is:

  1. 16-bit PCM WAV
  2. Mono
  3. 22.05 kHz or 44.1 kHz sample rate


Once formatted, save the file as Brewing.wav and copy it to the root of Device B’s CIRCUITPY drive.


6. Power Notes

Device B can be powered by USB during testing and operation. For deployment, a USB battery pack can be used.

  1. Servo and NeoPixels should draw power from VBUS (5V from USB)
  2. Amplifier should be powered by 3.3V (do not use VBUS)


7. System Test

To verify correct wiring and behavior:

  1. Plug in a button switch to the audio jack, or trigger from Device A
  2. You should observe:
  3. Servo moves forward briefly to press the Keurig button
  4. NeoPixels flash red in sync with the sound
  5. “Brewing.wav” plays three times from the speaker


You can view the serial output in the Tio using pycharm or another REPL tool to confirm successful execution and debug any issues.

3D Print Arm and Laser Cut Boxes

To keep the electronics protected and the system easy to use, each device is housed in a custom enclosure. These enclosures are designed to be laser cut from flat material and assembled as boxes. Additionally, a 3D-printed servo arm is used to physically press the Keurig brew button.


1. Laser-Cut Enclosures

Both Device A and Device B are mounted inside simple laser-cut boxes. These enclosures:

  1. Provide protection and portability
  2. Include cutouts for USB cables, 3.5mm audio jacks, and component mounting
  3. Can be customized to your own materials and laser cutter bed size

The design files for the laser-cut boxes are included in the project repository:

https://github.com/koster51/Keurig-button-clicker


The boxes are designed to be cut in 1/4 inch plywood and glued together.


2. 3D-Printed Servo Arm

To press the Keurig’s brew button, a 3D-printed arm is mounted to the horn of the servo motor. This arm translates the rotational motion of the servo into a reliable button press.

The arm used in this project is from the following model:

https://www.printables.com/model/110353-universal-button-pusher-sg90-mg996r/files


This model is compatible with many standard servos (including MG996R and SG90 types). For this project, it was mounted to a 180° metal gear servo using the included servo screws.

After printing the part (PLA is recommended), use small screws or tape to secure the arm to the servo. The position can be adjusted to align perfectly with your Keurig’s brew button.


3. Mounting the Devices

  1. Device A can be left on a table or mounted near the user with an assistive switch
  2. Device B should be positioned securely near the Keurig, with the servo arm aligned directly over the brew button

Velcro, zip ties, or 3D-printed brackets can be used to stabilize the setup. I personally used 3M velcro strips.

Once the physical enclosures and mounts are complete, you can move on to customizing the system and making it your own.

Customize Your Setup

Screenshot 2025-04-30 at 3.01.23 PM.png

Once the system is fully built and functional, you can start customizing it to better fit your specific use case, preferences, or accessibility needs. The project is designed to be flexible, so there are many ways to extend or adapt it.


1. Change the Sound File

You can create your own custom audio message to replace Brewing.wav. For example:

  1. Use ElevenLabs Text-to-Speech to generate a realistic AI voice
  2. Have the system say anything—“Brewing coffee now,” “Request received,” etc.


Once you have your sound file:

  1. Use Audacity to convert it to a compatible format:
  2. Mono
  3. 16-bit PCM WAV
  4. 22.05 kHz or 44.1 kHz sample rate
  5. Follow this tutorial to format it correctly:
  6. https://learn.adafruit.com/microcontroller-compatible-audio-file-conversion
  7. Rename the file to Brewing.wav and copy it to Device B’s CIRCUITPY drive


2. Adjust LED Colors or Patterns

By default, the NeoPixel strip pulses red three times. You can edit the code to:

  1. Change the color (e.g., green, blue, multicolor)
  2. Add a fade effect or chase animation
  3. Increase or decrease the number of pulses


Look for the pulse_pixels() function in code.py on Device B and modify the color values or timing.


3. Change Servo Motion

If your Keurig has a different button height or resistance, you may need to:

  1. Adjust the servo’s angle limits (target_angle and home_angle)
  2. Change the servo delay timing
  3. Experiment with a different servo arm length or mounting position


All of this can be updated in the move_servo_once() function in the Device B code.


4. Add More Devices or Triggers

You can expand the system to support:

  1. Additional remote trigger boxes (more Device A units)
  2. Timed or scheduled coffee starts using the Adafruit IO dashboard
  3. Button status logging for caregivers or usage tracking

This would require creating more feeds, modifying the MQTT setup, or integrating dashboard widgets.


5. Use a Different Appliance

The system is not limited to Keurig machines. With slight modifications, you can adapt this project to:

  1. Push buttons on microwaves, blenders, fans, or other small appliances
  2. Trigger remote lights or audio alerts
  3. Act as an accessible environmental control interface

All you need is a mechanical button and a reliable mounting point for the servo.


Once you’re happy with your customizations, you can finalize the build and prepare it for daily use.

Troubleshooting

If something doesn’t work during setup or operation, this section outlines common problems and how to fix them. Most issues can be resolved by checking wiring, power, or configuration settings.


1. Nothing Happens When Button Is Pressed

  1. Confirm the correct device has the button connected (Device A or Device B)
  2. Make sure the audio jack is wired with the signal to the correct GPIO pin
  3. Check that the settings.toml file exists and contains the correct Wi-Fi and Adafruit IO credentials
  4. Use a serial console (Mu Editor or Thonny) to view debug messages


2. Device B Responds Twice to One Button Press

  1. This means Device B is both detecting its local button press and responding to its own published MQTT message
  2. Fix: Make sure Device B does not publish to the Adafruit IO feed. It should only subscribe and react


3. No Sound Plays

  1. Check that Brewing.wav is present on the root of the CIRCUITPY drive on Device B
  2. Make sure the file is:
  3. 16-bit PCM WAV
  4. Mono
  5. 22.05 kHz or 44.1 kHz sample rate
  6. Confirm that the audio amp is wired correctly and powered from 3.3V
  7. Verify speaker connections and test the amplifier with another known audio source if needed


4. Servo Doesn’t Move

  1. Ensure the servo is powered by VBUS (5V), not 3.3V
  2. Double-check your servo wiring: signal to GP15, ground shared with the board
  3. If the servo twitches or buzzes without moving, power may be insufficient — try a higher-current USB supply or powered hub
  4. Confirm the servo angles (home_angle, target_angle) are appropriate for your setup


5. NeoPixel Strip Not Flashing

  1. Make sure the NeoPixel data line is connected to GP1
  2. Power the strip from VBUS (5V), not 3.3V
  3. All grounds must be connected: Pico, NeoPixels, servo, amp
  4. If the strip flickers or behaves erratically, check that the neopixel library is present in /lib


6. Wi-Fi or MQTT Not Connecting

  1. Double-check your Wi-Fi SSID and password in settings.toml
  2. Verify your Adafruit IO username and AIO key
  3. Make sure your Wi-Fi network supports 2.4 GHz (the Pico W does not support 5 GHz)
  4. Use a serial console to look for error messages like failed connections or bad credentials


7. Device A Doesn’t Trigger Device B

  1. Confirm that Device A is publishing to the correct feed (button-press)
  2. Confirm that Device B is subscribing to that feed
  3. Ensure both devices use the same Adafruit IO username and feed name
  4. Check that the feed was created on your Adafruit IO account and is named exactly button-press (lowercase, with a dash)


Once you’ve verified all of the above, your system should be working reliably. If you’re still stuck, try isolating each component (servo, audio, MQTT) and testing them separately before recombining everything. Using TIO via pycharm can also be very helpful in diagnosing the problem.