2

I'm trying to write a library for an accelerometer/magnetometer sensor. The sensor is a LSM303D chip (https://www.pololu.com/file/0J703/LSM303D.pdf).

I've written a function, readRegister() (below) that's supposed to get the data from the sensor. However, I put in many different registers into the function into the function, but it always returns the same number. That number changes every time I unplug my Arduino from my computer.

byte fp::readRegister(byte register_address, int numBytes) {
  Wire.requestFrom(register_address, numBytes);
  byte c;
  Serial.println(Wire.read());
  while (Wire.available()) {
    c = Wire.read();
  }
  Serial.print("0x");
  Serial.print(register_address, HEX);
  Serial.print("\t");
  Serial.print(c);
  Serial.print("\t");
  Serial.println(millis());
  return c;
}

Here's an example of the problem output:

0x8 190 2 
0x9 190 3
0xA 190 11

And here is something more like what I'd expect:

0x8 193 [time]
0x9 189 [time]
0xA 195 [time]

Here is the Git repo with the rest of the code: https://github.com/fpdotmonkey/fp_accel

Thank you in advance for your help.

  • Could you show the rest of the code? Is there a Write.endTransmission()? – Gerben Sep 8 '15 at 9:12
1
  Wire.requestFrom(register_address, numBytes);
  byte c;
  Serial.println(Wire.read());
  while (Wire.available()) {
    c = Wire.read();
  }

This has a number of problems. For one thing your (I presume) debugging print consumes the data from Wire.read, so when you go to get it into c, you have already printed it. In other words, you are reading byte #1 and printing it, but using byte #2. This seems an odd thing to do.

Next, what is this doing?

  while (Wire.available()) {
    c = Wire.read();
  }

You are reading an indefinite number of bytes, and retaining the last one. Why?

Possible rework:

byte fp::readRegister(byte register_address, int numBytes) {
  Wire.requestFrom(register_address, numBytes);
  byte c = Wire.read()
  Serial.println(c);
  Serial.print("0x");
  Serial.print(register_address, HEX);
  Serial.print("\t");
  Serial.print(c);
  Serial.print("\t");
  Serial.println(millis());
  return c;
}

Here is the Git repo with the rest of the code: https://github.com/fpdotmonkey/fp_accel

From your linked code:

  byte xlm = readRegister(fp::OUT_X_L_M, 1);
  byte xhm = readRegister(fp::OUT_X_H_M, 1);
  byte ylm = readRegister(fp::OUT_Y_L_M, 1);
  byte yhm = readRegister(fp::OUT_Y_H_M, 1);
  byte zlm = readRegister(fp::OUT_Z_L_M, 1);
  byte zhm = readRegister(fp::OUT_Z_H_M, 1);

You have the wrong end of the stick here.

  Wire.requestFrom(register_address, numBytes);

You request from the I2C address - that is the device address. The register is something else.

Judging by the datasheet you first have to send the register address, and then request the data. Something along the lines of:

byte fp::readRegister(byte register_address, int numBytes) {
  Wire.beginTransmission (DEVICE_ADDRESS);
  Wire.write (register_address);
  Wire.endTransmission (false);  // repeated start
  Wire.requestFrom(DEVICE_ADDRESS, 1);
  byte c = Wire.read()
  Serial.println(c);
  Serial.print("0x");
  Serial.print(register_address, HEX);
  Serial.print("\t");
  Serial.print(c);
  Serial.print("\t");
  Serial.println(millis());
  return c;
}

Similarly for writing to a register:

void fp::writeRegister(byte register_address, byte val) {
  Wire.beginTransmission(DEVICE_ADDRESS);
  Wire.write (register_address);
  Wire.write(val);
  Wire.endTransmission();
}

This is untested because I don't have the device here, but I know that what you had won't work. To check the actual device address run the I2C scanner I mentioned before.

  • I'm still experiencing the same problem. Every register address I plug in returns the same value. – fp.monkey Sep 8 '15 at 21:25
  • It would help to see the whole sketch and not just a function being called in an unknown way. It would also help to see your improved code. Are you sure you are communicating with the device? Can you do a WHO_AM_I and get back the right response? It's hard to debug a snippet. – Nick Gammon Sep 8 '15 at 21:32
  • Also confirm you have the right device address, and it is connected correctly. There is code to do that on my page about I2C - scroll down to the "I2C scanner". – Nick Gammon Sep 8 '15 at 21:33
  • My codebase, as well as the improved function, are in the Github link that is now in the original question. When I try to read from WHO_AM_I, I get the same response as from every other register. – fp.monkey Sep 9 '15 at 7:01
  • Well, see my amended reply. That is not how you access registers. – Nick Gammon Sep 9 '15 at 7:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.