How to Code TW10S UART Laser Module?

Hi,
I'm using a TW10S-UART sensor but i suppose it works the same.

I am using the SoftwareSerial Library in order to communicate with the sensor.

#include <SoftwareSerial.h>

#define TX_laser 4
#define RX_laser 5

SoftwareSerial Serial2(TX_laser, RX_laser);

To start measuring you need to send a request in the format that @ning_lily suggested:


uint8_t commandContinuous[8] = {0x01, 0x03, 0x00, 0x01, 0x00, 0x02, 0x95, 0xCB}; //the command for continuous reading
uint8_t commandUnique[8] = {0x01, 0x03, 0x00, 0x0F, 0x00, 0x02, 0xF4, 0x08}; //the command for one time reading
uint8_t onoff[11] = {0x01, 0x10, 0x00, 0x03, 0x00, 0x01, 0x02, 0x00, 0x01, 0x67, 0xA3}; //the command to turn it on or off
uint8_t data[9];

//*****************************************************************************

void setup() {
  // put your setup code here, to run once:
  Serial2.begin(9600); //start serial communication with the sensor
  delay(200);
  Serial2.write(onoff, 11); //turns the sensor on
}

//*****************************************************************************

void loop() {
  Serial2.write(commandUnique, 8); //ask for a one time measurement
  delay(200);
  if( Serial2.available() >0){
    Serial2.readBytes(data, 9); //reads the response and stores it as an array ( data )
    Serial2.overflow(); //clears serial2
  }

Once you have the response you can convert it to distance (in mm) using this:

uint8_t byte6_1, byte5_1, byte6_2, byte5_2, byte5_1_hex, byte5_2_hex, byte6_1_hex, byte6_2_hex;

uint8_t commandContinue[8] = {0x01, 0x03, 0x00, 0x01, 0x00, 0x02, 0x95, 0xCB};
uint8_t commandUnique[8] = {0x01, 0x03, 0x00, 0x0F, 0x00, 0x02, 0xF4, 0x08};
uint8_t marche[11] = {0x01, 0x10, 0x00, 0x03, 0x00, 0x01, 0x02, 0x00, 0x01, 0x67, 0xA3};
uint8_t data[9];
uint32_t distance;

//*****************************************************************************
uint32_t calcul_distance(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
  distance = (d * 1 + c * 16 + b * 16 * 16 + a * 16 * 16 * 16); //converts 4 hex digits into decimal
  return distance;
}

void loop() {
  Serial2.write(commandUnique, 8);
  delay(200);
  if( Serial2.available() >0){
    Serial2.readBytes(data, 9);
    Serial2.overflow();
  }

  delay(200);
  byte5_1 = data[5] / 16;
  byte5_2 = data[5] - byte5_1 * 16;
  byte6_1 = data[6] / 16;
  byte6_2 = data[6] - byte6_1 * 16;
  distance = calcul_distance(byte5_1, byte5_2, byte6_1, byte6_2);
  if (distance < 20000) {
    Serial.println(distance);
  }

}

Once you have the values you can use the CRC code to check the integrity of the values you received. to do that i am using the CRC library like so:

#include <CRC16.h>

CRC16 crc(CRC16_MODBUS_POLYNOME,
          CRC16_MODBUS_INITIAL,
          CRC16_MODBUS_XOR_OUT,
          CRC16_MODBUS_REV_IN,
          CRC16_MODBUS_REV_OUT);

/*...*/

void loop() {
  Serial2.write(commandUnique, 8);
  delay(200);
  if( Serial2.available() >0){
    Serial2.readBytes(data, 9);
    Serial2.overflow();
  }

  for(int i = 0; i < sizeof(data); i++)
  {
    crc.add(data[i]);
  }
  uint8_t CRC = crc.calc(); //calculates CRC check code

  if( CRC ==0 ) { //the data is valid only if CRC value is 0

    delay(200);
    byte5_1 = data[5] / 16;
    byte5_2 = data[5] - byte5_1 * 16;
    byte6_1 = data[6] / 16;
    byte6_2 = data[6] - byte6_1 * 16;
    distance = calcul_distance(byte5_1, byte5_2, byte6_1, byte6_2);

    if (distance < 20000) {
      Serial.println(distance);
    }
 }
  crc.restart(); //resets the library to be able to calculate another crc check code
}

That way you can decide to only calculate the distance if the data has been received correctly

Here is the whole code:


#include <CRC16.h>


//*****************************************************************************
#include <SoftwareSerial.h>

#define TX_laser 4
#define RX_laser 5

SoftwareSerial Serial2(TX_laser, RX_laser);

CRC16 crc(CRC16_MODBUS_POLYNOME,
          CRC16_MODBUS_INITIAL,
          CRC16_MODBUS_XOR_OUT,
          CRC16_MODBUS_REV_IN,
          CRC16_MODBUS_REV_OUT);



uint8_t byte6_1, byte5_1, byte6_2, byte5_2, byte5_1_hex, byte5_2_hex, byte6_1_hex, byte6_2_hex;

uint8_t commandContinue[8] = {0x01, 0x03, 0x00, 0x01, 0x00, 0x02, 0x95, 0xCB};
uint8_t commandUnique[8] = {0x01, 0x03, 0x00, 0x0F, 0x00, 0x02, 0xF4, 0x08};
uint8_t marche[11] = {0x01, 0x10, 0x00, 0x03, 0x00, 0x01, 0x02, 0x00, 0x01, 0x67, 0xA3};
uint8_t data[9];
uint32_t distance;


//*****************************************************************************
uint32_t calcul_distance(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {

  distance = (d * 1 + c* 16 + b * 16 * 16 + a * 16 * 16 * 16); //converts the 4 hex digits into decimal
  return distance;
}

//*****************************************************************************
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial2.begin(9600);
  delay(200);
  Serial.print("start");
  Serial2.write(marche, 11);
}

//*****************************************************************************

void loop() {
  Serial2.write(commandUnique, 8);
  delay(200);
  if( Serial2.available() >0){
    Serial2.readBytes(data, 9);
    Serial2.overflow();
  }

  for(int i = 0; i < sizeof(data); i++)
  {
    //Serial.print(data[i], HEX);
    //Serial.print("  ");
    crc.add(data[i]);
  }
  uint8_t CRC = crc.calc();
  //Serial.println(CRC, HEX);

  delay(200);
  byte5_1 = data[5] / 16;
  byte5_2 = data[5] - byte5_1 * 16;
  byte6_1 = data[6] / 16;
  byte6_2 = data[6] - byte6_1 * 16;
  distance = calcul_distance(byte5_1, byte5_2, byte6_1, byte6_2);

  if (distance < 20000 && CRC ==0) {
    Serial.println(distance);
  }

  crc.restart();
}