Home › Forums › TinyG › TinyG Support › Controlling TinyG programmatically: Best practices?
- This topic has 11 replies, 4 voices, and was last updated 11 years, 2 months ago by alden.
-
AuthorPosts
-
October 3, 2013 at 1:34 pm #4689JuKuMember
I’m developing a system where I’m controlling TinyG from my own program. My approach is to interpret the responses or TinyG messages and update my program internal status accordingly. The operation goes by looking at the current status, figure out what to do next and send another command. Sounds good and works to an extent, but I’m running to problems, as there doesn’t seem to be a universal way to tell that previous command processing has ended.
How do you handle this? Separate routines for each command (complex, duplicate code snippets etc)? Delays (slow)? some other approach to start with?
(Or how difficult would it be to add a universal idle state indicator?)
October 5, 2013 at 11:13 am #4701MakerboostMemberI think I read somewhere on this forum that the TinyG doesn’t always give a response back.
I’d be interested in knowing this too actually.
October 5, 2013 at 3:30 pm #4704aldenMemberWhat problems are you running into?
Every command is responded to in the JSON mode ‘r’ response. The footer contains the status code of the executed commands. Perhaps what you are referring to is that the system queues motion and other synchronous commands for execution in sequence. To see the completion of queued commands you need to use the status reports.
Best practice is to use the JSON commands, use the footer to tell the results of the command, and set up a filtered status report with all the state variables you want to track for queued commands. See the JSON and Status Report guidance on the wiki. The ‘stat’ variable is the universal idle state indicator. See those pages for guidance.
The other thing to be aware of is that it’s better to manage flow control at the planner buffer level than at the serial buffer level. In other words, instead of stuffing the serial buffer until it’s full, keep the planner buffers operating between a low and high level. Use Queue Reports to return the planner buffer level. If you are sending a file the planner should have at least 8 or 10 buffers in the queue to avoid motion starvation, and use no more than 24 of the 28 buffers available in the planner queue. Over 24 the serial buffer starts to back up. Things still work, but now you are queueing in the serial buffer. (FYI: 4 buffers are reserved for the next Gcode block, which may occupy as many as 4 planner buffers)
@Makerboost: All commands are responded to; perhaps what you are remembering is that status reports are not delivered faster than the maximum rate, so some state may be skipped (like position updates).Status reports will always deliver completion status, however. The main way to find completion status is track the “stat” variable.
- This reply was modified 11 years, 2 months ago by alden.
October 5, 2013 at 5:34 pm #4706MakerboostMemberThank you for the clearification and the helpful tips!
October 7, 2013 at 10:28 am #4716JuKuMember>What problems are you running into?
I find very difficult to figure out when TinyG has sent all the infromation it has to send. I’d like to find a non-leaking way to patiently wait until I have all the information there is to come, but not lock up waiting for something that is not coming.
Keeping track of the buffers does not work, in some cases (homing at least) it reports 28 buffers and then does the operation. Not all status reports include the stat, and stat:3 is not always the last status report sent.
But your tips have alrady been helpful, my communication routine is already simpler and better. Maybe homing and zero movement commands are indeed the only exeptions to the stat:3 rule? If so, I think I can build workarounds.
October 8, 2013 at 5:33 am #4717JuKuMemberAnswering my own question to share my experiences during last two days: As said, the goal is to recognize TinyG idle state, where all status variables are up to date and the machine state or position will not change anymore. The following logic seems to work for my application:
In the controlling software:
– Filter movement commands beforehand, so that commands that don’t result in movement, are not sent to TinyG.
-Home one axis at a time.In the TinyG interface setion, my communication is set up so that only full lines get processed. The line iterpretation routine logic is:
-If homing for axis q (where q is x, y or z; I don’t have homing on other axis), wait for a line that has both “mpoq”:0.000 and “coor”:2 => handle it as a status report (update all status variables), fire ready event and return.
-If line starts with {“sr”: => handle it as a status report. If it also contains “stat”:3 , fire ready event. Return.
-If line starts with {“r”:{“sr” , it is the response for asking a status report => Remove the wrapper, handle line as a status report, fire ready event and return
-If line starts with {“r”: , it is a response for asking or setting a setting or setting group => replace all “n” (where n = 1, 2, 3 or 4) with “motor_n” to get valid field names for Microsoft JavaScriptSerializer class (and other JSON interpretes, I suppose). Handle line as a settings report (updating UI where applicable etc), fire ready event and return.
—
The issues that caused some thinking were ‘no movement’ commands (that send out an empty status report) and a bug(?) in homing routine: On X axis homing, the stat:3 report comes the second to last status report, not the last. Firmware is 392.65, btw.October 8, 2013 at 9:10 am #4718aldenMemberOK, I’m going to look into this a bit more. I need to see what you are getting back from the end of homing. I also want to see what behavior should occur if a non-drawable line is received. It should return a value, but I need to look into this.
Also be aware that the status code (see Status Codes page on the wiki) is returned in the footer for all ‘r’esponses. It’s the second element of the array.
https://github.com/synthetos/TinyG/wiki/TinyG-Status-Codes
FYI, here is a diagram of the TinyG state model. The picture may be a bit dated and need updating, but the enumerations below are the current settings taken from the canonical_machine.h file. Be aware that the “program stop” and “program end” states are Gcode defined intermediate and end states triggered by the STOP and END M commands (and some other cases for stops)
October 8, 2013 at 3:27 pm #4722JuKuMember> I need to see what you are getting back from the end of homing.
When I started to collect data for a response, I found that the bug has to do with zero backoff. Here is a log, with some comments added:
{"xzb":0} // <======= Zero backoff to 0 {"r":{"xzb":0.000},"f":[1,0,10,2510]} g28.2 x0 {"r":{},"f":[1,0,9,4402]} {"sr":{"coor":0,"dist":1,"home":0,"cycs":3}} {"qr":28} {"qr":27} {"sr":{"mpox":-2.895,"stat":9,"momo":1,"macs":5,"mots":1}} {"sr":{"mpox":-8.465,"hold":3,"mots":2}} {"sr":{"mpox":-9.385,"hold":4}} {"qr":27} {"sr":{"mpox":-6.638,"hold":0,"mots":1}} {"sr":{"mpox":-0.929,"hold":3,"mots":2}} {"sr":{"mpox":-0.109,"hold":4}} {"sr":{"mpox":0.000,"stat":3,"coor":2,"momo":4,"dist":0,"home":1,"hold":0,"macs":3,"cycs":0,"mots":0}} {"qr":28} // <=== Homing ended cleanly with "stat":3 and "all buffers free" {"xzb":2} // <=== Setting zero backoff to != 0 {"r":{"xzb":2.000},"f":[1,0,10,5205]} g28.2 x0 {"r":{},"f":[1,0,9,4402]} {"sr":{"coor":0,"dist":1,"home":0,"cycs":3}} {"qr":28} {"qr":27} {"sr":{"mpox":-2.747,"stat":9,"momo":1,"macs":5,"mots":1}} {"sr":{"mpox":-8.415,"hold":3,"mots":2}} {"sr":{"mpox":-9.235,"hold":4}} {"qr":27} {"sr":{"mpox":-6.340,"hold":0,"mots":1}} {"sr":{"mpox":-0.779,"hold":3,"mots":2}} {"sr":{"mpox":0.041,"hold":4}} {"qr":27} {"sr":{"mpox":1.778,"hold":0,"mots":1}} {"sr":{"mpox":2.041,"stat":3,"macs":3,"mots":0}} <=== and the "stat":3 comes one message early. A bug? {"qr":28} {"sr":{"mpox":0.000,"coor":2,"momo":4,"dist":0,"home":1,"cycs":0}} {"qr":28}
> I also want to see what behavior should occur if a non-drawable line is received.
Another log:
g0 x1 {"r":{},"f":[1,0,6,4399]} {"sr":{"mpox":0.001,"stat":5,"macs":5,"cycs":1,"mots":1}} {"qr":27} {"sr":{"mpox":0.998}} {"sr":{"mpox":1.000,"stat":3,"macs":3,"cycs":0,"mots":0}} {"qr":28} g0 x1 {"r":{},"f":[1,0,5,4398]}
Here, it would be cleaner if there would have been a response {“sr”:{“mpox”:1.000,”stat”:3, … even though the second g0 x1 is an empty command in real life.
Please note, that the bug (if it is a bug; I have misunderstood things earlier! 🙂 ) or the missing status report are no problems at all. The logic above seems to work by today’s experiments, my code works just fine. And now when the behaviour is on the forum, others will not lock their code for waiting for “stat”:3 that will never come or have their machine one location message off after homing either. 🙂
- This reply was modified 11 years, 2 months ago by JuKu.
October 8, 2013 at 3:51 pm #4724aldenMemberThanks for the details. I’d rather have the responses work “cleanly”. I’m not yet prepared to comment on this until I have a closer look at what’s going on in the system internals. I appreciate your capturing this info.
October 10, 2013 at 8:09 pm #4736RileyKeymasterJuku,
It sounds like you are running a single thread to do your serial communications? Is this so? How tgFX works is there is a serial writer thread and a responseparser thread. While multithreaded applications complicate code a bit, its really the way to do what you are trying to do.
Riley
October 11, 2013 at 10:13 am #4745JuKuMemberYes, I do multithread also. 🙂 But I am also doing optical alignment, and for that to work, I need to be sure the machine is not moving and the position information is updated before taking a look.
October 13, 2013 at 11:56 am #4765aldenMember@Juku – To address your issue about status being returned during homing I have changed the way the firmware sets the stat value in dev build 394.23. From this point on it has a slightly different behavior.
At the start of homing stat will change to 9 (homing cycle). at the end it will change back to 3 (stopped) No other status will be provided, as they are not changing. This should not affect stat returns anywhere else in the code.
-
AuthorPosts
- You must be logged in to reply to this topic.