| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092 |
- /**
- * @defgroup eMPL
- * @brief Embedded Motion Processing Library
- *
- * @{
- * @file main.c
- * @brief Test app for eMPL using the Motion Driver DMP image.
- */
-
- /* Includes ------------------------------------------------------------------*/
- #include <rtthread.h>
- #include <finsh.h>
- #include "stdio.h"
- #include "MD_Ported_to_RTT.h"
- #include "motion_driver_example.h"
- #include "inv_mpu.h"
- #include "inv_mpu_dmp_motion_driver.h"
- #include "invensense.h"
- // #include "invensense_adv.h"
- #include "eMPL_outputs.h"
- #include "mltypes.h"
- #include "mpu.h"
- #include "log.h"
- #include "packet.h"
- /* Private typedef -----------------------------------------------------------*/
- /* The bus name of the mpu. */
- #define RT_MPU_DEVICE_NAME "i2c2"
- /* Data read from MPL. */
- #define PRINT_ACCEL (0x01)
- #define PRINT_GYRO (0x02)
- #define PRINT_QUAT (0x04)
- #define PRINT_COMPASS (0x08)
- #define PRINT_EULER (0x10)
- #define PRINT_ROT_MAT (0x20)
- #define PRINT_HEADING (0x40)
- #define PRINT_PEDO (0x80)
- #define PRINT_LINEAR_ACCEL (0x100)
- #define PRINT_GRAVITY_VECTOR (0x200)
- volatile uint32_t hal_timestamp = 0;
- #define ACCEL_ON (0x01)
- #define GYRO_ON (0x02)
- #define COMPASS_ON (0x04)
- #define MOTION (0)
- #define NO_MOTION (1)
- /* Starting sampling rate. */
- #define DEFAULT_MPU_HZ (20)
- // #define FLASH_SIZE (512)
- // #define FLASH_MEM_START ((void*)0x1800)
- #define PEDO_READ_MS (1000)
- #define TEMP_READ_MS (500)
- #define COMPASS_READ_MS (100)
- struct rt_mpu_device *mpu_dev;
- struct rx_s {
- unsigned char header[3];
- unsigned char cmd;
- };
- struct hal_s {
- unsigned char lp_accel_mode;
- unsigned char sensors;
- unsigned char dmp_on;
- unsigned char wait_for_tap;
- volatile unsigned char new_gyro;
- unsigned char motion_int_mode;
- unsigned long no_dmp_hz;
- unsigned long next_pedo_ms;
- unsigned long next_temp_ms;
- unsigned long next_compass_ms;
- unsigned int report;
- unsigned short dmp_features;
- struct rx_s rx;
- };
- static struct hal_s hal = {0};
- /* USB RX binary semaphore. Actually, it's just a flag. Not included in struct
- * because it's declared extern elsewhere.
- */
- volatile unsigned char rx_new;
- unsigned char *mpl_key = (unsigned char*)"eMPL 5.1";
- /* Platform-specific information. Kinda like a boardfile. */
- struct platform_data_s {
- signed char orientation[9];
- };
- /* The sensors can be mounted onto the board in any orientation. The mounting
- * matrix seen below tells the MPL how to rotate the raw data from the
- * driver(s).
- * TODO: The following matrices refer to the configuration on internal test
- * boards at Invensense. If needed, please modify the matrices to match the
- * chip-to-body matrix for your particular set up.
- */
- static struct platform_data_s gyro_pdata = {
- .orientation = { 1, 0, 0,
- 0, 1, 0,
- 0, 0, 1}
- };
- #if defined MPU9150 || defined MPU9250
- static struct platform_data_s compass_pdata = {
- .orientation = { 0, 1, 0,
- 1, 0, 0,
- 0, 0, -1}
- };
- #define COMPASS_ENABLED 1
- #elif defined AK8975_SECONDARY
- static struct platform_data_s compass_pdata = {
- .orientation = {-1, 0, 0,
- 0, 1, 0,
- 0, 0,-1}
- };
- #define COMPASS_ENABLED 1
- #elif defined AK8963_SECONDARY
- static struct platform_data_s compass_pdata = {
- .orientation = {-1, 0, 0,
- 0,-1, 0,
- 0, 0, 1}
- };
- #define COMPASS_ENABLED 1
- #endif
- /* Private define ------------------------------------------------------------*/
- /* Private macro -------------------------------------------------------------*/
- /* Private variables ---------------------------------------------------------*/
- /* Private function prototypes -----------------------------------------------*/
- /* ---------------------------------------------------------------------------*/
- /* Get data from MPL.
- * TODO: Add return values to the inv_get_sensor_type_xxx APIs to differentiate
- * between new and stale data.
- */
- static void read_from_mpl(void)
- {
- long msg, data[9];
- int8_t accuracy;
- unsigned long timestamp;
- float float_data[3] = {0};
- if (inv_get_sensor_type_quat(data, &accuracy, (inv_time_t*)×tamp)) {
- /* Sends a quaternion packet to the PC. Since this is used by the Python
- * test app to visually represent a 3D quaternion, it's sent each time
- * the MPL has new data.
- */
- eMPL_send_quat(data);
- /* Specific data packets can be sent or suppressed using USB commands. */
- if (hal.report & PRINT_QUAT)
- eMPL_send_data(PACKET_DATA_QUAT, data);
- }
- if (hal.report & PRINT_ACCEL) {
- if (inv_get_sensor_type_accel(data, &accuracy,
- (inv_time_t*)×tamp))
- eMPL_send_data(PACKET_DATA_ACCEL, data);
- }
- if (hal.report & PRINT_GYRO) {
- if (inv_get_sensor_type_gyro(data, &accuracy,
- (inv_time_t*)×tamp))
- eMPL_send_data(PACKET_DATA_GYRO, data);
- }
- #ifdef COMPASS_ENABLED
- if (hal.report & PRINT_COMPASS) {
- if (inv_get_sensor_type_compass(data, &accuracy,
- (inv_time_t*)×tamp))
- eMPL_send_data(PACKET_DATA_COMPASS, data);
- }
- #endif
- if (hal.report & PRINT_EULER) {
- if (inv_get_sensor_type_euler(data, &accuracy,
- (inv_time_t*)×tamp))
- eMPL_send_data(PACKET_DATA_EULER, data);
- }
- if (hal.report & PRINT_ROT_MAT) {
- if (inv_get_sensor_type_rot_mat(data, &accuracy,
- (inv_time_t*)×tamp))
- eMPL_send_data(PACKET_DATA_ROT, data);
- }
- if (hal.report & PRINT_HEADING) {
- if (inv_get_sensor_type_heading(data, &accuracy,
- (inv_time_t*)×tamp))
- eMPL_send_data(PACKET_DATA_HEADING, data);
- }
- if (hal.report & PRINT_LINEAR_ACCEL) {
- if (inv_get_sensor_type_linear_acceleration(float_data, &accuracy, (inv_time_t*)×tamp)) {
- MPL_LOGI("Linear Accel: %7.5f %7.5f %7.5f\r\n",
- float_data[0], float_data[1], float_data[2]);
- }
- }
- if (hal.report & PRINT_GRAVITY_VECTOR) {
- if (inv_get_sensor_type_gravity(float_data, &accuracy,
- (inv_time_t*)×tamp))
- MPL_LOGI("Gravity Vector: %7.5f %7.5f %7.5f\r\n",
- float_data[0], float_data[1], float_data[2]);
- }
- if (hal.report & PRINT_PEDO) {
- unsigned long timestamp;
- get_tick_count(×tamp);
- if (timestamp > hal.next_pedo_ms) {
- hal.next_pedo_ms = timestamp + PEDO_READ_MS;
- unsigned long step_count, walk_time;
- dmp_get_pedometer_step_count(&step_count);
- dmp_get_pedometer_walk_time(&walk_time);
- MPL_LOGI("Walked %ld steps over %ld milliseconds..\n", step_count,
- walk_time);
- }
- }
- /* Whenever the MPL detects a change in motion state, the application can
- * be notified. For this example, we use an LED to represent the current
- * motion state.
- */
- msg = inv_get_message_level_0(INV_MSG_MOTION_EVENT |
- INV_MSG_NO_MOTION_EVENT);
- if (msg) {
- if (msg & INV_MSG_MOTION_EVENT) {
- MPL_LOGI("Motion!\n");
- } else if (msg & INV_MSG_NO_MOTION_EVENT) {
- MPL_LOGI("No motion!\n");
- }
- }
- }
- #ifdef COMPASS_ENABLED
- void send_status_compass() {
- long data[3] = { 0 };
- int8_t accuracy = { 0 };
- unsigned long timestamp;
- inv_get_compass_set(data, &accuracy, (inv_time_t*) ×tamp);
- MPL_LOGI("Compass: %7.4f %7.4f %7.4f ",
- data[0]/65536.f, data[1]/65536.f, data[2]/65536.f);
- MPL_LOGI("Accuracy= %d\r\n", accuracy);
- }
- #endif
- /* Handle sensor on/off combinations. */
- static void setup_gyro(void)
- {
- unsigned char mask = 0, lp_accel_was_on = 0;
- if (hal.sensors & ACCEL_ON)
- mask |= INV_XYZ_ACCEL;
- if (hal.sensors & GYRO_ON) {
- mask |= INV_XYZ_GYRO;
- lp_accel_was_on |= hal.lp_accel_mode;
- }
- #ifdef COMPASS_ENABLED
- if (hal.sensors & COMPASS_ON) {
- mask |= INV_XYZ_COMPASS;
- lp_accel_was_on |= hal.lp_accel_mode;
- }
- #endif
- /* If you need a power transition, this function should be called with a
- * mask of the sensors still enabled. The driver turns off any sensors
- * excluded from this mask.
- */
- mpu_set_sensors(mask);
- mpu_configure_fifo(mask);
- if (lp_accel_was_on) {
- unsigned short rate;
- hal.lp_accel_mode = 0;
- /* Switching out of LP accel, notify MPL of new accel sampling rate. */
- mpu_get_sample_rate(&rate);
- inv_set_accel_sample_rate(1000000L / rate);
- }
- }
- static void tap_cb(unsigned char direction, unsigned char count)
- {
- switch (direction) {
- case TAP_X_UP:
- MPL_LOGI("Tap X+ ");
- break;
- case TAP_X_DOWN:
- MPL_LOGI("Tap X- ");
- break;
- case TAP_Y_UP:
- MPL_LOGI("Tap Y+ ");
- break;
- case TAP_Y_DOWN:
- MPL_LOGI("Tap Y- ");
- break;
- case TAP_Z_UP:
- MPL_LOGI("Tap Z+ ");
- break;
- case TAP_Z_DOWN:
- MPL_LOGI("Tap Z- ");
- break;
- default:
- return;
- }
- MPL_LOGI("x%d\n", count);
- return;
- }
- static void android_orient_cb(unsigned char orientation)
- {
- switch (orientation) {
- case ANDROID_ORIENT_PORTRAIT:
- MPL_LOGI("Portrait\n");
- break;
- case ANDROID_ORIENT_LANDSCAPE:
- MPL_LOGI("Landscape\n");
- break;
- case ANDROID_ORIENT_REVERSE_PORTRAIT:
- MPL_LOGI("Reverse Portrait\n");
- break;
- case ANDROID_ORIENT_REVERSE_LANDSCAPE:
- MPL_LOGI("Reverse Landscape\n");
- break;
- default:
- return;
- }
- }
- static inline void run_self_test(void)
- {
- int result;
- long gyro[3], accel[3];
- #if defined (MPU6500) || defined (MPU9250)
- result = mpu_run_6500_self_test(gyro, accel, 0);
- #elif defined (MPU6050) || defined (MPU9150)
- result = mpu_run_self_test(gyro, accel);
- #endif
- if (result == 0x7) {
- MPL_LOGI("Passed!\n");
- MPL_LOGI("accel: %7.4f %7.4f %7.4f\n",
- accel[0]/65536.f,
- accel[1]/65536.f,
- accel[2]/65536.f);
- MPL_LOGI("gyro: %7.4f %7.4f %7.4f\n",
- gyro[0]/65536.f,
- gyro[1]/65536.f,
- gyro[2]/65536.f);
- /* Test passed. We can trust the gyro data here, so now we need to update calibrated data*/
- #ifdef USE_CAL_HW_REGISTERS
- /*
- * This portion of the code uses the HW offset registers that are in the MPUxxxx devices
- * instead of pushing the cal data to the MPL software library
- */
- unsigned char i = 0;
- for(i = 0; i<3; i++) {
- gyro[i] = (long)(gyro[i] * 32.8f); //convert to +-1000dps
- accel[i] *= 2048.f; //convert to +-16G
- accel[i] = accel[i] >> 16;
- gyro[i] = (long)(gyro[i] >> 16);
- }
- mpu_set_gyro_bias_reg(gyro);
- #if defined (MPU6500) || defined (MPU9250)
- mpu_set_accel_bias_6500_reg(accel);
- #elif defined (MPU6050) || defined (MPU9150)
- mpu_set_accel_bias_6050_reg(accel);
- #endif
- #else
- /* Push the calibrated data to the MPL library.
- *
- * MPL expects biases in hardware units << 16, but self test returns
- * biases in g's << 16.
- */
- unsigned short accel_sens;
- float gyro_sens;
- mpu_get_accel_sens(&accel_sens);
- accel[0] *= accel_sens;
- accel[1] *= accel_sens;
- accel[2] *= accel_sens;
- inv_set_accel_bias(accel, 3);
- mpu_get_gyro_sens(&gyro_sens);
- gyro[0] = (long) (gyro[0] * gyro_sens);
- gyro[1] = (long) (gyro[1] * gyro_sens);
- gyro[2] = (long) (gyro[2] * gyro_sens);
- inv_set_gyro_bias(gyro, 3);
- #endif
- }
- else {
- if (!(result & 0x1))
- MPL_LOGE("Gyro failed.\n");
- if (!(result & 0x2))
- MPL_LOGE("Accel failed.\n");
- if (!(result & 0x4))
- MPL_LOGE("Compass failed.\n");
- }
- }
- static void handle_input(int argc, char **argv)
- {
- char c;
- if (argc < 2)
- {
- rt_kprintf("\n");
- // rt_kprintf("mpu6xxx [OPTION] [PARAM]\n");
- rt_kprintf("argc must more than 2\n");
- return ;
- }
- else if (argc == 2)
- {
- c = argv[1];
- rt_kprintf("input c=%c\n", c);
- }
- else
- {
- rt_kprintf("Unknown command!\n");
- }
-
- switch (c) {
- /* These commands turn off individual sensors. */
- case '8':
- hal.sensors ^= ACCEL_ON;
- setup_gyro();
- if (!(hal.sensors & ACCEL_ON))
- inv_accel_was_turned_off();
- break;
- case '9':
- hal.sensors ^= GYRO_ON;
- setup_gyro();
- if (!(hal.sensors & GYRO_ON))
- inv_gyro_was_turned_off();
- break;
- #ifdef COMPASS_ENABLED
- case '0':
- hal.sensors ^= COMPASS_ON;
- setup_gyro();
- if (!(hal.sensors & COMPASS_ON))
- inv_compass_was_turned_off();
- break;
- #endif
- /* The commands send individual sensor data or fused data to the PC. */
- case 'a':
- hal.report ^= PRINT_ACCEL;
- break;
- case 'g':
- hal.report ^= PRINT_GYRO;
- break;
- #ifdef COMPASS_ENABLED
- case 'c':
- hal.report ^= PRINT_COMPASS;
- break;
- #endif
- case 'e':
- hal.report ^= PRINT_EULER;
- break;
- case 'r':
- hal.report ^= PRINT_ROT_MAT;
- break;
- case 'q':
- hal.report ^= PRINT_QUAT;
- break;
- case 'h':
- hal.report ^= PRINT_HEADING;
- break;
- case 'i':
- hal.report ^= PRINT_LINEAR_ACCEL;
- break;
- case 'o':
- hal.report ^= PRINT_GRAVITY_VECTOR;
- break;
- #ifdef COMPASS_ENABLED
- case 'w':
- send_status_compass();
- break;
- #endif
- /* This command prints out the value of each gyro register for debugging.
- * If logging is disabled, this function has no effect.
- */
- case 'd':
- mpu_reg_dump();
- break;
- /* Test out low-power accel mode. */
- case 'p':
- if (hal.dmp_on)
- /* LP accel is not compatible with the DMP. */
- break;
- mpu_lp_accel_mode(20);
- /* When LP accel mode is enabled, the driver automatically configures
- * the hardware for latched interrupts. However, the MCU sometimes
- * misses the rising/falling edge, and the hal.new_gyro flag is never
- * set. To avoid getting locked in this state, we're overriding the
- * driver's configuration and sticking to unlatched interrupt mode.
- *
- * TODO: The MCU supports level-triggered interrupts.
- */
- mpu_set_int_latched(0);
- hal.sensors &= ~(GYRO_ON|COMPASS_ON);
- hal.sensors |= ACCEL_ON;
- hal.lp_accel_mode = 1;
- inv_gyro_was_turned_off();
- inv_compass_was_turned_off();
- break;
- /* The hardware self test can be run without any interaction with the
- * MPL since it's completely localized in the gyro driver. Logging is
- * assumed to be enabled; otherwise, a couple LEDs could probably be used
- * here to display the test results.
- */
- case 't':
- run_self_test();
- /* Let MPL know that contiguity was broken. */
- inv_accel_was_turned_off();
- inv_gyro_was_turned_off();
- inv_compass_was_turned_off();
- break;
- /* Depending on your application, sensor data may be needed at a faster or
- * slower rate. These commands can speed up or slow down the rate at which
- * the sensor data is pushed to the MPL.
- *
- * In this example, the compass rate is never changed.
- */
- case '1':
- if (hal.dmp_on) {
- dmp_set_fifo_rate(10);
- inv_set_quat_sample_rate(100000L);
- } else
- mpu_set_sample_rate(10);
- inv_set_gyro_sample_rate(100000L);
- inv_set_accel_sample_rate(100000L);
- break;
- case '2':
- if (hal.dmp_on) {
- dmp_set_fifo_rate(20);
- inv_set_quat_sample_rate(50000L);
- } else
- mpu_set_sample_rate(20);
- inv_set_gyro_sample_rate(50000L);
- inv_set_accel_sample_rate(50000L);
- break;
- case '3':
- if (hal.dmp_on) {
- dmp_set_fifo_rate(40);
- inv_set_quat_sample_rate(25000L);
- } else
- mpu_set_sample_rate(40);
- inv_set_gyro_sample_rate(25000L);
- inv_set_accel_sample_rate(25000L);
- break;
- case '4':
- if (hal.dmp_on) {
- dmp_set_fifo_rate(50);
- inv_set_quat_sample_rate(20000L);
- } else
- mpu_set_sample_rate(50);
- inv_set_gyro_sample_rate(20000L);
- inv_set_accel_sample_rate(20000L);
- break;
- case '5':
- if (hal.dmp_on) {
- dmp_set_fifo_rate(100);
- inv_set_quat_sample_rate(10000L);
- } else
- mpu_set_sample_rate(100);
- inv_set_gyro_sample_rate(10000L);
- inv_set_accel_sample_rate(10000L);
- break;
- case ',':
- /* Set hardware to interrupt on gesture event only. This feature is
- * useful for keeping the MCU asleep until the DMP detects as a tap or
- * orientation event.
- */
- dmp_set_interrupt_mode(DMP_INT_GESTURE);
- break;
- case '.':
- /* Set hardware to interrupt periodically. */
- dmp_set_interrupt_mode(DMP_INT_CONTINUOUS);
- break;
- case '6':
- /* Toggle pedometer display. */
- hal.report ^= PRINT_PEDO;
- break;
- case '7':
- /* Reset pedometer. */
- dmp_set_pedometer_step_count(0);
- dmp_set_pedometer_walk_time(0);
- break;
- case 'f':
- if (hal.lp_accel_mode)
- /* LP accel is not compatible with the DMP. */
- return;
- /* Toggle DMP. */
- if (hal.dmp_on) {
- unsigned short dmp_rate;
- unsigned char mask = 0;
- hal.dmp_on = 0;
- mpu_set_dmp_state(0);
- /* Restore FIFO settings. */
- if (hal.sensors & ACCEL_ON)
- mask |= INV_XYZ_ACCEL;
- if (hal.sensors & GYRO_ON)
- mask |= INV_XYZ_GYRO;
- if (hal.sensors & COMPASS_ON)
- mask |= INV_XYZ_COMPASS;
- mpu_configure_fifo(mask);
- /* When the DMP is used, the hardware sampling rate is fixed at
- * 200Hz, and the DMP is configured to downsample the FIFO output
- * using the function dmp_set_fifo_rate. However, when the DMP is
- * turned off, the sampling rate remains at 200Hz. This could be
- * handled in inv_mpu.c, but it would need to know that
- * inv_mpu_dmp_motion_driver.c exists. To avoid this, we'll just
- * put the extra logic in the application layer.
- */
- dmp_get_fifo_rate(&dmp_rate);
- mpu_set_sample_rate(dmp_rate);
- inv_quaternion_sensor_was_turned_off();
- MPL_LOGI("DMP disabled.\n");
- } else {
- unsigned short sample_rate;
- hal.dmp_on = 1;
- /* Preserve current FIFO rate. */
- mpu_get_sample_rate(&sample_rate);
- dmp_set_fifo_rate(sample_rate);
- inv_set_quat_sample_rate(1000000L / sample_rate);
- mpu_set_dmp_state(1);
- MPL_LOGI("DMP enabled.\n");
- }
- break;
- case 'm':
- /* Test the motion interrupt hardware feature. */
- #ifndef MPU6050 // not enabled for 6050 product
- hal.motion_int_mode = 1;
- #endif
- break;
- case 'v':
- /* Toggle LP quaternion.
- * The DMP features can be enabled/disabled at runtime. Use this same
- * approach for other features.
- */
- hal.dmp_features ^= DMP_FEATURE_6X_LP_QUAT;
- dmp_enable_feature(hal.dmp_features);
- if (!(hal.dmp_features & DMP_FEATURE_6X_LP_QUAT)) {
- inv_quaternion_sensor_was_turned_off();
- MPL_LOGI("LP quaternion disabled.\n");
- } else
- MPL_LOGI("LP quaternion enabled.\n");
- break;
- default:
- break;
- }
- hal.rx.cmd = 0;
- }
- #ifdef FINSH_USING_MSH
- MSH_CMD_EXPORT(handle_input, handle mpu commands input);
- #endif
- /* Every time new gyro data is available, this function is called in an
- * ISR context. In this example, it sets a flag protecting the FIFO read
- * function.
- */
- void gyro_data_ready_cb(void)
- {
- hal.new_gyro = 1;
- }
- /*******************************************************************************/
- /**
- * @brief main entry point.
- * @par Parameters None
- * @retval void None
- * @par Required preconditions: None
- */
-
- int _motion_driver_example(void)
- {
-
- inv_error_t result;
- unsigned char accel_fsr, new_temp = 0;
- unsigned short gyro_rate, gyro_fsr;
- unsigned long timestamp;
- struct int_param_s int_param;
- // struct rt_mpu_device *dev;
- #ifdef COMPASS_ENABLED
- unsigned char new_compass = 0;
- unsigned short compass_fsr;
- #endif
- // board_init();
-
- // result = mpu_init(&int_param);
- // if (result) {
- // MPL_LOGE("Could not initialize gyro.\n");
- // }
- /* Initialize mpu6xxx, The parameter is RT_NULL, means auto probing for i2c*/
- // rt_mpu_init(RT_MPU_DEVICE_NAME, RT_NULL);
- mpu_dev = rt_mpu_init(RT_MPU_DEVICE_NAME, RT_NULL);
- result = mpu_init(&int_param);
- if (result) {
- log_e("Could not initialize gyro.\n");
- }
- // if (dev == RT_NULL)
- // {
- // rt_kprintf("mpu init failed\n");
- // return -1;
- // }
- // rt_kprintf("mpu init succeed\n");
- /* If you're not using an MPU9150 AND you're not using DMP features, this
- * function will place all slaves on the primary bus.
- * mpu_set_bypass(1);
- */
- result = inv_init_mpl();
- if (result) {
- MPL_LOGE("Could not initialize MPL.\n");
- }
- // /* Compute 6-axis and 9-axis quaternions. */
- // inv_enable_quaternion();
- // inv_enable_9x_sensor_fusion();
- /* The MPL expects compass data at a constant rate (matching the rate
- * passed to inv_set_compass_sample_rate). If this is an issue for your
- * application, call this function, and the MPL will depend on the
- * timestamps passed to inv_build_compass instead.
- *
- * inv_9x_fusion_use_timestamps(1);
- */
- /* This function has been deprecated.
- * inv_enable_no_gyro_fusion();
- */
- /* Update gyro biases when not in motion.
- * WARNING: These algorithms are mutually exclusive.
- */
- // inv_enable_fast_nomot();
- /* inv_enable_motion_no_motion(); */
- /* inv_set_no_motion_time(1000); */
- /* Update gyro biases when temperature changes. */
- // inv_enable_gyro_tc();
- /* This algorithm updates the accel biases when in motion. A more accurate
- * bias measurement can be made when running the self-test (see case 't' in
- * handle_input), but this algorithm can be enabled if the self-test can't
- * be executed in your application.
- *
- * inv_enable_in_use_auto_calibration();
- */
- #ifdef COMPASS_ENABLED
- /* Compass calibration algorithms. */
- inv_enable_vector_compass_cal();
- inv_enable_magnetic_disturbance();
- #endif
- /* If you need to estimate your heading before the compass is calibrated,
- * enable this algorithm. It becomes useless after a good figure-eight is
- * detected, so we'll just leave it out to save memory.
- * inv_enable_heading_from_gyro();
- */
- /* Allows use of the MPL APIs in read_from_mpl. */
- inv_enable_eMPL_outputs();
- result = inv_start_mpl();
- if (result == INV_ERROR_NOT_AUTHORIZED) {
- while (1) {
- MPL_LOGE("Not authorized.\n");
- }
- }
- if (result) {
- MPL_LOGE("Could not start the MPL.\n");
- }
- /* Get/set hardware configuration. Start gyro. */
- /* Wake up all sensors. */
- #ifdef COMPASS_ENABLED
- mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL | INV_XYZ_COMPASS);
- #else
- mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL);
- #endif
- /* Push both gyro and accel data into the FIFO. */
- mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL);
- mpu_set_sample_rate(DEFAULT_MPU_HZ);
- #ifdef COMPASS_ENABLED
- /* The compass sampling rate can be less than the gyro/accel sampling rate.
- * Use this function for proper power management.
- */
- mpu_set_compass_sample_rate(1000 / COMPASS_READ_MS);
- #endif
- /* Read back configuration in case it was set improperly. */
- mpu_get_sample_rate(&gyro_rate);
- mpu_get_gyro_fsr(&gyro_fsr);
- mpu_get_accel_fsr(&accel_fsr);
- #ifdef COMPASS_ENABLED
- mpu_get_compass_fsr(&compass_fsr);
- #endif
- /* Sync driver configuration with MPL. */
- /* Sample rate expected in microseconds. */
- inv_set_gyro_sample_rate(1000000L / gyro_rate);
- inv_set_accel_sample_rate(1000000L / gyro_rate);
- #ifdef COMPASS_ENABLED
- /* The compass rate is independent of the gyro and accel rates. As long as
- * inv_set_compass_sample_rate is called with the correct value, the 9-axis
- * fusion algorithm's compass correction gain will work properly.
- */
- inv_set_compass_sample_rate(COMPASS_READ_MS * 1000L);
- #endif
- /* Set chip-to-body orientation matrix.
- * Set hardware units to dps/g's/degrees scaling factor.
- */
- inv_set_gyro_orientation_and_scale(
- inv_orientation_matrix_to_scalar(gyro_pdata.orientation),
- (long)gyro_fsr<<15);
- inv_set_accel_orientation_and_scale(
- inv_orientation_matrix_to_scalar(gyro_pdata.orientation),
- (long)accel_fsr<<15);
- #ifdef COMPASS_ENABLED
- inv_set_compass_orientation_and_scale(
- inv_orientation_matrix_to_scalar(compass_pdata.orientation),
- (long)compass_fsr<<15);
- #endif
- /* Initialize HAL state variables. */
- #ifdef COMPASS_ENABLED
- hal.sensors = ACCEL_ON | GYRO_ON | COMPASS_ON;
- #else
- hal.sensors = ACCEL_ON | GYRO_ON;
- #endif
- hal.dmp_on = 0;
- hal.report = 0;
- hal.rx.cmd = 0;
- hal.next_pedo_ms = 0;
- hal.next_compass_ms = 0;
- hal.next_temp_ms = 0;
- /* Compass reads are handled by scheduler. */
- get_tick_count(×tamp);
- /* To initialize the DMP:
- * 1. Call dmp_load_motion_driver_firmware(). This pushes the DMP image in
- * inv_mpu_dmp_motion_driver.h into the MPU memory.
- * 2. Push the gyro and accel orientation matrix to the DMP.
- * 3. Register gesture callbacks. Don't worry, these callbacks won't be
- * executed unless the corresponding feature is enabled.
- * 4. Call dmp_enable_feature(mask) to enable different features.
- * 5. Call dmp_set_fifo_rate(freq) to select a DMP output rate.
- * 6. Call any feature-specific control functions.
- *
- * To enable the DMP, just call mpu_set_dmp_state(1). This function can
- * be called repeatedly to enable and disable the DMP at runtime.
- *
- * The following is a short summary of the features supported in the DMP
- * image provided in inv_mpu_dmp_motion_driver.c:
- * DMP_FEATURE_LP_QUAT: Generate a gyro-only quaternion on the DMP at
- * 200Hz. Integrating the gyro data at higher rates reduces numerical
- * errors (compared to integration on the MCU at a lower sampling rate).
- * DMP_FEATURE_6X_LP_QUAT: Generate a gyro/accel quaternion on the DMP at
- * 200Hz. Cannot be used in combination with DMP_FEATURE_LP_QUAT.
- * DMP_FEATURE_TAP: Detect taps along the X, Y, and Z axes.
- * DMP_FEATURE_ANDROID_ORIENT: Google's screen rotation algorithm. Triggers
- * an event at the four orientations where the screen should rotate.
- * DMP_FEATURE_GYRO_CAL: Calibrates the gyro data after eight seconds of
- * no motion.
- * DMP_FEATURE_SEND_RAW_ACCEL: Add raw accelerometer data to the FIFO.
- * DMP_FEATURE_SEND_RAW_GYRO: Add raw gyro data to the FIFO.
- * DMP_FEATURE_SEND_CAL_GYRO: Add calibrated gyro data to the FIFO. Cannot
- * be used in combination with DMP_FEATURE_SEND_RAW_GYRO.
- */
- dmp_load_motion_driver_firmware();
- dmp_set_orientation(
- inv_orientation_matrix_to_scalar(gyro_pdata.orientation));
- dmp_register_tap_cb(tap_cb);
- dmp_register_android_orient_cb(android_orient_cb);
- /*
- * Known Bug -
- * DMP when enabled will sample sensor data at 200Hz and output to FIFO at the rate
- * specified in the dmp_set_fifo_rate API. The DMP will then sent an interrupt once
- * a sample has been put into the FIFO. Therefore if the dmp_set_fifo_rate is at 25Hz
- * there will be a 25Hz interrupt from the MPU device.
- *
- * There is a known issue in which if you do not enable DMP_FEATURE_TAP
- * then the interrupts will be at 200Hz even if fifo rate
- * is set at a different rate. To avoid this issue include the DMP_FEATURE_TAP
- *
- * DMP sensor fusion works only with gyro at +-2000dps and accel +-2G
- */
- hal.dmp_features = DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_TAP |
- DMP_FEATURE_ANDROID_ORIENT | DMP_FEATURE_SEND_RAW_ACCEL | DMP_FEATURE_SEND_CAL_GYRO |
- DMP_FEATURE_GYRO_CAL;
- dmp_enable_feature(hal.dmp_features);
- dmp_set_fifo_rate(DEFAULT_MPU_HZ);
- mpu_set_dmp_state(1);
- hal.dmp_on = 1;
- while(1){
-
- unsigned long sensor_timestamp;
- int new_data = 0;
- // if (USART_GetITStatus(USART2, USART_IT_RXNE)) {
- // /* A byte has been received via USART. See handle_input for a list of
- // * valid commands.
- // */
- // USART_ClearITPendingBit(USART2, USART_IT_RXNE);
- // handle_input();
- // }
- get_tick_count(×tamp);
- // #ifdef COMPASS_ENABLED
- // /* We're not using a data ready interrupt for the compass, so we'll
- // * make our compass reads timer-based instead.
- // */
- // if ((timestamp > hal.next_compass_ms) && !hal.lp_accel_mode &&
- // hal.new_gyro && (hal.sensors & COMPASS_ON)) {
- // hal.next_compass_ms = timestamp + COMPASS_READ_MS;
- // new_compass = 1;
- // }
- // #endif
- /* Temperature data doesn't need to be read with every gyro sample.
- * Let's make them timer-based like the compass reads.
- */
- if (timestamp > hal.next_temp_ms) {
- hal.next_temp_ms = timestamp + TEMP_READ_MS;
- new_temp = 1;
- }
- if (hal.motion_int_mode) {
- /* Enable motion interrupt. */
- // mpu_lp_motion_interrupt(500, 1, 5);
- /* Notify the MPL that contiguity was broken. */
- inv_accel_was_turned_off();
- inv_gyro_was_turned_off();
- inv_compass_was_turned_off();
- inv_quaternion_sensor_was_turned_off();
- /* Wait for the MPU interrupt. */
- while (!hal.new_gyro) {}
- /* Restore the previous sensor configuration. */
- // mpu_lp_motion_interrupt(0, 0, 0);
- hal.motion_int_mode = 0;
- }
- // if (!hal.sensors || !hal.new_gyro) {
- // continue;
- // }
- if (hal.new_gyro && hal.lp_accel_mode) {
- short accel_short[3];
- long accel[3];
- mpu_get_accel_reg(accel_short, &sensor_timestamp);
- accel[0] = (long)accel_short[0];
- accel[1] = (long)accel_short[1];
- accel[2] = (long)accel_short[2];
- inv_build_accel(accel, 0, sensor_timestamp);
- new_data = 1;
- hal.new_gyro = 0;
- } else if (hal.new_gyro && hal.dmp_on) {
- short gyro[3], accel_short[3], sensors;
- unsigned char more;
- long accel[3], quat[4], temperature;
- /* This function gets new data from the FIFO when the DMP is in
- * use. The FIFO can contain any combination of gyro, accel,
- * quaternion, and gesture data. The sensors parameter tells the
- * caller which data fields were actually populated with new data.
- * For example, if sensors == (INV_XYZ_GYRO | INV_WXYZ_QUAT), then
- * the FIFO isn't being filled with accel data.
- * The driver parses the gesture data to determine if a gesture
- * event has occurred; on an event, the application will be notified
- * via a callback (assuming that a callback function was properly
- * registered). The more parameter is non-zero if there are
- * leftover packets in the FIFO.
- */
- dmp_read_fifo(gyro, accel_short, quat, &sensor_timestamp, &sensors, &more);
- if (!more)
- hal.new_gyro = 0;
- if (sensors & INV_XYZ_GYRO) {
- /* Push the new data to the MPL. */
- inv_build_gyro(gyro, sensor_timestamp);
- new_data = 1;
- if (new_temp) {
- new_temp = 0;
- /* Temperature only used for gyro temp comp. */
- mpu_get_temperature(&temperature, &sensor_timestamp);
- inv_build_temp(temperature, sensor_timestamp);
- }
- }
- if (sensors & INV_XYZ_ACCEL) {
- accel[0] = (long)accel_short[0];
- accel[1] = (long)accel_short[1];
- accel[2] = (long)accel_short[2];
- inv_build_accel(accel, 0, sensor_timestamp);
- new_data = 1;
- }
- if (sensors & INV_WXYZ_QUAT) {
- inv_build_quat(quat, 0, sensor_timestamp);
- new_data = 1;
- }
- } else if (hal.new_gyro) {
- short gyro[3], accel_short[3];
- unsigned char sensors, more;
- long accel[3], temperature;
- /* This function gets new data from the FIFO. The FIFO can contain
- * gyro, accel, both, or neither. The sensors parameter tells the
- * caller which data fields were actually populated with new data.
- * For example, if sensors == INV_XYZ_GYRO, then the FIFO isn't
- * being filled with accel data. The more parameter is non-zero if
- * there are leftover packets in the FIFO. The HAL can use this
- * information to increase the frequency at which this function is
- * called.
- */
- hal.new_gyro = 0;
- mpu_read_fifo(gyro, accel_short, &sensor_timestamp,
- &sensors, &more);
- if (more)
- hal.new_gyro = 1;
- if (sensors & INV_XYZ_GYRO) {
- /* Push the new data to the MPL. */
- inv_build_gyro(gyro, sensor_timestamp);
- new_data = 1;
- if (new_temp) {
- new_temp = 0;
- /* Temperature only used for gyro temp comp. */
- mpu_get_temperature(&temperature, &sensor_timestamp);
- inv_build_temp(temperature, sensor_timestamp);
- }
- }
- if (sensors & INV_XYZ_ACCEL) {
- accel[0] = (long)accel_short[0];
- accel[1] = (long)accel_short[1];
- accel[2] = (long)accel_short[2];
- inv_build_accel(accel, 0, sensor_timestamp);
- new_data = 1;
- }
- }
- #ifdef COMPASS_ENABLED
- if (new_compass) {
- short compass_short[3];
- long compass[3];
- new_compass = 0;
- /* For any MPU device with an AKM on the auxiliary I2C bus, the raw
- * magnetometer registers are copied to special gyro registers.
- */
- if (!mpu_get_compass_reg(compass_short, &sensor_timestamp)) {
- compass[0] = (long)compass_short[0];
- compass[1] = (long)compass_short[1];
- compass[2] = (long)compass_short[2];
- /* NOTE: If using a third-party compass calibration library,
- * pass in the compass data in uT * 2^16 and set the second
- * parameter to INV_CALIBRATED | acc, where acc is the
- * accuracy from 0 to 3.
- */
- inv_build_compass(compass, 0, sensor_timestamp);
- }
- new_data = 1;
- }
- #endif
- if (new_data) {
- inv_execute_on_data();
- /* This function reads bias-compensated sensor data and sensor
- * fusion outputs from the MPL. The outputs are formatted as seen
- * in eMPL_outputs.c. This function only needs to be called at the
- * rate requested by the host.
- */
- read_from_mpl();
- }
- rt_thread_mdelay(10);
- }
- // rt_mpu_deinit(dev);
- }
- int motion_driver_example(void)
- {
- rt_err_t ret = RT_EOK;
- rt_thread_t thread = RT_NULL;
- thread = rt_thread_create("motion_driver",
- _motion_driver_example, RT_NULL,
- 10*1024, 5, 10);
- if(thread == RT_NULL)
- {
- return RT_ERROR;
- }
- rt_thread_startup(thread);
- return RT_EOK;
- }
- MSH_CMD_EXPORT(motion_driver_example, motion driver test function);
|