Servos only reacting when script is stepped

Hi everyone,

I have used the Micro Maestro and an RC Switch to build a gear door sequencer for an RC airplane. I am using a subroutine to open the gear doors, then extend the gear and close the doors on the main landing gear afterwards. A second subroutine executes the sequence in reverse to retract the landing gear.
I am using a not very elegant set of nested if statements to determine the position of the landing gear switch and whether it has changed state since the last loop. That part works fine and I am reasonably happy with it.
The part that I am experiencing some trouble with is when I set the gear door servos (1-4) to 0 at the end of each subroutine.I am doing this to have the gear door servos unpowered in flight because I am using a pneumatic ladning gear that automatically extends in case of a pressure drop and I don’t want the servos working against the landing gear in that case.

The issue starts after the first call of either subroutine (extend or retract) i.e. after the servos have been turned off for the first time in the script.
If I step through the script manually, the servos work but the speed command seems to be ignored as they move at full speed although I added a speed command for each servo in each subroutine. AM I seeing this behavior since the servos are off when I run the speed command?
The other issue I am having is when I run the script, the servos just stop working after they have been set to 0 for the first time.

I am not sure why I am seeing different behaviors when running vs. stepping the script so I would be very appreciative for any input.

Thanks in advance!
Nick

Here’s my script:

  0 3000 3968 8128 3968 3968 8000 initial_position # initial servo positions plus 0 to run the first loop


begin # Start loop

5 get_position 200 GREATER_THAN #get switch position and check if it is active
dup #duplicate current state to compare against in next loop
rot #rotate values on stack so duplicate is on the bottom for use in next loop
not_equals if #check if current switch position and last switch position are unequal --> switch state has changed
5 get_position # Get position of RC switch on channel 5
200 greater_than # if switch is in retracted position (>200)
  
if # then
retract_gear # retract landing gear,
else 
extend_gear # extend landing gear
endif
endif

repeat 



sub extend_gear
#3000 3968 8128 3968 3968 8000
  50 4 speed
  8000 4 servo
  50 3 speed
  3968 3 servo
  50 2 speed
  3968 2 servo
  50 1 speed
  8128 1 servo
  1500 delay
  3968 0 servo
  1500 delay
  3968 4 servo
  8000 3 servo
  0 4 servo
  0 3 servo
  0 2 servo
  0 1 servo
  
  return

sub retract_gear
#3000 8000 3648 8256 8000 3968 frame_0..4 # Frame 2
  50 4 speed
  8000 4 servo
  50 3 speed
  3968 3 servo
  1500 delay
  8000 0 servo
  1500 delay
  3968 4 servo
  8000 3 servo
  50 2 speed
  8256 2 servo
  50 1 speed
  3648 1 servo
  0 4 servo
  0 3 servo
  0 2 servo
  0 1 servo
    return

sub initial_position
  50 4 speed
  4 servo
  50 3 speed
  3 servo
  50 2 speed
  2 servo
  50 1 speed
  1 servo
  delay
  0 servo
  return

Your suspicion that disabling the output on the servo channels (i.e. setting the target to 0) is causing the speed limit to be ignored is correct. The Maestro limits the speed by breaking up the commanded movement into many smaller movements. To calculate this, it has to know the servo’s current position. Since servos do not make their feedback information available, the Maestro assumes it is at the position it is currently commanding it to be at. It does not assume the servo is still at the last commanded position when the servo output is disabled. However, since you know the position they are actually in, one way around this would be to send commands to re-enable the servo channels at their current position (e.g. at the start of your extend_gear subroutine, set the targets to the retracted positions).

By the way, since it looks like you are always using the same speed throughout your entire script, you do not need to keep sending speed commands. The speed command will affect all subsequent movements on the specified channel (as long as the Maestro knows the current position it is in). So, you can either just set it at the beginning or configure the default speed for each channel in the “Channel Settings” tab.

As far as why it seems to work when you step through the script and not when it runs at full speed, I suspect it is because your commands to disable the servo are being sent immediately when the script is running in real-time, which is not giving enough time for the servos to move or reach their commanded positions. Since you are using speed limits on all of your servos, you might consider using the GET_MOVING_STATE command to have your script wait until they stop moving before disabling them. You can see how to do this in the “Making smooth sequences with GET_MOVING_STATE” from the Example Scripts section of the Maestro user’s guide. The moving_wait subroutine from that example will delay until all the servos have reached their target position, so you might try using that and calling it before disabling your servos. A simpler, but less elegant method would be to just add a delay that is long enough to ensure your servos reach their target positions.

Brandon

Hi Brandon,

thanks for the quick reply, this really helped! You were spot on in your assessment!
I ended up following your suggestions and got everything to work the way I expected it to work:
I got rid of delays wherever possible and replaced them with the moving_wait subroutine like you suggested. All servo speed commands are gone from the script to declutter it.

As far as getting the servos to work with the script running, I am now commanding the last servo position prior to 0 before commanding a new position. Initially this caused full speed servo movement again since the script was apparently too quick for the servos to reach their “old” position. Since the servos didn’t have to move to get to the commanded position, I assumed this would be instantenous but I was wrong… Another call of the handy moving_wait subroutine fixed that last remaining bug.

I am posting the current state of the script for reference in case others reading through this conversation at some point in time.

Thanks again for the quick help and Thumbs up for outstanding customer support!!
Regards,
Nick

  0 3968 8128 3968 3968 8000 initial_position # initial servo positions


begin # Start loop

5 get_position 200 GREATER_THAN 
dup
rot
not_equals if #check if stack value and switch position are unequal --> switch state has changed
5 get_position # Get position of RC switch on channel 5
200 greater_than # if switch is in retracted position (>200)
  
if # then
retract_gear # retract landing gear,
else 
extend_gear # extend landing gear
endif
endif
#5 get_position 200 GREATER_THAN # Get position of RC switch on channel 5 to check for state chang in next loop
repeat 



sub extend_gear
#3000 3968 8128 3968 3968 8000
  #set all servos to the previous known position to re-enable them
  3968 4 servo
  8000 3 servo
  8256 2 servo
  3648 1 servo
  moving_wait #wait for servos to finish moving
  #start actual sequence
  8000 4 servo
  3968 3 servo
  3968 2 servo
  8128 1 servo
  moving_wait #wait for servos to finish moving
  3968 0 servo
  1500 delay #wait for pneumatics to do their thing
  3968 4 servo
  8000 3 servo
  moving_wait #wait for servos to finish moving
  #disable all gear door servos
  0 4 servo
  0 3 servo
  0 2 servo
  0 1 servo
  
  return

sub retract_gear
#3000 8000 3648 8256 8000 3968 frame_0..4 # Frame 2
  #set all servos to the previous known position to re-enable them
  3968 4 servo
  8000 3 servo
  3968 2 servo
  8128 1 servo
  moving_wait #wait for servos to finish moving
  #start actual sequence
  8000 4 servo
  3968 3 servo
  moving_wait #wait for main doors to open
  8000 0 servo #actuate valve
  1500 delay #wait for pneumatics to do their thing
  3968 4 servo
  8000 3 servo
  8256 2 servo
  3648 1 servo
  moving_wait #wait for servos to finish moving
  #disable all gear door servos
  0 4 servo
  0 3 servo
  0 2 servo
  0 1 servo
    return

sub initial_position
  4 servo
  3 servo
  2 servo
  1 servo
  moving_wait #wait for servos to finish moving
  0 servo
  
  return

sub moving_wait
  begin
    get_moving_state
  while
    # wait until it is no longer moving
  repeat
  return
1 Like

I am glad you were able to get it working and figure out the new problem that arose; thank you for letting us know and posting your updated script, too!

Brandon