Smartcar Shield
Loading...
Searching...
No Matches
GY50.cpp
Go to the documentation of this file.
1/*
2 L3G4200D implementation based on code by:
3 * http://bildr.org/2011/06/l3g4200d-arduino/
4 * http://www.pieter-jan.com/node/7
5 * https://github.com/sparkfun/Tri-Axis_Gyro_Breakout-L3G4200D
6*/
7#include "GY50.hpp"
8#include "../../../utilities/Utilities.hpp"
9
10namespace
11{
12const uint8_t kGyroAddress = 105;
13const auto kMeasurementInterval = 100;
14const float kGyroSensitivity = 0.07F;
15const int kGyroThreshold = 12; // Smaller changes are to be ignored
16} // namespace
17
18using namespace smartcarlib::utils;
19using namespace smartcarlib::constants::gy50;
20
21GY50::GY50(Runtime& runtime, int offset, unsigned long samplingInterval)
22 : kOffset{ offset }
23 , kSamplingInterval{ samplingInterval }
24 , mRuntime{ runtime }
25{
26}
27
29{
30 // Get the reading from (-180,180) to [0, 360) scale
31 static constexpr auto kFullScaleDegrees = 360;
32 auto normalizedReading = static_cast<int>(mAngularDisplacement) % kFullScaleDegrees;
33
34 return normalizedReading < 0 ? normalizedReading + kFullScaleDegrees : normalizedReading;
35}
36
38{
39 unsigned long currentTime = mRuntime.currentTimeMillis();
40 unsigned long interval = currentTime - mPreviousSample;
41 if (interval <= kSamplingInterval)
42 {
43 return; // Not the time to read yet
44 }
45
46 int drift = kOffset - getAngularVelocity();
47
48 if (getAbsolute(drift) > kGyroThreshold)
49 {
50 float gyroRate = static_cast<float>(drift) * kGyroSensitivity;
51 static constexpr auto kGyroscopeReadingScale = 1000.0F;
52 mAngularDisplacement += gyroRate / (kGyroscopeReadingScale / static_cast<float>(interval));
53 }
54 mPreviousSample = currentTime;
55}
56
57void GY50::attach()
58{
59 if (mAttached)
60 {
61 return;
62 }
63
64 mRuntime.i2cInit();
65 // Enable z and turn off power down
66 static constexpr uint8_t kControlRegister1 = 0x20;
67 writeL3G4200DRegister(kControlRegister1, 0b00001100); // NOLINT(readability-magic-numbers)
68 // If you'd like to adjust/use the HPF, you can edit the line below to configure CTRL_REG2
69 static constexpr uint8_t kControlRegister2 = 0x21;
70 writeL3G4200DRegister(kControlRegister2, 0b00000000); // NOLINT(readability-magic-numbers)
71 // Configure CTRL_REG3 to generate data ready interrupt on INT2
72 // No interrupts used on INT1, if you'd like to configure INT1
73 // or INT2 otherwise, consult the datasheet
74 static constexpr uint8_t kControlRegister3 = 0x22;
75 writeL3G4200DRegister(kControlRegister3, 0b00001000); // NOLINT(readability-magic-numbers)
76 // CTRL_REG4 controls the full-scale range, among other things
77 static constexpr uint8_t kControlRegister4 = 0x23;
78 writeL3G4200DRegister(kControlRegister4, 0b00110000); // NOLINT(readability-magic-numbers)
79 // CTRL_REG5 controls high-pass filtering of outputs, use it if you'd like
80 static constexpr uint8_t kControlRegister5 = 0x24;
81 writeL3G4200DRegister(kControlRegister5, 0b00000000); // NOLINT(readability-magic-numbers)
82
83 mAttached = true;
84}
85
86int GY50::getOffset(int measurements)
87{
88 if (measurements <= 0)
89 {
90 return kError;
91 }
92
93 long sum = 0;
94 for (auto i = 0; i < measurements; i++)
95 {
96 sum += getAngularVelocity();
97 mRuntime.delayMillis(kMeasurementInterval);
98 }
99
100 return static_cast<int>(sum / measurements);
101}
102
103int GY50::getAngularVelocity()
104{
105 attach();
106
107 static const uint8_t zAxisFirstByteRegister = 0x2D;
108 static const uint8_t zAxisSecondByteRegister = 0x2C;
109
110 auto firstByte = readL3G4200DRegister(zAxisFirstByteRegister);
111 auto secondByte = readL3G4200DRegister(zAxisSecondByteRegister);
112
113 static constexpr auto kBitsInByte = 8;
114
115 return static_cast<int16_t>((firstByte << kBitsInByte) | secondByte);
116}
117
118int GY50::readL3G4200DRegister(uint8_t registerAddress)
119{
120 mRuntime.i2cBeginTransmission(kGyroAddress);
121 mRuntime.i2cWrite(registerAddress);
122 mRuntime.i2cEndTransmission();
123 mRuntime.i2cRequestFrom(kGyroAddress, 1);
124
125 return mRuntime.i2cAvailable() != 0 ? mRuntime.i2cRead() : 0;
126}
127
128void GY50::writeL3G4200DRegister(uint8_t registerAddress, uint8_t value)
129{
130 mRuntime.i2cBeginTransmission(kGyroAddress);
131 mRuntime.i2cWrite(registerAddress);
132 mRuntime.i2cWrite(value);
133 mRuntime.i2cEndTransmission();
134}
int getOffset(int measurements=smartcarlib::constants::gy50::kDefaultCalibrationMeasurements)
Get the sensor's offset which is the value the sensor returns when still.
Definition GY50.cpp:86
GY50(Runtime &runtime, int offset, unsigned long samplingInterval=smartcarlib::constants::gy50::kDefaultSamplingInterval)
Constructs a GY50 gyroscope.
Definition GY50.cpp:21
int getHeading() override
Returns the current heading of the vehicle.
Definition GY50.cpp:28
void update() override
Updates the sensor's readings.
Definition GY50.cpp:37
An interface to serve as a wrapper for the native runtime environment, greatly inspired by the Arduin...
Definition Runtime.hpp:36
virtual size_t i2cWrite(uint8_t value)=0
Send the specified byte via i2c, equivalent of Wire.write in Arduino.
virtual void delayMillis(unsigned long milliseconds)=0
Block the execution for the specified number of milliseconds, equivalent of delay in Arduino.
virtual void i2cBeginTransmission(uint8_t address)=0
Initiate a transmission to the specified I2C slave device, equivalent of Wire.beginTransmission in Ar...
virtual uint8_t i2cEndTransmission()=0
Ends a transmission to an I2C device equivalent of Wire.endTransmission in Arduino.
virtual int i2cAvailable()=0
Gets the number of bytes available to be retrieved, equivalent of Wire.availableO in Arduino.
virtual int i2cRead()=0
Reads a byte from I2C bus, equivalent of Wire.read in Arduino.
virtual void i2cInit()=0
Initialize I2C bus as master, equivalent of Wire.begin in Arduino.
virtual uint8_t i2cRequestFrom(uint8_t address, uint8_t numberOfBytes)=0
Request a number of bytes from the specified I2C slave, equivalent of Wire.requestFrom in Arduino.
virtual unsigned long currentTimeMillis()=0
Gets the amount of milliseconds since the microcontroller started running, equivalent of millis in Ar...
constexpr AnyNumber getAbsolute(AnyNumber number)
Gets the absolute of the supplied number.
Definition Utilities.hpp:24