Friday, December 5, 2014

Reading MMA7660 Accelerometer Data With nRF51822 BLE SOC

In this post I will describe you how to connect MMA7660 accelerometer to nRF51822 ,how to use the interrupts and gestures and how to read accelerometer data via UART module in  NRF51822.

I'm using nRF Development Kit which includes two nRF51822 chips which are mounted on PCB with a matched antenna.The kit also includes a compact nRF51822 USB dongle that can act as a Bluetooth low energy master emulator when developing Bluetooth low energy applications. Unfortunately we couldn't buy a nRFgo Starter kit. So I will describe how to program the nRF chip without a nRFgo Starter Kit.

Connect pin2 and pin3 together and connect them to 3.3V in K1 header. Then find a ground signal from the board  (see P5 header) and connect it to the GND of the power source.

Initializing UART

To read the data via UART module I used USB to Serial converter module which can be easily buy from ebay. But in my next post, I will describe how to read data via BLE module in the chip. Before using the uart module you must configure the baud rate , hardware flow control and pins.

I did not use any hardware flow control. So I set HDFC to false.

     #define RX_PIN_NUMBER  11
     #define TX_PIN_NUMBER  9
     #define CTS_PIN_NUMBER 10
     #define RTS_PIN_NUMBER 8
     #define HWFC           false

Set the baud rate to 9600.

Initializing I2C


MMA7660 accelerometer module is specially designed for identify gestures. It communicates with the micro controller via I2C interface. So we must activate the I2C interface of nrf51822 SoC. In order to do so, twi_hw_master.c file should be imported to your workspace. By calling "twi_master_init(void)" function in the above C file,we can initialize hardware I2C interface of the chip. By default SDA and SCK pins are 24U and 25U. By reading the data sheet of accelerometer module you would get better understand how it communicates with external micro controller via I2C interface. In the data sheet they have mentioned the I2C frequency the accelerometer works with.

There are some issues with I2C interface. Most of the time devices will not communicate properly if the connections between them are loos. Connecting wires should shorter as possible. 

SDA and SCL pins should be connected to pull up resisters. In the breakout board I bought from ebay got those pull up resisters. So I was able to connect the breakout board's SCL and SDA pins directly to the chip.

So we have done the basic setup to communicate with accelerometer and get data out from it.

MMA7660 Register Settings 



You can set the accelerometer to power saving mode by several ways. Sample rate can be adjust using SR register. Device can set in the standby mode using MODE register. Interrupt settings can configure by adjusting INTSU register. I have set the basic settings in mma7660.c file. Those settings are made to identify several gestures through interrupts. Following settings can be viewed under "bool mma7660_init(uint8_t device_address)" function.

transfer_succeeded &= mma7660_register_write(MODE,0x00 );//The device must be placed in Standby Mode to change the value of the registers.
transfer_succeeded &= mma7660_register_write(INTSU,0xE4 );// make an interrupt transfer_succeeded &= mma7660_register_write(PDET,0x1F );//for tap detection sensitivity and tap direction select
transfer_succeeded &= mma7660_register_write(SR,0xE0 );//11100000  
transfer_succeeded &= mma7660_register_write(PD,0x14 );//Tap/Pulse Debounce Count Register (Read/Write)0x14 is good
 // transfer_succeeded &= mma7660_register_write(SPCNT,0xE0 );
transfer_succeeded &= mma7660_register_write(MODE,0x41 );//Interrupt output INT is push-pull and Interrupt output INT is active low

Above settings were enough for my project. It would different from your requirements. So please read the data sheet.

Reading Accelerometer Data


My purpose was not to read accelerometer data from mma7660, but to get gestures from it. But I saw something special within this module. The data it gives as accelerometer values for each 3 axis are in 2's compliment format. So you must convert the data before using it for any other calculations. In the following code sample, I have shown that how I was able to read the data.

void getacceldata(void)  //get the 2's compliment 
{
    uint8_t accelvalue[3];
    uint8_t accelval[3];
    int i=0;
    mma7660_accel_read(&accelvalue[0]);
    for(i=0;i<3;i++){
        accelvalue[i] = accelvalue[i]%64;
        if(accelvalue[i] > 31)
           accelval[i] = accelvalue[i]-64;
        else
           accelval[i] = accelvalue[i];
    }    
 sprintf(&tempBuff[0], "%d , %d , %d \r\n", accelval[0],accelval[1],accelval[2]);
 debug_if_send_buf(&tempBuff[0]);   
}   

What "mma7660_accel_read" function does is, reading 0x00, 0x01, 0x02 registers which contains accelerometer data of X, Y and Z axis. 
Once you get the 2's compliment data, in order to obtain g value of each axis "MMA7660FC ACQUISITION CODE TABLE" should be referred. (see page 28,29 of MMA7660 data sheet ).

Identifying Gestures

I use this module for my final year project to identify gestures. After working with the accelerometer module what I understood was MMA7660 is good for gesture recognition. Unfortunately some gestures didn't work properly due to some reason. In future I will fix the problem and post here.

You will be able to understand what kind of gestures can be identified by this module by reading Features topic in the data sheet. Following gestures can be identified by the accelerometer.

  
You must set the value for INTSU register to activate interrupt generation for each movement. For example, if you want to identify if shake is happening in x axis, you should set the SHINTX bit of INTSU register to '1' else '0'.

mma7660_register_write(INTSU,0x80 );// make an interrupt

Once you done this, accelerometer will generate an interrupt when it detects a shake in  axis.
Lets think you have configure the INTSU register as following

mma7660_register_write(INTSU,0xE4 );// make an interrupt

How you can determine which gesture is responsible for the interrupt ?
TILT register comes into the show in that point. TILT register will update its bit if it feels any gesture.
Following function calls when a interrupt occurs. It reads TILT register to identify the gesture.

void getinturrupt(void)
{
        uint8_t intdata;
        int bin[8];
        int data;
        detect_interrupt(&intdata);
        data = intdata;
        bin[0]=intdata/128;
        intdata = intdata%128;
        bin[1]=(intdata/64);
        intdata = intdata%64;
        bin[2]=(intdata/32);
        intdata = intdata%32;
        bin[3]=(intdata/16);
        intdata = intdata%16;
        bin[4]=(intdata/8);
        intdata = intdata%8;
        bin[5]=(intdata/4);
        intdata = intdata%4;
        bin[6]=(intdata/2);
        intdata = intdata%2;
        bin[7]=(intdata/1);
        sprintf(&tempBuff[0], " %d - %d %d %d %d %d %d %d %d \r\n",data,                                                bin[0],bin[1],bin[2],bin[3],bin[4],bin[5],bin[6],bin[7]); debug_if_send_buf(&tempBuff[0]);
    }


I hope above details will help you if you are getting troubles with MMA7660 accelerometer module. I would like to know your comments on my post. If anything is wrong there, please let me know.


No comments:

Post a Comment