Part Number: LP-CC2652RB
Other Parts Discussed in Thread: CC2652RB, SYSCONFIG, Z-STACK, SYSBIOS
I wanted to use the sample project zr_temperaturesensor_LP_CC2652RB_tirtos_ccs and implement my own temperature measuring sensor to try and connect the board with zigbee2mqtt and evaluate a possible new project. I used the BME680 temp sensor with I2C for which i wrote a driver previously and it works fine in a different project on which I can read and write data from the sensor. I can confirm that the communication is correct in terms of protocol compliance, as i've checked it with the oscilloscope. However, this does not work at all when introducing the driver into the sample project as i2c communication seems to fail mid transmission (this only happens when using a sample ztack project) . I will try and detail the steps i took below:
In main, before creating a new task i initialize the i2c peripheral and the sensor.
#define SPI_BUFFER_SIZE 64
#define I2C_BUS_ADDR 0x00
static struct bme680_dev gBME680Struct = { };
bool gResult = true;
uint16_t gMeasPeriod = 0;
static I2C_Handle gI2C = { 0 };
static I2C_Params gI2CParams = { 0 };
static I2C_Transaction gI2CTransaction = { 0 };
static bool gI2CInitDone = false;
static uint8_t txBuf[SPI_BUFFER_SIZE];
static uint8_t rxBuf[SPI_BUFFER_SIZE];
int8_t userRead(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len);
int8_t userWrite(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len);
void userDelay(uint32_t period);
int8_t sensorBME680Init()
{
if (!gI2CInitDone){
return __LINE__;
}
int8_t rslt = BME680_OK;
gBME680Struct.dev_id = BME680_I2C_ADDR_PRIMARY;
gBME680Struct.intf = BME680_I2C_INTF;
gBME680Struct.read = userRead;
gBME680Struct.write = userWrite;
gBME680Struct.delay_ms = userDelay;
gBME680Struct.amb_temp = 25;
rslt = bme680_init(&gBME680Struct);
if (0 != rslt)
{
return __LINE__;
}
uint16_t setRequiredSettings;
/* Set the temperature, pressure and humidity settings */
gBME680Struct.tph_sett.os_hum = BME680_OS_2X;
gBME680Struct.tph_sett.os_pres = BME680_OS_4X;
gBME680Struct.tph_sett.os_temp = BME680_OS_8X;
gBME680Struct.tph_sett.filter = BME680_FILTER_SIZE_3;
/* Set the remaining gas sensor settings and link the heating profile */
gBME680Struct.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS;
/* Create a ramp heat waveform in 3 steps */
gBME680Struct.gas_sett.heatr_temp = 320; /* degree Celsius */
gBME680Struct.gas_sett.heatr_dur = 150; /* milliseconds */
/* Select the power mode */
gBME680Struct.power_mode = BME680_FORCED_MODE;
/* Must be set before writing the sensor configuration */
/* Set the required sensor settings needed */
setRequiredSettings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL
| BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL;
/* Set the desired sensor configuration */
rslt = bme680_set_sensor_settings(setRequiredSettings, &gBME680Struct);
/* Set the power mode */
rslt = bme680_set_sensor_mode(&gBME680Struct);
bme680_get_profile_dur(&gMeasPeriod, &gBME680Struct);
gBME680Struct.delay_ms(gMeasPeriod); /* Delay till the measurement is ready */
memset(txBuf, 0, SPI_BUFFER_SIZE);
memset(rxBuf, 0, SPI_BUFFER_SIZE);
return rslt;
}
int8_t sensorBME680I2CInit()
{
I2C_init();
I2C_Params_init(&gI2CParams);
gI2C = I2C_open(I2C_BUS_ADDR, &gI2CParams);
if (NULL == gI2C)
{
return __LINE__;
}
gI2CInitDone = true;
return 0;
}
int8_t userRead(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
if (!gI2CInitDone)
{
return __LINE__;
}
if ((dev_id != gBME680Struct.dev_id) || (NULL == data))
{
return __LINE__;
}
memset(txBuf, 0, SPI_BUFFER_SIZE);
txBuf[0] = reg_addr;
gI2CTransaction.slaveAddress = dev_id /*<< 1*/;
gI2CTransaction.readCount = len;
gI2CTransaction.readBuf = data;
gI2CTransaction.writeCount = 1;
gI2CTransaction.writeBuf = txBuf;
gResult = I2C_transfer(gI2C, &gI2CTransaction);
if (!gResult)
{
return -1;
}
return 0;
}
int8_t userWrite(uint8_t dev_id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
if (!gI2CInitDone)
{
return -1;
}
if ((dev_id != gBME680Struct.dev_id) || (NULL == data))
{
return -1;
}
memset(txBuf, 0, SPI_BUFFER_SIZE);
txBuf[0] = reg_addr;
memcpy(&txBuf[1], data, len);
gI2CTransaction.slaveAddress = dev_id;
gI2CTransaction.writeCount = len + 1;
gI2CTransaction.writeBuf = txBuf;
gI2CTransaction.readCount = 0;
gResult = I2C_transfer(gI2C, &gI2CTransaction);
if (!gResult)
{
return 1;
}
return 0;
}
void userDelay(uint32_t period)
{
usleep(1000 * period);
}
int8_t getSensorData(struct bme680_field_data *pData)
{
if (!gI2CInitDone)
{
return -2;
}
if (NULL == pData)
{
return -1;
}
static int8_t rslt = 0;
rslt = bme680_get_sensor_data(pData, &gBME680Struct);
if (gBME680Struct.power_mode == BME680_FORCED_MODE)
{
rslt = bme680_set_sensor_mode(&gBME680Struct);
}
return rslt;
}
void sensorBME680CommInit()
{
int8_t rslt = sensorBME680I2CInit();
if (0 != rslt)
{
return;
}
rslt &= sensorBME680Init();
if (0 == rslt)
{
gInitDone = true;
}
}
Then, i create a new task to poll the sensor and report the temperature changes:
void pollTask()
{
static int16_t temp = 0;
static zstack_bdbRepChangedAttrValueReq_t zReq;
while (1)
{
if (gInitDone)
{
GPIO_toggle(CONFIG_GPIO_RLED);
getSensorData(&gZSensorData);
temp = gZSensorData.temperature;
if (temp < zclSampleTemperatureSensor_MaxMeasuredValue
&& temp > zclSampleTemperatureSensor_MinMeasuredValue)
{
zclSampleTemperatureSensor_MeasuredValue = temp;
}
else if (temp >= zclSampleTemperatureSensor_MaxMeasuredValue)
{
zclSampleTemperatureSensor_MeasuredValue =
zclSampleTemperatureSensor_MaxMeasuredValue;
}
else if (temp <= zclSampleTemperatureSensor_MinMeasuredValue)
{
zclSampleTemperatureSensor_MeasuredValue =
zclSampleTemperatureSensor_MinMeasuredValue;
}
#ifdef BDB_REPORTING
zReq.attrID = ATTRID_TEMPERATURE_MEASUREMENT_MEASURED_VALUE;
zReq.cluster = ZCL_CLUSTER_ID_MS_TEMPERATURE_MEASUREMENT;
zReq.endpoint = SAMPLETEMPERATURESENSOR_ENDPOINT;
Zstackapi_bdbRepChangedAttrValueReq(appServiceTaskId, &zReq);
#endif
Task_sleep(100 * (1000 / Clock_tickPeriod));
}
}
}
I initialize it in main and start the task:
#define SENSOR_TASK_STACK_SIZE 1000
Task_Struct gPollTask;
Char pollTaskStack[SENSOR_TASK_STACK_SIZE];
Void sensorPollTask(UArg a0, UArg a1)
{
extern void pollTask();
pollTask();
}
// in main
{
sensorBME680CommInit();
Task_Params sensorTaskParams;
Task_Params_init(&sensorTaskParams);
sensorTaskParams.stack = pollTaskStack;
sensorTaskParams.priority = 2;
sensorTaskParams.stackSize = SENSOR_TASK_STACK_SIZE;
Task_construct(&gPollTask, sensorPollTask, &sensorTaskParams, NULL);
BIOS_start();
}
I cannot use the debugger for debugging purposes as it jumps all over the place, i can't follow each instruction and neither can i see most variables' values even when i'm paused over a line in scope. I've never had this happen in any ide before. Anyways, i can use the oscilloscope and see that some parts of the code are not being executed, but the program does not seem to fail. To be more clear, the first step in initializing the sensor is a soft reset command via i2c (send address with write bit set, send register address and send register value). The peripheral will only send the slave address and register address (which are both successfully acknowledged by the slave), then abruptly cuts off, does not send the register value nor end the i2c transmission with the stop bit. Will attach photo:

I assume the transmission does not end with a fail, but as i said once the debugger reaches the I2C_Transfer line, it just free runs by itself and will not let me step over to see the transmission result. Code following sensorBME680CommInit(); in main seems to get executed as the main zigbee task is running and the board does not seem to reset.
As a summary: in main, i call rslt = bme680_init(&gBME680Struct); which in turn calls rslt &= sensorBME680Init(); which calls rslt = bme680_init(&gBME680Struct); that is supposed to send a soft reset command to the sensor. The first two frames of the command are sent and ack'ed, but the transmission ends abruptly while the rest of the code seems to get executed. I cannot, for the life of me, get the board to initialize the sensor and check whether the rest of what i wrote works. Sensor polling task starts, but the sensor was not initialized, thus i cannot validate the data it's supposed to send.