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.
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.
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.
Connecting female headers in Xtrinsic CN1 Connector.
Connecting Male headers in Riotboard (J13)
Setup after Connections ....
In order to retrieve data from the accelerometer the Enable (EN) pin of Xtrinsic needs to be logic high.
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.
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.