Ping))) yet again

I am a long time programmer but new to microcontrollers. I have been trying to create a program to find the clearest direction to turn a small bot when it meets an obstruction. So far, I have been frustrated getting this to work properly. I ping straight ahead until something is within 5 inches. Then I look right and left for the clearest path. The program pings forward just fine, pings left just fine, but when I try and ping in the other direction, I can’t get it to ping. I have tried switching and pinging right first and then left, but same results…second direction won’t ping. Which ever direction I ping in first, it will not ping in the other. (really has nothing to do with the actual direction…but rather a routine that does not want to work a second (or third) time…I think)

I have seen a lot of videos arduino/ping bots that do exactly what I am trying to do, so I know someone has gotten round this.

Here is the code…

#include <Servo.h> 

Servo myservo; 

const int pingPin = 10;
const int servoPin = 9;

long duration, inches, lastInches;
long rightDur = 0;
long leftDur = 0;

void setup() {
  Serial.begin(9600);
  myservo.attach(servoPin);
  myservo.write(90);        // start mid range
  }

void loop()
{
  // Clear right and left durations
  rightDur=0;
  leftDur=0;

  // Ping straight ahead
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  pinMode(pingPin, INPUT);

  inches = microsecondsToInches(pulseIn(pingPin, HIGH));

  // test that object less than five inches more than one ping in a row.
  if (inches < 5 && lastInches - inches < 5) {

      Serial.println("Looking for Path");

      // look left
      myservo.write(0);
      delay(1000);
    
      // loop until a measurement is obtained.

      Serial.print("Look Left ");
     do {
          pinMode(pingPin, OUTPUT);
          digitalWrite(pingPin, LOW);
          delayMicroseconds(2);
          digitalWrite(pingPin, HIGH);
          delayMicroseconds(5);
          digitalWrite(pingPin, LOW);
          pinMode(pingPin, INPUT);
          leftDur = pulseIn(pingPin, HIGH);
          Serial.print(" . ");
          } while (leftDur == 0);

      Serial.println();

      // look right
      myservo.write(180);
      delay(1000);
    
      // loop until a measurement is obtained.

      Serial.print("Look right ");
      do {
          pinMode(pingPin, OUTPUT);
          digitalWrite(pingPin, LOW);
          delayMicroseconds(12);
          digitalWrite(pingPin, HIGH);
          delayMicroseconds(5);
          digitalWrite(pingPin, LOW);
          pinMode(pingPin, INPUT);
          rightDur = pulseIn(pingPin, HIGH);
          Serial.print(" . ");
          } while (rightDur == 0);

      Serial.println();
      
      // reset back to mid range to look forward
      myservo.write(90);
    
      // display which is the clearer path
      if (rightDur > leftDur) {
          Serial.print("turn right!!  ");
          }
      else {
          Serial.print("turn left!!  ");
          }
      Serial.print("R=");
      Serial.print(rightDur);
      Serial.print("   L=");
      Serial.println(leftDur);  
      }
      
  // keep track of the last ping
  lastInches = inches;
  
  delay(100);
}

  
long microsecondsToInches(long microseconds)
{
  return microseconds / 74 / 2;
}

You have three blocks of identical code. This just screams for a function. In fact, the screaming is so loud that it is difficult to concentrate on just what your problem is.

The program pings forward just fine

You know this because of the Serial.print() statements?

pings left just fine

Again, you know this how?

but when I try and ping in the other direction, I can't get it to ping.

You wrote some code. It does something. The only thing that is clear, though, is that that something is not what you want. It is pretty clear what you want, but it is not at all clear just what the code does.

Does the servo at least move to the proper position?

Why does the ping get a longer trigger pulse looking right? What Paul said - put it in a function.

The ping WAS in a function but moved it back to the main loop trying to figure out what fails. I have attached the code with the function. I also remove the microsecondsToInches function as I don’t really care how many inches it is as long as I know the duration. This ONLY fails if the servo is connected (I was wrong in my first post). If the servo is not connected, the code does exactly what it should. If the servo is connected, the program will hang in the do loop for the second direction I try to ping in (even if I switch them, it’s always the second one). I know it is failing because program never assigns a value to rightDur causing the loop to not end and the ping LED does not flash while in that loop. Disconnect the servo and hit the reset and everything works fine.

#include <Servo.h> 

Servo myservo; 

const int pingPin = 10;
long duration, newPath, lastDur;

void setup() {
  Serial.begin(9600);
  myservo.attach(9);
 

}

void loop()
{
  myservo.write(90);
  duration = getPing();

  // 740 microseconds translates to about five inches 
  if (duration < 740 && lastDur - duration < 740) {
      Serial.println("object found");
      newPath=lookForPath();
      }
  lastDur=duration;
  delay(100);
}

int lookForPath() {
  long rightDur = 0;
  long leftDur = 0;
  
  Serial.println("Looking for Path");
  myservo.write(0);

  delay(5000);
  Serial.println("Looking Left ");
  do {
      leftDur = getPing();
      Serial.print(leftDur);
      } while (leftDur == 0);

  Serial. println();
  
  myservo.write(170);

  delay(5000);
  Serial.println("Looking Right ");  
  
  // Here is where the problem occures....If the servo is connected, the loop below will go on forever
  // because a value is never returned to rightDur and the ping LED never flashes in this loop.  
  // But if the servo is NOT connected, the ping LED flashes and rightDur is loaded  with a value 
  // on the first try and the code continues on as it should.
  
  do {
      rightDur = getPing();
      Serial.print(rightDur);
      } while (rightDur == 0);

  Serial. println();

  myservo.write(90);
  delay(5000);

  if (rightDur > leftDur) {
      Serial.print("turn right!!  ");
      return 0;
      }
  else {
      Serial.print("turn left!!  ");
      return 180;
      }
  }
  
long getPing() {
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  pinMode(pingPin, INPUT);
  return pulseIn(pingPin, HIGH);
  };

The ping WAS in a function but moved it back to the main loop trying to figure out what fails

And in doing so, you introduced a difference and possible error.

Ok, now I am not understanding that at all. No difference....in the function or out of the function, it behaves the same....and I have the same problem. I guess I don't know what you are saying. The only thing that makes a difference is if the servo is connected or not. With servo, ping does not work correctly; with servo disconnected, ping works exactly as it should. I am just trying to figure out how to get both to work.

Turned out to be another stupid user trick. Since I was only testing one of the servo routines, I was drawing power from logic power supply rather than an external source. Never occured to me that might be the problem because the servo seeme to work fine when it was connected. I put it on another power source and both the servo and the ping work perfectly.

Thanks for the responces anyway.

Ok, now I am not understanding that at all. No difference..

From your original post:

     Serial.print("Look Left ");
     do {
          pinMode(pingPin, OUTPUT);
          digitalWrite(pingPin, LOW);
          delayMicroseconds(2);
    Serial.print("Look right ");
      do {
          pinMode(pingPin, OUTPUT);
          digitalWrite(pingPin, LOW);
          delayMicroseconds(12);

Difficult to label that one a cut-and-paste error.

delayMicroseconds(12);

Gotcha. That was a failed experiment that I forgot to change back after it didn't help and before pasting the code here.