Serial read G code

Im trying to read from arduino serial terminal comands like G1 100, M1 230, M500,... brake them down into segments (G - type of command, 100 - integer) and then get:
if G1 comand
{
if (val == 100) {
some code...
}
}

My code:

void serialEvent() {
while (Serial.available())
{
char inChar = (char)Serial.read();
inputString += inChar;

if(inputString == "M0") Serial.println("K");

if ((inChar == 32)||(inChar == 13)) // Space in text
{
if(inputString == "10") Serial.println("OK");

inputString = "";
}

if (inChar == 13) inputString = ""; // Clear data at end
}
}

Ok, How well is it working? Does what you are getting match up with the G-code standards?
Paul

This might make a starting point.

#include "lilParser.h"

#define  MAX_PARAMS  5  // The Max number of params that a G-code can have.


// What param types that you can parse out. Looking at G codes it looks like the
// first letter gives the type. I gessed at some. you will need to fill this out.
enum paramTypes { xAxis, yAxis, zAxis, feed, letterI, letterJ };


// Handy little struct to hold a param value.
// Probably need to modify this at some point.
struct paramValue {
   paramTypes  theType;
   float       theValue;
};



// Our list of G code commands.
enum commands {   noCommand,  // ALWAYS start with noCommand. Or something simlar.
                  G00,        // The rest is up to you. help would be a good one. Have it list
                  G01,        // What the other commands are, how they work and what they do.
                  G02
                  // Add more here..
                  };          

lilParser   GCodeParser;        // The parser object.

void setup() {

   Serial.begin(57600);
   GCodeParser.addCmd(G00,"G00");   // Add G00 to your parser. (Command num,string typed in)
   GCodeParser.addCmd(G01,"G01");   // Add G01.
   GCodeParser.addCmd(G02,"G02");   // G02..
}


// Your loop where it parses out all your typings.
void loop(void) {

   char  inChar;
   int   command;
   
   if (Serial.available()) {                 // If serial has some data..
      inChar = Serial.read();                // Read out a charactor.
      Serial.print(inChar);                  // If using development machine, echo the charactor.
      command = GCodeParser.addChar(inChar); // Try parsing what we have.
      switch (command) {                     // Check the results.
         case noCommand : break;             // Nothing to report, move along.
         case G00   : doG00();   break;      // Got a G00
         case G01   : doG01();   break;      // Got a G01
         case G02   : doG02();   break;      // Got a G02
         default     : 
            Serial.println("What?");         // No idea. Try again?
         break;   
      }
   }
}



/************************************************************************************
*************************************************************************************

                     Now the list of command handlers you call from
                     your main loop() when commands are parsed.   
                                        
*************************************************************************************
*************************************************************************************/

// All the prams seem to be a char and a value. So we pull those apart with this.
paramValue parseParam(char* theParam) {

   paramValue  aValue;
   switch(theParam[0]) {
      case 'X' : aValue.theType = xAxis;     break;
      case 'Y' : aValue.theType = yAxis;     break;  
      case 'Z' : aValue.theType = zAxis;     break;
      case 'F' : aValue.theType = feed;      break;
      case 'I' : aValue.theType = letterI;   break;
      case 'J' : aValue.theType = letterJ;   break;
      default  :
         Serial.println("Unknown param type, Stopping program!");
         while(1);
   }
   aValue.theValue = atof(&(theParam[1]));
   return aValue;
}


// Deal with a G00 command. 
void doG00(void) {

   char*       paramStr;
   int         numParams;
   paramValue  theParams[MAX_PARAMS];        

   numParams = GCodeParser.numParams();      // How amny params we got in this one?
   for (int i=0;i<numParams;i++) {           // Loop through all the params..
      paramStr = GCodeParser.getParamBuff(); // We get a parameter. Each time it steps to the next one.
      theParams[i] = parseParam(paramStr);   // This function pulls the parameter apart and hands back the bits.
      free(paramStr);                        // Dump the parameter buffer ASAP.
   }
   Serial.println("Got a G00");
   Serial.print("With ");
   Serial.print(numParams);
   Serial.println(" params");
   // At this point you know how many prams you got.
   // You know what axis they came from and the values.
   // Do your deal!     
}


// Deal with a G01 command. 
void doG01(void) {

   char*       paramStr;
   int         numParams;
   paramValue  theParams[MAX_PARAMS];

   numParams = GCodeParser.numParams();      // How amny params we got in this one?
   for (int i=0;i<numParams;i++) {           // Loop through all the params..
      paramStr = GCodeParser.getParamBuff(); // We get a parameter. Each time it steps to the next one.
      theParams[i] = parseParam(paramStr);   // This function pulls the parameter apart and hands back the bits.
      free(paramStr);                        // Dump the parameter buffer ASAP.
   }
   Serial.println("Got a G01");
   Serial.print("With ");
   Serial.print(numParams);
   Serial.println(" params");
   // Again, at this point, do your deal!     
}


// Deal with a G02 command. 
void doG02(void) {

   char*       paramStr;
   int         numParams;
   paramValue  theParams[MAX_PARAMS];

   numParams = GCodeParser.numParams();      // How amny params we got in this one?
   for (int i=0;i<numParams;i++) {           // Loop through all the params..
      paramStr = GCodeParser.getParamBuff(); // We get a parameter. Each time it steps to the next one.
      theParams[i] = parseParam(paramStr);   // This function pulls the parameter apart and hands back the bits.
      free(paramStr);                        // Dump the parameter buffer ASAP.
   }
   Serial.println("Got a G02");
   Serial.print("With ");
   Serial.print(numParams);
   Serial.println(" params");
   // Again, at this point, do your deal!     
}

If you would like to try this, you will need to install LC_baseTools and LC_lilParser from the IDE library manager. And, if you want to do a bunch of G-codes, you should get a processor with more RAM that the standard Arduino UNO.

Good luck!

-jim lee

Ignoring for the moment that "G1 100, M1 230, M500,..." is not valid G-code....

How much of the RS-274 standard do you need to implement? It can get quite complex. And you cannot, in general, parse the code it AS is comes in, since the order of arguments on each block is not defined, and they MUST be executed in the correct order, regardless of the order in which they are received. You have to collect a line, parse the line, THEN determine the correct execution order.

Yes, but remember. The longest journey starts with but a simple step..

-jim lee

kristjank7:
Im trying to read from arduino serial terminal comands like G1 100, M1 230, M500,... brake them down into segments (G - type of command, 100 - integer) and then get:

i believe it's best to break the problem into parts.

consider the following
probably more than you want, but i breaks processing a line of input into tokens (e.g. G1 100) separated by commas and putting a string code (e.g. G1) and a numeric argument on a "stack" which is then processed after the input string is tokenized.

each element on the stack is processed using decode() which searches an incomplete table of functions for each code. you need to add the functions for each command code.

while you may feel the program is too complicated, you would probably struggle to write a simpler version. in general, biting the bullet, recognizing the complexity of the problem early and implementing a more generic approcah makes it easier in the long run as well as easier to fix those "oofs"

// ------------------------------------------------
void rapidPos     (int  arg) { Serial.println ("rapid positioning:"); }
void linearInterp (int  arg) { Serial.println ("linear interpolate:"); }
void optionalStop (int  arg) { Serial.println ("optional stop:"); }

struct Cmd_s  {
    const char *code;
    void (*func) (int arg);
} cmds [] = {
    { "G0",  rapidPos },
    { "G1",  linearInterp },

    { "M1",  optionalStop },
};

#define N_CMDS  (sizeof(cmds)/sizeof(Cmd_s))

// ------------------------------------------------
void
decode (
    char*   code,
    int     arg )
{
    unsigned n;
    for (n = 0; n < N_CMDS; n++)  {
        if (! strcmp (cmds [n].code, code))  {
            return cmds [n].func (arg);
        }
    }

    char s [30];
    sprintf (s, "%s: not found - %s", __func__, code);
    Serial.println (s);
}

// -----------------------------------------------------------------------------
#define STACK_SIZE 20
struct Stack_s {
    char *code;
    int   arg;
} stack [STACK_SIZE];

int stkIdx = 0;

// ------------------------------------------------
void
process (void)  {
    Serial.println (__func__);

    for (int n = 0; n < stkIdx; n++)  {
        char s [30];
        sprintf (s, "%6s %6d", stack [n].code, stack [n].arg);
        Serial.println (s);

        decode (stack [n].code, stack [n].arg);
    }
}

// ------------------------------------------------
void
parse (
    char *s)
{
    char  *p;
    char  *tok;

    Serial.println (__func__);

    stkIdx = 0; 
    for ( ; (tok = strtok_r (s, ",", &p)); s = NULL)  {
        Serial.println (tok);

        stack [stkIdx].code = strtok (tok, " ");

        if (char *sArg = strtok (NULL, " "))
            stack [stkIdx].arg = atoi (sArg);

        stkIdx++;
    }
}

// -----------------------------------------------------------------------------

void setup (void)
{
    Serial.begin (9600);

    parse ((char*) "G1 100, M1 230, M500");
    process ();
}

// -----------------
void loop (void)
{
}

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.