Joystick managed by Marlin

As a bit of a diversion from my second build, I’ve put together a joystick that allows jogging with analog control of the feed rate.

I decided to take a different approach from the approaches I’ve seen, which operate through the Raspberry Pi or a separate microcontroller like @arminth’s solution (

This one has a very dumb joystick, with modifications made to Marlin to read the analog values and inject g-code into itself. Here is a schematic of the joystick. The enable pin is active-low with a pullup on the digial pin, so if it’s disconnected it will treat it as disabled and not lose its mind trying to read floating analog voltages. Right now I have this connected on AUX-2, using A5, A10, D44, and A12.

[attachment file=106111]

I’ll publish the code, but I’m not sure whether to try for a fork and pull request, or to just publish a patch file. There is not that much code and it’s a pretty non-invasive modification. One way or another I’ll post it once I get it organized for publication.

I started with one of the super cheap x/y thumb joysticks, but the inconsistency of the ADC readings was making me nervous, so I bought this one for $17:

The overall strategy is mostly straightforward. Read the analog values, by mimicking the method used for temperature ADC reading. Then in the idle loop, check to see if the enable pin is active (low) and if the joystick is outside the dead zone. If the movement queue has more than 4 commands, then abort, so we fill the queue with only about 1/4th of a second worth of movement.

If all the checks pass, then calculate a feed rate (as a fraction of the maximum feed rate) based on how far the joystick is pushed. Then for that feed rate, calculate the distance that would take about 1/20th of a second to traverse. Then temporarily enter relative mode and inject a g-code command to move that distance at that feed rate.

As a result, the joystick should generate a constant flow of about 20 commands per second with roughly a 1/4 second lag between the joystick position and the speed response. Since a small movement of the joystick can provide slow movement, a bit of lag should be alright since you can jog quickly and fine-tune at low speed, so you don’t have to stop on a dime.


This is great! This is exactly what is needed in jogging. Very clever.

Have you tried a non linear response? I have a feeling my moves will all be full speed or creeping, but with a continuous in between. Making a little expo curve would give a bit more range on the low end while keeping a high top end.

1 Like

Wow…I hope this is can get pulled in. We could entertain so many people with a ZenXY…


A keen observation! Yes, actually it’s already nonlinear. I was first thinking exponential like you said, but quadratic was quicker to code (no decisions to make on choosing dynamic range) and so far it seems good enough by feel. Although I haven’t put it into real use, it seems to have pretty good granularity at the low end.

1 Like

Okay, here’s a commit which I “ported” to upstream Marlin bugfix-2.0.x.

It appears this branch of Marlin is a fast-moving target, functions and variables changed names so I don’t know that a single patch will apply to upstream Marlin and also work for (today’s) MPCNC flavors. But I can generate PRs against the V1 firmware if there’s interest.

I’m going to build “pure” Marlin with this change, plus configuration changes for steps/mm etc., and once I confirm that it still works I’ll submit it to upstream Marlin for their consideration.

1 Like

Okay, pull request officially submitted to upstream Marlin:

I have no idea if they will adopt it but we will see.

Awesome, subscribed to that one!

Looks good. I hope you don’t mind my armchair peer reviewing. I hope those things make it easier to swallow into the main. I do think they will want it outside of temperature. I also think they will like it. They do have some cnc only features and it’s completely disabled by default. There also some larger 3D printers that might benefit from this.

I personally am very tempted to hook my son’s toy 3D printer up with a spare Marlin controller and a joystick… He would go bonkers for it.

DUDE!!! YES! Congratulations! Awesome addition to Marlin.


Now I am going to have to figure out how to use it. Joystick has been ordered…Need to update my zen.

Oops jumped the gun…looks close though!

1 Like

WOW. 6 years later, has there been any third party success with this topic, particularly on Marlin 2.0 optimized for MPCNC dual endstop LCD? I am fearful of combining the two Marlin edits… not afraid to get my hands dirty with some C++ but is it worth the hassle. Also, you stated this script ran in the idle loop, does that mean it will not interfere with running Gcode or add unnecessary computation to the travel calculations? I am debating an attempt to disable temperature for this reason considering I am not planning to 3D print with this build. I know there are a few analog pins on the Rambo.

Definitely an admirable project and contribution!

Marlin 2.0 is changing rather a lot lately, and the patch for adding joystick to the latest Marlin won’t work on the MPCNC flavors. Some of the variables have changed names and it won’t merge cleanly.

I originally implemented the feature off the MPCNC codebase, so if you want it I can publish a fork that contains the joystick update. Tell me which branch you’re using and I can make it pretty hassle-free.

Or you can wait for the patch to make it into official Marlin and for the MPCNC fork to pull from upstream, but there are no guarantees on when either of these will happen.

It shouldn’t interfere with processing because 1. everything time-sensitive is driven by interrupts, and 2. it tries to minimize CPU usage by aborting early if there is nothing to do, and 3. it shouldn’t be enabled while you’re processing a job (part of the reason for the enable pin, besides preventing screwing up a job), and 4. a job will usually (maybe) keep the planner full, which also disables the joystick. So it should be extremely gentle on the CPU when running a job.


1 Like

What is 6 years?

And it looks like Jamie’s PR is getting enough attention to get effectively pulled when “ready”. NICE !

Whoops, I misread the forum date, looks like this is a lot more recent XD. Yes I am on the MPCNC full size RAMBO with dual endstop and large LCD flavor. I have a super-PID in the mail but I will likely keep it on a separate circuit with a dial just because I feel more comfortable with manual control over that, despite Marlin’s support for it. I think with all the emerging 3D printer tech it might be some time before a more convenient jogging method is prioritized over support for new extruder and sensor types, but hopefully not! I would very much appreciate the RAMBO_dualend_LCD patch if you still have it,



1 Like

here is the same joystick for non-USA residents.

(I live in Mexico and only a portion of amazon ships here.)

I was literally searching for a way to do this for 3 weeks. And then all the sudden after I had given up, I was on V1 Forums and you posted this. You are awesome.

Ok, it seems there’s quite a lot of interest in this. Eventually I am hoping it will make its way into upstream Marlin 2.0.x but in the mean time I’ve patched five versions of Ryan’s MPCNC code: RAMBo, dual and non-dual flavors, RAMPS, dual and non-dual flavors, and Mini-RAMBo.

I tested the change on the RAMPS series-wired version and merged the change into the other 4. I am pretty sure this will work but technically it’s untested.

I couldn’t create a proper fork because I already have a fork for the upstream Marlin 2.0.x and GitHub doesn’t permit multiple forks (or forks-of-forks) on a single account. So instead I imported which appears to be nearly the same thing.

Here are the versions

  • RAMPS, serial wiring:
  • RAMPS, dual endstops:
  • RAMBo, serial wiring:
  • RAMBo, dual endstops:
  • Mini-RAMBo (serial wiring):
This contains the implementation but it's not enabled by default. You must enable it and set your pins at the bottom of Configuration_adv.h.

You will also need to use M119 (with joystick switch off) to determine appropriate values for your joystick dead zone and max range. The configuration allows going without an enable switch but I think it’s a really bad idea to do so. Your machine might take off on you as soon as it’s powered on. The enable switch is configured to be enabled when the enable pin is shorted to ground, and disabled when the switch is open. This allows disconnecting the joystick without having the machine decide to move on its own.

I’d love to see video if other people get this working!


Looking over the list, I realized the ZenXY might be especially fun, so I patched those too:

  • ZenXY Mini-RAMBo:
  • ZenXY RAMPS:

I would appreciate any advice on adding a joystick to the SKR 1.3. I wonder if there are enough spare analog inputs to do this???