I2C and an MMA8452 accelerometer

Since commenting before, I have found that if the connection to the accelerometer isn’t perfect the Spark hangs when initialising it. I suspect this may have been my problem in the first place, maybe just a dodgy connection in the breadboard. Make sure you’ve got good contact everywhere to get a nice, clean signal through!

2 Likes

Thanks for all the help :slight_smile: I got the accelerometer working, and the basic example is working aswell. I just added a simple function to the basic example and the code compiles, but when I upload it, the core blinks red.

Does it have something to do with me declaring the pointers globally ?

/* 
 MMA8452Q Basic Example Code
 Nathan Seidle
 SparkFun Electronics
 November 5, 2012
 
 License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).
 
 This example code shows how to read the X/Y/Z accelerations and basic functions of the MMA5842. It leaves out
 all the neat features this IC is capable of (tap, orientation, and inerrupts) and just displays X/Y/Z. See 
 the advanced example code to see more features.
 
 Hardware setup:
 MMA8452 Breakout ------------ Arduino
 3.3V --------------------- 3.3V
 SDA -------^^(330)^^------- A4
 SCL -------^^(330)^^------- A5
 GND ---------------------- GND
 
 The MMA8452 is 3.3V so we recommend using 330 or 1k resistors between a 5V Arduino and the MMA8452 breakout.
 
 The MMA8452 has built in pull-up resistors for I2C so you do not need additional pull-ups.
 */

/* #include  */ // Used for I2C
#include "MMA8452-Accelerometer-Library-Spark-Core/MMA8452-Accelerometer-Library-Spark-Core.h" // Includes the SFE_MMA8452Q library

// The SparkFun breakout board defaults to 1, set to 0 if SA0 jumper on the bottom of the board is set
#define MMA8452_ADDRESS 0x1D  // 0x1D if SA0 is high, 0x1C if low

//Define a few of the registers that we will be accessing on the MMA8452
#define OUT_X_MSB 0x01
#define XYZ_DATA_CFG  0x0E
#define WHO_AM_I   0x0D
#define CTRL_REG1  0x2A

#define GSCALE 2 // Sets full-scale range to +/-2, 4, or 8g. Used to calc real g values.

float * prevValx;
float * prevValy;
float * prevValz;

void setup()
{
  Serial.begin(9600);
  Serial.println("MMA8452 Basic Example");

  Wire.begin(); //Join the bus as a master

  initMMA8452(); //Test and intialize the MMA8452
}

void loop()
{  
    Serial.println("TESTINGSTUFF");
  int accelCount[3];  // Stores the 12-bit signed value
  readAccelData(accelCount);  // Read the x/y/z adc values

  // Now we'll calculate the accleration value into actual g's
  float accelG[3];  // Stores the real accel value in g's
  for (int i = 0 ; i < 3 ; i++)
  {
    accelG[i] = (float) accelCount[i] / ((1<<12)/(2*GSCALE));  // get actual g value, this depends on scale being set
  }

  // Print out values
  //for (int i = 0 ; i < 3 ; i++)
  //{
  //  Serial.print(accelG[i], 4);  // Print g values
  //  Serial.print("\t");  // tabs in between axes
 // }
 // Serial.println();
 
 checkForMovement(accelG);

  delay(10);  // Delay here for visibility
}

void readAccelData(int *destination)
{
  byte rawData[6];  // x/y/z accel register data stored here

  readRegisters(OUT_X_MSB, 6, rawData);  // Read the six raw data registers into data array

  // Loop to calculate 12-bit ADC and g value for each axis
  for(int i = 0; i < 3 ; i++)
  {
    int gCount = (rawData[i*2] <>= 4; //The registers are left align, here we right align the 12-bit integer

    // If the number is negative, we have to make it so manually (no 12-bit data type)
    if (rawData[i*2] > 0x7F)
    {  
      gCount -= 0x1000;
    }

    destination[i] = gCount; //Record this gCount into the 3 int array
  }
}

// Initialize the MMA8452 registers 
// See the many application notes for more info on setting all of these registers:
// http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MMA8452Q
void initMMA8452()
{
  byte c = readRegister(WHO_AM_I);  // Read WHO_AM_I register
  if (c == 0x2A) // WHO_AM_I should always be 0x2A
  {  
    Serial.println("MMA8452Q is online...");
  }
  else
  {
    Serial.print("Could not connect to MMA8452Q: 0x");
    Serial.println(c, HEX);
    while(1) ; // Loop forever if communication doesn't happen
  }

  MMA8452Standby();  // Must be in standby to change registers

  // Set up the full scale range to 2, 4, or 8g.
  byte fsr = GSCALE;
  if(fsr > 8) fsr = 8; //Easy error check
  fsr >>= 2; // Neat trick, see page 22. 00 = 2G, 01 = 4A, 10 = 8G
  writeRegister(XYZ_DATA_CFG, fsr);

  //The default data rate is 800Hz and we don't modify it in this example code

  MMA8452Active();  // Set to active to start reading
}

// Sets the MMA8452 to standby mode. It must be in standby to change most register settings
void MMA8452Standby()
{
  byte c = readRegister(CTRL_REG1);
  writeRegister(CTRL_REG1, c & ~(0x01)); //Clear the active bit to go into standby
}

// Sets the MMA8452 to active mode. Needs to be in this mode to output data
void MMA8452Active()
{
  byte c = readRegister(CTRL_REG1);
  writeRegister(CTRL_REG1, c | 0x01); //Set the active bit to begin detection
}

// Read bytesToRead sequentially, starting at addressToRead into the dest byte array
void readRegisters(byte addressToRead, int bytesToRead, byte * dest)
{
  Wire.beginTransmission(MMA8452_ADDRESS);
  Wire.write(addressToRead);
  Wire.endTransmission(false); //endTransmission but keep the connection active

  Wire.requestFrom(MMA8452_ADDRESS, bytesToRead); //Ask for bytes, once done, bus is released by default

  while(Wire.available() < bytesToRead); //Hang out until we get the # of bytes we expect

  for(int x = 0 ; x < bytesToRead ; x++)
    dest[x] = Wire.read();    
}

// Read a single byte from addressToRead and return it as a byte
byte readRegister(byte addressToRead)
{
  Wire.beginTransmission(MMA8452_ADDRESS);
  Wire.write(addressToRead);
  Wire.endTransmission(false); //endTransmission but keep the connection active

  Wire.requestFrom(MMA8452_ADDRESS, 1); //Ask for 1 byte, once done, bus is released by default

  while(!Wire.available()) ; //Wait for the data to come back
  return Wire.read(); //Return this one byte
}

// Writes a single byte (dataToWrite) into addressToWrite
void writeRegister(byte addressToWrite, byte dataToWrite)
{
  Wire.beginTransmission(MMA8452_ADDRESS);
  Wire.write(addressToWrite);
  Wire.write(dataToWrite);
  Wire.endTransmission(); //Stop transmitting
}

void checkForMovement(float * accArray){
    
    float spikeX;
    float spikeY;
    float spikeZ;
    
    if(prevValx == NULL){
        
        *prevValx = accArray[0];
        *prevValy = accArray[1];
        *prevValz = accArray[2];
    }
    else{
        
       spikeX = *prevValx - accArray[0];
       spikeY = *prevValy - accArray[1];
       spikeZ = *prevValz - accArray[2];
        
        *prevValx = accArray[0];
        *prevValy = accArray[1];
        *prevValz = accArray[2];
    }
    
    if (spikeX > 1){
        Serial.print(char('A'));
    }
     if (spikeY > 1){
        Serial.print(char('B'));
    }
     if (spikeZ > 1){
        Serial.print(char('C'));
    }
    
    
}

Hi @Kevinruder

This allocates three pointers to float values, but no storage in RAM to hold float values.

3 Likes

ahhh ok - don’t use pointers is the lesson i guess ?

Hi!
I am trying to use this accelerometer with code from https://github.com/codebendercc/sketchfinder2/tree/master/test_sketchbooks/nate-sparkfun/Test/SpeedBagCounter .
I have changed MMA8452_ADDRESS to 0x1C and grounded my SA0 pin
But I get the mesage ‘Could not connect to MMA8452Q’ on serial. When I am printing the value of c, Serial.println(c, HEX); the who_am_i register, it prints FF.
I have placed 4.7k pull-ups in SCL and SDA line (and tested without them as well).
The photos of breakout board of MMA are attached with this. I am not able to find any resources to determine whether the board has got pull-ups or not, or any other info.

Have a try with this I2C address scanner if your address really is correct.
How to detect bh1750 light sensor not connected device or something wrong?)(solved)

And how have you powered the board.
If it’s powerd off 5V you might need pull-up to 5V too. But looking at the blurry image, I’d say near the SDA/SCL pins I can see two SMD resistors which might well be the pull-ups.

If you had a datasheet of that board that’d help.

1 Like

I have exactly the same problem! I am using an accelerometer (with headers, from SparkFun, that appear well soldered). I am using 330 ohm resistors, as per the instructions in the .ino file, and am powering the MM8452 from the 3V3 and ground.

When I flash the circuit (I have tried both the basic.ino and basicxyz.ino files) , it works for a bit and then I get the flashing green LED of doom.

Any ideas/suggestions/thoughts would be welcome!

I inadvertently ordered these without the headers for my students, so it sounds like if I tried to use them by just using jumper wires stuck in the holes, that I would be asking for problems. Does that seem right?

Yup, you are asking for trouble. You need to either solder the wires or solder some headers before you can do real testing. :wink:

Since I can’t even get mine (with the headers) to work, I’ll go ahead and just order the accelerometers with headers for my students. Maybe mine (with headers) is defective?

@mprogers, did you run the I2C address scanner app that @ScruffR posted above? This will help confirm the board is working and its address.

The 330ohm resistors are required only when using a 5V processor like the Uno:

330Ω Resistors – Assuming you’re using a 5V-based microcontroller

1 Like

I ran it, and it says “No I2C devices found”, even when I was pointing at it saying, “it’s right there!!”. :smile: Maybe I have the pins wrong? I am just naievely following the instructions in the MMA8452Q Basic.ino file (excluding the pull-up resistors, since I don’t need them):

Arduino --------------- MMA8452Q Breakout
3.3V --------------- 3.3V
GND --------------- GND
SDA (A4) --/330 Ohm/-- SDA
SCL (A5) --/330 Ohm/-- SCL

Cheers,

Michael

@mprogers, assuming you are using a Photon, SDA is pin D0 and SCL is pin D1.

https://docs.particle.io/datasheets/photon-datasheet/

2 Likes

Oops … I will try this again tonight, thank you!

2 Likes

The accelerometer works a whole lot better now, thank you! And as a warning for those who follow in my footsteps, the comments in the MMA8452Q-Basic.ino file does not apply to Photons.

1 Like