I want to connect multiple Ultrasonic sensors to my Arduino board. For that, I need multiple pulseIn() functions to work at the same time. How can I do that?
-
PulseIn() is an Arduino-specific thing. Like much of the Arduino software, it's a user-friendly thing, but it's far from optimal. If you want Arduino-specific help, you might be better asking on the Arduino stack exchange. On the other hand, if you want help to do this directly with the timers on the Atmel chip, this site is the right place. In that case, you'll need to edit your question to say which microprocessor your Arduino uses.– Jack BOct 1, 2016 at 16:30
-
As it stands, the question could be migrated to the Arduino stackexchange.– gbulmerOct 1, 2016 at 16:38
2 Answers
You can't use pulseIn() if you want to use both ultrasonic sensors at the same time.
So either:
- don't use pulseIn, and instead do that part yourself using eg. digitalRead,
- use the ultrasonic sensors sequentially, one then the other, or
- use pin-change interrupts to sense the signal pulse return.
The easiest approach is to use the ultrasonic sensors sequentially. In that case use the form pulseIn(PIN, value, timeout);
, where timeout
, in microseconds sets the maximum time to wait for a pulse.
This is practical if you know the realistic range is within a couple of metres. The speed of sound is 343.2 metres per second, or 0.3432 metres per millisecond. So if timeout
is set to 3000 microseconds (3 milliseconds), then it will wait for an echo up to (roughly) 0.5 metres away.
Edit: The distance to the object, measured by timing the delay, is half the total distance travelled because the sound travels to the object, then bounces back to the sensor.
Ie. distance to object = total distance travelled by sound / 2
An alternative is to do what pulseIn does, but for more than one pin. This is simpler than the real pulseIn code, but illustrates the idea:
int inPin1 = ...;
int inPin2 = ...;
void setup() {
// ... other stuff, then set up the pins
pinMode(inPin1, INPUT);
pinMode(inPin2, INPUT);
}
void loop() {
// start ultrasound 1
// start ultrasound 2
// wait for ultrasound 1 to send pulse
// wait for ultrasound 1 to send pulse
long startTime = micros();
while (digitalRead(inPin1)==LOW && digitalRead(inPin1)==LOW) {
; // do nothing
}
long stop1st = micros();
int firstBack = -1;
while (digitalRead(inPin2)==LOW) { // wait for the other if it was 1 first
firstBack = inPin1; // remember pin 1 returned first
}
while (digitalRead(inPin1)==LOW) { // wait for the other if it was 2 first
firstBack = inPin2; // remember pin 2 returned first
}
long stop2nd = micros();
// now have the two return times, and the pin which returned first
}
You could read the source of pulseIn()
and write better code than this.
The third option, to use external or pin-change interrupts, depends on which Arduino you are using. A normal ATmega328 has a couple of pins, 2 and 3, which have their own 'external' interrupt service routines (ie. each pin has a 'function' which is called when the hardware detects a signal change on a pin). To see how to attach them, see attachInterrupt.
Other pins can also be used with a 'pin change' interrupt, but each interrupt has to figure out which of a port (up to 8 pins) has triggered it, so it isn't as quick and simple.
The idea here is to start the ultrasonic sensors exactly as before, save the time they are started, exactly as before, but let a short interrupt routine capture the time that the returning echo pulse triggers the pin.
There is a little bit of care in making sure the times are captured and the main loop signalled.
You might choose to dedicate a timer to measuring the ultrasounds round trip, if you want higher resolution and lower jitter than the normal 4 microsecond timer. A microsecond is about 0.34mm, so 4 microsecond is about 1.3mm error.
-
"So if timeout is set to 3000 microseconds (3 milliseconds), then it will wait for an echo up to (roughly) 0.5 metres away." It should be close to ~1.02 meters away. Am I right? Oct 1, 2016 at 17:29
-
@Mat_python - sound travels 0.3432m/millisecond, so in 3 milliseconds it will travel about 1 metre. An ultrasound sensor works by bouncing sound, so sound has to travel to the object, and then return. So you are measuring round-trip time, hence the distance to the object is total distance/2.– gbulmerOct 2, 2016 at 8:15
-
Thank you. I thought so. I am trying to detect a moving object. i.e, a soccer ball. I am working on building a goal counter. The problem with an ultrasonic sensor is it misses the ball sometimes. I used two ultrasonic sensors to detect a soccer ball, which could be moving really fast, but it detected 8 times out of 10. what could be the problem? Is there any other sensors I can use to detect the soccer ball passing between 0-1.5 meters of distance from the sensor. I also tried PIR sensor, but it does not work well for non-living objects. Oct 2, 2016 at 15:51
-
@Mat_python - if all you want to make is a soccer ball counter, would detecting something crossing a line do? That could be easy to make. Or do you mean drive around a field counting balls? You'll need to be clear about the problem, and it may be worth writing a new question.– gbulmerOct 2, 2016 at 17:35
-
Yes. I want to make a soccer ball counter, and detecting something crossing a line will work. I tried using ultrasonic sensor. But, it misses if the ball is too fast. what are other alternatives? I also wrote new question thread on this here : arduino.stackexchange.com/questions/29748 Oct 2, 2016 at 19:12
here is how i fixed the problem for my self -5 years later im doing this on my own, running the pulsein code twice within the same loop function WILL NOT WORK, i got around it by adding a second separate part, idk the name if its a function or library...but here is my example code simply creating a distance measuring from 2 different sensors. i hope this help
const int trigPin =6;
const int echoPin =5;
const int trigPin2 = 11;
const int echoPin2 = 10;
long duration2;
long distance2;
long duration;
int distance;
void setup() {
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
pinMode(trigPin2, OUTPUT);
pinMode(echoPin2, INPUT);
Serial.begin(9600); // Starts the serial communication
}
void loop() {
digitalWrite(trigPin, LOW);// Clears the trigPin
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance= duration*0.034/2;
Serial.println(distance2);
test();
}
void test()
{
digitalWrite(trigPin2, LOW);// Clears the trigPin
delayMicroseconds(2);
digitalWrite(trigPin2, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin2, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration2 = pulseIn(echoPin2, HIGH);
distance2= duration2*0.034/2;
}
my code only prints the second sensor distance not both as you can see...not perfect this was a quick sketch i did