9-axis means it can measure each of acceleration, gyro and magnetic field values in 3 axes, which is very useful if your drone needs to know about its own motion.
Ada compiler, runtime
The compiler is the GNAT GPL 2016 arm-eabi one (built in this case for macOS and available on Sourceforge).The MCU on the AdaRacer board is an STM32F427VIT6, which is very close to an STM32F429. The RTS is a patched version of the ravenscar-sfp-stm32f429disco RTS supplied as part of AdaCore's GNAT GPL 2016 arm-eabi compiler distribution. The changes were
- the AdaRacer crystal runs at 24 MHz rather than the 8 MHz of the STMicroelectronics discovery board. I took the liberty of simplifying the code in bsp/setup_pll.adb to use the values calculated by the STM32CubeMX tool directly.
- the AdaRacer CLI (terminal) is on UART7 rather than the discovery board's USART1.
Peripheral support
The interfaces to the board's peripherals were generated using the SVD2Ada tool from AdaCore. Unfortunately, the STM32F427.svd file was incorrect, so STM32F429.svd was used instead.MPU9250 features
The MPU9250 contains an MPU6500 accelerator/gyro sensor, and an AK8963 magnetometer. Most people use it via I2C, set up so that the AK8963 has independent (bypass) visibility on the I2C bus. AdaRacer (and the PixRacer design on which it's based) use SPI; in this mode, the AK8963 (which natively supports SPI) has to be accessed via the MPU9250's internal I2C master (the pins that would support bypassed I2C SCL, SDA are dedicated to SPI use).I don't think that SPI is the best way to manage this chip.
Talking to the MPU9250 part wasn't specially difficult. However, talking to the AK8963 via the MPU9250 was unreliable, to put it mildly.
The process of reading the AK8963's WIA register (the 'who I am' register, should read 16#48#) is (according to the datasheet):
- tell the MPU9250 to set I2C_SLV_RNW to 1 and I2C_ID to the AK8963's I2C address in I2C_SLV0_ADDR
- tell the MPU9250 to set the register number for WIA (0) in I2C_SLV0_REG
- tell the MPU9250 to set I2C_SLV_EN to 1 and I2C_SLV_LENG to the number of bytes to be transferred (1) in I2C_SLV0_CTRL
- tell the MPU9250 to read 1 byte starting at EXT_SENS_DATA
- tell the MPU9250 to set I2C_SLV_RNW to 1 and I2C_ID to the AK8963's I2C address in I2C_SLV0_ADDR
- reset /CS
- tell the MPU9250 to set I2C_SLV_RNW to 1 and I2C_ID to the AK8963's I2C address in I2C_SLV0_ADDR
- set /CS
Thirdly, after telling the MPU9250 to arrange the transfer of
Fourthly, it seems a good plan to the PX4 firmware team to ensure the MPU9250's internal I2C is disabled before altering the registers (here, function MPU9250_mag::set_passthrough()).
The whole process then becomes
- reset /CS
- sleep 100 μs
- set I2C_SLV_EN to 0 in I2C_SLV0_CTRL
- set /CS
- reset /CS
- sleep 100 μs
- tell the MPU9250 to set I2C_SLV_RNW to 1 and I2C_ID to the AK8963's I2C address in I2C_SLV0_ADDR
- set /CS
- reset /CS
- sleep 100 μs
- tell the MPU9250 to set the register number for WIA (0) in I2C_SLV0_REG
- set /CS
- reset /CS
- sleep 100 μs
- tell the MPU9250 to set I2C_SLV_EN to 1 and I2C_SLV_LENG to the number of bytes to be transferred (1) in I2C_SLV0_CTRL
- set /CS
- wait for the data to be transferred, 25 μs/byte + 400 μs
- reset /CS
- sleep 100 μs
- set I2C_SLV_EN to 0 in I2C_SLV0_CTRL -->
- set /CS
- reset /CS
- sleep 100 μs
- tell the MPU9250 to read 1 byte starting at EXT_SENS_DATA
- set /CS
Issues
Measurement rate
The MPU9250, set to a digital low-pass filter bandwidth of 184 Hz or lower, generates a new reading every millisecond. You don't need to read it this often, of course. The AK8963 can cycle at 10 Hz or 100 Hz, and doesn't seem to like to be read more often than once every 20 ms.Performance
Related to the complexity of the SPI interface, particularly to the AK8963, the overall sleep time to read the magnetometer data is over a millisecond, in (mostly) 100 μs chunks. The current implementation of the sleep is a busy-wait loop rather than an Ada delay until, because the clock tick in the RTS is set to 1 ms.Self-test
The acceleration/gyro self-test is satisfactory. I haven't been able to get the AK8963 self-test to pass, however (the Z value is out of spec, both on the AdaRacer board and on a breakout board connected to an STM32F407-Disco).Values
The acceleration values seem satisfactory ("down" reads -1 g, as you'd expect given that the chip is on the underside of the AdaRacer board). The gyro values certainly change as the board is moved! However, the magnetometer readings ...A magnetic field caculator for my Lat/Long (51.749910, -2.212471) (relishing.elastic.tungsten at what3words.com if you're interested) shows that the total field strength should be 48,754 nT (487 mG). The breakout board noted above gives a reading of 498 mG, but the AdaRacer board gives 971 mG! Perhaps there's some magnetic component on the board?
Software
The software as tested is on Github at tag report-2016-10-08.Way ahead
Performance
The main problem is the lengthy time (more than a milliseond of CPU) to read the AK8963 data. Possible approaches include- decreasing the Ada tick rate to 100 μs
- using one of the MCU's timers to manage short intervals
- using the MPU9250 FIFO
Magnetometer
The self-test is failing.The AdaRacer board is returning twice the expected value. This may be a calibration issue? I'm not sure how this is done (hints about waving the device around in a figure 8?).
Anyway, more evidence required!
No comments:
Post a Comment