Earlier we have used xtrinsic as a temperature measuring module.

This time we shall use it as an accelerometer.

 

The Xtrinsic Sensor BoardXtrinsic Sensor Board comes bundled with multiple sensors & is arduino compatible.

2lvd30h.jpg

The Xtrinsic module supports consists of  sensors:

MPL3115A2  - high-precision sensor used to provide accurate pressure and temperature.

MAG3110     - small, low-power, digital 3-axis magnetometer

MMA8491Q  - low voltage, 3-axis low-g accelerometer

 

 

Setting up the Hardware

 

Lets start with the pin mapping of Xtrinsic.

we will be using 5 pins of Xtrinsic board.

 

 

Pin Mapping for Xtrinsic Accelerometer.

2n6w2ec.jpg

5  Male to Female jumper wires are used  to connect Riotboard Expansion port pins to Xtrinsic CN1 & CN2 .

 

 

Connecting female headers in Xtrinsic CN2 Connector.

30afhv6.jpg

 

 

Connecting female headers in Xtrinsic CN1 Connector.

1059lbt.jpg

 

 

Connecting Male headers in Riotboard (J13)

14nioth.jpg

 

 

Setup after Connections ....

5eg0lt.jpg

 

In order to retrieve data from the accelerometer the Enable (EN) pin of Xtrinsic needs to be logic high.

 

2ryhret.jpg

 

 

Based on schematics I an using PIN5 (GPIO)  in J13 port to drive xtrinsic pin1(EN) high.

we need to configure PIN5 as gpio.

 

Execute below command to set Pin5 as GPIO

devmem 0x20E009C w 0x5

 

Export the pin to sysfs filesystem so that we can use it:

echo 112 > /sys/class/gpio/export

 

PIN5 = GPIO4_16 (from schematics)

 

GPIO4_16 = (4-1)*32+16 = 112

 

Drive the GPIO high.

echo out > /sys/class/gpio/gpio112/direction

echo 1 > /sys/class/gpio/gpio112/value

 

Once done with the gpio settings, we will move to accelerometer driver.

 

I wrote a  user-space driver  to access the accelerometer sensor .

 

#include <stdio.h>
#include <stdint.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>

#define I2CFILE "/dev/i2c-3"

static int write_register(int file,unsigned char address,unsigned char reg,unsigned char data)
{

   unsigned char output_buffer[2];
   struct i2c_rdwr_ioctl_data packets;
   struct i2c_msg messages[1];

    messages[0].addr  = address;
    messages[0].flags = 0;
    messages[0].len   = sizeof(output_buffer);
    messages[0].buf   = output_buffer;

    output_buffer[0] = reg;
    output_buffer[1] = data;

    packets.msgs  = messages;
    packets.nmsgs = 1;

    if(ioctl(file, I2C_RDWR, &packets) < 0) {
        perror("Error sending data");
        return 1;
    }

    return 0;
}


static int read_register(int file, unsigned char address, unsigned char reg, unsigned char *data)
{
    unsigned char input_buffer, output_buffer;
    struct i2c_rdwr_ioctl_data packets;
    struct i2c_msg messages[2];


    output_buffer = reg;
    messages[0].addr  = address;
    messages[0].flags = 0;
    messages[0].len   = sizeof(output_buffer);
    messages[0].buf   = &output_buffer;

    messages[1].addr  = address;
    messages[1].flags = I2C_M_RD;
    messages[1].len   = sizeof(input_buffer);
    messages[1].buf   = &input_buffer;


    packets.msgs      = messages;
    packets.nmsgs     = 2;
    if(ioctl(file, I2C_RDWR, &packets) < 0) {
        perror("Error Receiving data");
        return 1;
    }
    *data = input_buffer;

    return 0;
}

int main() {
    int file, i;
    unsigned char data_m;
    unsigned char data_l;
    char string[200];

if ((file = open(I2CFILE, O_RDWR)) < 0)
{
    perror("Error openning file!");
    exit(1);
}
else
    printf("%s opened\n",I2CFILE);


while(1)
{
//accel status
   if(read_register(file, 0x55, 0x00, &data_m))
      exit(1);
   else
     printf("\n\n\nAcc Status: [0x%02X]: 0x%02X\n" , 00 , data_m);


//read accel MSB/LSB - X axis
   if(read_register(file, 0x55, 0x01, &data_m))
     exit(1);
   if(read_register(file, 0x55, 0x02, &data_l))
     exit(1);
   printf("X-Register : 0x%02X:0x%02X\n" , data_m, data_l);


//read accel MSB/LSB - Y axis
   if(read_register(file, 0x55, 0x03, &data_m))
     exit(1);
   if(read_register(file, 0x55, 0x04, &data_l))
     exit(1);
   printf("Y-Register : 0x%02X:0x%02X\n" , data_m, data_l);


//read accel MSB/LSB - Z axis
   if(read_register(file, 0x55, 0x05, &data_m))
     exit(1);
   if(read_register(file, 0x55, 0x06, &data_l))
     exit(1);
    printf("Z-Register : 0x%02X:0x%02X\n" , data_m, data_l);


system("echo out > /sys/class/gpio/gpio112/direction");
system("echo 1 > /sys/class/gpio/gpio112/value");
usleep(1000000);

}
    close(file);
    return 0;
}













 

Code Expln:

Once the values are read the EN pin is set low and the register contents are reset.

In Line 118 -119 we drive the EN pin high to preserve the register contents until next read.

Driving EN pin high, makes register [0x00] value as 0xFF.

Acc Status: [0x00]: 0xFF  (check terminal output towards the end of blog).

 

In Line 11  we  select /dev/i2c-3 (I2C4-SDA) pin as our communication path.

 

 

Compiling the program :

    On Riotboard:

    gcc xtrinsic_acc.c -o xtrinsic_acc

 

    On PC:

   <PATH_TO_TOOLCHAIN>/fsl-linaro-toolchain/bin/arm-fsl-linux-gnueabi-gcc xtrinsic_acc.c -o xtrinsic_acc

 

Once Compiled we will execute . To access a device file "/dev/i2c-3" (check line 11 above ) we need to be root.

# ./xtrinsic_acc

 

register values will change based on the inclination of the board ..

Even with no movement you can see changing values in the LSB part of register  due to table vibrations.

 

2unytck.jpg

 

 

Ok It works ..

 

We completed  integration of xtrinsic accelerometer sensor with Riotboard.

 

In Next blog we shall see how to get meaningful information out of the captured register values.