Motor speed ramping

Aloha –
I have had very little success with the following snippet of code, which runs on a Zumo-tracked bot.

void Forward(){ potValue = analogRead(A5); potValue = map(potValue, 0, 1023, 15, -15); digitalWrite (AIN1,HIGH); digitalWrite (AIN2,LOW); digitalWrite (BIN1,HIGH); digitalWrite (BIN2,LOW); for (int speedSet = 0; speedSet <= MAXSPEED; speedSet ++) { analogWrite(PWMA, speedSet + potValue); analogWrite(PWMB, speedSet); delay(5); } //checkLR(); //delay(5); //currentCheck(); }

I am running an A*MiniLV and TB6612FNG, driving a pair of micrometal gearmotors. What I get is the motor speeds ramping up, stopping, ramping up, stopping…
Without speed ramping, I am thinking the axles are wallowing the D-shape of the drive wheels. Getting this right, I can lower the current spikes, incorporate an IMU…

The Forward() is called from the main loop like this,

[code]void loop() {
curDist = readPing(); // read distance
//delay(10);
if (curDist < ALERTDIST)
{
if (curDist < COLLDIST)
{
stopAll();
delay(50);
Backward();
delay(300);
newchangePath();
}
else
{
newchangePath();
}
} // if forward is blocked change direction
else Forward();

//checkLR();
//currentCheck();
}[/code]

With my limited experience, I have been trying to get this bit of code right for quite a while. Could someone graciously point out my errors, it would be greatly appreciated.
Mahalo,
Mark

I was browsing the Reference pages at Arduino.cc and just stumbled upon the solution. The below seems to work well enough.

[size=85][code]// MotorSpeedRamping.ino

// TB6612FNG and A*mini pins
#define PWMA 10
#define AIN1 7
#define AIN2 8
#define PWMB 11
#define BIN1 6
#define BIN2 5
#define STBY 12

#define MAXSPEED 240

void setup() {
Serial.begin(115200);

pinMode(PWMA,OUTPUT);
pinMode(AIN1,OUTPUT);
pinMode(AIN2,OUTPUT);
pinMode(PWMB,OUTPUT);
pinMode(BIN1,OUTPUT);
pinMode(BIN2,OUTPUT);
pinMode(STBY,OUTPUT);

delay(8000); // turn on motor power, pour some cereal
}

void loop() {
startUp();
delay(100);

goForward();
delay(8000);

stopAll();
delay(1000);

shutDown();
delay(2000);
}

/*
void goForward () // Hard stop and go’s
{
digitalWrite (AIN1,HIGH);
digitalWrite (AIN2,LOW);
analogWrite(PWMA,200);
digitalWrite (BIN1,HIGH);
digitalWrite (BIN2,LOW);
analogWrite(PWMB,200);
}
*/

void goForward(){
int potValue = analogRead(A5);
potValue = map(potValue, 0, 1023, 15, -15); // mis-matched motors
digitalWrite (AIN1,HIGH);
digitalWrite (AIN2,LOW);
digitalWrite (BIN1,HIGH);
digitalWrite (BIN2,LOW);
for (int speedSet = 0; speedSet <= MAXSPEED; speedSet +=2)
{
analogWrite(PWMA, speedSet + potValue);
analogWrite(PWMB, speedSet);
if (speedSet >= MAXSPEED){
break;
} // http://arduino.cc/en/Reference/Break gawfawnit!
delay(50); // big bowl cereal
Serial.println(speedSet); // when do wheels turn? double that.
}
}

void stopAll ()
{
digitalWrite (AIN1,HIGH);
digitalWrite (AIN2,HIGH);
analogWrite(PWMA,255);
digitalWrite (BIN1,HIGH);
digitalWrite (BIN2,HIGH);
analogWrite(PWMB,255);
}

void startUp ()
{
digitalWrite(STBY,HIGH);
}
void shutDown ()
{
digitalWrite(STBY,LOW);
}

[/code][/size]

Hello.

It sounds like you figured out a solution. Thanks for sharing what you found.

- Grant

Aloha –

That last post of code? It did not fly when dropped into the larger sketch for the bot. Motor speed ramps up, cycles over and over. Other sensor functions are performed, but bot just yo-yo’s along when driving straight. The uncommented Forward() is not the desired option.

Any suggestions, advice would be greatly appreciated, as have been trying to get this, with little success.

Thanks

[code]/*
AStarMiniZumo6x2SpeedRamp.ino
*/

#include <NewPing.h>
/PING def*/
#define TRIGPIN A0
#define ECHOPIN A1
#define MAXDIST 500 // distances in cm
#define COLLDIST 10
#define ALERTDIST 15
//#define ALERTDIST collDist*3
NewPing sonar(TRIGPIN, ECHOPIN, MAXDIST); // sets up sensor library to use the correct pins to measure distance.

/* TB6612FNG and A pins*** */
#define PWMA 10
#define AIN1 7
#define AIN2 8
#define PWMB 11
#define BIN1 6
#define BIN2 5
#define STBY 12

#define MAXSPEED 240
//int speedSet = 0;

int led = 13;
//int sensorPower = 4;
//int speakerPin = 4;
int d = 0; // turn delay variable
int curDist = 0;
int val[3];
//const int numReadings = 3;

/*
const int numReadings = 10;
int readings[numReadings]; // the readings from the analog input
int index = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average
*/

int inputPin = A4;
int potValue = 0;

int readPing() { // read the ultrasonic sensor distance
delay(50);
unsigned int uS = sonar.ping();
int cm = uS/US_ROUNDTRIP_CM;
return cm;
}

//**************************** SETUP ****************************************
//***************************************************************************
void setup() {
Serial.begin(9600);
pinMode(led, OUTPUT);

val[0] = 0;
val[1] = 0;
val[2] = 0;

// for (int thisReading = 0; thisReading < numReadings; thisReading++)
// readings[thisReading] = 0;

pinMode(PWMA,OUTPUT);
pinMode(AIN1,OUTPUT);
pinMode(AIN2,OUTPUT);
pinMode(PWMB,OUTPUT);
pinMode(BIN1,OUTPUT);
pinMode(BIN2,OUTPUT);
pinMode(STBY,OUTPUT);
startUp();
setupBlink();
//Forward();
}
//************************ LOOP *********************************************
//***************************************************************************
void loop() {
Forward();
Ping(); // removed the contents in Ping() from here
}

//************************ FUNCTIONS ****************************************
//***************************************************************************

void Ping(){ // Removed from main loop to here
curDist = readPing();
//delay(10);
if (curDist < ALERTDIST)
{
if (curDist < COLLDIST)
{
stopAll();
delay(50);
Backward();
delay(300);
newPath();
}
else
{
newPath();
}
}
else Forward();

}

void newPath()
{
stopAll();
delay(50);

if (random(2) == 0)
{
rotateLeft();
d = ((random(4) + 1) * 100);
delay(d);
senseLeft();
}
else rotateRight();
d = ((random(4) + 1) * 100);
delay(d);
senseRight();
}

void senseLeft()
{
curDist = readPing(); // read distance
if ( curDist < COLLDIST )
{
rotateLeft();
delay(400);
}
else Forward();
}

void senseRight()
{
curDist = readPing(); // read distance
if ( curDist < COLLDIST )
{
rotateRight();
delay(400);
}
else Forward();
}

void checkLR() // Runs in the Forward() funxn
{
int leftValue = analogRead(A2); // LED/phototransistor
int rightValue = analogRead(A3);
if (rightValue < 500 && leftValue < 500)
{
stopAll();
sensorBlink();
delay(50);
sensorBlink();
Backward();
delay(400);
stopAll();
delay(100);
newPath();
}
if (leftValue < 900)
{
stopAll();
sensorBlink();
rotateRight();
delay(100);
}
if (rightValue < 900)
{
stopAll();
sensorBlink();
rotateLeft();
delay(100);
}
}

//**************************** MOTOR CONTROL ********************************
//***************************************************************************

void Forward () // Hard start and stop
{
potValue = analogRead(A5);
potValue = map(potValue, 0, 1023, 15, -15);
digitalWrite (AIN1,HIGH);
digitalWrite (AIN2,LOW);
analogWrite(PWMA,MAXSPEED + potValue); // Offset for speed diff of motors
digitalWrite (BIN1,HIGH);
digitalWrite (BIN2,LOW);
analogWrite(PWMB,MAXSPEED);
delay(20);
checkLR();
}

//**************** Problematic code here *********

/*
void Forward(){ // Soft start, and proceeds like a yo-yo.
potValue = analogRead(A5);
potValue = map(potValue, 0, 1023, 15, -15); // mis-matched motors
digitalWrite (AIN1,HIGH);
digitalWrite (AIN2,LOW);
digitalWrite (BIN1,HIGH);
digitalWrite (BIN2,LOW);
for (int speedSet = 0; speedSet <= MAXSPEED; speedSet +=2)
{
analogWrite(PWMA, speedSet + potValue);
analogWrite(PWMB, speedSet);
if (speedSet >= MAXSPEED){
break;
} // http://arduino.cc/en/Reference/Break gawfawnit!
delay(5);
//Serial.println(speedSet); // when do wheels turn? double that for MINSPEED
} // wheels turn real early, when PWM gets up to 20~30
}

void Forward(){ // Soft start, but drives like a yo-yo
potValue = analogRead(A5);
potValue = map(potValue, 0, 1023, 15, -15);
digitalWrite (AIN1,HIGH);
digitalWrite (AIN2,LOW);
digitalWrite (BIN1,HIGH);
digitalWrite (BIN2,LOW);
for (int speed = 0; speed <= MAXSPEED; speed ++)
{
analogWrite(PWMA, speed + potValue);
analogWrite(PWMB, speed);
delay(5);
}
}
*/

void Backward ()
{
potValue = analogRead(A5);
potValue = map(potValue, 0, 1023, 15, -15);
digitalWrite (AIN1,LOW);
digitalWrite (AIN2,HIGH);
analogWrite(PWMA,MAXSPEED + potValue);
digitalWrite (BIN1,LOW);
digitalWrite (BIN2,HIGH);
analogWrite(PWMB,MAXSPEED);
}
void rotateLeft ()
{
potValue = analogRead(A5);
potValue = map(potValue, 0, 1023, 15, -15);
digitalWrite (AIN1,HIGH);
digitalWrite (AIN2,LOW);
analogWrite(PWMA,(MAXSPEED + potValue) * 0.9);
digitalWrite (BIN1,LOW);
digitalWrite (BIN2,HIGH);
analogWrite(PWMB,MAXSPEED * 0.8);
}
void rotateRight ()
{
potValue = analogRead(A5);
potValue = map(potValue, 0, 1023, 15, -15);
digitalWrite (AIN1,LOW);
digitalWrite (AIN2,HIGH);
analogWrite(PWMA,(MAXSPEED + potValue) * 0.9);
digitalWrite (BIN1,HIGH);
digitalWrite (BIN2,LOW);
analogWrite(PWMB,MAXSPEED * 0.8);
}
void stopAll ()
{
digitalWrite (AIN1,HIGH);
digitalWrite (AIN2,HIGH);
analogWrite(PWMA,255);
digitalWrite (BIN1,HIGH);
digitalWrite (BIN2,HIGH);
analogWrite(PWMB,255);
}
void turnAround()
{
rotateLeft();
delay(1500);
}

void startUp ()
{
digitalWrite(STBY,HIGH);
}
void shutDown ()
{
digitalWrite(STBY,LOW);
}

/*********LED ********* edit to use for (increment) statements and millis() here */
void sensorBlink()
{
digitalWrite(led, HIGH);
delay(50);
digitalWrite(led, LOW);
}
void setupBlink()
{
digitalWrite(led, HIGH);
delay(50);
digitalWrite(led, LOW);
delay(50);
digitalWrite(led, HIGH);
delay(50);
digitalWrite(led, LOW);
}

/*
//************************* PIEZO TONES *************************************
//***************************************************************************
void setupTones(){
playTone(100,1000);
delay(1000);
playTone(100,1300);
delay(1000);
playTone(100,1600);
delay(1000);
}

// duration in mSecs, frequency in hertz
void playTone(long duration, int freq) {
duration *= 1000;
int period = (1.0 / freq) * 1000000;
long elapsed_time = 0;
while (elapsed_time < duration) {
//digitalWrite(speakerPin,HIGH);
delayMicroseconds(period / 2);
//digitalWrite(speakerPin, LOW);
delayMicroseconds(period / 2);
elapsed_time += (period);
}
}
*/[/code]

Hello.

From a quick glance at your code, it looks like you repeatedly call the function Forward() in your main loop. However, in both of the versions of Forward() that you have commented out, it looks like the for loop ramps up the speed from zero each time it is run. If you want the robot to only ramp up the speed from zero once and then continue to driver forward normally, you will probably want to include another ramping function that you call only once each time you want the motors to start.

If your code is supposed ramp up the speed over and over or that is not the issue you are referring to, could you describe what you want the behavior of your robot to be and what you are seeing instead?

- Grant

Thanks Grant –

Yeah, the Ping() function was in void loop() alone, and no second call to Forward(), that is what I have typically been working on until lately. My eyes are not really fresh on this matter any more, and the code I posted was some effort at ironing this out.

With some minor changes, such as re-defining TRIGPIN & ECHOPIN from analog to 18 & 19, respectively, and bringing that Ping function back into the main loop (eliminating that second call of Forward()), I am still observing the bot ramp up speed, start at zero, ramp speed up again,…(repeatedly).

Yes, a nice ramping up of speed to MAXSPEED, and remaining there indefinitely, until some object appears in the sensors field of detection, yes, that is what I am aiming for. I seem consistently falling short of this goal.

Spending some time with this today. Feel bad constantly posting what does not work.

A hui hou,

It sounds like you might not have understood some of the things in my previous post. Each time you call the version of Forward() that you said was giving you issues, the robot is going to set its speed to zero and ramp back up to MAXSPEED. This is because in that version of Forward() you set speedSet to zero at the start of the for loop. This happens in the following line of code:

  for (int speedSet = 0; speedSet <= MAXSPEED; speedSet +=2)

- Grant

Grant –

Oh, I caught what you had pointed out. Moving on, I have been trying to figure a way of determining direction and speed of rotation of motors before going to Forward(). Don’t know if this makes sense, but in a pseudocode description, something like:

void setup(){...}

void loop(){
  check sensors...
  if (criteria for doing something about an obstruction)
  else ( ! motors spinning )
       { Forward() }

void Forward() {...}

None of the Zumo code incorporates speed ramping. CollisionDetect has millis() delays before polling sensors after turns/detections. I should have just taken that as a big cue of what is possible.

Thanks for hanging in there with me Grant.

Me ka mahalo.

It is kind hard to follow what you are trying to do in your pseudo code, but it is definitely worth giving a try.

By the way, you might find the following robot builds with object avoidance interesting. Their write-ups include code, so you might find how they implement object avoidance helpful:

solderspot.wordpress.com/wallbot-project/
instructables.com/id/How-To- … ino-Robot/
instructables.com/id/FuzzBot/

- Grant