I need help Pololu mini maestro 6 channel multiple buttons

Hello! I have 6 channel maestro and I have attached 3 momentary buttons to operate 3 servos. These are all operational as viewed in the control center with attached resistors and are wired correctly.

I want the start position for each controller to be 752 (min) - I selected this setting in the Control Center so it is not in the script. When I push the button for the first time, I want the servo to go to 1264 (max) - I also selected this setting in the Control Center so it is not in the script. When I push the button the second time, I want the servo to go back to the original 752 (min) when pushed a third time I want the servo to go to 1264 (max) etc.

When I start the script below, buttons A and B will work once, thereafter only button c works and button c continues to work every time I push it going back and forth to the two positions as desired but the other 2 buttons will not work again until I restart the script. I would like to be able to press any button at any time and have it work and take the servo back to the previous setting. I have copied the script below. Can you take a look and let me know what I need to do?

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_a_press
  wait_for_button_a_open_10ms
  wait_for_button_a_closed_10ms
  return

# Wait for the button to be NOT pressed for at least 10 ms.
sub wait_for_button_a_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 10 ms.
sub wait_for_button_a_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
  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
  7822 frame
  3084 frame
repeat

sub frame
  wait_for_button_a_press
  1 servo

goto second_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 buttonb
  2 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_buttonb_press
  wait_for_buttonb_open_10ms
  wait_for_buttonb_closed_10ms
  return

# Wait for the button to be NOT pressed for at least 10 ms.
sub wait_for_buttonb_open_10ms
  get_ms # put the current time on the stack
  begin
    # reset the time on the stack if it is pressed
    buttonb
    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_buttonb_closed_10ms
  get_ms
  begin
    # reset the time on the stack if it is not pressed
    buttonb
    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.
second_loop:
begin
  7822 second
  3084 second
repeat

sub second
  wait_for_buttonb_press
  3 servo

goto third_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 buttonc
  4 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_buttonc_press
  wait_for_buttonc_open_10ms
  wait_for_buttonc_closed_10ms
  return

# Wait for the button to be NOT pressed for at least 10 ms.
sub wait_for_buttonc_open_10ms
  get_ms # put the current time on the stack
  begin
    # reset the time on the stack if it is pressed
    buttonc
    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_buttonc_closed_10ms
  get_ms
  begin
    # reset the time on the stack if it is not pressed
    buttonc
    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.
third_loop:
begin
  7822 third
  3084 third

repeat

sub third
  wait_for_buttonc_press
  5 servo
  return

Thanks!!!

Alan
801-660-8464

Hello.

I noticed the target position values you mention wanting your servos to move between do not match what you have in your script. For example, you say you want one position to be 752 microseconds (which is 3008 quarter microseconds), but in your script you use 3084 quarter microseconds. The same discrepancy is true for the other value you mention.

It looks like your script has several nested BEGIN...REPEAT loops inside of several layers of subroutines, and it sounds like it is getting stuck in the last loop, where only button C is being checked. It will probably be easier to start with the “Using multiple buttons or switches to control servos” example, found in the “Example Scripts” section of the Maestro controller’s user’s guide. That example shows how to use three buttons (button_a, button_b, and button_c) to trigger three different sequence (sequence_a, sequence_b, and sequence_c) at any point. It sounds like the only things you would need to change are the channel numbers to make them match your setup and the sequences. Since you just want your servos to toggle between two positions, you can have the sequence check what position the servo is in and change it accordingly. For example, you might change sequence_a to look like this:

 sub sequence_a
  1 get_position  #check the position of servo 1
  
  3084 equals if  #see if it is equal to 3084
    7822          #if it is, set new target of 7822
  else
    3084          #if it is not, set new target of 3084
  endif
  
  1 servo         #send the target position to servo 1
return

Please note that the example script I mentioned does not use the button debouncing subroutines since it uses somewhat long delays. From your description it sounds like your script might not use delays, so you might want to add the button debouncing to it too.

Also, you can initialize your servos to the starting position at the beginning of your code (e.g. in the example code I mentioned, you can call 3084 1 servo to set servo 1 to a starting point before the rest of your script starts). If they are not initiated to this position, the subroutine I posted above will send the servo to this position the first time it is called.

-Brandon

Brandon,

I did all that you suggested but I still cannot get more than one button to work more than once. The more simple, multi button coding posting on your site does not allow any button to be pushed at any time in any order. Can you take a look at the code and see if you can see something else I can try?

Thanks!

Alan

The “Using multiple buttons or switches to control servos” example that I mentioned in my previous post should accept button presses in any order. The restriction to this code is that while one sequence is running (e.g. the code within the sequence_a subroutine), button presses will be ignored. However, in your application, the subroutines should be very short, and for most practical uses, that code should work the way you described.

Could you post your new modified script?

-Brandon