Accumulated count based on how long an input switch remains closed

I’m a little bit lazy and a little bit lost :slight_smile:

I’m looking to run up a motor via an ESC and Maestro. Has anybody got any code-snippets for accumulating a count over time? I need my script to drive the motor based on a potentiometer position. If however a push-button on another input is pressed, the script will add an arbitrary value to the pot position and drive the ESC to this slightly higher position. The script then lets some time pass, before repeating as long as the switch stays pressed. This ramps up the motor over-and-above the pot setting as long as I keep the button pressed. The switch is actually a bite-switch and this is a pot plus for hands-free (the bite-switch) system.

Below is my very rudimentary start. Any snippets to help would be much appreciated. Many thanks, Brendan.

# SCRIPT TO CONTROL A MOTOR ESC
# 
# Inputs:
#    a) Potentiometer on '0'
#    b) Push-button switch on '1'
#    Output: One only - ESC on '2' 
#
# Functionality:
#    1) Drive servo '2' to position relative to pot '0'
#    2) If Push-button '1' pressed go to a rampup sub and...
#         A) Get position of pot
#         i) Add pot value to a a small number
#         ii) Drive servo to this number, remember number
#         iii) Wait for a small time
#         Va)  Is push-button still pressed? Yes - back to i) to repeat
#         Vb)  Is push-button still pressed? No - forget accumulated number and back to 1)   

begin
   swt_rampup      # Goto subroutine swt_rampup
   0 get_position   # Get the position of the Potentiometer
   2 servo             # Send this value to the servo (ESC)
repeat

sub swt_rampup
   begin
      1 get_position 500 less_than   # Is the swt active ("less_than")
      if
         return                                    # If swt inactive break out of sub
      else
        delay 1000
         if
            return
         endif
      endif
   repeat

From your description, it sounds like you want the servo output to be based on the potentiometer when the switch is not pressed and when the switched is pressed, have the servo output increase until it is released. If that is the case, doing something like this might work for you:

begin
  1 get_position 500 less_than  if    #check if the switch is pressed
   
    2 get_position 40 plus
    2 servo  #set the servo
    100 delay #short delay
 
  else

    0 get_position    # get the value of the pot, 0-1023
    4 times 4000 plus # scale it to 4000-8092, approximately 1-2 ms
    2 servo    #set the target of servo 2
  
  endif
repeat

The program above does not actually use a counter; instead it increments the servo target by a set amount (40 quarter microseconds) each time through the loop when the button is pressed. If you want the servo target to ramp up faster the longer the button is pressed, you would probably need some sort of counter. There are probably a few ways you could do this (e.g. using the get_ms command to time how long the button has been pressed), but using a counter that increases each time through the loop would probably work. After I modified my example above to use a counter, it looks like this:

0  #initialize counter value
begin
   
  1 get_position 500 less_than if    #check if the switch is pressed
  
    dup 10 times   #copy counter value and multiply it by a scaling factor
    2 get_position plus #get the current position of the servo and add the scaled counter
    2 servo  #set the servo 
    1 plus  #increase the counter on the stack by 1
    100 delay #short delay

  else
  
    drop  #drop the current counter
    0 get_position    # get the value of the pot, 0-1023
    4 times 4000 plus # scale it to 4000-8092, approximately 1-2 ms
    2 servo    #set the target of servo 2
    0   #reset the counter to zero
 
  endif
repeat

Brandon

Hi Brandon

Thank you very much for your help. I didn’t see your post and came up the the script below. Very similar to your first example, I think (no counter). I’ve tested it and it works as I want it to :slight_smile:

One question though, as I’m increasing a value on the stack - what happens when a stack value reaches the largest number possible? Does the value just stop increasing? Or roll-through to 0? I guess to be thorough, I should probably add a test to stop adding if the stack has a value greater than 2000?

Cheers and thanks again,
Brendan.

Begin
swt_rampup            #Goto Sub swt_rampup
0 get_position         #Get position of Pot 
4 times 4000 plus   #Normalise for servo output
2 servo                   #Set servo (ESC) to value
Repeat

sub swt_rampup
   0 get_position                               #Get position of Pot (again)
   4 times 4000 plus                         #Normalise
   begin
      1 get_position 500 less_than     #Test if button pressed
      if                                                 #If button not pressed...  
         Drop                                        #Drop the Pot value from Stack
         return                                      #Go back to main loop
      else                                            #If button is pressed...
         100 plus                                  #Start accumulating, add 100
         Dup                                         #Dup value to keep alive
         2 servo                                    #Set servo (ESC) to value
         250 delay                                #Wait 1/4 second
      endif                 
   repeat                                           #Back to the Test...

Since your counter is being used to set a servo target, there are two limits that would be important. The first value that will be reached is the maximum set target value for that servo channel. You can configure this value for each channel in the “Channel Settings” tab of the Maestro Control Center; please note that the values in the “Channel Settings” tab is in units of microseconds, while the value when sending a target in a script is in units of quarter microseconds, so you will need to convert the units appropriately. For example, since the default the max target value is 2000 microseconds, you can add some logic to prevent the counter from increasing beyond 8000 quarter microseconds. Sending target values above the configured maximum will send a target value equal to the configured maximum.

The next limit to be aware of is that values on the stack must be integers from -32768 to +32767. If you have a counter that exceeds 32767, it will roll over back to -32767.

Brandon

Thanks Brandon for the good advice and info.

I added a little test that stops the count accumulating if 8100 microseconds is reached (in bold below). I’ve bench tested this script and it works great (no one is more surprised by this than me!).

Begin
swt_rampup
0 get_position
4 times 4000 plus
2 servo
Repeat

sub swt_rampup
   0 get_position
   4 times 4000 plus
   begin
      1 get_position 500 less_than
      if
         Drop
         return
      else
       **Dup**
         **8100 less_than**
            if
               100 plus
            endif
         Dup
         2 servo
         250 delay
      endif
   repeat