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