Multitasking for Maestro Servo Controller

Dear Pololu Forum,

I use the Maestro Servo Controller controlled by a PC since a while to automize a model railway including self driving cars.
Now I tried to run the car controll as a script on a 24-Channel controller. Therefore I need a kind of multitasking feature.
The code snipped added as example shows a part of the complete script, where e.g. 2 bus-stopps are included, each wich a huge delay.
How can I controll the other actors by connected button, while the delay blocks teh script?

# this loop will listen for buttons beeing pressed.When a button
# is pressed it runs the corresponding sequence.
begin
  sensor_1 if actor0_toggle endif
  sensor_2 if actor1_toggle endif
  sensor_3 if actor2_toggle endif
  sensor_4a if sequence_bus_stopp1 endif
  sensor_4b if sequence_bus_stopp1 endif
  sensor_5 if sequence_bus_stopp2 endif
repeat
 
# These subroutines each return 1 if the corresponding
# button is pressed, and return 0 otherwise.
# sensor_1 at channel 18
# sensor_2 at channel 19
# sensor_3 at channel 20
# sensor_4a at channel 21
# sensor_4b at channel 22
# sensor_4c at channel 23
sub sensor_1 
  18 get_position 500 less_than
return
sub sensor_2 
  19 get_position 500 less_than
return
sub sensor_3 
  20 get_position 500 less_than
return
sub sensor_4a 
  21 get_position 500 greater_than
return
sub sensor_4b 
  22 get_position 500 greater_than
return
sub sensor_5 
  23 get_position 500 less_than
return

#----------------------------------------------
# Subroutines defining actions to be perfomed
sub actor0_toggle
  0 get_position    # get position of servo 0
  6005 less_than  # if true -> 1, if false ->0
  if
   7000 0 servo
  else
   5000 0 servo
  endif
return
sub actor1_toggle
  1 get_position    # get position of servo 
  6005 less_than  # if true -> 1, if false ->0
  if
   7000 1 servo
  else
   5000 1 servo
  endif
return
sub actor2_toggle
  2 get_position    # get position of servo
  6005 less_than  # if true -> 1, if false ->0
  if
   7000 2 servo
  else
   5000 2 servo
  endif
return
sub sequence_bus_stopp1
  7000 3 servo    #set switch to park lane
  7000 4 servo     #set stopp
  1500 delay
  5000 3 servo    #reset switch
  30000 delay
  5000 4 servo    #reset stopp
return
sub sequence_bus_stopp2
  7000 5 servo     #set stopp
  30000 delay
  5000 5 servo    #reset stopp
return

Best regards
Chris

Hello, Chris.

It is possible to do what you described by replacing your blocking DELAY commands with some code that uses the non-blocking GET_MS command to keep track of how much time has passed. The GET_MS command puts the current value of the millisecond timer on the stack. It might be difficult to keep track of multiple non-blocking delays at once, so I would suggest starting with getting one working first. You can see an example of how to do non-blocking code in a Maestro script in this post by Jon. Reading though the example in my post in this thread might be helpful as well.

If you try changing your delays into non-blocking delays and run into problems, you can post your updated script here, and I would be glad to take a look.

Brandon

Hellon BrandonM,

thanks for the hint to get_ms.
I realized to separate waiting loops in the following script, it´s working fine!

#initialize 

60	  # waiting time for bus stopp1 in seconds
0       # stack-place for timer bus stopp1
30	  # waiting time for bus stopp2 in seconds
0	  # stack-place for timer bus stopp2
0       # initialize seconds_timer, how many seconds have elapsed
get_ms  # initialize current_time_elapsed 

 
# this loop will listen for buttons beeing pressed.When a button
# is pressed it runs the corresponding sequence.
begin
  seconds_timer_update
  sensor_1 if actor0_toggle endif
  #sensor_2 if actor1_toggle endif
  #sensor_3 if actor2_toggle endif
  sensor_4a if sequence_bus_stopp1_set endif
  sensor_4b if sequence_bus_stopp1_set endif
  sequence_bus_stopp1_reset
  sensor_5 if sequence_bus_stopp2_set endif
	  sequence_bus_stopp2_reset	
repeat
 
# These subroutines each return 1 if the corresponding
# button is pressed, and return 0 otherwise.
# sensor_1 at channel 18
# sensor_2 at channel 19
# sensor_3 at channel 20
# sensor_4a at channel 21
# sensor_4b at channel 22
# sensor_5 at channel 23

sub seconds_timer_update
  # counts the seconds since started
  begin
    get_ms 1 pick minus 1000 greater_than while
    1000 plus         # (current_time_elapsed += 1000)
    swap 1 plus swap  # (seconds_timer += 1)      	
  repeat
return

sub sensor_1 
  18 get_position 500 less_than
return

sub sensor_2 
  19 get_position 500 less_than
return

sub sensor_3 
  20 get_position 500 less_than
return

sub sensor_4a 
  21 get_position 500 greater_than
return

sub sensor_4b 
  22 get_position 500 greater_than
return

sub sensor_5 
  19 get_position 500 less_than
return

#----------------------------------------------
# Subroutines defining actions to be perfomed
sub actor0_toggle
  0 get_position	# get position of servo 0
  6005 less_than  # if true -> 1, if false ->0
  if
   7000 0 servo
  else
   5000 0 servo
  endif
return
sub actor1_toggle
  1 get_position	# get position of servo 
  6005 less_than  # if true -> 1, if false ->0
  if
   7000 1 servo
  else
   5000 1 servo
  endif
return
sub actor2_toggle
  2 get_position	# get position of servo
  6005 less_than  # if true -> 1, if false ->0
  if
   7000 2 servo
  else
   5000 2 servo
  endif
return
sub sequence_bus_stopp1_set
  4 get_position 6000 less_than	#bus stopp1 reset
  if  
    7000 3 servo	#set switch to park lane
    7000 4 servo 	#set stopp
	    1500 delay
    5000 3 servo	#reset switch
    4 peek 1 poke	#store actual time for stopp1 set
  endif
return
sub sequence_bus_stopp1_reset
  4 get_position 6000 greater_than	#bus stopp1 set
  if
    1 peek 0 peek plus	#stored stop time plus waiting time
    4 peek swap greater_than 	# greater than actual time
    if 
     5000 4 servo	#reset stopp1
     0 1 poke		#reset stored time for stopp1 
    endif
  endif
return

sub sequence_bus_stopp2_set
  5 get_position 6000 less_than	#bus stopp2 reset
  if
    7000 5 servo 	#set stopp
    4 peek 3 poke	#store actual time for stopp2 set
  endif
return
sub sequence_bus_stopp2_reset
  5 get_position 6000 greater_than	#bus stopp2 set
  if
    3 peek 2 peek plus	#stored stop time plus waiting time
    4 peek swap greater_than 	# greater than actual time
    if 
	     5000 5 servo 	#reset stopp2
     0 3 poke		#reset stored time for stopp2
    endif
  endif
return

1 Like

I am glad you were able to get it working! Thank you for letting us know and sharing your code.

Brandon