# SRF05 problems when using 2 or more in tandem

So, as a part of a school project I’m working with a teammate on using these neat ultrasonic rangefinders to find the location of an object and use it as mouse input. We’re basically making a pseudo-touchscreen with three sensors and trilateration. The sensors will be placed around the edge of a screen and then when an object is in their range the Arduino will do a little bit of magic and interpret your intent as a click or select, and then send that to the computer. Right now we’re at the very first stage of implementation. We have an Arduino mega and 3 SRF05 Ultrasonic Rangefinders. We’re having trouble getting input from more than one sensor at a time, though. We found a great website online that’s using our exact sensor and we started doing basic tests with his code. This is code that we pilfered from his tutorial and modified slightly. The website is here.

int arrayIndex = 0;
int total = 0;
int averageDistance = 0;

int echoPin = 22;
int initPin = 24;
unsigned long pulseTime = 0;
unsigned long distance = 0;

void setup() {
pinMode(initPin, OUTPUT);
pinMode(echoPin, INPUT);
{
}
Serial.begin(9600);
}

void loop() {
digitalWrite(initPin, HIGH);
delayMicroseconds(10);
digitalWrite(initPin, LOW);
pulseTime = pulseIn(echoPin, HIGH);
distance = pulseTime/58;
arrayIndex = arrayIndex + 1;

{
arrayIndex = 0;
}

Serial.println(averageDistance, DEC);
delay(100);
}

So, this code takes readings on a single digital pin and averages a set of ten of them to remove jitter, as luckylarry terms it. It works great as is, but when we try and modify it to work with multiple sensors, it still only does the first sensor we define. Here’s our hacked code:

// written at: luckylarry.co.uk
// variables to take x number of readings and then average them
// to remove the jitter/noise from the SRF05 sonar readings
const int numOfReadings = 3;                   // number of readings to take/ items in the array
int arrayIndex = 0;                             // arrayIndex of the current item in the array
int total = 0;                                  // stores the cumlative total
int total2 = 0;
int total3 = 0;
int averageDistance = 0;                        // stores the average value
int averageDistance2 = 0;
int averageDistance3 = 0;

// setup pins and variables for SRF05 sonar device
int echoPin = 22;                                // SRF05 echo pin (digital 2)
int initPin = 24;                                // SRF05 trigger pin (digital 3)
int echoPin2 = 28;
int initPin2 = 30;
int echoPin3 = 34;
int initPin3 = 36;
unsigned long pulseTime = 0;                    // stores the pulse in Micro Seconds
unsigned long distance = 0;                     // variable for storing the distance (cm)
unsigned long pulseTime2 = 0;
unsigned long distance2 = 0;
unsigned long pulseTime3 = 0;
unsigned long distance3 = 0;

//setup
void setup()
{
pinMode(initPin, OUTPUT);                     // set init pin 3 as output
pinMode(echoPin, INPUT);                      // set echo pin 2 as input
pinMode(initPin2, OUTPUT);
pinMode(echoPin2, INPUT);
pinMode(initPin3, OUTPUT);
pinMode(echoPin3, INPUT);

// create array loop to iterate over every item in the array
{
}
// initialize the serial port, lets you view the
// distances being pinged if connected to computer
Serial.begin(9600);
}
// execute
void loop()
{
digitalWrite(initPin, HIGH);                    // send 10 microsecond pulse
digitalWrite(initPin2, HIGH);
digitalWrite(initPin3, HIGH);
delayMicroseconds(10);                  // wait 10 microseconds before turning off
digitalWrite(initPin, LOW);                     // stop sending the pulse
digitalWrite(initPin2, LOW);
digitalWrite(initPin3, LOW);

pulseTime = pulseIn(echoPin, HIGH);             // Look for a return pulse, it should be high as the pulse goes low-high-low
pulseTime2 = pulseIn(echoPin2, HIGH);
pulseTime3 = pulseIn(echoPin3, HIGH);

distance = pulseTime/58;                        // Distance = pulse time / 58 to convert to cm.
distance2 = pulseTime2/58;
distance3 = pulseTime3/58;
total= total - readings[arrayIndex];           // subtract the last distance

arrayIndex = arrayIndex + 1;                    // go to the next item in the array
// At the end of the array (10 items) then start again
{
arrayIndex = 0;
}

averageDistance = total / numOfReadings;      // calculate the average distance
// if the distance is less than 255cm then change the brightness of the LED

Serial.print(averageDistance, DEC);         // print out the average distance to the debugger
Serial.print(", ");
Serial.print(averageDistance2, DEC);
Serial.print(", ");
Serial.print(averageDistance3, DEC);
Serial.println();

delay(100);                                   // wait 100 milli seconds before looping again
}

I left Larry’s comments in on this one, sorry if it’s a little too much. So, we get garbage readings using that code (zeros, basically). I’m just wondering what the underlying problem is. We got it to work previously by breaking up the digitalWrite and pulseIn sections among the three sensors, letting each one do its business before trying to mess with another sensor. What’s the difference? I’m really curious about what’s going on underneath the hood here.

first thing you guys need to learn is array's to keep the code simpler - http://www.arduino.cc/en/Reference/Array

int total = 0; // stores the cumlative total
int total2 = 0;
int total3 = 0;
int averageDistance = 0; // stores the average value
int averageDistance2 = 0;
int averageDistance3 = 0;

would become

#define NUMSENSORS 3
int total[NUMSENSORS];
int averageDistance[NUMSENSORS];

and you can access the right sensor with loops like:

for (int i=0; i< NUMSENSORS; i++)
{
averageDistance = total*/ measurementsCount;*
* ...*
}
give it a try..

Well, right now I'm not as concerned with clean code as I am with figuring out what the problem with writing to and reading from multiple digital pins is. I'm not a paragon coder, but I've been around the block and I know what an array is. My question boils down to why does this fail to work:

digitalWrite(initPin, HIGH);                    // send 10 microsecond pulse
digitalWrite(initPin2, HIGH);
digitalWrite(initPin3, HIGH);
delayMicroseconds(10);                  // wait 10 microseconds before turning off
digitalWrite(initPin, LOW);                     // stop sending the pulse
digitalWrite(initPin2, LOW);
digitalWrite(initPin3, LOW);

pulseTime = pulseIn(echoPin, HIGH);             // Look for a return pulse, it should be high as the pulse goes low-high-low
pulseTime2 = pulseIn(echoPin2, HIGH);
pulseTime3 = pulseIn(echoPin3, HIGH);

distance = pulseTime/58;                        // Distance = pulse time / 58 to convert to cm.
distance2 = pulseTime2/58;
distance3 = pulseTime3/58;
pulseTime = pulseIn(echoPin, HIGH); // Look for a return pulse, it should be high as the pulse goes low-high-low
pulseTime2 = pulseIn(echoPin2, HIGH);
pulseTime3 = pulseIn(echoPin3, HIGH);

What if your second sensor's echo arrives before the first sensor's?

"pulseIn" works sequentially, not in parallel.

That might be the problem. I guess pulseIn might get confused while retrieving signals from a particular pin? The stumbling block for me is the fact that it works if it's split, but it doesn't when the statements are together. Is there any documentation for pulseIn anywhere?

EDIT: Found the Arduino docs on the main site. From pulseIn: "Returns the length of the pulse in microseconds. Gives up and returns 0 if no pulse starts within a specified time out." I'm getting zeroes, so perhaps that's the problem. Is there any way that I can dig a little deeper and find out if that's the issue? Like a pin monitor or something? I'm not a hardware guy.

You could look at the blink without delay example to give you ideas of how to monitor all three pins "simultaneously".

Is there any documentation for pulseIn anywhere?

Not only is there documentation, but you can look at the source if you want.
It's in "wiring_pulse.c"

I was actually trying to do the same thing as tgmoore. The main thing with your original code is that pulseIn() will not work in parallel like you’re asking it to. Once pulseIn() has started timing the first sensor and found the end point, the second sensor will already be at the end point and will return 0, this is why you might be seeing this value.

This code below solves that problem by doing each sensor one by one in an array type format. I should credit “mem” and “mjmcondor” for the ideas I used to create this code.

//This code uses 3 SRF05 sensors and outputs each sensors reading to the serial
//

int trigPins[] = {2,7,13}; // trigger pins which trigger the sensor to star
char *pingString[] = {"Right Side ","Front ", "Left Side "}; // prints in serial the direction
int echoPins[] = {4,8,12}; // echo pins setup location in array ex. i=0 is pin 4

void setup()
{
pinMode(trigPins[0] , OUTPUT);
pinMode(trigPins[1] , OUTPUT);
pinMode(trigPins[2] , OUTPUT);
pinMode(echoPins[0] , INPUT);
pinMode(echoPins[1] , INPUT);
pinMode(echoPins[2] , INPUT);

Serial.begin(9600);
}

//Ping function
unsigned long ping(int index)
{
unsigned long distance;

digitalWrite(trigPins[index], HIGH); // Send high pulse
delayMicroseconds(10); // Wait for 10 microseconds[this is the minimum time needed]
digitalWrite(trigPins[index], LOW); // stop sending pulse

distance = pulseIn(echoPins[index], HIGH); //Listen for echo
return (distance / 58) ; //output in cm
}

void loop()
{
unsigned long distancefromPing;
for(int i=0; i < 3; i++){
distancefromPing = ping(i);
Serial.print(pingString[i]);
Serial.print(distancefromPing);
Serial.print("cm, ");            //this will print the distances all horizontally, making it easier to read
delay(50);

}
Serial.println();                  //prints a new line when i >3
delay(50);
}

I have tried this and it does work