Stingray + PING)) object avoidance help

I recently bought a Sting Ray chassis from Parallax and am using an UNO R3, BOE Shield, and motor shield to control it. It’s my first experience outside of a BOE BOT, and I’m trying to learn as I go. I’m trying to make it autonomous for now, it has three PING sensors across the front, and I’m having some trouble getting them to work with each other. In this particular code, the Ping sensors will work, and I can read it through the serial monitor without the “forward”, “goRight”, “goleft” function calls in it. So, it will sit still and read distance from all three sensors, but if you add motor direction controls, the serial monitor stops working and the sensors don’t seem to all work. Am I out of memory? Or is my code terrible? I have tried other code including the “newPing” library and totally different code, but similar results.

#include <Ping.h>
// initialize
const int pingPin1 = 5 ;          // pin used for the Ping Sensor
const int pingPin2 = 6;           //Right Ping sensor
const int pingPin3 = 7;           //Left Ping sensor
int BaudRate = 9600 ;             // Baud rate
 
// set up
void setup() {
  Serial.begin(BaudRate) ;        // Setup Serial
  //Setup Channel A
  pinMode(12, OUTPUT);            //Initiates Motor Channel A pin
  pinMode(9, OUTPUT);             //Initiates Brake Channel A pin

  //Setup Channel B
  pinMode(13, OUTPUT); //Initiates Motor Channel B pin
  pinMode(8, OUTPUT);  //Initiates Brake Channel B pin
  digitalWrite(9, HIGH);  //Engage the Brake for Channel A
  digitalWrite(8, HIGH);  //Engage the Brake for Channel B
  delay(2000);
  
}
 
void loop()
{
  unsigned long duration1;
  int inches1, inches2, inches3;

  // Read distance 1
  pinMode(pingPin1, OUTPUT);
  digitalWrite(pingPin1, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin1, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin1, LOW);
  pinMode(pingPin1, INPUT);
  duration1 = pulseIn(pingPin1, HIGH);
  inches1 = microsecondsToInches(duration1);
  
  unsigned long duration2;  
  
  // Read distance 2
  pinMode(pingPin2, OUTPUT);
  digitalWrite(pingPin2, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin2, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin2, LOW);
  pinMode(pingPin2, INPUT);
  duration2 = pulseIn(pingPin2, HIGH);
  inches2 = microsecondsToInches(duration2);
  
  unsigned long duration3;  
  
  // Read distance 3
  pinMode(pingPin3, OUTPUT);
  digitalWrite(pingPin3, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin3, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin3, LOW);
  pinMode(pingPin3, INPUT);
  duration3 = pulseIn(pingPin3, HIGH);
  inches3 = microsecondsToInches(duration3);

  
  if (inches2 > 20)
  {
    forward();
  }  
 
  else if (inches1 <= 20) 
  {    
    goLeft();
  }
  else if (inches3 <= 20)
  {
    goRight();
  {
    Serial.print ("Distance : ") ;
    Serial.print(inches1);
    Serial.print("in, ");
    Serial.print(inches2);
    Serial.print("in, ");
    Serial.print(inches3);
    Serial.print("in, ");

    Serial.println();
  }
  delay (10); 
  }
}

void forward()
{
  //Motor A forward @ full speed
  digitalWrite(12, HIGH); //Establishes forward direction of Channel A
  digitalWrite(9, LOW);   //Disengage the Brake for Channel A
  analogWrite(3, 250);   //Spins the motor on Channel A at full speed

  //Motor B backward @ half speed
  digitalWrite(13, LOW);  //Establishes backward direction of Channel B
  digitalWrite(8, LOW);   //Disengage the Brake for Channel B
  analogWrite(11, 250);    //Spins the motor on Channel B at full speed
}
void reverse(){
  digitalWrite(9, HIGH);   //engage the Brake for Channel A
  digitalWrite(8, HIGH);   //engage the Brake for Channel B
  delay(500);
  //Motor A reverse @ full speed
  digitalWrite(12, LOW); //Establishes forward direction of Channel A
  digitalWrite(9, LOW);   //Disengage the Brake for Channel A
  analogWrite(3, 250);   //Spins the motor on Channel A at full speed

  //Motor B backward @ half speed
  digitalWrite(13, HIGH);  //Establishes backward direction of Channel B
  digitalWrite(8, LOW);   //Disengage the Brake for Channel B
  analogWrite(11, 250);    //Spins the motor on Channel B at full speed
}
void goRight(){
  digitalWrite(9, HIGH);  //Engage the Brake for Channel A
  digitalWrite(8, HIGH);  //Engage the Brake for Channel B
  delay(20);
  //Motor A forward @ full speed
  digitalWrite(12, HIGH); //Establishes forward direction of Channel A
  digitalWrite(9, LOW);   //Disengage the Brake for Channel A
  analogWrite(3, 200);   //Spins the motor on Channel A at full speed
  //Motor B backward @ half speed
  digitalWrite(13, HIGH);  //Establishes backward direction of Channel B
  digitalWrite(8, LOW);   //Disengage the Brake for Channel B
  analogWrite(11, 200);    //Spins the motor on Channel B at full speed
  delay(200);
}
void goLeft(){
  digitalWrite(9, HIGH);  //Engage the Brake for Channel A
  digitalWrite(8, HIGH);  //Engage the Brake for Channel B
  delay(20);
  //Motor A forward @ full speed
  digitalWrite(12, LOW); //Establishes forward direction of Channel A
  digitalWrite(9, LOW);   //Disengage the Brake for Channel A
  analogWrite(3, 200);   //Spins the motor on Channel A at full speed
  //Motor B backward @ half speed
  digitalWrite(13, LOW);  //Establishes backward direction of Channel B
  digitalWrite(8, LOW);   //Disengage the Brake for Channel B
  analogWrite(11, 200);    //Spins the motor on Channel B at full speed
  delay(200);
}
  
long microsecondsToInches(long microseconds)
{
    return microseconds / 74 / 2;
}

Let's play "spot the difference"

// Read distance 1
  pinMode(pingPin1, OUTPUT);
  digitalWrite(pingPin1, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin1, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin1, LOW);
  pinMode(pingPin1, INPUT);
  duration1 = pulseIn(pingPin1, HIGH);
  inches1 = microsecondsToInches(duration1);
// Read distance 2
  pinMode(pingPin2, OUTPUT);
  digitalWrite(pingPin2, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin2, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin2, LOW);
  pinMode(pingPin2, INPUT);
  duration2 = pulseIn(pingPin2, HIGH);
  inches2 = microsecondsToInches(duration2);

You'd cut the amount of code if you factored those three sections into a single function. Shorter code, easier to debug.

 unsigned long readDistance (byte pingPin)
 {
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  pinMode(pingPin, INPUT);
  return pulseIn(pingPin, HIGH);
}

Giving some names to the motor pins would help readability and maintainability too.

The Serial.print statements will only be executed if inches3 <= 20 because they are in the if block

Is this better, or have I gone way off track? Also, how can I work in a coversion to inches or cm to this?

byte pingPinR = 5 ;                  // pin used for the Ping Sensor
byte pingPin = 6;                  // Right Ping sensor
byte pingPinL = 7;                    // Left Ping sensor

}
 
void loop()
{
  readDistance(pingPin);
  readDistance(pingPinL);
  readDistance(pingPinR);
  
  Serial.print ("Distance : ") ;
  Serial.print(readDistance(pingPinL));
  Serial.print("in, ");
  Serial.print(readDistance(pingPin));
  Serial.print("in, ");
  Serial.print(readDistance(pingPinR));
  Serial.print("in, ");
  Serial.println();
  
  if (readDistance(pingPin) > 1000)
  {
    forward();
  }  
 
  else if (readDistance(pingPin) <= 1000) 
  { 
    (readDistance(pingPinL) > (readDistance(pingPinR)));
    goLeft();
  }
    else if ((readDistance(pingPinR)) > (readDistance(pingPinR)));
    goRight();
}

unsigned long readDistance (byte pingPin)
 {
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  pinMode(pingPin, INPUT);
  return pulseIn(pingPin, HIGH);
  }

Is this better, or have I gone way off track?

Not good - the "readDistance" is a function that returns a value, not a global pin number.

Edit: Sorry, misread it, but you shouldn't keep calling it like you have, and never call it like this

 readDistance(pingPin);
  readDistance(pingPinL);
  readDistance(pingPinR);
  • you're just wasting time, and achieving nothing.
unsigned long forwardRange = readDistance(pingPin);
unsigned long leftRange   readDistance(pingPinL);
unsigned long rightRange   readDistance(pingPinR);

, then use the variables.

Also, how can I work in a coversion to inches or cm to this?

unsigned long forwardRangeInches = microsecondsToInches(readDistance(pingPin) );

Thank you! You are the best. That was exactly what I needed. The Stingray works autonomously now, although it could use some tweaks. I tried the code below, and while it was successful in avoiding objects, it ended up in a spin several times. Granted, it was in a smallish area, but it should do better. I’m sure my if/else logic is flawed, but I’m working on it.

edit: discovered the left range would return 5 inches randomly, every second or so. just once, then go normal, then 5 inches, even though it was looking off into empty space. Is it possibly receiving a false return?

void loop()
{
  unsigned long forwardRange = readDistance(pingPin);
  unsigned long leftRange = readDistance(pingPinL);
  unsigned long rightRange = readDistance(pingPinR);
  unsigned long forwardRangeInches = microsecondsToInches(readDistance(pingPin));
  unsigned long leftRangeInches = microsecondsToInches(readDistance(pingPinL) );
  unsigned long rightRangeInches = microsecondsToInches(readDistance(pingPinR) );
  
  Serial.print ("Distance : ") ;
  Serial.print(leftRangeInches);
  Serial.print("in, ");
  Serial.print(forwardRangeInches);
  Serial.print("in, ");
  Serial.print(rightRangeInches);
  Serial.print("in, ");
  Serial.println();
    
 if (forwardRangeInches <= 15)
      {
        brake();
        reverse();
      } 
        else if (leftRangeInches <15)
             {
            goRight();
             }
        else if(rightRangeInches <= 15)
            {
             goLeft();
            }
                      
      else 
      {
        forward();
      }
}
unsigned long readDistance (byte pingPin)
 {
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  pinMode(pingPin, INPUT);
  return pulseIn(pingPin, HIGH);
  }

You could shorten the code a little, by making readDistance() call microsecondsToInches(), so that readDistance() returns a value in inches, not a time.

PaulS: You could shorten the code a little, by making readDistance() call microsecondsToInches(), so that readDistance() returns a value in inches, not a time.

I attempted this, but had trouble. I will look into it further, but for now, I thank you all for your help. The Stingray is now autonomous, probably needing only a few tweaks until I decide to do something else with it.