ADXL355 Embedded-hal driver crate
source link: https://jitter.company/blog/2020/02/14/adxl355-embedded-hal-driver-crate/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
A Rust driver crate for the ADXL355 digital accelerometer. This driver accepts an embedded-hal
SPI interface and a GPIO OutputPin (for the chip select). It implements the Accelerometer Trait
so you can easily obtain both raw sensor data and scaled-to- Standard-gravity sensor data.
The ADXL355 is one of the best three axis digital accelerometers that I know of. It has a noise floor of only 25 µg/√Hz
. For example, the very popular MPU9250 Inertial Measurement Unit (IMU) specifies 300 µg/√Hz
for its noise density. One order of magnitude higher.
Of course the ADXL355 is more expensive, but I think it hits a nice sweet spot between the low end IMUs and very high end and high cost MEMS accelerometers (with noise densities of around 7 µg/√Hz
).
For this blogpost we make use of this breakout board .
It has a 2x6 pin header. We hacked it by shorting pin 1 to pin 8 so we could use a 10 strand flatcable that we had laying around. That means we lose the INT1
pin, but we’re not using it yet anyway.
Using the driver
The first step is to add the crate in your Cargo.toml
. At the time of writing the latest version is 0.2.0
.
# Cargo.toml [dependencies] adxl355 = "0.2.0" [dependencies.embedded-hal] version = "0.2.3" features = ["unproven"]
Minimum viable example
To quickly get started with default settings you’ll only need to import
use adxl355::{Adxl355, Accelerometer};
Adxl355
is used to create the driver instance, and Accelerometer
needs to be use
d to get the trait in scope so we can use its API.
Let’s create the default driver and read a sample and send it over serial.
let mut accelerometer = Adxl355::default(spi, cs).unwrap(); // send start command accelerometer.start(); let accel = accelerometer.accel_norm().unwrap(); writeln!(tx, "accel [g]: x={:.3}, y={:.3}, z={:.3}", accel.x, accel.y, accel.z).unwrap();
Custom configuration and data_ready interrupt
It is unlikely that the default settings match exactly with your project requirements. In the next example we will configure the sample rate, the measurement range and utilise the ADXL355’s data ready signal to trigger reading the data registers.
Sample Rate
Since we’ll be looking at the serial data with our slow human eyes, we will select the slowest possible sample rate. We need to import the ODR_LPF
enum. It is called ODR_LPF
because it will configure both the O utput D ata R ate and the L ow P ass F ilter. Lower data rate means more filtering and less noise. According to the datasheet the slowest datarate is 3.906 Hz
. So we’ll get about 4 samples a second.
Measurement Range
For the measurement range we can choose between ±2g
, ±4g
and ±8g
. If you have ever worked with accelerometers, you probably noticed that you always measure the gravity constant as an offset in the direct of the gravity. That means that we actually have to subtract 1g
to get the effective range.
Let’s go for the ±4g
mode since ±2g
is default.
Use the customized config object
We apply these settings by creating a config object and changing its properties.
use adxl355::{Adxl355, Config as ADXLConfig, ODR_LPF, Range, Accelerometer}; // ... let mut cfg = ADXLConfig::new(); cfg.odr(ODR_LPF::ODR_3_906_Hz) .range(Range::_4G); let mut accelerometer = Adxl355::new(spi, cs, &cfg).unwrap();
External interrupt
To use the data ready interrupt we need to configure the gpio pin connected to this external signal. How to do this differs per microcontroller and also per HAL crate. For the STM32F103 it is done as follows:
let mut drdy = gpioa.pa0.into_floating_input(&mut gpioa.crl); drdy.make_interrupt_source(&mut afio); drdy.trigger_on_edge(&dp.EXTI, Edge::RISING); drdy.enable_interrupt(&dp.EXTI);
Then we poll the interrupt bit in the main loop and read the data when ready
loop { // Read accel data if data_ready interrupt bit is set if drdy.check_interrupt() { let norm = accelerometer.accel_norm().unwrap(); writeln!(tx, "accel [g]: x={:.3}, y={:.3}, z={:.3}", accel.x, accel.y, accel.z).unwrap(); // if we don't clear this bit, the ISR would trigger indefinitely drdy.clear_interrupt_pending_bit(); } }
More examples
ADXL355 with blackpill and black magic probe ADXL355 with blackpill and black magic probeFor the complete code and more examples please see the example directory of the crate repository.
See the README
for building and running instructions.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK