Skip to content

Commit c28ad9d

Browse files
committed
fix for MagneticSensorI2C uses incorrect bit mask calculation #402402
1 parent 0611830 commit c28ad9d

File tree

2 files changed

+54
-71
lines changed

2 files changed

+54
-71
lines changed

src/sensors/MagneticSensorI2C.cpp

+43-56
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,32 @@ MagneticSensorI2CConfig_s AS5600_I2C = {
55
.chip_address = 0x36,
66
.bit_resolution = 12,
77
.angle_register = 0x0C,
8-
.data_start_bit = 11
8+
.msb_mask = 0x0F,
9+
.msb_shift = 8,
10+
.lsb_mask = 0xFF,
11+
.lsb_shift = 0
912
};
1013

1114
/** Typical configuration for the 12bit AMS AS5048 magnetic sensor over I2C interface */
1215
MagneticSensorI2CConfig_s AS5048_I2C = {
1316
.chip_address = 0x40, // highly configurable. if A1 and A2 are held low, this is probable value
1417
.bit_resolution = 14,
1518
.angle_register = 0xFE,
16-
.data_start_bit = 15
19+
.msb_mask = 0xFF,
20+
.msb_shift = 6,
21+
.lsb_mask = 0x3F,
22+
.lsb_shift = 0
1723
};
1824

1925
/** Typical configuration for the 12bit MT6701 magnetic sensor over I2C interface */
2026
MagneticSensorI2CConfig_s MT6701_I2C = {
2127
.chip_address = 0x06,
2228
.bit_resolution = 14,
2329
.angle_register = 0x03,
24-
.data_start_bit = 15
30+
.msb_mask = 0xFF,
31+
.msb_shift = 6,
32+
.lsb_mask = 0xFC,
33+
.lsb_shift = 2
2534
};
2635

2736

@@ -30,57 +39,49 @@ MagneticSensorI2CConfig_s MT6701_I2C = {
3039
// @param _bit_resolution bit resolution of the sensor
3140
// @param _angle_register_msb angle read register
3241
// @param _bits_used_msb number of used bits in msb
33-
MagneticSensorI2C::MagneticSensorI2C(uint8_t _chip_address, int _bit_resolution, uint8_t _angle_register_msb, int _bits_used_msb){
34-
// chip I2C address
35-
chip_address = _chip_address;
36-
// angle read register of the magnetic sensor
37-
angle_register_msb = _angle_register_msb;
38-
// register maximum value (counts per revolution)
42+
MagneticSensorI2C::MagneticSensorI2C(uint8_t _chip_address, int _bit_resolution, uint8_t _angle_register_msb, int _bits_used_msb, bool lsb_right_aligned){
43+
_conf.chip_address = _chip_address;
44+
_conf.bit_resolution = _bit_resolution;
45+
_conf.angle_register = _angle_register_msb;
46+
_conf.msb_mask = (uint8_t)( (1 << _bits_used_msb) - 1 );
47+
48+
uint8_t lsb_used = _bit_resolution - _bits_used_msb; // used bits in LSB
49+
_conf.lsb_mask = (uint8_t)( (1 << (lsb_used)) - 1 );
50+
if (!lsb_right_aligned)
51+
_conf.lsb_shift = 8-lsb_used;
52+
else
53+
_conf.lsb_shift = 0;
54+
_conf.msb_shift = lsb_used;
55+
3956
cpr = _powtwo(_bit_resolution);
4057

41-
// depending on the sensor architecture there are different combinations of
42-
// LSB and MSB register used bits
43-
// AS5600 uses 0..7 LSB and 8..11 MSB
44-
// AS5048 uses 0..5 LSB and 6..13 MSB
45-
// MT6701 uses 0..5 LSB and 9..15 MSB
46-
// used bits in LSB
47-
lsb_used = _bit_resolution - _bits_used_msb;
48-
// extraction masks
49-
lsb_mask = (uint8_t)( (2 << lsb_used) - 1 );
50-
msb_mask = (uint8_t)( (2 << _bits_used_msb) - 1 );
5158
wire = &Wire;
5259
}
5360

54-
MagneticSensorI2C::MagneticSensorI2C(MagneticSensorI2CConfig_s config){
55-
chip_address = config.chip_address;
5661

57-
// angle read register of the magnetic sensor
58-
angle_register_msb = config.angle_register;
59-
// register maximum value (counts per revolution)
60-
cpr = _powtwo(config.bit_resolution);
6162

62-
int bits_used_msb = config.data_start_bit - 7;
63-
lsb_used = config.bit_resolution - bits_used_msb;
64-
// extraction masks
65-
lsb_mask = (uint8_t)( (2 << lsb_used) - 1 );
66-
msb_mask = (uint8_t)( (2 << bits_used_msb) - 1 );
63+
MagneticSensorI2C::MagneticSensorI2C(MagneticSensorI2CConfig_s config){
64+
_conf = config;
65+
cpr = _powtwo(config.bit_resolution);
6766
wire = &Wire;
6867
}
6968

69+
70+
7071
MagneticSensorI2C MagneticSensorI2C::AS5600() {
7172
return {AS5600_I2C};
7273
}
7374

74-
void MagneticSensorI2C::init(TwoWire* _wire){
75-
76-
wire = _wire;
7775

78-
// I2C communication begin
79-
wire->begin();
8076

77+
void MagneticSensorI2C::init(TwoWire* _wire){
78+
wire = _wire;
79+
wire->begin(); // I2C communication begin
8180
this->Sensor::init(); // call base class init
8281
}
8382

83+
84+
8485
// Shaft angle calculation
8586
// angle is in radians [rad]
8687
float MagneticSensorI2C::getSensorAngle(){
@@ -90,39 +91,25 @@ float MagneticSensorI2C::getSensorAngle(){
9091

9192

9293

93-
// function reading the raw counter of the magnetic sensor
94-
int MagneticSensorI2C::getRawCount(){
95-
return (int)MagneticSensorI2C::read(angle_register_msb);
96-
}
97-
9894
// I2C functions
9995
/*
100-
* Read a register from the sensor
101-
* Takes the address of the register as a uint8_t
102-
* Returns the value of the register
96+
* Read an angle from the angle register of the sensor
10397
*/
104-
int MagneticSensorI2C::read(uint8_t angle_reg_msb) {
98+
int MagneticSensorI2C::getRawCount() {
10599
// read the angle register first MSB then LSB
106100
byte readArray[2];
107101
uint16_t readValue = 0;
108102
// notify the device that is aboout to be read
109-
wire->beginTransmission(chip_address);
110-
wire->write(angle_reg_msb);
103+
wire->beginTransmission(_conf.chip_address);
104+
wire->write(_conf.angle_register);
111105
currWireError = wire->endTransmission(false);
112-
113106
// read the data msb and lsb
114-
wire->requestFrom(chip_address, (uint8_t)2);
107+
wire->requestFrom(_conf.chip_address, 2);
115108
for (byte i=0; i < 2; i++) {
116109
readArray[i] = wire->read();
117110
}
118-
119-
// depending on the sensor architecture there are different combinations of
120-
// LSB and MSB register used bits
121-
// AS5600 uses 0..7 LSB and 8..11 MSB
122-
// AS5048 uses 0..5 LSB and 6..13 MSB
123-
// MT6701 uses 0..5 LSB and 6..13 MSB
124-
readValue = ( readArray[1] & lsb_mask );
125-
readValue += ( ( readArray[0] & msb_mask ) << lsb_used );
111+
readValue = (readArray[0] & _conf.msb_mask) << _conf.msb_shift;
112+
readValue |= (readArray[1] & _conf.lsb_mask) >> _conf.lsb_shift;
126113
return readValue;
127114
}
128115

src/sensors/MagneticSensorI2C.h

+11-15
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@
88
#include "../common/time_utils.h"
99

1010
struct MagneticSensorI2CConfig_s {
11-
int chip_address;
12-
int bit_resolution;
13-
int angle_register;
14-
int data_start_bit;
11+
uint8_t chip_address;
12+
uint8_t bit_resolution;
13+
uint8_t angle_register;
14+
uint8_t msb_mask;
15+
uint8_t msb_shift;
16+
uint8_t lsb_mask;
17+
uint8_t lsb_shift;
1518
};
19+
1620
// some predefined structures
17-
extern MagneticSensorI2CConfig_s AS5600_I2C,AS5048_I2C;
21+
extern MagneticSensorI2CConfig_s AS5600_I2C, AS5048_I2C, MT6701_I2C;
1822

1923
#if defined(TARGET_RP2040)
2024
#define SDA I2C_SDA
@@ -31,7 +35,7 @@ class MagneticSensorI2C: public Sensor{
3135
* @param angle_register_msb angle read register msb
3236
* @param _bits_used_msb number of used bits in msb
3337
*/
34-
MagneticSensorI2C(uint8_t _chip_address, int _bit_resolution, uint8_t _angle_register_msb, int _msb_bits_used);
38+
MagneticSensorI2C(uint8_t _chip_address, int _bit_resolution, uint8_t _angle_register_msb, int _msb_bits_used, bool lsb_right_aligned = true);
3539

3640
/**
3741
* MagneticSensorI2C class constructor
@@ -56,13 +60,7 @@ class MagneticSensorI2C: public Sensor{
5660

5761
private:
5862
float cpr; //!< Maximum range of the magnetic sensor
59-
uint16_t lsb_used; //!< Number of bits used in LSB register
60-
uint8_t lsb_mask;
61-
uint8_t msb_mask;
62-
63-
// I2C variables
64-
uint8_t angle_register_msb; //!< I2C angle register to read
65-
uint8_t chip_address; //!< I2C chip select pins
63+
MagneticSensorI2CConfig_s _conf;
6664

6765
// I2C functions
6866
/** Read one I2C register value */
@@ -76,8 +74,6 @@ class MagneticSensorI2C: public Sensor{
7674

7775
/* the two wire instance for this sensor */
7876
TwoWire* wire;
79-
80-
8177
};
8278

8379

0 commit comments

Comments
 (0)