Statistics
| Branch: | Tag: | Revision:

amiro-os / components / accel / lis331dlh.cpp @ 10687985

History | View | Annotate | Download (11.27 KB)

1 58fe0e0b Thomas Schöpping
#include <string.h>
2
3
#include <amiro/util/util.h>
4
#include <amiro/bus/spi/HWSPIDriver.hpp>
5
#include <amiro/accel/lis331dlh.hpp>
6
#include <chprintf.h>
7
#include <cmath>  // abs()
8 b4885314 Thomas Schöpping
#include <amiro/Constants.h>
9 58fe0e0b Thomas Schöpping
10
namespace amiro {
11
12
LIS331DLH::
13
LIS331DLH(HWSPIDriver *driver) :
14
  driver(driver),
15
  currentFullScaleConfiguration(FS_2G) {
16
17
}
18
19
LIS331DLH::
20
~LIS331DLH() {
21
22
}
23
24
chibios_rt::EvtSource*
25
LIS331DLH::
26
getEventSource() {
27
  return &this->eventSource;
28
}
29
30
int16_t
31
LIS331DLH::
32
getAcceleration(const uint8_t axis) {
33
34
  return this->accelerations[axis];
35
36
}
37
38
int16_t
39
LIS331DLH::
40
getAccelerationForce(const uint8_t axis) {
41
42
  int16_t result;
43
44
  switch(this->currentFullScaleConfiguration) {
45
  default:
46
  case(FS_2G):
47
    // Should be this->accelerations[axis] * 0.9765625
48
    result = this->accelerations[axis];
49
    break;
50
  case(FS_4G):
51
      // Should be this->accelerations[axis] * 1.953125
52
      result =  this->accelerations[axis] << 1;
53
    break;
54
  case(FS_8G):
55
      // Should be this->accelerations[axis] * 3.90625
56
      result =  this->accelerations[axis] << 2;
57
    break;
58
  }
59
60
  return result;
61
62
}
63
64
msg_t
65
LIS331DLH::
66
main() {
67
68
  this->setName("Lis331dlh");
69
70
  while (!this->shouldTerminate()) {
71
72
    updateSensorData();
73
74
    this->eventSource.broadcastFlags(0);
75
76 b4885314 Thomas Schöpping
    this->waitAnyEventTimeout(ALL_EVENTS, CAN::UPDATE_PERIOD_MSEC);
77 58fe0e0b Thomas Schöpping
78
  }
79
  return RDY_OK;
80
}
81
82
void
83
LIS331DLH::
84
updateSensorData() {
85
86
  const size_t buffer_size = offsetof(LIS331DLH::registers, out_z)
87
                             - offsetof(LIS331DLH::registers, status_reg)
88
                             + MEMBER_SIZE(LIS331DLH::registers, out_z)
89
                             + 1; /* addressing */
90
  uint8_t buffer[buffer_size];
91
  uint8_t sreg;
92
93
  // this might be three-wire so we need to send ones
94
  memset(buffer, 0xFFu, buffer_size);
95
  buffer[0] = offsetof(LIS331DLH::registers, status_reg) | LIS331DLH::SPI_MULT | LIS331DLH::SPI_READ;
96
  this->driver->exchange(buffer, buffer, buffer_size);
97
98
  // assemble data
99
  sreg = buffer[1];
100
101
  if (sreg & LIS331DLH::XDA)
102
    this->accelerations[LIS331DLH::AXIS_X] = int16_t((buffer[3] << 8) | buffer[2]) >> 4;
103
104
  if (sreg & LIS331DLH::YDA)
105
    this->accelerations[LIS331DLH::AXIS_Y] = int16_t((buffer[5] << 8) | buffer[4]) >> 4;
106
107
  if (sreg & LIS331DLH::ZDA)
108
    this->accelerations[LIS331DLH::AXIS_Z] = int16_t((buffer[7] << 8) | buffer[6]) >> 4;
109
110
}
111
112
msg_t
113
LIS331DLH::
114
configure(LIS331DLHConfig *config) {
115
116
  const size_t ctrl_reg_size = offsetof(LIS331DLH::registers, ctrl_reg5)
117
                               - offsetof(LIS331DLH::registers, ctrl_reg1)
118
                               + MEMBER_SIZE(LIS331DLH::registers, ctrl_reg5)
119
                               + 1; /* addressing */
120
  const size_t int_reg_size = offsetof(LIS331DLH::registers, int1_duration)
121
                              - offsetof(LIS331DLH::registers, int1_cfg)
122
                              + MEMBER_SIZE(LIS331DLH::registers, int1_duration) /* linear interrupt config */
123
                              + MEMBER_SIZE(LIS331DLH::registers, int1_src)
124
                              + MEMBER_SIZE(LIS331DLH::registers, int1_src) /* 2x size of int1_src */
125
                              + 1; /* addressing */
126
  const size_t buffer_size = ctrl_reg_size > int_reg_size ? ctrl_reg_size : int_reg_size;
127
128
  uint8_t buffer[buffer_size];
129
  InterruptConfig *int_cfg = &config->int1_cfg;
130
  uint8_t i;
131
132
  // write interrupt config first
133
  for (i = 0x00u; i < 2; i++, int_cfg++) {
134
    // this might be three-wire so we need to send ones
135
    memset(buffer, 0xFFu, buffer_size);
136
    if (!i)
137
      buffer[0] = offsetof(LIS331DLH::registers, int1_cfg);
138
    else
139
      buffer[0] = offsetof(LIS331DLH::registers, int2_cfg);
140
    buffer[5] = buffer[0] + offsetof(LIS331DLH::registers, int1_src) - offsetof(LIS331DLH::registers, int1_cfg);
141
    buffer[5] |= LIS331DLH::SPI_READ;
142
    buffer[6] = 0xFFu,
143
    buffer[0] |= LIS331DLH::SPI_MULT | LIS331DLH::SPI_WRITE;
144
    buffer[1] = int_cfg->config;
145
    buffer[2] = 0xFFu; /* skip source register */
146
    buffer[3] = int_cfg->ths;
147
    buffer[4] = int_cfg->duration;
148
    this->driver->write(&buffer[0], 5);
149
    // read intN_src register to clear IA
150
    this->driver->exchange(&buffer[5], &buffer[5], 2);
151
  }
152
153
  // write control config
154
  // this might be three-wire so we need to send ones
155
  memset(buffer, 0xFFu, buffer_size);
156
  buffer[0] = offsetof(LIS331DLH::registers, ctrl_reg1) | LIS331DLH::SPI_MULT | LIS331DLH::SPI_WRITE;
157
  buffer[1] = config->ctrl1;
158
  buffer[2] = config->ctrl2;
159
  buffer[3] = config->ctrl3;
160
  buffer[4] = config->ctrl4;
161
  buffer[5] = config->ctrl5;
162
  this->driver->write(buffer, 6);
163
164
  // reset hp filter
165
  buffer[0] = offsetof(LIS331DLH::registers, hp_filter_reset) | LIS331DLH::SPI_WRITE;
166
  this->driver->write(buffer, 1);
167
168
  // Store the full scale configuration for acceleration decoding
169
  this->currentFullScaleConfiguration = config->ctrl4 & LIS331DLH::FS_8G;
170
171
  return RDY_OK;
172
173
}
174
175
uint8_t
176
LIS331DLH::
177
getCheck() {
178
179
  const size_t buffer_size = 1 /* addressing */
180
                             + 1; /* who am i */
181
  uint8_t buffer[buffer_size];
182
183
  // Exchange the data with the LIS331DLH accelerometer
184
  // Specify the adress and the mode
185
  buffer[0] = offsetof(LIS331DLH::registers, who_am_i) | LIS331DLH::SPI_READ;
186
  this->driver->exchange(buffer, buffer, buffer_size);
187
  // Check
188
  if (buffer[1] == LIS331DLH::LIS331DLH_ID) {
189
    return LIS331DLH::CHECK_OK;
190
  } else {
191
    return LIS331DLH::CHECK_FAIL;
192
  }
193
194
}
195
196
void
197
LIS331DLH::
198
printSelfTest(LIS331DLHConfig* config) {
199
200
  // Running the build in test from LIS331DLH manual and compare the
201
  // measured values against table 3
202
203
  const uint8_t amountOfMeanValues = 10;
204
  const uint32_t sleepBetweenMeasurementMs = 500;
205
  int32_t accel;
206
207
  // Choose a defined config, if none is given
208
  LIS331DLH::LIS331DLHConfig test_accel_run_cfg;
209
  if (config == NULL) {
210
    LIS331DLH::LIS331DLHConfig accel_run_cfg_tmp = {
211
    /* ctrl1    */LIS331DLH::PM_ODR | LIS331DLH::DR_50HZ_37LP | LIS331DLH::ZEN
212
        | LIS331DLH::YEN | LIS331DLH::XEN,
213
    /* ctrl2    */0x00u,
214
    /* ctrl3    */LIS331DLH::INT_LOW | LIS331DLH::I1_CFG_DRY,
215
    /* ctrl4    */LIS331DLH::BDU_CONT | LIS331DLH::BLE_LE | LIS331DLH::FS_8G
216
        | LIS331DLH::SIM_4WI,
217
    /* ctrl5    */LIS331DLH::SLEEP_TO_WAKE_OFF,
218
    /* int1_cfg */
219
    {
220
    /* config   */LIS331DLH::AOI_OR_INT,
221
    /* ths      */0x00u,
222
    /* duration */0x00u, },
223
    /* int2_cfg */
224
    {
225
    /* config   */LIS331DLH::AOI_OR_INT,
226
    /* ths      */0x00u,
227
    /* duration */0x00u, }, };
228
    test_accel_run_cfg = accel_run_cfg_tmp;
229
  } else {
230
    // Save the given config
231
    test_accel_run_cfg = *config;
232
  }
233
234
  // 1. Get some standard values
235
  // Configure for the test
236
  test_accel_run_cfg.ctrl4 = LIS331DLH::BDU_CONT | LIS331DLH::BLE_LE
237
      | LIS331DLH::FS_2G | LIS331DLH::SIM_4WI;
238
  this->configure(&test_accel_run_cfg);
239
  BaseThread::sleep(MS2ST(sleepBetweenMeasurementMs));
240
  // Grep some values and build the mean value
241
  chprintf((BaseSequentialStream*) &SD1, "\nACC: Get acc std values\n");
242
  int32_t stdAccValues[3] = { this->getAcceleration(LIS331DLH::AXIS_X), this
243
      ->getAcceleration(LIS331DLH::AXIS_Y), this->getAcceleration(
244
      LIS331DLH::AXIS_Z) };
245
246
  for (uint8_t n = 1; n < amountOfMeanValues; ++n) {
247
    BaseThread::sleep(MS2ST(sleepBetweenMeasurementMs));
248
    for (uint8_t i = LIS331DLH::AXIS_X; i <= LIS331DLH::AXIS_Z; i++) {
249
      accel = int32_t(this->getAcceleration(i));
250
      stdAccValues[i] = (stdAccValues[i] * n + accel) / (n + 1);
251
      chprintf((BaseSequentialStream*) &SD1, "%c%d:%d ", accel < 0 ? '-' : '+',
252
                accel < 0 ? -accel : accel, stdAccValues[i]);
253
    }
254
    chprintf((BaseSequentialStream*) &SD1, "\n");
255
  }
256
257
  // 2. Apply negative offset
258
  // Configure for the test
259
  test_accel_run_cfg.ctrl4 = LIS331DLH::BDU_CONT | LIS331DLH::BLE_LE
260
      | LIS331DLH::FS_2G | LIS331DLH::SIM_4WI | LIS331DLH::ST_ENABLE
261
      | LIS331DLH::STSIGN_NEG;
262
  this->configure(&test_accel_run_cfg);
263
  BaseThread::sleep(MS2ST(sleepBetweenMeasurementMs));
264
  // Grep some values and build the mean value
265
  chprintf((BaseSequentialStream*) &SD1, "\nACC: Get acc neg values\n");
266
  int16_t negAccValues[3] = { this->getAcceleration(LIS331DLH::AXIS_X), this
267
      ->getAcceleration(LIS331DLH::AXIS_Y), this->getAcceleration(
268
      LIS331DLH::AXIS_Z) };
269
270
  for (uint8_t n = 1; n < amountOfMeanValues; ++n) {
271
    BaseThread::sleep(MS2ST(sleepBetweenMeasurementMs));
272
    for (uint8_t i = LIS331DLH::AXIS_X; i <= LIS331DLH::AXIS_Z; i++) {
273
      accel = int32_t(this->getAcceleration(i));
274
      negAccValues[i] = (negAccValues[i] * n + accel) / (n + 1);
275
      chprintf((BaseSequentialStream*) &SD1, "%c%d:%d ", accel < 0 ? '-' : '+',
276
                accel < 0 ? -accel : accel, negAccValues[i]);
277
    }
278
    chprintf((BaseSequentialStream*) &SD1, "\n");
279
  }
280
281
  // 2. Apply positive offset
282
  // Configure for the test
283
  test_accel_run_cfg.ctrl4 = LIS331DLH::BDU_CONT | LIS331DLH::BLE_LE
284
      | LIS331DLH::FS_2G | LIS331DLH::SIM_4WI | LIS331DLH::ST_ENABLE
285
      | LIS331DLH::STSIGN_POS;
286
  this->configure(&test_accel_run_cfg);
287
  BaseThread::sleep(MS2ST(sleepBetweenMeasurementMs));
288
  // Grep some values and build the mean value
289
  chprintf((BaseSequentialStream*) &SD1, "\nACC: Get acc pos values\n");
290
  int16_t posAccValues[3] = { this->getAcceleration(LIS331DLH::AXIS_X), this
291
      ->getAcceleration(LIS331DLH::AXIS_Y), this->getAcceleration(
292
      LIS331DLH::AXIS_Z) };
293
294
  for (uint8_t n = 1; n < amountOfMeanValues; ++n) {
295
    BaseThread::sleep(MS2ST(sleepBetweenMeasurementMs));
296
    for (uint8_t i = LIS331DLH::AXIS_X; i <= LIS331DLH::AXIS_Z; i++) {
297
      accel = int32_t(this->getAcceleration(i));
298
      posAccValues[i] = (posAccValues[i] * n + accel) / (n + 1);
299
      chprintf((BaseSequentialStream*) &SD1, "%c%d:%d ", accel < 0 ? '-' : '+',
300
                accel < 0 ? -accel : accel, posAccValues[i]);
301
    }
302
    chprintf((BaseSequentialStream*) &SD1, "\n");
303
  }
304
305
  // Get the amplitude change and compare it to the standard values from LIS331DLH manual table 3
306
  int32_t amp;
307
  const int32_t ampXmax = 550, ampYmax = 550, ampZmax = 750;
308
  const int32_t ampXmin = 120, ampYmin = 120, ampZmin = 140;
309
310
  // TEST
311
  chprintf((BaseSequentialStream*) &SD1, "\n\nACC: Testresult\n");
312
  amp = std::abs(
313
      stdAccValues[LIS331DLH::AXIS_X] - negAccValues[LIS331DLH::AXIS_X]);
314
  if (amp < ampXmin || amp > ampXmax)
315
    chprintf((BaseSequentialStream*) &SD1, "ACC: Negative x-axis faulty\n");
316
  amp = std::abs(
317
      stdAccValues[LIS331DLH::AXIS_Y] - negAccValues[LIS331DLH::AXIS_Y]);
318
  if (amp < ampYmin || amp > ampYmax)
319
    chprintf((BaseSequentialStream*) &SD1, "ACC: Negative y-axis faulty\n");
320
  amp = std::abs(
321
      stdAccValues[LIS331DLH::AXIS_Z] - negAccValues[LIS331DLH::AXIS_Z]);
322
  if (amp < ampZmin || amp > ampZmax)
323
    chprintf((BaseSequentialStream*) &SD1, "ACC: Negative z-axis faulty\n");
324
  amp = std::abs(
325
      stdAccValues[LIS331DLH::AXIS_X] - posAccValues[LIS331DLH::AXIS_X]);
326
  if (amp < ampXmin || amp > ampXmax)
327
    chprintf((BaseSequentialStream*) &SD1, "ACC: Positive x-axis faulty\n");
328
  amp = std::abs(
329
      stdAccValues[LIS331DLH::AXIS_Y] - posAccValues[LIS331DLH::AXIS_Y]);
330
  if (amp < ampYmin || amp > ampYmax)
331
    chprintf((BaseSequentialStream*) &SD1, "ACC: Positive y-axis faulty\n");
332
  amp = std::abs(
333
      stdAccValues[LIS331DLH::AXIS_Z] - posAccValues[LIS331DLH::AXIS_Z]);
334
  if (amp < ampZmin || amp > ampZmax)
335
    chprintf((BaseSequentialStream*) &SD1, "ACC: Positive z-axis faulty\n");
336
337
  // Write back the original config
338
  this->configure(config);
339
}
340
341
} /* amiro */