Joystick managed by Marlin

In the firmware, within Marlin/src/feature/joystick.h there is //#define JOYSTICK_DEBUG, which you can uncomment, or just put #define JOYSTICK_DEBUG in Configuration_adv.h. With this enabled, M119 will report the joystick ADC values in addition to the endstop state. These ADC values can then be used to modify the settings in Configuration_adv.h:

#define JOY_X_LIMITS { 5600, 8190-100, 8190+100, 10800 } // min, deadzone start, deadzone end, max
#define JOY_Y_LIMITS { 5600, 8250-100, 8250+100, 11000 }
#define JOY_Z_LIMITS { 4800, 8080-100, 8080+100, 11550 }

Note that these values are still reported by M119 even if enable is off, so you can leave enable off and push the joystick to its maximum position to read off the values without simultaneously crashing the machine. :slight_smile:

My preference would have been to leave JOYSTICK_DEBUG enabled by default since almost everyone will need the M119 functionality when the voltages are not exactly identical to my joystick. Maybe I will submit another PR to move this option to Configuration_adv.h where it can be documented and more easily accessible.

1 Like


thanks for explanations, I 'll try



o.k. all works.

But I do not understand why you restricted the lower/upper limits that much which leads to a zero movement. If I use a manual joystick I permanently watch the movement of the toolhead … means any crash is in my responsibility …

BUT nice work!

Jamie, I inspired your awesome project. Thanks for share it.
Can you describe how use M119 command " to determine appropriate values for your joystick dead zone and max range. "?
When I type m119 command it only return endstops state.

You must define JOYSTICK_DEBUG somewhere in Configuration.h or Configuration_adv.h, by adding this line:

My preference would have been for this to be present (but commented) in the usual config files, but they put it in an obscure location in Marlin/src/feature/joystick.h. Without diving into the code it’s impossible to know how to enable it to determine the ADC limits. I probably ought to open a bug for that.

1 Like

Thank you very match, its work.
After I enable JOYSTICK_DEBUG I can see my own values.
I setup joystick on my SKR v1.3 board in thermistor port and got min value 23 and max value 4090. So default config from 5600 to 11000 not aim in my values and joystick do not move before. Now I change to
#define JOY_X_LIMITS { 23, 2045-50, 2045+50, 4090 }
and it work
Sorry for my ugly English, I hope you can understand me.


Your English is just fine!

This is very awesome Jamie. I’m afraid it’s over my head as I went the complete kit route for my LR2 with the minirambo board so plug and play basically on the marlin firmware for me. At least in the video you did this on a mpcnc, is this possible to do on the mini rambo for the LR2? I see this: (Mini-RAMBo (serial wiring): does that mean the board is good to go but perhaps not for LR2 or does that even matter?

It’s probably asking a lot but any chance of a cleaned up guide to implementing this with a first this then this sort of hand holding for beginners? It’s probably obvious for the pro’s here but as I said it’s a bit of wizardry to me.

That software was just the standard V1 firmware (at the time) with the joystick patch applied. It is now obsolete because the latest firmware includes the joystick stuff.

Unfortunately the firmware support doesn’t mean it’s easy, mainly because the Rambo and mini-rambo don’t make the “extra” pins available like the RAMPS and RAMPS-like boards do (like MKS Gen L or Sainsmart 2-in-1).

I’m sorry, I don’t think I can help much beyond that with Rambo or Mini Rambo because it’s not the hardware I’m using. But MPCNC and LR2 should both work the same way if you get it connected and enabled in firmware.

Alright, thanks Jamie all the same. It’s very cool that you got it working this way. I’ve been fussing with the lcd knob and it’s functional but leaves a lot to be desired as a user interface and was pointed this way as an alternative controller option.

Hi Jamie,

I was working on integrating (hacking :smiley: ) jogwheel code into marlin for my MPCNC when I came across your joystick code. Great work. It has inspired me to change direction with what I am doing. :+1:

Instead of modifying the marlin code to integrate a jogwheel and axis / speed selectors switches (a-la traditional CNC) , I’m now designing an external interface (using an arduino nano) that processes the jogwheel and switch info and then mimics a joystick thus connecting to Marlin using your joystick code. This way the Marlin code does not need to be modified and the jogwheel can be made to work with standard code. (win-win).

I have the code working on my testbench and am now at the stage where I need to hook it up and test it, however I have a question relating to the decode of the Joystick.

I need to mimic these values using the analog out of the Nano. Essentially reproducing the voltage that would normally be seen from the joystick.

My question is, what do the values defined for JOY_X_LIMITS correspond to? Are these resistance values?

I assume that they are not raw ADC values as most Arduino’s are only 10 bit, which only gives a max resolution of 1024, and the values you have in your code are much larger.

I did post a question on your github commit, but then thought it better to post here.

Any help / advice greatly appreciated.


If anyone is interested in what I’m doing code can be found on Github: /DeeEmm/Marlin-CNC-Pendant


That sounds fun! Please share pictures and progress, probably in another post, I think we are all interested.

Did you try turning on the JOY_DEBUG? That will show you the values you’re getting.

I think you also need a small R/C circuit to smooth the pwm output into an analog signal. I am guessing that without that, the analog input will either be 1024, 0, or random if it catches an edge.

They are like ADC values but the way Marlin does the sampling they are summed/averaged so they behave as if they are 14 bit values.

What hardware are you using? I am guessing an encoder based jog wheel? I can see the value in a jog wheel but I would be a little concerned it might not feel like what you are expecting. Either way I am interested to hear what you find.

Also, not to discourage you from the analog joystick method but if you already have an external processor you could inject gcode like the other joystick approach I’ve seen.

Ahh okay, so 2^14 = 16384 resolution. Thanks. :+1:

That should give me enough to be able to calculate voltage levels based on the resistance of the joystick and your JOY_X_LIMITS.

I did look at the example in the link. The issue for my setup is that I am using the serial port with an HC-06 bluetooth module so that I can use CNCjs on my laptop, which leaves me with having to use an alternate method. (I’m using a rumba board).

Hardware is a regular CNC style encoder jogwheel and simple selector switches for the axis and speed. (X, Y, Z & X1, X10, X100). A regular MPG jogwheel pendant will also work.

How it works: Essentially the jogwheel will always output a voltage equivalent to the centre of range (lets say 2.5v - an arbitrary voltage value just for explanation) so no movement will occur as this should equate to the centre of your defined dead band. Then if X1 is selected and the jog-wheel rotated, it will output either 2v or 3v depending on direction - so this mimics a small joystick movement. As the speed selector is increased, the voltage outputted also increases (1.5v & 3.5v) which mimics a larger joystick movement. It’s these voltages I need to calculate.

Of course the movement will only be one axis at a time and only at the selected speed. There is opportunity to make the output speed proportional to the speed that the jogwheel is rotated, but that’s not how it’s currently set up.

The code also detects the speed of the wheel rotation, so for small / slow movements it will output a pulse for each jogwheel click. For faster movements it will maintain the output to smooth the movement, otherwise each jogwheel pulse will generate a jerky movement.

On the bench it appears to work very well, with the voltage output seemingly stable and changing in accordance with the selected speed. Now I have some idea of the required output values I can move to testing on the machine and see how it actually works.

I’ll post up my findings in another thread as I don’t want to hijack yours.

1 Like

(Can’t find the edit button.)

Also, with regards to the setup in the link. I was concerned with the Gcode command buffer in sending movements. in that there will be moves buffered that will execute long after the jogwheel has stopped. This is exactly the same behaviour you see when you manually control your machine via a printer interface when connected serially.

The big appeal of your solution was the limitation on how the moves are buffered.

:+1: Exactly. This is why Jamie’s solution is my favorite. IIRC, there was someone trying to leverage Jamie’s planner commands via a jog command over serial. Grbl does this, I think, so that jog commands are interruptible and relative. Unfortunately, I remember them being $ commands.

Yes, that would definitely be possible, but requires change to the Marlin code. By utilising Jamie’s solution the Marlin code can be used without any need to modify / hack it. Which is far more elegant in my opinion.

I actually think that Jamies solution is brilliant, in both the way that it interfaces with Marlin and the characteristics of the movement. If I had not already have the jogwheel and switches for my build, I would definitely be purchasing a joystick. However I promised myself to get this finished over the Xmas break and there’s no time to wait for new parts to arrive (The joysticks are unfortunately not available locally).

Necessity is the mother of invention as they say. :slight_smile:


The Jogwheel is nice but I wouldn’t use it this way if I were you.
What I’d do would be to use both joysticks and this jogwheel. I know you don’t have joysticks right now, but those things are really super cheap and you can make your project including these even if you did not receive them yet. They can be installed at the very end, it doesn’t matter :slight_smile:

-Use the Joysticks to be able to quickly move from somewhere to somewhere else. It’s more convenient since you don’t have to switch between axis and click on a button every time. Much more intuitive.
-Use the jogwheel for precise movements, by correlating the wheel markings to actual dimensional movements. This can be very useful for precision positioning or, even better, for actual cutting in manual mode.

So, this way, you first move to the place you want to cut something using the joysticks, set your origin. Then you use the jogwheel to cut a 25.6 x 38.2mm rectangle, for instance. Basically the jogwheel would be a manual cutting tool, each increment could be 0.1mm of distance or whatever you want, and since you have markings on the wheel yo could easily do very accurate cuts.
That’s probably how I would have done it if I happened to have one of these wheels, the idea didn’t occur to me at that time.

You’d just need a button to switch between joystick mode or jogwheel mode. When pressing this button, you’d have to use both the joystick and the jogwheel together to get a movement.
For instance, you want to move the x axis 2.4mm to the right? Then move your joystick to the right and turn the jogwheel until it reaches 2.4mm. This way you don’t have to bother with “which way should I turn the jogwheel to go right”, it wouldn’t matter since the direction would be set by the joystick, which is much more intuitive.
You want to move the Y axis 5.6mm away from you? Then move the Y axis joystick away and turn the jogwheel until it reaches 5.6mm.
You just moved your jogwheel to 5.6mm and you have to do your next cut which is a 45.7mm cut. You don’t want to do the math? Then jus release the joysticks and move the jogwheel back to zero. No axis shoud move. You’re ready for your next cut, easy.
You can even probably move both axis at the same time so you can have 45 degree movements, using the same principles.

The code would need to be a bit different here, since it would need to be speed driven instead of just distance driven like the one I’m using. But this is probably easy to do.

And if you’re good at coding I suppose you could do some awesome stuff, like circles using some joystick combinations and the jogwheel. (ex: first go to the center, switch to maanual mode, then rotate the joystick all around twice, set the jogwheel to 5 mm and it will cut you a circle of a 5mm radius around the point you just set up as your center). There are lots of awesome possibilities for anyone who like to play around with the code I guess.

I think this would be the perfect remote control, If I wasn’t lazy to start over that’s probably how I’d do it.


The best thing I can think of using a joystick or a wheel is that I will not accidentally click on the Z axis and drive it into the board!

1 Like

I bought the same joystick… when I hooked it up to my meter with 5v I’m getting 1.8 to 3.3v on x and y and z twist is giving me only 0.05v to 0.10v. Is that normal ?