概述
液位檢測(cè)在工業(yè)自動(dòng)化、環(huán)境監(jiān)測(cè)和消費(fèi)電子等領(lǐng)域中具有廣泛的應(yīng)用價(jià)值。隨著技術(shù)的進(jìn)步,基于飛行時(shí)間(Time-of-Flight, ToF)傳感器的液位檢測(cè)解決方案以其高精度、非接觸式測(cè)量能力成為了熱門選擇。本文將介紹如何使用 STMicroelectronics 的 VL53L4CD ToF 傳感器進(jìn)行高精度液位檢測(cè),并重點(diǎn)探討在不同液體和容器條件下如何通過(guò)非線性校正算法提升測(cè)量準(zhǔn)確性。文中還將分析實(shí)驗(yàn)測(cè)試結(jié)果,并總結(jié)液位檢測(cè)應(yīng)用中可能面臨的挑戰(zhàn)及解決方案。
最近在弄ST的課程,需要樣片的可以加群申請(qǐng):615061293 。
視頻教學(xué)
[https://www.bilibili.com/video/BV1gj1BY1Ewe/]
樣品申請(qǐng)
[https://www.wjx.top/vm/OhcKxJk.aspx#]
完整代碼下載
[https://download.csdn.net/download/qq_24312945/89853013]
硬件準(zhǔn)備
首先需要準(zhǔn)備一個(gè)開(kāi)發(fā)板,這里我準(zhǔn)備的是自己繪制的開(kāi)發(fā)板,需要的可以進(jìn)行申請(qǐng)。
STSW-IMG039
該液位監(jiān)測(cè)解決方案基于意法半導(dǎo)體渡越時(shí)間測(cè)距傳感器,可與VL53L4CD渡越時(shí)間高精度接近傳感器或具有寬視野的VL53L5CX渡越時(shí)間8x8多區(qū)測(cè)距傳感器配合使用。
采用FlightSense技術(shù)的創(chuàng)新型意法半導(dǎo)體解決方案支持用戶使用非機(jī)械傳感器來(lái)測(cè)量液體的液位,以降低銹蝕風(fēng)險(xiǎn)。意法半導(dǎo)體解決方案可以十分精準(zhǔn)地測(cè)量各種液體,包括透明的水和深色的燃料等等。
VL53L4CD適用于接近測(cè)量和短距離測(cè)量,可實(shí)現(xiàn)從僅僅1 mm到1300 mm的超精準(zhǔn)距離測(cè)量。新一代激光發(fā)射器具有18°FoV(視場(chǎng)),提高了環(huán)境光下的性能,其測(cè)距速度高達(dá)100 Hz。
容器特性
AN5851 文件的內(nèi)容,第二章主要講解了 ST 的建議,該章節(jié)分為兩個(gè)部分,討論了容器的屬性和反射率對(duì)測(cè)量精度的影響,并給出了相應(yīng)的優(yōu)化建議。
容器的尺寸和傳感器的視場(chǎng)角 (FoV):VL53L4CD 傳感器的視場(chǎng)角是錐形的(18°),因此,如果容器的直徑小于傳感器的視場(chǎng)角,測(cè)量信號(hào)可能會(huì)從容器的邊緣反射回來(lái),導(dǎo)致測(cè)量精度下降。為了避免這一問(wèn)題,建議使用直徑大于傳感器視場(chǎng)的容器。
傳感器與液體表面的距離:傳感器應(yīng)放置在液面最高點(diǎn)上方至少 30 毫米的位置,以避免水滴反彈或容器晃動(dòng)時(shí)造成的信號(hào)干擾,從而影響測(cè)量準(zhǔn)確性。
低反射率容器:建議使用底部低反射率的容器,因?yàn)楫?dāng)液面較低時(shí),如果容器底部反射信號(hào)過(guò)強(qiáng),可能會(huì)與從液面反射回來(lái)的信號(hào)混淆,導(dǎo)致測(cè)量錯(cuò)誤。
透明或高反射率容器的影響:透明或高反射率的容器底部容易導(dǎo)致測(cè)量信號(hào)混亂,尤其是在液面較低時(shí)。因此,低反射率的底部設(shè)計(jì)能夠減少信號(hào)干擾,提高測(cè)量精度。
包含必要的頭文件
/* USER CODE BEGIN Includes */
#include "vl53l4cd_api.h" // VL53L4CD 傳感器 API
#include "custom_ranging_sensor.h" // 自定義測(cè)距傳感器頭文件
/* USER CODE END Includes */
變量定義
/* USER CODE BEGIN 0 */
int status;// 存儲(chǔ)操作狀態(tài)
volatile int IntCount;// 中斷計(jì)數(shù)器
uint8_t p_data_ready;// 數(shù)據(jù)準(zhǔn)備標(biāo)志
uint16_t dev, sensor_id;// 設(shè)備 ID 和傳感器 ID
VL53L4CD_ResultsData_t results; /* Results data from VL53L4CD */
VL53L4CD_Version_t sw_version; /* Driver version */
/* Below code has to be updated depending on customer setup parameters */
/* Start: Measure liquid level application*/
/* Consider X indicator levels and define a structure to store level, expected result and compensation value*/
// 液位標(biāo)志的數(shù)量,定義有 10 個(gè)級(jí)別
#define MAX_LABEL 10 /* Number of level indicators – To be updated depending on the number of levels in the OffGainVal.csv file */
typedef struct ogalgo_data
{
uint8_t level ;// 液位級(jí)別
uint16_t expected_res;// 預(yù)期測(cè)量結(jié)果
uint16_t og_val;// 補(bǔ)償值
}ogalgo_data;
/* Design a lookup table with a structure of compensate value data received from GUI once characterization is done*/
/* First column : indicator level , Second column: Expected result , Third column: compensate value*/
/* Example of values given below - To be updated with values from the GUI*/
/* 使用測(cè)量補(bǔ)償數(shù)據(jù)初始化查找表 */
ogalgo_data ogalgo_data_inst[MAX_LABEL]={
{ 9, 21, 4 },
{ 8, 42, 4 },
{ 7, 63, 2 },
{ 6, 84, 1 },
{ 5, 105, 5 },
{ 4, 126, 14 },
{ 3, 147, 25 },
{ 2, 168, 30 },
{ 1, 189, 20 },
};
/* Ranging 函數(shù)的原型聲明 */
int Ranging(Dev_t dev,uint16_t *ouputranging);
/* 開(kāi)啟算法標(biāo)志 */
uint8_t algo_enable=1; /* algo_enable=1 to apply the lookup table - algo_enable=0 to not apply */
uint16_t totaldistance=270; /* 傳感器到容器底部的高度,單位為毫米 */
uint16_t meanranging=0;// 平均測(cè)距值
uint16_t rangevalue_out=0;// 最終補(bǔ)償后的測(cè)距值
uint16_t invalid_range=999;// 無(wú)效測(cè)距值
void get_data_by_polling(Dev_t dev);// 數(shù)據(jù)輪詢獲取函數(shù)
/* USER CODE END 0 */
測(cè)距函數(shù) Ranging()
該函數(shù)執(zhí)行 10 次測(cè)距操作并計(jì)算平均值,確保測(cè)量結(jié)果的穩(wěn)定性。
/* Ranging 函數(shù) - 獲取測(cè)量數(shù)據(jù)并計(jì)算平均值 */
int Ranging(Dev_t dev,uint16_t *ouputranging)
{
uint8_t cnt=0;uint16_t mean_distance=0;uint16_t meanranging=0;
/* 進(jìn)行 10 次測(cè)量,取平均值 */
for (cnt = 0; cnt < 10;)
{
status = VL53L4CD_CheckForDataReady(dev, &p_data_ready);
// printf("status11=%d,data_ready=%dn",status,p_data_ready);
HAL_Delay(3);
if (p_data_ready)
{
VL53L4CD_ClearInterrupt(dev);
VL53L4CD_GetResult(dev, &results);
if(results.range_status ==0)
{
mean_distance+=results.distance_mm;
cnt++;
HAL_Delay(3);
}
}
}
// printf("cnt=%dn",cnt);
meanranging=mean_distance/10;// 計(jì)算平均值
*ouputranging =meanranging;
return status;
}
液位誤差補(bǔ)償函數(shù) Liquidlevelmeasureerrorcomponsate()
/* 液位測(cè)量誤差補(bǔ)償函數(shù) */
void Liquidlevelmeasureerrorcomponsate(uint16_t rangevalue,uint16_t *rangevalue_out)
{
uint16_t pos=0;
uint16_t i=0; uint16_t value;
for (i=0;i< MAX_LABEL;i++)
{
if (rangevalue < totaldistance+5) //5 buffer
{
if (rangevalue < ogalgo_data_inst[i].expected_res)
{
//Check first
if (i >0)
{
value = (ogalgo_data_inst[i].expected_res + ogalgo_data_inst[i-1].expected_res)/2;
}
else
value = ogalgo_data_inst[i].expected_res;
if(rangevalue <= value)
{
/* First position */
if (i ==0 )
{
pos=1;
break;
}
pos=1+(i-1); // adding one bcz position starts from 1
break;
}
else
{
pos=1+i;
break;
}
}
else
{
if (rangevalue > totaldistance+5)
pos=99;
else
pos=6; // Need to find which one is max OG value or store it directly here
}
}
else
pos=99;
}
/* 根據(jù)位置補(bǔ)償測(cè)量值 *//
switch(pos)
{
case 1:
*rangevalue_out=rangevalue + ogalgo_data_inst[pos].og_val; // Category Underranging,
break;
case 2:
*rangevalue_out=rangevalue + ogalgo_data_inst[pos].og_val; // Category Underranging, 30mm average b/w C3&C2
break;
case 3:
*rangevalue_out=rangevalue + ogalgo_data_inst[pos].og_val; // Category Underranging, 25mm average b/w C4&C3
break;
case 4:
*rangevalue_out=rangevalue + ogalgo_data_inst[pos].og_val; // Category Underranging, 12mm average b/w C2&C2
break;
case 5:
*rangevalue_out=rangevalue - ogalgo_data_inst[pos].og_val; // Category Overranging, 4mm average b/w C2&C2
break;
case 6:
*rangevalue_out=(uint16_t)(rangevalue - ogalgo_data_inst[pos].og_val); // Category Overranging,
break;
case 7:
*rangevalue_out=(uint16_t)(rangevalue - ogalgo_data_inst[pos].og_val); //Category Overranging,
break;
case 8:
*rangevalue_out=(uint16_t)(rangevalue - ogalgo_data_inst[pos].og_val); // Category Overranging,
break;
case 9:
*rangevalue_out=(uint16_t)(rangevalue - ogalgo_data_inst[pos].og_val); // Category Overranging,
break;
default:
printf("Valid water level not foundn");
}
}
/* End:Measure liquid level application */
數(shù)據(jù)輪詢函數(shù) get_data_by_polling()
該函數(shù)不斷輪詢 VL53L4CD 傳感器的數(shù)據(jù),計(jì)算平均測(cè)距值并輸出補(bǔ)償后的液位數(shù)據(jù)。
/* 通過(guò)輪詢獲取數(shù)據(jù) */
void get_data_by_polling(Dev_t dev){
do
{
/* Liquid level Measure application */
status=Ranging(dev,&meanranging);
if (!status)
{
if (algo_enable == 1)
{
Liquidlevelmeasureerrorcomponsate(meanranging,&rangevalue_out);
//printf("rg=%d %dn",meanranging, rangevalue_out);
if (rangevalue_out >0)
printf("Liquid level is = %d mmn",rangevalue_out);
else
printf("Invalid range is = %d mmn",invalid_range);
}
else
printf("Mean ranging is = %d mmn",meanranging);
}
}
while(1);
}
演示
水瓶大概19cm左右,當(dāng)只剩下一點(diǎn)水時(shí)。
加水到7cm左右。
加水到11cm左右。
加水到14左右。
審核編輯 黃宇
-
液位檢測(cè)
+關(guān)注
關(guān)注
0文章
47瀏覽量
9420 -
TOF
+關(guān)注
關(guān)注
9文章
482瀏覽量
36331
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論