Micro Maestro 6, Shiftbrite, Servo, Button Circuit Help

I picked up a project I started last year, creating a circuit and code that would use a Micro Maestro 6, 2 Shiftbrites, a servo, and 2 buttons. FYI, I am still learning some of the fundamentals of coding for the Maestro.

I my daisychained shiftbrites are on channel 0, 1, and 2, my servo is on channel 3, and my buttons are on channel 4 and 5. I would like to be able to push one button and have it cycle through some different colors with each press. I would like the other button to move a servo and alternate the shiftbrites on/off with each press.

Using the example resources I have successful programmed everything to work on it’s own, meaning I can get the servo to move, the buttons to function, and the shiftbrites to light up on their own.

I am using the Multiple Button code example, the Shiftbrite code example, and a servo code example but I am not sure how to integrate them all together and could use some help via more examples of similar type code or guides. I remember seeing something last year about coding an LED to turn on, turn off, blink, etc. but I cannot find that anymore, does anyone have examples of that as well?

I will post my existing code when I get home from work tonight. Thank you.

I continued to play around with my code last night and got the switches to active their respective devices.

The area I am still confused with is cycling through different routines on each button press. I feel like I need to have the code execute a routine on the button press, then add a value to the stack somewhere. Depending on what the value is on the stack would determine which routine would be run. If this is indeed what I need to do then where in the stack should that value go? Maybe on the bottom so that it is not consumed and can be used later.

What about the fact that I want to have 2 buttons doing this? Does that mean 2 places in my stack will be my value holders? I will continue to experiment with my code and see what kind of results I can come up with.

Edit: I threw together a basic example code for cycling through 3 different patterns upon each button press. Do I have the right idea? I do not have my Maestro with me now so I cannot test it.

begin
  3  #Number to be consumed?  For 3 different cycles
  BUTTON_A if SEQUENCE_A endif
repeat

sub BUTTON_A
  4 get_position 500 less_than #get state of the button
  return

sub SEQUENCE_A
  begin dup while #copies the value until value =0
   if
    3 equals goto FIRST_PATTERN else
    2 equals goto SECOND_PATTERN else
    1 equals goto THIRD_PATTERN else
   endif
   1 miNUS
  return

#Pattern subroutines would follow

I know this is probably a very inefficient code, would anyone have a better alternative to this? And how would I make 2 of these be able to operate together and still save each ones value to the stack

The code you wrote above will not work. Every time line 2 (the line that just has “3” on it) is executed, the Maestro will add the number 3 to the stack. Since there is no corresponding code to drop 3 from the stack, your stack will quickly fill up and overflow.

You could try writing your code in a blocking way like this:

begin
  wait_for_button_press
  sequence_a
  wait_for_button_press
  sequence_b
  wait_for_button_press
  sequence_c
repeat

You would need to copy and modify some code from the “Using a button or switch to control servos” example in the “Example scripts” section of the Maestro User’s Guide to get this to compile.

Unfortunately, it might be hard to extend this code to work with the second button.

–David

Stepping the code out makes since, I will definitely have to try it that way. I also understand what you mean about this not working with 2 separate cycle sequences.

I have seen example codes using if statements to test values, but is there a way to test for button presses and go to respective sequences as a result?

Yes. The condition of an if statement can be the state of a button, and the effect of an if statement can be to launch a sequence, if that’s what you want to do.

–David

I’ve got some code working but I do not think I am using the IF statements properly. When I run this code and press the button_light I get a stack over/underflow error, but I’m not sure from where.

Looking for advice if anyone has any. BTW, this controller will be for an Iron-man helmet to open and close the faceplate and turn the eyes on and off.

#####################################################################
##########  MY CODE FOR IM HELMET FACEPLATE AND EYES V.01  ######
###################################################################
###### HARDWARE SETUP ##############
## CHANNEL 0 = FIRST EYE LEDs (OUTPUT)
## CHANNEL 1 = SECOND EYE LEDS (OUTPUT)
## CHANNEL 2 = Not Used
## CHANNEL 3 = SERVO (SERVO)
## CHANNEL 4 = BUTTON_LIGHT (INPUT)
## CHANNEL 5 = BUTTON_DARK (INPUT)
##############
###### ORDER OF OPERATIONS#########
## STARTUP NO ROUTINES RUN, SYSTEM WAITS FOR BUTTON PRESSES
## WHEN BUTTON_LIGHT IS PRESSED IT CYCLES EYES WHITE_ON, BLUE_ON, ORANGE_ON, BLUE/ORANGE FLASH, OFF
## WHEN BUTTON_DARK IS PRESSED IT TURNS EYES OFF & OPENS FACEPLATE, CLOSES FACEPLATE & TURNS EYES ON#
#####################################################################################################


#*************************BEGIN CODE HERE************************#
########### Multiple Button code##################################
# 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.  I tried to integrate bouncing code

 0 0 servo
 6000 3 servo
begin
 goto EYES-OFF-FACE-CLOSED
repeat


EYES-OFF-FACE-CLOSED:
 wait_for_button_light_press if eyes_on endif goto EYES-ON-FACE-CLOSED #if button A is pressed it runs sequence A
 wait_for_button_dark_press if face_open endif goto EYES-OFF-FACE-OPEN #"
 return

EYES-OFF-FACE-OPEN:
 wait_for_button_dark_press if face_closed endif goto EYES-ON-FACE-CLOSED #"
 return

EYES-ON-FACE-CLOSED:
 wait_for_button_light_press if eyes_off endif goto EYES-OFF-FACE-CLOSED #if button A is pressed it runs sequence A
 wait_for_button_dark_press if face_open endif goto EYES-OFF-FACE-OPEN #"
 return
         
#~~~~WORKING SINGLE EYE LIGHT (test 2nd)~~~~~
#This light has a flicker on and off
sub eyes_on
 6100 0 servo
 30 delay
 0 0 servo
 25 delay
 6100 0 servo
 20 delay
 0 0 servo 
 15 delay
 6100 0 servo
 return

sub eyes_off
 0 dup 0 servo 1 servo
 15 delay
 6100 dup 0 servo 1 servo
 20 delay
 0 dup 0 servo 1 servo
 return

#Code for faceplate is still WIP
sub face_open
 #Enter servo code to open face
 eyes_off
 return

sub face_closed
 #Enter servo code to close face
 eyes_on
 return

#Button bouncing subs
# 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_light_press          #routine for button to be pressed
 wait_for_button_light_open_10ms         #these check for bouncing
  wait_for_button_light_closed_10ms 
  return

sub wait_for_button_dark_press          #routine for button to be pressed
 wait_for_button_dark_open_10ms         #these check for bouncing
  wait_for_button_dark_closed_10ms 
  return
  
# Wait for the button to be NOT pressed for at least 10 ms. 
sub wait_for_button_light_open_10ms 
  get_ms # put the current time on the stack 
  begin
    # reset the time on the stack if it is pressed 
    button_light
    if
      drop get_ms
    else
      get_ms over minus 10 greater_than
      if drop return endif
    endif
  repeat

sub wait_for_button_dark_open_10ms 
  get_ms # put the current time on the stack 
  begin
    # reset the time on the stack if it is pressed 
    button_dark
    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_light_closed_10ms 
  get_ms
  begin
    # reset the time on the stack if it is not pressed 
    button_light
    if
      get_ms over minus 10 greater_than
      if drop return endif
    else
      drop get_ms
    endif
  repeat

sub wait_for_button_dark_closed_10ms 
  get_ms
  begin
    # reset the time on the stack if it is not pressed 
    button_dark
    if
      get_ms over minus 10 greater_than
      if drop return endif
    else
      drop get_ms
    endif
  repeat

Your problem is that “wait_for_button_light_press” does not add a value to the stack, so there is no value for “if” to consume/test. This would cause a stack underflow. Do you understand what wait_for_button_light_press is supposed to do? Why did you write “if” after it?

After you fix that, you will run into another problem because of this code that you wrote at the top of your script:

begin
goto EYES-OFF-FACE-CLOSED
repeat

EYES-OFF-FACE-CLOSED:
...
return

There is nowhere to return to, so there will be a call stack underflow at that point. I would simplify it to this:

begin
...
repeat

–David