reading data from a sensor that has no driver using TWI

Hello, I am trying to read data from the sensor using I2C, I have the nrf9160 on an Icarus board https://www.actinius.com/icarus.

I tried following this guide: https://devzone.nordicsemi.com/guides/nrf-connect-sdk-guides/b/peripherals/posts/twi-ic2-implementation-with-nrfx-twis-driver

but I ended up with a lot of errors when building 

  

main.c

#include <device.h>
#include <devicetree.h>
#include <drivers/gpio.h>
#include <drivers/i2c.h>
#include <sys/printk.h>
#include <zephyr.h>

/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS 1000

/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)

const struct device *led_dev;

#if DT_NODE_HAS_STATUS(LED0_NODE, okay)
#define LED0 DT_GPIO_LABEL(LED0_NODE, gpios)
#define PIN DT_GPIO_PIN(LED0_NODE, gpios)
#define FLAGS DT_GPIO_FLAGS(LED0_NODE, gpios)
#else
/* A build error here means your board isn't set up to blink an LED. */
#error "Unsupported board: led0 devicetree alias is not defined"
#define LED0 ""
#define PIN 0
#define FLAGS 0
#endif

////////////////////////////////////////////////////////////

// TWI Test Configuration

////////////////////////////////////////////////////////////

#define ECHO_WRITES false
#define MSG_EXCHANGE_CNT 5
#define INFINITE_MSG_EXCHANGE false
#define TWI_LOOPBACK false
// In non-loopback mode, the tx message is unchanged.
// In loopback mode the rx buffer acts as both the tx and rx buffer. The rx buffer is updated with each read.

////////////////////////////////////////////////////////////

// Adding TWI Functionality

////////////////////////////////////////////////////////////

#define TWI_BUFFER_SIZE 14
/* static unsigned char i2c_tx_buffer[TWI_BUFFER_SIZE] = {'M', 'S', 'G', ' ', 'F', 'R', 'O', 'M', ' ', 'T', 'W', 'I', 'M', '\0'};
 */static unsigned char i2c_rx_buffer[TWI_BUFFER_SIZE] = "Begin Loopback";

// TWI Master Setup

#define MY_TWIM DT_NODELABEL(i2c2)
const struct device *nrfx_twis_dev1;

static void twim_init(void)
{
	int config_result = false;

	nrfx_twis_dev1 = device_get_binding(DT_LABEL(MY_TWIM));

	if (nrfx_twis_dev1 == NULL)
	{
		printk("\n\nI2C Slave: Device driver not found.\n");
	}
	else
	{
		printk("\nI2C device 1: %s\n", DT_PROP(DT_NODELABEL(twis_device1), label));

		config_result = i2c_configure(nrfx_twis_dev1, I2C_SPEED_SET(I2C_SPEED_FAST) | I2C_MODE_MASTER);

		if (!config_result)
		{
			printk("I2C Master: Slave ADDR: 0x%x SCL: %d, SDA: %d, CLK(Hz): %u\n\n",
				   DT_REG_ADDR(DT_NODELABEL(twis_device1)),
				   DT_PROP(MY_TWIM, scl_pin),
				   DT_PROP(MY_TWIM, sda_pin),
				   DT_PROP(MY_TWIM, clock_frequency));
		}
		else
			printk("\n\nI2C: Configuration error code: %d\n", config_result);
	}
}

// TWI Master Write

/* void twi_write_tst(void)
{
	int rtn_code = 0;
	uint8_t incr = 0;
	bool loopback = TWI_LOOPBACK;

	if (nrfx_twis_dev1 != NULL)
	{
		// printk("\nTWIM TX/writing.");
		if (!loopback)
		{ // write repeated default message
			rtn_code = i2c_write(nrfx_twis_dev1, i2c_tx_buffer, sizeof(i2c_tx_buffer), DT_REG_ADDR(DT_NODELABEL(twis_device1)));
		}
		else
		{ // use read buffer as write buffer
			rtn_code = i2c_write(nrfx_twis_dev1, i2c_rx_buffer, sizeof(i2c_rx_buffer), DT_REG_ADDR(DT_NODELABEL(twis_device1)));
		}

		if (ECHO_WRITES && (rtn_code == 0))
		{
			printk("\nTWIM TX:");
			while (incr < TWI_BUFFER_SIZE)
				printk("%c", i2c_rx_buffer[incr++]);
			printk("\n");
		} // rtn_code == 0

		if (rtn_code)
		{
			printk("twi return code %u\n\n", rtn_code);
		}
	}
	else // twis_dev1 == NULL
		printk("TWIS device is not initialized correctly.\n");
} */

void twi_read_tst(void)
{
	int rtn_code = 0;
	uint8_t incr = 0;

	if (nrfx_twis_dev1 != NULL)
	{
		// printk("\nTWIM RX/reading -->");
		rtn_code = i2c_read(nrfx_twis_dev1, i2c_rx_buffer, sizeof(i2c_rx_buffer),DT_REG_ADDR( DT_PATH(i2c2,cd30_61) ) );

		if (rtn_code == 0)
		{
			printk("TWIM RX:");
			while (incr < TWI_BUFFER_SIZE)
			{
				printk("%c", i2c_rx_buffer[incr++]);
			};
			printk("\n");
		}

		if (rtn_code)
			printk("twi return code %u\n\n", rtn_code);
	}
	else // twim_dev1 == NULL
		printk("TWI is not initialized correctly.\n");
}

void main(void)
{
	uint16_t twi_test_cnt = MSG_EXCHANGE_CNT;
	bool led_is_on = true;
	uint32_t ret;

	led_dev = device_get_binding(LED0);
	if (led_dev == NULL)
	{
		return;
	}

	ret = gpio_pin_configure(led_dev, PIN, GPIO_OUTPUT_ACTIVE | FLAGS);
	if (ret < 0)
	{
		return;
	}

	twim_init();

	while (1)
	{

		gpio_pin_set(led_dev, PIN, (int)led_is_on);
		led_is_on = !led_is_on;

		if ((twi_test_cnt) || (INFINITE_MSG_EXCHANGE))
		{
			
			twi_read_tst();

			if (twi_test_cnt)
			{
				twi_test_cnt--;
			}

			if ((!twi_test_cnt) && (!INFINITE_MSG_EXCHANGE))
			{
				printk("\n\nTo rerun this test, reset the master.\n\n");
			}
		}

		k_msleep(SLEEP_TIME_MS);
	}
}

actinuos_icarus_ns.overlay

&i2c2 {

	compatible = "nordic,nrf-twim";

	status = "okay";

	clock-frequency = <I2C_BITRATE_STANDARD>;
	/* other property settings can go here */

	
	twis_device1: scd30@61 {				/* e */
		// device compatible				/* f */
		label = "scd30";	/* g */
       	reg = <0x61>;						/* h */
   	};
};

log:

C:\Users\alnag\Desktop\Work\blinky-TWIM>west build -b actinius_icarus_ns
[0/1] Re-running CMake...
Including boilerplate (Zephyr base (cached)): C:/Users/alnag/ncs/v1.9.1/zephyr/cmake/app/boilerplate.cmake
-- Application: C:/Users/alnag/Desktop/Work/blinky-TWIM
-- Zephyr version: 2.7.99 (C:/Users/alnag/ncs/v1.9.1/zephyr), build: v2.7.99-ncs1-1
-- Found west (found suitable version "0.12.0", minimum required is "0.7.1")
-- Board: actinius_icarus_ns
-- Cache files will be written to: C:/Users/alnag/ncs/v1.9.1/zephyr/.cache
-- Found dtc: C:/Users/alnag/ncs/v1.9.1/toolchain/opt/bin/dtc.exe (found suitable version "1.4.7", minimum required is "1.4.6")
-- Found toolchain: gnuarmemb (c:/Users/alnag/ncs/v1.9.1/toolchain/opt)
-- Found BOARD.dts: C:/Users/alnag/ncs/v1.9.1/zephyr/boards/arm/actinius_icarus/actinius_icarus_ns.dts
-- Found devicetree overlay: c:/Users/alnag/Desktop/Work/blinky-TWIM/actinius_icarus_ns.overlay
-- Generated zephyr.dts: C:/Users/alnag/Desktop/Work/blinky-TWIM/build/zephyr/zephyr.dts
-- Generated devicetree_unfixed.h: C:/Users/alnag/Desktop/Work/blinky-TWIM/build/zephyr/include/generated/devicetree_unfixed.h
-- Generated device_extern.h: C:/Users/alnag/Desktop/Work/blinky-TWIM/build/zephyr/include/generated/device_extern.h
-- Including generated dts.cmake file: C:/Users/alnag/Desktop/Work/blinky-TWIM/build/zephyr/dts.cmake
Parsing C:/Users/alnag/ncs/v1.9.1/zephyr/Kconfig
Loaded configuration 'C:/Users/alnag/Desktop/Work/blinky-TWIM/build/zephyr/.config'
No change to configuration in 'C:/Users/alnag/Desktop/Work/blinky-TWIM/build/zephyr/.config'
No change to Kconfig header in 'C:/Users/alnag/Desktop/Work/blinky-TWIM/build/zephyr/include/generated/autoconf.h'
C:\Users\alnag\ncs\v1.9.1\toolchain\opt\bin\arm-none-eabi-gdb.exe: warning: Couldn't determine a path for the index cache directory.
Changed board to secure actinius_icarus (NOT NS)

=== child image spm -  begin ===
loading initial cache file C:/Users/alnag/Desktop/Work/blinky-TWIM/build/spm/child_image_preload.cmake
Including boilerplate (Zephyr base (cached)): C:/Users/alnag/ncs/v1.9.1/zephyr/cmake/app/boilerplate.cmake
-- Application: C:/Users/alnag/ncs/v1.9.1/nrf/samples/spm
-- Zephyr version: 2.7.99 (C:/Users/alnag/ncs/v1.9.1/zephyr), build: v2.7.99-ncs1-1
-- Found west (found suitable version "0.12.0", minimum required is "0.7.1")
-- Board: actinius_icarus
-- Cache files will be written to: C:/Users/alnag/ncs/v1.9.1/zephyr/.cache
-- Found dtc: C:/Users/alnag/ncs/v1.9.1/toolchain/opt/bin/dtc.exe (found suitable version "1.4.7", minimum required is "1.4.6")
-- Found toolchain: gnuarmemb (c:/Users/alnag/ncs/v1.9.1/toolchain/opt)
-- Found BOARD.dts: C:/Users/alnag/ncs/v1.9.1/zephyr/boards/arm/actinius_icarus/actinius_icarus.dts
-- Generated zephyr.dts: C:/Users/alnag/Desktop/Work/blinky-TWIM/build/spm/zephyr/zephyr.dts
-- Generated devicetree_unfixed.h: C:/Users/alnag/Desktop/Work/blinky-TWIM/build/spm/zephyr/include/generated/devicetree_unfixed.h
-- Generated device_extern.h: C:/Users/alnag/Desktop/Work/blinky-TWIM/build/spm/zephyr/include/generated/device_extern.h
-- Including generated dts.cmake file: C:/Users/alnag/Desktop/Work/blinky-TWIM/build/spm/zephyr/dts.cmake
Parsing C:/Users/alnag/ncs/v1.9.1/zephyr/Kconfig
Loaded configuration 'C:/Users/alnag/Desktop/Work/blinky-TWIM/build/spm/zephyr/.config'
No change to configuration in 'C:/Users/alnag/Desktop/Work/blinky-TWIM/build/spm/zephyr/.config'
No change to Kconfig header in 'C:/Users/alnag/Desktop/Work/blinky-TWIM/build/spm/zephyr/include/generated/autoconf.h'
C:\Users\alnag\ncs\v1.9.1\toolchain\opt\bin\arm-none-eabi-gdb.exe: warning: Couldn't determine a path for the index cache directory.
CMake Warning at C:/Users/alnag/ncs/v1.9.1/zephyr/CMakeLists.txt:1687 (message):
  __ASSERT() statements are globally ENABLED


-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/alnag/Desktop/Work/blinky-TWIM/build/spm
=== child image spm -  end ===

Dropping partition 'nrf_modem_lib_trace' since its size is 0.
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/alnag/Desktop/Work/blinky-TWIM/build
[0/136] Performing build step for 'spm_subimage'
[213/221] Linking C executable zephyr\zephyr_pre0.elf

[216/221] Linking C executable zephyr\zephyr_pre1.elf

[221/221] Linking C executable zephyr\zephyr.elf
Memory region         Used Size  Region Size  %age Used
           FLASH:         64 KB        64 KB    100.00%
            SRAM:       12008 B        32 KB     36.65%
        IDT_LIST:          0 GB         2 KB      0.00%
[44/134] Building C object CMakeFiles/app.dir/src/main.c.obj
FAILED: CMakeFiles/app.dir/src/main.c.obj
C:\Users\alnag\ncs\v1.9.1\toolchain\opt\bin\arm-none-eabi-gcc.exe -DBUILD_VERSION=v2.7.99-ncs1-1 -DEXT_API_MAGIC=0x281ee6de,0xb845acea,23298 -DFIRMWARE_INFO_MAGIC=0x281ee6de,0x8fcebb4c,23298 -DKERNEL -DNRF9160_XXAA -DNRF_SKIP_FICR_NS_COPY_TO_RAM -DNRF_TRUSTZONE_NONSECURE -DUSE_PARTITION_MANAGER=1 -D_FORTIFY_SOURCE=2 -D__PROGRAM_START -D__ZEPHYR__=1 -IC:/Users/alnag/ncs/v1.9.1/zephyr/include -Izephyr/include/generated -IC:/Users/alnag/ncs/v1.9.1/zephyr/soc/arm/nordic_nrf/nrf91 -IC:/Users/alnag/ncs/v1.9.1/zephyr/soc/arm/nordic_nrf/common/. -IC:/Users/alnag/ncs/v1.9.1/nrf/include -IC:/Users/alnag/ncs/v1.9.1/modules/hal/cmsis/CMSIS/Core/Include -IC:/Users/alnag/ncs/v1.9.1/modules/hal/nordic/nrfx -IC:/Users/alnag/ncs/v1.9.1/modules/hal/nordic/nrfx/drivers/include -IC:/Users/alnag/ncs/v1.9.1/modules/hal/nordic/nrfx/mdk -IC:/Users/alnag/ncs/v1.9.1/zephyr/modules/hal_nordic/nrfx/. -IC:/Users/alnag/ncs/v1.9.1/nrfxlib/nrf_modem/include -isystem C:/Users/alnag/ncs/v1.9.1/zephyr/lib/libc/minimal/include -isystem c:/users/alnag/ncs/v1.9.1/toolchain/opt/bin/../lib/gcc/arm-none-eabi/9.2.1/include -isystem c:/users/alnag/ncs/v1.9.1/toolchain/opt/bin/../lib/gcc/arm-none-eabi/9.2.1/include-fixed -Os -imacros C:/Users/alnag/Desktop/Work/blinky-TWIM/build/zephyr/include/generated/autoconf.h -ffreestanding -fno-common -g -gdwarf-4 -fdiagnostics-color=always -mcpu=cortex-m33 -mthumb -mabi=aapcs -mfp16-format=ieee -imacros C:/Users/alnag/ncs/v1.9.1/zephyr/include/toolchain/zephyr_stdint.h -Wall -Wformat -Wformat-security -Wno-format-zero-length -Wno-main -Wno-pointer-sign -Wpointer-arith -Wexpansion-to-defined -Wno-unused-but-set-variable -Werror=implicit-int -fno-asynchronous-unwind-tables -fno-pie -fno-pic -fno-strict-overflow -fno-reorder-functions -fno-defer-pop -fmacro-prefix-map=C:/Users/alnag/Desktop/Work/blinky-TWIM=CMAKE_SOURCE_DIR -fmacro-prefix-map=C:/Users/alnag/ncs/v1.9.1/zephyr=ZEPHYR_BASE -fmacro-prefix-map=C:/Users/alnag/ncs/v1.9.1=WEST_TOPDIR -ffunction-sections -fdata-sections -std=c99 -nostdinc -MD -MT CMakeFiles/app.dir/src/main.c.obj -MF CMakeFiles\app.dir\src\main.c.obj.d -o CMakeFiles/app.dir/src/main.c.obj -c ../src/main.c
In file included from C:/Users/alnag/ncs/v1.9.1/zephyr/include/arch/arm/aarch32/arch.h:20,
                 from C:/Users/alnag/ncs/v1.9.1/zephyr/include/arch/cpu.h:19,
                 from C:/Users/alnag/ncs/v1.9.1/zephyr/include/kernel_includes.h:33,
                 from C:/Users/alnag/ncs/v1.9.1/zephyr/include/kernel.h:17,
                 from C:/Users/alnag/ncs/v1.9.1/zephyr/include/init.h:11,
                 from C:/Users/alnag/ncs/v1.9.1/zephyr/include/device.h:29,
                 from ../src/main.c:7:
../src/main.c: In function 'twi_read_tst':
C:/Users/alnag/ncs/v1.9.1/zephyr/include/devicetree.h:81:17: error: 'DT_N_S_i2c2_S_cd30_61_REG_IDX_0_VAL_ADDRESS' undeclared (first use in this function); did you mean 'DT_N_S_cpus_S_cpu_0_REG_IDX_0_VAL_ADDRESS'?
   81 | #define DT_ROOT DT_N
      |                 ^~~~
C:/Users/alnag/ncs/v1.9.1/zephyr/include/devicetree.h:3022:24: note: in definition of macro 'DT_CAT'
 3022 | #define DT_CAT(a1, a2) a1 ## a2
      |                        ^~
C:/Users/alnag/ncs/v1.9.1/zephyr/include/devicetree.h:1717:30: note: in expansion of macro 'DT_REG_ADDR_BY_IDX'
 1717 | #define DT_REG_ADDR(node_id) DT_REG_ADDR_BY_IDX(node_id, 0)
      |                              ^~~~~~~~~~~~~~~~~~
../src/main.c:136:76: note: in expansion of macro 'DT_REG_ADDR'
  136 |   rtn_code = i2c_read(nrfx_twis_dev1, i2c_rx_buffer, sizeof(i2c_rx_buffer),DT_REG_ADDR( DT_PATH(i2c2,cd30_61) ) );
      |                                                                            ^~~~~~~~~~~
C:/Users/alnag/ncs/v1.9.1/zephyr/include/sys/util_internal.h:98:26: note: in expansion of macro 'UTIL_PRIMITIVE_CAT'
   98 | #define UTIL_CAT(a, ...) UTIL_PRIMITIVE_CAT(a, __VA_ARGS__)
      |                          ^~~~~~~~~~~~~~~~~~
C:/Users/alnag/ncs/v1.9.1/zephyr/include/devicetree.h:3004:2: note: in expansion of macro 'UTIL_CAT'
 3004 |  UTIL_CAT(DT_ROOT, MACRO_MAP_CAT(DT_S_PREFIX, __VA_ARGS__))
      |  ^~~~~~~~
C:/Users/alnag/ncs/v1.9.1/zephyr/include/devicetree.h:3004:11: note: in expansion of macro 'DT_ROOT'
 3004 |  UTIL_CAT(DT_ROOT, MACRO_MAP_CAT(DT_S_PREFIX, __VA_ARGS__))
      |           ^~~~~~~
C:/Users/alnag/ncs/v1.9.1/zephyr/include/devicetree.h:129:22: note: in expansion of macro 'DT_PATH_INTERNAL'
  129 | #define DT_PATH(...) DT_PATH_INTERNAL(__VA_ARGS__)
      |                      ^~~~~~~~~~~~~~~~
../src/main.c:136:89: note: in expansion of macro 'DT_PATH'
  136 |   rtn_code = i2c_read(nrfx_twis_dev1, i2c_rx_buffer, sizeof(i2c_rx_buffer),DT_REG_ADDR( DT_PATH(i2c2,cd30_61) ) );
      |                                                                                         ^~~~~~~
C:/Users/alnag/ncs/v1.9.1/zephyr/include/devicetree.h:81:17: note: each undeclared identifier is reported only once for each function it appears in
   81 | #define DT_ROOT DT_N
      |                 ^~~~
C:/Users/alnag/ncs/v1.9.1/zephyr/include/devicetree.h:3022:24: note: in definition of macro 'DT_CAT'
 3022 | #define DT_CAT(a1, a2) a1 ## a2
      |                        ^~
C:/Users/alnag/ncs/v1.9.1/zephyr/include/devicetree.h:1717:30: note: in expansion of macro 'DT_REG_ADDR_BY_IDX'
 1717 | #define DT_REG_ADDR(node_id) DT_REG_ADDR_BY_IDX(node_id, 0)
      |                              ^~~~~~~~~~~~~~~~~~
../src/main.c:136:76: note: in expansion of macro 'DT_REG_ADDR'
  136 |   rtn_code = i2c_read(nrfx_twis_dev1, i2c_rx_buffer, sizeof(i2c_rx_buffer),DT_REG_ADDR( DT_PATH(i2c2,cd30_61) ) );
      |                                                                            ^~~~~~~~~~~
C:/Users/alnag/ncs/v1.9.1/zephyr/include/sys/util_internal.h:98:26: note: in expansion of macro 'UTIL_PRIMITIVE_CAT'
   98 | #define UTIL_CAT(a, ...) UTIL_PRIMITIVE_CAT(a, __VA_ARGS__)
      |                          ^~~~~~~~~~~~~~~~~~
C:/Users/alnag/ncs/v1.9.1/zephyr/include/devicetree.h:3004:2: note: in expansion of macro 'UTIL_CAT'
 3004 |  UTIL_CAT(DT_ROOT, MACRO_MAP_CAT(DT_S_PREFIX, __VA_ARGS__))
      |  ^~~~~~~~
C:/Users/alnag/ncs/v1.9.1/zephyr/include/devicetree.h:3004:11: note: in expansion of macro 'DT_ROOT'
 3004 |  UTIL_CAT(DT_ROOT, MACRO_MAP_CAT(DT_S_PREFIX, __VA_ARGS__))
      |           ^~~~~~~
C:/Users/alnag/ncs/v1.9.1/zephyr/include/devicetree.h:129:22: note: in expansion of macro 'DT_PATH_INTERNAL'
  129 | #define DT_PATH(...) DT_PATH_INTERNAL(__VA_ARGS__)
      |                      ^~~~~~~~~~~~~~~~
../src/main.c:136:89: note: in expansion of macro 'DT_PATH'
  136 |   rtn_code = i2c_read(nrfx_twis_dev1, i2c_rx_buffer, sizeof(i2c_rx_buffer),DT_REG_ADDR( DT_PATH(i2c2,cd30_61) ) );
      |                                                                                         ^~~~~~~
[53/134] Building C object zephyr/kernel/CMakeFiles/kernel.dir/sched.c.obj
ninja: build stopped: subcommand failed.
FATAL ERROR: command exited with status 1: 'C:\Users\alnag\ncs\v1.9.1\toolchain\opt\bin\cmake.EXE' --build 'C:\Users\alnag\Desktop\Work\blinky-TWIM\build'

here is the project if someone to try bulding for themself.  

7026.blinky-TWIM.zip

Parents
  • Hi, thank you for your reply I was able to find the device using the scanner and I was also able to fix the previous code and it flashed successfully, the only problem now is that the readings from the sensor are printed in weird characters  blinky-TWIM-updated.zip

  • Hi 

    Good to hear you got the sensor working Slight smile

    Most likely the data from the sensor will not make sense in ASCII presentation. 

    You could try to print the data as hex or int values instead. To print as hex with at minimum two digits presentation, you can do it like this:

    int hex_val = 0x12;
    printk("Hex value: 0x%.2x", hex_val);

    Best regards
    Torbjørn

  • Hi Saed

    Can you show me the code you used to produce this printout?

    I don't see "0x" printed anywhere, so I must assume you didn't copy my code exactly.

    Best regards
    Torbjørn

  • hi, 

    I have attached a new code where I write commands to the sensor to start the measurement and get results, unfortunately, all that I get is 0xff 0xff 0xac

    /*
     * Copyright (c) 2016 Intel Corporation
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <device.h>
    #include <devicetree.h>
    #include <drivers/gpio.h>
    #include <drivers/i2c.h>
    #include <sys/printk.h>
    #include <zephyr.h>
    
    
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS 10000
    
    /* The devicetree node identifier for the "led0" alias. */
    #define LED0_NODE DT_ALIAS(led0)
    
    const struct device *led_dev;
    
    #if DT_NODE_HAS_STATUS(LED0_NODE, okay)
    #define LED0 DT_GPIO_LABEL(LED0_NODE, gpios)
    #define PIN DT_GPIO_PIN(LED0_NODE, gpios)
    #define FLAGS DT_GPIO_FLAGS(LED0_NODE, gpios)
    #else
    /* A build error here means your board isn't set up to blink an LED. */
    #error "Unsupported board: led0 devicetree alias is not defined"
    #define LED0 ""
    #define PIN 0
    #define FLAGS 0
    #endif
    
    ////////////////////////////////////////////////////////////
    
    // TWI Test Configuration
    
    ////////////////////////////////////////////////////////////
    
    #define ECHO_WRITES true
    #define MSG_EXCHANGE_CNT 5
    #define INFINITE_MSG_EXCHANGE false
    #define TWI_LOOPBACK false
    // In non-loopback mode, the tx message is unchanged.
    // In loopback mode the rx buffer acts as both the tx and rx buffer. The rx buffer is updated with each read.
    
    ////////////////////////////////////////////////////////////
    
    // Adding TWI Functionality
    
    ////////////////////////////////////////////////////////////
    
    #define TWI_BUFFER_SIZE 18
     
    static const uint8_t readCommand[] = {0x03,0x00} ;
    static const uint8_t dataReady[] = {0x02,0x02} ;
    static const uint8_t triggerContinuousMeasurement[2] = {0x00,0x10} ;
    static const uint8_t deactivateASC[] = {0x53, 0x06, 0x00, 0x00 } ;
    static const uint8_t activateASC[2] = {0x53, 0x06 } ;
    static const uint8_t getASC[] = {0x53, 0x06 } ;
    static const uint8_t softRest[] = {0xD3,0x04} ;															
    static const uint8_t framewareVersion[] = {0xD1,0x00} ;		 		
    
    //5sec
    
    static uint8_t i2c_rx_buffer [TWI_BUFFER_SIZE];
    
    // TWI Master Setup
    
    #define MY_TWIM DT_NODELABEL(i2c2)
    const struct device *nrfx_twis_dev1;
    
    
    static void twim_init(void)
    {
    	int config_result = false;
     
    
    	nrfx_twis_dev1 = device_get_binding(DT_LABEL(MY_TWIM));
    	printk("\n\nI2C Slave: Device driver not found.\n");
    	if (nrfx_twis_dev1 == NULL)
    	{
    		printk("\n\nI2C Slave: Device driver not found.\n");
    	}
    	else
    	{
    		printk("\nI2C device 1: %s\n", DT_PROP(DT_NODELABEL(twis_device1), label));
    
    		config_result = i2c_configure(nrfx_twis_dev1, I2C_SPEED_SET(I2C_SPEED_FAST) | I2C_MODE_MASTER);
    
    		if (!config_result)
    		{
    			printk("I2C Master: Slave ADDR: 0x%x SCL: %d, SDA: %d, CLK(Hz): %u\n\n",
    				   DT_REG_ADDR(DT_NODELABEL(twis_device1)),
    				   DT_PROP(MY_TWIM, scl_pin),
    				   DT_PROP(MY_TWIM, sda_pin),
    				   DT_PROP(MY_TWIM, clock_frequency));
    		}
    		else
    			printk("\n\nI2C: Configuration error code: %d\n", config_result);
    			
    	}
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // TWI Master Write
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     
    void twi_write_tst()
    {
    	int rtn_code = 0;
    	uint8_t incr = 0;
         
    
    	if (nrfx_twis_dev1 != NULL)
    	{
    		 printk("\nTWIM TX/writing.");
    	 
    		  // write repeated default message
    			rtn_code = i2c_write(nrfx_twis_dev1, activateASC ,2, DT_REG_ADDR(DT_NODELABEL(twis_device1)));
    		 	printk("\nTWIM TX/writing ----->        rtn_code: %d",rtn_code);
    	 
    		if (ECHO_WRITES && (rtn_code == 0))
    		{/* 
    			printk("\nTWIM TX:");
    			while (incr < 2)
    				printk("| 0x%.2x |", buffur[incr++]);
    			printk("\n"); */
    		} // rtn_code == 0
    
    		if (rtn_code)
    		{
    			printk("twi return code %u\n\n", rtn_code);
    		}
    	}
    	else // twis_dev1 == NULL
    		printk("TWIS device is not initialized correctly.\n");
    } 
    
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Checking if data is ready or not 
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    uint8_t getReadyStatus(void)
    {	
    
    	// printk("\n GETTING READY STATUS!! ");
    	int rtn_code = 0;
    	uint8_t incr = 0;
    
    
    	if (nrfx_twis_dev1 != NULL)
    	{
    		// printk("\nTWIM TX/writing.");
    	 
    		  // write repeated default message
    			rtn_code = i2c_write(nrfx_twis_dev1, dataReady , 2 , DT_REG_ADDR(DT_NODELABEL(twis_device1)));
    		 	 // printk("\nTWIM TX/writing  /dataReady/ -----> rtn_code: %d",rtn_code);
    	 
    		/* if (ECHO_WRITES && (rtn_code == 0))
    		{
    			printk("\nTWIM TX:");
    			while (incr < 2)
    				printk("|  %d  |", dataReady[incr++]);
    			printk("\n");
    		} // rtn_code == 0
     */
    		/* if (rtn_code)
    		{
    			printk("twi return code %u\n\n", rtn_code);
    		} */
    	}
    	else // twis_dev1 == NULL
    	//	printk("TWIS device is not initialized correctly.\n");
    
        rtn_code = 0;
    	incr = 0;
    	k_msleep(5);	
    	if (nrfx_twis_dev1 != NULL)
    	{
    		
    	//	printk("\nTWIM RX/reading -->");
    		rtn_code = i2c_read(nrfx_twis_dev1, i2c_rx_buffer, sizeof(i2c_rx_buffer), DT_REG_ADDR( DT_NODELABEL(twis_device1) ) );
    		
    
    		/* print the result */
    
    		if (rtn_code == 0)
    		{
    	/* 		printk("TWIM RX:");
    			while (incr < TWI_BUFFER_SIZE)
    			{
    				printk(" | %d  | ", i2c_rx_buffer[incr++]);
    			};
    			printk("\n");
    			 */
    			 
    		}
    
    		if (rtn_code)  printk("twi return code %u\n\n", rtn_code);
    	}
    	else // twim_dev1 == NULL
    		printk("TWI is not initialized correctly.\n");
    
    return i2c_rx_buffer[1] ;
    
    } 
    
    void twi_read_tst(void)
    {
    	int rtn_code = 0;
    	uint8_t incr = 0;
    
    	if (nrfx_twis_dev1 != NULL)
    	{
    		
    		printk("\nTWIM RX/reading -->");
    		rtn_code = i2c_read(nrfx_twis_dev1, i2c_rx_buffer, sizeof(i2c_rx_buffer), DT_REG_ADDR( DT_NODELABEL(twis_device1) ) );
    		
    
    		/* print the result */
    
    		if (rtn_code == 0)
    		{
    			printk("TWIM RX:");
    			while (incr < TWI_BUFFER_SIZE)
    			{
    				printk(" | 0x%.2x  | ", i2c_rx_buffer[incr++]);
    			};
    			printk("\n");
    		}
    
    		if (rtn_code)  printk("twi return code %u\n\n", rtn_code);
    	}
    	else // twim_dev1 == NULL
    		printk("TWI is not initialized correctly.\n");
    }
    
    void main(void)
    {
    	uint16_t twi_test_cnt = MSG_EXCHANGE_CNT;
    	bool led_is_on = true;
    	uint32_t ret;
    
    	led_dev = device_get_binding(LED0);
    	if (led_dev == NULL)
    	{
    		return;
    	}
    
    	ret = gpio_pin_configure(led_dev, PIN, GPIO_OUTPUT_ACTIVE | FLAGS);
    	if (ret < 0)
    	{
    		return;
    	}
    
    	twim_init();
    	k_msleep(2000);
    	i2c_write(nrfx_twis_dev1,softRest,2,DT_REG_ADDR(DT_NODELABEL(twis_device1)) )	;
    	k_msleep(2000);
    
    	int rtn_code = 5;
    	int	incr = 0 ;
    	i2c_write(nrfx_twis_dev1,triggerContinuousMeasurement,2,DT_REG_ADDR(DT_NODELABEL(twis_device1)) )	;
    	k_msleep(2000);
    	i2c_write(nrfx_twis_dev1,activateASC,2,DT_REG_ADDR(DT_NODELABEL(twis_device1)) );
    	k_msleep(2000);
    	i2c_write(nrfx_twis_dev1,dataReady,2,DT_REG_ADDR(DT_NODELABEL(twis_device1)) );
    	k_msleep(2000);
    	i2c_read(nrfx_twis_dev1, i2c_rx_buffer, sizeof(i2c_rx_buffer), DT_REG_ADDR( DT_NODELABEL(twis_device1) ) );
     	while (1)
    	{
    
    		gpio_pin_set(led_dev, PIN, (int)led_is_on);
    		led_is_on = !led_is_on;
    
    		if ((twi_test_cnt) || (INFINITE_MSG_EXCHANGE))
    		{		
    			incr = 0 ;
    			// i2c_write_read(nrfx_twis_dev1, DT_REG_ADDR(DT_NODELABEL(twis_device1)),readCommand,2,i2c_rx_buffer,18);
    			i2c_write(nrfx_twis_dev1,readCommand,2,DT_REG_ADDR(DT_NODELABEL(twis_device1)) );
    			i2c_read(nrfx_twis_dev1, i2c_rx_buffer, sizeof(i2c_rx_buffer), DT_REG_ADDR( DT_NODELABEL(twis_device1) ) );
     			while (incr < 18)
    			printk("| 0x%.2x |", i2c_rx_buffer[incr++]);
    			printk("\n"); 
    			
    			
    		}
    		k_msleep(10000);
    	}
    }

    blinky-TWIM3.zip

  • Hi 

    Assuming your sensor expects a typical write -> repeated start -> read pattern where you first write the command and then immediately read out the response, then you should use the i2c_write_read(..) function.

    Issuing separate i2c_write(..) and i2c_read(..) calls will most likely not have the same effect, since they will be interpreted by the sensor as two separate commands. 

    Best regards
    Torbjørn 

  • Hi, in the code I posted you can see that I have I2c_write_read() commented, that is because I tried using it as well, did not work with any command, however, I was able to get the frameware version ---> page 17 using separate I2C_write() then read, according to the scd30 Zephyr example:

     https://github.com/Sensirion/embedded-common/blob/1ac7c72c895d230c6f1375865f3b7161ce6b665a/hw_i2c/sample-implementations/zephyr_user_space/sensirion_hw_i2c_implementation.c

    when trying to write (Get measurement interval for example (page9)  ) I always get the deafult interval for the sensor which is 2 sec, although I just used command (set Interval) to change it 4 sec!

    when trying to get ( dataReady) it always returns 0  although I have already sent (triggerContinuous Measurement

    I don't understand where is the problem

  • Here is another example of the problem 

    void main(void)
    {
    	
    
    
    	uint16_t twi_test_cnt = MSG_EXCHANGE_CNT;
    	bool led_is_on = true;
    	uint32_t ret;
    
    	led_dev = device_get_binding(LED0);
    	if (led_dev == NULL)
    	{
    		return;
    	}
    
    	ret = gpio_pin_configure(led_dev, PIN, GPIO_OUTPUT_ACTIVE | FLAGS);
    	if (ret < 0)
    	{
    		return;
    	}
    	k_msleep(2000);
    	int	incr = 0 ;
    	int rtn_code = 5;
    
    	twim_init();
    	printk("\n"); 
    	printk("\n-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-\n"); 
    	printk("\n"); 
        k_msleep(2000);
    	i2c_write(nrfx_twis_dev1,softRest,2,DT_REG_ADDR(DT_NODELABEL(twis_device1)) )	;
    	k_msleep(2000);
    	i2c_write(nrfx_twis_dev1,activateASC,4,DT_REG_ADDR(DT_NODELABEL(twis_device1)) );
    	k_msleep(2000);
    	i2c_write(nrfx_twis_dev1,getASC,2,DT_REG_ADDR(DT_NODELABEL(twis_device1)) );
    	k_msleep(2000);
    	i2c_read(nrfx_twis_dev1, i2c_rx_buffer, sizeof(i2c_rx_buffer), DT_REG_ADDR( DT_NODELABEL(twis_device1) ) );
    	while (incr <4)
    			printk("| 0x%.2x |", i2c_rx_buffer[incr++]);
    	printk("\n"); 
    	printk("\n-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-\n"); 
    	printk("\n"); 
    
    	incr = 0 ;
    	k_msleep(2000);
    	i2c_write_read(nrfx_twis_dev1, DT_REG_ADDR(DT_NODELABEL(twis_device1)),getASC,2,i2c_rx_buffer,18);
    	while (incr< 4)
    			printk("| 0x%.2x |", i2c_rx_buffer[incr++]);
    	printk("\n"); 
    	printk("\n-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-\n"); 
    	printk("\n"); 
    }

    in this code I try to activate ASC: AUTO SELF CALIBRATION, I send the command to activate it then I send the command to get the ASC Status (both ways) and it returns 0 meaning it is not active

    I have no clue how is this happening?!

Reply
  • Here is another example of the problem 

    void main(void)
    {
    	
    
    
    	uint16_t twi_test_cnt = MSG_EXCHANGE_CNT;
    	bool led_is_on = true;
    	uint32_t ret;
    
    	led_dev = device_get_binding(LED0);
    	if (led_dev == NULL)
    	{
    		return;
    	}
    
    	ret = gpio_pin_configure(led_dev, PIN, GPIO_OUTPUT_ACTIVE | FLAGS);
    	if (ret < 0)
    	{
    		return;
    	}
    	k_msleep(2000);
    	int	incr = 0 ;
    	int rtn_code = 5;
    
    	twim_init();
    	printk("\n"); 
    	printk("\n-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-\n"); 
    	printk("\n"); 
        k_msleep(2000);
    	i2c_write(nrfx_twis_dev1,softRest,2,DT_REG_ADDR(DT_NODELABEL(twis_device1)) )	;
    	k_msleep(2000);
    	i2c_write(nrfx_twis_dev1,activateASC,4,DT_REG_ADDR(DT_NODELABEL(twis_device1)) );
    	k_msleep(2000);
    	i2c_write(nrfx_twis_dev1,getASC,2,DT_REG_ADDR(DT_NODELABEL(twis_device1)) );
    	k_msleep(2000);
    	i2c_read(nrfx_twis_dev1, i2c_rx_buffer, sizeof(i2c_rx_buffer), DT_REG_ADDR( DT_NODELABEL(twis_device1) ) );
    	while (incr <4)
    			printk("| 0x%.2x |", i2c_rx_buffer[incr++]);
    	printk("\n"); 
    	printk("\n-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-\n"); 
    	printk("\n"); 
    
    	incr = 0 ;
    	k_msleep(2000);
    	i2c_write_read(nrfx_twis_dev1, DT_REG_ADDR(DT_NODELABEL(twis_device1)),getASC,2,i2c_rx_buffer,18);
    	while (incr< 4)
    			printk("| 0x%.2x |", i2c_rx_buffer[incr++]);
    	printk("\n"); 
    	printk("\n-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-\n"); 
    	printk("\n"); 
    }

    in this code I try to activate ASC: AUTO SELF CALIBRATION, I send the command to activate it then I send the command to get the ASC Status (both ways) and it returns 0 meaning it is not active

    I have no clue how is this happening?!

Children
Related