Skip to content

Commit 051860e

Browse files
authored
Improve calibration (#60)
Co-authored-by: Maik Menz - redo of **calibrate()** function, Kudos to Maik Menz. - Fix #59 Added orientation arguments to calibrate function (#59) - Fix #57 calibration error scaling - update library.json - improve initialization of gax, gay and gaz - add **readRaw()** to improve calibrate() - update readme.md - improve initialization
1 parent e23401c commit 051860e

File tree

6 files changed

+132
-57
lines changed

6 files changed

+132
-57
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

88

9+
## [0.6.1] - 2024-07-25
10+
Co-authored-by: Maik Menz
11+
- redo of **calibrate()** function, Kudos to Maik Menz.
12+
- Fix #59 Added orientation arguments to calibrate function (#59)
13+
- Fix #57 calibration error scaling
14+
- update library.json
15+
- improve initialization of gax, gay and gaz
16+
- add **readRaw()** to improve calibrate()
17+
- update readme.md
18+
- improve initialization
19+
20+
921
## [0.6.0] - 2024-06-22
1022
- fix #54, calibrate() function, Kudos to jens-kuerten and MArimont3
1123
- minor edits

GY521.cpp

Lines changed: 82 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// FILE: GY521.cpp
33
// AUTHOR: Rob Tillaart
4-
// VERSION: 0.6.0
4+
// VERSION: 0.6.1
55
// PURPOSE: Arduino library for I2C GY521 accelerometer-gyroscope sensor
66
// URL: https://github.com/RobTillaart/GY521
77

@@ -26,12 +26,11 @@ GY521::GY521(uint8_t address, TwoWire *wire)
2626
_address = address;
2727
_wire = wire;
2828

29-
_ax = _ay = _az = 0;
30-
_aax = _aay = _aaz = 0;
31-
_gx = _gy = _gz = 0;
32-
_pitch = 0;
33-
_roll = 0;
34-
_yaw = 0;
29+
// initialize errors
30+
// don't do it in reset, as users might want to keep them
31+
axe = aye = aze = 0;
32+
33+
reset();
3534
}
3635

3736

@@ -66,13 +65,14 @@ void GY521::reset()
6665
_ax = _ay = _az = 0;
6766
_aax = _aay = _aaz = 0;
6867
_gx = _gy = _gz = 0;
68+
_gax = _gay = _gaz = 0;
6969
_pitch = 0;
7070
_roll = 0;
7171
_yaw = 0;
7272
}
7373

7474

75-
void GY521::calibrate(uint16_t times)
75+
bool GY521::calibrate(uint16_t times, float angleX, float angleY, bool inverted)
7676
{
7777
// disable throttling / caching of read values.
7878
bool oldThrottle = _throttle;
@@ -89,29 +89,50 @@ void GY521::calibrate(uint16_t times)
8989
// adjust times if zero.
9090
if (times == 0) times = 1;
9191

92-
// summarize (6x) the measurements.
92+
// sum (6x) the measurements.
93+
uint16_t samples = 0;
9394
for (uint16_t i = 0; i < times; i++)
9495
{
95-
read();
96-
_axe -= getAccelX();
97-
_aye -= getAccelY();
98-
_aze -= getAccelZ();
99-
_gxe -= getGyroX();
100-
_gye -= getGyroY();
101-
_gze -= getGyroZ();
96+
if (_readRaw() == GY521_OK)
97+
{
98+
_axe -= getAccelX();
99+
_aye -= getAccelY();
100+
_aze -= getAccelZ();
101+
_gxe -= getGyroX();
102+
_gye -= getGyroY();
103+
_gze -= getGyroZ();
104+
samples++;
105+
}
102106
}
103107

104-
// adjust calibration errors so read() should get all zero's on average.
105-
float factor = 1.0 / times;
106-
axe = _axe * factor;
107-
aye = _aye * factor;
108-
aze = _aze * factor;
108+
if (samples == 0) return false;
109+
110+
// scale gyro calibration errors so read() should get all zero's on average.
111+
float factor = _raw2dps / samples;
109112
gxe = _gxe * factor;
110113
gye = _gye * factor;
111114
gze = _gze * factor;
112115

116+
// scale accelerometer calibration errors so read() should get all zero's on average.
117+
factor = _raw2g / samples;
118+
axe = _axe * factor;
119+
aye = _aye * factor;
120+
aze = _aze * factor;
121+
122+
// remove expected gravity from error
123+
angleX *= GY521_DEGREES2RAD;
124+
angleY *= GY521_DEGREES2RAD;
125+
float _gravx = -sin(angleY) * cos(angleX);
126+
float _gravy = sin(angleX);
127+
float _gravz = cos(angleY) * cos(angleX);
128+
axe -= _gravx;
129+
aye -= _gravy;
130+
aze += inverted ? -_gravz : _gravz;
131+
113132
// restore throttle state.
114133
_throttle = oldThrottle;
134+
135+
return true;
115136
}
116137

117138

@@ -137,32 +158,11 @@ int16_t GY521::read()
137158
}
138159
_lastTime = now;
139160

140-
// Connected ?
141-
_wire->beginTransmission(_address);
142-
_wire->write(GY521_ACCEL_XOUT_H);
143-
if (_wire->endTransmission() != 0)
144-
{
145-
_error = GY521_ERROR_WRITE;
146-
return _error;
147-
}
148-
149-
// Get the data
150-
int8_t n = _wire->requestFrom(_address, (uint8_t)14);
151-
if (n != 14)
161+
int16_t rv = _readRaw();
162+
if (rv != GY521_OK)
152163
{
153-
_error = GY521_ERROR_READ;
154-
return _error;
164+
return rv;
155165
}
156-
// ACCELEROMETER
157-
_ax = _WireRead2(); // ACCEL_XOUT_H ACCEL_XOUT_L
158-
_ay = _WireRead2(); // ACCEL_YOUT_H ACCEL_YOUT_L
159-
_az = _WireRead2(); // ACCEL_ZOUT_H ACCEL_ZOUT_L
160-
// TEMPERATURE
161-
_temperature = _WireRead2(); // TEMP_OUT_H TEMP_OUT_L
162-
// GYROSCOPE
163-
_gx = _WireRead2(); // GYRO_XOUT_H GYRO_XOUT_L
164-
_gy = _WireRead2(); // GYRO_YOUT_H GYRO_YOUT_L
165-
_gz = _WireRead2(); // GYRO_ZOUT_H GYRO_ZOUT_L
166166

167167
// duration interval
168168
now = micros();
@@ -549,6 +549,43 @@ uint8_t GY521::getRegister(uint8_t reg)
549549
}
550550

551551

552+
///////////////////////////////////////////////////////////////////
553+
//
554+
// PRIVATE
555+
//
556+
int16_t GY521::_readRaw()
557+
{
558+
// Connected ?
559+
_wire->beginTransmission(_address);
560+
_wire->write(GY521_ACCEL_XOUT_H);
561+
if (_wire->endTransmission() != 0)
562+
{
563+
_error = GY521_ERROR_WRITE;
564+
return _error;
565+
}
566+
567+
// Get the data
568+
int8_t n = _wire->requestFrom(_address, (uint8_t)14);
569+
if (n != 14)
570+
{
571+
_error = GY521_ERROR_READ;
572+
return _error;
573+
}
574+
// ACCELEROMETER
575+
_ax = _WireRead2(); // ACCEL_XOUT_H ACCEL_XOUT_L
576+
_ay = _WireRead2(); // ACCEL_YOUT_H ACCEL_YOUT_L
577+
_az = _WireRead2(); // ACCEL_ZOUT_H ACCEL_ZOUT_L
578+
// TEMPERATURE
579+
_temperature = _WireRead2(); // TEMP_OUT_H TEMP_OUT_L
580+
// GYROSCOPE
581+
_gx = _WireRead2(); // GYRO_XOUT_H GYRO_XOUT_L
582+
_gy = _WireRead2(); // GYRO_YOUT_H GYRO_YOUT_L
583+
_gz = _WireRead2(); // GYRO_ZOUT_H GYRO_ZOUT_L
584+
585+
return GY521_OK;
586+
}
587+
588+
552589
// to read register of 2 bytes.
553590
int16_t GY521::_WireRead2()
554591
{

GY521.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// FILE: GY521.h
44
// AUTHOR: Rob Tillaart
5-
// VERSION: 0.6.0
5+
// VERSION: 0.6.1
66
// PURPOSE: Arduino library for I2C GY521 accelerometer-gyroscope sensor
77
// URL: https://github.com/RobTillaart/GY521
88

@@ -11,7 +11,7 @@
1111
#include "Wire.h"
1212

1313

14-
#define GY521_LIB_VERSION (F("0.6.0"))
14+
#define GY521_LIB_VERSION (F("0.6.1"))
1515

1616
const float GRAVITY = 9.80655;
1717

@@ -33,6 +33,7 @@ const float GRAVITY = 9.80655;
3333

3434
// CONVERSION CONSTANTS
3535
#define GY521_RAD2DEGREES (180.0 / PI)
36+
#define GY521_DEGREES2RAD (PI / 180.0)
3637
#define GY521_RAW2DPS (1.0 / 131.0)
3738
#define GY521_RAW2G (1.0 / 16384.0)
3839

@@ -51,7 +52,7 @@ class GY521
5152
// EXPERIMENTAL
5253
// calibrate needs to be called to compensate for errors.
5354
// must be called after setAccelSensitivity(as); and setGyroSensitivity(gs);
54-
void calibrate(uint16_t times);
55+
bool calibrate(uint16_t times, float angleX = 0, float angleY = 0, bool inverted = false);
5556

5657
bool wakeup();
5758
// throttle to force delay between reads.
@@ -151,6 +152,7 @@ class GY521
151152

152153
bool _normalize = true; // default true.
153154

155+
int16_t _readRaw();
154156
// to read register of 2 bytes.
155157
int16_t _WireRead2();
156158

README.md

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ It needs to be tested a lot more.
2424
See changelog.md for latest updates.
2525

2626

27+
#### 0.6.1
28+
29+
Improved **calibrate()** to support any angle.
30+
31+
2732
#### 0.6.0
2833

2934
Fixed a bug in calibration function, making previous versions obsolete.
@@ -92,6 +97,10 @@ This function overwrites the values of axe aye aze gxe gye gze.
9297

9398
Note the **calibrate()** function takes time, depending on the number of times.
9499

100+
Since version 0.6.1 the calibrate function is extended with optional parameters so the
101+
sensor can be calibrated in any angle.
102+
**bool calibrate(times, angleX = 0, angleY = 0, inverted = false)**
103+
95104

96105
#### Manual calibration
97106

@@ -120,14 +129,24 @@ Note call **Wire.begin()** before **begin()**.
120129

121130
### Calibrate
122131

123-
- **void calibrate(uint16_t times)** This function overwrites the values of axe aye aze gxe gye gze.
124-
To get "quality error" offsets, the GY521 sensor should not move during the calibration.
125-
The parameter times determines the number of measurements made.
126-
Typical values are 100 or more.
127-
Please note this is a time consuming function.
132+
- **bool calibrate(uint16_t times, float angleX = 0, float angleY = 0, bool inverted = false)**
133+
This function overwrites the values of axe aye aze and gxe gye gze.
134+
To improve the quality of the error offsets, the GY521 sensor should not move during the calibration.
135+
The parameter times determines the number of measurements the calibration function should make.
136+
Note that the actual number of samples can be less if a read of the sensor fails.
137+
If there is no good read at all the function returns **false**.
138+
Typical values for times are 100 or more.
139+
If times is set to 0, it will be forced to 1.
140+
Please note this call will be very time consuming.
128141

129142
Ideal the function **calibrate()** should continue until it is stable (how to define) for n reads.
130-
Drawback is that this would make the duration unpredictable.
143+
Drawback is that this would make the duration unpredictable.
144+
145+
New since 0.6.1 (experimental)
146+
The optional parameters **float angleX = 0, float angleY = 0** should be between -90 .. +90.
147+
These can be used if the sensor is not lying flat during calibration.
148+
The optional parameter **bool inverted = false** should be set to true if the sensor is
149+
upside down.
131150

132151

133152
### Throttle
@@ -293,7 +312,9 @@ However if one specific is needed, please open an issue.
293312

294313
#### Should
295314

296-
- test **calibrate()** function for different sensitivities.
315+
- test **calibrate()** function
316+
- for different sensitivities.
317+
- for different angles.
297318

298319
#### Could
299320

library.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@
88
"name": "Rob Tillaart",
99
"email": "[email protected]",
1010
"maintainer": true
11+
},
12+
{
13+
"name": "Maik Menz"
1114
}
1215
],
1316
"repository":
1417
{
1518
"type": "git",
1619
"url": "https://github.com/RobTillaart/GY521.git"
1720
},
18-
"version": "0.6.0",
21+
"version": "0.6.1",
1922
"license": "MIT",
2023
"frameworks": "*",
2124
"platforms": "*",

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=GY521
2-
version=0.6.0
2+
version=0.6.1
33
author=Rob Tillaart <[email protected]>
44
maintainer=Rob Tillaart <[email protected]>
55
sentence=Arduino library for GY521 angle measurement

0 commit comments

Comments
 (0)