Serial Communication w/ Command Frames

Hello, I've been working on a project with an Arduino Mega and a U81 laser range finder from JRT (user manual attached below). I'm utilizing the UART ports on the Arduino to just use TTL Serial since that seems to be the most simplistic way to accomplish my goal. The user manual is riddled with typos, poorly translated sections, etc and it has been causing a lot of issues by not having a good reference document.
Currently I'm not even trying to user the laser range finder to measure distance, I'm simply trying to establish communications between my microcontroller and the U81. At the moment, I'm trying to give it this command:
image
and then the user manual shows the following as the method to read the result of the previous command:
image

Yet my Serial Monitor Output only gives me the following:
Serial Monitor Output

I've also attempting to send just the "read input voltage" command, and then to store and display the resulting data into a temp array but have been unsuccessful so far.

Here is my code as it sits currently:

// No need to include SoftwareSerial library, as we will use hardware UART (Serial1)
//Serial1____ -> Referring to exterior devices
//Serial____ -> Communicating to PC Serial Monitor to print data.

// COMMANDS FROM DATASHEET
byte rd_status[5] = {0xAA, 0x80, 0x00, 0x00, 0x80}; 
byte reply_status[9] = {0xAA, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
byte rd_hv[5] = {0xAA, 0x80, 0x00, 0x0A, 0x8A};
byte reply_hv[9] = {0xAA, 0x80, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00}; 
byte rd_sw[5] = {0xAA, 0x80, 0x00, 0x0C, 0x8C};
byte rd_sn[5] = {0xAA, 0x80, 0x00, 0x0E, 0x8E};
byte rd_vo[5] = {0xAA, 0x80, 0x00, 0x06, 0x86};
byte reply_vo[9] = {0xAA, 0x80, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00};
byte laser_on[9] = {0xAA, 0x00, 0x01, 0xBE, 0x00, 0x01, 0x00, 0x01, 0xC1};   
byte laser_off[9]  = {0xAA, 0x00, 0x01, 0xBE, 0x00, 0x01, 0x00, 0x00, 0xC0};  
byte one_shot_auto[9]  = {0xAA, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x21};
byte reply_measurement_results[5] ={0xAA, 0x80, 0x00, 0x22, 0xA2};


//==========

void setup() {

  // Establish baud rate
  Serial.begin(115200);
  delay(1000);
  Serial1.begin(115200);
  delay(2500);
  Serial.println("==========");
  Serial.println("Setup: Baud Rate has been established.");
  
  // Cycle Power To LRF
    Serial.println("Setup: Cycling Power to LRF...");
    Serial1.write(laser_off, 9);
    delay(100);
    Serial1.write(laser_on, 9);
    delay(2000);
    Serial.println("Setup: LRF Powered On.");
    
  //Read Input Voltage
    Serial.println("Setup: Checking Input Voltage...");
    Serial1.write(rd_vo, 5);
    delay(10);

      if (Serial1.available() >= 9) {
        Serial1.readBytes(reply_vo, 9);
      
      
  //Print Response 
        byte payload1 = reply_vo[6];
        byte payload2 = reply_vo[7];
        int combinedpayload = (payload1 << 8) | payload2;
          if(combinedpayload < 0x1000){
            Serial.println("0"); //Print leading zero if necessary
          }
      Serial.println(combinedpayload, HEX);
      }
      else {
        Serial.print("Raw VCC Reply Packet: ");
          for (int i = 0; i < 9; i++) {
            Serial.print(reply_vo[i], HEX);
            Serial.print(" ");
          }       
          Serial.println(); // Print a newline at the end
      }
      


}
//==========

void loop() {
  
}

Any and all suggestions are greatly appreciated, have been struggling with this for a couple weeks now :frowning:
U81 Laser Distance Sensor USER MANUAL.pdf (3.1 MB)

you may be giving the device sufficient time to respond
initially try waiting for 9 bytes, e.g. replace

if (Serial1.available() >= 9) 

with

while(Serial1.available() <9) delay(1);

then checking what is in the 9 bytes

How many milliseconds will be needed to get all 9 bytes from your laser device?

I see one major issue. Since you are using a baud rate of 115200 you must send the rangefinder an autobaud byte of 0x55 and then wait for a response of one byte. You must wait at least 100ms after powerup to do this but no longer than 2.5s. If you wait more than 2.5s it defaults to 19200.

See pages 8 and 9 of the manual:

In initial state, Slave module (laser rangefinder) is in power down mode before Master pull up the PWREN pin. After PWREN goes high, and if nRST pin. Used please also remember to de-assert then RST ping by pull it up, Slave will take about 100 milliseconds to do self-boot, and then entering autobaud rate detect stage.

Master transfer 1byte fixed data 0x55 to slave for auto baud rate, if success, slave will reply 1 byte data to master, which present the slave itself address. In one master and multi-slave communication situation, the self-address reply from the slaves may cause USART bus conflict, keep in mind this byte should be ignored.

At 115200 assuming 1 start, 1 stop, no parity a max of 11.5 bytes can be transmitted every millisecond. But it could be slower if there are time gaps between bytes.

Okay maybe I misunderstood that part of the user manual. My understanding was that I could use any baud rate between 9600bps and 115200bps which was on the page preceding the quote that you mentioned. Additionally, I thought my baud rate initialization was successful because I wasn't receiving strange characters, and I was able to obtain 9 elements from my array consistently (despite lacking the payload information).

Do you think that my approach was correct in the sense of how I utilized the arrays?

Would a spectrum analyzer, or an oscilloscope be of benefit for me to try to identify which packets were being transmitted? Just not sure on next steps to troubleshoot this.

Figure 6-1 in the manual gives you the exact startup sequence with timing. I don't see in your code where you are manipulating a digital output corresponding to the PWREN pin on the laserfinder. After that you should wait 100ms to send a 0x55 for autobaud. After that wait for the single address byte coming back from the laserfinder. At that point you can communicate with it. The alternative is after you enable the PWREN pin then you can wait 2.5s and communicate at the default 19200 speed.

You can. BUT the laserfinder has no idea what you set your speed to; hence, the Autobaud byte of 0x55. This allows the rangefinder to detect your serial speed.

The board defaulted to 19200. You were transmitting at 115200. The board didn't understand your request did not transmit anything to you.

You read the exact same elements from your array that you initialized it with. So that means nothing.

Yes. But you are not communicating.

I would also suggest you initialize your response arrays with all 0xFF so that you know that they are getting overwritten with serial data.

Ah! This makes lots of sense, I'll go attempt to implement these changes. Thank you so much for the help! :slight_smile:

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.