Hello
I use mpu6050 and I want to use a 'Complementary Filter' to get the angle of the X, Y, and Z axes.
Applying this filter to the value of mpu6050 seems to reduce noise at first and produce good results. However, after some time, the value of the Z-axis continues to grow.
It keeps getting bigger and bigger, and after a while, the value is printed out too strangely.
This is the output when the sensor is placed on the floor. The X and Y axes seem to come out normally, but the Z axis has a strange value.
This is the code I wrote about filtering. I wrote it while referring to the example of Arduino, is there anything strange?
Or is it possible that this is a sensor problem?
//mpu6050 void mpu_init(void) { ret_code_t ret_code; // Initiate MPU driver ret_code = app_mpu_init(); APP_ERROR_CHECK(ret_code); // Check for errors in return value // Setup and configure the MPU with intial values app_mpu_config_t p_mpu_config = MPU_DEFAULT_CONFIG(); // Load default values p_mpu_config.smplrt_div = 19; // Change sampelrate. Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV). 19 gives a sample rate of 50Hz p_mpu_config.accel_config.afs_sel = AFS_2G; // Set accelerometer full scale range to 2G p_mpu_config.gyro_config.fs_sel = AFS_2G; // Set gyro full scale range to 2G ret_code = app_mpu_config(&p_mpu_config); // Configure the MPU with above values APP_ERROR_CHECK(ret_code); // Check for errors in return value } int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ; double mpu_accel_x, mpu_accel_y, mpu_accel_z; double mpu_gyro_x, mpu_gyro_y, mpu_gyro_z; float dt; float accel_angle_x, accel_angle_y, accel_angle_z; float gyro_angle_x, gyro_angle_y, gyro_angle_z; float filtered_angle_x, filtered_angle_y, filtered_angle_z; float baseAcX, baseAcY, baseAcZ; float baseGyX, baseGyY, baseGyZ; static void readAccelGyro() //send to app { uint32_t err_code; double angle_x, angle_y; accel_values_t accel_values; //mpu6050 gyro_values_t gyro_values; app_mpu_read_accel(&accel_values); err_code = app_mpu_read_accel(&accel_values); APP_ERROR_CHECK(err_code); app_mpu_read_gyro(&gyro_values); err_code = app_mpu_read_gyro(&gyro_values); APP_ERROR_CHECK(err_code); mpu_accel_x = accel_values.x; mpu_accel_y = accel_values.y; mpu_accel_z = accel_values.z; mpu_gyro_x = gyro_values.x; mpu_gyro_y = gyro_values.y; mpu_gyro_z = gyro_values.z; } void calibAccelGyro(){ float sumAcX = 0, sumAcY = 0, sumAcZ = 0; float sumGyX = 0, sumGyY = 0, sumGyZ = 0; readAccelGyro(); for(int i=0; i<10; i++){ readAccelGyro(); sumAcX += mpu_accel_x; sumAcY += mpu_accel_y; sumAcZ += mpu_accel_z; sumGyX += mpu_gyro_x; sumGyY += mpu_gyro_y; sumGyZ += mpu_gyro_z; nrf_delay_ms(100); } baseAcX = sumAcX / 10; baseAcY = sumAcY / 10; baseAcZ = sumAcZ / 10; baseGyX = sumGyX / 10; baseGyY = sumGyY / 10; baseGyZ = sumGyZ / 10; } uint32_t t_now; uint32_t t_prev; void initDT(){ t_prev = app_timer_cnt_get()*1000/32768;//milli-sec } void calcDT(){ t_now = app_timer_cnt_get()*1000/32768;//milli-sec dt = (t_now - t_prev) / 1000.0; //millis() t_prev = t_now; } void calcAccelYPR(){ float accel_x, accel_y, accel_z; float accel_xz, accel_yz; const float RADIANS_TO_DEGREES = 180/3.14159; accel_x = mpu_accel_x - baseAcX; accel_y = mpu_accel_y - baseAcY; accel_z = mpu_accel_z + (16384 - baseAcZ); accel_yz = sqrt(pow(accel_y, 2) + pow(accel_z, 2)); accel_angle_y = atan(-accel_x / accel_yz)*RADIANS_TO_DEGREES; accel_xz = sqrt(pow(accel_x, 2) + pow(accel_z, 2)); accel_angle_x = atan(accel_y / accel_xz)*RADIANS_TO_DEGREES; accel_angle_z = 0; } float gyro_x, gyro_y, gyro_z; void calcGyroYPR(){ const float GYROXYZ_TO_DEGREES_PER_SED = 131; gyro_x = (mpu_gyro_x - baseGyX) / GYROXYZ_TO_DEGREES_PER_SED; gyro_y = (mpu_gyro_y - baseGyY) / GYROXYZ_TO_DEGREES_PER_SED; gyro_z = (mpu_gyro_z - baseGyZ) / GYROXYZ_TO_DEGREES_PER_SED; gyro_angle_x += gyro_x * dt; gyro_angle_y += gyro_y * dt; gyro_angle_z += gyro_z * dt; } void calcFilteredYPR(){ const float ALPHA = 0.96; float tmp_angle_x, tmp_angle_y, tmp_angle_z; tmp_angle_x = filtered_angle_x + gyro_x * dt; tmp_angle_y = filtered_angle_y + gyro_y * dt; tmp_angle_z = filtered_angle_z + gyro_z * dt; filtered_angle_x = ALPHA * tmp_angle_x + (1.0 - ALPHA) * accel_angle_x; filtered_angle_y = ALPHA * tmp_angle_y + (1.0 - ALPHA) * accel_angle_y; filtered_angle_z = tmp_angle_z; /*printf("%.1f", filtered_angle_x); printf(", "); printf("%.1f", filtered_angle_y); printf(", "); printf("%.1f", filtered_angle_z); printf("\n"); */ } int main(void) { uint32_t err_code; bool erase_bonds = false; // Initialize. gpio_init(); uart_init(); log_init(); timers_init(); app_buttons_init(); power_management_init(); ble_stack_init(); gap_params_init(); set_static_passkey(); gatt_init(); services_init(); advertising_init(); conn_params_init(); peer_manager_init(); //err_code = app_button_enable(); err_code = app_button_disable(); APP_ERROR_CHECK(err_code); adc_configure(); pwm_init(); mpu_init(); //mpu6050 bsp_board_init(BSP_INIT_LEDS); //use bsp led // Start execution. printf("\r\nUART started.\r\n"); NRF_LOG_INFO("Debug logging for UART over RTT started."); //CenterLED_timers_start(); advertising_start(erase_bonds); //false //LeftLED_timers_start(); //Left Led timer All_Stop(); calibAccelGyro(); //start filter initDT(); pwm_change_frequency(500); do_play_buzzer(); //When start play buzzer // Enter main loop. for (;;) { pm_sec_params_set(NULL); //No Security parameters idle_state_handle(); //if no data sleep mode readAccelGyro(); calcDT(); calcAccelYPR(); calcGyroYPR(); calcFilteredYPR(); printf("%.1f", filtered_angle_x); //filter value printf(", "); printf("%.1f", filtered_angle_y); printf(", "); printf("%.1f", filtered_angle_z); printf("\n"); nrf_delay_ms(100); } }
Thank you.
//==================================================
I think I found a problem.
The value of dt in void calcDT() comes out as a fixed value as shown below, and suddenly becomes very large.
Can you tell me the cause of this problem??
dt : 0.153000 Gyro_xyz : 0.0, 0.0, 0.0 Filter : -0.3, 0.1, -8.5 dt : 0.152000 Gyro_xyz : 0.1, 0.0, -0.0 Filter : -0.3, 0.1, -8.5 dt : 4294836.500000 Gyro_xyz : 0.0, -0.0, 0.0 Filter : 195136.5, -31473.5, 19662.5 dt : 0.153000 Gyro_xyz : -0.0, -0.0, 0.0 Filter : 187331.0, -30214.6, 19662.5 dt : 0.153000 Gyro_xyz : -0.0, -0.0, -0.0 Filter : 179837.7, -29006.0, 19662.5 dt : 0.154000 Gyro_xyz : 0.0, -0.1, -0.0 Filter : 172644.2, -27845.7, 19662.5