Closed 109JB closed 9 years ago
GrblPanel uses only the send, wait method at present. This works fine except for uses such as laser or engraving where there are a lot of small moves. Then the Queue doesn’t fill up as much if at all.
One of the only useful things I learned from my Unix days was: less is more.
I only remove white space. I do nothing else with the Gcode on the way out. If it is wrong, then Grbl tells me/the user. This avoids issues such as keeping the GUI in line with Grbl features and enhancements
I was planning on implementing canned cycles until I realized how complex they are. I found some tools on the web that will create drill cycles for me using G0/G1’s.
My suggestion is to watch the gcode passing through (you really only need to look t the first 2-3 characters for this) and do something to it only if you have an interest in that gcode. Everything else should pass through except maybe to strip blanks. String operations can be expensive esp if they do implied resizing.
For canned cycles you need to also watch for intermediate lines and then the line that cancels the cycle. Lots of state to keep track of in between.
Are you certain that you need to handle drill cycles? CamBam has a post for Grbl that spits out G0/G1 instead.
Gerrit
From: 109JB [mailto:notifications@github.com] Sent: Thursday, April 23, 2015 11:57 AM To: gerritv/Grbl-Panel Cc: Gerrit Subject: [Grbl-Panel] GRBL Panel questions (#27)
@gerritv https://github.com/gerritv , I have been working on my version of a GRBL interface, which you have seen on the grbl github pages. I have it running very well, and did a comparison of cycle time between mine and GRBL Panel. I consistently get slightly higher cycle times with my program vs GRBL-Panel and Universal G-code sender. The latter two are very close in cycle time. I am trying to figure it out and had a few questions for you since you seem pretty knowledgable in programming respects.
1 - is GRBL-Panel using a simple send/read response streaming protocol, or is it using a buffer fillinf character counting scheme as described in the grbl WIKI? Mine is just using a simple: send....wait for "ok"...send....wait for "ok"...send.... type protocol. I'm hoping you will tell me that you used character counting and that is why mine is slower, because that is something I can fix later.
2 - If the answer to 1 is that you are using the simple send/read response protocol, then I have something else going on. As you may recall, I am using Visual Basic 2005 because I'm targeting a windows 98 machine. Do you think that there would be a difference in speed of the resulting program using VB2005 vs VS2013?
3 - What operations are your performing on the g-code lines before sending? For example, are you parsing every line? Checking for g-code errors? etc...
I have my parser set up to do the following:
a: Read every line and separate into individual "words" (single letter followed by numbers) b; Sort and save the "words" into a string array for later use by things like canned cycles subroutine. This string array has a certain value for each array index. (ie: index 0 is for Motion group codes (G0, G1, G2....) c: Check the array index value for motion codes to see if the sent line is GRBL supported, and if so, put the line back together and send it to GRBL (the sent line is without spaces or comments). d: if the Array index value for motion modes is one supported by my GUI, then act on it. If not, then send a message to the user that an command not supported by GRBL or the GUI was found.
Thanks in advance,
John Brannen
— Reply to this email directly or view it on GitHub https://github.com/gerritv/Grbl-Panel/issues/27 . https://github.com/notifications/beacon/AH0pYumWoVlMyhEE_H6nrW2N3NM9cF-jks5oCQ3SgaJpZM4EHEfp.gif
@gerritv
Thanks for the response.
Since you are using the same type send/wait streaming that I am the performance difference has to be somewhere else. I am going to try the code in VS2013 just to see if that has anything to do with it. I doubt it, but it is easy enough to try.
I guess I am a little old school and still do a fair amount of hand programming, so having the canned cycles is pretty mandatory for me. I already have a few of the canned cycles operating in my program. G81, G82, G85, G86, and G89 are working at present. The rest are tapping and back
I also would like to be able to use cutter diameter compensation in the future with GRBL. That is a tall order though that requires a one-line look ahead as well as some pretty complicated geometry . I am going to make some mods to my code with an eye toward this in the future but that is a ways off.
As for simply watching the G-code passing, it really isn't that simple. Since the NIST standard says that a line of code can have line numbers or not, can have comments anywhere, and can have the words in any mashed up order, it really requires parsing in order to really catch everything. For example,
N1000 G90 G01 F10 X5 Y7 Z9 (This is a simple linear move) is functionally equivalent to Y7 F10 X5 G01 (This is a simple linear move) Z9 G90
Because of this, I wrote my parser to be fairly robust. It doesn't check everything though. Even so, I don't think the parser is my issue. I spent a lot of time making it as efficient as possible. I had written the parser code sing a temporary VB program to call it that did nothing more than open a file, and parse it line by line sending the result to a textbox. It would parse the 4500 line roadrunner code in a blink. I can test it in my GUI though. I can simply place a few lines of code in the front of the parser to take the incoming line to be parsed and just pass it back without any work done to it, basically bypassing the parsing routines. I'll do that this weekend and see how the cycle time changes.
Incidentally, the time difference between GRBL Panel and mine is about 10% based on that one roadrunner code file. I don't have a CAM program of my own right now ($$$$$), so I go over to a friends shop and use his when he isn't. I'll see if I can go over there and generate some dummy G-code programs to use to test things.
One option I have is to have the program parse through the entire file, saving the whole thing to a string array before actually sending anything to GRBL. I would prefer that it do it on the fly, but this is an option.
In reality, the cycle time difference I am seeing isn't a big deal from a hobbyist perspective. It is just the anal engineer in me that wants it to work as efficiently as possible. My program combined with GRBL actually still runs the roadrunner code significantly faster than my LinuxCNC installation, but I understand that the upcoming 2.7 release of LinuxCNC will perform much better. A gentleman that has the pre-release of 2.7 with the new trajectory planner ran a test and said that it is about where your program sits. Here are the numbers that I think are about right for cycle time for different applications running the roadrunner code:
GRBL Panel - 3:00 Universal G-code Sender - 3:00 My program - 3:20 LinuxCNC 2.6 - 5:35 LinuxCNC 2.7 - 3:10
Anyway, long post, but I'm excited about GBRL and its performance and hope to be running it for real instead of just test very soon.
Thanks Again,
John Brannen
All the extra array processing takes its toll. Esp if VB has to resize the arrays each time, gets longer and longer to do. Which is why I don’t do anything I don’t need to do. I read the gcode file into a ListView Item that is attached to the grid view object. I add a few private items to each line, e.g. a status item.
Re: As for simply watching the G-code passing, it really isn't that simple To find the G8x codes, search the line. E.g. data.Contains(“G81”) If nothing of interest then don’t do the extra work. No need to decipher the line and store it if nothing of interest. Of course once you hit a G8x, then each following line can be an incremental position until you get a Cancel canned cycle gcode. But at least for most gcode lines you are not munging a bunch of data and operations unnecessarily.
It is of course possible that VB has had performance improvements as well. Bit 10% seems a lot of difference.
BTW CamBam is very capable, only $149 (as a retiree even I can afford that). It also comes with a generous 40 times execution trial. If you don’t exit it each time you can do a LOT of testing on 40 runs.
Gerrit
From: 109JB [mailto:notifications@github.com] Sent: Friday, April 24, 2015 11:51 AM To: gerritv/Grbl-Panel Cc: Gerrit Subject: Re: [Grbl-Panel] GRBL Panel questions (#27)
@gerritv https://github.com/gerritv
Thanks for the response.
Since you are using the same type send/way streaming that I am the performance difference has to be somewhere else. I am going to try the code in VS2013 just to see if that has anything to do with it. I doubt it, but it is easy enough to try.
I guess I am a little old school and still do a fair amount of hand programming, so having the canned cycles is pretty mandatory for me. I already have a few of the canned cycles operating in my program. G81, G82, G85, G86, and G89 are working at present. The rest are tapping and back
I also would like to be able to use cutter diameter compensation in the future with GRBL. That is a tall order though that requires a one-line look ahead as well as some pretty complicated geometry . I am going to make some mods to my code with an eye toward this in the future but that is a ways off.
As for simply watching the G-code passing, it really isn't that simple. Since the NIST standard says that a line of code can have line numbers or not, can have comments anywhere, and can have the words in any mashed up order, it really requires parsing in order to really catch everything. For example,
N1000 G90 G01 F10 X5 Y7 Z9 (This is a simple linear move) is functionally equivalent to Y7 F10 X5 G01 (This is a simple linear move) Z9 G90
Because of this, I wrote my parser to be fairly robust. It doesn't check everything though. Even so, I don't think the parser is my issue. I spent a lot of time making it as efficient as possible. I had written the parser code sing a temporary VB program to call it that did nothing more than open a file, and parse it line by line sending the result to a textbox. It would parse the 4500 line roadrunner code in a blink. I can test it in my GUI though. I can simply place a few lines of code in the front of the parser to take the incoming line to be parsed and just pass it back without any work done to it, basically bypassing the parsing routines. I'll do that this weekend and see how the cycle time changes.
Incidentally, the time difference between GRBL Panel and mine is about 10% based on that one roadrunner code file. I don't have a CAM program of my own right now ($$$$$), so I go over to a friends shop and use his when he isn't. I'll see if I can go over there and generate some dummy G-code programs to use to test things.
One option I have is to have the program parse through the entire file, saving the whole thing to a string array before actually sending anything to GRBL. I would prefer that it do it on the fly, but this is an option.
In reality, the cycle time difference I am seeing isn't a big deal from a hobbyist perspective. It is just the anal engineer in me that wants it to work as efficiently as possible. My program combined with GRBL actually still runs the roadrunner code significantly faster than my LinuxCNC installation, but I understand that the upcoming 2.7 release of LinuxCNC will perform much better. A gentleman that has the pre-release of 2.7 with the new trajectory planner ran a test and said that it is about where your program sits. Here are the numbers that I think are about right for cycle time for different applications running the roadrunner code:
GRBL Panel - 3:00 Universal G-code Sender - 3:00 My program - 3:20 LinuxCNC 2.6 - 5:35 LinuxCNC 2.7 - 3:10
Anyway, long post, but I'm excited about GBRL and its performance and hope to be running it for real instead of just test very soon.
Thanks Again,
John Brannen
— Reply to this email directly or view it on GitHub https://github.com/gerritv/Grbl-Panel/issues/27#issuecomment-95974181 . https://github.com/notifications/beacon/AH0pYjmOm8tVxUbPBqcViw7JmWPQPAWdks5oCl3agaJpZM4EHEfp.gif
@gerritv I did a bit of testing and found that for my code it makes no difference if I am using VS2013, or VB2005. Kind of what I suspected since it is the same code. I suppose that if I coded in VS2013 I would have access to some functionality that is not available in VS2005 which could be more efficient.
I had home projects today, so didn't have time to do anything else on the program.
As for how to implement canned cycles... In order to implement canned cycles that conform to the NIST RS274ngc standard, it really isn't as simple as checking for a G8# code and then running the canned cycle from that line. The canned cycle needs to know a bunch of modal stuff that might not be on that line. Take the following completely valid code example:
N01 G90 G54 G20 G98 N02 G17 X5 Y5 Z-1 N03 G0 N04 F10 N05 G81 X3 Y7 Z-1 R0.1 N06 X6 N07 G80
In the above program, the G81 drilling cycle on line N05 needs to know G98 and G90, from line N01, Z-1 from line N02, and F10 from line N04. The reasons are as follows:
G90 - self explanatory G98 - this is the "use old Z" code and is needed to determine how to perform the retract moves within the canned cycle. Z-1 - The canned cycle needs this because it is the last Z position used with G98. It is also needed because in this case the Z position is below the retract plane so the first move of the canned cycle will be to move Z upward to get the tool height at least above the retract plane. This move would not be necessary if Z started above the R plane. F10 - I suppose in terms of GRBL the feedrate isn't really needed because GRBL will remember this modal value
The program then has to remember all of this for line N06 which is still a G81. Some of the things that are needed are not even things allowed or tracked in GRBL. G98 & G99 for example are not recognized by GRBL, nor should it since G98 & G99 are only for canned cycles. For RS274ngc though they are modal and would need to be kept track of if you want to do canned cycles that conform to RS274ngc. So, now the GUI has to do it.
In your example of not parsing each line and just checking for a G8# canned cycle, once you get to the G81 line and don't know all of the preceeding stuff then you would have to search backward in the program to determine them. Imagine that the G81 is on line 4000 and the only G98/G99 call occurs on line 1. You then are going backward line by line for 4000 lines to find it. Really the only way to do it is to keep track of at least the relevant modal values and the machine coordinates as the program progresses.
The only other option would be to require the necessary items on each canned program line, and if missing, throw an error, or assume a value. For example assume G99 is always active unless G98 is specifically read on the line. This would work but would not conform to the RS274ngc.
I chose to write my parser to track everything so that I can implement other things later on. I can however comment out lines to get to where I am only tracking what is absolutely necessary.
Thanks again.
Found the problem with my cycle times. I just had to separate out the run routine into its own thread and now I am right where your program is.
Interesting. I have the receive data coming in on its own thread. Bit of a nuisance getting data etc between the threads but is keeps the program responsive to user interaction.
Glad you slayed that dragon :-)
@gerritv , I have been working on my version of a GRBL interface, which you have seen on the grbl github pages. I have it running very well, and did a comparison of cycle time between mine and GRBL Panel. I consistently get slightly higher cycle times with my program vs GRBL-Panel and Universal G-code sender. The latter two are very close in cycle time. I am trying to figure it out and had a few questions for you since you seem pretty knowledgable in programming respects.
1 - is GRBL-Panel using a simple send/read response streaming protocol, or is it using a buffer fillinf character counting scheme as described in the grbl WIKI? Mine is just using a simple: send....wait for "ok"...send....wait for "ok"...send.... type protocol. I'm hoping you will tell me that you used character counting and that is why mine is slower, because that is something I can fix later.
2 - If the answer to 1 is that you are using the simple send/read response protocol, then I have something else going on. As you may recall, I am using Visual Basic 2005 because I'm targeting a windows 98 machine. Do you think that there would be a difference in speed of the resulting program using VB2005 vs VS2013?
3 - What operations are your performing on the g-code lines before sending? For example, are you parsing every line? Checking for g-code errors? etc...
I have my parser set up to do the following:
a: Read every line and separate into individual "words" (single letter followed by numbers) b; Sort and save the "words" into a string array for later use by things like canned cycles subroutine. This string array has a certain value for each array index. (ie: index 0 is for Motion group codes (G0, G1, G2....) c: Check the array index value for motion codes to see if the sent line is GRBL supported, and if so, put the line back together and send it to GRBL (the sent line is without spaces or comments). d: if the Array index value for motion modes is one supported by my GUI, then act on it. If not, then send a message to the user that an command not supported by GRBL or the GUI was found.
Thanks in advance,
John Brannen