|
1 |
| -use accelerometer::vector::I16x3; |
2 |
| -use accelerometer::RawAccelerometer; |
| 1 | +use accelerometer::vector::{F32x3, I16x3}; |
| 2 | +use accelerometer::{Accelerometer, RawAccelerometer}; |
3 | 3 | use stm32f3xx_hal::gpio;
|
4 | 4 | use stm32f3xx_hal::gpio::{gpiob, OpenDrain};
|
5 | 5 | use stm32f3xx_hal::i2c;
|
@@ -67,3 +67,59 @@ impl RawAccelerometer<I16x3> for Compass {
|
67 | 67 | Ok(I16x3::new(reading.x, reading.y, reading.z))
|
68 | 68 | }
|
69 | 69 | }
|
| 70 | + |
| 71 | +/// Reads Accelerometer data in G-Force |
| 72 | +/// |
| 73 | +/// # Warning |
| 74 | +/// This is hard coded for the default settings because the driver doesn't provide a way |
| 75 | +/// to read the necessary registers to calculate it based on current settings. |
| 76 | +/// If you take control of the underlying device driver and change settings, |
| 77 | +/// this will not calculate the correct G-Force values. |
| 78 | +impl Accelerometer for Compass { |
| 79 | + type Error = i2c::Error; |
| 80 | + fn accel_norm(&mut self) -> Result<F32x3, accelerometer::Error<Self::Error>> { |
| 81 | + let reading = self.accel_raw()?; |
| 82 | + /* |
| 83 | + * LA_FS (linear acceleration measurment range [full scale]) |
| 84 | + * can be +/-2, +/-4, +/-8, or +/- 16 |
| 85 | + * LA_So (Linear acceleration sensitivity) can be 1,2,4, or 12 |
| 86 | + * and is measured in milli-G / LSB |
| 87 | + * The driver provides a way to set the range/sensitivy, |
| 88 | + * but no way to read it, so we just hard code the default settings here (for now?). |
| 89 | + * |
| 90 | + * At +/-2g, we get 1mg/LSB (1 mg/bit) resolution. |
| 91 | + * The device returns a 16 bit result. |
| 92 | + * magnitude g / (1 mg / bit) = |
| 93 | + * +/- 2g range = 4g magnitude |
| 94 | + * 4g / 65535 bits = 4g/(1<<16) = 0.000061 g / bit |
| 95 | + * 2g / 32768 bits = 2g/(1<<15) = 0.000061 g / bit |
| 96 | + * |
| 97 | + * I _think_ the general equation is: |
| 98 | + * scale_factor = magnitude / #of_bits * sensitivity |
| 99 | + * scale_factor = (abs(range)*2) / #of_bits * sensitivity |
| 100 | + * scale_factor = abs(range) / (#of_bits/2) * sensitivity |
| 101 | + * sf(+/-2g) = 4g / 65535 bits * 1mg/LSB = 0.000061 g |
| 102 | + * sf(+/-4g) = 8g / 65535 bits * 2mg/LSB = 0.000244 g |
| 103 | + * sf(+/-8g) = 16g / 65535 bits * 4mg/LSB = 0.000976 g |
| 104 | + * sf(+/-16g) = 32g / 65535 bits * 12mg/LSB = 0.005859 g |
| 105 | + * |
| 106 | + * NOTE: This also does not account for temperature variance. |
| 107 | + */ |
| 108 | + const MAGNITUDE: i32 = 4; |
| 109 | + const NO_OF_BITS: i32 = 1 << 16; |
| 110 | + const SENSITIVITY: i32 = 1; |
| 111 | + const SCALE_FACTOR: f32 = (MAGNITUDE as f32 / NO_OF_BITS as f32) * SENSITIVITY as f32; |
| 112 | + Ok(F32x3::new ( |
| 113 | + reading.x as f32 * SCALE_FACTOR, |
| 114 | + reading.y as f32 * SCALE_FACTOR, |
| 115 | + reading.z as f32 * SCALE_FACTOR, |
| 116 | + )) |
| 117 | + } |
| 118 | + |
| 119 | + fn sample_rate(&mut self) -> Result<f32, accelerometer::Error<<Self as Accelerometer>::Error>> { |
| 120 | + // we don't expose a way to change this, so hard coded to 400Hz right now |
| 121 | + // it should really be read from the device in case someone snags the raw lsm303dlhc struct, |
| 122 | + // but the driver does't give us a way to read it back from the device |
| 123 | + Ok(400.0) |
| 124 | + } |
| 125 | +} |
0 commit comments