Laser Range Finder Freezes after Several Minutes of Usage - Need Help with Serial Communication

Hello everyone,

I'm working on a project involving a laser range finder from DF Robot (Laser Ranging Sensor UART 4m SKU SEN0491). I am using a Seeed Xiao NRF52840 microcontroller for this setup. My Arduino code reads sensor values over Serial, but I'm running into an issue where the sensor works fine for about 5 minutes and then freezes. By "freezing," I mean it starts reporting the same distance value over and over.

Problem:

  • Laser works well for 5 minutes
  • Then it "freezes," i.e., gets stuck on the same distance value
  • Requires power cycling the laser to recover
  • Upon recovery, it freezes again after approximately 4 minutes

Code:


#define DEBUG                 true  
#define DEBUG_SERIAL \
  if (DEBUG) Serial


void setup(void) {
  Serial.begin(115200);
  Serial1.begin(115200);
  while (!Serial1);
  //init_dac();
}



void loop() {
  print_reply_wait();
  delay(10);
}



void print_reply_wait()
{
  //DEBUG_SERIAL.println("print/wait reply start");
  int32_t timeoutStart = millis();
  int32_t timeoutDuration = 100; 
  int32_t responseReceivedTimestamp = 0;
  bool responseReceived = false;
  
  const int bufferSize = 128;
  char readBuffer[bufferSize];
  int bufferIndex = 0;

  while (millis() - timeoutStart < timeoutDuration && bufferIndex < bufferSize - 1)
  {
    if (Serial1.available())
    {
      if (!responseReceived)
      {
        responseReceived = true;
        responseReceivedTimestamp = millis();
      }

      char incomingChar = (char)Serial1.read();
      readBuffer[bufferIndex] = incomingChar;
      bufferIndex++;
      
      //#if DEBUG
        //DEBUG_SERIAL.print(incomingChar);
      //#endif
    }

    if (responseReceived && millis() - responseReceivedTimestamp >= 50)
    {
      break; // Break the loop if a response was received and 200ms have passed
    }
  }
  
  readBuffer[bufferIndex] = '\0'; // Null-terminate the string
  
  char* startPtr = strstr(readBuffer, "d:");
  if (startPtr != NULL) 
  {
    startPtr += 3; // Move the pointer to the beginning of the distance value
    char* endPtr = strstr(startPtr, " mm");
    if (endPtr != NULL) 
    {
      *endPtr = '\0'; // Null-terminate the distance string
      int distance = atoi(startPtr);
      DEBUG_SERIAL.print("Extracted distance: ");
      DEBUG_SERIAL.println(distance);
    }
  }
  print_reply();
  //DEBUG_SERIAL.println("print/wait reply end");
}


void print_reply()
{
    while (Serial1.available())
    {
      #if DEBUG
        DEBUG_SERIAL.println("leftovers remain");
        DEBUG_SERIAL.print((char)Serial1.read());
        DEBUG_SERIAL.println("leftovers remain end");
      #else
        Serial1.read();
      #endif
    }
}


Things I've Tried:

  • Power-cycling the laser
  • Checked the buffer read and write operations

Questions:

  1. Could I be reading the serial port too fast or too slow? The laser's documentation isn't very comprehensive.
  2. Is there a potential issue with the buffer size or the way I'm reading the Serial data?
  3. Could this be a hardware issue? I don't face the problem when the microcontroller is reset, only when the laser is power-cycled.

I would greatly appreciate any insights or suggestions on how to resolve this issue. Thank you in advance for your time and help!

That can be because of writing bryond beyond the bounds of an array into memory that youbfont you don't "own". Print the bufferIndex to make sure that you are not writing past the bounds of the array.

Edit: fixed typos.

... that you don't ...

... make...

Tiny keyboard, fat shaky fingers.
Spellcheck not my friend today. Fixed.

Well, looks like you try and read from serial in a while loop with a millis timer for a possible time out..

but after the while loop you don't check to make certain that resonseReceived is true..

need another if after the serial while loop to make sure you didn't just time out..

good luck.. ~q

I connected the laser directly to an Analog Discovery Pro and used the serial analyzer. It is sending readings every 100ms. Even on the ADP it froze after about 4 minutes.
Faulty laser perhaps?

I can see there are some settings in the table, but I am unsure of how to apply these settings.

That's Modbus RTU..

have a look in in my git..
there's a spec doc and test app in there..
may help..

good luck.. ~q

Thanks! I'll give that a shot, although I am not sure what settings will help this particular situation.

Start with system recovery, first command, says it sets all other values to defaults..
If it's address is 1, then the bytes to send should be..

{0x01,0x06,0x00,0x00,0x00,0x01,0x48,0x0A}

good luck.. ~q

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