Skip to content

Commit 5e5818b

Browse files
committed
Code review updates
Remove option to set I2C address, and only check default address (fixed address, as of firmware v1.0) Move class member initialization to initialization list Remove initialization of values given to readRegister() calls Rename XY and H scalars to Linear and Angular Add separate units for linear derivatives Fix typos Add enVar bit to signal process bit field Add max number of read attempts to IMU calibration Add named constants for min/max scalar values Round scalar values instead of truncating
1 parent e39bbb4 commit 5e5818b

File tree

3 files changed

+84
-65
lines changed

3 files changed

+84
-65
lines changed

src/SparkFun_Qwiic_OTOS_Arduino_Library.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ class QwiicOTOS : public sfeQwiicOtos
1717
/// @param address I2C device address to use for the sensor
1818
/// @param wirePort Wire port to use for I2C communication
1919
/// @return True if successful, false otherwise
20-
bool begin(uint8_t address = kOtosDefaultAddress, TwoWire &wirePort = Wire)
20+
bool begin(TwoWire &wirePort = Wire)
2121
{
2222
// Setup Arduino I2C bus
23-
_theI2CBus.init(wirePort, address);
23+
_theI2CBus.init(wirePort, kOtosDefaultAddress);
2424

2525
// Begin the sensor
2626
return sfeQwiicOtos::begin(&_theI2CBus) == kSTkErrOk;

src/sfeQwiicOtos.cpp

Lines changed: 51 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,10 @@
77
#include "sfeQwiicOtos.h"
88

99
sfeQwiicOtos::sfeQwiicOtos()
10+
: _commBus{nullptr}, _linearUnit{kOtosLinearUnitInches}, _angularUnit{kOtosAngularUnitDegrees},
11+
_meterToUnit{kMeterToInch}, _radToUnit{kRadianToDegree}
1012
{
11-
// Set communication bus to nullptr
12-
_commBus = nullptr;
13-
14-
// Set default units to inches and degrees
15-
_linearUnit = kOtosLinearUnitInches;
16-
_angularUnit = kOtosAngularUnitDegrees;
17-
18-
// Set conversion factors to default units
19-
_meterToUnit = kMeterToInch;
20-
_radToUnit = kRadianToDegree;
13+
// Nothing to do here!
2114
}
2215

2316
sfeTkError_t sfeQwiicOtos::begin(sfeTkII2C *commBus)
@@ -27,7 +20,7 @@ sfeTkError_t sfeQwiicOtos::begin(sfeTkII2C *commBus)
2720
return kSTkErrFail;
2821

2922
// Check the device address
30-
if (commBus->address() < 0x08 || commBus->address() > 0x77)
23+
if (commBus->address() != kOtosDefaultAddress)
3124
return kSTkErrFail;
3225

3326
// Set bus pointer
@@ -45,7 +38,7 @@ sfeTkError_t sfeQwiicOtos::isConnected()
4538
return err;
4639

4740
// Read the product ID
48-
uint8_t prodId = 0;
41+
uint8_t prodId;
4942
err = _commBus->readRegisterByte(kOtosRegProductId, prodId);
5043
if(err != kSTkErrOk)
5144
return err;
@@ -62,7 +55,7 @@ sfeTkError_t sfeQwiicOtos::getVersionInfo(otos_version_t &hwVersion, otos_versio
6255
{
6356
// Read hardware and firmware version registers
6457
uint8_t rawData[2];
65-
size_t readBytes = 0;
58+
size_t readBytes;
6659
sfeTkError_t err = _commBus->readRegisterRegion(kOtosRegHwVersion, rawData, 2, readBytes);
6760
if(err != kSTkErrOk)
6861
return err;
@@ -121,22 +114,29 @@ sfeTkError_t sfeQwiicOtos::calibrateImu(uint8_t numSamples, bool waitUntilDone)
121114
if(!waitUntilDone)
122115
return kSTkErrOk;
123116

124-
// Wait for the calibration to finish, which is indicated by the gyro
125-
// calibration register reading zero
126-
uint8_t calibrationValue = numSamples;
127-
while(calibrationValue != 0)
117+
// Wait for the calibration to finish, which is indicated by the IMU
118+
// calibration register reading zero, or until we reach the maximum number
119+
// of read attempts
120+
for(uint8_t numAttempts = numSamples; numAttempts > 0; numAttempts--)
128121
{
129-
// Give a short delay between reads
130-
delayMs(2);
122+
// Give a short delay between reads. As of firmware v1.0, samples take
123+
// 2.4ms each, so 3ms should guarantee the next sample is done. This
124+
// also ensures the max attempts is not exceeded in normal operation
125+
delayMs(3);
131126

132127
// Read the gryo calibration register value
128+
uint8_t calibrationValue;
133129
err = _commBus->readRegisterByte(kOtosRegImuCalib, calibrationValue);
134130
if(err != kSTkErrOk)
135131
return err;
132+
133+
// Check if calibration is done
134+
if(calibrationValue == 0)
135+
return kSTkErrOk;
136136
}
137137

138-
// Done!
139-
return kSTkErrOk;
138+
// Max number of attempts reached, calibration failed
139+
return kSTkErrFail;
140140
}
141141

142142
otos_linear_unit_t sfeQwiicOtos::getLinearUnit()
@@ -178,8 +178,8 @@ void sfeQwiicOtos::setAngularUnit(otos_angular_unit_t unit)
178178
sfeTkError_t sfeQwiicOtos::getLinearScalar(float &scalar)
179179
{
180180
// Read the linear scalar from the device
181-
uint8_t rawScalar = 0;
182-
sfeTkError_t err = _commBus->readRegisterByte(kOtosRegScalarXY, rawScalar);
181+
uint8_t rawScalar;
182+
sfeTkError_t err = _commBus->readRegisterByte(kOtosRegScalarLinear, rawScalar);
183183
if(err != kSTkErrOk)
184184
return kSTkErrFail;
185185

@@ -192,22 +192,22 @@ sfeTkError_t sfeQwiicOtos::getLinearScalar(float &scalar)
192192

193193
sfeTkError_t sfeQwiicOtos::setLinearScalar(float scalar)
194194
{
195-
// Check if the scalar is out of bounds, can only be 0.872 to 1.127
196-
if(scalar < 0.872f || scalar > 1.127f)
195+
// Check if the scalar is out of bounds
196+
if(scalar < kSfeOtosMinScalar || scalar > kSfeOtosMaxScalar)
197197
return kSTkErrFail;
198198

199-
// Convert to raw integer, multiples of 0.1%
200-
uint8_t rawScalar = (int8_t)((scalar - 1.0f) * 1000);
199+
// Convert to integer, multiples of 0.1% (+0.5 to round instead of truncate)
200+
uint8_t rawScalar = (int8_t)((scalar - 1.0f) * 1000 + 0.5f);
201201

202202
// Write the scalar to the device
203-
return _commBus->writeRegisterByte(kOtosRegScalarXY, rawScalar);
203+
return _commBus->writeRegisterByte(kOtosRegScalarLinear, rawScalar);
204204
}
205205

206206
sfeTkError_t sfeQwiicOtos::getAngularScalar(float &scalar)
207207
{
208208
// Read the angular scalar from the device
209-
uint8_t rawScalar = 0;
210-
sfeTkError_t err = _commBus->readRegisterByte(kOtosRegScalarH, rawScalar);
209+
uint8_t rawScalar;
210+
sfeTkError_t err = _commBus->readRegisterByte(kOtosRegScalarAngular, rawScalar);
211211
if(err != kSTkErrOk)
212212
return kSTkErrFail;
213213

@@ -220,15 +220,15 @@ sfeTkError_t sfeQwiicOtos::getAngularScalar(float &scalar)
220220

221221
sfeTkError_t sfeQwiicOtos::setAngularScalar(float scalar)
222222
{
223-
// Check if the scalar is out of bounds, can only be 0.872 to 1.127
224-
if(scalar < 0.872f || scalar > 1.127f)
223+
// Check if the scalar is out of bounds
224+
if(scalar < kSfeOtosMinScalar || scalar > kSfeOtosMaxScalar)
225225
return kSTkErrFail;
226226

227-
// Convert to raw integer, multiples of 0.1%
228-
uint8_t rawScalar = (int8_t)((scalar - 1.0f) * 1000);
227+
// Convert to integer, multiples of 0.1% (+0.5 to round instead of truncate)
228+
uint8_t rawScalar = (int8_t)((scalar - 1.0f) * 1000 + 0.5f);
229229

230230
// Write the scalar to the device
231-
return _commBus->writeRegisterByte(kOtosRegScalarH, rawScalar);
231+
return _commBus->writeRegisterByte(kOtosRegScalarAngular, rawScalar);
232232
}
233233

234234
sfeTkError_t sfeQwiicOtos::resetTracking()
@@ -276,12 +276,12 @@ sfeTkError_t sfeQwiicOtos::setPosition(otos_pose2d_t &pose)
276276

277277
sfeTkError_t sfeQwiicOtos::getVelocity(otos_pose2d_t &pose)
278278
{
279-
return readPoseRegs(kOtosRegVelXL, pose, kInt16ToMeter, kInt16ToRps);
279+
return readPoseRegs(kOtosRegVelXL, pose, kInt16ToMps, kInt16ToRps);
280280
}
281281

282282
sfeTkError_t sfeQwiicOtos::getAcceleration(otos_pose2d_t &pose)
283283
{
284-
return readPoseRegs(kOtosRegAccXL, pose, kInt16ToMeter, kInt16ToRpss);
284+
return readPoseRegs(kOtosRegAccXL, pose, kInt16ToMpss, kInt16ToRpss);
285285
}
286286

287287
sfeTkError_t sfeQwiicOtos::getPositionStdDev(otos_pose2d_t &pose)
@@ -291,19 +291,19 @@ sfeTkError_t sfeQwiicOtos::getPositionStdDev(otos_pose2d_t &pose)
291291

292292
sfeTkError_t sfeQwiicOtos::getVelocityStdDev(otos_pose2d_t &pose)
293293
{
294-
return readPoseRegs(kOtosRegVelStdXL, pose, kInt16ToMeter, kInt16ToRps);
294+
return readPoseRegs(kOtosRegVelStdXL, pose, kInt16ToMps, kInt16ToRps);
295295
}
296296

297297
sfeTkError_t sfeQwiicOtos::getAccelerationStdDev(otos_pose2d_t &pose)
298298
{
299-
return readPoseRegs(kOtosRegAccStdXL, pose, kInt16ToMeter, kInt16ToRpss);
299+
return readPoseRegs(kOtosRegAccStdXL, pose, kInt16ToMpss, kInt16ToRpss);
300300
}
301301

302302
sfeTkError_t sfeQwiicOtos::getPosVelAcc(otos_pose2d_t &pos, otos_pose2d_t &vel, otos_pose2d_t &acc)
303303
{
304304
// Read all pose registers
305305
uint8_t rawData[18];
306-
size_t bytesRead = 0;
306+
size_t bytesRead;
307307
sfeTkError_t err = _commBus->readRegisterRegion(kOtosRegPosXL, rawData, 18, bytesRead);
308308
if(err != kSTkErrOk)
309309
return err;
@@ -314,8 +314,8 @@ sfeTkError_t sfeQwiicOtos::getPosVelAcc(otos_pose2d_t &pos, otos_pose2d_t &vel,
314314

315315
// Convert raw data to pose units
316316
regsToPose(rawData, pos, kInt16ToMeter, kInt16ToRad);
317-
regsToPose(rawData + 6, vel, kInt16ToMeter, kInt16ToRps);
318-
regsToPose(rawData + 12, acc, kInt16ToMeter, kInt16ToRpss);
317+
regsToPose(rawData + 6, vel, kInt16ToMps, kInt16ToRps);
318+
regsToPose(rawData + 12, acc, kInt16ToMpss, kInt16ToRpss);
319319

320320
// Done!
321321
return kSTkErrOk;
@@ -325,7 +325,7 @@ sfeTkError_t sfeQwiicOtos::getPosVelAccStdDev(otos_pose2d_t &pos, otos_pose2d_t
325325
{
326326
// Read all pose registers
327327
uint8_t rawData[18];
328-
size_t bytesRead = 0;
328+
size_t bytesRead;
329329
sfeTkError_t err = _commBus->readRegisterRegion(kOtosRegPosStdXL, rawData, 18, bytesRead);
330330
if(err != kSTkErrOk)
331331
return err;
@@ -336,8 +336,8 @@ sfeTkError_t sfeQwiicOtos::getPosVelAccStdDev(otos_pose2d_t &pos, otos_pose2d_t
336336

337337
// Convert raw data to pose units
338338
regsToPose(rawData, pos, kInt16ToMeter, kInt16ToRad);
339-
regsToPose(rawData + 6, vel, kInt16ToMeter, kInt16ToRps);
340-
regsToPose(rawData + 12, acc, kInt16ToMeter, kInt16ToRpss);
339+
regsToPose(rawData + 6, vel, kInt16ToMps, kInt16ToRps);
340+
regsToPose(rawData + 12, acc, kInt16ToMpss, kInt16ToRpss);
341341

342342
// Done!
343343
return kSTkErrOk;
@@ -347,7 +347,7 @@ sfeTkError_t sfeQwiicOtos::getPosVelAccAndStdDev(otos_pose2d_t &pos, otos_pose2d
347347
{
348348
// Read all pose registers
349349
uint8_t rawData[36];
350-
size_t bytesRead = 0;
350+
size_t bytesRead;
351351
sfeTkError_t err = _commBus->readRegisterRegion(kOtosRegPosXL, rawData, 36, bytesRead);
352352
if(err != kSTkErrOk)
353353
return err;
@@ -358,19 +358,19 @@ sfeTkError_t sfeQwiicOtos::getPosVelAccAndStdDev(otos_pose2d_t &pos, otos_pose2d
358358

359359
// Convert raw data to pose units
360360
regsToPose(rawData, pos, kInt16ToMeter, kInt16ToRad);
361-
regsToPose(rawData + 6, vel, kInt16ToMeter, kInt16ToRps);
362-
regsToPose(rawData + 12, acc, kInt16ToMeter, kInt16ToRpss);
361+
regsToPose(rawData + 6, vel, kInt16ToMps, kInt16ToRps);
362+
regsToPose(rawData + 12, acc, kInt16ToMpss, kInt16ToRpss);
363363
regsToPose(rawData + 18, posStdDev, kInt16ToMeter, kInt16ToRad);
364-
regsToPose(rawData + 24, velStdDev, kInt16ToMeter, kInt16ToRps);
365-
regsToPose(rawData + 30, accStdDev, kInt16ToMeter, kInt16ToRpss);
364+
regsToPose(rawData + 24, velStdDev, kInt16ToMps, kInt16ToRps);
365+
regsToPose(rawData + 30, accStdDev, kInt16ToMpss, kInt16ToRpss);
366366

367367
// Done!
368368
return kSTkErrOk;
369369
}
370370

371371
sfeTkError_t sfeQwiicOtos::readPoseRegs(uint8_t reg, otos_pose2d_t &pose, float rawToXY, float rawToH)
372372
{
373-
size_t bytesRead = 0;
373+
size_t bytesRead;
374374
uint8_t rawData[6];
375375

376376
// Attempt to read the raw pose data

src/sfeQwiicOtos.h

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ const uint8_t kOtosDefaultAddress = 0x17;
1717
const uint8_t kOtosRegProductId = 0x00;
1818
const uint8_t kOtosRegHwVersion = 0x01;
1919
const uint8_t kOtosRegFwVersion = 0x02;
20-
const uint8_t kOtosRegScalarXY = 0x04;
21-
const uint8_t kOtosRegScalarH = 0x05;
20+
const uint8_t kOtosRegScalarLinear = 0x04;
21+
const uint8_t kOtosRegScalarAngular = 0x05;
2222
const uint8_t kOtosRegImuCalib = 0x06;
2323
const uint8_t kOtosRegReset = 0x07;
2424

@@ -81,29 +81,47 @@ const float kInchToMeter = 1.0f / kMeterToInch;
8181
const float kRadianToDegree = 180.0f / M_PI;
8282
const float kDegreeToRadian = M_PI / 180.0f;
8383

84-
// Conversion factor for X and Y position/velocity/acceleration registers.
85-
// 16-bit signed registers with a max value of 16 gives a resolution of about
86-
// 0.00049 meters (0.019 inches)
87-
const float kMeterToInt16 = 32768.0f / 16.0f;
84+
// Conversion factor for the linear position registers. 16-bit signed registers
85+
// with a max value of 10 meters (394 inches) gives a resolution of about 0.0003
86+
// mps (0.012 ips)
87+
const float kMeterToInt16 = 32768.0f / 10.0f;
8888
const float kInt16ToMeter = 1.0f / kMeterToInt16;
8989

90-
// Converstion factor for the heading register. 16-bit signed register with a
91-
// max value of pi gives a resolution of about 0.00096 radians (0.0055 degrees)
90+
// Conversion factor for the linear velocity registers. 16-bit signed registers
91+
// with a max value of 5 mps (197 ips) gives a resolution of about 0.00015 mps
92+
// (0.006 ips)
93+
const float kMpsToInt16 = 32768.0f / 5.0f;
94+
const float kInt16ToMps = 1.0f / kMpsToInt16;
95+
96+
// Conversion factor for the linear acceleration registers. 16-bit signed
97+
// registers with a max value of 157 mps^2 (16 g) gives a resolution of
98+
// about 0.0048 mps^2 (0.49 mg)
99+
const float kMpssToInt16 = 32768.0f / (16.0f * 9.80665f);
100+
const float kInt16ToMpss = 1.0f / kMpssToInt16;
101+
102+
// Conversion factor for the angular position registers. 16-bit signed registers
103+
// with a max value of pi radians (180 degrees) gives a resolution of about
104+
// 0.00096 radians (0.0055 degrees)
92105
const float kRadToInt16 = 32768.0f / M_PI;
93106
const float kInt16ToRad = 1.0f / kRadToInt16;
94107

95-
// Converstion factor for the heading velocity register. 16-bit signed register
108+
// Conversion factor for the angular velocity registers. 16-bit signed registers
96109
// with a max value of 34.9 rps (2000 dps) gives a resolution of about 0.0011
97110
// rps (0.061 degrees per second)
98111
const float kRpsToInt16 = 32768.0f / (2000.0f * kDegreeToRadian);
99112
const float kInt16ToRps = 1.0f / kRpsToInt16;
100113

101-
// Converstion factor for the heading acceleration register. 16-bit signed
102-
// register with a max value of 3141 rps^2 (180000 dps^2) gives a resolution of
114+
// Conversion factor for the angular acceleration registers. 16-bit signed
115+
// registers with a max value of 3141 rps^2 (180000 dps^2) gives a resolution of
103116
// about 0.096 rps^2 (5.5 dps^2)
104117
const float kRpssToInt16 = 32768.0f / (M_PI * 1000.0f);
105118
const float kInt16ToRpss = 1.0f / kRpssToInt16;
106119

120+
// Min and max scalar values for the linear and angular scalars (8-bit signed
121+
// integer representing 0.1% increments)
122+
const float kSfeOtosMinScalar = 0.872f;
123+
const float kSfeOtosMaxScalar = 1.127f;
124+
107125
// Struct to define a 2D pose, including x and y coordinates and an angle h
108126
struct otos_pose2d_t
109127
{
@@ -141,7 +159,8 @@ typedef union {
141159
uint8_t enLut : 1;
142160
uint8_t enAcc : 1;
143161
uint8_t enRot : 1;
144-
uint8_t reserved : 5;
162+
uint8_t enVar : 1;
163+
uint8_t reserved : 4;
145164
};
146165
uint8_t value;
147166
} sfe_otos_config_signal_process_t;

0 commit comments

Comments
 (0)