forked from pololu/l3g-arduino
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathL3G.cpp
More file actions
148 lines (127 loc) · 3.47 KB
/
L3G.cpp
File metadata and controls
148 lines (127 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <L3G.h>
#include <Wire.h>
#include <math.h>
// Defines ////////////////////////////////////////////////////////////////
// The Arduino two-wire interface uses a 7-bit number for the address,
// and sets the last bit correctly based on reads and writes
#define L3G4200D_ADDRESS_SA0_LOW (0xD0 >> 1)
#define L3G4200D_ADDRESS_SA0_HIGH (0xD2 >> 1)
#define L3GD20_ADDRESS_SA0_LOW (0xD4 >> 1)
#define L3GD20_ADDRESS_SA0_HIGH (0xD6 >> 1)
// Public Methods //////////////////////////////////////////////////////////////
bool L3G::init(byte device, byte sa0)
{
_device = device;
switch (_device)
{
case L3G4200D_DEVICE:
if (sa0 == L3G_SA0_LOW)
{
address = L3G4200D_ADDRESS_SA0_LOW;
return true;
}
else if (sa0 == L3G_SA0_HIGH)
{
address = L3G4200D_ADDRESS_SA0_HIGH;
return true;
}
else
return autoDetectAddress();
break;
case L3GD20_DEVICE:
if (sa0 == L3G_SA0_LOW)
{
address = L3GD20_ADDRESS_SA0_LOW;
return true;
}
else if (sa0 == L3G_SA0_HIGH)
{
address = L3GD20_ADDRESS_SA0_HIGH;
return true;
}
else
return autoDetectAddress();
break;
default:
return autoDetectAddress();
}
}
// Turns on the L3G's gyro and places it in normal mode.
void L3G::enableDefault(void)
{
// 0x0F = 0b00001111
// Normal power mode, all axes enabled
writeReg(L3G_CTRL_REG1, 0x0F);
}
// Writes a gyro register
void L3G::writeReg(byte reg, byte value)
{
Wire.beginTransmission(address);
Wire.write(reg);
Wire.write(value);
Wire.endTransmission();
}
// Reads a gyro register
byte L3G::readReg(byte reg)
{
byte value;
Wire.beginTransmission(address);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom(address, (byte)1);
value = Wire.read();
Wire.endTransmission();
return value;
}
// Reads the 3 gyro channels and stores them in vector g
void L3G::read()
{
Wire.beginTransmission(address);
// assert the MSB of the address to get the gyro
// to do slave-transmit subaddress updating.
Wire.write(L3G_OUT_X_L | (1 << 7));
Wire.endTransmission();
Wire.requestFrom(address, (byte)6);
while (Wire.available() < 6);
uint8_t xlg = Wire.read();
uint8_t xhg = Wire.read();
uint8_t ylg = Wire.read();
uint8_t yhg = Wire.read();
uint8_t zlg = Wire.read();
uint8_t zhg = Wire.read();
// combine high and low bytes
g.x = (int16_t)(xhg << 8 | xlg);
g.y = (int16_t)(yhg << 8 | ylg);
g.z = (int16_t)(zhg << 8 | zlg);
}
void L3G::vector_cross(const vector *a,const vector *b, vector *out)
{
out->x = a->y*b->z - a->z*b->y;
out->y = a->z*b->x - a->x*b->z;
out->z = a->x*b->y - a->y*b->x;
}
float L3G::vector_dot(const vector *a,const vector *b)
{
return a->x*b->x+a->y*b->y+a->z*b->z;
}
void L3G::vector_normalize(vector *a)
{
float mag = sqrt(vector_dot(a,a));
a->x /= mag;
a->y /= mag;
a->z /= mag;
}
// Private Methods //////////////////////////////////////////////////////////////
bool L3G::autoDetectAddress(void)
{
// try each possible address and stop if reading WHO_AM_I returns the expected response
address = L3G4200D_ADDRESS_SA0_LOW;
if (readReg(L3G_WHO_AM_I) == 0xD3) return true;
address = L3G4200D_ADDRESS_SA0_HIGH;
if (readReg(L3G_WHO_AM_I) == 0xD3) return true;
address = L3GD20_ADDRESS_SA0_LOW;
if (readReg(L3G_WHO_AM_I) == 0xD4) return true;
address = L3GD20_ADDRESS_SA0_HIGH;
if (readReg(L3G_WHO_AM_I) == 0xD4) return true;
return false;
}