CNC Simulator Pro

user guide

11.18.2. Tutorial Arduino based Jog controller

There is a serial port controller protocol that can be used to control CNC Simulator Pro via the serial port (actually the USB port via a “virtual com port”).
At, we always claim that CNC should be fun. And we think this project is a really fun one. Hobbyists and students, it is time for some Do It Yourself electronics!
Using an Arduino Uno and some basic components, we can easily make a Jog controller. Here is how you can make your own:
You need:
3 1K-ohm Resistors
3 LED (Red, Green, Yellow)
1 Joystick Module (Amazon link)
1 Rotary Encoder (Amazon link)
Some cables, an Arduino Uno or compatible.
1 USB Cable
1 Breadboard
Let us test the circuit on the breadboard before putting everything together in a box.
When we have all wires and components in place, it is time to transfer the firmware program to the Arduino chip.
If you do not already have the Arduino software installed on your computer, please visit their website and download (and install it) using the following link.
Connect your Arduino and make sure you get it connected to the computer.
Copy and paste the CNC Simulator Pro Jog Controller Sketch to the Arduino program and upload it to the board. The sketch (program) is open source. Feel free to do changes as you like.

#include <Encoder.h>
// Encoder lib found here:
// "Jog Controller" - CNCSimulator Pro Arduino Sketch for manual jog of the CNC axis
// Made for Arduino JoyStick Module and Rotary encoder.
// Press the center button to switch between input modes (X,Y,Z,XY,STEP etc.)
// Move joystick to jog axis or change step (depending on mode)
// Long press to set all axis to zero and generate G92 code.
// This code is provided free of charge and should be considered an experimental prototype.
// Optimize for own hardware as well as customized functionality.
// Commands to send to the CNCSimulator.
// ST+ or ST- = STEP+ and STEP- Rotary encoder increase/decrease
// J[PotH]:[PotV] Joystick Potentiometer values, both range from -100 to 100
// CJM Cycle Jog Mode - Joystick center button was pressed, cycles Jog mode settings
// SZP Joystick center button was long pressed (1 sec). Sets zero point
// JMX Jog Mode X  (unused here, we use CJM instead)
// JMY Jog Mode Y  (unused here, we use CJM instead)
// JMZ Jog Mode Z  (unused here, we use CJM instead)
// JXY Jog Mode XY  (unused here, we use CJM instead)
// STP Step Mode   (unused here, we use CJM instead)
// ETL Embedded Tool (unused here, we use CJM instead)
// Commands to receive from the CNCSimulator
// @R Simulator is running  (Red LED)
// @P Simulator has paused  (Yellow LED)
// @S Simulator has stopped (Green LED)
// @E Simulation error (Red and green LEDs)
// @C Cycle leds
// @O All LEDs off
#define joyPin1 0               // slider variable connected to analog pin 0
#define joyPin2 1               // slider variable connected to analog pin 1
#define redLedPin 8
#define yelLedPin 9
#define greenLedPin 10
#define button1Pin 0            // joystick center button
#define encoderPin1 2
#define encoderPin2 3
#define blinkdelay 50
int value1 = 0;                 // variable to read the value from the analog pin 0
int value2 = 0;                 // variable to read the value from the analog pin 1
int button1state;
int btnval1;
int btnval2;                    // used to debounce buttons
boolean waitingForCmd = false;
int Counter = 0;
const int JoyStickDeadZone = 10;
volatile long encoderValue = 0;
long lastencoderValue = 0;
Encoder myEnc(encoderPin1, encoderPin2);
// Note: The Keyes Rot. Encoder is a bit bouncy with this sketch.
// Code changes or hardware debouncing might be needed.
void setup()
 // Setup pin modes
 pinMode(button1Pin, INPUT);
 pinMode(redLedPin, OUTPUT);
 pinMode(yelLedPin, OUTPUT);
 pinMode(greenLedPin, OUTPUT);
 pinMode(encoderPin1, INPUT_PULLUP);
 pinMode(encoderPin2, INPUT_PULLUP);
 button1state = digitalRead(button1Pin);
 // Do a little initial blink with the LEDs to signal wakeup
void loop()
 // Rotary encoder part
   if(encoderValue > lastencoderValue)
   lastencoderValue = encoderValue;
 // Joystick part
 if(Counter == 1)
   value1 = map(analogRead(joyPin1), 0,1023,-100,100);
 else if(Counter == 2)
   value2 = map(analogRead(joyPin2), 0,1023,-100,100);
 if(value1 < -JoyStickDeadZone ||
   value1 > JoyStickDeadZone ||
   value2 < -JoyStickDeadZone ||
   value2 > JoyStickDeadZone)
   // joystick is off center, notify the CNCSimulator
   if(value1 < -5 || value1 > 5)
   if(value2 < -5 || value2 > 5)
   btnval1 = digitalRead(button1Pin);
   btnval2 = digitalRead(button1Pin);
     if(btnval1 != button1state)
       button1state = btnval1;
       if(btnval1 == LOW)
         // Button 1 is pressed
         unsigned long timeStart = millis();
         while(digitalRead(button1Pin)==LOW)  // Wait for it to become released
           if(millis()-timeStart > 1000) // Long press
   Counter = 1;
 delay(80);  // delay needed between analog reads
 // Receive commands from the CNCSimulator
 if(Serial.available() > 0)
   char data =;
   else if(data == '@')  // one byte command on its way
     if(Serial.available()> 0)
       waitingForCmd = true;     
void doOneByteCmd(char cmd)
 waitingForCmd = false;
 if(cmd == 'R')  // Running
   setLEDs(true, false, false);
 else if(cmd=='P')  // Paused
   setLEDs(false, true, false);
 else if(cmd=='S')  // Stopped
   setLEDs(false, false, true);
 else if(cmd=='E')  // Error (Red + Green)
   setLEDs(true, false, true);
 else if(cmd=='O')  // All LEDs off
   setLEDs(false, false, false);
 else if(cmd=='C') // Cycle LEDs
void cycleLEDs()
 setLEDs(false, false, false);
 for(int l = 0; l<3; l++)
   setLEDs(true, false, false);
   setLEDs(true, true, false);
   setLEDs(true, true, true);
   setLEDs(false, true, true);
   setLEDs(false, false, true);
   setLEDs(false, false, false);
void setLEDs(bool red, bool yellow, bool green)
 digitalWrite(redLedPin, red);
 digitalWrite(yelLedPin, yellow);
 digitalWrite(greenLedPin, green);

Time to test it out!
Start CNC Simulator Pro and go to settings. Click on the Misc tab and check the Enable box. Set the com port (same as you have set in the Arduino software). Set the baud rate to 115200 to match the value in the Arduino sketch above.
When you close settings, the green LED should come on. This is a sign that CNC Simulator Pro and the Arduino are talking to each other.
Now when you turn the Rotary encoder, the feed knob should turn in the virtual CNC controller.
If this does not work, check your circuit and do some checks using the serial monitor in the Arduino software to make sure the commands get sent on the com port.
If it, on the other hand, works, Congratulations! You have made your own hand controller! At least a prototype of it.
To activate the Jogging function in CNC Simulator Pro, click the Jog Enable switch at the virtual controller.
If you add a workpiece to the machine, you can even mill (or turn) it manually using the hand controller joystick.
Do you see that tiny yellow LED blinking fast on the Arduino board? It is the Tx (transmit) LED telling us that the Arduino is sending data over the serial port (via the USB cable). In this case, the data is the Joystick movements.
And when you do normal simulation, check that the LEDs work. See the manual below for LED signals.

Jog Controller Manual

When Jogging is not enabled, the Rotary encoder will increase and decrease simulation speed.
When Jogging is enabled, it is used in the following way:
Click the center of the Joystick to cycle through the jogging modes. They are as follows for milling machines:
X – Jog the X-axis only (Joystick sideways and Rotary encoder)
Y – Jog the Y-axis only (Joystick vertically and Rotary encoder)
Z – Jog the Z-axis only (Joystick vertically and Rotary encoder)
XY – Jog both the X and the Y-axis (Joystick only)
ET – Cycle through the Embedded Tools (Rotary encoder)
STP – Increase and decrease step size (Rotary encoder)
If you long-press (1 second or more) the center button, the zero point will move to the current tool position, and a G92 block will be generated in the CNC program where the cursor is.
The LED:s works as follows:
Red: Simulator is running (busy)
Yellow: Simulator is paused
Green: Simulation is stopped (idle)
If you lose connection with the controller (for example, if the Arduino loses power), the correct procedure to restart the connection is to exit CNC Simulator Pro, unplug the Arduino USB cable, and after a few seconds, replug it. Then start CNC Simulator Pro again. The controller should now be reconnected.
Important! This project is not considered to be part of the main product. It is experimental and DIY (Do It Yourself). If you are not comfortable with basic electronics and Arduino microcontroller boards, we encourage you to read and do tutorials available on the Arduino web site. We cannot give any support on experimental hardware projects. It is impossible for our program support to know what could be going wrong in your particular project. Please have this in mind before starting any DIY projects described on our web site.