Receiving data from Ping sensor with as few delays as possible

Hey everyone, I'm working on a sumo robot that uses four Ping sensors, the kind with 3 pins, to find targets. On previous attempts I could be lazy and use the pulseIn function- as found in the Ping example code- however this time around the team is using drill motors, which in terms of software behave identically to brushless. Because a lot of timing is required for motor control as well as other parts of the system, interrupts and delays (beyond a few micros) are out of the question- That includes pulseIn. Attempting to replace pulseIn with non-blocking code has been unsuccessful, generally resulting in the sensors firing but not returning data, or firing once and remaining off. So far as I can tell most of it boils down to:

  • Not understanding the return pulse of the ultrasonic sensor

  • Unsure of what pulseIn(pingPin, HIGH) is looking for and timing, several Arduino forum posts and the documentation differ on how it's triggered on/off

Thanks, much appreciated.

const int pingPin = 3;
unsigned long start = 0;
bool readingPulse = false;
int stage = 0;

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
}

void loop() {
  unsigned long duration, inches, cm;

  if(stage == 0){
      stage = 1;
      digitalWrite(13, LOW);
      pinMode(pingPin, OUTPUT);
      digitalWrite(pingPin, LOW);
      delayMicroseconds(2);
      digitalWrite(pingPin, HIGH);
      delayMicroseconds(5);
      digitalWrite(pingPin, LOW);
      pinMode(pingPin, INPUT);
    }
  //here's where pulseIn would be
  if(stage == 1){
      if(digitalRead(pingPin) == HIGH && readingPulse == false){
          start = micros();
          readingPulse = true;
          digitalWrite(13, HIGH);
        }
      else if(digitalRead(pingPin) == LOW && readingPulse == true){
          stage = 0;
          duration = micros() - start;
          readingPulse = false;
          digitalWrite(13, LOW);
        }
    }

  inches = microsecondsToInches(duration);
  cm = microsecondsToCentimeters(duration);

  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
}

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

long microsecondsToCentimeters(long microseconds) {
  return microseconds / 29 / 2;
}

(Obviously this is a modified version of the Ping example code. Trying to minimize points of failure before getting too custom, since that code works fine with the sensors)

I think you need a third stage. You only want to do the conversion from duration to distance AFTER you have a good value for duration. As it is it will do that calculation on each pass of the loop, even while you are still measuring the pulse.

Do you really need the distance in both inches AND centimeters?

Hi,
Why not use the Ping Library to do all the work for you in one function?

https://playground.arduino.cc/Code/Ping

Tom.. :slight_smile: