I am working on a library for the MMA7660 accelerometer using I2C. I’ve got most of the basics working, but it will only read from the first register, I can read multiple bytes and it works though. Attached is my code, the relevent section is at the very bottom. I changed it from accepting an address to a hard coded address to see if that would help, but no luck. Oh also this is being written using the 1.0 IDE.
#include <Arduino.h>
#include <Wire.h>
#include "MMA7660.h"
MMA7660::MMA7660()
{
Wire.begin();
}
void MMA7660::init(){
//set mode to standy to set sample rate
write(MODE_REG, 0x00);
write(INTSU_REG, 0x10);
write(SR_REG, 0x00); //120 samples and auto-sleep
write(MODE_REG, 0x01); //set mode to active
}
void MMA7660::setPowerMode(int mode){
}
void MMA7660::setSamples(int samples){
}
void MMA7660::enableTap(uint8_t axis){
}
void MMA7660::enableShake(uint8_t axis){
uint8_t initialSetting = read(INTSU_REG);
write(MODE_REG, 0x00);
write(INTSU_REG, initialSetting | axis);
write(MODE_REG, 0x01);
}
int MMA7660::readAxis(uint8_t axis){
uint8_t data = 0x40;
//check if the alert bit is set, if so re-read
while(data & 0x40){
data = read(axis);
}
//if it's a negative value convert the two's complement
if(data & 0x20){
data += 0xC0; //the register returns a 6 bit number, fix for uint8_t
data = ~data;
data++;
return (int)data * -1;
}
return (int)data;
}
void MMA7660::write(uint8_t REG_ADDRESS, uint8_t DATA){
Wire.beginTransmission(MMA7660_CTRL_ID);
Wire.write(REG_ADDRESS);
Wire.write(DATA);
Wire.endTransmission();
}
uint8_t MMA7660::read(uint8_t REG_ADDRESS){
Wire.beginTransmission(MMA7660_CTRL_ID);
//Wire.write(REG_ADDRESS); // register to read
Wire.write(0x04); // register to read
Wire.endTransmission();
Wire.requestFrom(MMA7660_CTRL_ID, 1); // read a byte
while(! Wire.available()){
delay(1);
}
return Wire.read();
}
So I read the data sheet a little more carefully and found that the register pointer is reset when it receives a stop condition over I2C. So I tried removing the wire.endTransmission() and adding another Wire.beginTransmission() before I do the Wire.requestFrom(MMA7660_CTRL_ID, 1). It's still resetting the pointer though, any hints? Here's the part from the datasheet:
MMA7660FC clears its internal register address pointer to register 0x00 when a STOP condition is detected, so a single byte write has no net effect because the register address given in this first and only byte is replaced by 0x00 at the STOP condition. The internal register address pointer is not, however, cleared on a repeated start condition. Use a single byte write followed by a repeated start to read back data from a register
I can get the information if I read all the registers at once and just grab the one I want, but it seems kind of wasteful. Here's the hack I'm using for now: