【问题标题】:Can't read packets from Cygbot LIDAR properly无法从 Cygbot LIDAR 正确读取数据包
【发布时间】:2022-01-29 00:54:11
【问题描述】:

我正在尝试让 MCU 通过 UART 从激光雷达读取数据,但由于某种原因校验和不正确。我正在使用带有datasheet 的 ESP32-WROOM 开发芯片(使用 Arduino)和 Cygbot D1 LIDAR。我能够读取 2D 数据包,但不能读取更长的 3D 数据包。

收到一个数据包后,我使用Serial.read() 调用序列逐字节读取数据。正确读取数据包头、数据包长度字节和有效负载头。有效载荷长 14,401 字节。

当我读完数据后,校验和不匹配,串行缓冲区中还剩下大约 300 个字节。经过大量调试后,我被卡住了,如果有任何关于如何摆脱卡住的指示或想法,我将不胜感激。

我的代码的相关部分:

bool readPacket() {
  /*
   * Call when we're expecting a packet. The top of the buffer
   * must be the correct packet header. 
   */
  if (Serial2.available()) {
    //Check the header, return false if it's wrong
    if (not checkHeader()) {
      return false;
    }
    
    //Next 2 bytes are the packet length
    byte b0 = Serial2.read();
    byte b1 = Serial2.read();
    unsigned int payloadLen = combineBytesIntoInt(b0, b1);

    //Read in the data based on the payload header. 
    byte payloadHeader = Serial2.read();
    
    byte sum = b0 ^ b1 ^ payloadHeader; //Start computing checksum
    if (payloadHeader == 0x08) {
      sum ^= parse3D();
    }

    byte packetChecksum = Serial2.read();
    
    if (packetChecksum != sum) {
      Serial.println("Checksum error");
      return false;
    }
    return true;
  } else {
    return false;
  }
}

byte parse3D() {
  /*
   * Parse a 3D dataset, reading directly from the serial. 
   * Reading in batches of 3 due to the way data is formatted in the packet.
   * Returns checksum. 
   */
  byte checksum = 0;
  for (int i=0; i<N_MEASURES_3D; i+=2) {
    int msb0 = -1; 
    //If data hasn't been sent, Serial2.read will return -1. Wait until we receive valid data before proceeding.
    while (msb0 < 0) {
      msb0 = Serial2.read();
    }
    int split = -1;
    while (split < 0) {
      split = Serial2.read();
    }
    int lsb1 = -1;
    while (lsb1 < 0) {
      lsb1 = Serial2.read();
    }
    
    checksum ^= byte(msb0) ^ byte(split) ^ byte(lsb1);
  }
  return checksum
}

void loop() {
  //When the button is clicked, send a packet. 
  if (buttonState == 1) {    
    ct += 1;
    if (ct % 2 == 0) {
      Serial.println("Write packet: start 3d");
      lidarStart3DMode();
    }
  }
  
  bool readSuccess = readPacket();
  if (readSuccess) {
    lidarStop();
  }

  //This code just updates the button  
  if ((digitalRead(BUTTON_PIN) == 1) and (millis() - lastTime > BUTTON_DEBOUNCE_TIME)) {
      lastTime = millis();
      buttonState = 1;
  } else {
    buttonState = 0;
  }
}


【问题讨论】:

  • if (Serial2.available()) 只确保您至少有 1 个字节要读取。你盲目地打电话给.read(),而没有确保有什么要读的。

标签: arduino serial-port protocols uart packet


【解决方案1】:

您的代码中的所有内容都在这里:

byte b0 = Serial2.read();
byte b1 = Serial2.read();
unsigned int payloadLen = combineBytesIntoInt(b0, b1);

//Read in the data based on the payload header. 
byte payloadHeader = Serial2.read();

这里

byte packetChecksum = Serial2.read();

并且可能在checkHeader()(您没有提供)中,应该保护防止缓冲区欠载,即在没有可用字节时读取字节。

你可以添加

while (!Serial.available());

在每个read()之前。

【讨论】:

  • 谢谢!这解决了它。
猜你喜欢
  • 2022-01-15
  • 1970-01-01
  • 2012-03-15
  • 2021-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-05
相关资源
最近更新 更多