Statistics
| Branch: | Tag: | Revision:

amiro-os / components / accel / lis331dlh.cpp @ 6d830173

History | View | Annotate | Download (11.527 KB)

1
#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
#include <amiro/Constants.h>
9
#include <global.hpp>
10

    
11
namespace amiro {
12

    
13
extern Global global;
14

    
15
LIS331DLH::
16
LIS331DLH(HWSPIDriver *driver) :
17
  driver(driver),
18
  currentFullScaleConfiguration(FS_2G) {
19

    
20
}
21

    
22
LIS331DLH::
23
~LIS331DLH() {
24

    
25
}
26

    
27
chibios_rt::EvtSource*
28
LIS331DLH::
29
getEventSource() {
30
  return &this->eventSource;
31
}
32

    
33
int16_t
34
LIS331DLH::
35
getAcceleration(const uint8_t axis) {
36

    
37
  return this->accelerations[axis];
38

    
39
}
40

    
41
int16_t
42
LIS331DLH::
43
getAccelerationForce(const uint8_t axis) {
44

    
45
  int16_t result;
46

    
47
  switch(this->currentFullScaleConfiguration) {
48
  default:
49
  case(FS_2G):
50
    // Should be this->accelerations[axis] * 0.9765625
51
    result = this->accelerations[axis];
52
    break;
53
  case(FS_4G):
54
      // Should be this->accelerations[axis] * 1.953125
55
      result =  this->accelerations[axis] << 1;
56
    break;
57
  case(FS_8G):
58
      // Should be this->accelerations[axis] * 3.90625
59
      result =  this->accelerations[axis] << 2;
60
    break;
61
  }
62

    
63
  return result;
64

    
65
}
66

    
67
msg_t
68
LIS331DLH::
69
main() {
70

    
71
  this->setName("Lis331dlh");
72

    
73
  while (!this->shouldTerminate()) {
74

    
75
    updateSensorData();
76

    
77
    this->eventSource.broadcastFlags(0);
78

    
79
    this->waitAnyEventTimeout(ALL_EVENTS, CAN::UPDATE_PERIOD);
80

    
81
  }
82
  return RDY_OK;
83
}
84

    
85
void
86
LIS331DLH::
87
updateSensorData() {
88

    
89
  const size_t buffer_size = offsetof(LIS331DLH::registers, out_z)
90
                             - offsetof(LIS331DLH::registers, status_reg)
91
                             + MEMBER_SIZE(LIS331DLH::registers, out_z)
92
                             + 1; /* addressing */
93
  uint8_t buffer[buffer_size];
94
  uint8_t sreg;
95

    
96
  // this might be three-wire so we need to send ones
97
  memset(buffer, 0xFFu, buffer_size);
98
  buffer[0] = offsetof(LIS331DLH::registers, status_reg) | LIS331DLH::SPI_MULT | LIS331DLH::SPI_READ;
99
  this->driver->exchange(buffer, buffer, buffer_size);
100

    
101
  // assemble data
102
  sreg = buffer[1];
103

    
104
  if (sreg & LIS331DLH::XDA)
105
    this->accelerations[LIS331DLH::AXIS_X] = int16_t((buffer[3] << 8) | buffer[2]) >> 4;
106

    
107
  if (sreg & LIS331DLH::YDA)
108
    this->accelerations[LIS331DLH::AXIS_Y] = int16_t((buffer[5] << 8) | buffer[4]) >> 4;
109

    
110
  if (sreg & LIS331DLH::ZDA)
111
    this->accelerations[LIS331DLH::AXIS_Z] = int16_t((buffer[7] << 8) | buffer[6]) >> 4;
112

    
113
}
114

    
115
msg_t
116
LIS331DLH::
117
configure(LIS331DLHConfig *config) {
118

    
119
  const size_t ctrl_reg_size = offsetof(LIS331DLH::registers, ctrl_reg5)
120
                               - offsetof(LIS331DLH::registers, ctrl_reg1)
121
                               + MEMBER_SIZE(LIS331DLH::registers, ctrl_reg5)
122
                               + 1; /* addressing */
123
  const size_t int_reg_size = offsetof(LIS331DLH::registers, int1_duration)
124
                              - offsetof(LIS331DLH::registers, int1_cfg)
125
                              + MEMBER_SIZE(LIS331DLH::registers, int1_duration) /* linear interrupt config */
126
                              + MEMBER_SIZE(LIS331DLH::registers, int1_src)
127
                              + MEMBER_SIZE(LIS331DLH::registers, int1_src) /* 2x size of int1_src */
128
                              + 1; /* addressing */
129
  const size_t buffer_size = ctrl_reg_size > int_reg_size ? ctrl_reg_size : int_reg_size;
130

    
131
  uint8_t buffer[buffer_size];
132
  InterruptConfig *int_cfg = &config->int1_cfg;
133
  uint8_t i;
134

    
135
  // write interrupt config first
136
  for (i = 0x00u; i < 2; i++, int_cfg++) {
137
    // this might be three-wire so we need to send ones
138
    memset(buffer, 0xFFu, buffer_size);
139
    if (!i)
140
      buffer[0] = offsetof(LIS331DLH::registers, int1_cfg);
141
    else
142
      buffer[0] = offsetof(LIS331DLH::registers, int2_cfg);
143
    buffer[5] = buffer[0] + offsetof(LIS331DLH::registers, int1_src) - offsetof(LIS331DLH::registers, int1_cfg);
144
    buffer[5] |= LIS331DLH::SPI_READ;
145
    buffer[6] = 0xFFu,
146
    buffer[0] |= LIS331DLH::SPI_MULT | LIS331DLH::SPI_WRITE;
147
    buffer[1] = int_cfg->config;
148
    buffer[2] = 0xFFu; /* skip source register */
149
    buffer[3] = int_cfg->ths;
150
    buffer[4] = int_cfg->duration;
151
    this->driver->write(&buffer[0], 5);
152
    // read intN_src register to clear IA
153
    this->driver->exchange(&buffer[5], &buffer[5], 2);
154
  }
155

    
156
  // write control config
157
  // this might be three-wire so we need to send ones
158
  memset(buffer, 0xFFu, buffer_size);
159
  buffer[0] = offsetof(LIS331DLH::registers, ctrl_reg1) | LIS331DLH::SPI_MULT | LIS331DLH::SPI_WRITE;
160
  buffer[1] = config->ctrl1;
161
  buffer[2] = config->ctrl2;
162
  buffer[3] = config->ctrl3;
163
  buffer[4] = config->ctrl4;
164
  buffer[5] = config->ctrl5;
165
  this->driver->write(buffer, 6);
166

    
167
  // reset hp filter
168
  buffer[0] = offsetof(LIS331DLH::registers, hp_filter_reset) | LIS331DLH::SPI_WRITE;
169
  this->driver->write(buffer, 1);
170

    
171
  // Store the full scale configuration for acceleration decoding
172
  this->currentFullScaleConfiguration = config->ctrl4 & LIS331DLH::FS_8G;
173

    
174
  return RDY_OK;
175

    
176
}
177

    
178
uint8_t
179
LIS331DLH::
180
getCheck() {
181

    
182
  const size_t buffer_size = 1 /* addressing */
183
                             + 1; /* who am i */
184
  uint8_t buffer[buffer_size];
185

    
186
  // Exchange the data with the LIS331DLH accelerometer
187
  // Specify the adress and the mode
188
  buffer[0] = offsetof(LIS331DLH::registers, who_am_i) | LIS331DLH::SPI_READ;
189
  this->driver->exchange(buffer, buffer, buffer_size);
190
  // Check
191
  if (buffer[1] == LIS331DLH::LIS331DLH_ID) {
192
    return LIS331DLH::CHECK_OK;
193
  } else {
194
    return LIS331DLH::CHECK_FAIL;
195
  }
196

    
197
}
198

    
199
void
200
LIS331DLH::
201
printSelfTest(LIS331DLHConfig* config) {
202

    
203
  // Running the build in test from LIS331DLH manual and compare the
204
  // measured values against table 3
205

    
206
  const uint8_t amountOfMeanValues = 10;
207
  const uint32_t sleepBetweenMeasurementMs = 500;
208
  int32_t accel;
209

    
210
  // Choose a defined config, if none is given
211
  LIS331DLH::LIS331DLHConfig test_accel_run_cfg;
212
  if (config == NULL) {
213
    LIS331DLH::LIS331DLHConfig accel_run_cfg_tmp = {
214
    /* ctrl1    */LIS331DLH::PM_ODR | LIS331DLH::DR_50HZ_37LP | LIS331DLH::ZEN
215
        | LIS331DLH::YEN | LIS331DLH::XEN,
216
    /* ctrl2    */0x00u,
217
    /* ctrl3    */LIS331DLH::INT_LOW | LIS331DLH::I1_CFG_DRY,
218
    /* ctrl4    */LIS331DLH::BDU_CONT | LIS331DLH::BLE_LE | LIS331DLH::FS_8G
219
        | LIS331DLH::SIM_4WI,
220
    /* ctrl5    */LIS331DLH::SLEEP_TO_WAKE_OFF,
221
    /* int1_cfg */
222
    {
223
    /* config   */LIS331DLH::AOI_OR_INT,
224
    /* ths      */0x00u,
225
    /* duration */0x00u, },
226
    /* int2_cfg */
227
    {
228
    /* config   */LIS331DLH::AOI_OR_INT,
229
    /* ths      */0x00u,
230
    /* duration */0x00u, }, };
231
    test_accel_run_cfg = accel_run_cfg_tmp;
232
  } else {
233
    // Save the given config
234
    test_accel_run_cfg = *config;
235
  }
236

    
237
  // 1. Get some standard values
238
  // Configure for the test
239
  test_accel_run_cfg.ctrl4 = LIS331DLH::BDU_CONT | LIS331DLH::BLE_LE
240
      | LIS331DLH::FS_2G | LIS331DLH::SIM_4WI;
241
  this->configure(&test_accel_run_cfg);
242
  BaseThread::sleep(MS2ST(sleepBetweenMeasurementMs));
243
  // Grep some values and build the mean value
244
  chprintf((BaseSequentialStream*) &global.sercanmux1, "\nACC: Get acc std values\n");
245
  int32_t stdAccValues[3] = { this->getAcceleration(LIS331DLH::AXIS_X), this
246
      ->getAcceleration(LIS331DLH::AXIS_Y), this->getAcceleration(
247
      LIS331DLH::AXIS_Z) };
248

    
249
  for (uint8_t n = 1; n < amountOfMeanValues; ++n) {
250
    BaseThread::sleep(MS2ST(sleepBetweenMeasurementMs));
251
    for (uint8_t i = LIS331DLH::AXIS_X; i <= LIS331DLH::AXIS_Z; i++) {
252
      accel = int32_t(this->getAcceleration(i));
253
      stdAccValues[i] = (stdAccValues[i] * n + accel) / (n + 1);
254
      chprintf((BaseSequentialStream*) &global.sercanmux1, "%c%d:%d ", accel < 0 ? '-' : '+',
255
                accel < 0 ? -accel : accel, stdAccValues[i]);
256
    }
257
    chprintf((BaseSequentialStream*) &global.sercanmux1, "\n");
258
  }
259

    
260
  // 2. Apply negative offset
261
  // Configure for the test
262
  test_accel_run_cfg.ctrl4 = LIS331DLH::BDU_CONT | LIS331DLH::BLE_LE
263
      | LIS331DLH::FS_2G | LIS331DLH::SIM_4WI | LIS331DLH::ST_ENABLE
264
      | LIS331DLH::STSIGN_NEG;
265
  this->configure(&test_accel_run_cfg);
266
  BaseThread::sleep(MS2ST(sleepBetweenMeasurementMs));
267
  // Grep some values and build the mean value
268
  chprintf((BaseSequentialStream*) &global.sercanmux1, "\nACC: Get acc neg values\n");
269
  int16_t negAccValues[3] = { this->getAcceleration(LIS331DLH::AXIS_X), this
270
      ->getAcceleration(LIS331DLH::AXIS_Y), this->getAcceleration(
271
      LIS331DLH::AXIS_Z) };
272

    
273
  for (uint8_t n = 1; n < amountOfMeanValues; ++n) {
274
    BaseThread::sleep(MS2ST(sleepBetweenMeasurementMs));
275
    for (uint8_t i = LIS331DLH::AXIS_X; i <= LIS331DLH::AXIS_Z; i++) {
276
      accel = int32_t(this->getAcceleration(i));
277
      negAccValues[i] = (negAccValues[i] * n + accel) / (n + 1);
278
      chprintf((BaseSequentialStream*) &global.sercanmux1, "%c%d:%d ", accel < 0 ? '-' : '+',
279
                accel < 0 ? -accel : accel, negAccValues[i]);
280
    }
281
    chprintf((BaseSequentialStream*) &global.sercanmux1, "\n");
282
  }
283

    
284
  // 2. Apply positive offset
285
  // Configure for the test
286
  test_accel_run_cfg.ctrl4 = LIS331DLH::BDU_CONT | LIS331DLH::BLE_LE
287
      | LIS331DLH::FS_2G | LIS331DLH::SIM_4WI | LIS331DLH::ST_ENABLE
288
      | LIS331DLH::STSIGN_POS;
289
  this->configure(&test_accel_run_cfg);
290
  BaseThread::sleep(MS2ST(sleepBetweenMeasurementMs));
291
  // Grep some values and build the mean value
292
  chprintf((BaseSequentialStream*) &global.sercanmux1, "\nACC: Get acc pos values\n");
293
  int16_t posAccValues[3] = { this->getAcceleration(LIS331DLH::AXIS_X), this
294
      ->getAcceleration(LIS331DLH::AXIS_Y), this->getAcceleration(
295
      LIS331DLH::AXIS_Z) };
296

    
297
  for (uint8_t n = 1; n < amountOfMeanValues; ++n) {
298
    BaseThread::sleep(MS2ST(sleepBetweenMeasurementMs));
299
    for (uint8_t i = LIS331DLH::AXIS_X; i <= LIS331DLH::AXIS_Z; i++) {
300
      accel = int32_t(this->getAcceleration(i));
301
      posAccValues[i] = (posAccValues[i] * n + accel) / (n + 1);
302
      chprintf((BaseSequentialStream*) &global.sercanmux1, "%c%d:%d ", accel < 0 ? '-' : '+',
303
                accel < 0 ? -accel : accel, posAccValues[i]);
304
    }
305
    chprintf((BaseSequentialStream*) &global.sercanmux1, "\n");
306
  }
307

    
308
  // Get the amplitude change and compare it to the standard values from LIS331DLH manual table 3
309
  int32_t amp;
310
  const int32_t ampXmax = 550, ampYmax = 550, ampZmax = 750;
311
  const int32_t ampXmin = 120, ampYmin = 120, ampZmin = 140;
312

    
313
  // TEST
314
  chprintf((BaseSequentialStream*) &global.sercanmux1, "\n\nACC: Testresult\n");
315
  amp = std::abs(
316
      stdAccValues[LIS331DLH::AXIS_X] - negAccValues[LIS331DLH::AXIS_X]);
317
  if (amp < ampXmin || amp > ampXmax)
318
    chprintf((BaseSequentialStream*) &global.sercanmux1, "ACC: Negative x-axis faulty\n");
319
  amp = std::abs(
320
      stdAccValues[LIS331DLH::AXIS_Y] - negAccValues[LIS331DLH::AXIS_Y]);
321
  if (amp < ampYmin || amp > ampYmax)
322
    chprintf((BaseSequentialStream*) &global.sercanmux1, "ACC: Negative y-axis faulty\n");
323
  amp = std::abs(
324
      stdAccValues[LIS331DLH::AXIS_Z] - negAccValues[LIS331DLH::AXIS_Z]);
325
  if (amp < ampZmin || amp > ampZmax)
326
    chprintf((BaseSequentialStream*) &global.sercanmux1, "ACC: Negative z-axis faulty\n");
327
  amp = std::abs(
328
      stdAccValues[LIS331DLH::AXIS_X] - posAccValues[LIS331DLH::AXIS_X]);
329
  if (amp < ampXmin || amp > ampXmax)
330
    chprintf((BaseSequentialStream*) &global.sercanmux1, "ACC: Positive x-axis faulty\n");
331
  amp = std::abs(
332
      stdAccValues[LIS331DLH::AXIS_Y] - posAccValues[LIS331DLH::AXIS_Y]);
333
  if (amp < ampYmin || amp > ampYmax)
334
    chprintf((BaseSequentialStream*) &global.sercanmux1, "ACC: Positive y-axis faulty\n");
335
  amp = std::abs(
336
      stdAccValues[LIS331DLH::AXIS_Z] - posAccValues[LIS331DLH::AXIS_Z]);
337
  if (amp < ampZmin || amp > ampZmax)
338
    chprintf((BaseSequentialStream*) &global.sercanmux1, "ACC: Positive z-axis faulty\n");
339

    
340
  // Write back the original config
341
  this->configure(config);
342
}
343

    
344
} /* amiro */