Getting device not ready error when running fdc2x1x sample on XIAO BLE Sense

Hello!

Looking for some guidance on how I should start debugging an issue I'm experiencing trying to get the Zephyr fdc2x1x sample code running on a custom PCB that uses the XIAO BLE Sense (nRF52840). I have a custom PCB with two FDC2214 capacitive sensor ICs with I2C addresses 0x2A and 0x2B. To verify at least the 0x2A IC was working correctly, I created a copy of the fdc2x1x sample and added a build configuration based on the nRF9160DK. I wired ground and the I2C pins from my nRF9160DK up to the corresponding pins on my custom PCB, flashed the sample code onto the board and opened a serial terminal (note the shutdown pin of the 0x2A FDC2214 was pulled low in this setup to guarantee it was enabled). I can immediately see the sensor data print out showing that the nRF9160 is successfully talking with the IC. I then created a new build configuration based on the XIAO BLE Sense board, copied the nRF9160 overlay file, and updated it to match the corresponding I2C bus and pin definitions for shutdown and interrupt (see code below) based on the XIAO BLE Sense schematic and device tree. I then repeated the experiment of building the code, flashing it and opening the COM port serial terminal. Instead of getting sensor data I got the following message:

Electrically the only difference between the two test cases is the XIAO BLE Sense is directly controlling the shutdown pin of the FDC2214 (which I have verified goes low when the board powers on), versus in the nRF9160 case I am forcing it to always be enabled (low). My current best guess as to why this isn't working is 1) Something to do with the timing of the shutdown pin going low and when the driver tries to initialize the IC. 2) An error with my overlay or the XIAO BLE Sense device tree. 3) Something with pin MUXing not being handled correctly on the XIAO BLE Sense. 

My Setup:

OS: Windows 11

Dev Environment: VS Code 1.95.1

Toolkit: nRF Connect SDK for VS Code

SDK: nRF Connect SDK 2.6.1

Programmer: J-Link Edu Mini

Board: Xiao BLE Sense (Schematic) & nRF9160DK

xiao_ble_sense.overlay:

/*
 * Copyright (c) 2020 arithmetics.io
 *
 * SPDX-License-Identifier: Apache-2.0
 */

&i2c1 {
	clock-frequency = <I2C_BITRATE_FAST>;
	fdc2x1x@2A {
		compatible = "ti,fdc2x1x";
		reg = <0x2A>;
		
		sd-gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
		intb-gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;

		autoscan;
		deglitch = <5>;
		fref = <43360>;

		channel_0 {
			rcount = <7499>;
			settlecount = <48>;
			fref-divider = <1>;
			idrive = <10>;
			fin-sel = <2>;
			inductance = < 18 >;
		};

		channel_1 {
			rcount = <7499>;
			settlecount = <48>;
			fref-divider = <1>;
			idrive = <10>;
			fin-sel = <2>;
			inductance = <18>;
		};
	};
};

nrf9160dk_nrf9160.overlay:

/*
 * Copyright (c) 2020 arithmetics.io
 *
 * SPDX-License-Identifier: Apache-2.0
 */

&i2c2 {
	clock-frequency = <I2C_BITRATE_FAST>;
	fdc2x1x@2A {
		compatible = "ti,fdc2x1x";
		reg = <0x2A>;
		sd-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
		intb-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;

		autoscan;
		deglitch = <5>;
		fref = <43360>;

		channel_0 {
			rcount = <7499>;
			settlecount = <48>;
			fref-divider = <1>;
			idrive = <10>;
			fin-sel = <2>;
			inductance = < 18 >;
		};

		channel_1 {
			rcount = <7499>;
			settlecount = <48>;
			fref-divider = <1>;
			idrive = <10>;
			fin-sel = <2>;
			inductance = <18>;
		};
	};
};

Let me know if you have any ideas on what I should try testing first, or if you require any additional information on the setup.

Cheers,

Parker

  • Also, I will add that I have verified with an oscilloscope that SCL and SDA on the XIAO BLE Sense module are toggling when the board boots up, indicating that I have correctly setup up my overlay file to use those pins for talking with the sensor.

  • Hi!

    How about the pinctrl device tree node , did you set the correct SCL and SDA pint for the i2c1 there? Looks like by default this is 0.04(SDA) and 0.05 (SCL), is that the pins you are using?

  • Here is the pinctrl dtsi:

    /*
     * Copyright (c) 2022 Marcin Niestroj
     * SPDX-License-Identifier: Apache-2.0
     */
    
    &pinctrl {
    	uart0_default: uart0_default {
    		group1 {
    			psels = <NRF_PSEL(UART_TX, 1, 11)>;
    		};
    		group2 {
    			psels = <NRF_PSEL(UART_RX, 1, 12)>;
    			bias-pull-up;
    		};
    	};
    
    	uart0_sleep: uart0_sleep {
    		group1 {
    			psels = <NRF_PSEL(UART_TX, 1, 11)>,
    				<NRF_PSEL(UART_RX, 1, 12)>;
    			low-power-enable;
    		};
    	};
    
    	i2c0_default: i2c0_default {
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 0, 7)>,
    				<NRF_PSEL(TWIM_SCL, 0, 27)>;
    		};
    	};
    
    	i2c0_sleep: i2c0_sleep {
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 0, 7)>,
    				<NRF_PSEL(TWIM_SCL, 0, 27)>;
    			low-power-enable;
    		};
    	};
    
    	i2c1_default: i2c1_default {
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 0, 4)>,
    				<NRF_PSEL(TWIM_SCL, 0, 5)>;
    		};
    	};
    
    	i2c1_sleep: i2c1_sleep {
    		group1 {
    			psels = <NRF_PSEL(TWIM_SDA, 0, 4)>,
    				<NRF_PSEL(TWIM_SCL, 0, 5)>;
    			low-power-enable;
    		};
    	};
    
    	pwm0_default: pwm0_default {
    		group1 {
    			psels = <NRF_PSEL(PWM_OUT0, 0, 17)>;
    			nordic,invert;
    		};
    	};
    
    	pwm0_sleep: pwm0_sleep {
    		group1 {
    			psels = <NRF_PSEL(PWM_OUT0, 0, 17)>;
    			low-power-enable;
    		};
    	};
    
    	spi2_default: spi2_default {
    		group1 {
    			psels = <NRF_PSEL(SPIM_SCK, 1, 13)>,
    				<NRF_PSEL(SPIM_MOSI, 1, 15)>,
    				<NRF_PSEL(SPIM_MISO, 1, 14)>;
    		};
    	};
    
    	spi2_sleep: spi2_sleep {
    		group1 {
    			psels = <NRF_PSEL(SPIM_SCK, 1, 13)>,
    				<NRF_PSEL(SPIM_MOSI, 1, 15)>,
    				<NRF_PSEL(SPIM_MISO, 1, 14)>;
    			low-power-enable;
    		};
    	};
    
    	spi3_default: spi3_default {
    		group1 {
    			psels = <NRF_PSEL(SPIM_SCK, 0, 21)>,
    				<NRF_PSEL(SPIM_MOSI, 0, 20)>,
    				<NRF_PSEL(SPIM_MISO, 0, 24)>;
    		};
    	};
    
    	spi3_sleep: spi3_sleep {
    		group1 {
    			psels = <NRF_PSEL(SPIM_SCK, 0, 21)>,
    				<NRF_PSEL(SPIM_MOSI, 0, 20)>,
    				<NRF_PSEL(SPIM_MISO, 0, 24)>;
    			low-power-enable;
    		};
    	};
    
    	qspi_default: qspi_default {
    		group1 {
    			psels = <NRF_PSEL(QSPI_SCK, 0, 21)>,
    				<NRF_PSEL(QSPI_IO0, 0, 20)>,
    				<NRF_PSEL(QSPI_IO1, 0, 24)>,
    				<NRF_PSEL(QSPI_IO2, 0, 22)>,
    				<NRF_PSEL(QSPI_IO3, 0, 23)>,
    				<NRF_PSEL(QSPI_CSN, 0, 25)>;
    		};
    	};
    
    	qspi_sleep: qspi_sleep {
    		group1 {
    			psels = <NRF_PSEL(QSPI_SCK, 0, 21)>,
    				<NRF_PSEL(QSPI_IO0, 0, 20)>,
    				<NRF_PSEL(QSPI_IO1, 0, 24)>,
    				<NRF_PSEL(QSPI_IO2, 0, 22)>,
    				<NRF_PSEL(QSPI_IO3, 0, 23)>,
    				<NRF_PSEL(QSPI_CSN, 0, 25)>;
    			low-power-enable;
    		};
    	};
    };
    

    The pins appear to be set correctly for the i2c1 node and I have triple checked that my schematic and layout for the board correctly connect SDA/SCL to the FDC2214 I2C pins. Furthermore, I can see bus activity during startup if I measure SDA and SCL with an oscilloscope.

    If I wire the nRF9160 I2C pins (0.31 and 0.30) to the board I can talk with the FDC2214 no problem. So it seems like the hardware is good, abut something with the XIAO BLE Sense build configuration is not correctly working.

    One test I will try today is to pull the SD pin low with a jumper to enable the chip by default at power on. Maybe the chip isn't getting enabled before initialization over I2C takes place?

  • Hi!

    I suggest placing some breakpoints in the different return statements in fdc2x1x_init() and see if fdc2x1x_init will return something else than 0 somewhere in the function.

    https://github.com/nrfconnect/sdk-zephyr/blob/main/drivers/sensor/ti/fdc2x1x/fdc2x1x.c

  • Got it working! Turns out there is not a long enough delay between when the shutdown pin (SD) goes low to enable the chip and when the driver tries to initialize the IC.

    When I stepped through the code with the debugger everything magically worked the first try, since I was adding plenty of time between SD going low, and the first I2C communications. So I then added a delay of 100ms after the SD pin goes low and now the sensor initializes correctly each time.

Related