SPI communication with MXP7205VW Accelerometer help!!! code inside

I am using Arduino, a Mega 2560, and a MXP7205VW Dual-Axis Accelerometer from Memsic running on SPI communication.

Data Sheet for the MXP7205VW - http://www.memsic.com/userfiles/files/Datasheets/Accelerometer-Datasheets/mxp7205vw_rev_c.pdf

My issue with the communication stems from the datasheet not having a hex register map.

Example code to show what I mean by hex register - super dumbed down to save space.

char DATAX0 = 0x32              //This is the hex address for X-Axis Data 0
                                //Now I can use this address to transfer data over the SPI lines
SPI.transfer(DATAX0)           //Transfers the register address over SPI

This much I understand and have gotten to work in the past with different hardware (not the MXP chip), my issue now is that I am given a 16-bit protocol for reading the accelerometer output registers and I do not know how to handle it. I have googled and googled and right now am extremely frustrated and my guess is, it is a really really simple answer that I, for some reason, have not been able to grasp.

This is the 16 bit protocol

MSB LSB
15 0
[SQ1][SQ0][SEN][SQ2][-][-][-][-][-][-][-][-][LC3][LC2][LC1][LC0]

SQ1, SQ0, SQ2, LC3, and LC2 are all marked with - via a table in the data sheet, so from what I understand is it does not matter what binary value is there, so I used 0. All I am looking at is the binary value of SEN (determines if the Master is reading from the x and y/z channel or the MXP7205VW 8-bit control register), LC1 and LC0 (determines if from what x or y/z channels I am reading from).

SEN = 1 - Reading from the x and y/z channels
SEN = 0 - Reading from the MXP7205VW 8-bit control register
LC1 = 0, LC0 = 0, Reading from the Accelerometer output LSB register, x channel
LC1 = 0, LC0 = 1, Reading from the Accelerometer output LSB register, y/z channel
LC1=1, LC0 = 0, Reading from the Accelerometer output MSB register, x channel
LC1 = 1, LC0 = 1, Reading from the Accelerometer output MSB register, y/z channel

Based on this data I came to the conclusion that the Hex register address for the LSB X channel would be 0x2000, so when trying to write to that address using SPI I am using this code

digitalWrite(10, LOW) //Tells the SPI SS that I am wanting to communicate with the MXP7205VW chip
SPI.transfer(0x20);
SPI.transfer(0x00); //This is (hopefully?) the correct address for the LSB x channel
byte LSB = SPI.transfer(0xFF); //From what I understand this retrieves the current LSB X value
SPI.transfer(0x20);
SPI.transfer(0x02); //This is (hopefully?) the correct address for the MSB x channel
byte MSB = SPI.transfer(0xFF); //Retrieves the current MSB X value

                           //From what the data sheet says MSB contains the first 10 most significant bits
                          //and the LSB contains the 4 least significant bits followed by 6 0s, now combined
                          //this gives me the desired 14-bit output that contains the X channel data

x = ((MSB << 8) | LSB); //This combines MSB and LSB to get the data I want

Now according to what I understand this should work and I should be able to send the X value to Serial so I can read it, but all I get is 0s, however if you wave the board around sometimes, I repeat sometimes, I get a value like 250 or -1, or 7560. This seems random to me and most of the time when I am moving the accelerometer I get the value of 0. I am assuming its because I am not addressing the correct registers and am getting bogus data? Any help would make me so happy as I have stupidly been stuck with the issue for a while.

Here is my entire code that I am using. I am not very experienced so I'm sure it will make you cringe, sorry about that 8)

#include <SPI.h>  //Add the SPI library so we can communicate with the MXP7205VW

long x; //Holds the value for the current X position
long yz; //Holds the value for the current Y/Z position


int CS = 10; //Assigns the Chop Select signal to pin 10

byte MSB; //Assigns MSB to hold the byte value of the MSB data for the selected address (e.g. MSB x channel)
byte LSB; //Assigns LSB to hold the byte value of the LSB data for the selected address (e.g. LSB y/z channel)

int LED = 38; //Assigns the pin for the sign of life LED

void setup() {
  // put your setup code here, to run once:
  pinMode(LED, OUTPUT); //Sets the LED pin to an Output
  digitalWrite(LED, LOW); //Turns on the LED so we know the board is on and alive

  Serial2.begin(19200); //Start RS232 serial communication with my computer

  SPI.begin(); //Initiate an SPI communication instance
  SPI.setDataMode(SPI_MODE0); //Configure the SPI connection for the MXP7205VW

  pinMode(CS, OUTPUT); //Sets the Chip Select Pin to be an Output
  digitalWrite(CS, HIGH); //Before communication stats, the Chip Select pin needs to be set high

}

void loop() {
  // put your main code here, to run repeatedly:
digitalWrite(10, LOW); //Tells the SPI SS that I am wanting to communicate with the MXP7205VW chip
SPI.transfer(0x20);
SPI.transfer(0x00); //Sends the address for the LSB x channel
LSB = SPI.transfer(0xFF); //Retrieves the current LSB X value
SPI.transfer(0x20); 
SPI.transfer(0x02); //Sends the address for the MSB x channel
MSB = SPI.transfer(0xFF); //Retrieves the current MSB x value
x = ((MSB << 8) | LSB); //Combines MSB and LSB to get the correct x data I want
SPI.transfer(0x20);
SPI.transfer(0x01); //Sends the address for the LSB y/z channel
LSB = SPI.transfer(0xFF); //Retrieves the current LSB y/z value
SPI.transfer(0x20);
SPI.transfer(0x03); //Sends the address for the MSB y/z channel
MSB = SPI.transfer(0xFF); //Retrieves the current LSB y/z channe;
yz = ((MSB << 8) | LSB); //Combines MSB and LSB to get the correct y/z data I want
digitalWrite(10, HIGH); //Tells the SPI ss that I am done communicating to the MXP7205VW chip

Serial2.print("MSBx value is: "); //Prints out the values to my computer 
Serial2.println(x);
Serial2.print("LSByz value is: ");
Serial2.println(yz);
Serial2.println("     ");
Serial2.println("     ");

delay(500); //Half second delay

}

Thanks for looking over my issue and for any help given!!!

Chad Thomas

From reading the datasheet of the MXP7205, it would be much easier to work in word or int format as this is a 16bit sensor. This is how the protocol should work.
To read sensor data:

  1. Pull SS low
  2. Send a word request. You can use SPI.transfer16(). For example SPI.transfer16(0x2002) to get X MSB.
  3. Pull SS high to tell the sensor to prepare for a response. This is the key!!
  4. Pull SS low to prepare for read.
  5. Send a word request to read the sensor data, for example Data = SPI.transfer16(0xFFFF);
  6. Pull SS high to end SPI communication.

Once you get the MSB and LSB from, say from X axis data, you would do this:

  1. shift MSB << 4 and & with 0x3FF0
  2. perform an & between LSB and 0x000F.
  3. perform an | (or) between MSB and LSB.
  4. Check the resulting value and convert to a signed value as necessary.

Now repeat for the other axis.

for 14 bit format, you should get around 800 for 1g reading, and -800 if you flip the sensor 180 deg.

Hope this helps.