1

I am working on an autonomous robot using two 4-pin stepper motors, HC-SR04 ultrasonic sensor, 2 L298N motor drivers (one for each motor), and an Arduino Uno. My problem is that when I use the stepper motors with the Stepper library, only one motor works at a time. My solution was to control the one step at a time in a short period of time, which worked, however, this introduces a new problem. The ultrasonic sensor requires a delay to work, but this makes the movement of the robot quite slow and jittery as it works only by one step at a time. When I remove the delay from the ultrasonic sensor, it starts returning the correct value, but then also returning 0 right after each correct value. My solution was to ignore the returned 0, but this is not ideal.

How can I use two stepper motors at the same time and use an Ultrasonic sensor?

Here is my code:

#include <Stepper.h>
#include <Ultrasonic.h>

/*
 * Pass as a parameter the trigger and echo pin, respectively,
 * or only the signal pin (for sensors 3 pins), like:
 * Ultrasonic ultrasonic(13);
 */
 Ultrasonic ultrasonic(13, 12);
 int distance;

 int driveSpeed = 100;
 int stepsPerRevolution = 200;
 int leftMotorStep = 0;
 int rightMotorStep = 0;

 // Time interval between steps for both motors
 const int stepInterval = 10;  // Adjust as needed

 // Last step time for each motor
 unsigned long leftMotorLastStepTime = 0;
 unsigned long rightMotorLastStepTime = 0;

 Stepper rightMotor(stepsPerRevolution, 8, 9, 10, 11);
 Stepper leftMotor(stepsPerRevolution, 4, 5, 6, 7);

 void setup() {
   Serial.begin(9600);
   rightMotor.setSpeed(driveSpeed);
   leftMotor.setSpeed(driveSpeed);
 }
 void loop() {
   distance = ultrasonic.read();

   Serial.print("Distance in CM: ");
   Serial.println(distance);
   delay(250); //This delay makes the motors behave strangely

   if (distance < 15) {
     Serial.println("AVOIDING OBSTACLE!");
     // Perform obstacle avoidance behavior
     avoidObstacle();
   } else if (distance < 30) {
     Serial.println("APPROACHING OBSTACLE!");
     // Perform slow approach behavior
     slowApproach();
   } else {
     Serial.println("DRIVING!");
     // Perform normal driving behavior
     drive();
   }
 }

 void avoidObstacle() {
   // Stop the robot
   halt();

   // Rotate the robot to avoid the obstacle
   leftM();

   // Delay to allow the rotation to complete
   delay(1000);
 }

 void slowApproach() {
   // Slow down the motors
   int slowSpeed = 50;
   rightMotor.setSpeed(slowSpeed);
   leftMotor.setSpeed(slowSpeed);

   // Move the robot forward slowly
   forwardM();

   // Delay to allow the slow approach
   delay(1000);
 }

 void drive() {
   // Set the motors back to the normal speed
   rightMotor.setSpeed(driveSpeed);
   leftMotor.setSpeed(driveSpeed);

   // Move the robot forward
   forwardM();
 }

 void forwardM() {
   rightMotor.step(1);
   leftMotor.step(1);
 }
 void leftM() {
   rightMotor.step(1);
   leftMotor.step(-1);
 }
 void rightM() {
   rightMotor.step(-1);
   leftMotor.step(1);
 }
 void reverseM() {
   rightMotor.step(-1);
   leftMotor.step(-1);
 }
 void halt() {
   rightMotor.step(0);
   leftMotor.step(0);
 }
5
  • 1
    first, stop using delay()
    – jsotola
    May 29 at 15:21
  • When I don't use delay(), the Ultrasonic sensor returns 0 after every value (as mentioned int the post).
    – Renier Jr.
    May 29 at 18:44
  • 2
    stop using the delay() function to introduce a delay ... see the blinkWithoutDelay example sketch in the Arduino IDE
    – jsotola
    May 29 at 20:08
  • Thank you, this definitely helps!
    – Renier Jr.
    May 29 at 21:19
  • may be of interest ... wokwi.com/projects/327381547863769683
    – jsotola
    May 30 at 1:01

1 Answer 1

2

Try this code.

Here is a simulation. https://wokwi.com/projects/366108641014000641

Click on the sensor to set the distance in the simulation

NOTE: centimeters is cm, not CM.

Not tested on hardware.



// https://arduino.stackexchange.com/questions/93302/how-to-drive-two-stepper-motors-and-use-an-ultrasonic-sensor-together

#include <Stepper.h>
#include <Ultrasonic.h>

/*
 * Pass as a parameter the trigger and echo pin, respectively,
 * or only the signal pin (for sensors 3 pins), like:
 * Ultrasonic ultrasonic(13);
 */
 
 Ultrasonic ultrasonic(13, 12);
 
 int distance;

 int slowSpeed          =  100;
 int driveSpeed         = 1000;
 int stepsPerRevolution =  100;
 int leftMotorStep      =    0;                         // current step speed and direction
 int rightMotorStep     =    0;

 int stepSpeed          =   10;                         // this is the motor speed

 const int stepInterval =    1;                         // Time interval between steps for both motors

 unsigned long leftMotorLastStepTime  = 0;              // Last step time for each motor
 unsigned long rightMotorLastStepTime = 0;

 Stepper rightMotor(stepsPerRevolution, 8, 9, 10, 11);
 Stepper leftMotor (stepsPerRevolution, 4, 5,  6,  7);


 void setup() {
   Serial.begin(9600);
   rightMotor.setSpeed(1);
   leftMotor. setSpeed(1);
 }


 void loop() {

  distance = ultrasonic.read();

  Serial.print("Distance in cm: ");
  Serial.print(distance);  Serial.print("\t");

  switch (distance) {                              // used switch/case for cleaner looking code
    case 0 ... 14:
      Serial.println("avoid");
      avoidObstacle();                             // Perform obstacle avoidance behavior
      break;

    case 15 ... 29:
      Serial.println("approach");
      slowApproach();                              // Perform slow approach behavior
      break;

    default:
      Serial.println("drive");
      drive();                                     // Perform normal driving behavior
      break;
  }

  rightMotor.step(rightMotorStep);                 // this actually moves the motors
  leftMotor .step(leftMotorStep);
}

 void avoidObstacle() {
   halt();                                          // Stop the robot
   leftM();                                         // Rotate the robot to avoid the obstacle
 }

 void slowApproach() {
   rightMotor.setSpeed(slowSpeed);                  // Slow down the motors
   leftMotor. setSpeed(slowSpeed);
   forwardM();                                      // Move the robot forward slowly
 }

 void drive() {
   rightMotor.setSpeed(driveSpeed);                 // Set the motors back to the normal speed
   leftMotor. setSpeed(driveSpeed);
   forwardM();                                      // Move the robot forward
 }

 void forwardM() {
   rightMotorStep =  stepSpeed;                     // select direction of step only
   leftMotorStep  =  stepSpeed;                     // do not move motor
 }                                                  // actual stepping is done at end of loop()
 void leftM() {
   rightMotorStep =  stepSpeed;
   leftMotorStep  = -stepSpeed;
 }
 void rightM() {
   rightMotorStep = -stepSpeed;
   leftMotorStep  =  stepSpeed;
 }
 void reverseM() {
   rightMotorStep = -stepSpeed;
   leftMotorStep  = -stepSpeed;
 }
 void halt() {
   rightMotorStep =  0;
   leftMotorStep  =  0;
 }

1
  • Thank you, this is really helpful!
    – Renier Jr.
    Jun 2 at 20:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.