Pololu Robotics & Electronics
My account Comments or questions? About Pololu Contact Ordering information Distributors

Line following with steppers , slow and vibrating


Hello everyone,
I’m using an Arduino Mega2560 + QTR-8A + 2 x A4988 “black edition” + 2 x Nema17 stepper motors (400 step), for a line following robot. It is intended to work as a courier in our company. Accelstepper library for steppers, QTRSensors library by Pololu for QTR-8A.

The loop is:

stepperL.setMaxSpeed(800); stepperL.setSpeed(defaultSpeedL);
stepperR.setMaxSpeed(800); stepperR.setSpeed(defaultSpeedR);

while (1)  { 

  position = qtra.readLine(sensorValues); 
      stopErr = 1; // test for a black cross line
      for (unsigned char i = 0; i < NUM_SENSORS; i++)      if  (sensorValues[i] >= 800 ) stopErr++;  
      if (stopErr == NUM_SENSORS) { lcd.setCursor(0,1) ; lcd.print("FULL STOP "); stepperL.stop(); stepperR.stop(); delay(2000);}  
   error = position - 3500;
   kP = 0.25 * error ; kD = 5*(error - lastError);   motorSpeed = kP + kD;  
   lastError = error;   
   currentSpeedL = defaultSpeedL + motorSpeed;    currentSpeedR = defaultSpeedR - motorSpeed;

// some LCD update
String  secStr = String(millis()/100);  String  lastChr = secStr.substring(secStr.length()-1) ; 
int     val = lastChr.toInt(); 
if (val == 0)  {
   lcd.clear();    lcd.print("sL="); lcd.print(currentSpeedL); lcd.print(" sR="); lcd.print(currentSpeedR);
   lcd.setCursor(0,1) ; lcd.print("kP=") ; lcd.print(kP) ; lcd.print(" kD=") ; lcd.print(kD);   
   stepperL.setSpeed(currentSpeedL);   stepperR.setSpeed(currentSpeedR);
   stepperL.runSpeed();                stepperR.runSpeed(); 

With this program, the robot is acting good, but slow and vibrating (even some screws start to weak due to vibrations).
As I delete some lines, the speed increases. The values for speedL and R are computed correct, but somehow the motor seems to receive too sparse run()s.

If I leave only

stepperL.setMaxSpeed(800); stepperL.setSpeed(400);
stepperR.setMaxSpeed(800); stepperR.setSpeed(400);
while (1)  { 
   stepperL.runSpeed();                stepperR.runSpeed(); 

it goes pretty fast and no vibrations at all (of course only forward, at full speed).

If i comment the LCD part, it works better, but still way too slow.

Is it there any optimisation I can do, for a faster and smoother move?



Later edit with a film. Maybe this is a usual speed expected from steppers?




Thank you for posting a video. The movement in the video looks smooth to me. Is that the behavior with or without the LCD code included? It is hard to say if that is the speed you should expect since the speed will depend on your step rate, along with several other factors such as the microstepping mode, load on the motor, current limit, and supply voltage. Is there a reason you are using stepper motors instead of brushed DC motors? I suspect a brushed DC motor will give you smoother and faster motion.

By the way, I noticed you are using a black line on a wooden floor. For best performance, we generally recommend using the reflectance sensors with two contrasting materials, like black electrical tape on white poster board (shown in the “Building Line-Following and Line Maze Courses” tutorial).



Indeed, the video is without the LCD update and with my “best” values so far for kP and kD (no vibrations too). The A4988s are connected to 12V, 5A source, the load is pretty light - the current through steppers is set just to pull the cart, not more than that. I’m using steppers, because somewhere in the future I would like to convert the robot to self balancing, and as far as I saw, many people use steppers for that.

I put a couple of micros() before and after the main parts, they gave interesting results:
qtra.readline = 4612 µs
Stop test = 8 µs
LCD update = 248 µs

qtra.readline = 4196 µs
Stop test = 12 µs
LCD update = 248 µs

(there is a small speed increase, so for further tests I will use the NO_EMITTER option and without LCD)

It follows that a cycle takes about 4.5 ms, or 222 cycles / second. Since the motor has 400 steps, it does half a rotation for every second (corresponds with the reality).

So, is it there any possibility to shorten a cycle? maybe altering something in QTRSensors.cpp to speed it up a little?



Finally got the solution: using interrupts.

It took 200 minutes to research and 2 minute to implement it:

  • stepperL,R.runSpeed() moved into ISR(TIMER1_COMPA_vect) {...} , and
  • setting up the Timer1 using AVR stuff - something I don’t fully understand yet

I’ve tested with different values for OCR1A, until I’ve found one that goes fast - about 4 mph.
And the LCD update is not delaying anymore the movement.



I am glad you were able to find a solution and implement it. We would love to see a video of your updated robot! You might consider posting your updated code as well. Also, it would be fun to see your robot again after you have converted it to a balancing robot.



First steps on two wheels :slight_smile:


That was a fast transition to a balancing robot, and it looks like you are off to a good start! You might consider making a post about it in the “Share Your Projects” section of the forum when you are finished with it.

Keep up the good work!