This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Reading external sensor using I2C on nrf9160dk

Hello,

I want to read external accelerometer on nrf9160dk using I2C. But when I connect SDA and SCL pins of sensor to nrf91, there is no output.

The Code is:

#include <nrf9160.h>
#include <zephyr.h>
#include <misc/printk.h>
#include <i2c.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

#define I2C_ACCEL_READ_ADDR   60

struct device * i2c_accel;
u8_t I2C_BUFFER[35];


void init_accelerometer(){
    i2c_accel = device_get_binding("I2C_2");
    if (!i2c_accel) {
		printk("error\r\n");
	} 
    i2c_configure(i2c_accel, I2C_SPEED_SET(I2C_SPEED_FAST));

}


void main(void)
{
        printk("Start I2C comminication\r\n");
        init_accelerometer();

	while (1) {

                i2c_read(i2c_accel, I2C_BUFFER, 29, I2C_ACCEL_READ_ADDR);

                printk("I2C_BUFFER = %s\n", I2C_BUFFER);
	}
}

When I don't connect sensor to nrf91, then continuously it prints "I2C_BUFFER ="

When I connect the sensor, everything stops and when I again remove the pins it prints "I2C_BUFFER ="

What I am doing wrong? How to read these sensors value?

Thank you

Parents
  • Hi,

    Here is some code that you can test to see if you get a response from the sensor. If there is an ACK for the address, it prints the address it found.

    main.c

    #include <nrf9160.h>
    #include <zephyr.h>
    #include <misc/printk.h>
    #include <i2c.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    
    
    #include <gpio.h>
    
    #define I2C_ACCEL_WRITE_ADDR 0x32
    #define I2C_ACCEL_READ_ADDR 0x75
    
    struct device * i2c_accel;
    uint8_t WhoAmI = 0u;
    
    
    static struct device  *led_port;
    
    #ifdef CONFIG_SOC_NRF9160
    #define I2C_DEV "I2C_3"
    #else
    #define I2C_DEV "I2C_1"
    #endif
    
    
    void main(void)
    {
    	struct device *i2c_dev;
    	
    	k_sleep(500);
    
    	printk("Starting i2c scanner...\n");
    
    	i2c_dev = device_get_binding(I2C_DEV);
    	if (!i2c_dev) {
    		printk("I2C: Device driver not found.\n");
    		return;
    	}
    	
    	uint8_t error = 0u;
    	
    	i2c_configure(i2c_dev, I2C_SPEED_SET(I2C_SPEED_STANDARD));
    
    
    	printk("Value of NRF_TWIM3_NS->PSEL.SCL: %ld \n",NRF_TWIM3_NS->PSEL.SCL);
    	printk("Value of NRF_TWIM3_NS->PSEL.SDA: %ld \n",NRF_TWIM3_NS->PSEL.SDA);
    	printk("Value of NRF_TWIM3_NS->FREQUENCY: %ld \n",NRF_TWIM3_NS->FREQUENCY);
    	printk("26738688 -> 100k\n");
    	
    	
    	
    	for (u8_t i = 4; i <= 0x77; i++) {
    		struct i2c_msg msgs[1];
    		u8_t dst = 1;
    
    		/* Send the address to read from */
    		msgs[0].buf = &dst;
    		msgs[0].len = 1U;
    		msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;
    		
    		error = i2c_transfer(i2c_dev, &msgs[0], 1, i);
    		if (error == 0) {
    			printk("0x%2x FOUND\n", i);
    		}
    		else {
    			//printk("error %d \n", error);
    		}
    		
    		
    	}
    	
    
    	
    	
    }

    nrf9160_pca10090ns.overlay

    &i2c3 {
    	status = "ok";
    	compatible = "nordic,nrf-twim";
    	sda-pin = < 12 >;
    	scl-pin = < 11 >;
        clock-frequency = <I2C_BITRATE_STANDARD>;  
    };
    

    prj.conf

    #CONFIG_SERIAL=y
    #CONFIG_UART_INTERRUPT_DRIVEN=y
    CONFIG_I2C=y
    CONFIG_I2C_NRFX=y
    CONFIG_I2C_3=y
    CONFIG_I2C_3_NRF_TWIM=y
    
    CONFIG_NEWLIB_LIBC=y
    
    
    #CONFIG_LOG=y
    #CONFIG_I2C_LOG_LEVEL_DBG=y
    #CONFIG_LOG_BACKEND_UART=y
    #CONFIG_I2C_INIT_PRIORITY=60

  • Hello,

    I am trying to configure I2C_3 as slave on nrf9160. But I couldn't found any driver for that. There is i2c_nrfx_twim.c for master. But there is no such driver for slave. In i2c.h and nrf9160.h files there are definitions and registers for slave. But how to use them. I am not understanding how to do configuration. Please guide me for this.

    Thanks

  • It seems like I forgot the link in my last post. Here it is: https://devzone.nordicsemi.com/f/nordic-q-a/50656/using-pdm-mic-on-nrf9160dk/204715#204715

    This post shows you how to add nrfx driver for PDM. If you want to try this approach for TWIS, you will need to add the corresponding TWIS function and defines, e.g. NRFX_TWIS_ENABLED instead of NRFX_PDM_ENABLED.

  • Hi,

    I followed the above guide and NRFX TWIS drivers are included in the program.

    But still there are few doubts. Now is there any need of overlay file? How does the prj.conf file should look like? How to assign the SDA and SCL pins for TWIS?

    Now I have removed the overlay file from the project and removed I2C from prj.conf.

    prj.conf looks like this

    CONFIG_TRUSTED_EXECUTION_NONSECURE=y
    CONFIG_SERIAL=y
    CONFIG_UART_INTERRUPT_DRIVEN=y
    CONFIG_COMPILER_OPT="-DNRF_TWIS3=NRF_TWIS3 -DNRFX_TWIS3_ENABLED=1"
    
    
    CONFIG_NEWLIB_LIBC=y
    
    
    #CONFIG_LOG=y
    #CONFIG_I2C_LOG_LEVEL_DBG=y
    #CONFIG_LOG_BACKEND_UART=y
    #CONFIG_I2C_INIT_PRIORITY=60

    The code:

    #include <nrf9160.h>
    #include <zephyr.h>
    #include <misc/printk.h>
    #include <i2c.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <nrfx_twis.h>
    
    #include <gpio.h>
    
    #define TWI_ADDRESSES   60
    static const nrfx_twis_t m_twis = NRFX_TWIS_INSTANCE(3);
    uint8_t I2C_BUFFER[35];
    char hold_icm_acc[100];
    size_t size = 29;
    bool I2C_xfer_Done;
    
    
    static void twis_event_handler(nrfx_twis_evt_t const * const p_event)
       {
        switch(p_event->type)
        {
        case NRFX_TWIS_EVT_READ_REQ:
            if(p_event->data.buf_req)
            {
            }
            break;
        case  NRFX_TWIS_EVT_READ_DONE:
            break;
        case NRFX_TWIS_EVT_WRITE_REQ:
            if(p_event->data.buf_req)
            {
                nrfx_twis_rx_prepare(&m_twis, I2C_BUFFER, size);            
            }
            break;
        case NRFX_TWIS_EVT_WRITE_DONE:
            /* code to be done */
    
            I2C_xfer_Done=true;
    
            default:
            break;
        }
    }
    
    void twis_init (void) 
    {
    
        const nrfx_twis_config_t config =
        {
            .addr               = TWI_ADDRESSES,
            .scl                = 11,   /* How to assign SCL and SDA pins*/
            .sda                = 12
           // .interrupt_priority = APP_IRQ_PRIORITY_HIGH
            
        };
    
        /* Init TWIS */
        do
        {
            nrfx_twis_init(&m_twis, &config, twis_event_handler);
            nrfx_twis_enable(&m_twis);
        }while (0);
    
    
    }
    
    void main(void)
    {
    	printk("Starting TWIS program!\n");
            printk("ICM data = %d", I2C_BUFFER);
    
    	twis_init();
    }

    In twis_init() function, how to assign SCL and SDA pins. Now I have just given the numbers which I want to use.

    Actually I connected SCL, SDA pins to the Master's SCL, SDA. But as soon as I do connections, Master stops giving data. One more thing I observed is: there is no voltage level at SCL and SDA pins of nRF9160dk. What I am doing wrong? is there any problem in my code? I think I am not assigning the SCL, SDA pins properly. Please tell me how to do that. 

  • Is it necessary to declare the interrupt vector for the TWIS? In this link https://devzone.nordicsemi.com/f/nordic-q-a/50656/using-pdm-mic-on-nrf9160dk/204715#204715 they are adding the interrupt handling. I tried to do this in my project also, but it shows error.

    The code

    ISR_DIRECT_DECLARE(twis_isr_handler)
    {
    	nrfx_twis_3_irq_handler();
    	ISR_DIRECT_PM();
    
    	return 1;
    }
    
    void main(void)
    {
            IRQ_DIRECT_CONNECT(TWIS_IRQn, 0,  /*error for TWIS_IRQn*/
    			   twis_isr_handler, 0);

    Error: 

    1> ../src/main.c:293:28: error: 'TWIS_IRQn' undeclared (first use in this function); did you mean 'I2S_IRQn'?
    1> C:/ncs/zephyr/include/sw_isr_table.h:70:5: note: in definition of macro 'Z_ISR_DECLARE'
    1> C:/ncs/zephyr/include/irq.h:119:2: note: in expansion of macro 'Z_ARCH_IRQ_DIRECT_CONNECT'
    1> ../src/main.c:293:9: note: in expansion of macro 'IRQ_DIRECT_CONNECT'
    1> ../src/main.c:293:28: note: each undeclared identifier is reported only once for each function it appears in
    1> C:/ncs/zephyr/include/sw_isr_table.h:70:5: note: in definition of macro 'Z_ISR_DECLARE'
    1> C:/ncs/zephyr/include/irq.h:119:2: note: in expansion of macro 'Z_ARCH_IRQ_DIRECT_CONNECT'
    1> ../src/main.c:293:9: note: in expansion of macro 'IRQ_DIRECT_CONNECT'
    Build failed

  • Jagruti said:
    but it shows error.

    Try using UARTE3_SPIM3_SPIS3_TWIM3_TWIS3_IRQn instead.


    Jagruti said:
    Is it necessary to declare the interrupt vector for the TWIS?

     Yes, try to use the same approach as in the link.

  • Thank you so much. Your solution is working.

    But there is other problem. I receive some data then it shows "*** buffer overflow detected ***: terminated". When I run same program on nRF52840 with NRFX TWIS drivers there is no problem.

    How can I avoid RX buffer overflow?

    Output:

    ***** Booting Zephyr OS build v1.14.99-ncs3-snapshot2-2647-gd6e67554cfeb *****
    Starting TWIS program!
    Data = ,,,,,,,0,
    Data = ,,,,,,,0,
    Data = ,,,,,,,0,
    Data = ,,,,,,,0,
    *** buffer overflow detected ***: terminated
    exit

Reply
  • Thank you so much. Your solution is working.

    But there is other problem. I receive some data then it shows "*** buffer overflow detected ***: terminated". When I run same program on nRF52840 with NRFX TWIS drivers there is no problem.

    How can I avoid RX buffer overflow?

    Output:

    ***** Booting Zephyr OS build v1.14.99-ncs3-snapshot2-2647-gd6e67554cfeb *****
    Starting TWIS program!
    Data = ,,,,,,,0,
    Data = ,,,,,,,0,
    Data = ,,,,,,,0,
    Data = ,,,,,,,0,
    *** buffer overflow detected ***: terminated
    exit

Children
Related