Go Down

Topic: Reading serial data from maxSonar ultrasonic rangefinder (Read 9146 times) previous topic - next topic

Goldthing

Hi all, just started with arduino and thought I would share this. There seems to be plenty on using the analog or pulse width outputs from the MaxSonar products but nothing about their serial use. This simple function reads the incoming serial data, converts it to an integer and returns the result.

A few things to note first.

     - The serial output on the MAxSonar is always enabled unless told otherwise. Attempting to hook it up directly to the serial port will cause communication problems between arduino and computer.

     - Serial data is inverted from the MaxSonar, to remove the need for extra circuitry I have used the very handy function in SoftwareSerial to flip the signal

     - This should work for all LV-EZ* and XL* modules, however the range returned will either be inches or centimeters depending on the type.

Code: [Select]

/* test function to Parse data from MaxSonar serial data
and return integer */

#include <SoftwareSerial.h>

#define txPin 3                                            //define pins used for software serial for sonar
#define rxPin 2

SoftwareSerial sonarSerial(rxPin, txPin, true);            //define serial port for recieving data, output from maxSonar is inverted requiring true to be set.



boolean stringComplete = false;

void setup()
{
  Serial.begin(9600);                                      //start serial port for display
  sonarSerial.begin(9600);                                 //start serial port for maxSonar
  delay(500);                                              //wait for everything to initialize

}

void loop()
{
  int range = EZread();
  if(stringComplete)
  {
    stringComplete = false;                                //reset sringComplete ready for next reading

    Serial.print("Range ");
    Serial.println(range);
    //delay(500);                                          //delay for debugging
  }
}


int EZread()
{
  int result;
  char inData[4];                                          //char array to read data into
  int index = 0;


  sonarSerial.flush();                                     // Clear cache ready for next reading

  while (stringComplete == false) {
    //Serial.print("reading ");    //debug line

      if (sonarSerial.available())
    {
      char rByte = sonarSerial.read();                     //read serial input for "R" to mark start of data
      if(rByte == 'R')
      {
        //Serial.println("rByte set");
        while (index < 3)                                  //read next three character for range from sensor
        {
          if (sonarSerial.available())
          {
            inData[index] = sonarSerial.read();
            //Serial.println(inData[index]);               //Debug line

            index++;                                       // Increment where to write next
          } 
        }
        inData[index] = 0x00;                              //add a padding byte at end for atoi() function
      }

      rByte = 0;                                           //reset the rByte ready for next reading

      index = 0;                                           // Reset index ready for next reading
      stringComplete = true;                               // Set completion of read to true
      result = atoi(inData);                               // Changes string data into an integer for use
    }
  }

  return result;
}



Hope this helps someone out there. Thanks to everyone who posts their code, I would never have got anywhere without you.

AWOL

I don't understand the presence of the flag "stringComplete".
If I'm reading that correctly, "EZreadead" doesn't return (blocks) unless it has a complete reading, so the flag is redundant.

rkguy

AWOL: I am looking to get the same information using TTL. Should I use a different approach than softwareserial?
I specifically ordered a maxbotix rangefinder that uses TTL logic, thinking that it would be easier to interface with the arduino UNO than RS-232 but I see no examples on how to communicate with it using TTL.
Should I post this as a new topic? My apololgies for digging up an old one.

AWOL

It should be just as easy using TTL, just keep in mind that unlike RS232, TTL is not normally inverted.

rjdelbulk

Thanks for this Goldthing.
Does anyone out there know how to get a serial (apparently the most accurate) mm resolution reading from a HRLV unit ?

Piano_Man

A couple of days ago, I was helping a user with support for this topic (remember I work for MaxBotix), and I noticed that by default when reading the 1mm resolution from the MB1013 if the target was under 1 meter in distance, the Arduino would only read 3 numbers.  As soon as the target was further than 1 meter, the Arduino would output all 4 numbers.

Attached is the code that I gave this end user for support with this topic.

The information given, is from my personal experience and does not represent MaxBotix Inc. in any way.

rjdelbulk

Hi all,
In order to get the above serial code to resolve 1mm resolution the array has to be changed to 5 characters (from four), otherwise the last digit is not stored (giving you unrounded cm results as opposed to mm results).

Change from:
char inData[4];                                          //char array to read data into
to:
char inData[5];                                          //char array to read data into

AND...
Change from:
while (index < 3)
to:
while (index < 4)

Piano_Man

Thank you for the correction.  I will make that change in my code, I appreciate this.

rjdelbulk

What is the purpose of the line:

#define txPin 3   

(And isn't the specific usage of #define outdated?)
I do not current have anything connected to Pin 3 and the code seems to work fine.

Piano_Man

It tells the Arduino that this pin may not be used.

I tried removing this part of the code, and I kept getting errors because it wasn't defined.   So to keep from having a headache, I just removed it.

if anyone has a better way to using the serial data connection, please let me know.

NeilClark

I have a HRXL-MaxSonar MN 7369 and I'm having a hard time to use its Pin 5 (Serial Output) to communicate with Arduino. I used a RS232 to TTL converter. When I used the code in the comment (File Name: http://forum.arduino.cc/index.php?topic=114808.0) the Sensor seems to override the commands in the code and immediately prints out the distance value without printing the other texts. It is also weird because sometimes it prints out the serial value : http://imgur.com/bUJGMee and sometimes it does not: http://imgur.com/EH743kB. (That is the output given by the code) And when i upload a blank code, it gives a continuous serial output data: http://i.imgur.com/p3HhP7D.png Can anyonr enlighten me with this?

Just new in Arduino and I would really appreciate all the help! Thanks in advance!

digitalaudiotape

Thanks so much to Goldthing for posting a solution to reading serial output from Maxbotix MaxSonar ultrasonic rangefinder/proximity sensors on Arduino boards. I am doing a project with the MB1200 XL-MaxSonar-EZ0, pairing it with a proprietary LED panel with a built in ESP8266 limited to only 2 digital input pins. It was godsend to find out it's possible to flip the signal with SoftwareSerial (as well as see the integer parsing code). Flipping the signal in software is soooo simple and so much better than buying a hardware signal inverter. It took an extended Google dive to find this post but I'm glad I did. I came across a handful of other threads on this topic that died before the problem was resolved.

To add to the discussion, I ran into some LED frame rate issues with the "sonarSerial.available()" calls stalling the code down to 1-2 Hz. I was able to get my frame rate back up by removing "sonarSerial.available()" completely as well as removing "sonarSerial.flush()". This makes for a lot of garbage data, but that's easy enough to filter out with a simple if statement ignoring any readings below 20 centimeters or above 1000 centimeters. These changes also make the range readings stutter a bit, but the irregular updates are still faster than the 1 reading per second I need anyway. Not the greatest software engineering, but this is just for an art project anyway ;).

melsjam

Hi, this is great info!

Would someone happen to share their wiring for the XL, for this code? I am more used to non-serial setups, and have had issues getting a signal back at all ... thanks!

J

Hi all, just started with arduino and thought I would share this. There seems to be plenty on using the analog or pulse width outputs from the MaxSonar products but nothing about their serial use. This simple function reads the incoming serial data, converts it to an integer and returns the result.

A few things to note first.

     - The serial output on the MAxSonar is always enabled unless told otherwise. Attempting to hook it up directly to the serial port will cause communication problems between arduino and computer.

     - Serial data is inverted from the MaxSonar, to remove the need for extra circuitry I have used the very handy function in SoftwareSerial to flip the signal

     - This should work for all LV-EZ* and XL* modules, however the range returned will either be inches or centimeters depending on the type.

Code: [Select]

/* test function to Parse data from MaxSonar serial data
 and return integer */

#include <SoftwareSerial.h>

#define txPin 3                                            //define pins used for software serial for sonar
#define rxPin 2

SoftwareSerial sonarSerial(rxPin, txPin, true);            //define serial port for recieving data, output from maxSonar is inverted requiring true to be set.



boolean stringComplete = false;

void setup()
{
  Serial.begin(9600);                                      //start serial port for display
  sonarSerial.begin(9600);                                 //start serial port for maxSonar
  delay(500);                                              //wait for everything to initialize

}

void loop()
{
  int range = EZread();
  if(stringComplete)
  {
    stringComplete = false;                                //reset sringComplete ready for next reading

    Serial.print("Range ");
    Serial.println(range);
    //delay(500);                                          //delay for debugging
  }
}


int EZread()
{
  int result;
  char inData[4];                                          //char array to read data into
  int index = 0;


  sonarSerial.flush();                                     // Clear cache ready for next reading

  while (stringComplete == false) {
    //Serial.print("reading ");    //debug line

      if (sonarSerial.available())
    {
      char rByte = sonarSerial.read();                     //read serial input for "R" to mark start of data
      if(rByte == 'R')
      {
        //Serial.println("rByte set");
        while (index < 3)                                  //read next three character for range from sensor
        {
          if (sonarSerial.available())
          {
            inData[index] = sonarSerial.read();
            //Serial.println(inData[index]);               //Debug line

            index++;                                       // Increment where to write next
          } 
        }
        inData[index] = 0x00;                              //add a padding byte at end for atoi() function
      }

      rByte = 0;                                           //reset the rByte ready for next reading

      index = 0;                                           // Reset index ready for next reading
      stringComplete = true;                               // Set completion of read to true
      result = atoi(inData);                               // Changes string data into an integer for use
    }
  }

  return result;
}



Hope this helps someone out there. Thanks to everyone who posts their code, I would never have got anywhere without you.

47francois

Hi there.

I am using MB7092 XL-MaxSonar. it works only with rs232. Provides also analog but the precision with arduino would be very bad.

I was surprised nobody appear to have been able to use this sensor with rs232, I mean to get the usable integer out of it !

The code given by Piano_man didn't work for me. Or any other code, excepted the code for wiewing only on computer IDE screen serial that works, but as soon as I try to modify it to get something out of it, I am jammed with RRRR and other bad stuff.

I contacted MaxSonar customer aftersales, they gave me the link to this post.

After days of fighting hard...

I found the way to do it and code that really works !!!  yeah !!! (above)

Things to know :

1/ sofwareserial is not a real serial, it's a virtual serial. And it doesn't obey well or at all normally (as hardware serial).

Something like
if (sonarSerial.available()

doesn't work, or not properly. and it doesn't behave like the hardware serial too.

so forget all these !

source :
http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.LibrairieSerialSoftware



2/ arduino nano I was working on has only 1 serial hardware . So I started on arduino mega 2560.

3/ rs232 from sensor have inverted logic, and no way to invert mega's serial logic. Then I purchased a IC  : 74HC14  it contains 6 inverting with Schmitt function (Schmitt probably not necessary, but I found only this in the neighboorhood) it works perfectly. + on arduino's 5V and - to the ground. pin 5 from sensor to an input, and related output to pin 17, that is the hardware dedicated RX2 on this mega.


Reasult :

finally it works perfectly, you even don't need to convert into an int, because you get it already as an int !!!


So you need :

 -one arduino that have several hardware serial ports
 -signal inverting device (IC)
 -my code ;))


even don't need a library...
Have fun !



Code: [Select]

// Copyright (C) 2019 by Francois Regnault and licensed under
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
//READ MaxSonar 7092 sensor on rs232, arduino mega 2560
// readings from MaxSonar 7092 are first inverted using an IC 74HC14 (inverted logic from rs232 MaxSonar)
// Mega have several hardware pins . here, use of RX2 : input pin 17


int g;



void setup() {
 // initialize serial:
 Serial2.begin(9600);
 Serial.begin(9600);
 

}

void loop() {

     Serial.println("loop");




if (Serial2.available() > 0) {
g=Serial2.parseInt();
Serial.print(" mesure= "); Serial.println(g);



}


}


Go Up