Echo commands...
-
@nightowl999 said in Echo commands...:
I think I'll incorporate something like the M291 command, but is there a way to do something other than (essentially) just Resume or Cancel? A simple example would to prompt the user to move to a specific point (defined in a "startpoint.g" file, let's say) after initial homing has completed?
If you use M98 P"some_optional_code.g" to invoke a file, the code in that file can be executed or not by using a M291 with S3.
If you select CANCEL the rest of the code in that file, after the M291, will not be executed.
If you select OK the rest of the code in the file will be executed.
In either case execution will then continue after the M98 P"some_optional_code.g".
Frederick
-
@Nightowl999, as @fcwilt, says, the m291 is the only input method you can use, but RRF continues to expand, so additional options may show up in the future. With OK and cancel, it is possible to capture which answer the user gave. I wrote a little macro named "OK_CANCEL_checker.g" that can be called with
M98 P"<dir>/OK_Cancel_checker.g" S"Select OK for <option 1> and Cancel for <option 2>"
The S parameter is for the message you want displayed in the message box. When you want user input, call the macro. After the user answers and execution returns to the main macro, the value of a global variable is either "CANCEL" or "OK". You code can then branch based on the value.
Here's the full macro
; Macro to be called from other macros to let user select one of two options (OK and Cancel) ; PARAMETERS ; S = Message to be displayed ; R = any value. If included in parameter list, will return a random choice of OK or CANCEL without user interaction. ; used for debug of calling programs. ; RETURN ; Global.OK_CANCEL is set to "OK" or "CANCEL" ; USAGE ; if !exists(global.OK_CANCEL) global OK_CANCEL = "NO MESSAGE" else set global.OK_CANCEL = "NO MESSAGE" ;Check for parameters if !exists(param.S) ; see if a parameter was provided M291 P"Message parameter not provided. " S0 T5 ; S0 means no buttons, t5 means wait 5 seconds and move on. M99 if exists(param.R) ; see if a random response is requested instead of user action set global.OK_CANCEL = "OK" if random(100) > 50 set global.OK_CANCEL = "CANCEL" M99 ; return without asking for user interaction. set global.OK_CANCEL = "CANCEL" M291 P{param.S} S3 T-1 set global.OK_CANCEL = "OK" M99
-
Nice idea.
A boolean variable would be a bit easier for the calling code to check the result.
Frederick
-
This is great, thank you @mikeabuilder.
Not only does it help me, but it gives an insight into how code works.
Is there a guide or tutorial somewhere, where I can start to learn this stuff for myself, please? I appreciate there is guidance with some examples of gcode and meta commands on the Duet pages, but I'm hoping to learn more.
I used to program with Microsoft Visual Basic for Applications many years ago, but I imagine the language is quite different now.
-
@nightowl999 said in Echo commands...:
Is there a guide or tutorial somewhere, where I can start to learn this stuff for myself, please? I appreciate there is guidance with some examples of gcode and meta commands on the Duet pages, but I'm hoping to learn more.
I use quite a few code files beyond the common ones. Here is a set from one of my printers:
Feel free to ask any questions you may have about the "programming" features of the Duet firmware - version 3.4.x plus BtnCmd 0.10.09 can do some rather amazing things compared to the Duet firmware 2.x I started with a few years back.
Frederick
-
@fcwilt - I did start with a boolean variable, but the first time I used it I had to look to remember if "OK" was true of false. The second time I looked it up, I switched it to "OK" and "CANCEL" so I would not need to look it up again.
@Nightowl999 - The programming capability these folks are building into RRF (and I believe it if these few folks) is a relatively new capability and is very simplified. You will not find anything as fancy as what you learned in VB. It was primarily developed to support the "gcode everywhere" philosophy. Additional features may be added, but I would not expect a full-blown programming language.
Having said that, the meta command page in the wiki (https://docs.duet3d.com/en/User_manual/Reference/Gcode_meta_commands) really does describe all the capabilities. Beyond that, it's clever folks building macros. But here's my nuggets of RRF gcode programming wisdom.
- You use G codes and M codes in your macros to "send" things to the machine.
- You use the object model (https://github.com/Duet3D/RepRapFirmware/wiki/Object-Model-Documentation) to read things from the machine that you might use a G or M code in the console to see in the user interface. You can "never" set a value to a variable by setting it equal to am M or G code.
- Understanding what is and is not a "code block" is important because a variable created inside a code block is only available to itself and it sub-blocks (child blocks) not it's parent. Return to this when you get an error saying a variable does not exist when you know darn well you created it.
- It seems easiest to just make everything a global variable, but these take up memory space and are never deleted, except a power on or reset. So you can clog up the memory with too many. Best to use local variable wherever you can. Those are destroyed and the memory freed up for other uses as soon as the code block where they were created is finished being run.
- Carefully read and practice the echo, particular the echo >filename and echo >>filename. These are your ticket to having your macro write something to a file that you can read later.
- So far, there is not command for reading a file, making arrays, parsing strings, or collecting generalized user input. In my opinion, these things are slippery slopes to a mountain of work for the developers and they have been wise in approaching them with extreme caution.
-
So far, there is no command for reading a file
In a sense, there is: you can execute the file as a macro. This includes the ability to establish or modify global variables, to execute GCodes with parameters having been calculated at file creation time, to inspect the object model, and to run conditional code.
At least, this gives us the ability to store data, instructions and conditions - and to handle them when we "read" the file (calling it as a macro). This is different from the common idea of keeping data and code distant, but apart from string handling and a user interface in excess of M117 and M291, we have all the tools to control our machine by means of writing and reading states and conditions. Think different
-
@mikeabuilder said in Echo commands...:
@fcwilt - I did start with a boolean variable, but the first time I used it I had to look to remember if "OK" was true of false. The second time I looked it up, I switched it to "OK" and "CANCEL" so I would not need to look it up again.
Good to know.
But for the record OK is always True and CANCEL is always False.
I notice you check for the missing message parameter. Any reason you did not simply abort if missing?
Frederick
-
@fcwilt
I'm thinking I might configure a 'working' page specifically for CNC users with @MintyTrebor's BtnCmd add-in, but I need to get my head around what I need to see before I do that.Unlike you 3D printer guys, I really don't have an interest in temperatures, hot ends, fans, beds, heaters, etc., just a few progress indicators, pause, resume, stop and PANIC!! buttons, is all
-
One thought. In VBA you can hover the mouse icon over a declared variable and it will show it's value in a ToolTip. I'm not asking for that here (I don't think this system is complex enough to warrant that) but is there a way of finding the value of a variable in the code sender, or is it only in the Object Model (if at all)?
-
@infiniteloop - regarding writing a file that contains gcode that will put values into variables when it is executed. That's brilliant! Love it. The user (me) will need to be careful about managing global and local variables so as to not use up all the memory. I'm already envisioning an array.g for simple arrays.
@fcwilt - true (or should I say "OK") about OK always being true, but that's another thing to remember and my brain is nearly filled to capacity. I pop up a user message if there is no message parameter supplied just to help me during debug - but it is redundant with returning "NO MESSAGE" in the global variable.
-
@mikeabuilder said in Echo commands...:
The user (me) will need to be careful about managing global and local variables so as to not use up all the memory.
Well, in some cases macros can replace a global variable completely. That's not true for state and conditional checks during runtime, but why not put some parameter for a Gcode into a macro - together with the Gcode? As additional benefit, these "data" survive loss of power (and earthquakes as well).
-
@mikeabuilder said in Echo commands...:
@fcwilt - true (or should I say "OK") about OK always being true, but that's another thing to remember and my brain is nearly filled to capacity. I pop up a user message if there is no message parameter supplied just to help me during debug - but it is redundant with returning "NO MESSAGE" in the global variable.
I check for parameters as well and I do two things:
- use M291 to display the message dialog explaining the problem
- use abort to end execution and display the same message.
Even if aaa.g invokes bbb.g which invokes ccc.g, if ccc.g executes an abort that ends it right there and execution does not continue in bbb.g or aaa.g.
So "bad" things won't happen if I mess up passing a parameter.
Frederick
-
@fcwilt - thanks for pointing out the abort command. I was unaware. It's a great capability. I'll need to think if I always want to abort the whole shebang if a message is missing or I might add it as an optional parameter so the user can choose to abort or proceed if there is no message supplied.
I feel I'm standing on the edge of the slippery slope. A whole programming language could be built here...