PX4 Firmware
PX4 Autopilot Software http://px4.io
LSM303D.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2013-2019 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file LSM303D.cpp
36  * Driver for the ST LSM303D MEMS accelerometer / magnetometer connected via SPI.
37  */
38 
39 #include "LSM303D.hpp"
40 
41 /*
42  list of registers that will be checked in check_registers(). Note
43  that ADDR_WHO_AM_I must be first in the list.
44  */
45 static constexpr uint8_t _checked_registers[] = {
54 };
55 
56 LSM303D::LSM303D(int bus, uint32_t device, enum Rotation rotation) :
57  SPI("LSM303D", nullptr, bus, device, SPIDEV_MODE3, 11 * 1000 * 1000),
58  ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(get_device_id())),
59  _px4_accel(get_device_id(), ORB_PRIO_DEFAULT, rotation),
60  _px4_mag(get_device_id(), ORB_PRIO_LOW, rotation),
61  _accel_sample_perf(perf_alloc(PC_ELAPSED, "lsm303d: acc_read")),
62  _mag_sample_perf(perf_alloc(PC_ELAPSED, "lsm303d: mag_read")),
63  _bad_registers(perf_alloc(PC_COUNT, "lsm303d: bad_reg")),
64  _bad_values(perf_alloc(PC_COUNT, "lsm303d: bad_val")),
65  _accel_duplicates(perf_alloc(PC_COUNT, "lsm303d: acc_dupe"))
66 {
69  _px4_mag.set_external(external());
70 }
71 
73 {
74  // make sure we are truly inactive
75  stop();
76 
77  // delete the perf counter
83 }
84 
85 int
87 {
88  /* do SPI init (and probe) first */
89  int ret = SPI::init();
90 
91  if (ret != OK) {
92  PX4_ERR("SPI init failed (%i)", ret);
93  return PX4_ERROR;
94  }
95 
96  reset();
97 
98  start();
99 
100  return ret;
101 }
102 
103 void
105 {
106  uint8_t a = read_reg(0x02);
107  write_reg(0x02, (0x10 | a));
108  a = read_reg(0x02);
109  write_reg(0x02, (0xF7 & a));
110  a = read_reg(0x15);
111  write_reg(0x15, (0x80 | a));
112  a = read_reg(0x02);
113  write_reg(0x02, (0xE7 & a));
114 }
115 
116 void
118 {
119  // ensure the chip doesn't interpret any other bus traffic as I2C
120  disable_i2c();
121 
122  // enable accel
125 
126  // enable mag
129  write_checked_reg(ADDR_CTRL_REG3, 0x04); // DRDY on ACCEL on INT1
130  write_checked_reg(ADDR_CTRL_REG4, 0x04); // DRDY on MAG on INT2
131 
134 
135  // we setup the anti-alias on-chip filter as 50Hz. We believe
136  // this operates in the analog domain, and is critical for
137  // anti-aliasing. The 2 pole software filter is designed to
138  // operate in conjunction with this on-chip filter
140 
143 }
144 
145 int
147 {
148  // read dummy value to void to clear SPI statemachine on sensor
150 
151  // verify that the device is attached and functioning
152  if (read_reg(ADDR_WHO_AM_I) == WHO_I_AM) {
154  return OK;
155  }
156 
157  return -EIO;
158 }
159 
160 uint8_t
161 LSM303D::read_reg(unsigned reg)
162 {
163  uint8_t cmd[2] {};
164  cmd[0] = reg | DIR_READ;
165 
166  transfer(cmd, cmd, sizeof(cmd));
167 
168  return cmd[1];
169 }
170 
171 void
172 LSM303D::write_reg(unsigned reg, uint8_t value)
173 {
174  uint8_t cmd[2] {};
175 
176  cmd[0] = reg | DIR_WRITE;
177  cmd[1] = value;
178 
179  transfer(cmd, nullptr, sizeof(cmd));
180 }
181 
182 void
183 LSM303D::write_checked_reg(unsigned reg, uint8_t value)
184 {
185  write_reg(reg, value);
186 
187  for (uint8_t i = 0; i < LSM303D_NUM_CHECKED_REGISTERS; i++) {
188  if (reg == _checked_registers[i]) {
189  _checked_values[i] = value;
190  }
191  }
192 }
193 
194 void
195 LSM303D::modify_reg(unsigned reg, uint8_t clearbits, uint8_t setbits)
196 {
197  uint8_t val = read_reg(reg);
198  val &= ~clearbits;
199  val |= setbits;
200  write_checked_reg(reg, val);
201 }
202 
203 int
205 {
206  uint8_t setbits = 0;
207  uint8_t clearbits = REG2_FULL_SCALE_BITS_A;
208  float new_scale_g_digit = 0.0f;
209 
210  if (max_g == 0) {
211  max_g = 16;
212  }
213 
214  if (max_g <= 2) {
215  // accel_range_m_s2 = 2.0f * CONSTANTS_ONE_G;
216  setbits |= REG2_FULL_SCALE_2G_A;
217  new_scale_g_digit = 0.061e-3f;
218 
219  } else if (max_g <= 4) {
220  // accel_range_m_s2 = 4.0f * CONSTANTS_ONE_G;
221  setbits |= REG2_FULL_SCALE_4G_A;
222  new_scale_g_digit = 0.122e-3f;
223 
224  } else if (max_g <= 6) {
225  // accel_range_m_s2 = 6.0f * CONSTANTS_ONE_G;
226  setbits |= REG2_FULL_SCALE_6G_A;
227  new_scale_g_digit = 0.183e-3f;
228 
229  } else if (max_g <= 8) {
230  // accel_range_m_s2 = 8.0f * CONSTANTS_ONE_G;
231  setbits |= REG2_FULL_SCALE_8G_A;
232  new_scale_g_digit = 0.244e-3f;
233 
234  } else if (max_g <= 16) {
235  // accel_range_m_s2 = 16.0f * CONSTANTS_ONE_G;
236  setbits |= REG2_FULL_SCALE_16G_A;
237  new_scale_g_digit = 0.732e-3f;
238 
239  } else {
240  return -EINVAL;
241  }
242 
243  float accel_range_scale = new_scale_g_digit * CONSTANTS_ONE_G;
244 
245  _px4_accel.set_scale(accel_range_scale);
246 
247  modify_reg(ADDR_CTRL_REG2, clearbits, setbits);
248 
249  return OK;
250 }
251 
252 int
253 LSM303D::mag_set_range(unsigned max_ga)
254 {
255  uint8_t setbits = 0;
256  uint8_t clearbits = REG6_FULL_SCALE_BITS_M;
257  float new_scale_ga_digit = 0.0f;
258 
259  if (max_ga == 0) {
260  max_ga = 12;
261  }
262 
263  if (max_ga <= 2) {
264  // mag_range_ga = 2;
265  setbits |= REG6_FULL_SCALE_2GA_M;
266  new_scale_ga_digit = 0.080e-3f;
267 
268  } else if (max_ga <= 4) {
269  // mag_range_ga = 4;
270  setbits |= REG6_FULL_SCALE_4GA_M;
271  new_scale_ga_digit = 0.160e-3f;
272 
273  } else if (max_ga <= 8) {
274  // mag_range_ga = 8;
275  setbits |= REG6_FULL_SCALE_8GA_M;
276  new_scale_ga_digit = 0.320e-3f;
277 
278  } else if (max_ga <= 12) {
279  // mag_range_ga = 12;
280  setbits |= REG6_FULL_SCALE_12GA_M;
281  new_scale_ga_digit = 0.479e-3f;
282 
283  } else {
284  return -EINVAL;
285  }
286 
287  _px4_mag.set_scale(new_scale_ga_digit);
288 
289  modify_reg(ADDR_CTRL_REG6, clearbits, setbits);
290 
291  return OK;
292 }
293 
294 int
296 {
297  uint8_t setbits = 0;
298  uint8_t clearbits = REG2_ANTIALIAS_FILTER_BW_BITS_A;
299 
300  if (bandwidth == 0) {
301  bandwidth = 773;
302  }
303 
304  if (bandwidth <= 50) {
305  // accel_onchip_filter_bandwith = 50;
306  setbits |= REG2_AA_FILTER_BW_50HZ_A;
307 
308  } else if (bandwidth <= 194) {
309  // accel_onchip_filter_bandwith = 194;
310  setbits |= REG2_AA_FILTER_BW_194HZ_A;
311 
312  } else if (bandwidth <= 362) {
313  // accel_onchip_filter_bandwith = 362;
314  setbits |= REG2_AA_FILTER_BW_362HZ_A;
315 
316  } else if (bandwidth <= 773) {
317  // accel_onchip_filter_bandwith = 773;
318  setbits |= REG2_AA_FILTER_BW_773HZ_A;
319 
320  } else {
321  return -EINVAL;
322  }
323 
324  modify_reg(ADDR_CTRL_REG2, clearbits, setbits);
325 
326  return OK;
327 }
328 
329 int
330 LSM303D::accel_set_samplerate(unsigned frequency)
331 {
332  uint8_t setbits = 0;
333  uint8_t clearbits = REG1_RATE_BITS_A;
334 
335  if (frequency == 0) {
336  frequency = 1600;
337  }
338 
339  int accel_samplerate = 100;
340 
341  if (frequency <= 100) {
342  setbits |= REG1_RATE_100HZ_A;
343  accel_samplerate = 100;
344 
345  } else if (frequency <= 200) {
346  setbits |= REG1_RATE_200HZ_A;
347  accel_samplerate = 200;
348 
349  } else if (frequency <= 400) {
350  setbits |= REG1_RATE_400HZ_A;
351  accel_samplerate = 400;
352 
353  } else if (frequency <= 800) {
354  setbits |= REG1_RATE_800HZ_A;
355  accel_samplerate = 800;
356 
357  } else if (frequency <= 1600) {
358  setbits |= REG1_RATE_1600HZ_A;
359  accel_samplerate = 1600;
360 
361  } else {
362  return -EINVAL;
363  }
364 
365  _call_accel_interval = 1000000 / accel_samplerate;
366  _px4_accel.set_sample_rate(accel_samplerate);
367 
368  modify_reg(ADDR_CTRL_REG1, clearbits, setbits);
369 
370  return OK;
371 }
372 
373 int
374 LSM303D::mag_set_samplerate(unsigned frequency)
375 {
376  uint8_t setbits = 0;
377  uint8_t clearbits = REG5_RATE_BITS_M;
378 
379  if (frequency == 0) {
380  frequency = 100;
381  }
382 
383  int mag_samplerate = 100;
384 
385  if (frequency <= 25) {
386  setbits |= REG5_RATE_25HZ_M;
387  mag_samplerate = 25;
388 
389  } else if (frequency <= 50) {
390  setbits |= REG5_RATE_50HZ_M;
391  mag_samplerate = 50;
392 
393  } else if (frequency <= 100) {
394  setbits |= REG5_RATE_100HZ_M;
395  mag_samplerate = 100;
396 
397  } else {
398  return -EINVAL;
399  }
400 
401  _call_mag_interval = 1000000 / mag_samplerate;
402 
403  modify_reg(ADDR_CTRL_REG5, clearbits, setbits);
404 
405  return OK;
406 }
407 
408 void
410 {
411  // make sure we are stopped first
412  stop();
413 
414  // start polling at the specified rate
415  ScheduleOnInterval(_call_accel_interval - LSM303D_TIMER_REDUCTION);
416 }
417 
418 void
420 {
421  ScheduleClear();
422 }
423 
424 void
426 {
427  // make another accel measurement
429 
432  }
433 }
434 
435 void
437 {
438  uint8_t v = 0;
439 
440  if ((v = read_reg(_checked_registers[_checked_next])) != _checked_values[_checked_next]) {
441  /*
442  if we get the wrong value then we know the SPI bus
443  or sensor is very sick. We set _register_wait to 20
444  and wait until we have seen 20 good values in a row
445  before we consider the sensor to be OK again.
446  */
448 
449  /*
450  try to fix the bad register value. We only try to
451  fix one per loop to prevent a bad sensor hogging the
452  bus. We skip zero as that is the WHO_AM_I, which
453  is not writeable
454  */
455  if (_checked_next != 0) {
456  write_reg(_checked_registers[_checked_next], _checked_values[_checked_next]);
457  }
458 
459  _register_wait = 20;
460  }
461 
462  _checked_next = (_checked_next + 1) % LSM303D_NUM_CHECKED_REGISTERS;
463 }
464 
465 void
467 {
469 
470  // status register and data as read back from the device
471 #pragma pack(push, 1)
472  struct {
473  uint8_t cmd;
474  uint8_t status;
475  int16_t x;
476  int16_t y;
477  int16_t z;
478  } raw_accel_report{};
479 #pragma pack(pop)
480 
481  check_registers();
482 
483  if (_register_wait != 0) {
484  // we are waiting for some good transfers before using
485  // the sensor again.
486  _register_wait--;
488  return;
489  }
490 
491  /* fetch data from the sensor */
492  const hrt_abstime timestamp_sample = hrt_absolute_time();
493  raw_accel_report.cmd = ADDR_STATUS_A | DIR_READ | ADDR_INCREMENT;
494  transfer((uint8_t *)&raw_accel_report, (uint8_t *)&raw_accel_report, sizeof(raw_accel_report));
495 
496  if (!(raw_accel_report.status & REG_STATUS_A_NEW_ZYXADA)) {
499  return;
500  }
501 
502  /*
503  we have logs where the accelerometers get stuck at a fixed
504  large value. We want to detect this and mark the sensor as
505  being faulty
506  */
507  if (((_last_accel[0] - raw_accel_report.x) == 0) &&
508  ((_last_accel[1] - raw_accel_report.y) == 0) &&
509  ((_last_accel[2] - raw_accel_report.z) == 0)) {
510 
512 
513  } else {
515  }
516 
517  if (_constant_accel_count > 100) {
518  // we've had 100 constant accel readings with large
519  // values. The sensor is almost certainly dead. We
520  // will raise the error_count so that the top level
521  // flight code will know to avoid this sensor, but
522  // we'll still give the data so that it can be logged
523  // and viewed
525 
527 
529  return;
530  }
531 
532  // report the error count as the sum of the number of bad
533  // register reads and bad values. This allows the higher level
534  // code to decide if it should use this sensor based on
535  // whether it has had failures
537  _px4_accel.update(timestamp_sample, raw_accel_report.x, raw_accel_report.y, raw_accel_report.z);
538 
539  _last_accel[0] = raw_accel_report.x;
540  _last_accel[1] = raw_accel_report.y;
541  _last_accel[2] = raw_accel_report.z;
542 
544 }
545 
546 void
548 {
550 
551  // status register and data as read back from the device
552 #pragma pack(push, 1)
553  struct {
554  uint8_t cmd;
555  int16_t temperature;
556  uint8_t status;
557  int16_t x;
558  int16_t y;
559  int16_t z;
560  } raw_mag_report{};
561 #pragma pack(pop)
562 
563  // fetch data from the sensor
564  const hrt_abstime timestamp_sample = hrt_absolute_time();
565  raw_mag_report.cmd = ADDR_OUT_TEMP_L | DIR_READ | ADDR_INCREMENT;
566  transfer((uint8_t *)&raw_mag_report, (uint8_t *)&raw_mag_report, sizeof(raw_mag_report));
567 
568  /* remember the temperature. The datasheet isn't clear, but it
569  * seems to be a signed offset from 25 degrees C in units of 0.125C
570  */
571  _last_temperature = 25.0f + (raw_mag_report.temperature * 0.125f);
574 
576  _px4_mag.set_external(external());
577  _px4_mag.update(timestamp_sample, raw_mag_report.x, raw_mag_report.y, raw_mag_report.z);
578 
579  _mag_last_measure = timestamp_sample;
580 
582 }
583 
584 void
586 {
592 
593  ::printf("checked_next: %u\n", _checked_next);
594 
595  for (uint8_t i = 0; i < LSM303D_NUM_CHECKED_REGISTERS; i++) {
596  uint8_t v = read_reg(_checked_registers[i]);
597 
598  if (v != _checked_values[i]) {
599  ::printf("reg %02x:%02x should be %02x\n",
600  (unsigned)_checked_registers[i],
601  (unsigned)v,
602  (unsigned)_checked_values[i]);
603  }
604  }
605 }
void check_registers(void)
check key registers for correct values
Definition: LSM303D.cpp:436
#define REG5_RES_HIGH_M
Definition: LSM303D.hpp:103
uint8_t _checked_values[LSM303D_NUM_CHECKED_REGISTERS]
Definition: LSM303D.hpp:295
#define REG2_FULL_SCALE_8G_A
Definition: LSM303D.hpp:98
int mag_set_samplerate(unsigned frequency)
Set the LSM303D internal mag sampling frequency.
Definition: LSM303D.cpp:374
perf_counter_t _bad_registers
Definition: LSM303D.hpp:278
#define REG7_CONT_MODE_M
Definition: LSM303D.hpp:121
static struct vehicle_status_s status
Definition: Commander.cpp:138
uint8_t _constant_accel_count
Definition: LSM303D.hpp:285
void write_checked_reg(unsigned reg, uint8_t value)
Write a register in the LSM303D, updating _checked_values.
Definition: LSM303D.cpp:183
measure the time elapsed performing an event
Definition: perf_counter.h:56
#define REG5_RATE_BITS_M
Definition: LSM303D.hpp:106
void set_sample_rate(unsigned rate)
void set_device_type(uint8_t devtype)
#define REG2_FULL_SCALE_4G_A
Definition: LSM303D.hpp:96
#define WHO_I_AM
Definition: l3gd20.cpp:65
PX4Accelerometer _px4_accel
Definition: LSM303D.hpp:270
void set_error_count(uint64_t error_count)
#define REG2_FULL_SCALE_BITS_A
Definition: LSM303D.hpp:94
#define LSM303D_ACCEL_DEFAULT_ONCHIP_FILTER_FREQ
Definition: LSM303D.hpp:128
#define REG2_AA_FILTER_BW_773HZ_A
Definition: LSM303D.hpp:89
void reset()
Definition: LSM303D.cpp:117
void update(hrt_abstime timestamp, float x, float y, float z)
#define ADDR_CTRL_REG3
Definition: lps25h.cpp:56
#define ADDR_WHO_AM_I
Definition: lps25h.cpp:52
#define ADDR_CTRL_REG2
Definition: lps25h.cpp:55
#define REG2_ANTIALIAS_FILTER_BW_BITS_A
Definition: LSM303D.hpp:88
void Run() override
Definition: LSM303D.cpp:425
virtual int probe()
Definition: LSM303D.cpp:146
#define REG_STATUS_A_NEW_ZYXADA
Definition: LSM303D.hpp:123
#define REG2_AA_FILTER_BW_362HZ_A
Definition: LSM303D.hpp:91
#define LSM303D_MAG_DEFAULT_RANGE_GA
Definition: LSM303D.hpp:130
void modify_reg(unsigned reg, uint8_t clearbits, uint8_t setbits)
Modify a register in the LSM303D.
Definition: LSM303D.cpp:195
uint8_t read_reg(unsigned reg)
Read a register from the LSM303D.
Definition: LSM303D.cpp:161
int init() override
Definition: LSM303D.cpp:86
#define LSM303D_ACCEL_DEFAULT_RANGE_G
Definition: LSM303D.hpp:126
#define ADDR_INCREMENT
Definition: ms5611_spi.cpp:45
PX4Magnetometer _px4_mag
Definition: LSM303D.hpp:271
Namespace encapsulating all device framework classes, functions and data.
Definition: CDev.cpp:47
count the number of times an event occurs
Definition: perf_counter.h:55
int accel_set_onchip_lowpass_filter_bandwidth(unsigned bandwidth)
Set the LSM303D on-chip anti-alias filter bandwith.
Definition: LSM303D.cpp:295
#define LSM303D_TIMER_REDUCTION
Definition: LSM303D.hpp:139
uint8_t _register_wait
Definition: LSM303D.hpp:282
static constexpr float CONSTANTS_ONE_G
Definition: geo.h:51
void set_error_count(uint64_t error_count)
#define ADDR_CTRL_REG7
Definition: LSM303D.hpp:68
#define DRV_ACC_DEVTYPE_LSM303D
Definition: drv_sensor.h:65
void set_external(bool external)
float _last_temperature
Definition: LSM303D.hpp:289
#define REG6_FULL_SCALE_12GA_M
Definition: LSM303D.hpp:119
#define ADDR_CTRL_REG5
Definition: l3gd20.cpp:93
#define DIR_READ
Definition: bmp388_spi.cpp:46
int accel_set_samplerate(unsigned frequency)
Set the LSM303D internal accel sampling frequency.
Definition: LSM303D.cpp:330
#define DRV_MAG_DEVTYPE_LSM303D
Definition: drv_sensor.h:56
#define REG5_RATE_100HZ_M
Definition: LSM303D.hpp:112
void print_info()
Diagnostics - print some basic information about the driver.
Definition: LSM303D.cpp:585
#define REG6_FULL_SCALE_4GA_M
Definition: LSM303D.hpp:117
perf_counter_t _accel_sample_perf
Definition: LSM303D.hpp:276
perf_counter_t _bad_values
Definition: LSM303D.hpp:279
void perf_count(perf_counter_t handle)
Count a performance event.
#define REG1_BDU_UPDATE
Definition: LSM303D.hpp:83
#define ADDR_CTRL_REG4
Definition: lps25h.cpp:57
void perf_free(perf_counter_t handle)
Free a counter.
void set_temperature(float temperature)
void init()
Activates/configures the hardware registers.
#define LSM303D_ACCEL_DEFAULT_RATE
Definition: LSM303D.hpp:127
#define REG2_FULL_SCALE_2G_A
Definition: LSM303D.hpp:95
void set_temperature(float temperature)
#define REG6_FULL_SCALE_8GA_M
Definition: LSM303D.hpp:118
#define perf_alloc(a, b)
Definition: px4io.h:59
void update(hrt_abstime timestamp, int16_t x, int16_t y, int16_t z)
#define REG1_X_ENABLE_A
Definition: LSM303D.hpp:86
Rotation
Enum for board and external compass rotations.
Definition: rotation.h:51
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
#define ADDR_OUT_TEMP_L
Definition: LSM303D.hpp:57
static hrt_abstime hrt_elapsed_time(const hrt_abstime *then)
Compute the delta between a timestamp taken in the past and now.
Definition: drv_hrt.h:102
#define REG2_FULL_SCALE_16G_A
Definition: LSM303D.hpp:99
unsigned _call_accel_interval
Definition: LSM303D.hpp:273
void write_reg(unsigned reg, uint8_t value)
Write a register in the LSM303D.
Definition: LSM303D.cpp:172
#define REG2_AA_FILTER_BW_194HZ_A
Definition: LSM303D.hpp:90
void perf_end(perf_counter_t handle)
End a performance event.
unsigned _call_mag_interval
Definition: LSM303D.hpp:274
__BEGIN_DECLS typedef uint64_t hrt_abstime
Absolute time, in microsecond units.
Definition: drv_hrt.h:58
#define REG1_RATE_BITS_A
Definition: LSM303D.hpp:70
perf_counter_t _accel_duplicates
Definition: LSM303D.hpp:280
void set_scale(float scale)
void set_scale(float scale)
#define DIR_WRITE
Definition: bmp388_spi.cpp:47
#define REG6_FULL_SCALE_BITS_M
Definition: LSM303D.hpp:115
LSM303D(int bus, uint32_t device, enum Rotation rotation)
Definition: LSM303D.cpp:56
#define REG5_RATE_25HZ_M
Definition: LSM303D.hpp:110
#define ADDR_CTRL_REG1
Definition: lps25h.cpp:54
#define LSM303D_MAG_DEFAULT_RATE
Definition: LSM303D.hpp:131
void perf_print_counter(perf_counter_t handle)
Print one performance counter to stdout.
#define REG5_RATE_50HZ_M
Definition: LSM303D.hpp:111
uint64_t perf_event_count(perf_counter_t handle)
Return current event_count.
static constexpr uint8_t _checked_registers[]
Definition: LSM303D.cpp:45
Definition: bst.cpp:62
perf_counter_t _mag_sample_perf
Definition: LSM303D.hpp:277
#define REG2_AA_FILTER_BW_50HZ_A
Definition: LSM303D.hpp:92
virtual ~LSM303D()
Definition: LSM303D.cpp:72
void measureAccelerometer()
Fetch accel measurements from the sensor and update the report ring.
Definition: LSM303D.cpp:466
#define REG1_Y_ENABLE_A
Definition: LSM303D.hpp:85
#define REG1_RATE_200HZ_A
Definition: LSM303D.hpp:78
int accel_set_range(unsigned max_g)
Set the LSM303D accel measurement range.
Definition: LSM303D.cpp:204
uint8_t _checked_next
Definition: LSM303D.hpp:296
hrt_abstime _mag_last_measure
Definition: LSM303D.hpp:287
Driver for the ST LSM303D MEMS accelerometer / magnetometer connected via SPI.
#define OK
Definition: uavcan_main.cpp:71
#define REG1_Z_ENABLE_A
Definition: LSM303D.hpp:84
void stop()
Definition: LSM303D.cpp:419
#define ADDR_CTRL_REG6
Definition: LSM303D.hpp:67
static constexpr int LSM303D_NUM_CHECKED_REGISTERS
Definition: LSM303D.hpp:294
void set_device_type(uint8_t devtype)
#define REG1_RATE_100HZ_A
Definition: LSM303D.hpp:77
int mag_set_range(unsigned max_g)
Set the LSM303D mag measurement range.
Definition: LSM303D.cpp:253
#define ADDR_STATUS_A
Definition: LSM303D.hpp:59
#define REG6_FULL_SCALE_2GA_M
Definition: LSM303D.hpp:116
void disable_i2c()
disable I2C on the chip
Definition: LSM303D.cpp:104
void measureMagnetometer()
Fetch mag measurements from the sensor and update the report ring.
Definition: LSM303D.cpp:547
#define REG1_RATE_800HZ_A
Definition: LSM303D.hpp:80
void perf_begin(perf_counter_t handle)
Begin a performance event.
#define REG5_ENABLE_T
Definition: LSM303D.hpp:101
#define REG1_RATE_1600HZ_A
Definition: LSM303D.hpp:81
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
#define REG1_RATE_400HZ_A
Definition: LSM303D.hpp:79
#define REG2_FULL_SCALE_6G_A
Definition: LSM303D.hpp:97
void start()
Definition: LSM303D.cpp:409
int16_t _last_accel[3]
Definition: LSM303D.hpp:284