Optimized Obstacle-Avoiding Robot Code: A Breakthrough for Robotics Enthusiasts

Optimized Obstacle-Avoiding Robot Code: A Breakthrough for Robotics Enthusiasts

This entry is part 10 of 10 in the series Arduino Tips & Tricks

Struggling with unreliable obstacle-avoiding robots? Learn how an optimized ultrasonic sensor code can revolutionize your projects! From fixing trigger pulse issues to handling invalid readings and ensuring flawless motor control, discover how this foolproof code outperforms the commonly used versions. Perfect for hobbyists and professionals alike — your robot’s performance will never be the same again!

Many times, you must have observed that obstacle-avoiding robots using ultrasonic sensors do not work properly. Even if they work, there are often significant errors, particularly with distance sensing and other critical parameters. These issues can lead to robots behaving unpredictably or failing to perform their intended tasks. After encountering and analyzing many such cases, I embarked on a journey to refine the code. By experimenting with different possibilities and logical approaches, I developed a perfectly working and foolproof solution.

In this article, we will compare the commonly used ultrasonic sensor-based obstacle-avoiding robot code (referred to as the “original code”) with the optimized version that addresses its shortcomings. The optimized code resolves distance sensing issues and ensures reliable motor control, making it ideal for practical applications.

The Original Code (Commonly Used by Hobbyists)

This code, while commonly used in hobbyist projects, is prone to several practical errors. The primary issue lies in the improper handling of ultrasonic sensor signals, which can lead to inaccurate distance measurements and erratic robot behavior. To ensure reliable performance, it is crucial that the ultrasonic sensor signals are sampled with precise timing and processed using logical coding practices. Without addressing these factors, the robot may misinterpret its surroundings, stop unnecessarily, or fail to detect obstacles altogether, undermining its effectiveness as an obstacle-avoiding robot.

#include <AFMotor.h>

AF_DCMotor RM(4); // Right motor
AF_DCMotor LM(3); // Left motor
int trigger = 9; // Ultrasonic sensor trigger pin
int echo = 10; // Ultrasonic sensor echo pin
float time = 0;
float distance = 0;

void setup()
{
  Serial.begin(9600);
  LM.setSpeed(100);
  RM.setSpeed(100);
  pinMode(trigger, OUTPUT);
  pinMode(echo, INPUT);
}

void loop()
{
  digitalWrite(trigger, LOW);
  delayMicroseconds(1);
  digitalWrite(trigger, HIGH);
  delayMicroseconds(1);
  digitalWrite(trigger, LOW);
  delayMicroseconds(1);

  time = pulseIn(echo, HIGH);
  distance = time * 0.034 / 2;
  Serial.println(distance);

  if (distance < 10)
  {
    LM.run(RELEASE);
    RM.run(RELEASE);
    delay(2000);

    LM.setSpeed(200);
    RM.setSpeed(200);
    LM.run(BACKWARD);
    RM.run(BACKWARD);
    delay(1000);

    LM.run(RELEASE);
    RM.run(RELEASE);
    delay(1000);
  }
  else
  {
    LM.setSpeed(100);
    RM.setSpeed(100);
    LM.run(FORWARD);
    RM.run(FORWARD);
  }
}

Issues with above Code

  1. Improper Trigger Pulse Timing:
    • The trigger pulse duration was too short (1 microsecond). Ultrasonic sensors require at least 10 microseconds to generate a proper burst.
  2. Lack of Timeout in pulseIn():
    • If the sensor failed to detect an echo, the program could hang indefinitely, causing erratic robot behavior.
  3. No Handling of Invalid Readings:
    • When no echo was received, pulseIn() returned 0, resulting in distance = 0. This caused the robot to misinterpret the absence of obstacles as a close-range object, leading to unnecessary stopping and turning.
  4. Unreliable Distance Calculation:
    • The code did not validate or filter sensor readings, which could lead to erroneous behavior in noisy environments.
  5. Redundant Delay Logic:
    • Excessive delays in motor control caused sluggish and unresponsive movements.

The Optimized Code

This code is the outcome of experimentation and research work conducted at Vidyasagar Academy by expert faculties. Use this code and just relax! It surely will work!
Don’t forget to post your experience as a comment at the bottom of this post…!

#include <AFMotor.h> // install shield library from following link:
// https://github.com/adafruit/Adafruit-Motor-Shield-library/blob/master/AFMotor.h

AF_DCMotor RM(4);
AF_DCMotor LM(3);
int trigger = 9;
int echo = 10;
float time = 0;
float distance = 0;

void setup()
{
  Serial.begin(9600);
  LM.setSpeed(100);
  RM.setSpeed(100);
  pinMode(trigger, OUTPUT);
  pinMode(echo, INPUT);
}

void loop()
{
  int x = random(2);

  digitalWrite(trigger, LOW);
  delayMicroseconds(2);
  digitalWrite(trigger, HIGH);
  delayMicroseconds(10); // Corrected timing
  digitalWrite(trigger, LOW);

  time = pulseIn(echo, HIGH, 30000); // 30ms timeout

  if (time == 0)
  {
    distance = -1; // Invalid reading
  }
  else
  {
    distance = time * 0.034 / 2;
  }

  Serial.println(distance);

  if (distance > 0 && distance < 10)
  {
    LM.run(RELEASE);
    RM.run(RELEASE);
    delay(2000);

    LM.setSpeed(200);
    RM.setSpeed(200);
    LM.run(BACKWARD);
    RM.run(BACKWARD);
    delay(1000);

    LM.run(RELEASE);
    RM.run(RELEASE);
    delay(1000);

    if (x == 0)
    {
      LM.setSpeed(110);
      RM.setSpeed(110);
      LM.run(FORWARD);
      RM.run(BACKWARD);
      delay(600);
    }
    else
    {
      LM.setSpeed(110);
      RM.setSpeed(110);
      LM.run(BACKWARD);
      RM.run(FORWARD);
      delay(600);
    }
  }
  else if (distance >= 10)
  {
    LM.setSpeed(100);
    RM.setSpeed(100);
    LM.run(FORWARD);
    RM.run(FORWARD);
  }
}

Improvements in Optimized Code

  1. Corrected Trigger Pulse Timing:
    • The trigger pulse was increased to 10 microseconds, ensuring proper ultrasonic burst generation and accurate distance measurements.
  2. Added Timeout in pulseIn():
    • A 30ms timeout prevents the program from hanging when no echo is detected.
  3. Handled Invalid Readings:
    • Introduced logic to set distance = -1 for invalid readings, avoiding false obstacle detection.
  4. Improved Motor Control Logic:
    • Eliminated redundant delays, ensuring smooth and responsive movements.
  5. Validated Distance Measurements:
    • The condition if (distance > 0 && distance < 10) ensures the robot reacts only to valid readings.

Why the Optimized Code Works Perfectly

  • Reliability: It handles sensor errors and environmental noise effectively.
  • Efficiency: Eliminates unnecessary delays, improving responsiveness.
  • Accuracy: Validates distance measurements, avoiding false triggers.
  • Error Handling: Prevents the robot from stalling due to sensor malfunctions.

Conclusion

The original code, while functional, had significant flaws that made it unreliable for practical use. The optimized version addresses these issues, making it robust and suitable for real-world applications. By implementing proper trigger pulse timing, adding timeout and error handling, and refining motor control logic, this code ensures your obstacle-avoiding robot performs flawlessly.

Don’t forget to post your experience as a comment at the bottom of this post…!

What to do if it still doesn’t work?

Identifying Ultrasonic Sensor Malfunctions Due to Motor Interference

Ultrasonic sensors can occasionally malfunction or mistrigger when motors draw large currents from the battery, especially in robots. This issue arises due to electrical noise and voltage fluctuations caused by the motors’ operation, which can interfere with the sensor’s signals. Even with an optimized code, such hardware-level issues may persist.

Don’t forget to read the same type of power supply issue that arises with servo motors. I have written one lab tested solution on such problem.

Symptoms of Malfunction:

  1. Erratic Distance Readings: The sensor may output rapidly fluctuating or unusually low values, even when no obstacle is present.
  2. False Triggering: The robot may stop or change direction without any obstacle in its path.
  3. Unresponsive Sensor: The sensor might fail to detect any obstacle or provide no readings intermittently.

How to Identify the Problem:

  1. Test Without Motors: Run the ultrasonic sensor independently, without powering the motors, to ensure it provides stable readings. Compare this to the sensor’s behavior when motors are active.
  2. Check Battery Voltage: Monitor the battery voltage while motors are running. Significant voltage drops can affect the sensor’s performance.
  3. Inspect Sensor Placement: Ensure the sensor and its wiring are physically separated from the motor wires to minimize electromagnetic interference.
  4. Use Decoupling Capacitors: Add capacitors (e.g., 100µF and 0.1µF in parallel) across the motor terminals and the battery supply to filter out noise.

By systematically testing and isolating components, you can determine if motor interference is causing the ultrasonic sensor to malfunction, even when using the new optimized code. Addressing these issues at the hardware level is essential for ensuring reliable robot operation.

So hope that this article will surely be helpful to you…!
Don’t forget to post your experience as a comment at the bottom of this post…!

Series Navigation<< Having trouble to drive Servo motor with Arduino Uno SMD? Get perfect solution now…
Dr. Dattaraj Vidyasagar
Dr. Dattaraj Vidyasagar

M.S. Electronics & Telecomm. (Cleveland Institute of Electronics, Ohio), Associate Member (IETE, Kolkata), Panelist on Dr. Homi Bhabha Foundation, Google certified educator (Level-1), Mentor of Change (MoC-1619) Niti Ayog, Government of India, International Robotics Trainer, Veteran of Applied Electronics since 35+ years.

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x