Duet3D Logo Duet3D
    • Tags
    • Documentation
    • Order
    • Register
    • Login

    Make use of variables

    Scheduled Pinned Locked Moved
    Firmware wishlist
    14
    40
    6.6k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • dc42undefined
      dc42 administrators
      last edited by

      IMO it's better to define the bed centre as X=0 Y=0 no matter what type of printer you have. That's what I do on my Cartesian, Delta and SCARA printers. It is one of the things that allows me to print the same GCode files on all of them.

      Duet WiFi hardware designer and firmware engineer
      Please do not ask me for Duet support via PM or email, use the forum
      http://www.escher3d.com, https://miscsolutions.wordpress.com

      1 Reply Last reply Reply Quote 3
      • Googliolaundefined
        Googliola
        last edited by Googliola

        @phaedrux said in Make use of variables:

        There are some examples of config file sets that put a lot of work into parameterizing the whole thing, making system state switches by calling macros. This can be tedious to troubleshoot as you have to chase down the issues between macros to see how the system state is being altered through each step of the way. But it does allow for keeping sets of configuration variables in one place to edit, and then apply everywhere the macro is called.
        Having $variables defined in one place would let macros become a lot more readable and you could refer back to the single variable definition file to see what is what. Currently the state of a gcode is always explicitly defined when it's called.

        That's one reason to have variables. Less effort, more control over system state (as it is defined in one place). and better readability.

        I'd be curious to see if people would find that more difficult or less difficult than it is now. And beyond the initial setup of the machine, you're not really editing those variables very often.

        Well, having many parametrised macros is certainly quite messy the bigger the number. And if someone does not like to use variables then they could still use the existing approach.

        A facility to make this possible is already planned!

        @dc42 can't wait to use it. Bedcenter is just an example, where it variables would be helpful. Running a z-probe repeatabilty test would be much easier to implement too. Let's assume I want to repeat the test in other places than bedcenter (to spot a mechanical issue). Again, I would need to create yet another macro to set the location of the probing to take place. With vars, one could

        ; StartProbeLocationMacro.g:
        Set probing location coords $X $Y at bedcenter
        Run repeatProbe.g and record results in log file
        Set probing location coords $X $Y at front left
        Run repeatProbe.g
        Set probing location coords $X $Y at front right 
        ......
        Reset probing location to default state $defaultBedCenterX $defaultBedCenterY
        
        ; StartProbeSpeedMacro.g:
        Set probing feedrate, speed, height
        Run repeatProbe.g
        Change probing parameter
        Run repeatProbe.g
        ....
        Reset probing params to default state
        

        This does seem like something that is more useful for a machine that is in development

        @SupraGuy Absolutely. Either to setup and fine tune the configuration during development, but also to perform quality control upon setup of a new machine or to run maintenance tests.

        As for the changes in the slicer as you pointed out:

        G1 BED_X_CENTRE BED_Y_CENTRE 5.0
        M280 PBL_TOUCH_PIN I1 S10

        Hmmm, true. I don't see a use case for that - yet. Both lines are likely to bo into the start or end code scripts. Plus, that could just as well be done with macros containing the variables. But then how can you instruct your slicer to run a macro (apart from onstart, onlayerchange etc events)

        As for the #define statements, I think the "gcode everywhere" approach is a MUCH better fit, due to adherence to coding standards and coherence.

        I think it is important to point out that the value of the variables can be altered by
        Mxx0 Kkeyname VNewValue

        Thanks everyone for your input!

        1 Reply Last reply Reply Quote 2
        • Phaedruxundefined
          Phaedrux Moderator
          last edited by

          @Googliola Check this out. I think it will deliver very close to what you're after.

          https://github.com/token47/duetcfgen created by @token47

          To quote:

          duetcfgen
          Duet Config Generator

          What this is NOT:

          • attempt to negate the RRF "All Gcode" filosophy
          • an attempt to create a Configuration.h (a la Marlin) for RRF

          What this IS:

          • a way to quickly edit all the files on the same place
          • a way to use variables for repetitive information
          • a way to use "vim" on my linux instead of the web editor

          It will:

          • compile a template, generating all the individual files
          • do variable replacement while compiling
          • upload all of them to the duet using ftp
          • optionally will reset the duet after uploading
          • can potentially download a backup of all files before uploading (currently broken)

          Z-Bot CoreXY Build | Thingiverse Profile

          1 Reply Last reply Reply Quote 0
          • Googliolaundefined
            Googliola
            last edited by

            @Phaedrux Thanks for the link. Indeed a simple and nice workaround. Unfortunately, I'm a Windows (8.1) and not a Linux person. But I starred the project and will check back.

            1 Reply Last reply Reply Quote 0
            • Danalundefined
              Danal
              last edited by Danal

              There is no "right or wrong" answer to having (or not) variables in G-Code.

              At the same time, the NIST standards writers for G-Code chose "not". There is a fairly deep philosophy behind this: G-Code is/was intended to be a machine control language. It is philosophically not intended to be a programming language.

              Anyone who's coded, even the simplest languages, knows that programming languages that have conditional execution and variables can have many emergent behaviours. This is highly undesirable when controlling machines that can break themselves, break parts, and injure operators.

              G-Code is specifically limited to "deterministic" behaviors. Even allowing math on a single line is a bit debateable in this philosophy; it did make it into the final standard. Nonetheless, people tend to avoid it in truly deterministic G-Code.

              The assumption is that all conditional execution, repetition, etc. will be accomplished in the generator of the G-Code, not the G-Code itself.

              Again, no right/wrong here, but knowing the background philosophy may help explain why things that seem desirable in G-Code may have been intentionally excluded.

              Delta / Kossel printer fanatic

              1 Reply Last reply Reply Quote 2
              • dc42undefined
                dc42 administrators
                last edited by

                This week I have been designing a mechanism for conditional and looping GCode with variables. I will publish the proposal soon.

                Duet WiFi hardware designer and firmware engineer
                Please do not ask me for Duet support via PM or email, use the forum
                http://www.escher3d.com, https://miscsolutions.wordpress.com

                timcurtis67undefined 1 Reply Last reply Reply Quote 2
                • timcurtis67undefined
                  timcurtis67 @dc42
                  last edited by

                  @dc42 said in Make use of variables:

                  This week I have been designing a mechanism for conditional and looping GCode with variables. I will publish the proposal soon.

                  Sweet! I've been waiting for this feature.

                  1 Reply Last reply Reply Quote 1
                  • SupraGuyundefined
                    SupraGuy
                    last edited by

                    @Googliola : For what it's worth, this seems to be a collection of shell scripts and python code. There is a Windows port of bash to execute the shell scripts, and python can be run on just about anything. You MIGHT need to do some translation of some of the different locations and so forth, but I see little reason why this can't work in a Windows environment, if you're willing to put up with some teething pains and see what needs to be changed.

                    @Danal : Certainly fair point, until you get things like configuration files and macros in a "gcode everywhere" the idea that the generator should be doing all of the work is a good one. In this case though since the configuration files, and presumably most of the macros are going to be (for the largest part) hand-coded, with the exception of things like the RepRap Configuration Generator, it gets to be a bit of a pain.

                    I was thinking about the things that I was talking about above, and I realized that gcc includes a facility for running things through its preprocessor without trying to run them through the actual compile process. It throws certain errors, as it expects C/C++ style comments, and not ones with a semicolon prefix, but that isn't too hard to handle.

                    So for example, I have a file test.h which contains the following:

                    #define DEFAULTPROBE P8 H8 F780 I1 T9000 R0.8 Z1
                    #define MESHGRID X30:190 Y35:235 S20
                    #define PROBEOFFSETS X0.0 Y0.0 Z-0.1

                    Then there's a file called manualprobemacro.c (The .c is just more convenient for the preprocessor)

                    ; manualprobe.g manually define a mesh grid without needing to probe manually 90 times

                    #include "test.h"

                    M558 P0
                    G31 X0 Y0 Z0
                    M557 X35:185 Y25:250 S75
                    G29
                    M558 DEFAULTPROBE
                    G31 PROBEOFFSETS
                    M557 MESHGRID

                    Then I run gcc -E manualprobe.c

                    I get some returns from gcc on stderror, since this really isn't C code, but on stdout I get

                    4 "manualprobe.c" 2

                    M558 P0
                    G31 X0 Y0 Z0
                    M557 X35:185 Y25:250 S75
                    G29
                    M558 P8 H8 F780 I1 T9000 R0.8 Z1
                    G31 X0.0 Y0.0 Z-0.1
                    M557 X30:190 Y35:235 S20

                    Now I can probably do something with awk to fix or remove things like the # comment lines. I can probably have it redirect the .c files to .g versions which can then be uploaded en masse to the macro directory. I can probably set up a makefile so that I can just do something like make macros.

                    Maybe if I ever think that I'll have more than a dozen such macros, I might go through the trouble of setting it up.

                    Lead screw driven printer, powered by Duet 2 Wifi
                    MPCNC powered by Duet 2 Wifi
                    CoreXY printer driven by Duet 3 6HC
                    LowRider CNC powered by Duet 2 Wifi

                    1 Reply Last reply Reply Quote 1
                    • dc42undefined
                      dc42 administrators
                      last edited by

                      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.

                      Duet WiFi hardware designer and firmware engineer
                      Please do not ask me for Duet support via PM or email, use the forum
                      http://www.escher3d.com, https://miscsolutions.wordpress.com

                      wilrikerundefined 1 Reply Last reply Reply Quote 5
                      • wilrikerundefined
                        wilriker @dc42
                        last edited by

                        @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.

                        Manuel
                        Duet 3 6HC (v0.6) with RPi 4B on a custom Cartesian
                        with probably always latest firmware/DWC (incl. betas or self-compiled)
                        My Tool Collection

                        1 Reply Last reply Reply Quote 0
                        • Googliolaundefined
                          Googliola
                          last edited by Googliola

                          @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.

                          dc42undefined 1 Reply Last reply Reply Quote 0
                          • dc42undefined
                            dc42 administrators @Googliola
                            last edited by dc42

                            @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$measuredZmean

                            Yes, that or something similar will be possible.

                            Duet WiFi hardware designer and firmware engineer
                            Please do not ask me for Duet support via PM or email, use the forum
                            http://www.escher3d.com, https://miscsolutions.wordpress.com

                            1 Reply Last reply Reply Quote 0
                            • Googliolaundefined
                              Googliola
                              last edited by

                              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.)

                              dc42undefined 1 Reply Last reply Reply Quote 0
                              • tjb1undefined
                                tjb1
                                last edited by

                                @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.

                                1 Reply Last reply Reply Quote 0
                                • dc42undefined
                                  dc42 administrators @Googliola
                                  last edited by

                                  @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

                                  Duet WiFi hardware designer and firmware engineer
                                  Please do not ask me for Duet support via PM or email, use the forum
                                  http://www.escher3d.com, https://miscsolutions.wordpress.com

                                  Googliolaundefined 1 Reply Last reply Reply Quote 0
                                  • garyd9undefined
                                    garyd9
                                    last edited by

                                    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 if

                                    If 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'm not saying that you are wrong - I'm just trying to fit it into my real world simulated experience."

                                    1 Reply Last reply Reply Quote 0
                                    • dc42undefined
                                      dc42 administrators
                                      last edited by

                                      I anticipate that the new features would be used almost exclusively in macro files that are used only on printers running RepRapFirmware.

                                      Duet WiFi hardware designer and firmware engineer
                                      Please do not ask me for Duet support via PM or email, use the forum
                                      http://www.escher3d.com, https://miscsolutions.wordpress.com

                                      garyd9undefined 1 Reply Last reply Reply Quote 0
                                      • garyd9undefined
                                        garyd9 @dc42
                                        last edited by

                                        @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

                                        "I'm not saying that you are wrong - I'm just trying to fit it into my real world simulated experience."

                                        fmaundefined 1 Reply Last reply Reply Quote 0
                                        • Googliolaundefined
                                          Googliola @dc42
                                          last edited by

                                          @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...

                                          1 Reply Last reply Reply Quote 0
                                          • botundefined
                                            bot
                                            last edited by bot

                                            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.

                                            *not actually a robot

                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post
                                            Unless otherwise noted, all forum content is licensed under CC-BY-SA