3

I am using the HC-SR04 ultra sound sensor for Arduino. I have used the following code to calculate distance and it works perfectly.

  long duration;
  digitalWrite(trigger, LOW);  
  delayMicroseconds(2);
  digitalWrite(trigger, HIGH);
  delayMicroseconds(10); 
  digitalWrite(trigger, LOW);
  duration = pulseIn(echo, HIGH);
  distance = (duration/2) / 29.1;

However I want to use three more of these sensors, for a total of four. This block of code will be called every time I want to find the distance of one of the sensors. I am worried however that delayMicroseconds() pauses the entire program and that I cannot perform other tasks in while the sensors are working (e.g. driving wheels, it's a robot). The following code is object oriented for each sensor.

class distSensor{
   int trigPin;
   int echoPin;
   int distance;

   //Will be used in timer
   unsigned long previousMillis;

   public:
   distSensor(int tPin,int ePin){
   trigPin = tPin;
   echoPin = ePin;

   pinMode(trigPin, OUTPUT);
   pinMode(echoPin, INPUT);

   previousMillis = 0;
 }

 int calculateDistance(){

  //records time since program start
  unsigned long currentMillis = millis();

  long duration;
  digitalWrite(trigPin, LOW); 

  //check if the previous time the method was called is greater than the interval of 2
  if(currentMillis - previousMillis > 2){
    digitalWrite(trigPin, HIGH);
    previousMillis = currentMillis;
  }

  //check if distance between current time and previous time it was called is greater than interval of 10.
  if(currentMillis - previousMillis > 10){
      digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  }
  return distance;
 }
};

In the calculateDistance() method I am trying to do the same thing as the first code but without delay() and instead a timer. But when I run the program it does not work and distance is read as 0. Can anyone help me rewrite the HC-SR04 code from the start that doesn't delay the whole program?

  • 1
    Trying to use multiple sound based distance sensors at the same time may be problematic. If they should "hear" each other their operation my result in unexpected values. Consider using optical distance sensors based on the parallax principle. – st2000 Apr 8 '17 at 14:18
  • 1
    theyre faced perpendicular and in opposite directions, thats not the issue – Don Grey Apr 8 '17 at 14:21
  • 1
    Likely there are configurations (room corners) which may still confuse sodar and sonar sensors which are trying to sample at the same time. – st2000 Apr 8 '17 at 14:56
  • 1
    pulseIn() also blocks, so that won't help; you need an interrupt. – dandavis Apr 9 '17 at 4:35
  • You said that the distance read is 0 ; your code does not work because you trigger the sensor with delays of 2ms and 10ms, you should use delayMicroseconds of 2us and 10us. As these delays are in us, you dont need to avoid them, you can use delayMicroseconds in your codes. The pulseIn() function blocks for too long, this is the one you have to avoid with interrupt as dandavis said. – Arno Bozo yesterday
2

delay() causes the processor to do nothing but wait. You need to switch to millis().

In your code, you need to "grab" the current time using millis() and store it in a variable. Add the number of milliseconds that you want to wait to this variable - you will have to consider the case where this value will overflow for a complete solution. Then, in your code, you need to create an infinite loop where you check what millis() returns. When your stored value and millis() match, it is time to execute the code that would normally come after the delay() call.

Here, Arduino Playground - How and Why to avoid delay(), delay() and millis() are discussed in detail.

So that this answer will cover your question, consider placing all your events which need to be timed into this one infinite loop. Also, consider keeping independent variables, one for each timed event, such that different events are timed independently.

  • ` //check if the previous time the method was called is greater than the interval of 2 if(currentMillis - previousMillis > 2){ digitalWrite(trigPin, HIGH); previousMillis = currentMillis; } //check if distance between current time and previous time it was called is greater than interval of 10. if(currentMillis - previousMillis > 10){ digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distance = (duration/2) / 29.1; } ` I have done that already but it still does not work. currentmillis is the time counted from program start, – Don Grey Apr 8 '17 at 14:12
  • That is a very difficult comment to read. You need to consider overflow of the variable type used and of the type returned by the medthod call to millis(). I don't think you included that in your comment above. Also, for the way you are describing events, you might also have to worry about using unsigned integers. It may be simpler to check if millis() returns an expected value rather than finding the difference between what millis() returns and some variable. – st2000 Apr 8 '17 at 14:53
-3

Try referring to the code in this question, HC-SR04 returning incorrect distances.

I had the same problem once.

  • 1
    This is a StackOverflow link to a different answer which answers his question. – Rishi Swethan Jun 12 '17 at 7:50
  • Remove the unlike, please. – Rishi Swethan Jun 12 '17 at 8:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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