wpi-32u4-library
LSM6.cpp
Go to the documentation of this file.
1#include <Wire.h>
2#include <LSM6.h>
3#include <math.h>
4
5// Defines ////////////////////////////////////////////////////////////////
6
7// The Arduino two-wire interface uses a 7-bit number for the address,
8// and sets the last bit correctly based on reads and writes
9#define DS33_SA0_HIGH_ADDRESS 0b1101011
10#define DS33_SA0_LOW_ADDRESS 0b1101010
11
12#define TEST_REG_ERROR -1
13
14#define DS33_WHO_ID 0x69
15
16// Constructors ////////////////////////////////////////////////////////////////
17
19{
21
22 io_timeout = 0; // 0 = no timeout
23 did_timeout = false;
24}
25
26// Public Methods //////////////////////////////////////////////////////////////
27
28// Did a timeout occur in readAcc(), readGyro(), or read() since the last call to timeoutOccurred()?
30{
31 bool tmp = did_timeout;
32 did_timeout = false;
33 return tmp;
34}
35
36void LSM6::setTimeout(uint16_t timeout)
37{
38 io_timeout = timeout;
39}
40
42{
43 return io_timeout;
44}
45
47{
48 uint8_t settings = readReg(LSM6::CTRL2_G);
49 settings &= 0xf0; //clear sensitivity bits; can't use 125 setting
50 switch (gfs)
51 {
52 case GYRO_FS245:
53 writeReg(LSM6::CTRL2_G, settings | 0b00000000);
54 mdps = 8.75;
55 break;
56 case GYRO_FS500:
57 writeReg(LSM6::CTRL2_G, settings | 0b00000100);
58 mdps = 17.5;
59 break;
60 case GYRO_FS1000:
61 writeReg(LSM6::CTRL2_G, settings | 0b00001000);
62 mdps = 35;
63 break;
64 case GYRO_FS2000:
65 writeReg(LSM6::CTRL2_G, settings | 0b00001100);
66 mdps = 70;
67 break;
68 default:
69 Serial.println("Error setting gyro sensitivity!");
70 }
71}
72
74{
75 uint8_t settings = readReg(LSM6::CTRL1_XL);
76 settings &= 0xf0; //clear sensitivity bits
77 switch (afs)
78 {
79 case ACC_FS2:
80 writeReg(LSM6::CTRL1_XL, 0b00000000);
81 mg = 0.061;
82 break;
83 case ACC_FS4:
84 writeReg(LSM6::CTRL1_XL, 0b00001000);
85 mg = 0.122;
86 break;
87 case ACC_FS8:
88 writeReg(LSM6::CTRL1_XL, 0b00001100);
89 mg = 0.244;
90 break;
91 case ACC_FS16:
92 writeReg(LSM6::CTRL1_XL, 0b00000100);
93 mg = 0.488;
94 break;
95 default:
96 Serial.println("Error setting acc sensitivity!");
97 }
98}
99
101{
102 if(rate < 0 || rate > ODR166k)
103 {
104 Serial.println(F("Illegal gyro ODR"));
105 return;
106 }
107 uint8_t settings = readReg(LSM6::CTRL2_G);
108 settings &= 0x0f; //clear ODR bits
109 writeReg(LSM6::CTRL2_G, settings | (rate << 4));
110}
111
113{
114 if(rate < 0 || rate > ODR166k)
115 {
116 Serial.println(F("Illegal acc ODR"));
117 return;
118 }
119
120 uint8_t settings = readReg(LSM6::CTRL1_XL);
121 settings &= 0x0f; //clear ODR bits
122 writeReg(LSM6::CTRL1_XL, settings | (rate << 4));
123}
124
126{
127 // perform auto-detection unless device type and SA0 state were both specified
128 if (device == device_auto || sa0 == sa0_auto)
129 {
130 // check for LSM6DS33 if device is unidentified or was specified to be this type
131 if (device == device_auto || device == device_DS33)
132 {
133 // check SA0 high address unless SA0 was specified to be low
135 {
136 sa0 = sa0_high;
137 if (device == device_auto)
138 {
139 device = device_DS33;
140 }
141 }
142 // check SA0 low address unless SA0 was specified to be high
144 {
145 sa0 = sa0_low;
146 if (device == device_auto)
147 {
148 device = device_DS33;
149 }
150 }
151 }
152
153 // make sure device and SA0 were successfully detected; otherwise, indicate failure
154 if (device == device_auto || sa0 == sa0_auto)
155 {
156 return false;
157 }
158 }
159
160 _device = device;
161
162 switch (device)
163 {
164 case device_DS33:
166 break;
167 default:;
168 }
169
170 return true;
171}
172
173/*
174Enables the LSM6's accelerometer and gyro. Also:
175- Sets sensor full scales (gain) to default power-on values, which are
176 +/- 2 g for accelerometer and 245 dps for gyro
177- Selects 1.66 kHz (high performance) ODR (output data rate) for accelerometer
178 and 1.66 kHz (high performance) ODR for gyro. (These are the ODR settings for
179 which the electrical characteristics are specified in the datasheet.)
180- Enables automatic increment of register address during multiple byte access
181Note that this function will also reset other settings controlled by
182the registers it writes to.
183*/
185{
186 if (_device == device_DS33)
187 {
188 // Accelerometer
189
190 // 0x80 = 0b10000000
191 // ODR = 1000 (1.66 kHz (high performance)); FS_XL = 00 (+/-2 g full scale)
192 //writeReg(CTRL1_XL, 0x80);
194
195 // Gyro
196
197 // 0x80 = 0b010000000
198 // ODR = 1000 (1.66 kHz (high performance)); FS_XL = 00 (245 dps)
199 //writeReg(CTRL2_G, 0x80);
201 // Common
202
203 // 0x04 = 0b00000100
204 // IF_INC = 1 (automatically increment register address)
205 writeReg(CTRL3_C, 0x04);
206 }
207}
208
209void LSM6::writeReg(uint8_t reg, uint8_t value)
210{
211 Wire.beginTransmission(address);
212 Wire.write(reg);
213 Wire.write(value);
214 last_status = Wire.endTransmission();
215}
216
217uint8_t LSM6::readReg(uint8_t reg)
218{
219 uint8_t value;
220
221 Wire.beginTransmission(address);
222 Wire.write(reg);
223 last_status = Wire.endTransmission();
224 Wire.requestFrom(address, (uint8_t)1);
225 value = Wire.read();
226 Wire.endTransmission();
227
228 return value;
229}
230
231// Reads the 3 accelerometer channels and stores them in vector a
233{
234 Wire.beginTransmission(address);
235 // automatic increment of register address is enabled by default (IF_INC in CTRL3_C)
236 Wire.write(OUTX_L_XL);
237 Wire.endTransmission();
238 Wire.requestFrom(address, (uint8_t)6);
239
240 uint16_t millis_start = millis();
241 while (Wire.available() < 6)
242 {
243 if (io_timeout > 0 && ((uint16_t)millis() - millis_start) > io_timeout)
244 {
245 did_timeout = true;
246 return;
247 }
248 }
249
250 uint8_t xla = Wire.read();
251 uint8_t xha = Wire.read();
252 uint8_t yla = Wire.read();
253 uint8_t yha = Wire.read();
254 uint8_t zla = Wire.read();
255 uint8_t zha = Wire.read();
256
257 // combine high and low bytes
258 a.x = (int16_t)(xha << 8 | xla);
259 a.y = (int16_t)(yha << 8 | yla);
260 a.z = (int16_t)(zha << 8 | zla);
261}
262
263// Reads the 3 gyro channels and stores them in vector g
265{
266 Wire.beginTransmission(address);
267 // automatic increment of register address is enabled by default (IF_INC in CTRL3_C)
268 Wire.write(OUTX_L_G);
269 Wire.endTransmission();
270 Wire.requestFrom(address, (uint8_t)6);
271
272 uint16_t millis_start = millis();
273 while (Wire.available() < 6)
274 {
275 if (io_timeout > 0 && ((uint16_t)millis() - millis_start) > io_timeout)
276 {
277 did_timeout = true;
278 return;
279 }
280 }
281
282 uint8_t xlg = Wire.read();
283 uint8_t xhg = Wire.read();
284 uint8_t ylg = Wire.read();
285 uint8_t yhg = Wire.read();
286 uint8_t zlg = Wire.read();
287 uint8_t zhg = Wire.read();
288
289 // combine high and low bytes
290 g.x = (int16_t)(xhg << 8 | xlg);
291 g.y = (int16_t)(yhg << 8 | ylg);
292 g.z = (int16_t)(zhg << 8 | zlg);
293
294 dps.x = g.x * mdps / 1000.;
295 dps.y = g.y * mdps / 1000.;
296 dps.z = g.z * mdps / 1000.;
297}
298
299// Reads all 6 channels of the LSM6 and stores them in the object variables
300void LSM6::read(void)
301{
302 readAcc();
303 readGyro();
304}
305
306// void LSM6::vector_normalize(vector<float> *a)
307// {
308// float mag = sqrt(vector_dot(a, a));
309// a->x /= mag;
310// a->y /= mag;
311// a->z /= mag;
312// }
313
314// Private Methods //////////////////////////////////////////////////////////////
315
316int16_t LSM6::testReg(uint8_t address, regAddr reg)
317{
318 Wire.beginTransmission(address);
319 Wire.write((uint8_t)reg);
320 if (Wire.endTransmission() != 0)
321 {
322 return TEST_REG_ERROR;
323 }
324
325 Wire.requestFrom(address, (uint8_t)1);
326 if (Wire.available())
327 {
328 return Wire.read();
329 }
330 else
331 {
332 return TEST_REG_ERROR;
333 }
334}
#define TEST_REG_ERROR
Definition: LSM6.cpp:12
#define DS33_SA0_LOW_ADDRESS
Definition: LSM6.cpp:10
#define DS33_SA0_HIGH_ADDRESS
Definition: LSM6.cpp:9
#define DS33_WHO_ID
Definition: LSM6.cpp:14
LSM6(void)
Definition: LSM6.cpp:18
int16_t testReg(uint8_t address, regAddr reg)
Definition: LSM6.cpp:316
void setAccDataOutputRate(ODR)
Definition: LSM6.cpp:112
void setFullScaleAcc(ACC_FS afs)
Definition: LSM6.cpp:73
vector< int16_t > g
Definition: LSM6.h:108
uint8_t last_status
Definition: LSM6.h:116
uint8_t readReg(uint8_t reg)
Definition: LSM6.cpp:217
uint16_t getTimeout(void)
Definition: LSM6.cpp:41
sa0State
Definition: LSM6.h:18
@ sa0_high
Definition: LSM6.h:18
@ sa0_auto
Definition: LSM6.h:18
@ sa0_low
Definition: LSM6.h:18
void setGyroDataOutputRate(ODR)
Definition: LSM6.cpp:100
void readAcc(void)
Definition: LSM6.cpp:232
float mg
Definition: LSM6.h:113
void writeReg(uint8_t reg, uint8_t value)
Definition: LSM6.cpp:209
deviceType _device
Definition: LSM6.h:146
void enableDefault(void)
Definition: LSM6.cpp:184
void setTimeout(uint16_t timeout)
Definition: LSM6.cpp:36
bool did_timeout
Definition: LSM6.h:150
void read(void)
Definition: LSM6.cpp:300
uint8_t address
Definition: LSM6.h:147
ACC_FS
Definition: LSM6.h:20
@ ACC_FS8
Definition: LSM6.h:20
@ ACC_FS16
Definition: LSM6.h:20
@ ACC_FS4
Definition: LSM6.h:20
@ ACC_FS2
Definition: LSM6.h:20
void readGyro(void)
Definition: LSM6.cpp:264
GYRO_FS
Definition: LSM6.h:21
@ GYRO_FS245
Definition: LSM6.h:21
@ GYRO_FS1000
Definition: LSM6.h:21
@ GYRO_FS2000
Definition: LSM6.h:21
@ GYRO_FS500
Definition: LSM6.h:21
uint16_t io_timeout
Definition: LSM6.h:149
bool timeoutOccurred(void)
Definition: LSM6.cpp:29
float mdps
Definition: LSM6.h:112
regAddr
Definition: LSM6.h:36
@ WHO_AM_I
Definition: LSM6.h:48
@ CTRL2_G
Definition: LSM6.h:50
@ OUTX_L_G
Definition: LSM6.h:67
@ CTRL1_XL
Definition: LSM6.h:49
@ OUTX_L_XL
Definition: LSM6.h:73
@ CTRL3_C
Definition: LSM6.h:51
void setFullScaleGyro(GYRO_FS gfs)
Definition: LSM6.cpp:46
ODR
Definition: LSM6.h:23
@ ODR166k
Definition: LSM6.h:31
bool init(deviceType device=device_auto, sa0State sa0=sa0_auto)
Definition: LSM6.cpp:125
vector< int16_t > a
Definition: LSM6.h:107
deviceType
Definition: LSM6.h:17
@ device_DS33
Definition: LSM6.h:17
@ device_auto
Definition: LSM6.h:17
vector< float > dps
Definition: LSM6.h:109