How to use communication protocol of a sensor with arduino

Hello,

I habe bought a Infrared Laser Distance Sensor SEN0366 from DFrobot. It uses the UART communication protocol, so I use the RX and TX pin on my arduino UNO.
There is also a example sketch avaiable, how to measure distances. This works fine for me.

But there is also a communication protocol SEN0366 Communication Protocol.pdf avaiable, where I can change the setting of the SEN0366, like the frequency or the accuracy. But I don´t know how to put this into my code. Here is a snippet of this document:

Does anybody knows how to send the command Code to this Sensor. I have tried:

Serial1.println("FA 06 01 FF") ;

in my Code or I typed in this command into the console of the Arduino IDE, but nothing happens. I also don´t know how to recieve the return code.

best regards,
Hanz

Welcome to the forum

Using those pins is not generally a good idea because they are used by the hardware Serial interface to upload code and the Serial monitor

Serial1 does not use pins 0 and 1 so I don't understand this. Please post your full sketch, using code tags when you do

Hello,
thank you for your answer. You are right, I did not use the TX and RX Pin. I use the softwareSerial, like in the example Sketch of this sensor, which is:

/*!
 * @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);
mySerial.print(FA 06 01 FF); //send command to Sensor
}

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

So I have tried to send the command code with:

mySerial.print(FA 06 01 FF); in the void setup(). I don´t think, that this is correct? I also don´t know, how to recieve the Return Code like in the snippet of the Document I have posted

mySerial.print(FA 06 01 FF);

That won't work

Either send the sequence as a string or send it as a sequence of individual bytes (more likely) but I cannot be sure that either will work

I tried it to send the sequence as a string

mySerial.print("FA 06 01 FF"); 

But I don´t know if something happens. Is there a way to recieve the return code in the console?

if (Serial1.available())
{
  Serial.print(Serial1.read));
}

thanks for your answer. I tried it, but nothing is written in the console

void setup()
{
 Serial.begin(115200);
 mySerial.begin(9600);
 mySerial.print("FA 06 01 FF");  
    if (mySerial.available())
{
  Serial.print(mySerial.read());
}

}

How can I send the string

FA 06 01 FF

as individual bytes?

Simple but not elegant

Serial1.write(0xFA);
Serial1.write(0x05);
Serial1.write(0x01);
Serial1.write(0xFF);

More elegant

byte buffer[] = {0xFA, 0x06, 0x01, 0xFF);
Serial1.write((buffer, sizeof(buffer));

thank you for your answer. It seems to work in this way. For example: I set the maximum range to 5 m and the laser will only give me distances up to 5 metres.

But I cannot see the return codes in the console

if (mySerial.available()>0)
{
 
  Serial.print(mySerial.read());
}

There only a -1 is written and not the return code of the communication protocol of the sensor

a value of -1 from a read() means that there was no data available to read. This should be impossible if you first test to see whether anything is available before reading

Please post your full sketch that sends the commands and reads the reply, if any

Hello,
this is my sketch, it is like the example sketch, but with some additional lines:

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2,3);//Define software serial, 3 is TX, 2 is RX

char buff[4]={0x80,0x06,0x03,0x77}; //continues measuring
byte buffe[] = {0xFA, 0x04, 0x0C, 0x01, 0xF5};  //Set resolution 1mm
byte buffe2[] = {0xFA, 0x04, 0x0A, 0x0A, 0xEE}; //Set frequency: 
byte buffe3[] = {0xFA, 0x04, 0x09, 0x05, 0xF4}; //Set range to 5 metres
unsigned char data[11]={0};
void setup()
{
 Serial.begin(115200);
 mySerial.begin(9600);
 
mySerial.write(buffe, sizeof(buffe)); 
//mySerial.write(buffe2, sizeof(buffe2)); 
//mySerial.write(buffe3, sizeof(buffe3)); 
if (mySerial.available()>0)
{
  Serial.print(mySerial.read());
}

}

void loop()
{

    
  mySerial.print(buff);

  
  while(1)
  {
    if(mySerial.available()>0)//Determine whether there is data to read on the serial 
    {
      delay(20);
      for(int i=0;i<11;i++)
      {
        data[i]=mySerial.read();
       // Serial.print(data[i]);
      }
      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);
  }
}

For example, when I set resolution, then there should be a return code like in the third column of this snippet from the sensor communication protocol (FA 04 8C 76):

the console give me a "-1" for this code (line 17) in the setup()

if (mySerial.available()>0)
{
  Serial.print(mySerial.read());
}

Why is the buff array declared as char and not byte ?

What do you think

  mySerial.print(buff);

sends ?

For your initial tests I would keep things very simple. For instance

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //Define software serial, 3 is TX, 2 is RX

byte buff[] = {0x80, 0x06, 0x03, 0x77}; //byte sequence to test goes here

void setup()
{
  Serial.begin(115200);
  mySerial.begin(9600); //are you sure that the baud rate is correct ?
  mySerial.write(buff, sizeof(buff));
}

void loop()
{
  if (mySerial.available())
  {
    Serial.print(mySerial.read());
  }
}
1 Like

the buff array is declared as char in the example sketch from the sensor

mySerial.print(buff);

according to the communication protocol it sends the command for continues measuring

When I use your sketch, then I get the following numbers in the console:
"128 6 131 48 48 48 46 48 52 57 156"

If I change the buff to
byte buffe[] = {0xFA, 0x04, 0x0C, 0x01, 0xF5}; // set resolution

Then I get the following numbers in the console now:
"250 4 140 118" but it should be "FA 04 8c 76" -> the first one is decimal and the last one is the hex presentation :slight_smile: So it seems to work with your sketch :slight_smile:

In your sketch buff is declared as an array of 4 chars but when you print it the Arduino has no idea how many characters are in the array and it will keep sending characters until it comes across a zero which it will take as the string terminator

This is the reason why I suggested using write() as it sends the raw bytes, not a character representing the numbers, and you can use a second parameter to tell the sketch how many bytes to send

Have you posted the example sketch in this topic ? If so, then I missed it

in my third post, I posted the example sketch, except of this line in this sketch:

mySerial.print(FA 06 01 FF); //send command to Sensor

this line was my code

I don't trust that code, but what happens if you run it without your addition ?

If I use the example sketch without my modifications it works very good. The console is giving me the right distances.

Ok, so you have a working starting point

What happens if you change the contents of the buff array to send a different command ?

Hello,
it works now. When I change the buff to different commands, then it works, even with the correct return code. The return code is in decimal, so I have to convert it to hex.
The important thing was your Post #9 and #13. Thank you very much for your help :slight_smile:

I have a last question. I need to controll four of this Sensors parallel. This is not possible with the UNO, I think. So I have to go to the Mega, which has 4 hardware serial Ports, right?
Is there a problem to use all 4 Hardware Serial Ports?

In your first post you have written, that is not a good idea, to use the RX, TX Pin from the UNO. Is it the same with the Mega?

I am glad that you have got it working

When you print the returned data add the HEX format specifier and it will be printed in hex

Serial.print(dataByte, HEX);

If you want to do a comparison between the returned data and a hex value then there is no need to convert anything as hex is just a more human friendly way of presenting the data than 8 bits which is easy to misread

As to using the 4 UARTS of the Mega, the same problems will arise if you use Serial on pins 0 and 1. What you could do is to use the other 3 hardware Serial ports and a single instance of SoftwareSerial