概述
最近在弄ST和瑞薩RA的課程,需要樣片的可以加群申請:615061293 。
零偏是影響加速度計輸出精度的重要指標之一,零偏可分為靜態零偏和動態零偏 。靜態零偏也稱為固定零偏,通常經標定與補償減小靜態零偏。動態零偏是由于加速度計自身的缺陷或環境因素(如溫度、振動、電子干擾等)引起的,懸絲加速度計在運動過程中其精度會受到動態零偏的影響,因此在投入使用前要先對加速度計的動態零偏進行測試。
硬件準備
首先需要準備一個開發板,這里我準備的是自己繪制的開發板,需要的可以進行申請。 主控為STM32U073CC,加速度計為LIS2DUX12
視頻教學
[https://www.bilibili.com/video/BV17J4m1W7Fb/]
樣品申請
[https://www.wjx.top/vm/OhcKxJk.aspx#]
源碼下載
[https://download.csdn.net/download/qq_24312945/89197967]
六位置法的標定方案
本文在校準三軸加速度計時使用六位置校準法,該方法使用地球的重力力加速度在靜態下校準三軸加速度傳感器,具體的校準過程如下圖所示。具體校準過程如下:
- 將傳感器的Y軸垂直水平面向下;
- 以X軸為基準軸,繞其逆旋轉90°,使乙軸垂直水平面向上
- 以Y軸為基準軸,繞其逆旋轉90°,使X軸垂直水平面向下
- 以Y軸為基準軸,繞其逆時針旋轉90°使2軸垂直水平面向下
- 繞Y軸逆時針旋轉909、使X軸垂直水平面向上
- 繞Z軸順時針旋轉90°、使Y軸垂直水平面向上
在沒有精密設備的情況下。這種方法基本上是在試圖找到每個軸的偏移(zero-g offset)和靈敏度(scale factor)。這種方法通常稱為靜態校準方法,因為它不需要動態輸入,只需將設備置于靜態的已知方向即可。
旋轉加速度計以找到極值
將加速度計沿每個軸正向和反向對齊,使其盡可能地與地球重力向量對齊。在理想情況下,當某一軸完全與地球的重力向量對齊時,該軸應顯示約 ±1g 的讀數,而其他軸應顯示 0g。
記錄每個軸在這六個方向(X+, X-, Y+, Y-, Z+, Z-)的輸出,即每個軸的最大值和最小值。
在未校準情況下,讀出的數據會超過1g的數值,所以要進行加速度計校準。
計算偏移和靈敏度
偏移(Offset):可以通過計算每個軸最大值和最小值的平均值得到:
Offset=(Max value+Min value)/2
靈敏度(Scale factor):可以通過兩個極值之差與2g(因為從+1g到-1g的總變化是2g)的比例來計算:
Scale factor=(Max value-Min value)/2g
應用校準參數
一旦計算得到每個軸的偏移量和靈敏度,校準參數就可以應用到新的加速度計測量數據中以修正這些數據。修正后的加速度值由下列公式計算得出:
Calibrated value= (Raw value?Offset)/Scale Factor
這個步驟實質上是一個線性變換,它調整原始加速度讀數以反映真實的加速度。
這些算法步驟基于直接的數學操作,并不涉及復雜的統計算法或優化算法。這些方法足以處理大多數基本應用場景下的加速度計校準需求,尤其是在資源受限的嵌入式系統中。如果環境變化大或加速度計的非理想特性影響較大(如高溫、機械應力等),可能需要更復雜的算法來進行動態校準或更高級的誤差補償。
注意事項
- 確保在靜態環境中進行測試,避免任何震動或移動。
- 使用精確的水平儀確保加速度計的對齊。
- 可以通過多次測量和取平均值來增加校準的準確性。 這種校準方法相對簡單,適合大多數基本應用,但對于需要極高精度的應用,可能需要更復雜的校準技術和專業設備。
串口中斷
開啟串口中斷來接收數據。
要在主程序鐘開啟中斷接收。
HAL_UART_Receive_IT(&huart1, (uint8_t *)RxBuff, 1); //打開串口中斷接收
定義接收函數。
// 捕獲中斷回調函數,每次捕獲到信號就會進入這個回調函數
void HAL_UART_RxCpltCallback(UART_HandleTypeDef*UartHandle)
{
Rx_flag=RxBuff[0];
RxBuff[0]=0;
// printf("flag=%d",Rx_flag);
HAL_UART_Receive_IT(&huart1, (uint8_t *)RxBuff, 1); //每接收一個數據,就打開一次串口中斷接收,否則只會接收一個數據就停止接收
}
變量定義
data_accx_min, data_accx_max, data_accy_min, data_accy_max, data_accz_min, data_accz_max:這些變量存儲加速度計在X、Y、Z軸上的最小值和最大值。這些極值通常是通過在特定時間內收集加速度計數據,然后從這些數據中找出最小值和最大值得到的。
Offset_x, Offset_y, Offset_z:這些是各軸的偏移值,計算方法是各軸最大值和最小值的算術平均值。偏移值用于調整每個軸的零點位置,使其在沒有運動時接近零。
Scale_factor_x, Scale_factor_y, Scale_factor_z:這些是各軸的靈敏度系數,計算方法是各軸最大值和最小值的差除以2。這個系數用于調整每個軸的測量值,使其在已知加速度的情況下反映實際的物理加速度。
calibrated_x, calibrated_y, calibrated_z:這些變量用于存儲校準后的加速度值,校準的目的是確保加速度計輸出準確反映實際加速度。
校準參數計算函數 calculate_calibration_params,此函數執行以下操作:
計算偏移(Offset):通過取每個軸的最大值和最小值的平均值來計算偏移。這樣做是為了將未校準的加速度計讀數的中心調整到0點附近,以補償傳感器的系統偏差。
計算靈敏度(Scale factor):通過取每個軸的最大值和最小值之差的一半來計算靈敏度。這個值表示了在理想條件下,傳感器輸出從最小到最大應覆蓋的理想范圍(通常是±1g)。通過這種方式,您可以根據實際的傳感器響應調整加速度計的讀數。
float data_accx_min=0,data_accx_max=0;//加速度計x軸極值
float data_accy_min=0,data_accy_max=0;//加速度計y軸極值
float data_accz_min=0,data_accz_max=0;//加速度計z軸極值
float Offset_x=0.0f;//x偏移
float Scale_factor_x=0.0f;//x靈敏度
float Offset_y=0.0f;//y偏移
float Scale_factor_y=0.0f;//y靈敏度
float Offset_z=0.0f;//z偏移
float Scale_factor_z=0.0f;//z靈敏度
float calibrated_x=0.0f;//校準后加速度計x軸值
float calibrated_y=0.0f;//校準后加速度計y軸值
float calibrated_z=0.0f;//校準后加速度計z軸值
int acc_i=0;
uint8_t RxBuff[1]; //進入中斷接收數據的數組
int Rx_flag=0; //接受到數據標志
void calculate_calibration_params(void) {
Offset_x=(data_accx_max+data_accx_min)/2;
Offset_y=(data_accy_max+data_accy_min)/2;
Offset_z=(data_accz_max+data_accz_min)/2;
Scale_factor_x=(data_accx_max-data_accx_min)/2;
Scale_factor_y=(data_accy_max-data_accy_min)/2;
Scale_factor_z=(data_accz_max-data_accz_min)/2;
}
主程序流程
使用 lis2dux12_status_get 函數檢查新的加速度計數據是否已經準備好。如果status.drdy(數據就緒標志)為真,這意味著有新數據可讀。
通過調用 lis2dux12_xl_data_get 函數讀取加速度計數據。這些數據被存儲在 data_xl.mg 數組中,分別對應 X、Y、Z 軸的加速度值。
根據 Rx_flag 的值,更新對應軸的最小值或最大值。每次更新后,調用 calculate_calibration_params 函數重新計算校準參數。
Rx_flag == 1 和 Rx_flag == 2 分別更新 X 軸的最小和最大值。
Rx_flag == 3 和 Rx_flag == 4 分別更新 Y 軸的最小和最大值。
Rx_flag == 5 和 Rx_flag == 6 分別更新 Z 軸的最小和最大值。
使用更新后的校準參數(偏移和靈敏度)來校準讀取的加速度數據。校準公式為:
Calibrated value= 1000*(Raw value?Offset)/Scale Factor
這里乘以1000是為了將結果轉換為毫重力單位(mg),常用于顯示加速度計的讀數。
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* Read output only if new values are available */
lis2dux12_status_get(&dev_ctx, &status);
if (status.drdy) {
lis2dux12_xl_data_get(&dev_ctx, &md, &data_xl);
if(Rx_flag==1)//X軸min
{
data_accx_min=data_xl.mg[0];
Rx_flag=0;
calculate_calibration_params();
}
else if(Rx_flag==2)//X軸max
{
data_accx_max=data_xl.mg[0];
Rx_flag=0;
calculate_calibration_params();
}
else if(Rx_flag==3)//Y軸min
{
data_accy_min=data_xl.mg[1];
Rx_flag=0;
calculate_calibration_params();
}
else if(Rx_flag==4)//Y軸max
{
data_accy_max=data_xl.mg[1];
Rx_flag=0;
calculate_calibration_params();
}
else if(Rx_flag==5)//Y軸min
{
data_accz_min=data_xl.mg[2];
Rx_flag=0;
calculate_calibration_params();
}
else if(Rx_flag==6)//Y軸max
{
data_accz_max=data_xl.mg[2];
Rx_flag=0;
calculate_calibration_params();
}
calibrated_x=1000*(data_xl.mg[0]-Offset_x)/Scale_factor_x;
calibrated_y=1000*(data_xl.mg[1]-Offset_y)/Scale_factor_y;
calibrated_z=1000*(data_xl.mg[2]-Offset_z)/Scale_factor_z;
printf("min_x=%4.2f,max_x=%4.2lf,min_y=%4.2f,max_y=%4.2f,min_z=%4.2f,max_z=%4.2frn",
data_accx_min,data_accx_max,data_accy_min,data_accy_max,data_accz_min,data_accz_max);
printf("校準前acc[mg]:%4.2ft%4.2ft%4.2frn",
data_xl.mg[0], data_xl.mg[1], data_xl.mg[2]);
printf("校準后acc[mg]:%4.2ft%4.2ft%4.2frn",
calibrated_x, calibrated_y, calibrated_z);
HAL_Delay(10);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
串口發送定義
演示
審核編輯 黃宇
-
加速度計
+關注
關注
6文章
690瀏覽量
45670 -
開發板
+關注
關注
25文章
4704瀏覽量
95750 -
stm32cubemx
+關注
關注
5文章
278瀏覽量
14581
發布評論請先 登錄
相關推薦
評論