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

    Running a Background Macro

    Scheduled Pinned Locked Moved
    General Discussion
    4
    16
    463
    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.
    • Aitorundefined
      Aitor
      last edited by Aitor

      Good morning @dc42,

      I am trying to run a macro in the background using daemon.g. I want to use it to monitor an end-of-material sensor by checking the state of a capacitive sensor. If it does not detect material, it initiates a material load. For this load, I use a fan output to activate my pellet feed system, which I want to turn off after a certain time and not execute again for another period. To do this, I have also blocked daemon.g so that it does not run if one has already been executed and not finished.

      The issue is that if I use this in the same plane as a GCode, I cannot use the M400 command as this would pause the print for the specified time. On the other hand, without using it, when my single-line print codes exceed my G4 codes, they take longer to respond. Could you review my code and see if I am acting appropriately or if there is something I might have overlooked?

      ;daemon.g
      if state.status = "processing"
      	M596 P1
      	if global.DaemonActive = true
      		set global.DaemonActive = false
      		if global.ContPelletsT0 <= 10
      			if {sensors.gpIn[1].value = 1}
      				var TiempoCarga = 6
      				var Bucle = true
      				echo >>"0:/sys/Alimentador Registro" {global.ContPelletsT0}
      				while var.Bucle = true
      					M106 P3 S1
      					G4 S1 M400
      					if sensors.gpIn[1].value = 0 && var.Bucle = true
      						M106 P3 S0
      						G4 S1 M400
      						if sensors.gpIn[1].value = 0
      							set global.ContPelletsT0 = 1
      							M300 S5000 P500
      							set var.Bucle = false
      					if var.TiempoCarga <= 0 && var.Bucle = true
      						set global.ContPelletsT0 = global.ContPelletsT0+1
      						M300 S5000 P3000
      						set var.Bucle = false
      					set var.TiempoCarga = var.TiempoCarga-1
      				M106 P3 S0
      				G4 S15 M400
      		else
      			set global.ContPelletsT0 = 1
      			M596 P0
      			M25
      			M400
      			M291 R"Sensor Right" P"No Pellets detected" S2 T0
      		set global.DaemonActive = true
      
      Product					Short Name		Version
      Duet 3 MB6HC				MB6HC			3.5.1
      Duet 3 Expansion EXP3HC			EXP3HC			3.5.1
      Duet WiFi Server			n/a			2.1.0
      Duet Web Control			DWC			3.5.1
      

      Best regards,

      Aitorundefined 1 Reply Last reply Reply Quote 0
      • Aitorundefined
        Aitor @Aitor
        last edited by

        Good morning @dc42,

        I think I'm doing something wrong, or there is something I haven't understood well. I am trying to use Multiple Motion Systems to run a macro that turns my pellet feeder on and off, to prevent lines from taking too long during printing and to ensure it reacts in the expected time, but I can't get it to work properly and I don't know what I'm doing wrong.

        Today, I tried configuring a T5 tool, for example:

        M563 P5 F3 X4 Y5 S"Feeder"; assigning it a "part cooling fan" which will be my feeder and assigning it fictitious axes, so that when it is selected in M596 P1, there are no waiting conflicts.

        Despite this, the result was not what I expected, as now it behaves strangely. It seems to execute everything I specify in the macro, but once the long movements of the main gcode finish, the secondary ones execute all at once, causing my feeder to turn on and off almost instantly.

        This is the modified code I used this time. I thought I might need to treat it as a tool to make it work:

        ;daemon.g
        M596 P1
        T5
        if state.status = "processing"
        	if global.DaemonActive = true
        		set global.DaemonActive = false
        		if global.ContPelletsT0 <= 10
        			if {sensors.gpIn[1].value = 1}
        				var TiempoCarga = 6
        				var Bucle = true
        				echo >>"0:/sys/Alimentador Registro" {global.ContPelletsT0}
        				while var.Bucle = true
        					M106 S1
        					G4 S1 M400
        					if sensors.gpIn[1].value = 0 && var.Bucle = true
        						M107
        						M300 S5000 P500
        						G4 S1 M400
        						if sensors.gpIn[1].value = 0
        							set global.ContPelletsT0 = 1
        							M300 S5000 P500
        							set var.Bucle = false
        					if var.TiempoCarga <= 0 && var.Bucle = true
        						set global.ContPelletsT0 = global.ContPelletsT0+1
        						M300 S5000 P3000
        						set var.Bucle = false
        					set var.TiempoCarga = var.TiempoCarga-1
        				M107
        				G4 S20 M400
        			else
        				set global.ContPelletsT0 = 1
        		else
        			set global.ContPelletsT0 = 1
        			M596 P0
        			M25
        			M400
        			M291 R"Sensor Right" P"No Pellets T0 detected" S2 T0
        		set global.DaemonActive = true
        

        Best regards,

        dc42undefined 1 Reply Last reply Reply Quote 0
        • OwenDundefined
          OwenD
          last edited by OwenD

          I haven't delved into your code, but might I suggest an alternate method?

          I presume you have some sort of hopper that has an inductive sensor at the bottom?

          If so then I suggest you also fit an inductive sensor near the top.

          Then simply set up triggers on the two sensors. (they can both point to the same trigger file)
          The lower one simply turns on a motor (a fan or heater output would work)
          The upper sensor trigger turns the motor off again when the hopper is full.

          so your config.g might look like this.
          I don't know what board you have but this should work on a mini5

          EDIT
          Added code to pause the print if the hopper hasn't filled in X seconds

          M950 F3 C"!out9"  ; Fan 3 uses inverted !out9 pin
          M106 P3 C"Pellet_Feeder" S0 H-1 
          M950 J1 C"IO2.in"            ; Input 1 uses IO2.in pin
          M950 J2 C"IO3.in"            ; Input 2 uses IO2.in pin
          M581 T5 P1 S0 R1 ; ; invoke trigger 5 when an active to inactive edge is detected on input 1 and a file is being printed from SD card
          M581 T5 P2 S1 R1 ; invoke trigger 5 when an inactive-to-active edge is detected on input 2 and a file is being printed from SD card
          

          Then in trigger5.g something like

          var maxFillTime = 60 ; maximum time (seconds)  to fill hopper.  Print paused if not filled in this time
          if !exist global.pauseNoPelletsTime
            global pauseNoPelletsTime = state.upTime + var.maxFillTime
          if sensors.gpIn[1].value = 0  ; if the lower sensor 
            M106 P3 S1
            set global.pauseNoPelletsTime = state.upTime + var.maxFillTime
          if sensors.gpIn[2].value = 1
            M106 P3 S0  
          

          If you want the beep then I'd put this in daemon.g
          The while true loop will keep it running so it must have a delay in it to hand back to the main process.

          while true
            if fans[3].actualValue > 0
              M300 S5000 P500
              G4 P500
            ; at this point you could check either sensor depending how you want it to work
            if (global.pauseNoPelletsTime < state.upTime) && (sensors.gpIn[2].value = 0) && (state.status = "processing")
              M106 P3 S0 ; turn off feeder
              M25 ; pause print as hopper hasn't refilled
            G4 S3 ; delay between loops
          
          Aitorundefined 1 Reply Last reply Reply Quote 0
          • dc42undefined
            dc42 administrators @Aitor
            last edited by

            @Aitor I am out of the office today but I have a few comments on your posts:

            1. I don't understand the reason for the M400 commands. Please explain what you mean by "On the other hand, without using it, when my single-line print codes exceed my G4 codes, they take longer to respond."

            2. You should not need to use a tool in the daemon.g code.

            3. What's the purpose of setting global.DaemonActive false and then true in the daemon.g file? RRF will never re-enter the daemon.g file, so you don't need this to prevent the daemon.g code being executed twice in parallel.

            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

            Aitorundefined 1 Reply Last reply Reply Quote 0
            • Aitorundefined
              Aitor @dc42
              last edited by

              Good morning @dc42,

              Thanks for taking a look. First of all, to also respond to @OWEND, initially I had configured this code as a trigger and used the file called trigger2.g, as I normally do with filament equipment. However, I encountered certain problems that a constant check would solve. Therefore, I decided to use daemon.g, although it is likely that if I solve the daemon.g problem, I can apply it in trigger#. (response to point 2)

              The case is that I am using a Pulsar head, which integrates a capacitive sensor to detect if there are pellets in the head. I have connected it to the Duet and configured it as a trigger as follows:

              M950 J1 C"1.io2.in"			; Create GPIO/servo pin
              M581 P1 T2 R-1				; Configure external trigger#.g
              

              I am using a custom feeder that absorbs pellets through the Venturi effect, so my fan output simply activates or deactivates an electropneumatic relay.

              The main problem is that I must activate this output for 6 seconds. Less time does not perform a load, and more time excessively empties my compressor, losing the necessary pressure for a second load. Therefore, I also keep the valve closed for at least 20 seconds. (I am trying to buy a larger capacity compressor, but I doubt it will be ready in time for the fair). Additionally, I count failed load attempts, and if this number is 10 or more, I pause the print, assuming that either my feed load has failed or it has run out of material. (response to point 1)

              The reason for blocking daemon.g was that I realized it sometimes executed before a previous execution had finished, causing strange behaviors. I decided to block it for safety, although I am not sure this was the cause of the strange behavior. To be sure, I blocked it. If there is an active daemon.g and it has not finished executing in 10 seconds, is it possible for it to execute again? (response to point 3)

              Delving into point 1, whether I use daemon.g or trigger#.g in the same stack as the g-code, daemon or trigger mix with the print code. That is, they execute at the same time as printing. When I print pieces where the extrusion lines are short and execute quickly, such as printing a circle composed of hundreds of small straight lines, the macros execute quickly and even behave as expected. The problem arises when the extrusion lines are long, such as in a solid fill. Also, keep in mind that my print area is 1000mm x 1000mm, so these lines can take quite a while to go from one point to another. For example, I notice that when my solenoid valve is activated, and then a long print line follows, such as a diagonal from side to side, from point 0,0 to 1000,1000, which can take approximately 15-30 seconds, my solenoid valve remains active all this time, emptying my compressor and preventing a successful second load. Therefore, I thought of using M596 P1, either for daemon.g or trigger#.g, so that my macro executes at the times set in the macro, regardless of what lines of code the main stack is printing and the time it takes to execute them. The problem is that M596 P1 does not work as I expect, or I am not using it correctly.

              Sorry for the long message, and if something is unclear, please feel free to ask.

              Best regards,

              droftartsundefined dc42undefined 2 Replies Last reply Reply Quote 0
              • droftartsundefined
                droftarts administrators @Aitor
                last edited by

                @Aitor said in Running a Background Macro:

                The problem arises when the extrusion lines are long, such as in a solid fill.

                If it works on short line segments, but not on long ones, you could try using segmentation, to segment long lines into smaller moves. See M996 S and T parameters, here: https://docs.duet3d.com/en/User_manual/Reference/Gcodes#m669-set-kinematics-type-and-kinematics-parameters

                e.g.:

                M669
                Kinematics is Cartesian, no segmentation, matrix:
                1.00 0 0
                0 1.00 0
                0 0 1.00
                
                M669 S1
                
                M669
                Kinematics is Cartesian, 1 segments/sec, min. segment length 0.20mm, matrix:
                1.00 0 0
                0 1.00 0
                0 0 1.00
                

                Ian

                Bed-slinger - Mini5+ WiFi/1LC | RRP Fisher v1 - D2 WiFi | Polargraph - D2 WiFi | TronXY X5S - 6HC/Roto | CNC router - 6HC | Tractus3D T1250 - D2 Eth

                Aitorundefined 1 Reply Last reply Reply Quote 0
                • Aitorundefined
                  Aitor @OwenD
                  last edited by

                  Good morning @OwenD,

                  I will carefully review your suggestion, as there are certain points that I am not fully understanding and need to analyze in depth. I am still getting used to programming and there are certain object models in your code that I do not know by heart.

                  Anyway, at first glance, I think my main problem with the compressor issue will still exist.

                  Thank you for your contribution. I would be happy to hear any further suggestions you have.

                  Best regards,

                  OwenDundefined 1 Reply Last reply Reply Quote 0
                  • Aitorundefined
                    Aitor @droftarts
                    last edited by

                    Good morning @droftarts,

                    I will try this immediately. Just to clarify, if I have code running, for example, a print line from point 0,0 to point 1000,1000, does this mean that it will be divided into parts so that other commands can execute before this line finishes?

                    Best regards,

                    droftartsundefined 1 Reply Last reply Reply Quote 0
                    • OwenDundefined
                      OwenD @Aitor
                      last edited by OwenD

                      @Aitor said in Running a Background Macro:

                      Good morning @OwenD,

                      I will carefully review your suggestion, as there are certain points that I am not fully understanding and need to analyze in depth. I am still getting used to programming and there are certain object models in your code that I do not know by heart.

                      Anyway, at first glance, I think my main problem with the compressor issue will still exist.

                      Thank you for your contribution. I would be happy to hear any further suggestions you have.

                      Best regards,

                      OK
                      If I understand your setup correctly then I believe this code will work.
                      By using the while true in daemon.g, it will only open once (and continue endlessly), not run every 10 seconds,
                      So you MUST have a delay inside the while loop

                      if !exists global.runUntilTime
                      	global runUntilTime = state.upTime + 6
                      if !exists global.noRunBeforeTime
                      	global noRunBeforeTime = state.upTime
                      if !exists global.failedLoadCount 
                      	global failedLoadCount = 0	
                      
                      while true
                      	if (state.status = "processing") && (sensors.gpIn[2].value=0) && (global.noRunBeforeTime < state.upTime)
                      		M106 P3 S1
                      		set global.runUntilTime = state.upTime + 6
                      		while state.upTime < global.runUntilTime ; count off the fill time
                      			M300 S5000 P500
                      			G4 S1
                      		M106 P3 S0
                      		set global.noRunBeforeTime = state.upTime + 20 ; set the new time to allow compressor refill
                      		if sensors.gpIn[2].value=0 ; is hopper still empty?
                      			set global.failedLoadCount = global.failedLoadCount + 1
                      		else
                      			global.failedLoadCount = 0
                      		if global.failedLoadCount > 10
                      			M25
                      	G4 S1
                      
                      1 Reply Last reply Reply Quote 1
                      • droftartsundefined
                        droftarts administrators @Aitor
                        last edited by

                        @Aitor said in Running a Background Macro:

                        Just to clarify, if I have code running, for example, a print line from point 0,0 to point 1000,1000, does this mean that it will be divided into parts so that other commands can execute before this line finishes?

                        Yes, it should do. Use the M669 S and T parameters to get the granularity that you need. My example chose M669 S1, which means minimum 1 segment per second, so it can have more than 1 segment per second (ie multiple short moves) and will stop/pause within a second (or do other tasks like checking triggers).

                        M669 T parameter is similar, it just means that any move longer than the minimum segment size is broken up into equal length moves that are, at a minimum, the minimum segment size (yes, slightly confusing that one!).

                        e.g. with M669 T0.1 set:

                        • a 0.199mm move will be 1 segment of 0.199mm, as it cannot be divided into equal length moves of less than 0.1mm.
                        • a 0.201mm move would be split into two moves of 0.1005mm
                        • a 0.299mm move would be split into two moves of 0.1495mm

                        So any move that is more than double the size of M669 T#, will be split into equal length segments that are between # and 1.5x # long.

                        Ian

                        Bed-slinger - Mini5+ WiFi/1LC | RRP Fisher v1 - D2 WiFi | Polargraph - D2 WiFi | TronXY X5S - 6HC/Roto | CNC router - 6HC | Tractus3D T1250 - D2 Eth

                        Aitorundefined 1 Reply Last reply Reply Quote 1
                        • Aitorundefined
                          Aitor @droftarts
                          last edited by

                          Good morning everyone,

                          Thank you very much @droftarts, your contribution was key to solving the main problem of the excessively long lines. Configuring M669 T0.1 S1 worked perfectly, starting and stopping my feeder during long runs. However, it only worked when using M596 P1; I don't completely understand why, but I really appreciate your help.

                          @OwenD Thank you too for your code. Although it doesn't behave as it should, probably due to the "while true", it will help me a lot to optimize my code. After seeing yours, I realize that sometimes I'm a bit clumsy. 😁

                          Best regards,

                          Aitorundefined 1 Reply Last reply Reply Quote 0
                          • Aitorundefined
                            Aitor @Aitor
                            last edited by

                            Good morning everyone again,

                            I have a question: Can M669 T0.1 S1 potentially slow down other processes or make the Duet work excessively? I will adjust this value to something less extreme, as I understand that M669 T15 S1 might be sufficient.

                            I also increased the value of the second stack with the command M595 Q1 P60. My question here is similar: What could be the implications of increasing the stack so much? I will continue testing, but I understand that setting the same number of lines as my macro, or even fewer, should be enough, right? Or would this slow down the process?

                            Best regards,

                            droftartsundefined 1 Reply Last reply Reply Quote 0
                            • droftartsundefined
                              droftarts administrators @Aitor
                              last edited by

                              @Aitor I'm not sure if segmentation is applied before or after the command is added to the queue, but I think after, so a command added to the queue is still just a single command (I'll check with @dc42). I don't think segmentation would slow down other processes particularly. Some kinematics (Polar, SCARA) usually have segmentation configured, with S100 T0.2, but as far as I'm aware there's no appreciable slow down.

                              Having a long command queue can cause problems. Yes, you don't want a short queue, and then not be able to supply enough commands to keep the axes moving continuously, but then you also have the problem of sending commands that go into the queue, and how long it takes for them to be enacted. For a summary of this, see https://docs.duet3d.com/User_manual/Reference/Gcodes#command-queueing
                              You don't need to have the whole of your macro in the queue, just enough of it that it doesn't stutter. You also don't have any moves that need to be 'planned' ie G0/1/2/3 moves, you're just turning on the hopper motor with M106 commands, and there's a lot of G4 pauses.

                              Running the macro supplied by @OwenD should work, though looking at it it doesn't look like it's running in the second motion system? With all the pauses, and only using M106, perhaps it doesn't need to. I have a feeling that running the M300 command to play a beep sound pauses the whole queue while sound is played, so that might be causing pauses if it's not run in the second motion system.

                              Ian

                              Bed-slinger - Mini5+ WiFi/1LC | RRP Fisher v1 - D2 WiFi | Polargraph - D2 WiFi | TronXY X5S - 6HC/Roto | CNC router - 6HC | Tractus3D T1250 - D2 Eth

                              Aitorundefined 1 Reply Last reply Reply Quote 0
                              • Aitorundefined
                                Aitor @droftarts
                                last edited by

                                Good morning, @droftarts,

                                I understand the topic of segmentation and also the queue. I believe that leaving the stack of 3 as the default might be sufficient; however, I will conduct tests regarding this.

                                I have modified @OwenD's macro a bit to run it in the background. Additionally, I have added some features to save compressed air and to keep a record of my attempts, in order to analyze the number of attempts I usually need, and thus be able to better adjust the value of 10 repetitions. The result so far is this:

                                M596 P1
                                if (state.status = "processing") && (sensors.gpIn[1].value = 1) && (global.DaemonActive < state.upTime)
                                	M106 P3 S1
                                	set global.TimerPelletsT0 = state.upTime + 6
                                	echo >>"0:/sys/Alimentador Registro" {global.ContPelletsT0} ;Log of number of unsuccessful attempts
                                	while state.upTime < global.TimerPelletsT0	; count off the fill time
                                		if sensors.gpIn[1].value = 0 ;Check for pellets
                                			M106 P3 S0
                                			G4 P500 M400 ;Perform a short wait before checking
                                				if sensors.gpIn[1].value = 0 ;Check that it was not a false detection
                                					set global.TimerPelletsT0 = state.upTime - 6
                                					M300 S5000 P500
                                				else ;A false detection was detected, continue.
                                					M106 P3 S1
                                		G4 S1 M400
                                	M106 P3 S0
                                	set global.DaemonActive = state.upTime + 20 ; set the new time to allow compressor refill
                                	if sensors.gpIn[1].value = 1 ; is hopper still empty?
                                		set global.ContPelletsT0 = global.ContPelletsT0 + 1
                                	else
                                		set global.ContPelletsT0 = 1
                                	if global.ContPelletsT0 > 10
                                		M596 P0
                                		M25
                                		M291 R"Material Sensor" P"No Pellets detected" S2 T0
                                

                                I can also tell you that making beeps does not cause any pauses, they only generate an interruption if you place a G4 and M400 right after, but in my case, running in the background, the M400s do not cause pauses. What I have noticed is that when I run this same macro without M400 in the foreground, the delays execute before reaching those lines, meaning they don't wait to reach that line and then everything executes at once. However, it's true that segmenting the line shouldn't cause this, so I will review it again. I am sure that if I run this macro with M400s in the foreground, I will have pauses during printing, hence the reason for running them in the background.

                                Regards,

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

                                  @Aitor said in Running a Background Macro:

                                  The reason for blocking daemon.g was that I realized it sometimes executed before a previous execution had finished, causing strange behaviors.

                                  RRF will never re-enter daemon.g, unless you use M98 to execute daemon.g explicitly from somewhere else.

                                  Likewise when a trigger is executing, another trigger (whether the same one of a different one) won't be executed until the original one has completed or aborted; except that trigger 0 can always be executed.

                                  @Aitor said in Running a Background Macro:

                                  Delving into point 1, whether I use daemon.g or trigger#.g in the same stack as the g-code, daemon or trigger mix with the print code. That is, they execute at the same time as printing.

                                  What do you mean by "in the same stack"?

                                  @Aitor said in Running a Background Macro:

                                  For example, I notice that when my solenoid valve is activated, and then a long print line follows, such as a diagonal from side to side, from point 0,0 to 1000,1000, which can take approximately 15-30 seconds, my solenoid valve remains active all this time, emptying my compressor and preventing a successful second load.

                                  That is not expected, if the solenoid valve is activated only by daemon.g or by the trigger. Both daemon.g and a trigger file (if triggered) should execute concurrently (several times if needed) with long moves in the job file; provided that you do not either command motion in the same motion system or use M400 in the trigger file or daemon.g.

                                  If your daemon.g or trigger files does not command any motion, you should not need to use M596 P1.

                                  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

                                  Aitorundefined 1 Reply Last reply Reply Quote 0
                                  • Aitorundefined
                                    Aitor @dc42
                                    last edited by

                                    Good morning @dc42,

                                    Thank you for your response. Regarding blocking daemon.g, it is clear to me that it is not necessary. It was likely a feeling I had due to the behavior I observed, and I decided to block it to be sure, but I have now removed it from my code.

                                    Regarding "stack," it is probably a mistranslation; I mean the movement queue (M596 P0 or P1).

                                    As for your last comment, I just tried it and still have to use M569 P1 because if I don't use it, it does not execute in the desired times. Even using M669 T0.1 S1, the execution response of daemon.g is slow. Here are the details of how I conducted the tests.

                                    Gcode being printed:

                                    ; G-Code generated by INDART3D
                                    
                                    G21                         ; Metric values
                                    T0 P0                       ; Select Tool
                                    G28                         ; Home all
                                    G0 Z900
                                    M400                        ; Wait for current moves to finish
                                    
                                    ; Macro
                                    G1 X0 Y0 F3000
                                    G1 X1000 Y1000
                                    G1 X0 Y1000
                                    G1 X1000 Y0
                                    G1 X0 Y0 F3000
                                    G1 X1000 Y1000
                                    G1 X0 Y1000
                                    G1 X1000 Y0
                                    G1 X0 Y0 F3000
                                    G1 X1000 Y1000
                                    G1 X0 Y1000
                                    G1 X1000 Y0
                                    G1 X1000 Y0
                                    G1 X0 Y0 F3000
                                    ; The gcode keeps repeating these commands hundreds more times
                                    

                                    daemon.g modified with your instructions:

                                    ; M596 P1
                                    if (state.status == "processing") && (sensors.gpIn[1].value == 1) && (global.DaemonActive < state.upTime)
                                        M106 P3 S1
                                        set global.TimerPelletsT0 = state.upTime + 6
                                        echo >>"0:/sys/Alimentador Registro" {global.ContPelletsT0} ; Log of number of unsuccessful attempts
                                        while state.upTime < global.TimerPelletsT0 ; count off the fill time
                                            if sensors.gpIn[1].value == 0 ; Check for pellets
                                                M106 P3 S0
                                                G4 P500 ; M400 ; Perform a short wait before checking
                                                if sensors.gpIn[1].value == 0 ; Check that it was not a false detection
                                                    set global.TimerPelletsT0 = state.upTime - 6
                                                    M300 S5000 P500
                                                else ; A false detection was detected, continue.
                                                    M106 P3 S1
                                            G4 S1 ; M400
                                        M106 P3 S0
                                        set global.DaemonActive = state.upTime + 20 ; set the new time to allow compressor refill
                                        if sensors.gpIn[1].value == 1 ; is hopper still empty?
                                            set global.ContPelletsT0 = global.ContPelletsT0 + 1
                                        else
                                            set global.ContPelletsT0 = 1
                                        if global.ContPelletsT0 > 10
                                            set global.ContPelletsT0 = 1
                                            ; M596 P0
                                            M25
                                            M291 R"Material Sensor" P"No Pellets detected" S2 T0
                                    

                                    The result I get is the same. Right now, I am testing with an empty system, so sensors.gpIn[1].value is always equal to 1. The issue is that without using the secondary motion queue, it does not respect the 6 seconds, it always takes longer than desired, and it always turns off or on at the end of the complete Gcode lines, despite being fragmented with M669 T0.1 S1.

                                    Best regards,

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