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

Pololu Forum

Maestro 6 channel Subroutine Overflow 0x0080 error

Hi there
I’ve done some reading about this error but I can not find the solution to my script. Probably because I am new to this and I do not understand enough about programming in general :slight_smile: What i do understand is that the 6 channel maestro is limited to 10 subroutines and my subroutines and stack continue to add up as the script is stepped through. I do not understand how to write the script so that is drops each subroutine as it finishes it. Could it be that I just need to upgrade to a 12, 18 or 24 channel maestro. Can someone help me?
Here is my script to my over engineered Sofa Beer Fridge. I have tried to write some #notes so that you understand what I’m trying to do.
thanks Justin

# SOFA BEER FRIDGE CODE
main_loop: 
begin 
start_sequence
repeat quit  
 
### Sequence subroutines: ###
 
sub start_sequence
wait_for_button_closed_10ms
500 3986 3986 3986 frame_3..5 # Frame 0 (ensure all motor switches to open)  
1 get_position 500 greater_than if load_beer else normal_deliver endif  #check proximity sensor if beer is in the delivery draw
return quit

sub load_beer
500 8000 frame_5 # Frame 5 start despencing motor (ready beer in delivery draw)  
2000 delay
1 get_position 500 less_than if normal_deliver endif  # waiting for proximity sensor low (detect beer in draw) 
2000 delay
1 get_position 500 less_than if normal_deliver endif
2000 delay
1 get_position 500 less_than if normal_deliver endif
2000 delay
1 get_position 500 less_than if normal_deliver endif
2000 delay
1 get_position 500 greater_than if 500 3986 frame_5 endif  #If fridge empty, after 10 sec sequence cancelled (There has to be a better way than this)   
start_sequence
return quit

sub normal_deliver
500 3986 frame_5 
wait_for_button1_closed_10ms
500 8000 frame_3# Frame 1 start draw deliver  
check_draw
return quit


sub check_draw
2000 delay
1 get_position 500 greater_than if beer_removed endif
2000 delay
1 get_position 500 greater_than if beer_removed endif
2000 delay
1 get_position 500 greater_than if beer_removed endif
2000 delay
1 get_position 500 greater_than if beer_removed endif
2000 delay
1 get_position 500 less_than if beer_remain endif
return quit
 
sub beer_remain  
500 3986 frame_3 # Frame 2 stop draw deliver 
1000 delay  
500 8000 frame_4 # Frame 3 start draw return
wait_for_button2_closed_10ms
500 3986 frame_4 # Frame 4 stop draw return
start_sequence
return quit


sub beer_removed
500 3986 frame_3 # Frame 2 stop draw deliver
1000 delay  
500 8000 frame_4 # Frame 3 start draw return
wait_for_button2_closed_10ms
500 3986 frame_4 # Frame 4 stop draw return 
1500 delay 
500 8000 frame_5 # Frame 5 start beer ready  
wait_for_button1_closed_10ms
500 3986 frame_5 # Frame 6 
start_sequence
return quit
 
 
sub frame_3..5
  5 servo
  4 servo
  3 servo
  200 delay 
  return quit

sub frame_3
  3 servo
  200 delay
  return quit

sub frame_4
  4 servo
  200 delay
  return quit

sub frame_5
  5 servo
  200 delay
  return quit


#START SWITCH

# 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
    0 get_position 500 less_than
    if
      get_ms over minus 10 greater_than
      if drop return endif
    else
      drop get_ms
    endif
  repeat quit


#PROXIMITY SWITCH
 
# Wait for the button to be pressed for at least 10 ms.
sub wait_for_button1_closed_10ms
  get_ms
  begin
    # reset the time on the stack if it is not pressed
    1 get_position 500 less_than
    if 
      get_ms over minus 10 greater_than
      if drop return endif
    else
      drop get_ms
    endif
  repeat quit

#LIMIT SWITCH

# Wait for the button to be pressed for at least 10 ms.
sub wait_for_button2_closed_10ms
  get_ms
  begin
    # reset the time on the stack if it is not pressed
    2 get_position 500 less_than
    if 
      get_ms over minus 10 greater_than
      if drop return endif  
    else
      drop get_ms
    endif
  repeat quit

Hello.

Note that the 6-channel Maestro can handle 10 levels of recursion (e.g. subroutines calling other subroutines); it is not limited to only 10 subroutines. This should be more than enough to do what you need based on your script, so you should not need to upgrade to a 12-, 18-, or 24-channel Maestro for that reason.

There are essentially 2 problems with now your script is currently set up. One is that extra values are getting left on the stack, which will eventually cause it to overflow. The second is that your subroutines are calling the start_sequence subroutine instead of returning back to it (eventually causing the error when it reaches more than 10 levels of recursion).

Skimming through your script, it looks like a few of your subroutines have hard coded delays, but you are still passing them a value when you call them, causing an extra value to be left on the stack that the subroutine never uses. This seems to be the case for frame_3..5, frame_3, frame_4, and frame_5. For example, frame_3 looks like this:

sub frame_3
  3 servo
  200 delay
  return quit

So when you call it, all you need to do is put the desired target value of servo 3 on the stack, before calling it. It will then move servo 3 to that target and delay for the hard-coded 200ms. However, when you call it, you seem to be putting 2 values on the stack: 500 followed by your set target value (e.g. 500 8000 frame_3 in normal_deliver), so after moving the servo to the set target value and delaying for 200ms, 500 is still there. Depending on how you want it to work, you could either remove the extra 500 when you call these subroutines, or remove the 200 before the delay in the subroutines, which would require you to specify the delay every time you call them.

As far as the recursive subroutine layers, I suggest removing the start_sequence call in your load_beer, beer_remain, and beer_removed subroutines. The return command will send the script back to where the subroutine was called from. This might cause some unwanted behavior from your check_draw subroutine, but that can get handled by rethinking how that subroutine works. If that does happen and you would like some help getting it to work how you want, could you explain how you want it to work compared to how it is currently working and post an updated version of your script?

Brandon