Netduino home hardware projects downloads community

Jump to content


Photo

I2C With Triple Axis Accelerometer - MMA8452Q

I2C MMA8452Q

Best Answer CW2, 26 December 2012 - 05:15 PM

The device requires I2C repeated start condition to access the registers, you'd need special I2C methods for that. Pass the register address as internalAddress parameter, internalAddressSize = 1 (i.e. replace write+read transaction with single CreateReadTransaction(data, 0x0D, 1) call, the write transaction to set the register address is issued internally).

Go to the full post


  • Please log in to reply
11 replies to this topic

#1 tma

tma

    Member

  • Members
  • PipPip
  • 12 posts

Posted 26 December 2012 - 05:05 PM

I have attached a Triple Axis Accelerometer Breakout - MMA8452Q from Sparkfun, https://www.sparkfun.../products/10955 to a Netduino board.
The physical connection seems to work, as well as writing and reading - the only problem, I cannot set the register to read from.

 

Following are some parts of the code I wrote:
 
[font="'courier new', courier, monospace;"] // Freescale MMA8452Q[/font]
[font="'courier new', courier, monospace;"]            I2CDevice.Configuration Conf = new I2CDevice.Configuration(0x1D, 50);[/font]
[font="'courier new', courier, monospace;"]            I2CDevice icD = new I2CDevice(Conf);[/font]
[font="'courier new', courier, monospace;"]            byte[] data = new byte[7];[/font]
 
[font="'courier new', courier, monospace;"] // Set Device Active  (This part works correctly)[/font]
[font="'courier new', courier, monospace;"]            I2CDevice.I2CTransaction[] writeTransaction = new I2CDevice.I2CTransaction[][/font]
[font="'courier new', courier, monospace;"]                {[/font]
[font="'courier new', courier, monospace;"]                    I2CDevice.CreateWriteTransaction(new byte[] {0x2A, 0x01})[/font]
[font="'courier new', courier, monospace;"]                };[/font]
[font="'courier new', courier, monospace;"]            int bytesWritten = icD.Execute(writeTransaction, 50);[/font]
 
[font="'courier new', courier, monospace;"]  // Try to read Device ID  (This part does not work correctly)[/font]
[font="'courier new', courier, monospace;"]            I2CDevice.I2CTransaction[] rwtransaction = new I2CDevice.I2CTransaction[2] [/font]
[font="'courier new', courier, monospace;"]                {[/font]
[font="'courier new', courier, monospace;"]                    I2CDevice.CreateWriteTransaction(new byte[1] { 0x0D }),[/font]
[font="'courier new', courier, monospace;"]                    I2CDevice.CreateReadTransaction(data)[/font]
[font="'courier new', courier, monospace;"]                 };[/font]
[font="'courier new', courier, monospace;"]            int bytesRead = icD.Execute(rwtransaction, 50);[/font]
[font="'courier new', courier, monospace;"]            Debug.Print(ByteToInt(data[0]).ToString());[/font]
 
It seems that the read register is not set to 0x0D, but that it is set to 0X00, hence the byte array "data" contains the content of the registers starting at 0X00.
 
Has anybody made the same experiences and found a way how to address this?
 
Thanks


#2 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 26 December 2012 - 05:15 PM   Best Answer

The device requires I2C repeated start condition to access the registers, you'd need special I2C methods for that. Pass the register address as internalAddress parameter, internalAddressSize = 1 (i.e. replace write+read transaction with single CreateReadTransaction(data, 0x0D, 1) call, the write transaction to set the register address is issued internally).


  • tma likes this

#3 tma

tma

    Member

  • Members
  • PipPip
  • 12 posts

Posted 26 December 2012 - 09:00 PM

CW2, thanks very much for the quick response, I very much appreciate. 

I have tried this before, but did not succeed to get it running, I always get a Null Value for fieldInfo:

 

 

[font="'courier new', courier, monospace;"] public class Program[/font]
[font="'courier new', courier, monospace;"]    {[/font]
[font="'courier new', courier, monospace;"]    public static I2CDevice.I2CReadTransaction CreateReadTransaction(byte[] buffer, uint internalAddress, byte internalAddressSize)[/font]
[font="'courier new', courier, monospace;"]        {[/font]
[font="'courier new', courier, monospace;"]            I2CDevice.I2CReadTransaction readTransaction = I2CDevice.CreateReadTransaction(buffer);[/font]
[font="'courier new', courier, monospace;"]            Type readTransactionType = typeof(I2CDevice.I2CReadTransaction);[/font]
 
[font="'courier new', courier, monospace;"]            FieldInfo [color=#ff0000;]fieldInfo[/color] = readTransactionType.GetField("Custom_InternalAddress", BindingFlags.NonPublic | BindingFlags.Instance);[/font]
[font="'courier new', courier, monospace;"]            fieldInfo.SetValue(readTransaction, internalAddress);[/font]
 
[font="'courier new', courier, monospace;"]            fieldInfo = readTransactionType.GetField("Custom_InternalAddressSize", BindingFlags.NonPublic | BindingFlags.Instance);[/font]
[font="'courier new', courier, monospace;"]            fieldInfo.SetValue(readTransaction, internalAddressSize);[/font]
 
[font="'courier new', courier, monospace;"]            return readTransaction;[/font]
[font="'courier new', courier, monospace;"]        }[/font]
[font="'courier new', courier, monospace;"]       [/font]
 
[font="'courier new', courier, monospace;"]     public static  void Main()[/font]
[font="'courier new', courier, monospace;"]        {[/font]
[font="'courier new', courier, monospace;"]            I2CDevice.Configuration Conf = new I2CDevice.Configuration(0x1D, 50);[/font]
[font="'courier new', courier, monospace;"]            I2CDevice icD = new I2CDevice(Conf);[/font]
 
[font="'courier new', courier, monospace;"]            byte[] data = new byte[7];[/font]
[font="'courier new', courier, monospace;"]            I2CDevice.I2CTransaction[] rwtransaction = new I2CDevice.I2CTransaction[] [/font]
[font="'courier new', courier, monospace;"]            {CreateReadTransaction(data, 0x0D, 1)};[/font]
[font="'courier new', courier, monospace;"]            int bytesRead = icD.Execute(rwtransaction, 50);[/font]
[font="'courier new', courier, monospace;"]         }[/font]
[font="'courier new', courier, monospace;"]     }[/font]
 
I guess I must do something wrong...


#4 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 26 December 2012 - 09:30 PM

What is the version of the firmware you have on your Netduino?



#5 tma

tma

    Member

  • Members
  • PipPip
  • 12 posts

Posted 26 December 2012 - 09:50 PM

I may have an older version:  4.1.0.6, may this be the issue?

 


#6 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 26 December 2012 - 10:02 PM

Yes, this feature is not available in 4.1.0.6, it was introduced in 4.1.1. I would recommend upgrading to the latest 4.2.0 version; alternatively you could get 4.1.1 beta 1 for a quick test.



#7 tma

tma

    Member

  • Members
  • PipPip
  • 12 posts

Posted 26 December 2012 - 10:13 PM

Thanks so much for your education - it will take me a while to update the firmware - it will be the first time for me doing it.  I will keep you posted.



#8 tma

tma

    Member

  • Members
  • PipPip
  • 12 posts

Posted 28 December 2012 - 07:23 AM

CW2, I have updated the Firmware to 4.2 and used the recommended way to address the I2C registers in read mode - and it works like a charm! Thanks very much for your great help - Happy New Year!



#9 cmelk75

cmelk75

    New Member

  • Members
  • Pip
  • 1 posts

Posted 10 May 2013 - 09:07 AM

Hi TMA and all,
I saw that this thread is quite old, anyway I hope someone can help me
I'm trying to use MMA8452 too, but still without results, I cannot write or read any data by I2C connection... can you please give me some example how to read axis values with Netduino 2 plus...
I've tryed to follow even I2C read/write suggestion, but with 4.2.2 firmware it doesn't works, "I2CDevice.I2CWriteTransaction" has no "Custom_InternalAddress" and "Custom_InternalAddressSize" fields...
 
I used another I2C device, a temperature sensor, and everythign gone well...
 
Thank you

 



#10 tma

tma

    Member

  • Members
  • PipPip
  • 12 posts

Posted 17 May 2013 - 11:24 PM

cmelk75, sorry, I have not noticed your question earlier.

But it happens that I am trying to port my application to a Netduino 2 - and I cannot get it work.

There are various threads about problems with I2C on Netdiuino 2.

So far I have tried:

- Decrease the value of the pull-up resistors to 1k

- Upgrade firmware to 4.2.2.2

Neither has helped :-(



#11 tma

tma

    Member

  • Members
  • PipPip
  • 12 posts

Posted 19 May 2013 - 02:29 PM

OK, I got it working on the Netduino 2:

It seems that the repeated start bit is handled in the Netduino 2, hence the [color=rgb(90,90,90);font-family:helvetica, arial, sans-serif;font-size:13px;background-color:rgb(234,248,226);] [/color]special I2C methods (which seem not to work with the Netduino 2) are not required for the Netduino 2.

 

Hence, you can use the code that I have originally posted - it does work for me - I can now read all the registers correctly.

Something like the code below should work for reading x, y and z position to an accuracy of one byte, only using the MSB registers. If you need higher resolution you will also need to consider the LSB registers. 

 

 

[color=#008000;][font="'courier new', courier, monospace;"]         // Version for Netduino 2[/color][/font]
[font="'courier new', courier, monospace;"]         int[]  Position = new int[3];[/font]

[font="'courier new', courier, monospace;"]         byte[] data = new byte[7];[/font]

 

[font="'courier new', courier, monospace;"]         I2CDevice.I2CTransaction[] rwtransaction = new I2CDevice.I2CTransaction[2] [/font]
[font="'courier new', courier, monospace;"]         {[/font]
[font="'courier new', courier, monospace;"]            I2CDevice.CreateWriteTransaction(new byte[1] { 0x00 }), [/font]
[font="'courier new', courier, monospace;"]            I2CDevice.CreateReadTransaction(data)[/font]
[font="'courier new', courier, monospace;"]         };[/font]
[font="'courier new', courier, monospace;"] [/font][font="'courier new', courier, monospace;"]       int bytesRead = icDevice.Execute(rwtransaction, 50);[/font]
[font="'courier new', courier, monospace;"]         Position[0] = (int)(sbyte)[/font][font="'courier new', courier, monospace;"]data[1];[/font]
[font="'courier new', courier, monospace;"]         Position[1] = [/font][font="'courier new', courier, monospace;"](int)(sbyte)[/font][font="'courier new', courier, monospace;"]data[3];[/font]
[font="'courier new', courier, monospace;"]         Position[2] = [/font][font="'courier new', courier, monospace;"](int)(sbyte)[/font][font="'courier new', courier, monospace;"]data[5];[/font]


#12 tmcginty

tmcginty

    New Member

  • Members
  • Pip
  • 1 posts

Posted 21 June 2013 - 01:51 AM

Thanks tma, this bounding by a single transaction got me working (almost) with the MMA8452 from Sparkfun on the Netduino plus 2 as well. For those facing the issue of only receiving 255 as the result of reading the WHO_AMI_I register, the above code for the I2CDevice.I2Trasaction[] { ... } is the answer.

 

One point I note though is I am reading back 1 byte more that the read buffer can hold. Buffer is 1 byte in length, Execute() returns 2, second byte is a 0. Obviously my send matching can subtract 1 from the result :).

 

What clock speed (Khz) value are you initializing your device with?

 

Tony.







0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.