Hello!
I've been playing around with nRF9160DK for a while now and so far the device seems great and the vast majority of available resources for development is really great. But I've stumbled upon an issue for the last couple of days and can't find what might be the reason.
The issue:
I decided to update the existing cellular UDP sample code so that it reads data from an actual sensor and sends them to the desired endpoint. I enable i2c, added the devicetree node and got the sensor working. The reading was held in another work task independent from UDP upload task. So far so good. Then I checked the current consumption and saw that the current in PSM jumped from ~4uA to ~370 uA - all clear, the i2c driver is not sleeping and it added the current draw. Spent some time figuring out the correct way to put peripheral to sleep but I got it working. Calling pm_device_action_run(DEVICE_DT_GET(DT_NODELABEL(i2c2)), PM_DEVICE_ACTION_SUSPEND);
and pm_device_action_run(DEVICE_DT_GET(DT_NODELABEL(i2c2)), PM_DEVICE_ACTION_RESUME);
returns success and seems like the peripheral should be sleeping, but when I checked nRF9160 current profile, I saw the same ~370uA in PSM mode - not the result I was looking for. I spent a lot of time debugging this issue but nothing helped and then I decided to try the same Power manager functions on uart0 (the serial output peripheral) and everything worked just fine - in PSM I saw the same ~4uA and in active mode the serial output was printing to console meaning that module was indeed in low power mode.
Now comes the question what is wrong with i2c, why I did not see any current drop when i2c is in sleep mode? Could it be a hardware issue? Currently I don't have second DK but its ordered and on its way. I'll test this whenever I get my hands on it. But maybe its something else I missed?
proj.conf:
#
# Copyright (c) 2020 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
# General config
CONFIG_PICOLIBC_IO_FLOAT=y
CONFIG_NCS_SAMPLES_DEFAULTS=y
CONFIG_SERIAL=y
# Network
CONFIG_NETWORKING=y
CONFIG_NET_NATIVE=n
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_OFFLOAD=y
# LTE link control
CONFIG_LTE_LINK_CONTROL=y
# Modem library
CONFIG_NRF_MODEM_LIB=y
# Heap and stacks
CONFIG_HEAP_MEM_POOL_SIZE=1024
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
# LTE parameters
## Network Mode / LTE category
CONFIG_LTE_NETWORK_MODE_LTE_M=y
## PSM
CONFIG_UDP_PSM_ENABLE=y
CONFIG_LTE_PSM_REQ_RPTAU="00100001"
CONFIG_LTE_PSM_REQ_RAT="00000000"
## eDRX
CONFIG_UDP_EDRX_ENABLE=y
CONFIG_LTE_EDRX_REQ_VALUE_LTE_M="1001"
## RAI
CONFIG_UDP_RAI_ENABLE=y
CONFIG_UDP_DATA_UPLOAD_FREQUENCY_SECONDS=10
## Additional peripherals
CONFIG_I2C=y
CONFIG_PM_DEVICE=y
function suspending and resuming i2c:
void read_sensor_measurements() {
/* Function variables */
static bool firstLoop = true;
int error;
int numBytes = 7;
uint8_t data[numBytes];
enum pm_device_state state;
if(!firstLoop) //skip first iteration
{
error = pm_device_action_run(DEVICE_DT_GET(DT_NODELABEL(i2c2)), PM_DEVICE_ACTION_RESUME);
if(error !=0)
{
printf("i2c RESUME failed %d\n", error);
}
pm_device_state_get(DEVICE_DT_GET(DT_NODELABEL(i2c2)), &state);
printf("Current state after resume: %d\n", state);
}
/* Wakeup */
if(!(_wakeup())) {
printf("Failed to wake up sensor.\n");
return;
}
/* Request values */
error = i2c_write_dt(&dev_i2c, &ERROR_STATUS, 1);
error = i2c_read_dt(&dev_i2c, data, numBytes);
if(error != 0 ) {
printf("Failed to read values. Error code: %d\n", error);
return;
}
/* Read values */
/* Error status */
uint8_t eStatus = data[0];
/* Reserved */
uint8_t byteHi = data[1];
uint8_t byteLo = data[2];
byteHi = data[3];
byteLo = data[4];
/* CO2 value */
byteHi = data[5];
byteLo = data[6];
uint16_t co2Val = ((int16_t)(int8_t) byteHi << 8) | (uint16_t)byteLo;
firstLoop = false;
error = pm_device_action_run(DEVICE_DT_GET(DT_NODELABEL(i2c2)), PM_DEVICE_ACTION_SUSPEND);
if(error != 0 ) {
printf("Failed to suspend i2c %d\n", error);
}
k_sleep(K_MSEC(500));
pm_device_state_get(DEVICE_DT_GET(DT_NODELABEL(i2c2)), &state);
printf("Current state after suspend: %d\n", state);
printf("CO2: %d ppm\n", co2Val);
printf("Error Status: 0x%X\n", eStatus);
}
devicetree overlay file (copied from BME680 sample so some comments might be irrelevant):
/*
* Copyright (c) 2020, Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
&i2c2 {
compatible = "nordic,nrf-twim";
// status = "okay";
clock-frequency = <I2C_BITRATE_STANDARD>;
/* The I2C address could be one of two, here 0x77 is assumed */
sensor: sensor@68 {
compatible = "i2c-device";
status = "okay";
reg = <0x68>;
};
};
And here is the .zip of project 2134.udp_sample_i2c.zip
In case you need anything else to help me resolve this issue let me know.
Regards,
Andris