rusEFI
The most advanced open source ECU
accelerometer.cpp
Go to the documentation of this file.
1 /*
2  * @file accelerometer.cpp
3  *
4  * stm32f4discovery has MEMS LIS302DL
5  * www.st.com/resource/en/datasheet/lis302dl.pdf
6  *
7  * SPI1
8  * LIS302DL_SPI_SCK PA5
9  * LIS302DL_SPI_MISO PA6
10  * LIS302DL_SPI_MOSI PA7
11  * LIS302DL_SPI_CS_PIN PE3
12  *
13  *
14  *
15  * @date May 19, 2016
16  * @author Andrey Belomutskiy, (c) 2012-2020
17  */
18 
19 #include "pch.h"
20 
21 #include "accelerometer.h"
22 #include "hardware.h"
23 
24 #if EFI_ONBOARD_MEMS
25 #include "mpu_util.h"
26 #include "lis302dl.h"
28 
29 #if (EFI_ONBOARD_MEMS_LIS2DW12 == TRUE)
30 #include "lis2dw12.h"
31 #endif
32 #if (EFI_ONBOARD_MEMS_LIS2DH12 == TRUE)
33 #include "lsm303agr.h"
34 #endif
35 #if (EFI_ONBOARD_MEMS_LIS302DL == TRUE)
36 #include "lis302dl.h"
37 #endif
38 #if (EFI_ONBOARD_MEMS_LIS3DSH == TRUE)
39 #include "lis3dsh.h"
40 #endif
41 
42 /*
43  * SPI1 configuration structure.
44  * Speed 5.25MHz, CPHA=1, CPOL=1, 8bits frames, MSb transmitted first.
45  */
46 static SPIConfig accelerometerSpiCfg = {
47 #if SPI_SUPPORTS_CIRCULAR == TRUE
48  .circular = FALSE,
49 #endif
50  .end_cb = NULL,
51  /* HW dependent part.*/
52  .ssport = NULL,
53  .sspad = 0,
54  .cr1 = SPI_CR1_BR_0 | SPI_CR1_BR_1 | SPI_CR1_CPOL | SPI_CR1_CPHA |
55  SPI_CR1_8BIT_MODE,
56  .cr2 = SPI_CR2_8BIT_MODE
57 };
58 
60 
61 #if (EFI_ONBOARD_MEMS_LIS2DW12 == TRUE)
62 
63 static LIS2DW12Config lis2dw12cfg = {
64 #if LIS2DW12_USE_SPI
65  .spip = NULL,
66  .spicfg = &accelerometerSpiCfg,
67 #endif
68 #ifdef LIS2DW12_USE_I2C
69  /* TODO: */
70 #endif
71  .accsensitivity = NULL,
72  .accbias = NULL,
73  .accoutputdatarate = LIS2DW12_ACC_ODR_25HZ,
74  .accoutputresolution = LIS2DW12_ACC_OR_HP,
75  .acclowpowermode = LIS2DW12_ACC_LP_MODE2,
76  .accbadwidthselect = LIS2DW12_ACC_BW_ODR4,
77  .accfullscale = LIS2DW12_ACC_FS_4G,
78 };
79 
80 /* LIS302DL Driver: This object represent an LIS302DL instance */
81 static LIS2DW12Driver LIS2DW12;
82 
83 #endif //EFI_ONBOARD_MEMS_LIS2DW12 == TRUE
84 
85 #if (EFI_ONBOARD_MEMS_LIS2DH12 == TRUE)
86 
87 static LSM303AGRConfig lis2dh12cfg = {
88 #if LSM303AGR_USE_SPI
89  .spip = NULL,
90  .spicfg = &accelerometerSpiCfg,
91 #endif
92  .accsensitivity = NULL,
93  .accbias = NULL,
94  .accfullscale = LSM303AGR_ACC_FS_4G,
95  .accoutdatarate = LSM303AGR_ACC_ODR_50Hz,
96 #if LSM303AGR_USE_ADVANCED
97  .accmode = LSM303AGR_ACC_MODE_HRES,
98  .accblockdataupdate = LSM303AGR_ACC_BDU_CONT,
99  .accendianess = LSM303AGR_ACC_END_LITTLE,
100 #endif
101  /* LIS2DW12 is Accelerometer only, ignore following */
102  .compsensitivity = NULL,
103  .compbias = NULL,
104  .compoutputdatarate = LSM303AGR_COMP_ODR_50HZ,
105 #if LSM303AGR_USE_ADVANCED
106  .compmode = LSM303AGR_COMP_MODE_NORM,
107  .complp = LSM303AGR_COMP_LPOW_EN
108 #endif
109 };
110 
111 /* LSM303AGR Driver: This object represent an LIS2DH12 instance */
112 static LSM303AGRDriver LIS2DH12;
113 
114 #endif //EFI_ONBOARD_MEMS_LIS2DH12 == TRUE
115 
116 #if (EFI_ONBOARD_MEMS_LIS302DL == TRUE)
117 static LIS302DLConfig lis302dlcfg ={
118 #if LIS302DL_USE_SPI
119  .spip = NULL,
120  .spicfg = &accelerometerSpiCfg,
121 #endif
122 #if LIS302DL_USE_I2C
123  /* TODO: */
124 #endif
125  .accsensitivity = NULL,
126  .accbias = NULL,
127  .accfullscale = LIS302DL_ACC_FS_8G,
128  .accoutputdatarate = LIS302DL_ACC_ODR_100HZ,
129 #if LIS302DL_USE_ADVANCED
130  .acchighpass = LIS302DL_ACC_HP_0,
131 #endif
132 };
133 
134 static LIS302DLDriver LIS302DL;
135 
136 #endif //EFI_ONBOARD_MEMS_LIS302DL == TRUE
137 
138 #if (EFI_ONBOARD_MEMS_LIS3DSH == TRUE)
139 
140 static LIS3DSHConfig lis3dshcfg ={
141 #if LIS3DSH_USE_SPI
142  .spip = NULL,
143  .spicfg = &accelerometerSpiCfg,
144 #endif
145  .accsensitivity = NULL,
146  .accbias = NULL,
147  .accfullscale = LIS3DSH_ACC_FS_4G,
148  .accoutputdatarate = LIS3DSH_ACC_ODR_50HZ,
149 #if LIS3DSH_USE_ADVANCED
150  .accantialiasing = LIS3DSH_ACC_BW_50HZ,
151  .accblockdataupdate = LIS3DSH_ACC_BDU_CONTINUOUS,
152 #endif
153 };
154 
155 static LIS3DSHDriver LIS3DSH;
156 
157 #endif //EFI_ONBOARD_MEMS_LIS3DSH == TRUE
158 
162  ACCEL_LIS2DH12, // Same as LSM303
163  ACCEL_LIS302DL, // STM32F4DISCOVERY (old?)
164  ACCEL_LIS3DSH, // STM32F4DISCOVERY
165 };
166 
168 
169 class AccelController : public PeriodicController<UTILITY_THREAD_STACK_SIZE> {
170 public:
171  AccelController() : PeriodicController("Acc SPI") { }
172 private:
173  void PeriodicTask(efitick_t nowNt) override {
174  msg_t ret = MSG_RESET;
175  float acccooked[3];
176 
177  #if (EFI_ONBOARD_MEMS_LIS2DW12 == TRUE)
178  if (AccelType == ACCEL_LIS2DW12) {
179  ret = lis2dw12AccelerometerReadCooked(&LIS2DW12, acccooked);
180  }
181  #endif
182  #if (EFI_ONBOARD_MEMS_LIS2DH12 == TRUE)
183  if (AccelType == ACCEL_LIS2DH12) {
184  ret = lsm303agrAccelerometerReadCooked(&LIS2DH12, acccooked);
185  }
186  #endif
187  #if (EFI_ONBOARD_MEMS_LIS302DL == TRUE)
188  if (AccelType == ACCEL_LIS302DL) {
189  ret = lis302dlAccelerometerReadCooked(&LIS302DL, acccooked);
190  }
191  #endif
192  #if (EFI_ONBOARD_MEMS_LIS3DSH == TRUE)
193  if (AccelType == ACCEL_LIS3DSH) {
194  ret = lis3dshAccelerometerReadCooked(&LIS3DSH, acccooked);
195  }
196  #endif
197 
198  if ((engineConfiguration->useSpiImu) && (ret == MSG_OK)) {
199  /* milli-G to G */
200  engine->sensors.accelerometer.lat = acccooked[0] / 1000.0;
201  engine->sensors.accelerometer.lon = acccooked[1] / 1000.0;
202  engine->sensors.accelerometer.vert = acccooked[2] / 1000.0;
203  }
204  }
205 };
206 
207 static AccelController instance;
208 
210 #if HAL_USE_SPI
211  static SPIDriver *bus;
212  msg_t ret = MSG_RESET;
213 
215  return; // not used
216 
218  if (bus == nullptr) {
219  // error already reported
220  return;
221  }
222 
223  /* so far only Hellen boards share SPI device for SD card and accelerometer
224  * thus need to make sure CS pin is in a well known proper state */
227  }
230 
231  /* Try to detect any of enabled accels */
232  /* Hope all device drivers know how to detect correct chip */
233 #if (EFI_ONBOARD_MEMS_LIS2DW12 == TRUE)
234  if (ret != MSG_OK) {
235  lis2dw12cfg.spip = bus;
236 
237  /* LIS2DW12 Object Initialization.*/
238  lis2dw12ObjectInit(&LIS2DW12);
239 
240  /* Activates the LIS2DW12 driver.*/
241  ret = lis2dw12Start(&LIS2DW12, &lis2dw12cfg);
242  if (ret == MSG_OK) {
244  }
245  }
246 #endif //EFI_ONBOARD_MEMS_LIS2DW12 == TRUE
247 #if (EFI_ONBOARD_MEMS_LIS2DH12 == TRUE)
248  if (ret != MSG_OK) {
249  lis2dh12cfg.spip = bus;
250 
251  /* LIS2DH12 Object Initialization.*/
252  lsm303agrObjectInit(&LIS2DH12);
253 
254  /* Activates the LIS2DH12 driver.*/
255  ret = lsm303agrStart(&LIS2DH12, &lis2dh12cfg);
256  if (ret == MSG_OK) {
258  }
259  }
260 #endif //EFI_ONBOARD_MEMS_LIS2DH12 == TRUE
261 #if (EFI_ONBOARD_MEMS_LIS302DL == TRUE)
262  if (ret != MSG_OK) {
263  lis302dlcfg.spip = bus;
264 
265  /* LIS302DL Object Initialization.*/
266  lis302dlObjectInit(&LIS302DL);
267 
268  /* Activates the LIS302DL driver.*/
269  ret = lis302dlStart(&LIS302DL, &lis302dlcfg);
270  if (ret == MSG_OK) {
272  }
273  }
274 #endif //EFI_ONBOARD_MEMS_LIS302DL == TRUE
275 #if (EFI_ONBOARD_MEMS_LIS3DSH == TRUE)
276  if (ret != MSG_OK) {
277  lis3dshcfg.spip = bus;
278 
279  /* LIS3DSH Object Initialization.*/
280  lis3dshObjectInit(&LIS3DSH);
281 
282  /* Activates the LIS3DSH driver.*/
283  ret = lis3dshStart(&LIS3DSH, &lis3dshcfg);
284  if (ret == MSG_OK) {
286  }
287  }
288 #endif //EFI_ONBOARD_MEMS_LIS3DSH == TRUE
289 
290  if (ret == MSG_OK) {
291  /* 50 Hz */
292  instance.setPeriod(20 /*ms*/);
293  instance.start();
294  efiPrintf("accelerometer init OK");
295  } else {
296  efiPrintf("accelerometer init failed %d", ret);
297  }
298 #endif /* HAL_USE_SPI */
299 }
300 
301 #endif /* EFI_ONBOARD_MEMS */
AccelType_t
@ ACCEL_LIS2DH12
@ ACCEL_UNK
@ ACCEL_LIS3DSH
@ ACCEL_LIS302DL
@ ACCEL_LIS2DW12
static LIS2DW12Driver LIS2DW12
void initAccelerometer()
static LIS3DSHConfig lis3dshcfg
OutputPin accelerometerChipSelect
static LIS2DW12Config lis2dw12cfg
static AccelController instance
static LIS3DSHDriver LIS3DSH
static LIS302DLDriver LIS302DL
static SPIConfig accelerometerSpiCfg
static LSM303AGRDriver LIS2DH12
static AccelType_t AccelType
static LIS302DLConfig lis302dlcfg
static LSM303AGRConfig lis2dh12cfg
SensorsState sensors
Definition: engine.h:327
Single output pin reference and state.
Definition: efi_output.h:50
void initPin(const char *msg, brain_pin_e brainPin, pin_output_mode_e outputMode, bool forceInitWithFatalError=false)
Definition: efi_gpio.cpp:690
bool isInitialized() const
Definition: efi_gpio.cpp:536
Base class for a controller that needs to run periodically to perform work.
virtual void PeriodicTask(efitick_t nowNt)=0
Called periodically. Override this method to do work for your controller.
PeriodicController(const char *name, tprio_t priority, float frequencyHz)
ioportid_t getHwPort(const char *msg, brain_pin_e brainPin)
ioportmask_t getHwPin(const char *msg, brain_pin_e brainPin)
Engine * engine
SPIDriver * getSpiDevice(spi_device_e spiDevice)
Definition: hardware.cpp:144
engine_configuration_s * engineConfiguration
bool isBrainPinValid(brain_pin_e brainPin)
Accelerometer accelerometer
Definition: engine_parts.h:23