Make use of variables
-
I've put a draft proposal at https://docs.google.com/document/d/1urmNjfs2QXUZ2aFeWu6LOaj78cyfNeYZ0ofMJoQsZVk/edit?usp=sharing. It's lacking some detail, in particular the object model, but it should be sufficient to use as a basis for discussion.
-
@dc42 I personally would already been happy with just variables. Anyway very good proposal.
Only I found one thing missing. At the requirements you state that variables need to be type-safe but in their declaration the type is only inferred from the value (at least nothing is stated). It might be safer to have the declaration include the type. But I know that these makes it more complicated and inconvenient.
-
@dc42 I haven't had time to properly review your proposal yet - will do over the weekend. First of all: Wooooohooo, you are the most responsive dev I have met so far. Big up for your effort!!!! And in contrast to (an-)other dev of hard- & firmware, you are super friendly and quick at solving customer needs! I feel like I found the right place to base my printer kit on!
At first sight, I would kind of stick to the Gcode-everywhere paradigm, when it come to the simplest of all - setting and reading a variable. But as I can't read your mind but suspect that the RRF object model you have in mind is separate from the Gcode processor (or for any number of another reasons), the var approach seems to be unnecessarily stray from your paradigm.
Maybe M123 Kkeyname Vvalue is a better approach? Where KeyName could be retrieved by just adding a designator like @ or $?
Also, M123 could be extend by the data-type such as M123 KmyInt V3.1412 Dfloat would be reflected?On another page, but related: In terms of usability of a specific product (like the e3d tool-changing printer), it would be tremendeously helpful to be able to read the current setting of commands like M558, M584 and the like by issueing a M558 A? (and get the value of A back) or M558? to get the values of all parameters back (either as string or as a named array - preference for the latter of course )
One major use-case is the way you could set your z-probe offset with G31 Z$measuredZmean
The way I do it now is by running @Phaedrux script he provided here but with the above suggestion, there would be no need to read the mean value in the console - just get the mean value, store the value by M123 KtriggerHeight VmeasuredZmean and set triggerHeight value by G31 Z$measuredZmean
Except for the paper-trick, no further manual action would be required....Or think about how endstops could be used (again for tool-changing) if I had a simple microswitch, I could retrieve the state of and them take according action - like if T1 parked or is a tool loaded.
-
@googliola, thanks for responding.
At first sight, I would kind of stick to the Gcode-everywhere paradigm, when it come to the simplest of all - setting and reading a variable. But as I can't read your mind but suspect that the RRF object model you have in mind is separate from the Gcode processor (or for any number of another reasons), the var approach seems to be unnecessarily stray from your paradigm.
The object model is just a way of referring to all the machine parameters, so it's more or less independent of the syntax of the additional commands in my proposal.
Maybe M123 Kkeyname Vvalue is a better approach? Where KeyName could be retrieved by just adding a designator like @ or $?
Also, M123 could be extend by the data-type such as M123 KmyInt V3.1412 Dfloat would be reflected?One concern is readability. GCode isn't very readable because you need to remember what each code does. So for things like loops, conditional blocks etc. I think it makes more sense to use keywords. The question then arises, should we also use keywords for things like setting variables, for which there isn't an existing GCode command?
On another page, but related: In terms of usability of a specific product (like the e3d tool-changing printer), it would be tremendeously helpful to be able to read the current setting of commands like M558, M584 and the like by issueing a M558 A? (and get the value of A back) or M558? to get the values of all parameters back (either as string or as a named array - preference for the latter of course )
That will be possible, because all configuration variables will be included in the object model.
One major use-case is the way you could set your z-probe offset with G31 Z$measuredZmean
The way I do it now is by running @Phaedrux script he provided here but with the above suggestion, there would be no need to read the mean value in the console - just get the mean value, store the value by M123 KtriggerHeight VmeasuredZmean and set triggerHeight value by G31 Z$measuredZmeanYes, that or something similar will be possible.
-
That will be possible, because all configuration variables will be included in the object model
@dc42 how would you refer to the (M558) A param value in that case?
- M558. A
or - parentObject.[otherObject].value
While the first is self-explanatory, the other might adhere to the OM, but would complicate things for the user and documentation (but maybe much easier to develop??)
I think using a Gcode is more user-friendly overall.
Again, I don't know much about the consequences in terms of the code or the HW restrictions (cpu, ram, performance etc.) - M558. A
-
@dc42 I would say most of industry is accustomed to Fanuc Custom Macro B and might be a good standard to follow if you are looking for industry support.
Sometimes its a bit convoluted to do loops or proper if statements but it works. Something I use in my programs to calculate a loop variable based on a hole diameter is below
IF[#510NE#4115]THEN#3000=1(LOAD WORKSHIFTS) - #3000=1 is program ending alarm
IF[#504EQ0]GOTO7 - Will skip ahead in program to line N7
IF[#507EQ0]GOTO7
#100=.5
#101=.45
IF[#500GE#100]THEN#3000=1(ORDER HOLE TOO LARGE)
IF[#500GT.35]THEN#101=[#500+.1]
#102=#100-#101
#103=FIX[#102/.012](NUMBER OF PASSES ROUNDED DOWN)
#104=[#102MOD2](EVEN-ODD TEST)
IF[#104EQ0]THEN#105=#103+2(EVEN PASS)
IF[#104NE0]THEN#105=#103+1(ODD PASS)
#106=[#102/#105](NEW DEPTH OF CUT)
#105=#105/2(DOUBLE PASS SPLIT)and then the while loop that uses it
#107=0
WHILE[#107LT#105]DO1
G1 U-[#106] F6.
Z-1.0
U-[#106] F1.
Z.0625 F6.
#107=#107+1
END1#100-#199 variables are called common and are typically cleared at program end/reset, this can be changed on some machines by changing a parameter in the control
#500-#999 are maintained between programs and power cycles
#1000 and above are typically machine variables that can be read (and sometimes modified) but these are defined in the Fanuc Operation and Maintenance handbook for the control. On Fanuc 16i/18i/21i (and possibly more) #5021-#5028 will give you the machine coordinate for the respective axis (X, Y, Z, etc...) while #5041-#5048 will give you the workpiece coordinate for the respective axis. In the above sample #4115 is the currently loaded program number.
This is a good reference for Fanuc Custom Macro B that I use at work, it also goes pretty deep into bitwise operations available on Fanuc.
-
@googliola said in Make use of variables:
@dc42 how would you refer to the (M558) A param value in that case?
Something like: machine.zprobe.maxattempts
-
In regards to the proposal...
There are currently several different "standards" for gcodes, but they are (for the most part) compatible with each other. I can usually take a basic gcode file that prints a cube and run it on any printer's firmware (or firmware specific preprocessor such as the case of sailfish) that supports gcode. 95% of the time, that gcode file will run fine. Even if a particular flavor of gcode doesn't support a specific command, it will usually recognize that it's not supported, spit out a warning, and continue.
This proposal isn't a case of adding some M commands that are specific to RRF (but could be safely ignored by other processors.) This proposal is a fundamental change in the gcode "language" while trying to still call it gcode. For example, I believe that gcode defines the "G1" command as one single linear movement (potentially in more than one axis.) With this proposal, however, that G1 command might be inside a loop (that only RRF understands) and really means to make one movement 2 times, 10 times, or a hundred times.
To add to the issue, there's no gcode command (that I know of) that could tell a gcode processor "don't run this file as it can't be compatible with you." I suppose you could have a header that includes a "M0" command wrapped with an always false conditional similar to:
if 1 = 0
M0
end ifIf a gcode processor ignores any line it doesn't understand, it would only process the "M0" and stop. (Assuming it supports M0 to begin with. Not all gcode processors do.)
Anyway, to get to the point, I'd suggest NOT making changes to gcode that actually change the language. If you want to write a new language, then write a new language. Not only would this prevent compatibility issues (by assuring incompatibility) but would also free you from any constraints of trying to be gcode compatible when it clearly can't be.
-
I anticipate that the new features would be used almost exclusively in macro files that are used only on printers running RepRapFirmware.
-
@dc42 said in Make use of variables:
I anticipate that the new features would be used almost exclusively in macro files that are used only on printers running RepRapFirmware.
Then perhaps call it something else (RRF-Code or Duet-Code) with a different file extension and only allow it in macros. I realize that you have a certain expectation of competence of your users, but there's a large potential for something to go wrong when these machines are being used for laser cutters, CNC, etc
-
@dc42 From a user perspective, the terminology would cause confusion and additional and maintained documentation , but then the question is how much you weigh user-friendliness.
If I were in your shoes, I would probably stick to ease and coherence with known / documented guidelines. You might open Pandora box here. People might argue that common (Fanuc) standards are 'better'. Comes down to taste at the end of the day really... -
I really like your proposal, dc42.
I have only one immediate use-case that I would want to employ: check current z height, and raise then lower bed to switch IDEX tools and avoid obstacles near the bed perimeter, if current z height is insufficient to clear said obstacles. This would have to be located in the actual print gcode files, in the tool switching script.
I don't see any problem with doing this, based on your proposal, but just wanted to mention a use-case that would have the script inside a gcode file for printing.
edit: Upon further reflection, these commands could be contained in the firmware-based macro tool change scripts. I was thinking of a case of using slicer based tool change scripts, but that would not be necessary. Ignore my stated use case of scripts in a printable gcode file.
-
@dc42 Haven't had much time lately to follow up on my feature request. With holidays ahead, this will change soon
Just been wondering how the object model is coming along and if you could make a statement about when / what version it will be implemented.
Thanks in advance -
@googliola said in Make use of variables:
@dc42 Haven't had much time lately to follow up on my feature request. With holidays ahead, this will change soon
Just been wondering how the object model is coming along and if you could make a statement about when / what version it will be implemented.
Thanks in advanceA small amount of the object model is supported in firmware 2.02RC5 along with variable substitution, as a proof of concept. The full implementation is planned for release 2.03.
-
@garyd9 said in Make use of variables:
@dc42 said in Make use of variables:
I anticipate that the new features would be used almost exclusively in macro files that are used only on printers running RepRapFirmware.
Then perhaps call it something else (RRF-Code or Duet-Code) with a different file extension and only allow it in macros. I realize that you have a certain expectation of competence of your users, but there's a large potential for something to go wrong when these machines are being used for laser cutters, CNC, etc
Didn't follow this thread before... I agree with @garyd9: as no slicer will generate such custom G-Code, if the goal is to use it from macros, I suggest to write a macro language, like Slic3r does, evaluated by the macro pre-processor, and keep a standard G-Code.
-
The additional facilities will be provided by way of additional (not replacement) syntax and will not affect the ability of RRF to run GCode produced by slicers.
-
Yes, I understand, but this means that it will be possible to use this syntax from Slicers (using custom code), which is, IMO, more dangerous than from macros only...
-
Maybe another thing to think about is having the possibility to give params to macros...
-
@fma said in Make use of variables:
Maybe another thing to think about is having the possibility to give params to macros...
Yes, I will probably include that.
-
Glad I found this topic! Sorry for dragging up an old topic but I don't see any other information on the wiki about this.
I'm looking for variable support as well. An example of an immediate want (notice I didn't say need lol) is the ability to call a macro with hotend first layer temperature and bed temperature parameters.
My Cartesian machines all will set initial hotend temp to 160° while bed heats up, then do a mesh bed leveling and finally heating up the nozzle to print temp just outside the print area and doing a purge line before it begins the print.
Yes I know that I can put this in Slic3r custom gcode for print start, but then I have to manage it for each printer I'd love to take advantage of just putting the macro call in the custom gcode section.