SHT4x interface with nRF52840

Hi,

I am trying to integrate Sensirion SHT40 sensor with nRF52840. I am using the sensor sample app from 2.9.0 SDK. I am building with 2.6.1 SDK with toolchain 2.6.1.  The build is ok, but when the app starts, it just get stuck as I can see in the console as follows.

[00:00:00.003,143] <inf> ieee802154_nrf5: nRF5 802154 radio initialized
[00:00:00.003,173] <dbg> temp_nrf5_mpsl: temp_nrf5_mpsl_init:
[00:00:00.009,490] <inf> fs_nvs: 8 Sectors of 4096 bytes
[00:00:00.

Then I added CONFIG_COAP_CLIENT=y to prj.conf and I get the following.

[00:00:00.[00:00[00:00:00.003,326] <dbg> temp_nrf5_mpsl: temp_nrf5_mpsl_init:
[00:00:00.009,643] <inf> fs_nvs: 8 Sectors of 4096 bytes
[00:00:00.009,643] <inf> fs_nvs: alloc wra: 0, e00
[00:00:00.009,674] <inf> fs_nvs: data wra: 0, 810
*** Booting nRF Connect SDK v3.5.99-ncs1-1 ***
ASSERTION FAIL @ WEST_TOPDIR/zephyr/kernel/thread.c:601
        invalid priority (15); allowed range: 14 to -16
[00:00:00.038,909] <dbg> temp_nrf5_mpsl: temp_nrf5_mpsl_sample_fetch: sample: 96
[00:00:00.038,940] <dbg> temp_nrf5_mpsl: temp_nrf5_mpsl_channel_get: Temperature:24,0
[00:00:00.039,031] <err> os: r0/a1:  0x00000004  r1/a2:  0x00000259  r2/a3:  0x00000009
[00:00:00.039,062] <err> os: r3/a4:  0x20001a40 r12/ip:  0x00000014 r14/lr:  0x00022321
[00:00:00.039,062] <err> os:  xpsr:  0x41000000
[00:00:00.039,093] <err> os: s[ 0]:  0x00000001  s[ 1]:  0x20003f10  s[ 2]:  0x20002bf8  s[ 3]:  0x0003b379
[00:00:00.039,093] <err> os: s[ 4]:  0x00000000  s[ 5]:  0x00000000  s[ 6]:  0x000539d0  s[ 7]:  0x20015744
[00:00:00.039,123] <err> os: s[ 8]:  0x20002bf8  s[ 9]:  0x0003ac5d  s[10]:  0x000539d0  s[11]:  0x20015744
[00:00:00.039,154] <err> os: s[12]:  0x0000000e  s[13]:  0x00022317  s[14]:  0x000539d0  s[15]:  0x0000000f
[00:00:00.039,154] <err> os: fpscr:  0x0000000e
[00:00:00.039,154] <err> os: Faulting instruction address (r15/pc): 0x0003ac4a
[00:00:00.039,215] <err> os: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0
[00:00:00.039,245] <err> os: Current thread: 0x20003f10 (main)

I have attached my prj.conf and overlay file.

87304.prj.conf

6366.nrf52840dk_nrf52840.overlay

I haven't modified any thread priority. I tried searching for where this priorities are assigned, but couldn't find that either.

Please help.

Cheers,

Kaushalya

Parents
  • Hello Kaushalya,

    The log shows you are reading the temperature from the nRF52's TEMP peripheral, not the external sht40 sensor. Maybe you selected the wrong sensor device in your app?

    Regarding the assertion, it appears to be raised for the main thread if I'm the crash log correctly, but I don't see why this would happen when enabling the CONFIG_COAP_CLIENT symbol. Please check the generated configuration file (.config) for your application located in the build directory and check if the CONFIG_MAIN_THREAD_PRIORITY is set to '0' in both cases.

    Cheers,

    Vidar

  • Hi Vidar,

    Many thanks for lookin into this. 

    Thats interesting observation that I am using Temp peripheral. How do we enable Temp peripheral? 

    What I have done in my case is

    1. Enable Sensirion SHT4x node under I2C node in the device tree as follows. 

     

    &pinctrl {
    	i2c0_default: i2c0_default {
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 1, 15)>,
    				<NRF_PSEL(TWIM_SCL, 1, 13)>;
    		};
    	};
    
    	i2c0_sleep: i2c0_sleep {
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 1, 15)>,
    				<NRF_PSEL(TWIM_SCL, 1, 13)>;
    			low-power-enable;
    		};
    	};
    };
    
    &i2c0 {
    	status = "okay";
    	clock-frequency = <I2C_BITRATE_FAST>;
    	sht4x@44 {
    		status = "okay";
    		compatible = "sensirion,sht4x";
    		reg = <0x44>;
    		repeatability = <2>;
    	};
    };

    2. Access it from coap_client.c as follows.

    const struct device *const sht = DEVICE_DT_GET_ANY(sensirion_sht4x);
    struct sensor_value temp, hum;
    
    #if !DT_HAS_COMPAT_STATUS_OKAY(sensirion_sht4x)		// Feature 17
    #error "No sensirion,sgp40 compatible node found in the device tree"
    #endif
    .
    .
    void ADCscan () {
    	if (sensor_sample_fetch(sht)) {
    		LOG_INF("Failed to fetch sample from SHT4X device\n");
    		return;
    	}
    	sensor_channel_get(sht, SENSOR_CHAN_AMBIENT_TEMP, &temp);
    	sensor_channel_get(sht, SENSOR_CHAN_HUMIDITY, &hum);
    
    	LOG_INF("SHT4X: %.2f Temp. [C] ; %0.2f RH [%%]",
    		sensor_value_to_float(&temp),
    		sensor_value_to_float(&hum));
     
        .
        .
    }
    
    int main () {
    	if (!device_is_ready(sht)) {
    		LOG_INF("Device %s is not ready.\n", sht->name);
    		return 0;
    	}
    	ADCscan ();
    	.
    	.
    }

    Is there anything you see I have not done correctly here for getting data from SHT40? I get both temperature and humidity readings in my case and both values seems to change with environmental conditions. Furthermore I can see the I2C signals on bus as well. So seems like the data is originating from the SGT40 sensor.

     CONFIG_MAIN_THREAD_PRIORITY is set to '0' in both cases.

    I checked that in both cases of CONFIG_COAP_CLIENT, the CONFIG_MAIN_THREAD_PRIORITY  is 0, but when CONFIG_COAP_CLIENT is enabled it crashes as before.

    This is my .config file.

    5734..config.zip

  • I can see "CONFIG_TEMP_NRF5_MPSL=y" in the .config file, which indicates use of internal temp sensor. When I do Menuconfig, I can see TEMP_NRF5_MPSL is enabled under Device Drivers, but its readonly. 

  • Sorry, the last code snippet shows that you are correctly fetching data from your sht40 sensor. I just saw references to the  "temp_nrf5_mpsl" driver in the log you posted and assumed you may have selected the SoC's built-in temperature sensor like in the CPU die temperature polling sample. This internal temperature sensor is used by the clock calibration and the 15.4 radio driver and that is why it is enabled in your project.

    Regarding the assertion, the problem appears to be that CONFIG_COAP_CLIENT_THREAD_PRIORITY defaults to CONFIG_NUM_PREEMPT_PRIORITIES instead of CONFIG_NUM_PREEMPT_PRIORITIES - 1.

    https://github.com/zephyrproject-rtos/zephyr/blob/2eb8cfb7f5084d040725dc0f4c61b526fa40b8f0/subsys/net/lib/coap/Kconfig#L114 

    I will report this as a bug internally. The fix for now is to assign an appropriate priority level for the coap thread in your prj.conf file. For example: CONFIG_COAP_CLIENT_THREAD_PRIORITY=0.

Reply Children
  • Hi Vidar, Your reply is much appreciated. Now that is sorted, I have another. I have two sensors on the same I2C bus, the Sensirion SHT40 and SGP40. The device nodes are defined in my overlay as 

    &i2c0 {
        status = "okay";
        clock-frequency = <I2C_BITRATE_FAST>;
        sht4x@44 {
            status = "okay";
            compatible = "sensirion,sht4x";
            reg = <0x44>;
            repeatability = <2>;
        };
        sgp40@59 {
            status = "okay";
            compatible = "sensirion,sgp40";
            reg = <0x59>;
            enable-selftest;
        };
    };
    This is present in my zephyr.dts file as well. 
    Now when I try to enable the driver using 'CONFIG_SGP40=y' in prj.conf, it says "DT_HAS_SENSIRION_SGP40_ENABLED" is missing !! but when I check in the .config file it has 
    "CONFIG_SGP40=y"
    When I try to Kconfig the SGP40, it is disabled due to DT_HAS_SENSIRION_SGP40_ENABLED being false.
    When I debug into the program, the "device_is_ready(sgp)" fails because the dev->state->init_res is not 0 (it is 5)
    How come the SHT4x node gets detected and SGP40 node is not detected from the devicetree ?
    Cheers,
    Kaushalya
  • Strangely enough, when I restarted my computer, the above SGP40 issue disappeared !! Now I can kconfig and see the SGP40 driver enable is active.

    Now I get the following errors when try to fetch data from SGP40.

    [00:00:00.003,173] <inf> ieee802154_nrf5: nRF5 802154 radio initialized
    [00:00:00.003,204] <dbg> temp_nrf5_mpsl: temp_nrf5_mpsl_init:
    
    
    [00:00:00.253,540] <err> SGP40: Failed to read data sample.
    [00:00:00.253,601] <err> SGP40: Selftest failed!
    [00:00:00.260,437] <inf> fs_nvs: 8 Sectors of 4096 bytes
    [00:00:00.260,467] <inf> fs_nvs: alloc wra: 0, e98
    [00:00:00.260,467] <inf> fs_nvs: data wra: 0, 550
    *** Booting nRF Connect SDK v3.5.99-ncs1-1 ***
    [00:00:00.281,524] <dbg> temp_nrf5_mpsl: temp_nrf5_mpsl_sample_fetch: sample: 115
    [00:00:00.281,555] <dbg> temp_nrf5_mpsl: temp_nrf5_mpsl_channel_get: Temperature:28,750000
    [00:00:00.281,677] <err> coap_client: Device sgp40@59 is not ready.
    

    My code snippet is like this.

    .
    .
    static void ADCscan_fn () {
    
    int16_t temp16, hum16;
    
    	// 17. SHT40 functionality
    	if (sensor_sample_fetch(sht)) {
    		LOG_INF("Failed to fetch sample from SHT4X device\n");
    		return;
    	}
    
    	sensor_channel_get(sht, SENSOR_CHAN_AMBIENT_TEMP, &temp);
    	sensor_channel_get(sht, SENSOR_CHAN_HUMIDITY, &hum);
    
    #if CONFIG_APP_USE_HEATER
    	struct sensor_value heater_p;
    	struct sensor_value heater_d;
    
    	heater_p.val1 = CONFIG_APP_HEATER_PULSE_POWER;
    	heater_d.val1 = CONFIG_APP_HEATER_PULSE_DURATION;
    	sensor_attr_set(sht, SENSOR_CHAN_ALL,
    			SENSOR_ATTR_SHT4X_HEATER_POWER, &heater_p);
    	sensor_attr_set(sht, SENSOR_CHAN_ALL,
    			SENSOR_ATTR_SHT4X_HEATER_DURATION, &heater_d);
    #endif
    
    	LOG_INF("SHT4X: %.2f Temp. [C] ; %0.2f RH [%%]", sensor_value_to_float(&temp), sensor_value_to_float(&hum));
    
    	#if CONFIG_APP_USE_HEATER
    	/*
    	 * Conditions in which it makes sense to activate the heater
    	 * are application/environment specific.
    	 *
    	 * The heater should not be used above SHT4X_HEATER_MAX_TEMP (65 °C)
    	 * as stated in the datasheet.
    	 *
    	 * The temperature data will not be updated here for obvious reasons.
    	 **/
    	if (hum.val1 > CONFIG_APP_HEATER_HUMIDITY_THRESH &&
    			temp.val1 < SHT4X_HEATER_MAX_TEMP) {
    		printf("Activating heater.\n");
    
    		if (sht4x_fetch_with_heater(sht)) {
    			printf("Failed to fetch sample from SHT4X device\n");
    			return 0;
    		}
    
    		sensor_channel_get(sht, SENSOR_CHAN_HUMIDITY, &hum);
    	}
    #endif
    
    #if CONFIG_APP_USE_COMPENSATION
    		comp_t.val1 = temp.val1; /* Temp [°C] */
    		comp_rh.val1 = hum.val1; /* RH [%] */
    		sensor_attr_set(sgp,
    				SENSOR_CHAN_GAS_RES,
    				SENSOR_ATTR_SGP40_TEMPERATURE,
    				&comp_t);
    		sensor_attr_set(sgp,
    				SENSOR_CHAN_GAS_RES,
    				SENSOR_ATTR_SGP40_HUMIDITY,
    				&comp_rh);
    #endif
    
    	if (sensor_sample_fetch(sgp)) {
    		LOG_INF("Failed to fetch sample from SGP40 device.\n");
    		return;
    	}
    
    	sensor_channel_get(sgp, SENSOR_CHAN_GAS_RES, &aq);
    	LOG_INF("SGP40: %d Gas [a.u.]\n", aq.val1);
    	// -----------------------
    
        .
        .
    	k_work_schedule (&ADC_scan_work, K_MSEC(30000));	// schedule for next cycle
    }
    
    .
    .
    int main(void)
    {
    	int ret;
    
    	if (!device_is_ready(sht)) {
    		LOG_ERR("Device %s is not ready.\n", sht->name);
    		return 0;
    	}
    	if (!device_is_ready(sgp)) {
    		LOG_ERR("Device %s is not ready.\n", sgp->name);
    		return 0;
    	}
    	k_work_schedule (&ADC_scan_work, K_NO_WAIT);	// just to test Sensiron SHT40/SGP40
        .
        .
    }
    

    1. From the console it seems a SGP40 read cycle and a self test has happened before checking device ready. But device read status check happens first thing in the main (). I tried debugging into it and also fount that device ready status check happened first and then main () returns as a fail of that. 

    2. Why is "device_is_ready(sgp)" fails?

    Cheers,

    Kaushalya

  • Strangely enough, when I restarted my computer, the above SGP40 issue disappeared !! Now I can kconfig and see the SGP40 driver enable is active.

    I am now continuing the rest of the tests.

    Cheers,

    Kaushalya

  • ok now I can see the self test command correctly send to SGP40 using a logic analyzer. But the read of the result seems to fail with return code -5.

    Any idea?

  • -5 translates to -EIO. Since this happens while you're attempting to read from the sensor, I suspect the sensor is responding with a NACK.

    I haven't worked with this sensor before, but I had a look at the datasheet and the driver implementation, and I'm wondering if the delay between writing the test command and reading back the result is sufficient. Section 3.3 of the datasheet says it should be 320 ms, but it is 250 ms in the code: https://github.com/zephyrproject-rtos/zephyr/commit/0d7cb32c58dce7396315c7c6fb7f67749e5ee1b3#diff-0b4f8ce909416f09b98d94dafd9f360d5243bfa41a913d8eba3ce394ca2cb143R21 

    Could you try to increase this delay and see if it helps?

Related