Single Wire Hardware Serial

This is a continuation of my thread from here:

I tried connecting with the circuit in that thread, 220ohm resistors in the TX and RX lines before connecting together. I could not communicate at all with the ultrasonic sensor. (Deleted the code inadvertently so I can't post it). I also tried using NewSoftSerial. While the sensor indicated communication, the data I got back was bogus.

Here is the code I used using SoftwareSerial, which works fine (modified from an example program provided with sensor). It gets the software version from the sensor in the setup, then loops over and over, doing 100 ranges and averaging them. If the distance is less than 10, onboard LED is illuminated.

#include <SoftwareSerial.h>


#define txrxPin 10                                          // Defines a pin to be used as both rx and tx for the SRF01
#define srfAddress 0x01                                    // Address of the SFR01
#define getSoft 0x5D                                       // Byte to tell SRF01 we wish to read software version
#define getRange 0x53                                      // Byte used to get range from SRF01 in inches
#define getStatus 0x5F                                     // Byte used to get the status of the transducer


SoftwareSerial UltrasonicBus(txrxPin, txrxPin);

void setup(){
  pinMode(13,OUTPUT);
  Serial.begin(19200);
  
  UltrasonicBus.begin(9700);                                      
  delay(200);                                              // Waits some time to make sure that SRF01 is powered up
  Serial.println("SRF01 Test");                           
  SRF01_Cmd(srfAddress, getSoft);                          // Calls a function to get the SRF01 software version
  int softVer = UltrasonicBus.read();                             // Read software version from SRF01
  Serial.print("V:");                                      
  Serial.println(softVer);                                   // Prints the software version to LCD03
  delay(200);
  
  Serial.println("Initialization Complete");
}


void loop(){
 
  int max = 10;
  int sum = 0;
  for (int count = 0; count < max; count++) {
    sum = sum + doRange();
  }
  
  int range = sum / max;
 
  Serial.print("Range 100avg = ");                                
  Serial.print(range);                                     // Print range result to the screen
  Serial.println("  ");                                      // Print some spaces to the screen to make sure space direcly after the result is clear
  if(range<10){
    digitalWrite(13, HIGH);
  } else {
    digitalWrite(13, LOW);
  }
  checkLock();
  delay(100);
}


void SRF01_Cmd(byte Address, byte cmd){                     // Function to send commands to the SRF01
  pinMode(txrxPin, OUTPUT);                                 // Set pin to output and send break by sending pin low, waiting 2ms and sending it high again for 1ms
  digitalWrite(txrxPin, LOW);                              
  delay(2);                                               
  digitalWrite(txrxPin, HIGH);                            
  delay(1);                                                
  UltrasonicBus.print(Address, BYTE);                              // Send the address of the SRF01
  UltrasonicBus.print(cmd, BYTE);                                  // Send commnd byte to SRF01
  pinMode(txrxPin, INPUT);                                  // make input ready for Rx
}



void checkLock() {
  SRF01_Cmd(srfAddress, getStatus);                         // Call to a function that checks if the trancducer is locked or unlocked
  byte statusByte = UltrasonicBus.read();                          // Reads the SRF01 status, The least significant bit tells us if it is locked or unlocked
  int status = statusByte & 0x01;                           // Get status of lease significan bit
  if(status == 0){                                      
    
    Serial.println("Unlocked");                            // Prints the word unlocked followd by a couple of spaces to make sure space after has nothing in
  }
   else {                                      
    Serial.println("Locked   ");                              // Prints the word locked followd by a couple of spaces to make sure that the space after has nothing in
  }
}

int doRange() {
  SRF01_Cmd(srfAddress, getRange);                         // Calls a function to get range from SRF01
  byte highByte = UltrasonicBus.read();                           // Get high byte
  byte lowByte = UltrasonicBus.read();                            // Get low byte
  int dist = ((highByte<<8)+lowByte);                     // Put them together
  return dist;
}

I tried using NewSoftSerial with this same code, just changing the appropriate SoftwareSerial references to NewSoftSerial. The data light on the sensor flashed as normal to indicated communication, but the data I got back was bogus- the software version, which should return "1", returned "-1." The distance measurement numbers were all random. I was getting fluctuating numbers in the 500-700 range while I should have been getting steady numbers in the 5-10 range. I suspect they might have been even more all over the place but the averaging probably smoothed it.

I am suspecting it is a timing issue. My understanding is SoftwareSerial is polling based, which allows them to use delays as necessary in getting the attention of the transducer, but since NewSoftSerial and hardware serial are interrupt based, the delays do nothing..............?

Anyone have some suggestions to this? Code greatly appreciated if anyone can post some.

Thanks.

Hi,

I am facing the same problem. I followed the (Arduino Examples Ultrasonic Ranger) example, wich is very similar to brad81987´s code.
Any solution to this problem?

Best regards,

Hi again,

searching a bit more in the forum, I found that the SoftwareSerial baut rate may be set to 9750 (http://arduino.cc/forum/index.php/topic,48311.0.html).

It works pretty great now.

Hi, I'm using SRF01s on a robot and was having grief getting it to work using softwareserial without it breaking my timer based odometry code so I really wanted to get it working using hardware serial. Anyway I've managed to get it working and stuck it all into a class in case anyone else wants to do something similar in the future so that they don't have the same headaches

The rx and tx pins do still need to be tied together using 220 resistors as drone showed here http://arduino.cc/forum/index.php/topic,22664.msg171337.html#msg171337

#ifndef SONAR_H
#define SONAR_H

#ifndef NUMOFSONAR
    #define NUMOFSONAR 1
#endif

#ifndef SERIALTOUSE
    #define SERIALTOUSE Serial3
#endif

#ifndef SERIALWAIT 
    #define SERIALWAIT 100
#endif

#include "pins.h"
#define GETRANGE 0x54          // Byte used to get range from SRF01

class Sonar
{
  private :
    byte sonarsConnected[NUMOFSONAR]; 
    int sonarReadings[NUMOFSONAR];
    byte tx, rx;
       
  public :
    Sonar( uint8_t _tx=0, uint8_t _rx=0 );
    int getReading( int sonarNumber );
    void readAll();
    int readOne( int i );
    void setSonarAddr( int pos, uint8_t addr );
};

void Sonar::setSonarAddr( int pos, uint8_t addr )
{
    sonarsConnected[pos] = addr;
}

Sonar::Sonar( uint8_t _tx, uint8_t _rx)
{  
    if( _tx != 0 && _rx != 0 )
    {
        tx = _tx;
        rx = _rx;
    }
    else if( SERIALTOUSE == Serial ) 
    {
        tx = 1;
        rx = 0;
    }
    else if( SERIALTOUSE == Serial1 )
    {
        tx = 18;
        rx = 19;
    }
    else if( SERIALTOUSE == Serial2 )
    {
        tx = 16;
        rx = 17;
    }
    if( SERIALTOUSE == Serial3 )
    {
        tx = 14;
        rx = 15;
    }
}

int Sonar::readOne( int i )
{  
    SERIALTOUSE.end();
    pinMode( tx, OUTPUT );
    
    digitalWrite( tx, LOW );
    delay(2);
    
    digitalWrite( tx, HIGH );
    delay(1);
    
    SERIALTOUSE.begin(9600);
    SERIALTOUSE.flush();
    SERIALTOUSE.write(sonarsConnected[i]);
    SERIALTOUSE.write(GETRANGE);
    
    unsigned long start = millis();
    while( millis() -start <= SERIALWAIT && SERIALTOUSE.available() < 4 ) delay(1);

    if( SERIALTOUSE.available() >= 4 )
    {   
        // the bytes sent out on the tx pin will also be returned on the rx pin, clear them out of the way
        SERIALTOUSE.read(); SERIALTOUSE.read(); 
        byte hByte = SERIALTOUSE.read();
        byte lByte = SERIALTOUSE.read();
    
        sonarReadings[i] = ((hByte<<8)+lByte); 
    }
    else
        sonarReadings[i] = -1;

    return sonarReadings[i];
}

void  Sonar::readAll()
{
    for( int i=0; i<NUMOFSONAR; i++ )
       readOne(i);
}

int Sonar::getReading(int sonarNumber)
{
  return sonarReadings[sonarNumber];
}


#endif SONAR_H

So if you want to use it it's just a case of changing SERIALTOUSE and NUMOFSONAR to the values you desire and calling the functions i.e.

#define SERIALTOUSE Serial3
#define NUMOFSONAR 2


Sonar s;

void setup()
{
    s.setSonarAddr( 0, 0x01 );
    s.setSonarAddr( 1, 0x03 );
}

void loop()
{
    s.readAll();

    for( int i=0; i<NUMOFSONARS; ++i )
        Serial.println( s.getReading(i) );
}

Guys,
Could anyone give me a simple code to run the SFR01?
I only need to read out the range in Serial.println() no LCD etc.
I already burned 3 SFR02 by removing the sensor head and the SFR01 is just the right fit.

I am not a SW programmer an forgot after engineering school the "classes" definitions, so have mercy on my SW skills....

Many thanks in advance
Y3G