If you have done any extensive poking around the Grbl source code you will eventually come across this line in nut_bolts.h.
#define N_AXIS 3 // Number of axes
It would be so easy to just change that to 4 or 6 and have some fun, right? No, unfortunately it is not that easy. With a little work though, it is not too hard to add those extra axes to Grbl. I decide to try this with my PSoC port of Grbl.
Typically the axes after X,Y, and Z are labeled A,B, and C and are often rotary axes. Here is a simple 4th rotary axis.
Things get more complicated when you add more axes. Here is an example of a 5 axis upgrade for a 3 axis machine.
While simply changing N_AXIS does not suddenly make the extra axes work, it does do a lot of the work. I found it used over 80 places in my port. It will do virtually all of the major code work. I just needed to do the following…
- Read the ABC parameters in the gcode.
- Add additional $$ settings for steps/mm, speed and acceleration for the A, B, and C axes.
- Add homing code for A,B, and C.
- Adds some #define statements to make it easier to configure between the axis counts.
As I was working on this I stumbled upon a few other people working on this. This code I found was especially helpful.
Grbl uses 1 byte byte each for axis step, direction and limits switches. Those bytes are used with a mask (to say with bits are actually used) and applied directly to an I/O port. This is a very efficient way of doing it, but it forces you to put all axes on one I/O port for each of the step direction and limit switch functions.
My port to PSoC uses Control Registers to output the step and direction signals and Status Registers to read the limits switches. These registers can be ‘wired’ directly to I/O pins. There are several advantages to this, but the main ones in this context are, you don’t need to map them to the same I/O port and you only have to connect the ones you want to use. Here I have defined all 6 bits on the Control Register, but have only connected the I/O pins I am using.
To make the PSoC port easier to maintain as Grbl changes, I did not change the Grbl method to much. The mask is still applied, but the mask is hard coded.
The homing switches work in a similar fashion. Here is a 4 axis setup.
The storage of the steps/mm, speed, and acceleration will increase the amount of EEPROM required. The PSoC has plenty, but keep in mind every time you change the axis count, you will need to reset the EEPROM because the locations will get shuffled and the restore from EEPROM will not work the first time you start under the new axis count.
The status is going to report the extra axes, so I assume it will break a few senders.
? <Idle|MPos:1.680,4.568,-0.900,0.664,0.428,0.984|FS:0,0> ok
$# [G54:0.000,0.000,0.000,0.000,0.000,0.000] [G55:0.000,0.000,0.000,0.000,0.000,0.000] [G56:0.000,0.000,0.000,0.000,0.000,0.000] [G57:0.000,0.000,0.000,0.000,0.000,0.000] [G58:0.000,0.000,0.000,0.000,0.000,0.000] [G59:0.000,0.000,0.000,0.000,0.000,0.000] [G28:0.000,0.000,0.000,0.000,0.000,0.000] [G30:0.000,0.000,0.000,0.000,0.000,0.000] [G92:0.000,0.000,0.000,0.000,0.000,0.000] ok
Sending the GCode is pretty easy, but I don’t know of any basic gcode senders that support more than three axes.
My personal sender uses regular expression to do the basic parsing of the status. This is a robust way to to handle status that can change formats as long as it is predictable. I send the position data to a function that splits it into a string array. I’ll just need to add some DROs for the extra axes if it detects them.
I don’t have a 4 or 6 axis CNC, so I built a little test rig with 6 axes. I used a Gecko G540 and 2 single axis drivers. Each stepper has it’s own home switch triggered by a cam on limit switches with roller actuators. This allows the switches to be triggered , but allows the steppers to run continuously in either direction. The homing sequence is quite fun to watch. Building this test rig took about as much time as the firmware changes.
I want to do a lot of testing, then build a machine to do some real world testing. I currently don’t have any decent CAM software over 3 axes, so I will need to deal with that. I will then add it to my GitHub repo for this.