Go Down

Topic: SRF05 problems when using 2 or more in tandem (Read 2764 times)previous topic - next topic

tgmoore

Apr 05, 2011, 10:00 pm
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.

Code: [Select]
`const int numOfReadings = 10;                   int readings[numOfReadings];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);  for (int thisReading = 0; thisReading < numOfReadings; thisReading++)  {    readings[thisReading] = 0;  }  Serial.begin(9600); }void loop() {digitalWrite(initPin, HIGH);delayMicroseconds(10);digitalWrite(initPin, LOW);pulseTime = pulseIn(echoPin, HIGH);distance = pulseTime/58; total= total - readings[arrayIndex];readings[arrayIndex] = distance;total= total + readings[arrayIndex];arrayIndex = arrayIndex + 1;if (arrayIndex >= numOfReadings){    arrayIndex = 0;}averageDistance = total / numOfReadings;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:
Code: [Select]
`// 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 readingsconst int numOfReadings = 3;                   // number of readings to take/ items in the arrayint readings[numOfReadings];                    // stores the distance readings in an arrayint readings2[numOfReadings];int readings3[numOfReadings];int arrayIndex = 0;                             // arrayIndex of the current item in the arrayint total = 0;                                  // stores the cumlative totalint total2 = 0;int total3 = 0;int averageDistance = 0;                        // stores the average valueint averageDistance2 = 0;int averageDistance3 = 0;// setup pins and variables for SRF05 sonar deviceint 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 Secondsunsigned 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;//setupvoid 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  for (int thisReading = 0; thisReading < numOfReadings; thisReading++)  {    readings[thisReading] = 0;  }// initialize the serial port, lets you view the // distances being pinged if connected to computer     Serial.begin(9600); }// executevoid 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    total2 = total2 - readings2[arrayIndex];    total3 = total3 - readings3[arrayIndex];    readings[arrayIndex] = distance;                // add distance reading to array    readings2[arrayIndex] = distance2;    readings3[arrayIndex] = distance3;        total = total + readings[arrayIndex];            // add the reading to the total    total2 = total + readings2[arrayIndex];    total3 = total + readings3[arrayIndex];        arrayIndex = arrayIndex + 1;                    // go to the next item in the array// At the end of the array (10 items) then start again    if (arrayIndex >= numOfReadings)    {        arrayIndex = 0;    }        averageDistance = total / numOfReadings;      // calculate the average distance    averageDistance2 = total2 / numOfReadings;    averageDistance3 = total3 / numOfReadings;  // 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.

robtillaart

#1
Apr 05, 2011, 10:11 pm

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..
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

tgmoore

#2
Apr 05, 2011, 10:16 pm
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:

Code: [Select]
`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;`

AWOL

#3
Apr 05, 2011, 11:09 pmLast Edit: Apr 05, 2011, 11:17 pm by AWOL Reason: 1
Code: [Select]
` 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.
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

tgmoore

#4
Apr 06, 2011, 02:08 amLast Edit: Apr 06, 2011, 02:12 am by tgmoore Reason: 1
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.

AWOL

#5
Apr 06, 2011, 08:44 amLast Edit: Apr 06, 2011, 09:26 am by AWOL Reason: 1
You could look at the blink without delay example to give you ideas of how to monitor all three pins "simultaneously".

Quote
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"
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

bcd_uno

#6
Jul 08, 2011, 03:26 am
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.

Code: [Select]
`//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 starchar *pingString[] = {"Right Side ","Front ", "Left Side "}; // prints in serial the directionint echoPins[] = {4,8,12}; // echo pins setup location in array ex. i=0 is pin 4void 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 functionunsigned 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

Go Up