• Tags
  • Documentation
  • Order
  • Register
  • Login
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
198
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.
  • undefined
    machinemark
    last edited by 27 Jan 2025, 14:50

    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

    undefined 1 Reply Last reply 27 Jan 2025, 16:02 Reply Quote 0
    • undefined
      dc42 administrators @machinemark
      last edited by 27 Jan 2025, 16:02

      @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
      • undefined
        machinemark
        last edited by 27 Jan 2025, 17:33

        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
        • undefined
          mikeabuilder
          last edited by 27 Jan 2025, 18:20

          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
          • undefined
            machinemark
            last edited by 27 Jan 2025, 20:04

            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
            • undefined
              mikeabuilder
              last edited by 27 Jan 2025, 21:09

              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.

              undefined 1 Reply Last reply 28 Jan 2025, 08:51 Reply Quote 0
              • undefined
                zuoyan
                last edited by 27 Jan 2025, 22:14

                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
                • undefined
                  machinemark
                  last edited by 28 Jan 2025, 08:35

                  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
                  • undefined
                    dc42 administrators @mikeabuilder
                    last edited by 28 Jan 2025, 08:51

                    @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
                    • undefined dc42 marked this topic as a question 28 Jan 2025, 08:51
                    • undefined dc42 has marked this topic as solved 28 Jan 2025, 08:51
                    5 out of 9
                    • First post
                      5/9
                      Last post
                    Unless otherwise noted, all forum content is licensed under CC-BY-SA