Class to control the URM37 via serial

I recently got a DFRobot URM37 sensor and created a class to use it (going in library once solid). Your feedback is greatly appreciated.

Link to sensor:
http://www.dfrobot.com/index.php?route=product/search&filter_name=urm37

Notes about class / library...
This is BETA 1 of the class/library but tested on 328 and mega board. There is duplicate code in there to handle mega .. but if your board is not a mega .. it won't even compile in so it won't use any extra footprint.

In the process up updating code from www.yerobot.com, I removed the usage of extra pins outside the serial pins and made it work with Serial1/2/3 in the mega boards too (nice because you can upload without disconnecting the sensor from tx/rx).

In it's simplest form .. the usage is 123.

  1. Define a URM37Simple instance (i.e. URM37Simple sensor1);
  2. in setup() - call:
    sensor1.initSetup();
  3. in the loop, get the distance using:
    sensor1.getDistance()
/* Ultrasound Sensor Class
 *- Based on code from www.yerobot.com 
 * - edits include removing the power and enable from pons - directly to VCC grid
 * - Removed some of the variables to save memory, including hard coding the commands to send
 * - Be sure to change the jumper on the URM37 to TTL ***
 *------------------
  To Use:
  Create an instance of the URM37Simple class
  In setup - call <YOURNAME>.initSetup()
  In loop - call <YOURNAME>.getDistance() to force a reading on distance - return value is distance in cm
 *------------------
 * URM V3.2 ultrasonic sensor TTL connection with Arduino
 * Reads values (0-300) from an ultrasound sensor (3m sensor)
 * VCC 5v -> Pin 1 VCC (URM V3.2)
 * GND (Arduino) -> Pin 2 GND (URM V3.2)
 * VCC 5v -> Pin 7 (URM V3.2)
 * Pin 0 (Arduino) -> Pin 9 (URM V3.2)
 * Pin 1 (Arduino) -> Pin 8 (URM V3.2)
 */
#define SERIAL_MODE_DEFAULT 0
#define SERIAL_MODE_MEGA_1 1
#define SERIAL_MODE_MEGA_2 2
#define SERIAL_MODE_MEGA_3 3

class URM37Simple {

public:
  byte serialMode;
  int distance;

  URM37Simple(byte theSerialMode) {
    serialMode = theSerialMode;
  };

  URM37Simple() {
    serialMode = SERIAL_MODE_DEFAULT;
  };
  ~URM37Simple() {
  };

  int getDistance(){
    //-- if a mega - then chose the serial port in use    
    #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560) 

      switch (serialMode){
          case SERIAL_MODE_DEFAULT : return getDistanceFromDefault();
          case SERIAL_MODE_MEGA_1 : return getDistanceFrom1();
          case SERIAL_MODE_MEGA_2 : return getDistanceFrom2();
          case SERIAL_MODE_MEGA_3 : return getDistanceFrom3();
      }
      //-- should never happen - but just in case return default;
      return getDistanceFromDefault();
    #else
      //-- Not a mega so no computation required in this compile
      return getDistanceFromDefault();
    #endif      
  }

  int getDistanceFromDefault(){
    Serial.print(0x22,BYTE);
    Serial.print(0x0,BYTE);
    Serial.print(0x0,BYTE);
    Serial.print(0x22,BYTE);

    while(true)
    {
      if(Serial.available()>3)
      {
        int header=Serial.read(); //0x22
        int highbyte=Serial.read();
        int lowbyte=Serial.read();
        int sum=Serial.read();//sum

        if(highbyte==255)
        {
          distance=0;  //if highbyte =255 , the reading is invalid.
        }
        else
        {
          distance = highbyte*255+lowbyte;
        }
        return distance;
      }
      delayMicroseconds(10);
    }
  }

//--- only if this is a mega do we need these functions 
    #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560) 
   

  int getDistanceFrom1(){
    Serial1.print(0x22,BYTE);
    Serial1.print(0x0,BYTE);
    Serial1.print(0x0,BYTE);
    Serial1.print(0x22,BYTE);

    while(true)
    {
      if(Serial1.available()>3)
      {
        int header=Serial1.read(); //0x22
        int highbyte=Serial1.read();
        int lowbyte=Serial1.read();
        int sum=Serial1.read();//sum

        if(highbyte==255)
        {
          distance=0;  //if highbyte =255 , the reading is invalid.
        }
        else
        {
          distance = highbyte*255+lowbyte;
        }
        return distance;
      }
      delayMicroseconds(10);
    }
  }

  int getDistanceFrom2(){
    Serial2.print(0x22,BYTE);
    Serial2.print(0x0,BYTE);
    Serial2.print(0x0,BYTE);
    Serial2.print(0x22,BYTE);

    while(true)
    {
      if(Serial2.available()>3)
      {
        int header=Serial2.read(); //0x22
        int highbyte=Serial2.read();
        int lowbyte=Serial2.read();
        int sum=Serial2.read();//sum

        if(highbyte==255)
        {
          distance=0;  //if highbyte =255 , the reading is invalid.
        }
        else
        {
          distance = highbyte*255+lowbyte;
        }
        return distance;
      }
      delayMicroseconds(10);
    }
  }

  int getDistanceFrom3(){
    Serial3.print(0x22,BYTE);
    Serial3.print(0x0,BYTE);
    Serial3.print(0x0,BYTE);
    Serial3.print(0x22,BYTE);

    while(true)
    {
      if(Serial3.available()>3)
      {
        int header=Serial3.read(); //0x22
        int highbyte=Serial3.read();
        int lowbyte=Serial3.read();
        int sum=Serial3.read();//sum

        if(highbyte==255)
        {
          distance=0;  //if highbyte =255 , the reading is invalid.
        }
        else
        {
          distance = highbyte*255+lowbyte;
        }
        return distance;
      }
      delayMicroseconds(10);
    }
  }

   
   #endif      

  void initSetup(){
    distance = 0;

    switch (serialMode){
    case 0 : 
      Serial.begin(9600); 
      break;
 #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560) 
      // serial ports with with Arduino Mega only
    case 1 : 
      Serial1.begin(9600); 
      break;
    case 2 : 
      Serial2.begin(9600); 
      break;
    case 3 : 
      Serial3.begin(9600); 
      break;
#endif      
    }

    delay(200); //Give sensor some time to start up --Added By crystal  from Singapo, Thanks Crystal.
  }
};




#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560) 
  URM37Simple sensor1 = URM37Simple(1);
#else
  URM37Simple sensor1;
#endif      

void setup() {
  sensor1.initSetup();
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560) 
  if (sensor1.serialMode > 0 ){
    //-- if we are not using default serial - then init so we can talk via the monitor
    Serial.begin(9600);
  }
#endif      
}

void loop()
{
  Serial.println(sensor1.getDistance());
  delay(50);
}

The Arduino convention seems to be to call the initialization method ".begin()". You might want to use that instead of ".initSetup()".

Thanks for the tip, I'll update that if/when moved to library form.

I created a simple library but feel I should use it some before posting.

I really do not like the duplicate functions. I created this in a couple hours to create an interactive light bar. I'll work out how to reference a pointer to the correct serial instance or at least break out duplicate function into a single routine before posting as a library.

Other feedback welcome.

Hi marklar,

I am newbie in programming the Arduino. My knowledge about electronics is quite good but it is a long time ago when I do the last things in this field. So I have to learn some things new. Please excuse for my newbie questions.

I have an Arduion MEGA 2560 an the UMR37 V3.2 and I want to read the distance permanently. I am a little bit confused about the switch between TTL and serial. I thought that for using the MEGA I could switch the URM37 to serial an connect direct with the serial-TX/RX from the MEGA. But in the code is a note:

"* - Be sure to change the jumper on the URM37 to TTL ***"

Is this wright?

Thank you
Regards,
Gerd

Can you post a usage example?

Hello,
I am new on this forum and don' t have an idea how to post my qestion, so
I will do it this way,
I have a sketh downloaded from www.jo3ri.be. its a tank level measurement.
The program works fine with a urm37 connected. My problem is that i want to use
the urm37 as a sensor with cable, appox 7m long. This gives probles to the program.
Is there a way to use a cable with a lenght of 7 m connected to an arduino
The cable i use 4x0,75 mm shielded.

Thanx peter