2

I'm using 2 SRF02 sensors on the same Arduino board to attempt to have the transmitter only pulse the 40 KHz wave, while the receiver will be only taking a fake range, i.e. picking up a reading based on another transmission.

I've been using SoftwareSerial and need to know how to synchronize the time for the receiver to know when the transmitter sent the data. What I found is that I'm going to have to do this using start and stop bytes to set them in the same cycle.

How can I do this?

This is my current code:

#include <SoftwareSerial.h>  
SoftwareSerial mySerial(10,11); // RX, TX 

void SendCmd(unsigned char address,unsigned char cmd) {
  mySerial.write(address);
  //set the address of SRF02(factory default is 0)
  delayMicroseconds(100);
  //serial data is fixed at 9600,N,8,2,so we need some time to create the second stop bit
  mySerial.write(cmd);
  //send the command to SRF02
  delayMicroseconds(100);
  //serial data is fixed at 9600,N,8,2,so we need some time to create the second stop bit
}
void setup(void) {
  Serial.begin(9600);
  mySerial.begin(9600);
  Serial.println("SRF02 TEST!");
}

void loop(void) {
  unsigned int reading;
  SendCmd(0x00,0x5C);
  //Transmit 8 cycle 40khz pulse from address 0x00 - transmitter
  delay(70);
  //time for SRF02 to measure the range
  SendCmd(0x02,0x57);
  //Get Fake Range at Address 0x02 - receiver
  delay(10);
  //wait for some time,let the Arduino receive 2 bytes data from the TX pin of SRF02
  if(mySerial.available()>=2) {
    //if two bytes were received
    reading = mySerial.read()<<8;
    //receive high byte (overwrites previous reading) and shift high byte to be high 8 bits
    reading |= mySerial.read();
    // receive low byte as lower 8 bits
    Serial.print(reading);
    // print the reading
    Serial.println("cm");
    //Serial.println("Time Sent: "); 
    //Serial.print(T_sent);
  }
  delay(250);
  // wait a bit since people have to read the output :)
}

3 Answers 3

0

Your code bit

SendCmd(0x00,0x5C);//Transmit 8 cycle 40khz pulse from address 0x00 - transmitter
delay(70);//time for SRF02 to measure the range
SendCmd(0x02,0x57); //Get Fake Range at Address 0x02 - receiver

will send a sound burst, delay 70 ms, then start listening for the burst, which by then will have traveled around 24 meters and probably be no longer audible.

You should instead start the fake range listener immediately after sending the burst. The general idea for one approach is as follows:

  • Record time (eg, t1=micros();)
  • Send burst (eg, SendCmd(0,0x5C);)
  • Record time (eg, t2=micros();)
  • Listen for burst (eg, SendCmd(2,0x58); // Get microseconds)
  • Wait 70 ms, then read microseconds result t3
  • Compute corrected total microseconds, tm=t3+t2-t1
  • Convert microseconds to cm

Note use of command 0x58 instead of 0x57 to get microseconds instead of cm. If you used 0x57, instead of adding t2-t1 to t3, you would add t2-t1 microseconds-converted-to-cm to a cm reading.

The reason for the computation tm=t3+t2-t1 is that the second command is issued about t2-t1 microseconds later than the first command, as explained in the next paragraph.

There is an unknown delay d1 between when t1 is recorded and when the first SRF02 acts; and there is an unknown delay d2 between when t2 is recorded and when the second SRF02 begins listening. The correct amount to add to t3 is t2+d2-(t1+d1), which is t2-t1 if d1 equals d2, a more-or-less plausible assumption. If your experiments reveal a constant error, add a small constant offset to compensate.

I doubt you should have the delayMicroseconds(100); statements in SendCmd(), and would recommend getting the code to work ok, then see if it still works ok when you take them out. The delay(10); is unnecessary if you rewrite your 2-character-wait correctly (ie as a while rather than an if), and the delay(70); is unnecessary if you start conversion with command 0x5A, “Fake Ranging Mode - Result in centimeters, automatically Tx range back to controller as soon as ranging is complete” and then properly wait for two characters to arrive, instead of a blind wait followed by a test if they've arrrived.

1
  • unsigned int reading; unsigned long t1=micros(); SendCmd(0, 0x5C);//send pulse with transmitter unsigned long t2=micros(); SendCmd(2, 0x58);//return value in microseconds delay(70);//time for SRF02 to measure the range //SendCmd(0x02,0x5E); unsigned long t3 = SendCmd(2,0x5E); unsigned long tm = t3+t2-t1;
    – Umbus
    Nov 25, 2015 at 7:44
0
 unsigned int reading;
  unsigned long t1=micros();
  SendCmd(0, 0x5C);//send pulse with transmitter
  unsigned long t2=micros();
  SendCmd(2, 0x58);//return value in microseconds

  delay(70);//time for SRF02 to measure the range
  //SendCmd(0x02,0x5E);
  unsigned long t3 = SendCmd(2,0x5E);
  unsigned long tm = t3+t2-t1;

Hey thanks for the input. When I created t3, I get an error saying void value not ignored as ought to be.

3
  • After you do SendCmd(2,0x5E);, you need to read the serial reply from 2nd SRF02, and store that 16-bit value into t3. Nov 25, 2015 at 18:54
  • i dont know how to store the value returned, it tells me the the void value not ignored as ought to be. am i not supposed to use t3 = SendCmd(2, 0x5E) to store ?
    – Umbus
    Nov 25, 2015 at 18:58
  • SendCmd() doesn't return a non-void value, so you aren't supposed to say something = SendCmd(...). Instead, just issue the SendCmd(2, 0x5E), then read 2 serial bytes and combine into 16-bit value, like you did for reading Nov 25, 2015 at 19:02
0

This is my updated code based on your suggestions, jwpat, although I did not understand your comment with delay(70); not being needed if I start conversion with (2,0x5A).

#include <SoftwareSerial.h>  
SoftwareSerial mySerial(10,11); // RX, TX 

void SendCmd(unsigned char address,unsigned char cmd)
{
  mySerial.write(address);//set the address of SRF02(factory default is 0)
  //delayMicroseconds(100);//serial data is fixed at 9600,N,8,2,so we need some time to creat the sencond stop bit
  mySerial.write(cmd);//send the command to SRF02
  //delayMicroseconds(100);//serial data is fixed at 9600,N,8,2,so we need some time to creat the sencond stop bit
}
void setup(void)
{
  Serial.begin(9600);
  mySerial.begin(9600);
  Serial.println("SRF02 TEST!");
}
void loop(void)
{
  unsigned long t3;
  unsigned long t1=micros();//time tx command issued
  SendCmd(0, 0x5C);//send pulse with transmitter
  unsigned long t2=micros();//time rx command issued
  SendCmd(2, 0x58);//listen for pulse
  //SendCmd(2, 0x5A);
  delay(70);//time for SRF02 to measure the range
  //SendCmd(0x02,0x5E);
  SendCmd(2,0x5E);//Get range






 while(mySerial.available()>=2)//if two bytes were received
  {
    t3 = mySerial.read()<<8;//receive high byte (overwrites previous reading) and shift high byte to be high 8 bits
    t3 |= mySerial.read();// receive low byte as lower 8 bits
    unsigned long Tm = t3 + t2 - t1;//total amt of microseconds between pulse and reading
    unsigned long Dist = (Tm/29); //converting microseconds to cm
    Serial.print(Dist); // print the reading
    Serial.println("cm");
    //Serial.print(tm);
    //Serial.println("ms");

  }
  delay(250); // wait a bit since people have to read the output :)
}

After running this code my results keep being the following values regardless of me shifting the distance between the sensors: 72cm enter image description here

8
  • Instead of while(mySerial.available()>=2) { t3 = mySerial.read()<<8; ... as you have, say while(mySerial.available() < 2) {}; t3 = mySerial.read()<<8;. That is, you need to stall until two characters are available from the 5E command, and then read them. Probably what's happening now is that first time in, since mySerial.available()>=2 is false, your while doesn't run; so you return from loop() and then loop() and steps on the ongoing conversion, messing it up; eventually two characters arrive; and this happens over and over the same way. Note, you should edit this stuff into Q Nov 25, 2015 at 20:41
  • I made the changes and what i now get is a value of 2302cm in my Serial Monitor
    – Umbus
    Nov 25, 2015 at 21:20
  • Perhaps you can edit your question and put current code into it. 2302cm is about the distance one expects for a 70 ms delay. If you are indeed now using while(mySerial.available() < 2) {}; to stall until 2 chars are available you should be able to remove the 70 ms delay and change from 58 command to 5A command. (Adding "answers" that are really part of the question is a no-no. Edit the question instead.) Nov 25, 2015 at 22:00
  • gotcha, i just dont have enough space for the new code
    – Umbus
    Nov 25, 2015 at 22:04
  • also what did you mean by edit into Q?
    – Umbus
    Nov 25, 2015 at 23:02

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.