Module f3::examples::_13_log_sensors
[−]
[src]
Logs data from the motion sensors over ITM
This example logs sensor data over ITM. The data is encoded in a binary format and logged as COBS frames. The binary format is as follows:
Magnetometer readings
mx
:i16
, LE (Little Endian), 2 bytesmy
:i16
, LE, 2 bytesmz
:i16
, LE, 2 bytes
Gyroscope readings
arx
:i16
, LE, 2 bytesary
:i16
, LE, 2 bytesarz
:i16
, LE, 2 bytes
Accelerometer readings
gx
:i16
, LE, 2 bytesgy
:i16
, LE, 2 bytesgz
:i16
, LE, 2 bytes
The suggested way to receive this data is to connect the F3 SWO pin to a UART to USB converter
and then to read out the associated device file using itmdump
. Make sure you configure the
serial device before calling itmdump
. The commands to run are:
$ stty -F /dev/ttyUSB0 raw 2000000 -echo
$ itmdump -f /dev/ttyUSB0 > data.txt
You can plot this data using the plot.py
script in the root of this crate.
#![deny(warnings)] #![no_std] extern crate aligned; extern crate byteorder; extern crate cobs; extern crate cortex_m; extern crate f3; #[macro_use(block)] extern crate nb; use core::ptr; use aligned::Aligned; use byteorder::{ByteOrder, LE}; use cortex_m::{asm, itm}; use f3::hal::i2c::I2c; use f3::hal::prelude::*; use f3::hal::spi::Spi; use f3::hal::stm32f30x; use f3::hal::timer::Timer; use f3::l3gd20::{self, Odr}; use f3::lsm303dlhc::{AccelOdr, MagOdr}; use f3::{L3gd20, Lsm303dlhc}; // TRY changing the sampling frequency const FREQUENCY: u32 = 220; // TRY changing the number of samples const NSAMPLES: u32 = 32 * FREQUENCY; // = 32 seconds fn main() { let mut cp = cortex_m::Peripherals::take().unwrap(); let dp = stm32f30x::Peripherals::take().unwrap(); let mut flash = dp.FLASH.constrain(); let mut rcc = dp.RCC.constrain(); let clocks = rcc.cfgr .sysclk(64.mhz()) .pclk1(32.mhz()) .freeze(&mut flash.acr); // enable ITM // TODO this should be some high level API in the cortex-m crate unsafe { // enable TPIU and ITM cp.DCB.demcr.modify(|r| r | (1 << 24)); // prescaler let swo_freq = 2_000_000; cp.TPIU.acpr.write((clocks.sysclk().0 / swo_freq) - 1); // SWO NRZ cp.TPIU.sppr.write(2); cp.TPIU.ffcr.modify(|r| r & !(1 << 1)); // STM32 specific: enable tracing in the DBGMCU_CR register const DBGMCU_CR: *mut u32 = 0xe0042004 as *mut u32; let r = ptr::read_volatile(DBGMCU_CR); ptr::write_volatile(DBGMCU_CR, r | (1 << 5)); // unlock the ITM cp.ITM.lar.write(0xC5ACCE55); cp.ITM.tcr.write( (0b000001 << 16) | // TraceBusID (1 << 3) | // enable SWO output (1 << 0), // enable the ITM ); // enable stimulus port 0 cp.ITM.ter[0].write(1); } let mut gpioa = dp.GPIOA.split(&mut rcc.ahb); let mut gpiob = dp.GPIOB.split(&mut rcc.ahb); let mut gpioe = dp.GPIOE.split(&mut rcc.ahb); // I2C let scl = gpiob.pb6.into_af4(&mut gpiob.moder, &mut gpiob.afrl); let sda = gpiob.pb7.into_af4(&mut gpiob.moder, &mut gpiob.afrl); let i2c = I2c::i2c1(dp.I2C1, (scl, sda), 400.khz(), clocks, &mut rcc.apb1); // LSM303DLHC let mut lsm303dlhc = Lsm303dlhc::new(i2c).unwrap(); lsm303dlhc.accel_odr(AccelOdr::Hz400).unwrap(); lsm303dlhc.mag_odr(MagOdr::Hz220).unwrap(); // SPI let mut nss = gpioe .pe3 .into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper); nss.set_high(); let sck = gpioa.pa5.into_af5(&mut gpioa.moder, &mut gpioa.afrl); let miso = gpioa.pa6.into_af5(&mut gpioa.moder, &mut gpioa.afrl); let mosi = gpioa.pa7.into_af5(&mut gpioa.moder, &mut gpioa.afrl); let spi = Spi::spi1( dp.SPI1, (sck, miso, mosi), l3gd20::MODE, 1.mhz(), clocks, &mut rcc.apb2, ); // L3GD20 let mut l3gd20 = L3gd20::new(spi, nss).unwrap(); l3gd20.set_odr(Odr::Hz380).unwrap(); // TIMER let mut timer = Timer::tim2(dp.TIM2, FREQUENCY.hz(), clocks, &mut rcc.apb1); // start of COBS frame itm::write_all(&mut cp.ITM.stim[0], &[0]); // Capture N samples let mut tx_buf: Aligned<u32, [u8; 20]> = Aligned([0; 20]); for _ in 0..NSAMPLES { block!(timer.wait()).unwrap(); // Read sensors let m = lsm303dlhc.mag().unwrap(); let ar = l3gd20.gyro().unwrap(); let g = lsm303dlhc.accel().unwrap(); // Serialize the data let mut buf = [0; 18]; let mut start = 0; LE::write_i16(&mut buf[start..start + 2], m.x); start += 2; LE::write_i16(&mut buf[start..start + 2], m.y); start += 2; LE::write_i16(&mut buf[start..start + 2], m.z); start += 2; LE::write_i16(&mut buf[start..start + 2], ar.x); start += 2; LE::write_i16(&mut buf[start..start + 2], ar.y); start += 2; LE::write_i16(&mut buf[start..start + 2], ar.z); start += 2; LE::write_i16(&mut buf[start..start + 2], g.x); start += 2; LE::write_i16(&mut buf[start..start + 2], g.y); start += 2; LE::write_i16(&mut buf[start..start + 2], g.z); // Log data cobs::encode(&buf, &mut tx_buf); itm::write_aligned(&mut cp.ITM.stim[0], &tx_buf); } // Done asm::bkpt(); }