Tuesday, July 14, 2009

G-Code Interpreter

As part of my 3D-Printer project, I'm writing a G-Code interpreter to run on an Arduino. My machine will support a fairly limited subset of G-Code, as well as a few extra commands specific to my machine.
  1. Using the partial G-Code spec available from LinuxCNC, I developed a rudimentary parser. Here's the control flow of the parser:
  2. Split G-Code file into lines (blocks)
  3. Search each block for valid words in specific order: X, Y, Z, S, F, T, M, G
  4. Handle each word appropriately (set feed, set speed, move, etc.)

There are some notes here:

Location values must be maintained statically so code like this will run:
G01 Z1.0 F.05 X0.0
Speeds and feeds must be read first so code like this will run:
G01 Z1.0 F.05
Since my printer only has one toolhead, I changed the T word to represent temperature. I realize this is an awful and confusing decision, and will probably change it eventually. Here's my (messy) code.
void  Printer::parseBlock(char *string)
{
//Location must be maintained
static Location location = Location(0,0,0);

//Control words: Feed rate, extrusion speed and temperature
int s = 0;
int f = 0;
int t = 0;

//G Mode is persistent
static int g = 0;

//Machine Option is not persistent
int m = 0;

//Search string for accepted codes, then execute
//order is important, be careful when changing

char *p = string;

//Position First
if ((p = strpbrk(string, "X")))
{
sscanf(p, "X%f", &(location.iX));
}
if ((p = strpbrk(string, "Y")))
{
sscanf(p, "Y%f", &(location.iY));
}

if ((p = strpbrk(string, "Z")))
{
sscanf(p, "Z%f", &(location.iZ));
}

//Speed, Temp and Feed
if ((p = strpbrk(string, "S")))
{
sscanf(p, "S%d", &s);
S(s);
}

if ((p = strpbrk(string, "F")))
{
sscanf(p, "F%d", &f);
F(f);
}

if ((p = strpbrk(string, "T")))
{
sscanf(p, "T%d", &t);
T(t);
}

//Operation Codes (M)
//Conflicts are resolved by order
//AKA: conflicts are not resolved
p = string;
while ((p = strpbrk(p, "M")))
{
sscanf(p, "M%d", &m);
M(m);
//Move to next spot
p++;
}

//G Codes
//Conflicts are resolved in order, AKA not resolved
p = string;
while ((p = strpbrk(p, "G")))
{
sscanf(p, "G%d", &g);
G(g, location);
p++;
}

}

1 comment:

Robert Giteya said...

I am about to start work on my own microcontroller based G-Code Interpreter and seeing as you have already walked down that road, any insights as to where and how I should start?