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

  • The I2C-slave driver support seems to be missing in Zephyr for nrf. You can create a feature request in Zephyr if this is something you need. Note that you might be able to use the nrfx TWIS driver directly instead, see this post on how to use nrfx directly. Alternately, you can use the nRF9160 as I2C master, and the SAM as slave. Or you can use a different protocol between the nRF9160 and the SAM. E.g. UART or SPI.

  • Ok thank you for the reply.

    So how can I use nrfx TWIS driver. what should I add in prj.conf and overlay file to include this driver?

  • 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. 

Reply
  • 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. 

Children
No Data
Related