Pages: [1]   Go Down
Author Topic: Need help with SPI + accelerometer  (Read 1247 times)
0 Members and 1 Guest are viewing this topic.
Buenos Aires, Argentina
Offline Offline
Newbie
*
Karma: 0
Posts: 18
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, I´m working in a project. and I´m trying to use a freescale MMA7455l accelerometer that I´ve got. I´m using a code for the ADXL345 accelerometer from http://www.sparkfun.com/tutorials/240 to test my accelelrometer. I already chance some of the registers adresses with the ones on the MMA7455L datasheet.

http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MMA745xL&tab=Documentation_Tab&linkline=Data%20Sheets&fpsp=1.

CODE QUESTION? - this appear in the code...

//Since we're performing a read operation, the most significant bit of the register address should be set.
  char address = 0x80 | registerAddress;
  //If we're doing a multi-byte read, bit 6 needs to be set as well.
  if(numBytes > 1)address = address | 0x40;


I know that this lines correspond to the ADXL345 accelerometer datasheet, but don´t know the equivalent for the MMA7455L. I Don´t undestand what this lines are for and if I need to use it for my accelerometer.

First time trying with an accelerometer, not quite easy at first. Any help, tips or docs will be appreciate.


Thanks in advance
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 212
Posts: 8952
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Read page 18 of the datasheet. 

To write a register:

digitalWrite(SlaveSelectPin, LOW);
SPI.transfer(0x80 | (registerAddress << 1));
SPI.transfer(dataValueToBeWritten);
digitalWrite(SlaveSelectPin, HIGH);


To read a register:

digitalWrite(SlaveSelectPin, LOW);
SPI.transfer(registerAddress << 1);
result = SPI.transfer(0);
digitalWrite(SlaveSelectPin, HIGH);

The SPI interface on that device doesn't seem to support multi-byte reads.
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Buenos Aires, Argentina
Offline Offline
Newbie
*
Karma: 0
Posts: 18
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

john, thanks for the reply

I read the page 18 of the datasheet, but I´m still confuse. this is what I got, but I´m still not getting any result. I´m not sure where is the problem.

Code:
#include <SPI.h>

//Assign the Chip Select signal to pin 10.
int CS=10;

//These variables will be used to hold the x,y and z axis accelerometer values.
int x,y,z;

//This is a list of some of the registers available on the MMA7455L.
char DATAX0 = 0x00; //X-Axis Data 0
char DATAX1 = 0x01; //X-Axis Data 1
char DATAY0 = 0x02; //Y-Axis Data 0
char DATAY1 = 0x03; //Y-Axis Data 1
char DATAZ0 = 0x04; //Z-Axis Data 0
char DATAZ1 = 0x05; //Z-Axis Data 1


void setup(){
 
  //Initiate an SPI communication instance.
  SPI.begin();
  //Configure the SPI connection.
  digitalWrite(0x15, 0x05); //to set the accelerometer into SPI 4 wire mode 2g measurement mode.
  digitalRead(0x16);  //Read the Control Register $16 to ensure that the value is correct (0x05).
 
  //Create a serial connection to display the data on the terminal.
  Serial.begin(9600);
 
  //Set up the Chip Select pin to be an output from the Arduino.
  pinMode(CS, OUTPUT);
  //Before communication starts, the Chip Select pin needs to be set high.
  digitalWrite(CS, HIGH);
 
}

void loop(){ 
 
  //Print the results to the terminal.
  Serial.print(x, DEC);
  Serial.print(',');
  Serial.print(y, DEC);
  Serial.print(',');
  Serial.println(z, DEC);     
  delay(10);
}
// To write a register:
  void writeRegister(char registerAddress, char value){
     
digitalWrite(CS, LOW);
SPI.transfer(0x80 | (registerAddress << 1));
SPI.transfer(value);
digitalWrite(CS, HIGH);
}

  //To read a register:
void readRegister(char registerAddress, int numBytes, char * values){
    //Since we're performing a read operation, the most significant bit of the register address should be set.
char address = 0x80 | registerAddress;

digitalWrite(CS, LOW);
SPI.transfer(registerAddress << 1);
for(int i=0; i<numBytes; i++){
values[i] = SPI.transfer(0);
}
digitalWrite(CS, HIGH);
}

I´m trying to get this working for a while (I´m not a pro) and is getting annoying.

any help will be great.
 
 
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 212
Posts: 8952
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  digitalWrite(0x15, 0x05); //to set the accelerometer into SPI 4 wire mode 2g measurement mode.
  digitalRead(0x16);  //Read the Control Register $16 to ensure that the value is correct (0x05).

Those are probably not doing what you think they are doing.  smiley

digitalWrite and digitalRead will set an Arduino pin HIGH or LOW.

0x15 is a decimal value of 21 and your basic Arduino doesn't have a Pin 21.

I suspect you are trying to set a register but you will need SPI transfers for that.

In your accelerometer, register 0x15 is the upper three bits of the "Offset drift Z value" and has nothing to do with an "SPI mode".
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 212
Posts: 8952
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Your results don't change because you have no code in loop() to change x, y, or z.  You just send them out, wait 10 milliseconds, and repeat.  You probably want to read the data registers from the accelerometer to get values for X, Y and Z.  You can just read the 8-bit values to start (registers 0x07, 0x08, and 0x09).  Once that works you can try reading the 10-bit versions: 0x00/0x01, 0x02/0x03, 0x04/0x05.
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Buenos Aires, Argentina
Offline Offline
Newbie
*
Karma: 0
Posts: 18
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Those are probably not doing what you think they are doing.  smiley

digitalWrite and digitalRead will set an Arduino pin HIGH or LOW.

0x15 is a decimal value of 21 and your basic Arduino doesn't have a Pin 21.

I suspect you are trying to set a register but you will need SPI transfers for that.

In your accelerometer, register 0x15 is the upper three bits of the "Offset drift Z value" and has nothing to do with an "SPI mode".

You right, about digitalWrite and 0x15, nothing to do with what I want.

Your results don't change because you have no code in loop() to change x, y, or z.  You just send them out, wait 10 milliseconds, and repeat.  You probably want to read the data registers from the accelerometer to get values for X, Y and Z.  You can just read the 8-bit values to start (registers 0x07, 0x08, and 0x09).  Once that works you can try reading the 10-bit versions: 0x00/0x01, 0x02/0x03, 0x04/0x05.

I added a code for the loop, still not working, but no quick sure why. Is the loop code the bug or are there more bugs in the rest?

Code:
//Add the SPI library so we can communicate with the MMA7455L sensor
#include <SPI.h>

//Assign the Chip Select signal to pin 10.
int CS=10;

//This buffer will hold values read from the MMA7455L registers.
char values[6];
//These variables will be used to hold the x,y and z axis accelerometer values.
int x,y,z;

//This is a list of some of the registers available on the MMA7455L.
char DATAX0 = 0x00; //X-Axis 10 bits output Data LSB
char DATAX1 = 0x01; //X-Axis 10 bits output Data MSB
char DATAY0 = 0x02; //Y-Axis 10 bits output Data LSB
char DATAY1 = 0x03; //Y-Axis 10 bits output Data MSB
char DATAZ0 = 0x04; //Z-Axis 10 bits output Data LSB
char DATAZ1 = 0x05; //Z-Axis 10 bits output Data MSB
char XOUT8  = 0x06;     //X-Axis 8 bits output Data
char YOUT8  = 0x07;     //Y-Axis 8 bits output Data
char ZOUT8  = 0x08;     //Z-Axis 8 bits output Data

void setup()
{
    //Initiate an SPI communication instance.
  SPI.begin();
   //Create a serial connection to display the data on the terminal.
  Serial.begin(9600);
   //Set up the Chip Select pin to be an output from the Arduino.
  pinMode(CS, OUTPUT);
   //Before communication starts, the Chip Select pin needs to be set high.
  digitalWrite(CS, HIGH);
 
  writeRegister(0x16, 0x01); //to set the accelerometer into 2g measurement mode.
}

void loop(){ 
 
  //The results of the read operation will get stored to the values[] buffer.
  readRegister(XOUT8, 3, values);

  //The X value is stored in values[6].
  x = ((int)values[6] << 1);
  //The Y value is stored in values[7].
  y = ((int)values[7] << 1);
  //The Z value is stored in values[8].
  z = ((int)values[8] << 1);
 
  //Print the results to the terminal.
  Serial.print(x, DEC);
  Serial.print(',');
  Serial.print(y, DEC);
  Serial.print(',');
  Serial.println(z, DEC);     
  delay(10);
 
 
}
// To write a register:
  void writeRegister(char registerAddress, char value){
     
digitalWrite(CS, LOW);
SPI.transfer(registerAddress << 1);
SPI.transfer(value);
digitalWrite(CS, HIGH);
}

  //To read a register:
void readRegister(char registerAddress, int numBytes, char * values){
    //Since we're performing a read operation, the most significant bit of the register address should be set.
char address = (0x80 | registerAddress << 1);

digitalWrite(CS, LOW);
SPI.transfer(address);
    //Continue to read registers until we've read the number specified, storing the results to the input buffer.
  for(int i=0; i<numBytes; i++){
    values[i] = SPI.transfer(0);
  }
digitalWrite(CS, HIGH);
}
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 212
Posts: 8952
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You are trying to do a multi-byte read on a device that does not support multi-byte reads.

You are doing four SPI transfers with the values:  XOUT8 (0x80 | (0x06 << 1)),  0, 0, and 0.

The first transfer will be used as the register address, which is good.
The data received during the next transfer is saves in values[0], also good.
That SHOULD be the end.  The CS line should be set HIGH to signal the end of the register read.

I don't know what it does with the other two transfers but you store any data returned in values[1] and values[2];

You then look for data in values[6] which you never set.  Not good.

Your readRegister() function should probably read ONE register and return the value.  Then you can write:
Code:
x = readRegister(XOUT8);
y = readRegister(YOUT8);
z = readRegister(ZOUT8);
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Pages: [1]   Go Up
Jump to: