Infrared laser distance sensor (50m/80m)

I bought a INFRARED LASER DISTANCE SENSOR (50M/80M) last week. I connected it to an Arduino Uno as shown in the wiring diagram in the doco. All that happens is a red laser points out the front. Nothing is returned to the Arduino. What’s the red laser for? - shouldn’t it be infra-red?

1 Like

Hey Jim,

Do you have a link to the one you bought? A lot of distance meter tools will have a red laser for aiming and an infrared for distance.

Got some photos/video of how it’s wired up and the code you’re using?

1 Like

https://www.dfrobot.com/product-2108.html
https://image.dfrobot.com/image/data/
https://wiki.dfrobot.com/Infrared_Laser_Distance_Sensor_50m_80m_SKU_SEN0366
also see https://dfimg.dfrobot.com/nobody/wiki/068db268ba37a41067c1b17607932139.pdf

… supplied by Core last week.

1 Like

Hi Jim
I know it may sound silly but you have called up the Serial Monitor in Arduino tools menu to display results on screen haven’t you ??
Cheers Bob

2 Likes

I have a Perl script listening to /dev/ttyACM0
I tested it by modding the .ino to Serial.println("hello") which the Perl caught and put on the screen.

2 Likes

Hi Jim.
Well that bit obviously works. Was just a thought.
Cheers Bob

2 Likes

Hi Jim,

Sure sounds like you’re almost there, any chance you feel like posting the code you’re running? Hopefully we can get to the bottom of this.

-James

1 Like

James,
Yes - see my reply dated 30 Aug. The code I use came from the wiki; it begins by sending 80 06 03 77 which seems sensible and should start continuous measurement but nothing happens when I run it. One plausible explanation is that my device isn’t set to address 80, perhaps because it’s a different item. Or it’s faulty.

3 Likes

Hey Jim,

No worries, so that’d be this one?:

/*!
 * @File  DFRobot_Iraser_Sensor.ino
 * @brief  In this example, the infrared laser ranging sensor is used to measure the distance, and the sensor data is processed to obtain the measured distance
 * @copyright  Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
 * @licence  The MIT License (MIT)
 * @author  [liunian](nian.liu@dfrobot.com)
 * @version  V1.0
 * @date  2020-08-13
 */
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2,3);//Define software serial, 3 is TX, 2 is RX
char buff[4]={0x80,0x06,0x03,0x77};
unsigned char data[11]={0};
void setup()
{
 Serial.begin(115200);
 mySerial.begin(9600);
}

void loop()
{
  mySerial.print(buff);
  while(1)
  {
    if(mySerial.available()>0)//Determine whether there is data to read on the serial 
    {
      delay(50);
      for(int i=0;i<11;i++)
      {
        data[i]=mySerial.read();
      }
      unsigned char Check=0;
      for(int i=0;i<10;i++)
      {
        Check=Check+data[i];
      }
      Check=~Check+1;
      if(data[10]==Check)
      {
        if(data[3]=='E'&&data[4]=='R'&&data[5]=='R')
        {
          Serial.println("Out of range");
        }
        else
        {
          float distance=0;
          distance=(data[3]-0x30)*100+(data[4]-0x30)*10+(data[5]-0x30)*1+(data[7]-0x30)*0.1+(data[8]-0x30)*0.01+(data[9]-0x30)*0.001;
          Serial.print("Distance = ");
          Serial.print(distance,3);
          Serial.println(" M");
        }
      }
      else
      {
        Serial.println("Invalid Data!");
      }
    }
    delay(20);
  }
}

When you say

Is it printing Distance = 80 M? Or just the number 80? Just going to run through the code compared against the output in order to determine what’s causing your error and if it is the hardware of your sensor.

Can you please send us a screenshot of the output that you’re getting from the sensor, as well as of the way in which the sensor is connected to your board? First thing that comes to mind is that this could be a continuity error, although that seems unlikely if we’re getting consistent outcomes for how long the sensor runs before it freezes.

1 Like

Hey Bryce,

I think Jim is referring to the following lines:

Seems this sensor requires initialisation (according to the wiki page). We don’t have any on the shelf to test, but I’ll look into this further.

If we work out you’ve got a bad unit, we’ll continue with an RMA

Keen to get you back on track!
-James

2 Likes

Hi Jim,

We’ve been hard at work testing some units from stock here in support, and have run into similar issues to you. We’ve found the devices generally unresponsive with example or custom code, so we’ve reached out to our supplier to work out whether there’s anything you or we have missed.

We’ll let you know as soon as we get more info!
-James

3 Likes

Hey all,

I read through the datasheet that DFRobot supplied on their wiki and commented out the example code so it’s human readable:

/*!
 * @File  DFRobot_Iraser_Sensor.ino
 * @brief  In this example, the infrared laser ranging sensor is used to measure the distance, and the sensor data is processed to obtain the measured distance
 * @copyright  Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
 * @licence  The MIT License (MIT)
 * @author  [liunian](nian.liu@dfrobot.com)
 * @version  V1.0
 * @date  2020-08-13
 */
#define ADDR 0x80
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2,3);//Define software serial, 3 is TX, 2 is RX
char buff[4]={ADDR,0x06,0x03,0x77}; //continuous measurement Request
// Continuous measurement returns 11 Bytes. On success:
// ADDR 0x06 0x83 0x3X 0x3X 0x3X 0x2E 0x3X 0x3X 0x3X CHECK_BYTE (where 0x3X are Ascii digits, 0x2E is Ascii '.')
// On Fail:
// ADDR 0x06 0x83 'E' 'R' 'R' '-' '-' '-' 0x3X CHECK_BYTE (where 3X are Ascii digits, 0x2E is Ascii '.')
unsigned char data[11]={0}; //prepate an array to receive data
void setup()
{
 Serial.begin(115200); //Hardware serial, for use with serial monitor
 mySerial.begin(9600); //Software serial, for use with Laser
}

void loop()
{
  mySerial.print(buff); // Request continous measurement mode
  while(1)
  {
    if(mySerial.available()>0) //Determine whether there is data to read from the Laser
    {
      delay(50);
      //read received data
      for(int i=0;i<11;i++)
      {
        data[i]=mySerial.read();
      }
      //calculate the CHECK_BYTE for received data
      unsigned char Check=0;
      for(int i=0;i<10;i++)
      {
        Check=Check+data[i];
      }
      Check=~Check+1;
      if(data[10]==Check) //Compare received CHECK_BYTE to calculated CHECK_BYTE
      { //If the check_bytes match, data is ok
        if(data[3]=='E'&&data[4]=='R'&&data[5]=='R')
        {
          Serial.println("Out of range");
        }
        else
        {
          float distance=0;
          distance=(data[3]-0x30)*100+(data[4]-0x30)*10+(data[5]-0x30)*1+(data[7]-0x30)*0.1+(data[8]-0x30)*0.01+(data[9]-0x30)*0.001; //Convert the distance from a string of chars to a float.
          Serial.print("Distance = ");
          Serial.print(distance,3); //Print the value to Hardware Serial
          Serial.println(" M");
        }
      }
      else //The CHECK_BYTEs don't match. Something's wrong!
      {
        Serial.println("Invalid Data!");
      }
    }
    delay(20);
  }
}

It’s probably worth modifying the sketch to see if first turning the laser on by sending:
0x80 0x06 0x05 0x01 0x74 or off with 0x80 0x06 0x05 0x00 0x75 helps at all.

Also, it’s worth noting that it actually returns ascii digits, so you should actually be able to strip it right back and pass the raw data straight to the serial monitor via the Hardware serial.

Here’s a hardware <-> software serial passthrough sketch I did up a while back that might come in handy here:

Oh, I also double checked, and the UART protocol the datasheet requires is the default for software serial and Hardware serial: 8 data bits, no parity bit, and 1 stop bit, so shouldn’t be any issues there.

Maybe someone who’s actually got one of these modules can get some part numbers off the ICs, and see if we can’t find a proper datasheet?

Another thought, it might be worth writing a simple script that runs through all possible addresses and checks for a valid response.

4 Likes

Actually, it seems that any messages starting with 0xFA should be received by the device irrespective of its address.

I’ve just modified the DFRobot code to first set the address, before going to continuous measurement mode.

And then I realised something… the DFRobot is using serial.print() instead of serial.write() !!!

Print() converts binary numbers to a human readable ASCII decimal! We need to use Write() to send raw data. Fingers crossed, the below code should just work now!

/*!
 * @File  DFRobot_Iraser_Sensor.ino
 * @brief  In this example, the infrared laser ranging sensor is used to measure the distance, and the sensor data is processed to obtain the measured distance
 * @copyright  Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com)
 * @licence  The MIT License (MIT)
 * @author  [liunian](nian.liu@dfrobot.com)
 * @version  V1.0
 * @date  2020-08-13
 */
#define ADDR 0x80
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2,3);//Define software serial, 3 is TX, 2 is RX
char buff[4]={ADDR,0x06,0x03,0x77}; //continuous measurement Request
// Continuous measurement returns 11 Bytes. On success:
// ADDR 0x06 0x83 0x3X 0x3X 0x3X 0x2E 0x3X 0x3X 0x3X CHECK_BYTE (where 0x3X are Ascii digits, 0x2E is Ascii '.')
// On Fail:
// ADDR 0x06 0x83 'E' 'R' 'R' '-' '-' '-' 0x3X CHECK_BYTE (where 3X are Ascii digits, 0x2E is Ascii '.')
unsigned char data[11]={0}; //prepate an array to receive data
void setup()
{
 Serial.begin(115200); //Hardware serial, for use with serial monitor
 mySerial.begin(9600); //Software serial, for use with Laser
 
 delay(50); //delays just because DFRobot did, to give the laser sometime to respond
 
 const unsigned char SetAddr[5] = {0xFA, 0x04, 0x01, ADDR, 0x81}; //set the address to 0x80, just in case
 mySerial.write(SetAddr, 5);
 delay(50);
 while(mySerial.available()){
   Serial.write(mySerial.read()); //pass any returned data to the serial monitor (success = FA 04 81 81, fail = FA 84 81 02 FF)
 }
 delay(50);
}

void loop()
{
  mySerial.write(buff, 4); // Request continous measurement mode
  while(1)
  {
    if(mySerial.available()>0) //Determine whether there is data to read from the Laser
    {
      delay(50);
      //read received data
      for(int i=0;i<11;i++)
      {
        data[i]=mySerial.read();
      }
      //calculate the CHECK_BYTE for received data
      unsigned char Check=0;
      for(int i=0;i<10;i++)
      {
        Check=Check+data[i];
      }
      Check=~Check+1;
      if(data[10]==Check) //Compare received CHECK_BYTE to calculated CHECK_BYTE
      { //If the check_bytes match, data is ok
        if(data[3]=='E'&&data[4]=='R'&&data[5]=='R')
        {
          Serial.println("Out of range");
        }
        else
        {
          float distance=0;
          distance=(data[3]-0x30)*100+(data[4]-0x30)*10+(data[5]-0x30)*1+(data[7]-0x30)*0.1+(data[8]-0x30)*0.01+(data[9]-0x30)*0.001; //Convert the distance from a string of chars to a float.
          Serial.print("Distance = ");
          Serial.print(distance,3); //Print the value to Hardware Serial
          Serial.println(" M");
        }
      }
      else //The CHECK_BYTEs don't match. Something's wrong!
      {
        Serial.println("Invalid Data!");
      }
    }
    delay(20);
  }
}
4 Likes

It’s a bit difficult getting type numbers off the chips as they’re all inside tin shields. You might end up bricking the device.

2 Likes

Hi Oliver,

Great code! We’ve tested this on an Arduino Mega, and it worked beautifully after changing the software RX and TX pins to 10 and 11 respectively:
image

Everyone else should also keep in mind that software serial only works on certain pins depending on your board.

If your board has hardware serial, this sketch should work as well:

char setAddress[5] = {0xFA,0x04,0x01,0x80,0x81};
char measureCont[5] = {0x80,0x06,0x03,0x77};
char bin[4] = {};

void setup(){
  Serial.begin(115200); //Open hardware serial connected via USB
  while(!Serial){
    delay(50);
  }
  Serial.println("USB Serial opened"); //Announce yourself to PC
  Serial1.begin(9600);
  Serial1.write(setAddress);
  while(Serial1.available()<4){
    delay(50);
  }
  Serial1.readBytes(bin, 4)
  Serial1.write(measureCont);
}

void loop(){
  if (Serial1.available()>=11){
    char response[11] = {};
    Serial1.readBytes(response, 11);
    for(int i = 3; i <= 9; i++){
      Serial.print(response[i]);
    }
    Serial.println(" Metres");
  }
}

Please note that The RX pin of your microcontroller should be plugged into the yellow line of the sensor, and TX to white. We’ll update the product page for this as soon as we can, as the documented opposite wiring will leave you very frustrated!

If you need help deciphering the serial message reference, let us know, as we had to work with it a lot during testing.

Keen to see what you make with this once you’ve got it going!
James

4 Likes

Glad to hear it works!