I have been trying to interface the Witmotion WT901 sensor with the nRF5340 using the I2C interface. I have previously run the exact code on the nRF52DK and it was working perfectly well. However, when I try the same code for nRF5340, the sensor values I get are 0. I originally got the code by converting the provided STM SDK for the nRF52. I have also tried using the TWIM as an alternative but with the same results. Is there a hardware or project settings issue? I am using the i2c1 with P1.02 as SDA and P1.03 as the SCL.
Here is my main.c code.
#include <zephyr/kernel.h> #include <stdio.h> #include <dk_buttons_and_leds.h> #include <zephyr/drivers/i2c.h> #include <zephyr/shell/shell.h> #include <zephyr/shell/shell_uart.h> #include <drivers/include/nrfx_twim.h> #include <string.h> #include "REG.h" #define ACC_UPDATE 0x01 #define GYRO_UPDATE 0x02 #define ANGLE_UPDATE 0x04 #define MAG_UPDATE 0x08 #define READ_UPDATE 0x80 // Return message #define WIT_HAL_OK (0) /**< There is no error */ #define WIT_HAL_BUSY (-1) /**< Busy */ #define WIT_HAL_TIMEOUT (-2) /**< Timed out */ #define WIT_HAL_ERROR (-3) /**< A generic error happens */ #define WIT_HAL_NOMEM (-4) /**< No memory */ #define WIT_HAL_EMPTY (-5) /**< The resource is empty */ #define WIT_HAL_INVAL (-6) /**< Invalid argument */ #define WIT_DATA_BUFF_SIZE 256 // Protocols selection #define WIT_PROTOCOL_NORMAL 0 #define WIT_PROTOCOL_MODBUS 1 #define WIT_PROTOCOL_CAN 2 #define WIT_PROTOCOL_I2C 3 // Nordic related declarations #define I2C1_NODE DT_NODELABEL(witsensor) // static const nrfx_twim_t dev_i2c = NRF_TWIM_INSTANCE(I2C1_NODE); static const struct i2c_dt_spec dev_i2c = I2C_DT_SPEC_GET(I2C1_NODE); // Wit related declarations int16_t sReg[REGSIZE]; static volatile char s_cDataUpdate = 0, s_cCmd = 0xff; static uint8_t s_ucAddr = 0xff; static uint8_t s_ucWitDataBuff[WIT_DATA_BUFF_SIZE]; static uint32_t s_uiWitDataCnt = 0, s_uiProtoclo = 0, s_uiReadRegIndex = 0; // Function prototypes typedef int32_t (*WitI2cWrite)(const struct i2c_dt_spec *spec, const uint8_t *buf, uint32_t num_bytes); typedef int32_t (*WitI2cRead)(const struct i2c_dt_spec *spec, uint8_t *buf, uint32_t num_bytes); typedef void (*RegUpdateCb)(uint32_t uiReg, uint32_t uiRegNum); int32_t WitInit(uint32_t uiProtocol, uint8_t ucAddr); int32_t WitI2cFuncRegister(WitI2cWrite write_func, WitI2cRead read_func); int32_t WitRegisterCallBack(RegUpdateCb update_func); static void SensorDataUpdata(uint32_t uiReg, uint32_t uiRegNum); // Protocol states static WitI2cWrite p_WitI2cWriteFunc = NULL; static WitI2cRead p_WitI2cReadFunc = NULL; static RegUpdateCb p_WitRegUpdateCbFunc = NULL; int32_t WitInit(uint32_t uiProtocol, uint8_t ucAddr) { if (uiProtocol > WIT_PROTOCOL_I2C) { return WIT_HAL_INVAL; } s_uiProtoclo = uiProtocol; s_ucAddr = ucAddr; s_uiWitDataCnt = 0; return WIT_HAL_OK; } int32_t WitI2cFuncRegister(WitI2cWrite write_func, WitI2cRead read_func) { if (!write_func) { return WIT_HAL_INVAL; } if (!read_func) { return WIT_HAL_INVAL; } p_WitI2cWriteFunc = write_func; p_WitI2cReadFunc = read_func; return WIT_HAL_OK; } int32_t WitRegisterCallBack(RegUpdateCb update_func) { if (!update_func) { return WIT_HAL_INVAL; } p_WitRegUpdateCbFunc = update_func; return WIT_HAL_OK; } static void SensorDataUpdata(uint32_t uiReg, uint32_t uiRegNum) { int i; for (i = 0; i < uiRegNum; i++) { switch (uiReg) { // case AX: // case AY: case AZ: s_cDataUpdate |= ACC_UPDATE; break; // case GX: // case GY: case GZ: s_cDataUpdate |= GYRO_UPDATE; break; // case HX: // case HY: case HZ: s_cDataUpdate |= MAG_UPDATE; break; // case Roll: // case Pitch: case Yaw: s_cDataUpdate |= ANGLE_UPDATE; break; default: s_cDataUpdate |= READ_UPDATE; break; } uiReg++; } } int32_t WitReadReg(uint32_t uiReg, uint32_t uiReadNum) { uint16_t usTemp, i; uint8_t ucBuff[8]; if ((uiReg + uiReadNum) >= REGSIZE) { return WIT_HAL_INVAL; } if (p_WitI2cReadFunc == NULL) { return WIT_HAL_EMPTY; } usTemp = uiReadNum << 1; if (WIT_DATA_BUFF_SIZE < usTemp) { return WIT_HAL_NOMEM; } if (i2c_write_read_dt(&dev_i2c, &uiReg, 1, s_ucWitDataBuff, usTemp) == 0) { if (p_WitRegUpdateCbFunc == NULL) { return WIT_HAL_EMPTY; } for (i = 0; i < uiReadNum; i++) { sReg[i + uiReg] = ((uint16_t)s_ucWitDataBuff[(i << 1) + 1] << 8) | s_ucWitDataBuff[i << 1]; } p_WitRegUpdateCbFunc(uiReg, uiReadNum); } else { ("Failed to write / read I2C device address %x at Reg. %x \n\r ", dev_i2c.addr, uiReg); s_uiReadRegIndex = uiReg; } s_uiReadRegIndex = uiReg; return WIT_HAL_OK; } int main(void) { // 0x50 is the default sensor target address WitInit(WIT_PROTOCOL_I2C, 0x50); // Store the write and read functions WitI2cFuncRegister(i2c_write_dt, i2c_read_dt); // register to get sensor data callback function WitRegisterCallBack(SensorDataUpdata); int i; float fAcc[3], fGyro[3], fAngle[3]; while (1) { // Read sensor data at intervals WitReadReg(AX, 12); for (i = 0; i < 3; i++) { fAcc[i] = sReg[AX + i] / 32768.0f * 16.0f; fGyro[i] = sReg[GX + i] / 32768.0f * 2000.0f; fAngle[i] = sReg[Roll + i] / 32768.0f * 180.0f; } if (s_cDataUpdate & ACC_UPDATE) { printf("acc:%.3f %.3f %.3f\r\n", fAcc[0], fAcc[1], fAcc[2]); s_cDataUpdate &= ~ACC_UPDATE; } if (s_cDataUpdate & GYRO_UPDATE) { printf("gyro:%.3f %.3f %.3f\r\n", fGyro[0], fGyro[1], fGyro[2]); s_cDataUpdate &= ~GYRO_UPDATE; } if (s_cDataUpdate & ANGLE_UPDATE) { printf("angle:%.3f %.3f %.3f\r\n", fAngle[0], fAngle[1], fAngle[2]); s_cDataUpdate &= ~ANGLE_UPDATE; } if (s_cDataUpdate & MAG_UPDATE) { printf("mag:%d %d %d\r\n", sReg[HX], sReg[HY], sReg[HZ]); s_cDataUpdate &= ~MAG_UPDATE; } printf("angle:%.3f %.3f %.3f\r\n", fAngle[0], fAngle[1], fAngle[2]); } return 0; }
My overlay file:
&i2c1 { compatible = "nordic,nrf-twim"; status = "okay"; clock-frequency = <I2C_BITRATE_STANDARD>; witsensor: witsensor@50 { compatible = "i2c-device"; reg = <0x50>; label = "witsensor"; }; };
And for my prj.conf
CONFIG_I2C=y CONFIG_CBPRINTF_FP_SUPPORT=y