Run code only on long press of button

I have the following script that runs fine but I would like it to not run when the button is pressed momentarily and only run when the button is pressed for a longer period of time (i.e. 3 seconds). Any help would be appreciated.

    begin

    0 get_position #Check state of switch, number is the channel the switch is on
    1 less_than #Check if switch is held, number is the amount of time the switch must be held before moving servo
    if

    sequence_0 #Run the move servo subroutine


    endif

    0 get_position #Check state of switch, 0 is the channel the switch is on
    1 greater_than #Check if switch is released, number is the amount of time the switch must be released before moving servo 
    if

    endif


    repeat
    return




    ### Sequence subroutines: ###

    # Sequence 0
    sub Sequence_0
      500 5940 0 0 5800 0 frame_1..5 # Frame 0
      1300 6400 6400 frame_1_4 # Frame 1
      1300 delay # Frame 2
      1300 delay # Frame 3
      1300 delay # Frame 4
      1300 delay # Frame 5
      1300 delay # Frame 6
      1300 delay # Frame 7
      1300 5940 5800 frame_1_4 # Frame 8
      return

    sub frame_1..5
      5 servo
      4 servo
      3 servo
      2 servo
      1 servo
      delay
      return

    sub frame_1_4
      4 servo
      1 servo
      delay
      return

    6500 4 servo
    50 delay # added delay for 50 miliseconds
    3000 4 servo
    100 delay # added delay for 100 miliseconds
    return

Hello.

There are various ways to implement the type of feature you described. I would recommend merging the script example under the “Using a button or switch to control servos” heading in the “Example Scripts” section of the Maestro Servo Controller User’s Guide with your code and extend the button hold time from 10 ms to 3000 ms (3 seconds) in the wait_for_button_closed_10ms subroutine by changing:

get_ms over minus 10 greater_than

to

get_ms over minus 3000 greater_than

If you have trouble merging the two codes, you can post your modified script, and I would be happy to take a look.

By the way, I noticed in your script there are a few lines code that are incomplete. The code lines I am referring to are:

return	# code line after repeat

and

6500 4 servo
50 delay # added delay for 50 miliseconds
3000 4 servo
100 delay # added delay for 100 miliseconds
return

You should probably remove those code parts to avoid confusion and make the code look cleaner.

- Amanda

Thank you Amanda. I tried merging my code with the one in the example scripts last night. I haven’t been to get it to work yet but I will play with it some more this weekend. I’ll post my modified script if I’m still having troubles.

One question, do I get rid of my code I was using previously to monitor the button and replace it with the button monitoring code from the example script or do I use both codes?

I think I picked up the return from another example script and assumed I needed it. Good to know I don’t.

The last bit of code actually controls an LED output I assigned to servo 4.

So I have the code working so it only runs my script when I hold the button for 3 seconds but now it keeps running my code in a loop. I would like it to stop the script when the button is open. Here is the merged script.

     goto main_loop    # Run the main loop when the script starts (see below).
      
     # This subroutine returns 1 if the button is pressed, 0 otherwise.
     # To convert the input value (0-1023) to a digital value (0 or 1) representing
     # the state of the button, we make a comparison to an arbitrary threshold (500).
     # This subroutine puts a logical value of 1 or a 0 on the stack, depending
     # on whether the button is pressed or not.

     sub button
       0 get_position 500 less_than
       return
      
     # This subroutine uses the BUTTON subroutine above to wait for a button press,
     # including a small delay to eliminate noise or bounces on the input.
     sub wait_for_button_press
       wait_for_button_open_10ms
       wait_for_button_closed_3000ms
       return
      
     # Wait for the button to be NOT pressed for at least 10 ms.
     sub wait_for_button_open_10ms
       get_ms # put the current time on the stack
       begin
         # reset the time on the stack if it is pressed
         button
         if
           drop get_ms
         else
           get_ms over minus 10 greater_than
           if drop return endif
         endif
       repeat
      
     # Wait for the button to be pressed for at least 3000 ms.
     sub wait_for_button_closed_3000ms
       get_ms
       begin
         # reset the time on the stack if it is not pressed
         button

         if
           get_ms over minus 3000 greater_than
           if drop return endif
         else
           drop get_ms
         endif
       repeat

      
     # Uses WAIT_FOR_BUTTON_PRESS to allow sequence_0 to run.

     # Sequence 0
     sub Sequence_0
     begin
       500 5940 0 0 5800 0 frame_1..5 # Frame 0
       1300 6400 6400 frame_1_4 # Frame 1
       1300 delay # Frame 2
       1300 delay # Frame 3
       1300 delay # Frame 4
       1300 delay # Frame 5
       1300 delay # Frame 6
       1300 delay # Frame 7
       1300 5940 5800 frame_1_4 # Frame 8
     repeat


     sub frame_1..5
       5 servo
       4 servo
       3 servo
       2 servo
       1 servo
       delay
     return
       
     main_loop:
      
     sub frame
       wait_for_button_press

     sequence_0



     sub frame_1_4
       4 servo
       1 servo
       delay

      return

Looking at your recent script, you have a begin/repeat block within your Sequence_0 subroutine, which is causing the program to repeat. One way to fix this problem is to remove the begin/repeat lines in Sequence_0 and use return instead (at the end of that subroutine). Then add begin/repeat lines around the code under main_loop. Like so:

# Sequence 0
sub Sequence_0
    500 5940 0 0 5800 0 frame_1..5 # Frame 0
    1300 6400 6400 frame_1_4 # Frame 1
    1300 delay # Frame 2
    1300 delay # Frame 3
    1300 delay # Frame 4
    1300 delay # Frame 5
    1300 delay # Frame 6
    1300 delay # Frame 7
    1300 5940 5800 frame_1_4 # Frame 8
    return

main_loop:
    begin
        wait_for_button_press
        Sequence_0
    repeat

Using return at the end of the Sequence_0 subroutine tells the program to return back to the point where the subroutine was last called, which prevents the program from falling through and executing frame_1..5. By encapsulating wait_for_button_press and Sequence_0 in a begin/repeat block under main_loop, the program will continually cycle between waiting for a button press (lasting for at least 3 seconds) and executing the movement sequence.

Since it seems that you are new to using the Maestro Scripting Language, I strongly recommend reading the “Command Reference” section of the Maestro Servo Controller User’s Guide to get a better understanding of the commands.

By the way, you mentioned in your previous post that the last bit of code actually controls an LED output that you assigned to servo 4, but in your original script, it does not look like the program will ever reach that section of code. If you can tell me what you are using the LED for, I might be able to offer suggestions on how you can implement that feature into your script.

- Amanda