Shop OBEX P1 Docs P2 Docs Learn Events
MMA8452Q Accelerometer - Getting I2C To Work With It — Parallax Forums

MMA8452Q Accelerometer - Getting I2C To Work With It

Hey guys,
I am playing around with a MMA8452Q accelerometer from sparkfun, and trying to get the I2C to work with it. I'm looking through arduino libraries, and misc. I2C libraries in the object exchange to piece something together. I am under the impression there is not a working library for this yet?

My first step is just to read the "WHO_AM_I" register of "$0D" just to see if I have this thing working.

I'm slightly confused because the documentation says the addresses are 7 bits, followed by another bit which tells the slave if its going to be receiving or sending.

So in an attempt, I snagged the "pasm_i2c_driver", and tried this out... which obviously doesn't work haha:
CON
        _clkmode = xtal1 + pll16x                                               'Standard clock mode * crystal frequency = 80 MHz
        _xinfreq = 5_000_000

  '////////////////////////////////////////////////////////////////////////////
  '///    Pin assignments
  '////////////////////////////////////////////////////////////////////////////

  ACCEL_SCL_PIN = 17


  '////////////////////////////////////////////////////////////////////////////
  '///    Accelerometer Registers
  '////////////////////////////////////////////////////////////////////////////
  
  STATUS_MMA8452Q = $00
  OUT_X_MSB = $01
  OUT_X_LSB = $02
  OUT_Y_MSB = $03
  OUT_Y_LSB = $04
  OUT_Z_MSB = $05
  OUT_Z_LSB = $06
  SYSMOD = $0B
  INT_SOURCE = $0C
  WHO_AM_I = $0D
  XYZ_DATA_CFG = $0E
  HP_FILTER_CUTOFF = $0F
  PL_STATUS = $10
  PL_CFG = $11
  PL_COUNT = $12
  PL_BF_ZCOMP = $13
  P_L_THS_REG = $14
  FF_MT_CFG = $15
  FF_MT_SRC = $16
  FF_MT_THS = $17
  FF_MT_COUNT = $18
  TRANSIENT_CFG = $1D
  TRANSIENT_SRC = $1E
  TRANSIENT_THS = $1F
  TRANSIENT_COUNT = $20
  PULSE_CFG = $21
  PULSE_SRC = $22
  PULSE_THSX = $23
  PULSE_THSY = $24
  PULSE_THSZ = $25
  PULSE_TMLT = $26
  PULSE_LTCY = $27
  PULSE_WIND = $28
  ASLP_COUNT = $29
  CTRL_REG1 = $2A
  CTRL_REG2 = $2B
  CTRL_REG3 = $2C
  CTRL_REG4 = $2D
  CTRL_REG5 = $2E
  OFF_X = $2F
  OFF_Y = $30
  OFF_Z = $31


  
  
OBJ
  PST     : "Parallax Serial Terminal"                    ''Used ONLY For DEBUGGING
  ACCEL   : "pasm_i2c_driver" 
  

VAR
  byte buffer
  byte address 

PUB Main
  PST.Start(115200)                                     'Used ONLY For DEBUGGING
  waitcnt(clkfreq / 2 + cnt)                            'Allow device time to power up fully
  PST.Clear

  PST.Str(string("Parallax Serial Terminal Initialized",13))

  ACCEL.Initialize(ACCEL_SCL_PIN)
  waitcnt(clkfreq + cnt)                            'Allow device time to power up fully
  PST.Str(string("I2C Initialized",13))

  buffer := ReadRegister(WHO_AM_I) 
  PST.Str(string("WHO_AM_I: "))
  PST.Hex(buffer,2)
  PST.Str(string(13))
  

  
PUB ReadRegister (reg) | registerResult
  ACCEL.Start(ACCEL_SCL_PIN)
  ACCEL.WRITE(ACCEL_SCL_PIN,$1D)
  ACCEL.WRITE(ACCEL_SCL_PIN,$0D) 'WHO_AM_I register
  ACCEL.Start(ACCEL_SCL_PIN)
  registerResult := ACCEL.Read(ACCEL_SCL_PIN,0)
  ACCEL.Stop(ACCEL_SCL_PIN)

  return registerResult


Once I get this simple test working, I plan on organizing it into a MMA84 object and push all the functionality into that. But It seems I am missing something? Any help is greatly appreciated, and if you can't tell, I am a noob with I2C.
-Matt

Comments

  • kwinnkwinn Posts: 8,697
    It is a 7 bit address but the explanation in the data sheet is a bit obtuse.
    Bits 7..2 are the factory programmed fixed address of the chip.
    Bit 1 is the least significant address bit, and is set by the logic level of pin 7 on the chip.
    Bit 0 is the R/W bit, 1 for read, 0 for write.

    All of the bits are sent sequentially starting with bit 7 so are typically set up as a single byte and sent MSB first.
  • I2C can be tricky at first, ensuring that it's wired properly is the first step. I've packaged a bunch of routines together here. Run the I2C poller and it'll display on the serial terminal the 7-bit address of every device on the bus.

    I've written my drivers to be as easy to use as possible. To read a register, all that's required is 'accel.readByte(device_ID,register_address)'. The start, r/w bit, restart, ack/nak, and stop are handled automatically.

    Unfortunately I don't have a demo for the MMA84; the registers are in different locations than they are in the MMA7455.
  • MahonroyMahonroy Posts: 175
    edited 2016-09-11 18:54
    ChrisGadd wrote: »
    I2C can be tricky at first, ensuring that it's wired properly is the first step. I've packaged a bunch of routines together here. Run the I2C poller and it'll display on the serial terminal the 7-bit address of every device on the bus.

    I've written my drivers to be as easy to use as possible. To read a register, all that's required is 'accel.readByte(device_ID,register_address)'. The start, r/w bit, restart, ack/nak, and stop are handled automatically.

    Unfortunately I don't have a demo for the MMA84; the registers are in different locations than they are in the MMA7455.

    Thanks for the code, I tried the poller and it finds the device $1D.
    I'm confused because when I then do a I2C.readByte($1D,$0D) it returns $2A. $0D is the WHO_AM_I register by the way. Shouldn't these IDs match since its the device id?

    EDIT:
    Ok it seems 1D is always the address, and the WHO_AM_I is a second address that is factory set to $2A, but can be changed if need be (I imagine if there are multiple sensors on the same I2C bus?)
  • Honestly I'm not sure what the purpose the whoami register serves, other than to verify comms. The chip has a SA0 pin that determines the lsb of the device ID - pulled low the address is $1C, high is $1D.
  • kwinnkwinn Posts: 8,697
    ChrisGadd wrote: »
    Honestly I'm not sure what the purpose the whoami register serves, other than to verify comms. The chip has a SA0 pin that determines the lsb of the device ID - pulled low the address is $1C, high is $1D.

    The whoami register is there for a bus with multiple types of chips. The master uses it to determine what chip it is and can then use the correct format to communicate with it.
  • kwinn wrote: »
    The whoami register is there for a bus with multiple types of chips. The master uses it to determine what chip it is and can then use the correct format to communicate with it.
    Interesting. My poller guesses at what each device is based on the device ID, which I only found by scouring datasheets, and even then the same ID is often used for wildly different chips. I suppose the whoami register might allow the poller to differentiate between a MMA8452Q, a MMA7455L, and an ADXL345, each a possible device at $1D, though the whoami register address for each is different: $0D for the 8452, $0F for the 7455, and $00 for the 345.
    Seems tricky to definitively identify a device; having to check multiply registers and hoping the whoami address for one chip doesn't contain the same value in another chip where that address is used for a different purpose. And that's if the chip even contains a whoami register, and it hasn't been changed from the default.

    Sorry for the sidetrack, Matt, glad to hear it's working.
  • kwinnkwinn Posts: 8,697
    ChrisGadd wrote: »
    kwinn wrote: »
    The whoami register is there for a bus with multiple types of chips. The master uses it to determine what chip it is and can then use the correct format to communicate with it.
    Interesting. My poller guesses at what each device is based on the device ID, which I only found by scouring datasheets, and even then the same ID is often used for wildly different chips. I suppose the whoami register might allow the poller to differentiate between a MMA8452Q, a MMA7455L, and an ADXL345, each a possible device at $1D, though the whoami register address for each is different: $0D for the 8452, $0F for the 7455, and $00 for the 345.
    Seems tricky to definitively identify a device; having to check multiply registers and hoping the whoami address for one chip doesn't contain the same value in another chip where that address is used for a different purpose. And that's if the chip even contains a whoami register, and it hasn't been changed from the default.

    Sorry for the sidetrack, Matt, glad to hear it's working.

    Unfortunately it seems that either there is no standard for identifying the chips, or if there is one it is not universally followed. That's too bad because identifying a chip's specific type would have some uses.
Sign In or Register to comment.