MMA8452Q Accelerometer - Getting I2C To Work With It
Mahonroy
Posts: 175
in Propeller 1
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:
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
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
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.
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?)
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.
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.