RobTillaart / AS5600

Arduino library for AS5600 magnetic rotation meter
MIT License
114 stars 23 forks source link

Intermittent 0 degree angle returned (wrong value) #44

Closed antoinec4 closed 1 year ago

antoinec4 commented 1 year ago

When using the as5600::rawAngle method, I sometimes receive a zero value intermittently, although the magnet position is not at zero. This happens every 30 or so reads, when probing around 2 times a second.

I'm using a teensy 4.1 and the as5600 board is connected via i2c. The cable length is about 1 foot, the supply voltage is a steady 3.3V and the dir pin is connected to GND.

I've read i2c on teensy 4.1 need external pull-ups, but I have been successful without using them before.

Anyone has thoughts on this ?

Thanks,

RobTillaart commented 1 year ago

Thanks for reporting this issue.

No clue yet, not seen it in my testing.

RobTillaart commented 1 year ago

I've read i2c on teensy 4.1 need external pull-ups, but I have been successful without using them before.

Still you should use them (4K7), see https://www.gammon.com.au/i2c why (I cannot explain it better than Nick does.)

This happens every 30 or so reads, when probing around 2 times a second.

Can you try to get exact timing? If the moments are equidistant in time, it might give a clue for the cause.

so far my thoughts?

Q: are there other things connected?

antoinec4 commented 1 year ago

Thanks for the quick reply.

As for now, the timing of the wrong reads is quite random. Yes there are other things connected, but I have an other exact setup working flawlessly.

Actually there are 2x as5600 encoders connected to my actual setup, one on i2c bus 1 and the other on the i2c bus 2, both having the similar problem, although the returned wrong values and not synchronized.

I checked my supplied voltage to the boards and it is withing range and it's not fluctuating.

Also, the teensy 4.1 isn't 5V tolerant on IO. Should I put a 4.7K pull-up between VCC (5V) or 3.3V ? Should the resistor value be different ?

Thanks,

RobTillaart commented 1 year ago

Should I put a 4.7K pull-up between VCC (5V) or 3.3V ? Should the resistor value be different ?

3V3 should be OK, 4k7 is the one I would try first normally on I2C, you can use even a 1K resistor (will draw additional current).

The low level I2C reading sets an _error variable. It is not accessible (yet) in the library.

You could add a function int lastError() { return _error; } in the .h file and check if there is an I2C problem with the I2C read if the raw value returned == 0.

alternative is to (temporary) patch in the as5600.cpp

uint8_t AS5600::readReg(uint8_t reg)
{
  _wire->beginTransmission(_address);
  _wire->write(reg);
  _error = _wire->endTransmission();
  if (_error != 0) Serial.println(_error);  //  <<<<<<<<<<<<<<

  _wire->requestFrom(_address, (uint8_t)1);
  uint8_t _data = _wire->read();
  return _data;
}

uint16_t AS5600::readReg2(uint8_t reg)
{
  _wire->beginTransmission(_address);
  _wire->write(reg);
  _error = _wire->endTransmission();
  if (_error != 0) Serial.println(_error);  //  <<<<<<<<<<<<<<

  _wire->requestFrom(_address, (uint8_t)2);
  uint16_t _data = _wire->read();
  _data <<= 8;
  _data += _wire->read();
  return _data;
}
RobTillaart commented 1 year ago

As the error can also occur in the fetching you could patch that too

uint8_t AS5600::readReg(uint8_t reg)
{
  _wire->beginTransmission(_address);
  _wire->write(reg);
  _error = _wire->endTransmission();
  if (_error != 0) Serial.println(_error);  //  <<<<<<<<<<<<<<

  if (_wire->requestFrom(_address, (uint8_t)1)  != 1) Serial.println("TIK");
  uint8_t _data = _wire->read();
  return _data;
}

uint16_t AS5600::readReg2(uint8_t reg)
{
  _wire->beginTransmission(_address);
  _wire->write(reg);
  _error = _wire->endTransmission();
  if (_error != 0) Serial.println(_error);  //  <<<<<<<<<<<<<<

  if (_wire->requestFrom(_address, (uint8_t)2)  != 2) Serial.println("TOK");
  uint16_t _data = _wire->read();
  _data <<= 8;
  _data += _wire->read();
  return _data;
}

just using these silly prints only to see if there is a low level I2C problem.

antoinec4 commented 1 year ago

I finally added two 5k resistors between 3.3V and SCL/SDA respectively. It now works flawlessly.

Thank you for the help provided and the library,