Pages: [1]   Go Down
Author Topic: SRF05 problems when using 2 or more in tandem  (Read 1191 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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:
// 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 readings[numOfReadings];                    // stores the distance readings in an array
int readings2[numOfReadings];
int readings3[numOfReadings];
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
  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);
 }
// 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
    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.

Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 168
Posts: 12417
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


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++)
{
  total = readSensor(i);
  averageDistance = total/ measurementsCount;
  ...
}

give it a try..
Logged

Rob Tillaart

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

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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;
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24286
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
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.
« Last Edit: April 05, 2011, 04:17:01 pm by AWOL » Logged

"Pete, it's a fool 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.

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
« Last Edit: April 05, 2011, 07:12:30 pm by tgmoore » Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24286
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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"
« Last Edit: April 06, 2011, 02:26:48 am by AWOL » Logged

"Pete, it's a fool 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.

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
//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
Logged

Pages: [1]   Go Up
Jump to: