2 button Maestro input script

Hello,

Stupid issue here with a simple maestro script. I only have 2 sequences (“Sequence 1” and “Sequence 2”) and only 2 inputs (Channel 22 and 23 on maestro, momentary SPST push-button switch). My monkey brain cannot figure out what is wrong with the script, I bet you can see it immediately. Please help! TIA!

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
  22 get_position 500 less_than
  return
 
#me
sub button_2
  23 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_10ms
  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
#me
button_2 
    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 10 ms.
sub wait_for_button_closed_10ms
  get_ms
  begin
    # reset the time on the stack if it is not pressed
    button
    if
      get_ms over minus 10 greater_than
      if drop return endif
    else
      drop get_ms
    endif

#me
button_2
    if
      get_ms over minus 10 greater_than
      if drop return endif
    else
      drop get_ms
    endif


  repeat
 
# An example of how to use wait_for_button_press is shown below:
 
# Uses WAIT_FOR_BUTTON_PRESS to allow a user to step through
# a sequence of positions on servo 1.
main_loop:
begin
  wait_for_button_press          # call subroutine before executing sequence
  500 5184 5376 6336 5632 6272 0 
  0 0 0 0 0 0 
  0 0 0 0 0 0 
  0 0 0 0 frame_0..21 # Frame 0
  500 6784 frame_0 # Frame 1
  500 8000 frame_1 # Frame 2
  500 8384 frame_2 # Frame 3
  500 8000 frame_3 # Frame 4
  500 8192 frame_4 # Frame 5
  500 6272 frame_4 # Frame 6
  500 5632 frame_3 # Frame 7
  500 6336 frame_2 # Frame 8
  500 5376 frame_1 # Frame 9
  500 5184 frame_0 # Frame 10
  2000 6784 8000 8384 8000 8192 frame_0..4 # Frame 11
  1000 5184 5376 6336 5632 6272 frame_0..4 # Frame 12
  1500 6784 8000 8384 8000 8192 frame_0..4 # Frame 13
  1500 5184 5376 6336 5632 6272 frame_0..4 # Frame 14
  500 6784 8000 frame_0_1 # Frame 15
  500 5376 8384 frame_1_2 # Frame 16
  500 6336 8000 frame_2_3 # Frame 17
  500 5632 8192 frame_3_4 # Frame 18
  500 6272 frame_4 # Frame 19
  500 6826 7460 6923 7326 frame_1..4 # Frame 20
  1000 5376 6336 5632 6272 frame_1..4 # Frame 21
  1000 8000 8384 8000 8192 frame_1..4 # Frame 22
  1000 6750 7423 6880 7284 frame_1..4 # Frame 23
  200 5376 frame_1 # Frame 24
  200 6336 frame_2 # Frame 25
  200 5632 frame_3 # Frame 26
  200 6272 frame_4 # Frame 27
repeat

#sub Sequence_0
#  wait_for_button_press
  1 servo
  return



#PERCY PROGRAMS

### Sequence subroutines: ###

# Sequence 0
sub Sequence_0
  500 5184 5632 3584 3904 5245 0 
  0 0 0 0 0 0 
  0 0 0 0 0 0 
  0 0 0 0 frame_0..21 # Frame 0
  500 6784 frame_0 # Frame 1
  500 7104 frame_1 # Frame 2
  500 6592 frame_2 # Frame 3
  500 6400 frame_3 # Frame 4
  500 7296 frame_4 # Frame 6
  return
# Sequence 1
sub Sequence_1
  500 5184 5376 6336 5632 6272 0 
  0 0 0 0 0 0 
  0 0 0 0 0 0 
  0 0 0 0 frame_0..21 # Frame 0
  500 6784 frame_0 # Frame 1
  500 8000 frame_1 # Frame 2
  500 8384 frame_2 # Frame 3
  500 8000 frame_3 # Frame 4
  500 8192 frame_4 # Frame 5
  500 6272 frame_4 # Frame 6
  500 5632 frame_3 # Frame 7
  500 6336 frame_2 # Frame 8
  500 5376 frame_1 # Frame 9
  500 5184 frame_0 # Frame 10
  2000 6784 8000 8384 8000 8192 frame_0..4 # Frame 11
  1000 5184 5376 6336 5632 6272 frame_0..4 # Frame 12
  1500 6784 8000 8384 8000 8192 frame_0..4 # Frame 13
  1500 5184 5376 6336 5632 6272 frame_0..4 # Frame 14
  500 6784 8000 frame_0_1 # Frame 15
  500 5376 8384 frame_1_2 # Frame 16
  500 6336 8000 frame_2_3 # Frame 17
  500 5632 8192 frame_3_4 # Frame 18
  500 6272 frame_4 # Frame 19
  500 6826 7460 6923 7326 frame_1..4 # Frame 20
  1000 5376 6336 5632 6272 frame_1..4 # Frame 21
  1000 8000 8384 8000 8192 frame_1..4 # Frame 22
  1000 6750 7423 6880 7284 frame_1..4 # Frame 23
  200 5376 frame_1 # Frame 24
  200 6336 frame_2 # Frame 25
  200 5632 frame_3 # Frame 26
  200 6272 frame_4 # Frame 27
  return
# Sequence 2
sub Sequence_2
  500 5184 5376 6336 5632 6272 0 
  0 0 0 0 0 0 
  0 0 0 0 0 0 
  0 0 0 0 frame_0..21 # Frame 0
  500 7228 frame_4 # Frame 1
  500 6785 frame_3 # Frame 2
  500 7326 frame_2 # Frame 3
  500 6673 frame_1 # Frame 4
  500 5981 frame_0 # Frame 5
  500 6784 frame_0 # Frame 6
  500 8000 frame_1 # Frame 7
  500 8384 frame_2 # Frame 8
  500 8000 frame_3 # Frame 9
  5000 8192 frame_4 # Frame 10
  5000 5184 5376 6336 5632 6272 frame_0..4 # Frame 11
  3000 6784 8000 8384 8000 8192 frame_0..4 # Frame 12
  4000 5184 5376 frame_0_1 # Frame 13
  4000 6784 frame_0 # Frame 14
  4000 8000 frame_1 # Frame 15
  1500 5184 5376 6336 5632 6272 frame_0..4 # Frame 16
  return

sub frame_0..21
  21 servo
  20 servo
  19 servo
  18 servo
  17 servo
  16 servo
  15 servo
  14 servo
  13 servo
  12 servo
  11 servo
  10 servo
  9 servo
  8 servo
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_0
  0 servo
  delay
  return

sub frame_1
  1 servo
  delay
  return

sub frame_2
  2 servo
  delay
  return

sub frame_3
  3 servo
  delay
  return

sub frame_4
  4 servo
  delay
  return

sub frame_0..4
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_0_1
  1 servo
  0 servo
  delay
  return

sub frame_1_2
  2 servo
  1 servo
  delay
  return

sub frame_2_3
  3 servo
  2 servo
  delay
  return

sub frame_3_4
  4 servo
  3 servo
  delay
  return

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

Hello.

Can you describe what you are trying to have your script do, and what it is actually doing right now? How do you want the buttons to function? It looks like you added some logic for your second button to the wait_for_button_press, wait_for_button_open_10ms and wait_for_button_closed_10ms, but it is not clear if you want to wait for either button to be pressed, or if you want the buttons to work independently in some way.

Brandon

Hi Brandon,

Thanks for your help. All I need this script to do is:

  • wait for either button to be pressed
  • if button 1 is pressed Sequence 1 plays
  • if button 2 is pressed Sequence 2 plays
  • after either Sequence is finished system goes back to the top, waiting for a button press

Stupid simple, I know…

Cheers

It looks like you based your script off of the “Using a button or switch to control servos” example in the “Example Scripts” section of the Maestro user’s guide. The method shown in the “Using multiple buttons or switches to control servos” example is probably a better starting point for what you are doing. This example monitors three buttons, each triggering a different subroutine before returning to monitoring the buttons again, so you would need to remove one button and sequence combination since you only have two.

Brandon

Hi Brandon,

Yes, you are correct. I didn’t see the multiple button example underneath it, thank you.
I have been staring at the screen now for waaaay too long and still am getting errors. Can you spot them? There are 5 servos taking up channel 0-4 on the maestro. TIA!

goto main_loop    # Run the main loop when the script starts (see below).
 
sub wait_for_button_press
  wait_for_button_open_10ms
  wait_for_button_closed_10ms
  return

# When the script is not doing anything else,
# this loop will listen for button presses.  When a button
# is pressed it runs the corresponding sequence.
begin
  button_a if Sequence_1 endif
  button_b if Sequence_2 endif
repeat
 
# These subroutines each return 1 if the corresponding
# button is pressed, and return 0 otherwise.
# Currently button_a is assigned to channel 0, 
# button_b is assigned to channel 1, and
# button_c is assigned to channel 2.
# These channels must be configured as Inputs in the
# Channel Settings tab.
sub button_a
  22 get_position 500 less_than            #button_a is ch22 on maestro
  return
 
sub button_b
  23 get_position 500 less_than            #button_b is ch23 on maestro
  return
 
 
# These subroutines each perform an arbitrary sequence
# of servo movements.  You should change these to fit
# your application.
sub Sequence_1
  500 6784 frame_0 # Frame 1
  500 8000 frame_1 # Frame 2
  500 8384 frame_2 # Frame 3
  500 8000 frame_3 # Frame 4
  500 8192 frame_4 # Frame 5
  500 6272 frame_4 # Frame 6
  500 5632 frame_3 # Frame 7
  500 6336 frame_2 # Frame 8
  500 5376 frame_1 # Frame 9
  500 5184 frame_0 # Frame 10
  2000 6784 8000 8384 8000 8192 frame_0..4 # Frame 11
  1000 5184 5376 6336 5632 6272 frame_0..4 # Frame 12
  1500 6784 8000 8384 8000 8192 frame_0..4 # Frame 13
  1500 5184 5376 6336 5632 6272 frame_0..4 # Frame 14
  500 6784 8000 frame_0_1 # Frame 15
  500 5376 8384 frame_1_2 # Frame 16
  500 6336 8000 frame_2_3 # Frame 17
  500 5632 8192 frame_3_4 # Frame 18
  500 6272 frame_4 # Frame 19
  500 6826 7460 6923 7326 frame_1..4 # Frame 20
  1000 5376 6336 5632 6272 frame_1..4 # Frame 21
  1000 8000 8384 8000 8192 frame_1..4 # Frame 22
  1000 6750 7423 6880 7284 frame_1..4 # Frame 23
  200 5376 frame_1 # Frame 24
  200 6336 frame_2 # Frame 25
  200 5632 frame_3 # Frame 26
  200 6272 frame_4 # Frame 27
  return

   
sub Sequence_2
  500 7228 frame_4 # Frame 1
  500 6785 frame_3 # Frame 2
  500 7326 frame_2 # Frame 3
  500 6673 frame_1 # Frame 4
  500 5981 frame_0 # Frame 5
  500 6784 frame_0 # Frame 6
  500 8000 frame_1 # Frame 7
  500 8384 frame_2 # Frame 8
  500 8000 frame_3 # Frame 9
  5000 8192 frame_4 # Frame 10
  5000 5184 5376 6336 5632 6272 frame_0..4 # Frame 11
  3000 6784 8000 8384 8000 8192 frame_0..4 # Frame 12
  4000 5184 5376 frame_0_1 # Frame 13
  4000 6784 frame_0 # Frame 14
  4000 8000 frame_1 # Frame 15
  1500 5184 5376 6336 5632 6272 frame_0..4 # Frame 16
  return
 
# An example of how to use wait_for_button_press is shown below:
 
# Uses WAIT_FOR_BUTTON_PRESS to allow a user to step through
# a sequence of positions on servo 1.
main_loop:
begin
  wait_for_button_press          # call subroutine before executing sequence
repeat


#  wait_for_button_press
  1 servo
  return



#PERCY PROGRAMS

### Sequence subroutines: ###

# Sequence 1
sub Sequence_1
  500 5184 5376 6336 5632 6272 0 
  0 0 0 0 0 0 
  0 0 0 0 0 0 
  0 0 0 0 frame_0..21 # Frame 0
  500 6784 frame_0 # Frame 1
  500 8000 frame_1 # Frame 2
  500 8384 frame_2 # Frame 3
  500 8000 frame_3 # Frame 4
  500 8192 frame_4 # Frame 5
  500 6272 frame_4 # Frame 6
  500 5632 frame_3 # Frame 7
  500 6336 frame_2 # Frame 8
  500 5376 frame_1 # Frame 9
  500 5184 frame_0 # Frame 10
  2000 6784 8000 8384 8000 8192 frame_0..4 # Frame 11
  1000 5184 5376 6336 5632 6272 frame_0..4 # Frame 12
  1500 6784 8000 8384 8000 8192 frame_0..4 # Frame 13
  1500 5184 5376 6336 5632 6272 frame_0..4 # Frame 14
  500 6784 8000 frame_0_1 # Frame 15
  500 5376 8384 frame_1_2 # Frame 16
  500 6336 8000 frame_2_3 # Frame 17
  500 5632 8192 frame_3_4 # Frame 18
  500 6272 frame_4 # Frame 19
  500 6826 7460 6923 7326 frame_1..4 # Frame 20
  1000 5376 6336 5632 6272 frame_1..4 # Frame 21
  1000 8000 8384 8000 8192 frame_1..4 # Frame 22
  1000 6750 7423 6880 7284 frame_1..4 # Frame 23
  200 5376 frame_1 # Frame 24
  200 6336 frame_2 # Frame 25
  200 5632 frame_3 # Frame 26
  200 6272 frame_4 # Frame 27
  return
# Sequence 2
sub Sequence_2
  500 5184 5376 6336 5632 6272 0 
  0 0 0 0 0 0 
  0 0 0 0 0 0 
  0 0 0 0 frame_0..21 # Frame 0
  500 7228 frame_4 # Frame 1
  500 6785 frame_3 # Frame 2
  500 7326 frame_2 # Frame 3
  500 6673 frame_1 # Frame 4
  500 5981 frame_0 # Frame 5
  500 6784 frame_0 # Frame 6
  500 8000 frame_1 # Frame 7
  500 8384 frame_2 # Frame 8
  500 8000 frame_3 # Frame 9
  5000 8192 frame_4 # Frame 10
  5000 5184 5376 6336 5632 6272 frame_0..4 # Frame 11
  3000 6784 8000 8384 8000 8192 frame_0..4 # Frame 12
  4000 5184 5376 frame_0_1 # Frame 13
  4000 6784 frame_0 # Frame 14
  4000 8000 frame_1 # Frame 15
  1500 5184 5376 6336 5632 6272 frame_0..4 # Frame 16
  return

sub frame_0..21
  21 servo
  20 servo
  19 servo
  18 servo
  17 servo
  16 servo
  15 servo
  14 servo
  13 servo
  12 servo
  11 servo
  10 servo
  9 servo
  8 servo
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_0
  0 servo
  delay
  return

sub frame_1
  1 servo
  delay
  return

sub frame_2
  2 servo
  delay
  return

sub frame_3
  3 servo
  delay
  return

sub frame_4
  4 servo
  delay
  return

sub frame_0..4
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

sub frame_0_1
  1 servo
  0 servo
  delay
  return

sub frame_1_2
  2 servo
  1 servo
  delay
  return

sub frame_2_3
  3 servo
  2 servo
  delay
  return

sub frame_3_4
  4 servo
  3 servo
  delay
  return

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

Thank you for posting your updated code. It looks like you still have a lot of code left over from your original script that is causing problems. For example, because your code starts with the goto main_loop command your script never reaches your new BEGIN/REPEAT loop that checks your two buttons. You should remove the following portions of leftover code:

goto main_loop    # Run the main loop when the script starts (see below).
 
sub wait_for_button_press
  wait_for_button_open_10ms
  wait_for_button_closed_10ms
  return

and

main_loop:
begin
  wait_for_button_press          # call subroutine before executing sequence
repeat


#  wait_for_button_press
  1 servo
  return

Additionally, you now have sub Sequence_1 and sub Sequence_2 each defined twice. If you intended to have 4 different subroutines, they should all have unique identifiers. Otherwise, you should determine which of these are the intended subroutines and remove or comment out the two others.

Brandon

Brandon, you are a steely-eyed-missile man! That did it, thanks again for the help.

Quick question: program is working fine but input (ch 22 and 23, push buttons, simple) is very, very sensitive. To the point where without attaching anything to those pins but simply touching them with my finger give a noisy spazm that shows in the control center status window.

My guess is I am missing a known tip (that I can’t find) on using a resistor of a known value to calm this input down.

Help!

And thank you!

From your description it sounds like you might have connected your buttons in a way that doesn’t use pull-up resistors, as shown in the “Button or switch” heading of the “Attaching Servos and Peripherals” section in the Maestro user’s guide. If you did connect your buttons per the instructions in the user’s guide, and it is still very sensitive, can you post some pictures that show your connections?

Alternatively, since you have a 24-channel Maestro, you could check the “Enable pull-ups on channels 18-20” check box in the “Channel Settings” tab of the Maestro Control Center to use internal pull-up resistors and move your buttons to two of those channels, connecting between the signal pin and ground. Please note that you would need to change the pin numbers to reflect this change in your script as well.

Brandon

By the looks of it, grayfxman is trying to accomplish the same as I am.
I have a 24 channel Maestro set up to control two servos, using two scripts, triggered by two buttons.
My problem is, that I’m encountering some outside interference, which sometimes triggers the inputs.
I’ve been trying to overcome this by adding a debounce routine as mentioned in the “Using a button or switch to control servos” example to the “Using multiple buttons or switches to control servos” example. But I keep getting error messages.
Could you please steer me in the right direction in how to debounce multiple buttons?

I just followed Brandon’s advice (used channel 19 and 20 in my case) and it worked perfectly.

Yes, but you took out most of the debouncing in your second attempt and Brandon told you to take out what was left of it. I tried to include the debouncing code and make it work for two buttons, but couldn’t get it to work.

Hello, Micropuller.

There are probably multiple ways you could go about doing something like that. If you want the subroutines to wait for a specific button to be pressed, one option might be to duplicate the button, wait_for_button_press, wait_for_button_open_10ms, and wait_for_button_closed_10ms subroutines in the “Using a button or switch to control servos” example script and modified the duplicates to work for a button on a different channel (please note that you would need to modify the names of the duplicate subroutines as well). It might be more efficient to try modifying those subroutines so you can pass them a channel number, so you could use the same subroutines for both buttons. However, if you want to monitor both buttons and run a different sequence depending on which button is pressed (essentially behaving like the Using multiple buttons or switches to control servos example, but with debouncing), you will likely need a different approach.

I came up with the subroutine below to check an input channel for a button press and do some debouncing. It needs to be passed the channel number of the button, so you can use this same subroutine for both of your inputs (e.g. 0 button_debounce would check the input on channel 0). This subroutine should return 1 if the button has been pressed for the debouncing time (I used 100 in the sample), and 0 if the button is released before that time. Please note that the program will stay in the subroutine for the duration of the debouncing time if the button is being pushed the whole time.

sub button_debounce
  get_ms  #get current time and put it on stack
  begin
    swap dup get_position 500 less_than     #check if specified button is pressed
    if
      swap get_ms over minus 100 greater_than  #return 1 if it has been pressed for 100ms+
      if drop drop 1 return endif
    else     #if button is released before specified time return 0
      drop drop 0 return
    endif
repeat    #if button is still being held and it has not been 100ms repeat subroutine

Brandon

Thanks! I’ll try that tomorrow!

Brandon, I can’t thank you enough, that worked a treat!

1 Like