Go Down

Topic: Class to control the URM37 via serial (Read 1 time) previous topic - next topic

marklar

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()

Code: [Select]

/* 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);
}




johnwasser

The Arduino convention seems to be to call the initialization method ".begin()".  You might want to use that instead of ".initSetup()".
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

marklar

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.



loby

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

MurtenSaerbi


smitex

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 

Go Up