Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

Help Getting Started with Maestro


#1

I am just starting out with the Maestro, and I was hoping someone can point me in the right direction. I just want to create a simple toggle to set all 12 servos to a certain value with a momentary switch. Any help will be much appreciated!


#2

Hello.

You can use the Sequencer feature of the Maestro Control Center to easily create frames that designate the position values for all 12 of your servos before copying it to a script using the “Copy Sequence to Script” button under the “Sequence” tab. For more details about the Sequencer feature, see the “Sequencer” section of the Maestro Servo Controller User’s Guide.

After you creating the two frames for your script to toggle between, you can then merge your script with the “Using a button or switch to control servos” example script, which detects the state of a button or switch and executes the associated motion sequence. You can find that example script under the “Example Scripts” section of the user’s guide.

If you try merging your code with the button example code and run into issues, you can post your modified script here, and I would be happy to take a look.

- Amanda


#3

Hi Amanda,

Thanks for helping me out on this. I’ve done what you suggested, but I can’t seem to get the button working. I’ve wired it up like the instructions say, I’ve confirmed that it is behaving as it should with a multimeter, but it isn’t toggling the values, nor is it showing anything in the status section.

Here’s the code:


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_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
  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
  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
  4000 frame
  5000 frame
  6000 frame
  7000 frame
  8000 frame
repeat
 
sub frame
  wait_for_button_press
  1 servo
  return


# Rec Trigger
begin
  500 3968 3968 3968 3968 3968 3968 
  3968 3968 frame_1..8 # Frame 0
  500 8000 8000 8000 8000 8000 8000 
  8000 8000 frame_1..8 # Frame 1
repeat

sub frame_1..8
  wait_for_button_press
  8 servo
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  delay
  return

Here’s what the status screen shows, no matter what:

Here’s the breadboard:

Here’s the momentary button being closed:


#4

Sorry I posted the wrong code. Here is the code I am using:

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_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
  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
  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
  500 3968 3968 3968 3968 3968 3968 
  3968 3968 frame_1..8 # Frame 0
  500 8000 8000 8000 8000 8000 8000 
  8000 8000 frame_1..8 # Frame 1
repeat

sub frame_1..8
  wait_for_button_press
  8 servo
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  delay
  return

#5

I added code tags to your code in both your posts to make it easier to read. Please format your code in future posts by putting a backtick (`) before and after the code (if it is in the middle of a paragraph) or indenting the code by four spaces (if it is a block of code). You can click on the pencil icon in the upper right-hand corner of your recent post and view the raw source to see how I formated your code.

I did not see anything obviously wrong with your code, so I tried to reproduce the issue, but was unable to. Does the slider on channel 0 toggle between 0 and 255 when you press and release the pushbutton? Do you have the “Run script on startup” option selected under the “Script” tab? The script will not run automatically unless you manually click the “Run Script” button under that tab.

If the problem still continues, can you post the settings file for your Maestro here? You can save the file by selecting “Save settings file…” option under the “File” menu in the Control Center.

- Amanda


#6

Thanks for all your help, Amanda. I purchased another board, and the code is working perfectly. I must have damaged the board some how.


#7

Okay, so now my new board is having the same problem that the old board had. I changed nothing. I only had it unplugged for about a week. I plugged the USB back in, and the button no longer registers, and the servo positions don’t change. I don’t understand what’s going on.

I’ve attached the settings file.

maestro_settings_pushbutton_servo_change.txt (4.6 KB)


#8

I think I’ve figured it out. Here’s my new code:

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
  11 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
  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
  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
  500 5900 5900 5900 5900 5900 5900 
  5900 5900 5900 5900 5900 frame_0..10 # Frame 0
  500 6200 6200 6200 6200 6200 6200 
  6200 6200 6200 6200 6200 frame_0..10 # Frame 1
repeat

sub frame_0..10
  wait_for_button_press
  10 servo
  9 servo
  8 servo
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  return

And here’s my settings file:
maestro_settings_pushbutton.txt (4.7 KB)

One problem I’ve found with this method is that I need a definable transition from one position to the next in order for my device to work. Right now, when I click the button the transition from one value to the next activates my device, so that is good. The problem with with the code is that when i first power up the device, I have to push the button to get to the first value, then push the button again to activate the transition to the next.

My question is: Can I set the board to already have the first value loaded when I initially power up? That way, I can start the transition with the first button press, instead of the second.

Thanks again!


#9

I am glad you were able to narrow down the issue.

You can set the default positions for each servo channel in the Maestro Control Center. To do that, go to the “Channel Settings” tab, select “On startup: Goto”, enter the default position for each channel, and click the “Apply Settings” button in the bottom right corner of the Control Center.

Alternatively, you can set each servo to the default position at the beginning of your script before you jump to main_loop. Although, after looking at your code, I think the easiest way is to call wait_for_button_press after setting all your servos to their positions in the frame_0..10 subroutine like so:

sub frame_0..10
  10 servo
  9 servo
  8 servo
  7 servo
  6 servo
  5 servo
  4 servo
  3 servo
  2 servo
  1 servo
  0 servo
  delay
  wait_for_button_press
  return

- Amanda