source: rtos_arduino/trunk/arduino_lib/libraries/ZumoShield/L3G.cpp@ 232

Last change on this file since 232 was 232, checked in by ertl-honda, 8 years ago

Zumo用ライブラリの追加

File size: 6.2 KB
Line 
1#include <L3G.h>
2#include <Wire.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 D20_SA0_HIGH_ADDRESS 0b1101011 // also applies to D20H
10#define D20_SA0_LOW_ADDRESS 0b1101010 // also applies to D20H
11#define L3G4200D_SA0_HIGH_ADDRESS 0b1101001
12#define L3G4200D_SA0_LOW_ADDRESS 0b1101000
13
14#define TEST_REG_ERROR -1
15
16#define D20H_WHO_ID 0xD7
17#define D20_WHO_ID 0xD4
18#define L3G4200D_WHO_ID 0xD3
19
20// Constructors ////////////////////////////////////////////////////////////////
21
22L3G::L3G(void)
23{
24 _device = device_auto;
25
26 io_timeout = 0; // 0 = no timeout
27 did_timeout = false;
28}
29
30// Public Methods //////////////////////////////////////////////////////////////
31
32// Did a timeout occur in read() since the last call to timeoutOccurred()?
33bool L3G::timeoutOccurred()
34{
35 bool tmp = did_timeout;
36 did_timeout = false;
37 return tmp;
38}
39
40void L3G::setTimeout(unsigned int timeout)
41{
42 io_timeout = timeout;
43}
44
45unsigned int L3G::getTimeout()
46{
47 return io_timeout;
48}
49
50bool L3G::init(deviceType device, sa0State sa0)
51{
52 int id;
53
54 // perform auto-detection unless device type and SA0 state were both specified
55 if (device == device_auto || sa0 == sa0_auto)
56 {
57 // check for L3GD20H, D20 if device is unidentified or was specified to be one of these types
58 if (device == device_auto || device == device_D20H || device == device_D20)
59 {
60 // check SA0 high address unless SA0 was specified to be low
61 if (sa0 != sa0_low && (id = testReg(D20_SA0_HIGH_ADDRESS, WHO_AM_I)) != TEST_REG_ERROR)
62 {
63 // device responds to address 1101011; it's a D20H or D20 with SA0 high
64 sa0 = sa0_high;
65 if (device == device_auto)
66 {
67 // use ID from WHO_AM_I register to determine device type
68 device = (id == D20H_WHO_ID) ? device_D20H : device_D20;
69 }
70 }
71 // check SA0 low address unless SA0 was specified to be high
72 else if (sa0 != sa0_high && (id = testReg(D20_SA0_LOW_ADDRESS, WHO_AM_I)) != TEST_REG_ERROR)
73 {
74 // device responds to address 1101010; it's a D20H or D20 with SA0 low
75 sa0 = sa0_low;
76 if (device == device_auto)
77 {
78 // use ID from WHO_AM_I register to determine device type
79 device = (id == D20H_WHO_ID) ? device_D20H : device_D20;
80 }
81 }
82 }
83
84 // check for L3G4200D if device is still unidentified or was specified to be this type
85 if (device == device_auto || device == device_4200D)
86 {
87 if (sa0 != sa0_low && testReg(L3G4200D_SA0_HIGH_ADDRESS, WHO_AM_I) == L3G4200D_WHO_ID)
88 {
89 // device responds to address 1101001; it's a 4200D with SA0 high
90 device = device_4200D;
91 sa0 = sa0_high;
92 }
93 else if (sa0 != sa0_high && testReg(L3G4200D_SA0_LOW_ADDRESS, WHO_AM_I) == L3G4200D_WHO_ID)
94 {
95 // device responds to address 1101000; it's a 4200D with SA0 low
96 device = device_4200D;
97 sa0 = sa0_low;
98 }
99 }
100
101 // make sure device and SA0 were successfully detected; otherwise, indicate failure
102 if (device == device_auto || sa0 == sa0_auto)
103 {
104 return false;
105 }
106 }
107
108 _device = device;
109
110 // set device address
111 switch (device)
112 {
113 case device_D20H:
114 case device_D20:
115 address = (sa0 == sa0_high) ? D20_SA0_HIGH_ADDRESS : D20_SA0_LOW_ADDRESS;
116 break;
117
118 case device_4200D:
119 address = (sa0 == sa0_high) ? L3G4200D_SA0_HIGH_ADDRESS : L3G4200D_SA0_LOW_ADDRESS;
120 break;
121 }
122
123 return true;
124}
125
126/*
127Enables the L3G's gyro. Also:
128- Sets gyro full scale (gain) to default power-on value of +/- 250 dps
129 (specified as +/- 245 dps for L3GD20H).
130- Selects 200 Hz ODR (output data rate). (Exact rate is specified as 189.4 Hz
131 for L3GD20H and 190 Hz for L3GD20.)
132Note that this function will also reset other settings controlled by
133the registers it writes to.
134*/
135void L3G::enableDefault(void)
136{
137 if (_device == device_D20H)
138 {
139 // 0x00 = 0b00000000
140 // Low_ODR = 0 (low speed ODR disabled)
141 writeReg(LOW_ODR, 0x00);
142 }
143
144 // 0x00 = 0b00000000
145 // FS = 00 (+/- 250 dps full scale)
146 writeReg(CTRL_REG4, 0x00);
147
148 // 0x6F = 0b01101111
149 // DR = 01 (200 Hz ODR); BW = 10 (50 Hz bandwidth); PD = 1 (normal mode); Zen = Yen = Xen = 1 (all axes enabled)
150 writeReg(CTRL_REG1, 0x6F);
151}
152
153// Writes a gyro register
154void L3G::writeReg(byte reg, byte value)
155{
156 Wire.beginTransmission(address);
157 Wire.write(reg);
158 Wire.write(value);
159 last_status = Wire.endTransmission();
160}
161
162// Reads a gyro register
163byte L3G::readReg(byte reg)
164{
165 byte value;
166
167 Wire.beginTransmission(address);
168 Wire.write(reg);
169 last_status = Wire.endTransmission();
170 Wire.requestFrom(address, (byte)1);
171 value = Wire.read();
172 Wire.endTransmission();
173
174 return value;
175}
176
177// Reads the 3 gyro channels and stores them in vector g
178void L3G::read()
179{
180 Wire.beginTransmission(address);
181 // assert the MSB of the address to get the gyro
182 // to do slave-transmit subaddress updating.
183 Wire.write(OUT_X_L | (1 << 7));
184 Wire.endTransmission();
185 Wire.requestFrom(address, (byte)6);
186
187 unsigned int millis_start = millis();
188 while (Wire.available() < 6)
189 {
190 if (io_timeout > 0 && ((unsigned int)millis() - millis_start) > io_timeout)
191 {
192 did_timeout = true;
193 return;
194 }
195 }
196
197 uint8_t xlg = Wire.read();
198 uint8_t xhg = Wire.read();
199 uint8_t ylg = Wire.read();
200 uint8_t yhg = Wire.read();
201 uint8_t zlg = Wire.read();
202 uint8_t zhg = Wire.read();
203
204 // combine high and low bytes
205 g.x = (int16_t)(xhg << 8 | xlg);
206 g.y = (int16_t)(yhg << 8 | ylg);
207 g.z = (int16_t)(zhg << 8 | zlg);
208}
209
210void L3G::vector_normalize(vector<float> *a)
211{
212 float mag = sqrt(vector_dot(a,a));
213 a->x /= mag;
214 a->y /= mag;
215 a->z /= mag;
216}
217
218// Private Methods //////////////////////////////////////////////////////////////
219
220int L3G::testReg(byte address, regAddr reg)
221{
222 Wire.beginTransmission(address);
223 Wire.write((byte)reg);
224 if (Wire.endTransmission() != 0)
225 {
226 return TEST_REG_ERROR;
227 }
228
229 Wire.requestFrom(address, (byte)1);
230 if (Wire.available())
231 {
232 return Wire.read();
233 }
234 else
235 {
236 return TEST_REG_ERROR;
237 }
238}
Note: See TracBrowser for help on using the repository browser.