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

    WHILE loop acts like an IF statement

    Scheduled Pinned Locked Moved Solved
    Gcode meta commands
    4
    9
    200
    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.
    • machinemarkundefined
      machinemark
      last edited by

      I have been trying to create a while loop that either breaks out after some time or when an input becomes high.

      The following code sort of works,

      If the input is high before running, the code goes through the while loop and displays the 'Input Tripped' message as expected.

      If the input remains low the iterations/count are reached and breaks out of the while loop displaying the 'Time Out' message as expected.

      However if the input goes from low to high during the WHILE loop it does not 'break' out and 'Times out'

      It is almost as if the WHILE acts as an IF

      I have tried several variations, like 'while true' , using the iterations variable etc but never had any luck achieving an expected result.

      var timeOut = 8 ; Set time out in seconds
      var tooLong = 0 ; Reset 
      var count = 1 ; Counter reset to 1
      var trippedInput = 0 ; Reset
      
      echo "State of input is " , sensors.gpIn[2].value
      G4 P2000 ; Pause for 2 seconds to see the input state
      
      while sensors.gpIn[2].value == 0 
      	echo "Seconds " , var.count 
      	G4 P1000 ; Pause for 1 second
      	set var.count = var.count + 1
      	if var.count > var.timeOut
      		set var.tooLong = 1
      		break
      
      if var.tooLong == 1
      	M291 P"Time Out" S2
      else
      	M291 P"Input Tripped" S2
      

      I have had a look at other examples and spent several hours, on what I thought should be a simple execution of a WHILE loop but ............

      My next idea is to try and structure the code not using any WHILE statement and using only IF statements. Getting clunkier as we go along.

      Any ideas would be great.

      Thanks Mark

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

        @machinemark what firmware version? Standalone mode or SBC mode?

        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
        • machinemarkundefined
          machinemark
          last edited by

          Thanks dc42, I see you have been busy in the forums.

          echo boards[0].firmwareVersion
          

          Returns 3.5.1

          As far as I know, the Duet is in Standalone mode ie we do NOT have an SBC like a RPI or other hanging off the Duet.

          Thanks Mark

          1 Reply Last reply Reply Quote 0
          • mikeabuilderundefined
            mikeabuilder
            last edited by

            If I understand correctly, the expected behavior when the input goes from low to high during the while loop is that on the next iteration of the loop, when the loop condition is tested (sensors.gpIn[2].value == 0) the loop does not exit.

            Is it possible the input is returning to the low state before the condition is checked?

            As a debug step, you might add a an echo of the sensors.gpIn[2].value at the end of your loop so that you can see that the value was high at that moment.

            If you need to catch a short spike on the input, you might look into is setting up a trigger (https://docs.duet3d.com/en/User_manual/Tuning/Triggers) on the input. The trigger would catch a spike in the input and run a macro that could set a global variable (set global.my_sensor_triggered). Then your code loop above could loop on a number of iterations and break on the global being triggered. Downside of using a trigger is you need to reset the global when you know the sensor is low.

            1 Reply Last reply Reply Quote 0
            • machinemarkundefined
              machinemark
              last edited by

              Hi mikeabuilder,

              That's a top idea. Also modified the echo state during the WHILE loop;

              var timeOut = 8 ; Set time out in seconds
              var tooLong = 0 ; Reset 
              var count = 1 ; Counter reset to 1
              var trippedInput = 0 ; Reset
              
              echo "State of input before the WHILE loop is " , sensors.gpIn[2].value
              G4 P2000 ; Pause for 2 seconds to see the input state
              
              while sensors.gpIn[2].value == 0 
              	echo var.count , "Seconds. Input state - " , sensors.gpIn[2].value
              	G4 P1000 ; Pause for 1 second
              	set var.count = var.count + 1
              	if var.count > var.timeOut
              		set var.tooLong = 1
              		break
              
              echo "State of input after the WHILE loop is " , sensors.gpIn[2].value
              
              if var.tooLong == 1
              	M291 P"Time Out" S2
              else
              	M291 P"Input Tripped" S2
              

              I notice that the input state only shows '1' if the input is high before starting the macro. If I switch the input high during the WHILE loop, the input state remains at '0' even after the while loop. Unexpected behavior. May need to restructure using IF statement but can not see a way to BRANCH to loop like using a GOTO statement.

              Thanks again for the idea, showed something is not right.

              1 Reply Last reply Reply Quote 0
              • mikeabuilderundefined
                mikeabuilder
                last edited by

                Interesting. Your results make me wonder if macro execution is "blocking", meaning that the object model is not updated until after the macro finishes. I'm being particular by stating "object model". Your macro is getting the state of the IO from the object model, not a direct reading from the GPIO and if there is some lag in getting the object model updated, it could give the result you are seeing.

                It's too bad that M42 cannot be used to return the state of a GPIO. Many other gcode commands return the current value if the value-setting parameter is omitted.

                Using a trigger might be needed.

                I also wonder about the M950 command you used to define this IO. Maybe different types of IO are handled in different ways when updating the object model.

                dc42undefined 1 Reply Last reply Reply Quote 0
                • zuoyanundefined
                  zuoyan
                  last edited by

                  If it's something related to 'while expression', you can test the macro version like:

                  while true
                    if sensors.gpIn[2].value != 0
                      break
                    if iterations > var.timeOut
                      set var.tooLong = 1
                      break
                  

                  At least, I believe 'while true' is well tested.

                  1 Reply Last reply Reply Quote 0
                  • machinemarkundefined
                    machinemark
                    last edited by

                    Hello zuoyan,

                    Thanks for message, you are spot about macro "blocking". There is a little more to the story. The input is fed from an output (I did this for testing as I am connected to the Duet remotely). So I would run the macro that runs the WHILE loop and as it is counting up I would run another macro to change the state of an output that is connected to the input (sensors.gpIn[2]) that we are testing. Once I got somebody to switch the input with a simple button, all worked as expected.

                    Thank you for all your help.

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

                      @mikeabuilder said in WHILE loop acts like an IF statement:

                      if there is some lag in getting the object model updated, it could give the result you are seeing.

                      There is no lag in reading OM values within macros when running in standalone mode. Even in SBC mode there is usually no lag because the SBC asks RRF to evaluate expressions.

                      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
                      • dc42undefined dc42 marked this topic as a question
                      • dc42undefined dc42 has marked this topic as solved
                      • First post
                        Last post
                      Unless otherwise noted, all forum content is licensed under CC-BY-SA