@@ -80,16 +80,16 @@ static float q3[4] = {SENSOR_QUATERNION_CORRECTION}; // correction quaternion
8080
8181static float last_lin_a [3 ] = {0 }; // vector to hold last linear accelerometer
8282
83+ static float last_m [3 ] = {0 };
84+ static int64_t last_mag_time = -1000 ;
85+ static int64_t mag_interval = 0 ;
86+
8387static float temp ; // sensor temperature
8488static int64_t last_temp_time = -1000 ;
8589
8690static int64_t last_suspend_attempt_time = 0 ;
8791static int64_t last_data_time ;
8892
89- static float max_gyro_speed_square ;
90- static bool mag_use_oneshot ;
91- static bool mag_skip_oneshot ;
92-
9393static float accel_actual_time ;
9494static float gyro_actual_time ;
9595static float mag_actual_time ;
@@ -680,9 +680,9 @@ int sensor_init(void)
680680 mag_enabled = CONFIG_1_SETTINGS_READ (CONFIG_1_SENSOR_USE_MAG );
681681
682682 // setup sensor, set ODR
683- float accel_initial_time = 1.0 / CONFIG_2_SETTINGS_READ (CONFIG_2_SENSOR_ACCEL_ODR ); // configure with ~1000Hz ODR
684- float gyro_initial_time = 1.0 / CONFIG_2_SETTINGS_READ (CONFIG_2_SENSOR_GYRO_ODR ); // configure with ~1000Hz ODR
685- float mag_initial_time = sensor_update_time_ms / 1000.0 ; // configure with ~200Hz ODR
683+ float accel_initial_time = 1.0 / CONFIG_2_SETTINGS_READ (CONFIG_2_SENSOR_ACCEL_ODR );
684+ float gyro_initial_time = 1.0 / CONFIG_2_SETTINGS_READ (CONFIG_2_SENSOR_GYRO_ODR );
685+ float mag_initial_time = 0.1 ; // configure with 10Hz ODR
686686 err = sensor_imu -> init (clock_actual_rate , accel_initial_time , gyro_initial_time , & accel_actual_time , & gyro_actual_time );
687687 sensor_actual_time = MIN (accel_actual_time , gyro_actual_time );
688688#if SENSOR_IMU_SPI_EXISTS
@@ -697,7 +697,8 @@ int sensor_init(void)
697697 {
698698 // TODO: need to flag passthrough enabled
699699// sensor_imu->ext_passthrough(true); // reenable passthrough
700- err = sensor_mag -> init (mag_initial_time , & mag_actual_time ); // configure with ~200Hz ODR
700+ err = sensor_mag -> init (mag_initial_time , & mag_actual_time );
701+ mag_interval = mag_actual_time * 0.9f * 1000 ; // start attemping magnetometer reads before expected new sample
701702#if SENSOR_MAG_SPI_EXISTS
702703 LOG_INF ("Requested SPI frequency: %.2fMHz" , (double )sensor_mag_spi_dev .config .frequency / 1000000.0 );
703704#endif
@@ -724,7 +725,7 @@ int sensor_init(void)
724725 }
725726 else
726727 {
727- sensor_fusion -> init (gyro_actual_time , accel_actual_time , mag_initial_time ); // TODO: using initial time since mag are not polled at the actual rate
728+ sensor_fusion -> init (gyro_actual_time , accel_actual_time , mag_actual_time );
728729 }
729730
730731 sensor_calibration_update_sensor_ids (sensor_imu_id );
@@ -778,6 +779,7 @@ static uint64_t total_read_packets = 0;
778779static uint64_t total_processed_packets = 0 ;
779780static uint64_t total_gyro_samples = 0 ;
780781static uint64_t total_accel_samples = 0 ;
782+ static uint64_t total_mag_samples = 0 ;
781783static uint64_t total_loop_time = 0 ;
782784static uint64_t total_loop_iterations = 0 ;
783785#endif
@@ -815,11 +817,6 @@ void sensor_loop(void)
815817 // Fusing data will take between 100us (~7 samples, low noise) - 500us (~33 samples, low power) for xiofusion
816818 // TODO: on any errors set main_ok false and skip (make functions return nonzero)
817819
818- // At high speed, use oneshot mode to have synced magnetometer data
819- // Call before FIFO and get the data after
820- if (mag_available && mag_enabled && mag_use_oneshot )
821- sensor_mag -> mag_oneshot ();
822-
823820 // Read IMU temperature
824821 err = sensor_imu -> temp_read (& temp ); // TODO: use as calibration data
825822 if (!err )
@@ -853,8 +850,12 @@ void sensor_loop(void)
853850
854851 // Read magnetometer
855852 float raw_m [3 ];
856- if (mag_available && mag_enabled )
853+ bool mag_read = false;
854+ if (mag_available && mag_enabled && (k_uptime_get () - last_mag_time > mag_interval )) // some magnetometer do not have int pin // TODO: implement for magnetometer that does, or read status byte
855+ {
856+ mag_read = true;
857857 sensor_mag -> mag_read (raw_m ); // reading mag last, and it will be processed last
858+ }
858859
859860 int16_t last_sensor_fifo_threshold = sensor_fifo_threshold ;
860861
@@ -885,7 +886,6 @@ void sensor_loop(void)
885886 int g_count = 0 ;
886887 float a_sum [3 ] = {0 };
887888 int a_count = 0 ;
888- max_gyro_speed_square = 0 ;
889889 int processed_packets = 0 ;
890890 for (uint16_t i = 0 ; i < packets ; i ++ )
891891 {
@@ -919,11 +919,6 @@ void sensor_loop(void)
919919 sensor_fusion -> get_gyro_bias (g_off );
920920 for (int i = 0 ; i < 3 ; i ++ )
921921 g_off [i ] = g [i ] - g_off [i ];
922-
923- // Get the highest gyro speed
924- float gyro_speed_square = g_off [0 ] * g_off [0 ] + g_off [1 ] * g_off [1 ] + g_off [2 ] * g_off [2 ];
925- if (gyro_speed_square > max_gyro_speed_square )
926- max_gyro_speed_square = gyro_speed_square ;
927922 }
928923 }
929924
@@ -961,16 +956,19 @@ void sensor_loop(void)
961956 total_processed_packets += processed_packets ;
962957#endif
963958
964- if (mag_available && mag_enabled )
959+ if (mag_available && mag_enabled && mag_read && memcmp ( raw_m , last_m , sizeof ( last_m ))) // check data has changed from last acquisition
965960 {
961+ #if DEBUG
962+ total_mag_samples ++ ;
963+ #endif
964+ last_mag_time = k_uptime_get ();
966965 bool mag_calibrated = true;
967- float uncalibrated_m [3 ] = {0 };
968- memcpy (uncalibrated_m , raw_m , sizeof (uncalibrated_m )); // copy raw magnetometer data
966+ memcpy (last_m , raw_m , sizeof (last_m )); // copy raw magnetometer data
969967 sensor_calibration_process_mag (raw_m );
970968 float zero_m [3 ] = {0 };
971969 if (v_epsilon (raw_m , zero_m , 1e-6 )) // if the magnetometer is not calibrated, skip and send raw data
972970 {
973- memcpy (raw_m , uncalibrated_m , sizeof (uncalibrated_m ));
971+ memcpy (raw_m , last_m , sizeof (last_m ));
974972 mag_calibrated = false;
975973 }
976974 float mx = raw_m [0 ];
@@ -980,7 +978,7 @@ void sensor_loop(void)
980978
981979 // Process fusion
982980 if (mag_calibrated )
983- sensor_fusion -> update_mag (m , sensor_update_time_ms / 1000.0 ); // TODO: use actual time?
981+ sensor_fusion -> update_mag (m , mag_actual_time );
984982
985983 v_rotate (m , q3 , m ); // magnetic field in local device frame, no other transformation will be done
986984 connection_update_sensor_mag (m );
@@ -1035,43 +1033,6 @@ void sensor_loop(void)
10351033
10361034 sensor_update_sensor_state ();
10371035
1038- // Update magnetometer mode
1039- if (mag_available && mag_enabled )
1040- {
1041- // TODO: magnetometer might be better to limit to a lower (fixed) rate
1042- float gyro_speed = sqrtf (max_gyro_speed_square );
1043- float mag_target_time = 1.0f / (4 * gyro_speed ); // target mag ODR for ~0.25 deg error
1044- if (mag_target_time < 0.005f && mag_skip_oneshot ) // only use continuous modes if oneshot is not available
1045- mag_target_time = 0.005 ;
1046- if (mag_target_time > 0.1f ) // limit to 0.1 (minimum 10Hz)
1047- mag_target_time = 0.1 ;
1048- sys_interface_resume ();
1049- if (mag_target_time < 0.005f ) // cap at 0.005 (200Hz), above this the sensor will use oneshot mode instead
1050- {
1051- int err = sensor_mag -> update_odr (INFINITY , & mag_actual_time );
1052- if (mag_actual_time == INFINITY )
1053- {
1054- if (!err )
1055- LOG_DBG ("Switching magnetometer to oneshot" );
1056- mag_use_oneshot = true;
1057- }
1058- else // magnetometer did not have a oneshot mode, try 200Hz
1059- {
1060- if (!err )
1061- mag_skip_oneshot = true;
1062- mag_target_time = 0.005 ;
1063- }
1064- }
1065- if (mag_target_time >= 0.005f || mag_actual_time != INFINITY ) // under 200Hz or magnetometer did not have a oneshot mode
1066- {
1067- int err = sensor_mag -> update_odr (mag_target_time , & mag_actual_time );
1068- if (!err )
1069- LOG_DBG ("Switching magnetometer ODR to %.2fHz" , 1.0 / (double )mag_actual_time );
1070- mag_use_oneshot = false;
1071- }
1072- sys_interface_suspend ();
1073- }
1074-
10751036 // Update orientation
10761037 bool send_quat_data = !q_epsilon (q , last_q , 0.001 );
10771038 bool send_lin_accel_data = !v_epsilon (lin_a , last_lin_a , 0.05 );
@@ -1109,13 +1070,13 @@ void sensor_loop(void)
11091070 last_status_time = k_uptime_get ();
11101071 if (max_loop_time > 0 )
11111072 {
1112- LOG_WRN ("Last update steps took up to %lld ms" , time_delta );
1073+ LOG_WRN ("Last update steps took up to %lld ms" , max_loop_time );
11131074 max_loop_time = 0 ;
11141075 }
11151076#if DEBUG
1116- LOG_DBG ("loop iterations: %llu, packets read: %llu, processed: %llu, gyro samples: %llu, accel samples: %llu, total acquisition time: %lld us, total loop time: %lld us" , total_loop_iterations , total_read_packets , total_processed_packets , total_gyro_samples , total_accel_samples , k_ticks_to_us_near64 (total_acquisition_time ), k_ticks_to_us_near64 (total_loop_time ));
1077+ LOG_DBG ("loop iterations: %llu, packets read: %llu, processed: %llu, gyro samples: %llu, accel samples: %llu, mag samples: %llu, total acquisition time: %lld us, total loop time: %lld us" , total_loop_iterations , total_read_packets , total_processed_packets , total_gyro_samples , total_accel_samples , total_mag_samples , k_ticks_to_us_near64 (total_acquisition_time ), k_ticks_to_us_near64 (total_loop_time ));
11171078 LOG_DBG ("sensor loop rate: %.2fHz, processing time: %.2f/%.2f us -> %.2f%%" , (double )total_loop_iterations / (double )k_ticks_to_us_near64 (total_acquisition_time ) * 1000000.0 , (double )k_ticks_to_us_near64 (total_loop_time ) / (double )total_loop_iterations , (double )k_ticks_to_us_near64 (total_acquisition_time ) / (double )total_loop_iterations , (double )total_loop_time / (double )total_acquisition_time * 100.0 );
1118- LOG_DBG ("reported gyro rate: %.2fHz, actual: %.2fHz, reported accel rate: %.2fHz, actual: %.2fHz" , 1.0 / (double )gyro_actual_time , (double )total_gyro_samples / (double )k_ticks_to_us_near64 (total_acquisition_time ) * 1000000.0 , 1.0 / (double )accel_actual_time , (double )total_accel_samples / (double )k_ticks_to_us_near64 (total_acquisition_time ) * 1000000.0 );
1079+ LOG_DBG ("reported gyro rate: %.2fHz, actual: %.2fHz, reported accel rate: %.2fHz, actual: %.2fHz, reported mag rate: %.2fHz, actual: %.2fHz " , 1.0 / (double )gyro_actual_time , (double )total_gyro_samples / (double )k_ticks_to_us_near64 (total_acquisition_time ) * 1000000.0 , 1.0 / (double )accel_actual_time , (double )total_accel_samples / ( double ) k_ticks_to_us_near64 ( total_acquisition_time ) * 1000000.0 , 1.0 / ( double ) mag_actual_time , ( double ) total_mag_samples / (double )k_ticks_to_us_near64 (total_acquisition_time ) * 1000000.0 );
11191080#endif
11201081 }
11211082
@@ -1131,9 +1092,9 @@ void sensor_loop(void)
11311092 main_wfi = false;
11321093 }
11331094 }
1134- else // if signal was sent during processing, loop immediately to catch up
1095+ else // if signal was sent during processing, loop immediately to catch up (I2C could cause this to happen constantly)
11351096 {
1136- LOG_INF ("FIFO THS/WM/WTM triggered during loop" );
1097+ LOG_DBG ("FIFO THS/WM/WTM triggered during loop" );
11371098 k_yield ();
11381099 main_wfi = false;
11391100 }
0 commit comments