I2C Communication Issue with SEN5X Sensor on nRF9160 DK -EI0

I'm experiencing an issue with I2C communication between the SEN5X sensor and multiple nRF9160 DK boards. The problem manifests as an  crc error during I2C read operations, specifically a -EIO error, indicating an Input/Output error. This issue occurs on some nRF9160 DK boards but not all, which suggests it might be a hardware or configuration issue.

The output is like this.

*** Booting nRF Connect SDK v3.5.99-ncs1-1 ***
Welcome to IOTPM running on nrf9160dk_nrf9160
Start the Sen55
SEN5X: write: 0xd304
Get the sensor information
SEN5X: write: 0xd014
SEN5X: Error i2c read
crc error: byte 0: found: 0x05, expected 0xc2
crc error: byte 2: found: 0x63, expected 0x7b
crc error: byte 4: found: 0x00, expected 0x02
crc error: byte 6: found: 0x41, expected 0x81
crc error: byte 8: found: 0x80, expected 0x81
crc error: byte 10: found: 0x00, expected 0xaa
crc error: byte 12: found: 0x00, expected 0x49
crc error: byte 14: found: 0x3f, expected 0xfb
crc error: byte 16: found: 0x80, expected 0x81
crc error: byte 18: found: 0x00, expected 0xaa
crc error: byte 20: found: 0x00, expected 0x49
crc error: byte 22: found: 0x3f, expected 0xfb
crc error: byte 24: found: 0x80, expected 0x81
crc error: byte 26: found: 0x00, expected 0xaa
crc error: byte 28: found: 0x00, expected 0x49
crc error: byte 30: found: 0x3f, expected 0xfb
SEN5X: write: 0xd033
SEN5X: Error i2c read
crc error: byte 0: found: 0x05, expected 0xc2
crc error: byte 2: found: 0x63, expected 0x7b
crc error: byte 4: found: 0x00, expected 0x02
crc error: byte 6: found: 0x41, expected 0x81
crc error: byte 8: found: 0x80, expected 0x81
crc error: byte 10: found: 0x00, expected 0xaa
crc error: byte 12: found: 0x00, expected 0x49
crc error: byte 14: found: 0x3f, expected 0xfb
crc error: byte 16: found: 0x80, expected 0x81
crc error: byte 18: found: 0x00, expected 0xaa
crc error: byte 20: found: 0x00, expected 0x49
crc error: byte 22: found: 0x3f, expected 0xfb
crc error: byte 24: found: 0x80, expected 0x81
crc error: byte 26: found: 0x00, expected 0xaa
crc error: byte 28: found: 0x00, expected 0x49
crc error: byte 30: found: 0x3f, expected 0xfb
SEN5X: Device name: 8
SEN5X: Serial number: 8
Connect to the LTE


I have an overlay with the following 

&uart0 {
  status = "okay";
};

&i2c2 {
	status = "ok";
	clock-frequency = <100000>;
	compatible = "nordic,nrf-twim";
	pinctrl-0 = <&i2c2_default>;
	pinctrl-1 = <&i2c2_sleep>;
	sen55: sen55@69{
		// compatible = "nordic,nrf-twim";
		compatible = "i2c-device";
		reg = <0x69>;
		label = "sensirion i2c sen55";
	};
};

&i2c2_default {
	group1 {
		psels = <NRF_PSEL(TWIM_SDA, 0, 30)>, <NRF_PSEL(TWIM_SCL, 0, 31)>;
		bias-pull-up;
	};
};

The errer is coming from the readmany() function below.

#include <zephyr/drivers/i2c.h>
#include <sen5x/sen5x.h>

const struct device * sen5x_dev;

bool sen5x_init(const struct device * dev){
	sen5x_dev=dev;
	if(!device_is_ready(sen5x_dev)){ printk("SEN5X: I2C device not ready\n"); return false;}
	uint32_t i2c_cfg = I2C_SPEED_SET(I2C_SPEED_STANDARD) | I2C_MODE_CONTROLLER;
	int32_t ret=i2c_configure(sen5x_dev, i2c_cfg);
	if(ret){printk("SEN5X: Error configuring I2C\n");return false;}
	return true;
}

void sen5x_write_short(uint16_t command){
	uint8_t data[2];
	data[0]=(command&0xFF00)>>8;
	data[1]=(command&0x00FF)>>0;
	printk("SEN5X: write: 0x%02x%02x\n",data[0],data[1]);
	i2c_write(sen5x_dev,data,2,PM_I2C_ADDRESS);
}

void sen5x_write(uint8_t * data, uint8_t len){
	int32_t ret=i2c_write(sen5x_dev, data, len, PM_I2C_ADDRESS);	
	if(ret){printk("SEN5X: Error i2c write\n");}
}

void sen5x_read(uint8_t * data, uint8_t len){
	int32_t ret=i2c_read(sen5x_dev, data, len, PM_I2C_ADDRESS);
	if(ret){printk("SEN5X: Error i2c read\n");}
}

void sen5x_read_many(uint8_t * many, uint8_t len){
	uint8_t data[100];
	uint8_t mlen=len+(len/2);
	sen5x_read((uint8_t*)data,mlen);
	//printk("SEN5X: many (%i)",mlen);
	//for(uint32_t i=0;i<mlen;i++){printk("%02x",(uint32_t)data[i]);}
	//printk("\n");
	for(uint32_t i=0;i<len/2;i++){
		many[2*i]  =data[3*i];
		many[2*i+1]=data[3*i+1];
		if(data[3*i+2]!=sen5x_crc(&many[2*i],2)){printk("crc error: byte %i: found: 0x%02x, expected 0x%02x\n",(2*i),data[3*i+2],sen5x_crc(&many[2*i],2));}
	}
}

uint8_t sen5x_crc(const uint8_t * data, uint8_t len){
  uint8_t crc = 0xFF;
  for (uint32_t current_byte = 0; current_byte < len; ++current_byte) {
      crc ^= (data[current_byte]);
      for (uint8_t crc_bit = 8; crc_bit > 0; --crc_bit) {
          if(crc & 0x80)
						crc = (crc << 1) ^ 0x31;
          else         
						crc = (crc << 1);
      }
  }
  return crc;
}

void sen5x_reset(){
	sen5x_write_short(0xD304);
	k_msleep(100);
}

void sen5x_get_serial(char * serial, uint8_t len){
	sen5x_write_short(0xD033);
	for(uint32_t i=0;i<len;i++){ serial[i]=0; }
	k_msleep(500);
	sen5x_read_many(serial,len);
}

void sen5x_get_name(char * name, uint8_t len){
	sen5x_write_short(0xD014);
	for(uint32_t i=0;i<len;i++){ name[i]=0; }
	k_msleep(500);
	sen5x_read_many(name,len);
}

void sen5x_get_version(struct sen5x_version * pmv){
	sen5x_write_short(0xD100);
	k_msleep(500);
	sen5x_read_many((uint8_t*)pmv,8);	
}

void sen5x_start(){
	sen5x_write_short(0x0021);
	k_msleep(500);
}

void sen5x_stop(){
	sen5x_write_short(0x0104);
	k_msleep(50);
}

void sen5x_get_measurement(struct sen5x_measurement * pmm){
	sen5x_write_short(0x03C4);
	k_msleep(20);
	uint8_t data[16];
	sen5x_read_many(&data[0],16);
	pmm->mass_concentration_pm1p0=data[0]<<8|data[1];
	pmm->mass_concentration_pm2p5=data[2]<<8|data[3];
	pmm->mass_concentration_pm4p0=data[4]<<8|data[5];
	pmm->mass_concentration_pm10p0=data[6]<<8|data[7];
	pmm->ambient_humidity=data[8]<<8|data[9];
	pmm->ambient_temperature=data[10]<<8|data[11];
	pmm->voc_index=data[12]<<8|data[13];
	pmm->nox_index=data[14]<<8|data[15];
}

void sen5x_print_measurement(struct sen5x_measurement * pmm){
	printk("Mass concentration pm1p0: %.2f ug/m3\n", (pmm->mass_concentration_pm1p0 / 10.0f));
	printk("Mass concentration pm2p5: %.2f ug/m3\n", (pmm->mass_concentration_pm2p5 / 10.0f));
	printk("Mass concentration pm4p0: %.2f ug/m3\n", (pmm->mass_concentration_pm4p0 / 10.0f));
	printk("Mass concentration pm10p0: %.2f ug/m3\n", (pmm->mass_concentration_pm10p0 / 10.0f));
	printk("Ambient humidity: %.2f %%RH\n", (pmm->ambient_humidity / 100.0f));
	printk("Ambient temperature: %.3f C\n", (pmm->ambient_temperature / 200.0f));
	printk("Voc index: %.2f\n", (pmm->voc_index / 10.0f));
	printk("Nox index: %.2f\n", (pmm->nox_index / 10.0f));
}

void sen5x_get_info(struct sen5x_info * info){
	sen5x_get_name(info->name,32);
	sen5x_get_serial(info->serial,32);
}

void sen5x_print_info(struct sen5x_info * info){
	printk("SEN5X: Device name: %s\n", info->name);
	printk("SEN5X: Serial number: %s\n", info->serial);	
}

void sen5x_print_details(){
	char name[32];
	sen5x_get_name(name,32);
	printk("SEN5X: Device name: %s\n",name);

	char serial[32];
	sen5x_get_serial(serial,sizeof(serial));
	printk("SEN5X: Serial number: %s\n", serial);

	struct sen5x_version pmv;
	sen5x_get_version(&pmv);
	printk("SEN5X: FW: %u.%u.%u\n", pmv.firmware_major,pmv.firmware_minor, pmv.firmware_debug);
	printk("SEN5X: HW: %u.%u\n", pmv.hardware_major,pmv.hardware_minor);
	printk("SEN5X: PR: %u.%u\n", pmv.protocol_major,pmv.protocol_minor);
}

Parents Reply Children
Related