Hi all,
i tried to find a way of searching the forum but unfortunately the only search I found was top right of web page which appears to search google not the forum, so if the question or similar has been asked before I apologise. A hint of how to search forum posts wouldn’t go amiss either.
Im looking for help parsing a serial string.
For those of you who know GRBL is code written by Sonny which will operate milling machines, routers etc
Grbl sends a data string back to the pc which looks like
<Idle|MPos:0.000,0.000,0.000|Bf:15,128|FS:0,1000|Ov:100,100,100|A:SF>
occasionally it outputs
<Idle|MPos:0.000,0.000,0.000|Bf:15,128|FS:0,1000|WCO:0.000,0.000,0.000>
Im wanting to parse the string using delimiters and store the results in an array which i can call back values from.
The data i’m interested in parsing is the spindle speed and the command acknowledgement.
FS:0,1000 is the feedrate and spindle speed (delimited by a comma) and A:SF is the indication that the coolant pump and spindle are running, where S represents the coolant/suds pump and F or C (snapshot was taken with spindle running in forward “F” - C being counterclockwise). I have worked through Robin2’s examples and zoomcat? but not been able to get exactly what i wanted. I have attached code which AWOL wrote which i can get to parse some of the data but it has 2 restrictions for me. The occasional change of string input from the serial port and secondly the code doesn’t use an array it just seems to dump data to serial port, I suspect because it is stepping through each character at a time.
The string length appears to stay the same length (apart from the occasional additional line which happens every fifth line for arguments sake).
I’m wanting to get the Spindle speed as an absolute minimum as i can read the grbl pins for The direction and coolant but it would be nice if i can get it all from the string.
For obvious reasons i cant go rewriting GRBL to provide the string in a more usable format.
//Input string example
//<Idle|MPos:0.000,0.000,0.000|Bf:15,128|FS:0,1000|Ov:100,100,100|A:SF>
//& occasionally
//<Idle|MPos:0.000,0.000,0.000|Bf:15,128|FS:0,1000|WCO:0.000,0.000,0.000>
//code from AWOL-
//[quote author=AWOL link=msg=2515146 date=1449735549]
const int MAX_LEN = 69;
const char lineEnding = '>'; // whatever marks the end of your input.
char inputSentence [MAX_LEN + 1];
int inputIndex;
bool newInput;
int spindleSpeed=0;
const byte MAX_TOKENS = 20;
const char* delimiters = "|,:"; // whatever characters delimit your input string
char* tokens [MAX_TOKENS + 1];
enum indexName {angle, fuel, speed, altitude,and1,and2,and3,and4,and5,and6,and7,and8,and9,and10,and11,and12,and13,and14,and15};
#define PRINT_ITEM(x) printItem (x, #x)
void setup ()
{
Serial.begin (115200);
}
void loop ()
{
while (Serial.available() )
{
char readChar = Serial.read ();
if (readChar == lineEnding)
{
newInput = true;
}
else
{
if (inputIndex < MAX_LEN)
{
inputSentence [inputIndex++] = readChar;
inputSentence [inputIndex] = '\0';
}
}
}
if (newInput && strlen (inputSentence))
{
int tokenIndex = 0;
//Serial.println (inputSentence); // tell 'em what you've got
tokens [tokenIndex] = strtok (inputSentence, delimiters);
while ((tokenIndex < MAX_TOKENS - 1) && tokens [tokenIndex])
{
tokenIndex++;
tokens [tokenIndex] = strtok (NULL, delimiters);
}
//PRINT_ITEM (angle);
//PRINT_ITEM (fuel);
//PRINT_ITEM (speed);
//PRINT_ITEM (altitude);
//PRINT_ITEM (and1);
//PRINT_ITEM (and2);
//PRINT_ITEM (and3);
//PRINT_ITEM (and4);
//PRINT_ITEM (and5);
//PRINT_ITEM (and6);
PRINT_ITEM (and7);
//PRINT_ITEM (and8);
//PRINT_ITEM (and9);
//PRINT_ITEM (and10);
//PRINT_ITEM (and11);
//PRINT_ITEM (and12);
//PRINT_ITEM (and13);
//PRINT_ITEM (and14);
//PRINT_ITEM (and15);
// reset things for the next lot.
newInput = false;
inputIndex = 0;
inputSentence [0] = '\0';
}
//Serial.println (spindleSpeed);
}
void printItem (int index, char* name)
{
// Serial.print (name);
Serial.print (F(" "));
Serial.println (tokens [index]);
}
PRINT_ITEM (and13) is the position of the A:SF command, but it disappears when the occasional data string is sent and returns A: when no commands are sent ie, coolant and spindle are off.
As you can appreciate im more mechanical than a programmer, i’m one of those cut and paste coders but i can do just about everything else from space to underwater so please be kind at my attempts of programming - especially you PaulS.
My ideas going forward are to read the entire string into a buffer based on the <> delimiters and then somehow split the string using first the “|” delimiter and then “,”. Using a switch/case statement to then look in the array at [13] and see if the ascii character are there if its decimal 0 then its the odd string and i can ignore acting upon it. If the command characters are awkward to split out then i will use hardware pins instead for direction and coolant.
The hardware setup is a pc connected to an arduino running grbl which operates a CNC machine. A second arduino (remote) is used to sniff data from the first arduinos (GRBL) TX pin. This works fantastically well - Trust me. and does not interfere with the PC-GRBL link or operation. There are many soothsayers here who cringe when you mention sniffing RX/TX lines. We used to do it all the time when computers were operated using DOS and still used magnetic tape as storage medium, for all the millennial’s that’s how the old boys checked for data on serial busses. Its still a valid tool.
Any help or direction would be very much appreciated
The end goal is to use the second arduino to send the Spindle and command data over an RS485 communication link (Re Nick gammon) to yet another arduino which will be connected to a variable frequency drive which drives a 3 phase spindle motor on my milling machine. The RS485 link is required as the VFD upsets the signals from grbl due to high frequency noise on the signal path. - Its a shame not to get grbl running my spindle as well as my CNC milling machine.