2 buttons and 3 servos

Hi! My name is Saso and I received a Micro Maestro a week ago and I am struggling to write a script.

So here it goes:

I have set button_1 on channel 0
button_2 on channel 1
servo_1 on channel 3
servo_2 on channel 4
and servo_3 on channel 5

I want my controller to do this:

If I press button_1 and button_ 2
then servos goes to desired positions

If I press just button_1
then servos goes to second desired positions

If I press just button_2
then servos goes to third desired positions

And if none of the buttons is pressed
then the sequence of movements is played

The program should start with both buttons pressed and end with no buttons pressed

I hope its not to complicated and that you understand what I want
Thanks

Hello, Saso.

I am sorry you are having problems writing your script. If you are trying to have the script wait for you to press a certain button (or combination of buttons), you might try looking at how the wait_for_button_press subroutine handles this in the “Using a button or switch to control servos” heading of the “Example Scripts” section of the Maestro user’s guide. You might also find the “Step script” button in the “Script” tab of the Maestro Control Center helpful for troubleshooting your script.

If those suggestions do not help with the trouble you are having, you can post the script you have so far here, and I would be glad to take a look.

Brandon

Hello Brandon

Thanks for a quick response

I have no experience in scripting or programming at all.

I found something that might be useful from Dante Slo that he posted on this forum.

I am trying to adjust it to my needs becouse its a script for 3 inputs and 4 servos but not succesfully.

What does that mean: Error applying parameters. script:5:17: The Label USER_START was not found.

It sounds like the script you are using has a GOTO command that is trying to send the script to a USER_START label, but it is missing from the code (maybe it was left out when copying over the script or the script you copied was not complete). If you post the script here, I can probably say for sure.

Brandon

I got it, I made the script

The problem was, cos I was using logical_and command totally wrong

In the script you can not say YOU AND ME, insted its YOU ME AND

Hello.

I’m sending you the script if you could add one more thing to it (or maybe explain it to me how)
The Script is written for 1 servo just for testing.

I want to add this to the script:
When button 2 is pressed and button 1 is not pressed for at least 10 seconds the servo goes to the 29th row in the script (the one before it quits)
I’m trying to use goto and get_ms commands.

CHANNELS:
Button 1 on Input 1
Button 2 on Input 2
Servo on Servo 5

“Excuse my stupidity but I don’t know how to upload a script”

THE SCRIPT:

1. begin

2. 1 get_position 1023 equals
3. 2 get_position 1023 equals
4. logical_and
5. if
6. 4000 5 servo
7. endif

8. 1 get_position 1023 equals
9. 2 get_position 512 less_than
10. logical_and
11. if
12. 5000 5 servo
13. endif

14. 1 get_position 512 less_than
15. 2 get_position 1023 equals
16. logical_and
17. if
18. 6000 5 servo
19. endif

20. 1 get_position 512 less_than
21. 2 get_position 512 less_than
22. logical_and
23. if
24. 4500 5 servo 500 delay
25. 5000 5 servo 500 delay
26. 5500 5 servo 500 delay
27. 6000 5 servo 500 delay
28. 6500 5 servo 500 delay
29. 7000 5 servo
30. quit
31. endif

32. repeat

It sounds like you are probably on the right track looking at the get_ms and goto commands. Can you be more specific about how you want the script to behave? Are you describing a script that essentially starts a timer after button 2 is pressed and if the timer reaches 10 seconds before button 1 is pressed it jumps to the ending sequence? Does button 2 need to be held during that 10 seconds? If it helps, you could try writing it out in pseudocode.

Brandon

Yes

If button if button 1 gets depth after its releast (get_position 1 less_than 512) within 10 seconds then the script should behave like it doesent have this command that Im trying to add

I tried putting together some code that does what you described (if I understand it correctly). It is probably not the most optimized way to do this kind of thing, but I used a state variable to detect when button 2 was pressed and also stored the get_ms value on the stack for comparisons. To get the state variable and timing values to work correctly, I added the following line of code before the BEGIN statement to initialize these parameters:

get_ms 1 	# this line of code puts the current time on the stack followed by the state variable defaulted to 1

Then, I added the following code just before the REPEAT command at the end of your script:

dup 2 get_position 512 less_than logical_and if  #This line of code checks if the state variable is 1 and button 2 is pressed
    drop  		#if the statement above is true, drop the current state variable and replace it with 0
    0
 endif

dup logical_not 1 get_position 512 less_than logical_and if  #This checks if the state variable is 0 and button 1 is pressed
  drop  		#if true, set the state variable back to the default of 1
  1
endif

 dup if swap drop get_ms swap endif	#if state variable is true, update the timer

swap dup get_ms minus		#subtract the current time from the stored timer
 dup negative if 			#if negative, make positive
   negate
 endif
   10000 greater_than		#compare it to 10 seconds (10000 ms)
     if  
       goto end			#if greater than 10 seconds, go to the "end" label
     endif
swap

Lastly, I put the end: label just before the command you mentioned (line 29 of your original code).

You might try making those modifications and seeing if that gives you the behavior you wanted. Additionally, you can use the “Step script” button in the “Script” section of the Maestro Control Center to get a better understanding of how the code works, or help figure out where you might need to adjust it.

Brandon

Still not working properly

Try to visualize it like this:

  • We have just one button and the end: in the script is like emergency stop.
  • If butonn is pressed than servo goes to lets say 4000
  • If button is released than servo goes to 5000
  • If button is pressed longer than 10 second servo goes to 6000 (emergency stop)
  • If button is released before 10 seconds servo goes normaly to 5000

Something like this, exept that I want it in reverse (goes to
emergency stop when button is released more than 10 second) and only when
button 2 is pressed.

I think you will understand now.

I am still not entirely sure I understand what you are describing, but the code modifications I suggested should be a good start for doing a non-blocking timer in a Maestro script. Have you tried modifying the additions I suggested to get it working like you want?

Just to make sure the modifications I suggested were copied to your script correctly, they should result in the following behavior after combining it with your original script:

  • if neither button is being pushed, servo 5 goes to 4000
  • if button 2 is pushed (and button 1 is not), servo 5 goes to 5000
  • if button 1 is pushed (and button 2 is not), servo 5 goes to 6000
  • if button 1 and button 2 are pushed at the same time, servo 5 goes through a sequence of movements then the script ends
  • if button 1 is not pressed within 10 seconds after button 2 is pressed, servo 5 goes to 7000 and the script ends

If that is not the behavior you are getting, you can post your current script here, and I would be glad to take a look.

Brandon

Im going nuts with this project:

I dont even know how to do this with one button:
If button is not pressed - servo goes to first position
If button is pressed for 10 seconds - servo goes to second position

Maybe I can start with that. Must I use get_ms or delay on button?

Please help. I think this one is easy for you.

Thanks

Simplifying it down to just one button for now sounds like a good idea. Using get_ms is likely going to be much more practical than a blocking delay, especially since you are going to be adding a second button later.

One way to use the get_ms command for checking a delay like this is to have the current time continuously updating when the button is not pushed, like this:

get_ms #get initial timer value
begin
  1 get_position 512 less_than if    #check if button is pressed
    #the rest of your code goes here				
  else				#if not, drop the current time on the stack and update it with a new one
    drop get_ms			#you can also add your command for sending the servo to the first position here
  endif
repeat

Then, if the button is pressed, you can subtract the current time from the time that was left on the stack. Note that to preserve the value on the stack, you can duplicate it before you use it. Also, to set the parameters for the minus command to the right order, you can use the swap command, like so:

dup get_ms swap minus		#duplicate time on stack and subtract the current time from it

This will place a value on the stack that represents how long the button has been held down in milliseconds, so you can use this to tell if the button has been held down for longer than 10 seconds with another if statement:

1000 greater_than if
  				#you can add your command for sending the servo to the second position here
				#once the button is released, it will go back to the position 1 set above    
endif

As I said in my previous post, if you try modifying or writing your own code that handles this delay, you can post it here, and I would be glad to take a look.

Brandon

OK. I have the script for which it took me 2 weeks and still not satisfied with result.
Sorry I don’t have any comments - and subroutines are names for inputs and outcomes for my application.
Also english is not my native language so I’m having problems with understanding descriptions of commands.
Here is the script:

  1. goto main_loop
  2. sub button_off
  3. 1 get_position 512 less_than
  4. return
  5. sub button_on
  6. 1 get_position 1023 equals
  7. return
  1. #########################################
  2. sub released_10s
  3. release_for_10s
  4. return
  5. sub release_for_10s
  6. get_ms
  7. begin
  8. button_off
  9. if
  10. get_ms over minus 10000 greater_than
  11. if drop return endif
    
  12. else
  13. drop get_ms
  14. endif
  15. repeat
  16. #########################################
  1. #########################################
  2. sub released
  3. release
  4. return
  1. sub release
  2. get_ms
  3. begin
  4. button_off
  5. if
  6. get_ms over minus 10 greater_than
  7. if drop return endif
    
  8. else
  9. drop get_ms
  10. endif
  11. repeat
  12. #########################################
  1. #########################################
  2. sub pulled
  3. pull_and_hold
  4. pull_and_drop
  5. return
  1. sub pull_and_hold
  2. get_ms
  3. begin
  4. button_on
  5. if
  6. drop get_ms
  7. else
  8. get_ms over minus 10 greater_than
  9. if drop return endif
  10. endif
  11. repeat
  1. sub pull_and_drop
  2. get_ms
  3. begin
  4. button_on
  5. if
  6. get_ms over minus 10 greater_than
  7. if drop return endif
    
  8. else
  9. drop get_ms
  10. endif
  11. repeat
  12. #########################################
  1. main_loop:
  2. begin
  3. 4000 DT
  4. 5000 straight
  5. 6000 circle
  6. repeat
  7. sub DT
  8. released_10s
  9. 5 servo
  10. return
  1. sub straight
  2. pulled
  3. 5 servo
  4. return
  1. sub circle
  2. released
  3. 5 servo
  4. return

And now I will explain what the script is not doing right.
I don’t want to wait 10 second to press a button (button_on) if I want a servo to go to 4000

Is there perhaps some other way to write a script for the same thing that I wrote?

Many thanks in advance

Sorry I ment servo go to 5000

How stupid am I.
This post from you would work If I mentioned the most important thing - I’m using pull down resistor on buttons.
Eventualy I think I’ll have to switch to pull up resistor, becouse servos, buttons and maestro will be mounted in carbon fiber casing which is a great conductor and I don’t want any short circuits

This is the working script:

  1. get_ms 1
  1. begin
  1. 1 get_position 1023 equals
  2. 2 get_position 1023 equals
  3. logical_and
  4. if
  5. 4000 5 servo
  6. endif
  1. 1 get_position 1023 equals
  2. 2 get_position 512 less_than
  3. logical_and
  4. if
  5. 5000 5 servo
  6. endif
  1. 1 get_position 512 less_than
  2. 2 get_position 1023 equals
  3. logical_and
  4. if
  5. 6000 5 servo
  6. endif
  1. 1 get_position 512 less_than
  2. 2 get_position 512 less_than
  3. logical_and
  4. if
  5. 4500 5 servo 500 delay
  6. 5000 5 servo 500 delay
  7. 5500 5 servo 500 delay
  8. 6000 5 servo 500 delay
  9. 6500 5 servo 500 delay
  10. end:
  11. 7000 5 servo
  12. quit
  13. endif
  1. dup 2 get_position 1023 equals logical_and if
  2. drop
    
  3. 0
    
  4. endif
  5. dup logical_not 1 get_position 1023 equals logical_and if
  6. drop
  7. 1
  8. endif
  9. dup if swap drop get_ms swap endif
  10. swap dup get_ms minus
  11. dup negative if
  12. negate
  13. endif
  14. 10000 greater_than
  15.  if  
    
  16.    goto end
    
  17.  endif
    
  18. swap
  19. repeat

Thanks, you’re the best

Hello.

I know I am persistent but the scritp doesn’t have all the features that I want yet.

I was going through example scripts and can’t find anywhere how to start the script with button press. I want this to happen with both buttons pressed and I don’t mean that it would overrun the quit command.
I know that when I turn on or reset the controller the script will run automatically, but I want it to initiate the whole thing with button press.

And the last feature I need -is to extend those 10000 miliseconds to 180 seconds. Thats no problem with servo delays but this is another story.

I got the “trigger”:

wait_for_trigger_press_100ms
goto main_loop
sub trigger
  1 get_position 1023 equals
  2 get_position 1023 equals
  logical_and
return
sub wait_for_trigger_press_100ms
  get_ms
  begin
    trigger
    if
      get_ms over minus 100 greater_than
      if drop return endif
    else
      drop get_ms
    endif
  repeat


main_loop:

I am glad you were able to figure out a way to have the script wait for a button push before starting the main loop.

The timer on the Maestro ranges from -32768 to 32767, so you can only measure up to around 64 seconds at a time with it. If you want to do more than that (like 180 seconds), you would probably need to do it in stages or by breaking it down into smaller intervals and using a separate counter to keep track of them.

Brandon