MMA7455L connected via SPI

 

This is just the first attempt to work with MMA7455L.
  • MMA7455L sensor module http://strawberry-linux.com/catalog/items?code=12102
  • Code is based on the following application note: http://strawberry-linux.com/pub/AN3468.pdf
  • CS should be connected to any pin other than P19 which is off(0); I'm not sure but controlling CS does not work as expected.
  • Pulse Detection does not work though P15 is flagged; what should I do next?
  • 10bit is only enabled for 8g according to page 15 of the spec. above.
  • It seems that we should accumulate values (for a delta time) from a sensor to get consistent result.
  • LEDs is used to indicate the activities on those sensors.
  • Add negative number support (for reading 10-bit value)
mma7455l_test
// Testing MMA7455L SPI
#include "mbed.h"

SPI spi(p5, p6, p7);
DigitalOut cs(p19);
InterruptIn int1(p15), int2(p16);
Serial pc(USBTX, USBRX);
DigitalOut led1(LED1), led2(LED2), led3(LED3);

int read(int reg) {
    cs = 0;
    int v = spi.write(reg << 1);
    cs = 1;
    return v;
}

void write(int reg, int val) {
    cs = 0;
    spi.write(0x80 | (reg << 1));
    spi.write(val);
    cs = 1;
}

int read10(int reg) {
    cs = 0;
    int v = spi.write(reg << 1);
    v |= spi.write((reg + 1) << 1) << 8;
    
    if(v & 0x200)
        v = v - 1024;
    
    cs = 1;
    return v;
}

int readSensorDirect(int sensor) {
    return read10(sensor * 2);
}

const int SENSBUFSIZE = 100;
int sensbuf[3][SENSBUFSIZE];
int sens_ptr = 0;

void reset()
{
    for(int i = 0; i < 3; i++)
    {
        int offset = readSensorDirect(i);
        write(0x10 + i * 2, offset * 2);
    }
    memset(sensbuf, 0, sizeof(sensbuf));
}

void accumulate()
{
    for(int i = 0; i < 3; i++)
        sensbuf[i][sens_ptr] = readSensorDirect(i);
    sens_ptr++;
    if(sens_ptr == SENSBUFSIZE)
        sens_ptr = 0;
}

int readSensor(int sensor)
{
    int* buf = sensbuf[sensor];
    int a = 0;
    for(int i = 0; i < SENSBUFSIZE; i++)
        a += buf[i];
    return a;
}

void int1_raised() {
    pc.printf("1\n");
    //pc.printf("1: %06d,%06d,%06d\n", readX(), readY(), readZ());
}

void int2_raised() {
    pc.printf("2\n");
    //pc.printf("2: %06d,%06d,%06d\n", readX(), readY(), readZ());
}

const int INDSIZE = 5;
const int FULLSIZE = INDSIZE * 2 + 1;

void bar(char* ind, int v)
{
    memcpy(ind, "..........|.........." + (10 - INDSIZE), FULLSIZE);
    if(v < 0)
    {
        char* p = ind + INDSIZE - 1;
        for(int i = 0; i < INDSIZE; i++)
        {
            if(v) *p = '#';
            p--;
            v /= 5;
        }
    }
    else
    {
        char* p = ind + INDSIZE + 1;
        for(int i = 0; i < INDSIZE; i++)
        {
            if(v) *p = '#';
            p++;
            v /= 8;
        }
    }
}

int main() {

    wait_ms(300);

    spi.format(8, 0);
    spi.frequency(1 * 1000* 1000);

    // Device ID
    read(0xf);
    pc.printf("WHOAMI: %02X\n", read(0xf));

    // $16: Mode Control Register
    // 0x0: Standby Mode
    // 0x1: Measurement Mode
    // 0x2: Level Detection Mode
    // 0x3: Pulse Detection
    int mode = 0x2;

    // 0x0: 8g
    // 0x8: 4g
    // 0x4: 2g
    int glv = 0x0;

    read(0x16);
    write(0x16, glv | mode);
    pc.printf("Mode Control Register: %02X\n", read(0x16));

    // Optimal Settings for Freefall using Level Detection
    // 1. THOPT=0 Absolute Condition
    // 2. ZDA=0 Enable Z, YDA=0 Enable Y, XDA=0 Enable X
    write(0x18, read(0x18) & 0x87);
    // 3. Negative AND Logia Set LDPL
    write(0x19, read(0x19) & 0x1);
    // 4. Set Threshold = 1 g
    write(0x1a, 0x10);
    
    /*
    // Optimal Settings for Motion using Level Detection
    // 1. THOPT=0 Absolute Condition
    // 2. ZDA=1 Disable Z, YDA=0 Enable Y, XDA=0 Enable X
    write(0x18, (read(0x18) & 0x87) | 0x20);
    // 3. Positive OR Logic Clear LDPL
    write(0x19, read(0x19) & 0xfe);
    // Set Threshold to 2 g
    write(0x1a, 0x20);
    */

    /*
    // Optimal Settings for Single Pulse Detection
    // 1. Positive OR Logic PDPL=0
    write(0x19, read(0x19) & 0xfd);
    // 2. X,Y,Z enabled
    write(0x18, read(0x18) & 0x87);
    // 3. PDTH (Pulse Threshold) set to 4 g
    write(0x1b, 0x40);
    // 4. PD (Pulse Duration) set to 8 ms
    write(0x1c, 0x80);
    */

    int1.rise(int1_raised);
    int2.rise(int2_raised);
    
    reset();
    for(int i = 0;; i++)
    {
        wait_us(100);
        accumulate();
        
        int x = readSensor(0);
        int y = readSensor(1);
        int z = readSensor(2);
        led1 = x / 100;
        led2 = y / 100;
        led3 = z / 100;

        if (i % 100 == 0)
        {
            char buf[FULLSIZE * 3 + 3];
            memset(buf, ' ', FULLSIZE * 3 + 2);
            buf[FULLSIZE * 3 + 2] = 0;
            bar(buf, x);
            bar(buf + FULLSIZE + 1, y);
            bar(buf + (FULLSIZE + 1) * 2, z);
        
            pc.printf("P:%s\n", buf);
        }
    }
}


1 comment

05 Aug 2011

Thanks for the code,

could you post a wiring diagram as I'm unsure which pins MISO and MOSI are connected to on the MMA7455.

Thanks again,

Sam

You need to log in to post a comment