As promised here some more information about the laser range meter.
Attached you can find a protocol overview.
The following code sends the request to the laser device:
After 2 seconds the results are polled from the uart rx buffer
To make it better the answer should be, as already described, received with an interrupt routine.
Attached you can find a protocol overview.
The following code sends the request to the laser device:
Code:
//Define laser measurement on USART2
#define LASER_POWER_PIN 25
#define LASER_START_PIN 24
#define LASER_HEIGHT 1986
#define LASER_LATENCY 1999 //time for laser to answer in ms
int16_t laser_distance_array[SNOW_ARRAYSIZE] = { -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200, -200};
uint8_t laser_distance_array_ind = 0;
uint8_t laser_wd;
uint32_t LaserReqtime;
uint8_t LaserFlag = 0;
union laser_send_data_t {
struct bytes_t {
uint8_t preamble;
uint8_t command;
uint8_t data[3];
uint8_t check_code[2];
} bytes;
uint8_t array[sizeof(bytes)];
} laser_send_data;
union laser_rcv_data_t {
struct bytes_t {
uint8_t preamble;
uint8_t command;
uint8_t result;
uint8_t data[3];
uint8_t check_code[2];
} bytes;
uint8_t array[sizeof(bytes)];
} laser_rcv_data;
pinMode(LASER_POWER_PIN, OUTPUT);
pinMode(LASER_START_PIN, OUTPUT);
digitalWrite(LASER_POWER_PIN, HIGH);
digitalWrite(LASER_START_PIN, HIGH);
delay(50);
digitalWrite(LASER_START_PIN, LOW);
laser_send_data.bytes.preamble = 0xAA;
laser_send_data.bytes.command = 0x03;
Serial2.begin(38400);Code:
//Read distance with laser ---- data is retrieved at the end of callback_10s
laser_send_data.bytes.check_code[0] = (uint8_t)(laser_send_data.bytes.preamble + laser_send_data.bytes.command + laser_send_data.bytes.data[0] + laser_send_data.bytes.data[1] + laser_send_data.bytes.data[2]) << 8;
laser_send_data.bytes.check_code[1] = (uint8_t)(laser_send_data.bytes.preamble + laser_send_data.bytes.command + laser_send_data.bytes.data[0] + laser_send_data.bytes.data[1] + laser_send_data.bytes.data[2]);
Watchdog.reset(); //Reset global watchdog, just to make sure that it won't get trapped
Serial2.write(laser_send_data.array, sizeof(laser_send_data.array));
LaserReqtime = millis();
LaserFlag = 1;
//Check laser watchdog reset condition - if watchdog is not resetted within the data retrieving section reboot the laser distance sensor
if (laser_wd < 5) {
laser_wd++;
}
else {
digitalWrite(LASER_POWER_PIN, LOW);
delay(100);
digitalWrite(LASER_POWER_PIN, HIGH);
digitalWrite(LASER_START_PIN, HIGH);
delay(50);
digitalWrite(LASER_START_PIN, LOW);
laser_wd = 0;
}Code:
/////////////////////////////////////////////////////////////////////////////////
//////// Read values of laser distance sensor via USART 2 ///////////////////////
/////////////////////////////////////////////////////////////////////////////////
void read_laser(void) {
//Get data of Laser distance measurement
Watchdog.reset(); //Reset global watchdog, just to make sure that it won't get trapped
//Try to get data from serial 2
if (Serial2.available() >= 8) {
laser_wd = 0;//Reset Watchdog of laser meter if data is received - device is resettet after 5 sending counts without an answer
//Get data from buffer
Serial2.readBytes(laser_rcv_data.array, sizeof(laser_rcv_data.array));
//Calculate checksum
uint16_t checksum = 0;
for (uint8_t i = 0; i < sizeof(laser_rcv_data.array) - 2; i++) {
checksum = checksum + laser_rcv_data.array[i];
}
//Calculate distance if command, result and checksum is ok
if ((laser_rcv_data.bytes.command == 0x03) && (laser_rcv_data.bytes.result == 0x06) && (checksum == (laser_rcv_data.bytes.check_code[0] << 8 | laser_rcv_data.bytes.check_code[1]))) {
int32_t distance_temp = ((int32_t)(laser_rcv_data.bytes.data[0] << 16) | (int32_t)(laser_rcv_data.bytes.data[1] << 8) | (int32_t)laser_rcv_data.bytes.data[2]);
if (distance_temp < 32000 && distance_temp > -1) {
laser_distance_array[laser_distance_array_ind] = (int16_t)distance_temp;
//Serial.println(laser_distance_array[laser_distance_array_ind]);
}
//Move array pointer
if (laser_distance_array_ind < SNOW_ARRAYSIZE) {
laser_distance_array_ind++;
}
else {
laser_distance_array_ind = 0;
}
}
//If laser answers with wrong values
/*
else {
laser_distance_array[laser_distance_array_ind] = -100;
//Serial.println(laser_distance_array[laser_distance_array_ind]);
//Move array pointer
if (laser_distance_array_ind < SNOW_ARRAYSIZE) {
laser_distance_array_ind++;
}
else {
laser_distance_array_ind = 0;
}
}
*/
uint32_t uart_timeout = millis();
//Flush serial buffer if something is left for any reason and protect from endless looping
while (Serial2.available() > 0 && (millis() - uart_timeout < 500)) {
Serial2.read();
//Serial.println("Empty Buffer");
}
}
}To make it better the answer should be, as already described, received with an interrupt routine.

