NRF52840 locking up trying to communicate with CO2 Sensor

I am using a seeed nRF52840 (link)
and trying to communicate with a senseair K33 CO2 sensor

Here is my code that works for about 2 minutes, then seems to halt randomly. It will stop printing to the console until I remove power and plug back in.


#include <Wire.h>
#include "Adafruit_TinyUSB.h"


int co2Addr = 0x68;


void setup() {
  Serial.begin(115200);
  while(!Serial)
  {
    delay(5);
  }
  Serial.println("Program Started");
  Wire.setClock(100000); // Set I2C clock speed to 100 kHz
  Wire.begin();
}


double readCo2() {
  Serial.println("Starting readCo2() function");
  int co2_value = 0;

  // Clear I2C bus
  Wire.beginTransmission(co2Addr);
  byte clearBusResult = Wire.endTransmission();
  Serial.print("Clear bus result: ");
  Serial.println(clearBusResult);
  delay(5);  // Wait a bit before sending the actual command

  Wire.beginTransmission(co2Addr);
  Wire.write(0x22);  // Command to read from RAM
  Wire.write(0x00);  // High byte of number of bytes to read
  Wire.write(0x08);  // Start address (high byte of CO2 value)
  Wire.write(0x2A);  // Checksum for the write sequence
  byte transmissionResult = Wire.endTransmission();
  Serial.print("End transmission result: ");
  Serial.println(transmissionResult);

  delay(20);  // Wait for the sensor to process the command

  Serial.println("Requesting data from sensor");
  Wire.requestFrom(co2Addr, 4);
  byte buffer[4] = {0, 0, 0, 0};

  if (Wire.available() == 4) {
    Serial.println("Reading data from buffer");
    for (int i = 0; i < 4; i++) {
      buffer[i] = Wire.read();
      Serial.print("Buffer[");
      Serial.print(i);
      Serial.print("]: ");
      Serial.println(buffer[i], HEX);
    }

    co2_value = (buffer[1] << 8) | buffer[2];
    Serial.print("CO2 Value: ");
    Serial.println(co2_value);

    byte sum = buffer[0] + buffer[1] + buffer[2];
    Serial.print("Calculated checksum: ");
    Serial.println(sum, HEX);
    Serial.print("Received checksum: ");
    Serial.println(buffer[3], HEX);

    if (sum == buffer[3]) {
      Serial.println("Checksum valid");
      return (double)co2_value;
    } else {
      Serial.println("Checksum invalid");
      return (double)-1;
    }
  } else {
    Serial.println("Insufficient data received");
    return (double)-1;  // Communication failed
  }
}



void loop() {
  unsigned long currentTime = millis();
  Serial.print("Time since start: ");
  Serial.print(currentTime / 1000);  // Convert milliseconds to seconds
  Serial.println(" seconds");
  double co2Value = readCo2();
  if (co2Value >= 0) {
    Serial.print("CO2: ");
    Serial.println(co2Value);
  }
  else {
    Serial.println("Checksum failed / Communication failure");
  }
  delay(2000);
}

I have the 5V rail from the nRF powering the CO2 sensor, and then i2c lines connected as expected on pins 4 and 5.


Any suggestions why it seems to "lock up" ?

Blockquote

So, what was the last thing printed? And is that consistent?

I see in the documentation that this call returns the number of bytes that were returned. So you might want to check here for the byte being returned has a value of 4 and an error if not 4.

No unfortunately not.
I actually just ran a test running this only:

double readCo2() {
  Serial.println("Starting readCo2() function");
  int co2_value = 0;

  // Clear I2C bus
  Wire.beginTransmission(co2Addr);
  byte clearBusResult = Wire.endTransmission();
  Serial.print("Clear bus result: ");
  Serial.println(clearBusResult);
  delay(5);  // Wait a bit before sending the actual command
}

After about 1 minute (not repeatable) it will stop printing to console

With all the serial.print calls, you must be able to determine the last message to be displayed! What is it?

It ranges. but typically lands on Serial.print("Time since start: "); right before the call to the readCO2() function. But I have seen in land on the Serial.print("Clear bus result: "); as well

Which model sensor do you have? Is it 3.3V, to match the processor?

Rather than read one byte and print, I suggest to read all four bytes, then do other things like print.

    for (int i = 0; i < 4; i++) {
      buffer[i] = Wire.read();
      Serial.print("Buffer[");

Yes, very strange!
Try moving ALL your locally defined variables to globally defined and see if that changes anything.