Speed Ramping

Rich

United Kingdom

Speed ramping is something that comes up often and while it's not (yet) a built in function in ARC's movement panels it's not too difficult to achieve.

Before anything you will need an init script to set the variables so as not to cause errors in the ramping script. These can't be set in the ramping script as it would stop it working correctly.

Two variables need defining, $motor1speed and $motor2speed.


# Define variables
$motor1speed = 1
$motor2speed = 1

These can be set to anything as other scripts will change them before ramping begins.

Then you need the ramping script which will gradually increase the speed of the motors, uncomment the required control method where indicated within the script. H-Bridges work a little differently and therefore another script will be posted to cover the H-Bridge version.

The ramping script would be as follows, I have commented it to explain each part where necessary.


# Script commands for gradual ramping to desired speeds.

# Author: Rich
# Version: 2015.01.08.00

# Desired speeds set elsewhere. This script is called with ControlCommands.
# Note: An init script must have previously run to set the variables.

$rampdelay = 50 # Adjust to suit speed increase

# Do not modify beyond this point unless you know what you are doing
# Any changes may cause the script to run incorrectly.

# Check the direction of ramping up or down and set the steps to suit
IF ($motor1speed > $motor1speed_end)
  # If true motor speed needs to increase therefore +1
  $motor1steps = 1
ELSE 
  # Otherwise it needs to decrease therefore -1
  $motor1steps = -1
ENDIF 
  
IF ($motor2speed > $motor2speed_end)
  # If true motor speed needs to increase therefore +1
  $motor2steps = 1
ELSE 
  # Otherwise it needs to decrease therefore -1
  $motor2steps = -1
ENDIF 
  
REPEATUNTIL($motor1speed = $motor1speed_end AND $motor2speed = $motor2speed_end)
# This section will now loop from the above REPEATUNTL down to ENDREPEATUNTIL until the above statement is true (until motor speeds match those required).

# Movement commands - uncomment required control method.

  # Serial Control Method (Sabertooth etc)
  # SendSerial(D7,38400,$motor1speed)
  # SendSerial(D7,38400,$motor2speed)

  # Modified servo Method
  # Servo(D7, $motor1speed)
  # Servo(D8, $motor2speed)

  IF ($motor1speed = $motor1speed_end)
    # Avoid increasing speed when not needed - in the case of uneven steps between motors. Also state motor up to speed for info.
    Print("Motor1 Up To Speed")
  ELSE 
    # Otherwise increase or decrease the motor speed
    $motor1speed = $motor1speed + $motor1steps
  ENDIF 
    # Increase motor 2's speed if required
  IF ($motor2speed = $motor2speed_end)
    # Avoid increasing speed when not needed - in the case of uneven steps between motors. Also state motor up to speed for info.
    Print("Motor2 Up To Speed")
  ELSE 
    # Otherwise increase or decrease the motor speed
    $motor2speed = $motor2speed + $motor2steps
  ENDIF 
    
  # Add a slight delay as required (increase/decrease the delay in the variable at the top of the script)
  SLEEP($rampdelay)
ENDREPEATUNTIL

Now we are in business to start ramping...

You need the Custom Movement Panel for this and each direction requires a very similar script.

For forward movement the script needs to be something like this (again commented for guidance);


# Set the required end speed for motor 1
$motor1speed_end = 1

# Set the required end speed for motor 2
$motor2speed_end = 180

# Start the ramping script going
ControlCommand("Movement Controls", ScriptStart, "Ramp Speed")

For reverse


# Set the required end speed for motor 1
$motor1speed_end = 180

# Set the required end speed for motor 2
$motor2speed_end = 1

# Start the ramping script going
ControlCommand("Movement Controls", ScriptStart, "Ramp Speed")

Turn Right


# Set the required end speed for motor 1
$motor1speed_end = 180

# Set the required end speed for motor 2
$motor2speed_end = 180

# Start the ramping script going
ControlCommand("Movement Controls", ScriptStart, "Ramp Speed")

Turn Left


# Set the required end speed for motor 1
$motor1speed_end = 1

# Set the required end speed for motor 2
$motor2speed_end = 1

# Start the ramping script going
ControlCommand("Movement Controls", ScriptStart, "Ramp Speed")

Stop


# Set the required end speed for motor 1
$motor1speed_end = 90

# Set the required end speed for motor 2
$motor2speed_end = 90

# Start the ramping script going
ControlCommand("Movement Controls", ScriptStart, "Ramp Speed")

Note: You will more than likely need to change the values in the above depending on your servos or serial device.

And that's pretty much it for Modified Servos or Serial. PWM/H-Bridge is different and that will be in post 2 when I get the chance.

I will update as and when time permits and also post an Example Project when I get chance to make it. Enjoy :)

By — Last update

ARC Pro

Upgrade to ARC Pro

With Synthiam ARC Pro, you're not just programming a robot; you're shaping the future of automation, one innovative idea at a time.

United Kingdom
#1  

NOTE: H-BRIDGE/PWM METHOD STILL UNDER DEVELOPMENT

If using a H-Bridge the method will need to be somewhat different as the PWM is simply 0% to 100% as opposed to the above method where lower numbers reverse the direction.

Note: There may be a better method than this and if I think of it I will update

We still need the same init script to set the variables.


# Define variables
$motor1speed = 1
$motor2speed = 1

We also need a very similar ramping script to the above to but with a slight change;


# Script commands for gradual ramping to desired speeds.

# Author: Rich
# Version: 2015.01.08.00

# Desired speeds set elsewhere. This script is called with ControlCommands.
# Note: An init script must have previously run to set the variables.

$rampdelay = 50 # Adjust to suit speed increase

# Do not modify beyond this point unless you know what you are doing
# Any changes may cause the script to run incorrectly.

# Check the direction of ramping up or down and set the steps to suit
IF ($motor1speed > $motor1speed_end)
  # If true motor speed needs to increase therefore +1
  $motor1steps = 1
ELSE 
  # Otherwise it needs to decrease therefore -1
  $motor1steps = -1
ENDIF 
  
IF ($motor2speed > $motor2speed_end)
  # If true motor speed needs to increase therefore +1
  $motor2steps = 1
ELSE 
  # Otherwise it needs to decrease therefore -1
  $motor2steps = -1
ENDIF 
  
REPEATUNTIL($motor1speed = $motor1speed_end AND $motor2speed = $motor2speed_end)
# This section will now loop from the above REPEATUNTL down to ENDREPEATUNTIL until the above statement is true (until motor speeds match those required).

# Movement commands
  PWM(D7, $motor1speed)
  PWM(D8, $motor2speed)

  IF ($motor1speed = $motor1speed_end)
    # Avoid increasing speed when not needed - in the case of uneven steps between motors. Also state motor up to speed for info.
    Print("Motor1 Up To Speed")
  ELSE 
    # Otherwise increase or decrease the motor speed
    $motor1speed = $motor1speed + $motor1steps
  ENDIF 
    # Increase motor 2's speed if required
  IF ($motor2speed = $motor2speed_end)
    # Avoid increasing speed when not needed - in the case of uneven steps between motors. Also state motor up to speed for info.
    Print("Motor2 Up To Speed")
  ELSE 
    # Otherwise increase or decrease the motor speed
    $motor2speed = $motor2speed + $motor2steps
  ENDIF 
    
  # Add a slight delay as required (increase/decrease the delay in the variable at the top of the script)
  SLEEP($rampdelay)
ENDREPEATUNTIL

Since we need the PWM to ramp as appropriate we either need a script which is constantly running and monitoring the direction or we need to use a custom movement panel. The custom Movement Panel will work in a similar way to the above serial/servo method so for simplicity I'll use this method.

Based on the L298n H-Bridge since this is the more common H-Bridge we need to set the required ports high or low to tell the H-Bridge what to do then ramp the PWM. So, similar to the serial method we need the five movement scripts.

It is assumed In1 to In4 are on D0 to D3 respectively.

Forward


# Set the required end speed for motor 1
$motor1speed_end = 100

# Set the required end speed for motor 2
$motor2speed_end = 100

# Set the high/low for In1 to In4 of the H-Bridge
Set(D0, On)
Set(D1, Off)
Set(D2, On)
Set(D3, Off)

# Start the ramping script going
ControlCommand("Movement Controls", ScriptStart, "Ramp Speed")

Reverse


# Set the required end speed for motor 1
$motor1speed_end = 100

# Set the required end speed for motor 2
$motor2speed_end = 100

# Set the high/low for In1 to In4 of the H-Bridge
Set(D0, Off)
Set(D1, On)
Set(D2, Off)
Set(D3, On)

# Start the ramping script going
ControlCommand("Movement Controls", ScriptStart, "Ramp Speed")

Turn Right


# Set the required end speed for motor 1
$motor1speed_end = 100

# Set the required end speed for motor 2
$motor2speed_end = 100

# Set the high/low for In1 to In4 of the H-Bridge
Set(D0, On)
Set(D1, Off)
Set(D2, Off)
Set(D3, On)

# Start the ramping script going
ControlCommand("Movement Controls", ScriptStart, "Ramp Speed")

Turn Left


# Set the required end speed for motor 1
$motor1speed_end = 100

# Set the required end speed for motor 2
$motor2speed_end = 100

# Set the high/low for In1 to In4 of the H-Bridge
Set(D0, Off)
Set(D1, On)
Set(D2, On)
Set(D3, Off)

# Start the ramping script going
ControlCommand("Movement Controls", ScriptStart, "Ramp Speed")

Stop


# Set the required end speed for motor 1
$motor1speed_end = 0

# Set the required end speed for motor 2
$motor2speed_end = 0

# Keep digital pins for In1 to In4 as they were to ramp down from last movement

# Start the ramping script going
ControlCommand("Movement Controls", ScriptStartWait, "Ramp Speed")

# When ramping down is completed then release all In1 to In4 to low for freewheel

Set(D0, Off)
Set(D1, Off)
Set(D2, Off)
Set(D3, Off)

That should pretty much do it.

Note: This method is currently untested however in theory should work

#2  

Thanks Rich, I'm going to file that for future use.

#4  

Thanks @Rich.

This has been on my do-do list for a while, both for H-Bridge and Continuous Rotation Servos and I just haven't found the time. Glad you were on the case :)

Alan

United Kingdom
#6  

Not a problem. It's one which had me baffled for a while until I stopped over thinking it and since writing it for Gwen it's come in handy a few times so it deserves it's own topic. I know Dave wants similar for a single motor too so I'll cover that eventually too.

#7  

I know this may sound a little novice because i am one. I understand the ini script setting the $motorspeed1 and 2. I am putting this script in my ini script file. I am not sure though where the next code needs to be written.

I am using parallax HB-25 motor controllers. They act like standard modified servos so I am using the first set of code. I just do not know where it should go.

I am slowly learning the EZ-B script but i am having troubles with where to write the scripts. Any help would be greatly appreciated.

Ellis

#8  

Nice done Rich! Thanks for your time and talents doing this! Very timely. This helps a lot.

#9  

Thanks Rich. I will definately copy this one.

PRO
Synthiam
#10  

Rich, for the PWM version... use the ServoSpeed() command. Something like this...

This will initialize the ramping...



# set PWM Ramping for hbridge pwm ports
ServoSpeed(d0, 3)
ServoSpeed(d1, 3)

Now when ever you want to make the robot move, simply do this


# example moving forward
PWM(d0, 0)
PWM(d1, 0)

Set(d2, true)
set(d3, false)
set(d4, true)
set(d5, false)

PWM(d0, 100)
PWM(d1, 100)


# example stopping
PWM(d0, 0)
PWM(d1, 0)

Also, look at the EZ-Cloud for the Continuous Rotation servo Ramping Demo. It uses ServoSpeed() as well to ramp PWM between positions.

United Kingdom
#11  

Thanks for the tips, they will certainly come in handy when I have a proper look at pwm/h-bridge control.

The issue I see with it is the ramping down then back up for moving from forward to reverse. My method wont ramp properly but I'm sure there's a simple way that I missed. And no doubt it'll cone to me out of the blue like most things do, usually while I'm driving (I have a long drive ahead of me so it's all good).

PRO
Synthiam
#12  

For PWM H-Bridge, simply use the ServoSpeed(). As in my above example. The servospeed() will ramp the speed between PWM's.

Works really well :)

United Kingdom
#13  

@ellis, I'll be posying example projects when I get home. There is already a sabertooth one (very similar to this one) on the cloud, just check under my name for it. Replace the speed ramp script for the one in post 1 and it should work.

For servo control (which I believe your controller uses) just adjust the values in the movement panel.

Once I get back home (probably late tomorrow) I'll pop up some more examples.

PRO
Synthiam
#14  

For servo control, load the project from the EZ-Cloud called Continuous Rotation Speed Ramp Demo. It shows how to use the ServoSpeed() command on the Continuous Rotation Servos for speed ramping.

Remember... ServoSpeed() ramps between two PWM's. So if you have the PWM set to 10, a ServoSpeed() of 0, and set the PWM to 100, it will instantly move to 100 PWM.

If you have a PWM set to 10, a ServoSpeed() of 2, and set the PWM to 100, it will take N time to get to 100 PWM.

So using the PWM ramping for HBridge PWM and Continuous rotation is a good way for speed ramping with one line of code per channel.

PRO
Synthiam
#15  

To better understand what ServoSpeed() does, watch this video...

So if you can understand what it is doing - it's slowly ramping the PWM between two points. It does this inside of the EZ-B. You can leverage this PWM command ServoSleep() to use for speed ramping of HBridge PWM and Continuous Rotation.

#16  

DJ I will try this ASAP. It can't be that simple. Can it?

Also thanks to Rich. I have been on your cloud and impressed with you vast number of samples. I am looking forward to visiting them. I know I need several.

Ellis

#17  

Well it worked. I don't know why making ServoSpeed(D0, 2) and ServoSpeed(D1, 2) made it work but it did perfectly. This speed made it ramp beautifully.

:D

Thanks DJ on the short fix and thanks Rich on helping me understand code better.

Ellis

#18  

Can I start this Sabertooth ramping script with a simple call script and without installing or useing a custom movement panel? Seems that I would have to insert into the call script everything shown in the custom Movement Panel script above and set the proper $motor1speed variable speed I what to achieve.

I looks like the ramping script needs to know the final top spèed and the $motor1speed variable sets that. Does the custom Movement Panel do that in the background?

#19  

@Dave Schulpius,

Weren't you the one who posted in the thread where this started (Gwen's halloween thread) that you could set the Sabertooth to automatically ramp through Describe software? I haven't hooked mine up yet, but that sounded like an ideal solution for Sabertooth.

Alan

United Kingdom
#20  

Set the speed ramping going by first setting the speed for the motor (or motors) then call the ramping script to start. You needn't use the movement panel.

For example, if you had a script for moving a turret clockwise you would just need this (which is in the custom Movement Panel - so yes, this is done in the background);

# Set the required end speed for motor 1
$motor1speed_end = 1

# Start the ramping script going
ControlCommand("Movement Controls", ScriptStart, "Ramp Speed")

When the script is run it will start the motor moving in the direction specified and ramp up to the speed specified. Once it's up to speed it will continue moving until told otherwise.

If it was for a sequence where it would ramp up to a speed, move for 10 seconds then ramp down to stopping you would need this;

# Set the required end speed for motor 1
$motor1speed_end = 1

# Start the ramping script going
ControlCommand("Movement Controls", ScriptStart, "Ramp Speed")

# Sleep for 10 seconds
Sleep(10000)

# Set the required end speed for motor 1
$motor1speed_end = 63

# Start the ramping script going
ControlCommand("Movement Controls", ScriptStart, "Ramp Speed")
#21  

@Alen, Yes, I think it was me that said that. I was repeating what i read and was told by Dimension Engineering. I've never tried it though on just a Sabertooth.

@Rich, You're a jewel. Thanks for the clarity on the code. So what I hear you saying is all I need to do is send a version of your $motor1speed_end = 1 to bring the motor up to the wanted speed. I see by your scripts that changing the "1" to the value the controller is looking for is what I need to do and the motor will ramp up (and of course adjusting the Delay in the ramping script)?

However my application is a bit different than running two motors for wheels attached to a sabertooth. I'm using a DC motor on the elbow of my B9 Robot arm and have a Pot attached to it for feedback. I'm controlling it's speed and position with a Kangaroo x2 attached to the Sabertooth. DE's Kangaroo X2 does all the work figuring all this out but when it's in Independent Position mode like I'm using it there is no ramping.

I'm trying to rewrite your ramping script to give the Sabertooth a smoother start up. I'm sending Simple Serial commands through the Kangaroo connected to the Sabertooth through EZB's Uart port for the arm's up and down movement. DE says I can place a command loop like your script to ramp the speed so I thought I'd give it a try.

Here's the proper command to send through EZB's Uart port to have the Sabertooth/Kangaroo combo move one motor on it's channel 1 to a wanted position at a wanted speed:

uartWrite(1, 0, "1, p1800 s400", 0x0d)

Here's the code I have so far (thanks to Rich) . I have mixed results with it. I can get the motor to move to position and at the speed I want but haven't been able to get any ramping. I Plan to keep playing with it and have high hopes. Anyone feel free to jump with suggestions. ;)

Thanks! Dave


$rampdelay = 30 # Adjust to suit speed increase

# Check the direction of ramping up or down and set the steps to suit
IF ($motor1speed < $motor1speed_end)
  # If true motor speed needs to increase therefore +1
  $motor1steps = 1
ELSE 
  # Otherwise it needs to decrease therefore -1
  $motor1steps = -1
ENDIF 
  
REPEATUNTIL($motor1speed = $motor1speed_end)
  # This section will now loop from the above REPEATUNTL down to
  # ENDREPEATUNTIL until the above statement is true
  # (until motor speeds match those required).
  
  # Movement command
  
  # Uart - Serial Control Method (Sabertooth/Kangaroo)
UARTWrite(0, 0, "1, P"+$Moror1positon, "S"+$motor1speed, 0x0d)
  
  IF ($motor1speed = $motor1speed_end)
    # Avoid increasing speed when not needed -
    # in the case of uneven steps between motors.
    # Also state motor up to speed for info.
    Print("Motor1 Up To Speed")
  ELSE 
    # Otherwise increase or decrease the motor speed
    $motor1speed = $motor1speed + $motor1steps
  ENDIF  
    
    # Add a slight delay as required (increase/decrease the delay in the variable at the top of the script)
  SLEEP($rampdelay)
ENDREPEATUNTIL