MMA7455L test for I2C interface. 10-bit 8g mode.

Dependencies:   mbed

main.cpp

Committer:
lnadal
Date:
2011-08-21
Revision:
0:17e709908189

File content as of revision 0:17e709908189:

#include "mbed.h"

/*
*************************************************************************************************
MMA7455. Simple test for I2C interface and 10-bit 8g mode . 2g, 4g, 8g, digital triple axis accelerometer
with I2C/SPI interface.

In Level Detection Mode and pulse detection mode, dynamic range is set automatically to 8g.
Read or Write Low Byte first.

Wiring:
pin 2, pin 3, pin 5, IADDR0(pin 4), pin 10 and pin 11 tied to ground.
DVdd(pin 1),AVdd(pin 6) and CS(pin 7) tied to 3.3V.
INT1(p8) to mBed's p15(INT1 is not used in this program). INT2(p9) to mBed's p16.

Author: Lluis Nadal. August 2011.
*************************************************************************************************
*/

I2C i2c(p9, p10); // SDA(p13), SCL(p14). 4.7k pull-up resistors.

//pin 4 (IADDR0) tied to ground.
const int addr_R = 0x3B; // Address to read:  111011
const int addr_W = 0x3A; // Address to write: 111010

Serial pc(USBTX, USBRX);

DigitalOut led1(LED1), led2(LED2), led3(LED3), led4(LED4);
InterruptIn int1(p15); //
InterruptIn int2(p16); //

int offset[3];
int v[6];
int a;
char msb, lsb;




void read_8(int n) { // Read 8-bit register
    i2c.start();
    v[0]=i2c.write(addr_W);
    v[1]=i2c.write(n);
    i2c.start();
    v[2] = i2c.write(addr_R);
    v[3]=i2c.read(0);
    i2c.stop();
//ACK = v[0]= v[1]= v[2]= 1; NACK = 0. v[3] = value.
    pc.printf(" (v[0],v[1],v[2],v[3]) = (%d, %d, %d, %d)\r\n\r\n", v[0],v[1],v[2],v[3]);
}


void read(int n) { // Read 10-bit registers n and n+1
    i2c.start();
    i2c.write(addr_W);
    i2c.write(n); // Starting register(L)
    i2c.start();
    i2c.write(addr_R);
    lsb = i2c.read(0);
    i2c.stop();

    i2c.start();
    i2c.write(addr_W);
    i2c.write(n+1); // Next register(H)
    i2c.start();
    i2c.write(addr_R);
    msb = i2c.read(0);
    i2c.stop();
    pc.printf(" (msb, lsb): (%d, %d)\r\n", msb, lsb);
    pc.printf("\r\n");
    a = (int)msb;
    a = (a << 8) | lsb;
    if ((msb >> 1) == 1) a = a -1024; // If negative
    pc.printf(" a = %d\r\n\r\n", a);
}


void write_8(int reg, int data) { // Write 8-bit data to register
    i2c.start();
    v[0]=i2c.write(addr_W);
    v[1]=i2c.write(reg);
    v[2] = i2c.write(data);
    i2c.stop();
//ACK = v[0]= v[1]= v[2] = 1; NACK = 0.
    // pc.printf(" (v[0],v[1],v[2]) = (%d, %d, %d)\r\n", v[0],v[1],v[2]);
    // pc.printf("\r\n");
}

void write_offset(int reg, int data) { // Write 11-bit data to offset registers L and H
    char H, L;
    i2c.start();
    i2c.write(addr_W);
    i2c.write(reg); // Starting register(L)
    if (data < 0) data = 2048 + data ; // If negative
    pc.printf(" data = %d\r\n", data);
    H = (char) ((data & 0xFF00) >> 8);
    L = (char) (data & 0x00FF);
    i2c.write(L);
    i2c.stop();
    i2c.start();
    i2c.write(addr_W);
    i2c.write(reg+1); // Next register(H)
    i2c.write(H);
    i2c.stop();
    pc.printf(" (H, L) = (%d, %d )\r\n\r\n", H, L);
}




void clr_int() {   // Clear interrupt latch
    write_8(0x17, 0x03);
    write_8(0x17, 0x00); // Default option
}

void flash() {
    led4 = 0;
    pc.printf("Pulse detected!\r\n");
    led4 = 1;
    wait(1);
    led4 = 0;
    clr_int(); // Clear interrupt latch
}




int main() {

    i2c.frequency(100000);

    led1 = 0, led2 = 0, led3 = 0, led4 = 0;
    wait(2);

// Read some 8-bit registers
    pc.printf(" Read some registers: \r\n\r\n");


    pc.printf(" WHOAMI register: ");
    read_8(0x0F); // WHOAMI

    pc.printf(" I2C ADDRESS: ");
    read_8(0x0D); // I2C ADDRESS

    pc.printf(" MODE CONTROL register: ");
    read_8(0x16); // Mode control register


    // 0x16: Mode[1:0] Control Register:
    // 00: Standby Mode
    // 01: Measurement Mode
    // 10: Level Detection Mode
    // 11: Pulse Detection Mode

    // 0x16: GLV[1:0] Control Register:
    // 00: 8g
    // 10: 4g
    // 01: 2g

    pc.printf( "Write to MODE CONTROL register 0x16\r\n\r\n");
    // Write: DRPD = 1, GLVL = 00(8g), MODE: 01(Measurement).
    write_8(0x16, 0x41);
    clr_int(); // Clear interrupt latch

    pc.printf(" MODE CONTROL register updated: ");
    read_8(0x16); // MODE CONTROL register is updated

    pc.printf(" Interrupt latch register: ");
    read_8(0x17); // Interrupt latch register

    pc.printf(" Status: ");
    read_8(0x09); // Status

// Clear offset registers: 11-bit
    pc.printf(" Clear offset registers\r\n\r\n");
    write_offset(0x10, 0); // Offset x
    write_offset(0x12, 0); // Offset y
    write_offset(0x14, 0); // Offset z
    wait(0.1);

    // Start autocalibration. Lay device down horizontal and do not move
    // Average 4 readings
    // Offsets must be multiplied by 2
    pc.printf(" Autocalibration: lay device down horizontal and do not move\r\n\r\n");
    led1 = 1; // Start autocalibration in 4 seconds
    wait(4);
    offset[0] = 0, offset[1] = 0, offset[2] = 0;

    for (int i = 0; i < 4; i++) {

        pc.printf(" x: \r\n");
        read(0x00);
        offset[0] = offset[0]-a;

        pc.printf( "y: \r\n");
        read(0x02);
        offset[1] = offset[1]-a ;

        pc.printf(" z: \r\n");
        read(0x04);
        offset[2] = offset[2]-a;
        wait(0.2);
    }

    led2 = 1; // End autocalibration

    // Offsets must be multiplied by 2 and divided by 4 to calculate the average
    offset[0] = offset[0]/2;
    offset[1] = offset[1]/2;
    offset[2] = offset[2]/2 + 2*64; //Z axis output for 1g must be 64 in 10-bit mode


    // Write offset registers (11-bit). Offset registers are volatile and are cleared on  power off.
    pc.printf(" Write offset registers\r\n\r\n");
    write_offset(0x10, offset[0]); // Offset x
    write_offset(0x12, offset[1]); // Offset y
    write_offset(0x14, offset[2]); // Offset z
    wait(0.1);


// Read x, y, z with offset correction
    pc.printf(" Read x, y, z with offset correction\r\n\r\n");
    pc.printf(" x corrected: \r\n");
    read(0x00);
    pc.printf( "y corrected: \r\n");
    read(0x02);
    pc.printf(" z corrected: \r\n");
    read(0x04);
    wait(0.1);

// Single pulse detection
    write_8(0x16, 0x43); // DRPD = 1; GLV = 00(8g), MODE: 11(pulse detection).
    write_8(0x19, 0x00);
    write_8(0x18, 0x00); // Int2 for pulse detection
    write_8(0x1B, 0x20); // Unsigned 7-bit Pulse Treshold set to 2g.
    write_8(0x1C, 0x10); // Pulse duration set to 8 ms
    int2.rise(&flash); // Attach flash function to int2
    pc.printf(" Start pulse detection\r\n\r\n");
    led3 = 1; // Start pulse detection

    while (1) {
    }
}