Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Library deadlocks when using PM25AQI sensor with uart #14

Open
mraleson opened this issue Jan 24, 2024 · 1 comment
Open

Library deadlocks when using PM25AQI sensor with uart #14

mraleson opened this issue Jan 24, 2024 · 1 comment

Comments

@mraleson
Copy link

  • Arduino board: ESP32 Feather
  • Arduino IDE version (found in Arduino -> About Arduino menu): 1.8.13

When connecting to the particle sensor using the uart, the sensor will after about a minute fail continuously and not give any output. Removing this check allows the sensor to eventually resolve and continue functioning:

// Are there enough bytes to read from?
if (serial_dev->available() < bufLen) {
return false;
}

It looks like the sensor won't send any more data until the bogus bytes are read. After they are consumed the sensor will continue forward, fail the checksum and re-stabilize.

This PR would help prevent the issue: #10

Although, there may be other situations that could cause this deadlock to arise, like a noisy serial connection. I think both of these changes might be worth making, the consequence being some reads might fail the checksum, but as it is the reads fail continuously anyway.

Also in the forums it looks like these issues have been what these two people refer to, and sounds like it caused them to return their sensors:
https://forums.adafruit.com/viewtopic.php?t=200668&sid=ddf03cb5dfe45415ac3b76f599fcfa4e&start=15

@mraleson
Copy link
Author

This is the approach I ended up taking. It's an alternative to #10 but incorporates those fixes and fixes this issue. It also simplifies the code (aside from reusing the buffer). Hopefully I didn't overlook anything / introduce any bugs but it seems to be working and I tested a few cases. Sorry its not a PR I just ran out of time!

uint16_t consumed = 0;
uint8_t buffer[32];
bool read_aqi(PM25_AQI_Data *data) {
  // check that the aqi data structure is allocated
  if (!data) {
    return false;
  }

  // recycle any failed buffer if possible, by finding a new start byte
  if (consumed == 32) {
    uint16_t i, j;
    for (i = 1; i < 32 && buffer[i] != 0x42; i++) {}
    consumed = 32 - i;
    for (j = 0; j < consumed; j++) {
      buffer[j] = buffer[i + j];
    }
  }

  // attempt to read a complete message
  while (Serial1.available() && consumed < 32) {
    buffer[consumed] = Serial1.read();
    consumed++;
  }

  // if unable to read enough bytes, exit and continue next time
  if (consumed < 32) {
    return false;
  }

  // check the start bytes
  if (buffer[0] != 0x42 || buffer[1] != 0x4d) {
    return false;
  }

  // compute check sum
  uint16_t sum = 0;
  for (uint8_t i = 0; i < 30; i++) {
    sum += buffer[i];
  }

  // the data comes in endian'd, this solves it so it works on all platforms
  uint16_t buffer_u16[15];
  for (uint8_t i = 0; i < 15; i++) {
    buffer_u16[i] = buffer[2 + i * 2 + 1];
    buffer_u16[i] += (buffer[2 + i * 2] << 8);
  }

  // put it into a nice struct :)
  memcpy((void *)data, (void *)buffer_u16, 30);

  // validate the checksum
  if (sum != data->checksum) {
    return false;
  }

  // success!
  consumed = 0;
  return true;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant