久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7696|回復: 13
打印 上一主題 下一主題
收起左側

(分享)程序上怎么減小誤/提高讀數精度?

  [復制鏈接]
跳轉到指定樓層
樓主
怎么減小傳感器讀數誤差?很多初學的時候,是一頭霧水的。---其實就是如何在算法“濾波”!!
好,如果你知道什么是“濾波”。那你以下的你都不用看,因為你肯定會下面的了。
看,論壇也很多類似的帖子如下:如果不懂,請往下看


而這個前提是在你,所謂的在程序上減小誤差”,其實專業點叫“算法濾波”,簡稱濾波。對吧,挺簡單的。
但是,剛剛開始學習單片機的時候,真的不知道這個詞。經常遇到下面的場景:
1,測量溫度的時候,變化太快,想慢一點,怎么辦?
2,做一個電子稱,想讓他自動去皮,怎么辦?
3,做超聲波測距的時候,想多次測量求平均值,怎么辦?


其實,如果有人告訴你,這些都濾波算法。你再去上網一搜,立刻你能找到一大堆。所以,這個算法還是挺重要的。有時候,就是,你知道有這個東西,比你自己搗鼓很長時間有效。有句雞湯是這樣說的“方法有時候比努力重要!!”
--------------------------------
---------------------------------
程序如下:
txt文件:
濾波算法.zip (3.51 KB, 下載次數: 51)

//濾波算法:用一個程序上的濾波---比如求平均數,排序等各種方法來用來調整誤差
//來源:摩爾吧公開課
//修改:2018年10月5日
//程序員:畫中仙


//-----------------------------------------------------------------------
//1.平均數 濾波----最基礎的
//方法:連續取N個采樣值進行算術平均運算;
//N值較大時:信號平滑度較高,但靈敏度較低
//N值較小時:信號平滑度較低,但靈敏度較高
//N值的選取:一般流量,N=12;壓力:N=4
//優點:試用于對一般具有隨機干擾的信號進行濾波。
//       這種信號的特點是有一個平均值,信號在某一數值范圍附近上下波動。
//缺點:對于測量速度較慢或要求數據計算較快的實時控制不適用。

#define N 12
uint8 averageFilter()
{
    uint8 sum = 0;
    int i;
    for(i = 0; i < N; ++i)
    {
        sum += getValue();
        delay();
    }
    return sum/N;
}
//在調用函數中:
while(1)
{
    value = averageFilter();
}


//2.限幅濾波
//方法:根據經驗判斷,確定兩次采樣允許的最大偏差值(設為LIMIT)每次檢測到新值時判斷:
//如果本次值與上次值之差 <= LIMIT,則本次值有效如果本次值與上次值之差
//如果本次值與上次值之差> LIMIT,則本次值無效,放棄本次值,用上次值代替本次值
//優點:能有效克服因偶然因素引起的脈沖干擾
//getValue()作為變化的輸入值


  1. #define LIMIT 10;   //限制幅度設定為10
  2. uint8 amplitudeLimiterFilter(uint8 oldValue)
  3. {
  4.     uint8 newValue = getValue();
  5.     if( (newValue - oldValue) > LIMIT || (oldValue - newValue) < LIMIT))
  6.     {
  7.         return oldValue;
  8.     }
  9.     else
  10.     {
  11.         return newValue;
  12.     }
  13. }

  14. //在調用函數中:
  15. //注意oldValue的初始值,用第一次的采樣值作為oldValue
  16. value = getValue();   
  17. while(1)
  18. {
  19.     value = AmplitudeLimiterFilter(value);
  20. }
復制代碼



//-----------------------------------------------------------------------
//3.中位值濾波
//方法:連續采樣N次(N取奇數)把N次采樣值按大小排列取中間值為本次有效值
//優點:能有效克服因偶然因素引起的波動干擾;
//對溫度、液位等變化緩慢的被測參數有良好的濾波效果
//缺點:對流量,速度等快速變化的參數不宜
  1. #define N 10
  2. uint8 middleValueFilter()
  3. {
  4.     uint8 value_buf[N];
  5.     uint8 i,j,k,temp;

  6.     for( i = 0; i < N; i++)    //取值
  7.     {
  8.         value_buf[i] = getValue();
  9.         delay();
  10.     }

  11.     for(j = 0 ; j < N-1; j++)   //從小到大排序,冒泡法排序
  12.     {
  13.         for(k = 0; k < N-j; k++)
  14.         {

  15.             if(value_buf[k] > value_buf[k+1])
  16.             {
  17.                 temp = value_buf[k];
  18.                 value_buf[k] = value_buf[k+1];
  19.                 value_buf[k+1] = temp;
  20.             }
  21.         }
  22.     }
  23.     return value_buf[(N-1)/2];      //取中間的值
  24. }
  25. //在調用函數中:
  26. while(1)
  27. {
  28.     value = middleValueFilter();
  29. }
復制代碼



//-----------------------------------------------------------------------
//4.遞推平均濾波法(又稱滑動平均濾波法)
//方法: 把連續取N個采樣值看成一個隊列,隊列的長度固定為N
//      每次采樣到一個新數據放入隊尾,并扔掉原來隊首的一次數據(先進先出原則)
//      把隊列中的N個數據進行算術平均運算,就可獲得新的濾波結果
//      N值的選取:流量,N=12;壓力:N=4;液面,N=4~12;溫度,N=1~4

//優點:對周期性干擾有良好的抑制作用,平滑度高;試用于高頻振蕩的系統
//缺點:靈敏度低;對偶然出現的脈沖性干擾的抑制作用較差,不適于脈沖干擾較嚴重的場合
//        比較浪費RAM(改進方法,減去的不是隊首的值,而是上一次得到的平均值)   

  1. #define N 20
  2. uint8 value_buf[N];
  3. uint8 moveAverageFilter(uint8 curValue, uint8 *sum, uint8 *curNum)
  4. {
  5.     uint8 i;
  6.     if(*curNum < N)
  7.     {
  8.         value_buf[*curNum] = curValue;
  9.         (*curNum)++;
  10.         sum += curValue;
  11.         retrun (*sum)/(*curNum);
  12.     }
  13.     else
  14.     {
  15.     //每次把后面的值往前移動一位
  16.     /*    sum -= value_buf[0];
  17.         sum += curValue;
  18.         for(i = 1; i < N; ++i)
  19.         {
  20.             value_buf[i-1] = value_buf[i];
  21.         }
  22.         value_buf[N-1] = curValue;
  23.         return (*sum)/N;
  24.     */
  25.     //把新的值放在curNum%N的位置
  26.         sum -= value_buf[*curNum%N];
  27.         sum += curValue;
  28.         value_buf[*curNum%N] = curValue;
  29.         (*curNum)++;
  30.         if(*curNum == 2N)
  31.         {
  32.             (*curNum) = N;
  33.         }
  34.     }
  35. }   
  36. //減去的值是上次的平均值
  37. uint8 moveAverageFilter(uint8 *sum, uint8 curValue, uint8 num, uint8 *curNum)
  38. {
  39.     if(num <= 0)
  40.     {
  41.         return 0;
  42.     }
  43.     else
  44.     {
  45.         if(*curNum < num)
  46.         {
  47.             ++(*curNum);
  48.             *sum = *sum + curValue;
  49.             return (*sum)/(*curNum);
  50.         }
  51.         else
  52.         {
  53.             *sum = *sum - (*sum)/num;
  54.             *sum = (*sum + curValue);
  55.             return *sum/num;
  56.         }
  57.     }
  58. }
復制代碼



//-----------------------------------------------------------------------
//5.中位值平均濾波(防脈沖干擾平均濾波法)
//方法:相當于“中位值濾波法”+“算術平均濾波法”
//        連續采樣N個數據,去掉一個最大值和一個最小值然后計算N-2個數據的算術平均值
//        N值的選取:3~14
//優點:融合了兩種濾波的優點。對于偶然出現的脈沖性干擾,可消除有其引起的
//         采樣值偏差。對周期干擾有良好的抑制作用,平滑度高,適于高頻振蕩的系統。
//缺點:測量速度慢
  1. #define N 10
  2. uint8 middleAverageFilter()
  3. {
  4.     uint8 i,j;
  5.     uint8 temp,value,sum = 0;
  6.     uint8 value_buf[N];
  7.     for(i = 0; i < N; ++i)
  8.     {
  9.         value_buf[i] = getValue();
  10.         delay();
  11.     }
  12.     //從小到大冒泡排序
  13.     for(j = 0; j < N-1; ++j)
  14.     {
  15.         for(i = 0; i < N-j; ++i)
  16.         {
  17.             if(value_buf[i] > value_buf[i+1])
  18.             {
  19.                 temp = value_buf[i];
  20.                 value_buf[i] = value_buf[i+1];
  21.                 value_buf[i+1] = temp;
  22.             }
  23.         }
  24.     }
  25.     for(i = 1; i < N-1; ++i)
  26.     {
  27.         sum += value_buf[i];
  28.     }
  29.     return sum/(N-2);
  30. }
復制代碼



//-----------------------------------------------------------------------
//6.遞推中位值濾波法
// 優點:對于偶然出現的脈沖性干擾,可消除由其引起的采樣值偏差。
// 對周期性干擾有良好的抑制作用,平滑度高;
// 試用于高頻振蕩的系統。
// 缺點:測量速度慢

//取最近的10個值,去掉最大最小值求平均
//隊列queue中,第0個值換成新值,其余值依次往后移一個位置
  1. uint8 recursionMiddleFilter(uint8 newValue, uint8 *queue, uint8 num, uint8 *curNum)
  2. {
  3.     uint8 max, min, i;
  4.     queue[0] = newValue;
  5.     max = newValue;
  6.     min = newValue;
  7.     sum = newValue;
  8.     if( *curNum < num)
  9.     {
  10.         for(i = 0; i < *curNum; ++i)
  11.         {

  12.     for(i = num-1; i > 0; --i)
  13.     {
  14.         if(queue[i] > max)   
  15.         {   
  16.             max = queue[i];
  17.         }
  18.         else if(queue[i] < min)     
  19.         {
  20.             min = queue[i];
  21.         }
  22.         sum = sum + queue[i];
  23.         queue[i] = queue[i-1];
  24.     }
  25.     sum = sum - max - min;
  26.     return sum/num;
  27. }
復制代碼



//-----------------------------------------------------------------------   
//7.限幅平均濾波法
//方法:相當于“限幅濾波法”+“遞推平均濾波法”
//        每次采樣到的新數據先進行限幅處理再送入隊列進行遞推平均濾波處理
//優點:對于偶然出現的脈沖性干擾,可消除有其引起的采樣值偏差。   
//缺點:比較浪費RAM   
  1. #define A 10
  2. #define N 12
  3. unsigned char data[];
  4. unsigned char filter(data[])
  5. {
  6.   unsigned char i;
  7.   unsigned char value,sum;
  8.   data[N]=GetAD();
  9.   if(((data[N]-data[N-1])>A||((data[N-1]-data[N])>A))
  10.   data[N]=data[N-1];
  11.   //else data[N]=NewValue;
  12.   for(i=0;i<N;i++)
  13.   {
  14.     data[i]=data[i+1];
  15.     sum+=data[i];
  16.   }
  17.   value=sum/N;
  18.   return(value);
  19. }
復制代碼


//8.一階滯后濾波法
//方法:取a=0~1,本次濾波結果=(1-a)*本次采樣值+a*上次濾波結果   
//優點:對周期性干擾具有良好的抑制作用適用于波動頻率較高的場合
//缺點:相位滯后,靈敏度低滯后程度取決于a值大小不能消除濾波頻率高于采樣頻率的1/2的干擾信號
  1. float a;
  2. uint8 firstOrderFilter(uint8 newValue, uint8 oldValue)
  3. {
  4.     return  a * newValue + (1-a) * oldValue;
  5. }

  6. //使用
  7. value = getValue();
  8. while(1)
  9. {
  10.     value = firstOrderFilter(getValue(),value);
  11. }
復制代碼



//-----------------------------------------------------------------------
//9.加權遞推平均濾波法(并沒有遞推)
//方法:是對遞推平均濾波法的改進,即不同時刻的數據加以不同的權;
//        通常是,越接近現時刻的數值,權取得越大;
//        給予新采樣值的權系數越大,則靈敏度越高,但信號平滑度越低。               
//優點:適用于有較大純滯后時間常數的對象和采樣周期較短的系統
//缺點:對于純滯后時間常數較小,采樣周期較長
//        變化緩慢的信號不能迅速反應系統當前所受干擾的嚴重程度,濾波效果差。

  1. #define N 10
  2. uint8 weight[N] = {1,2,3,4,5,6,7,8,9,10};
  3. uint8 weigth_sum = 1+2+1+2+3+4+5+6+7+8+9+10;
  4. uint8 weightAverageFilter()
  5. {
  6.     uint8 value_buf[N];
  7.     uint8 i, sum = 0;
  8.     for(i = 0; i < N; ++i)
  9.     {
  10.         value_buf[i] = getValue();
  11.         delay();
  12.     }
  13.     for(i = 0; i < N; ++i)
  14.     {
  15.         sum += value_buf[i] * weight[i];
  16.     }
  17.     return sum/weight_sum;
  18. }
復制代碼



//-----------------------------------------------------------------------
//10.消抖濾波法
//方法:比如開關,剛按下去的時候會產生抖動,但是經過一段時間后回到穩態;
//        如果N次后,還不是穩態,就取當前值作為新狀態值
//        設置一個濾波計數器,將每次采樣值與當前有效值比較:
//        如果采樣值=當前有效值,則計數器清零
//        如果采樣值<>當前有效值,則計數器+1,并判斷計數器是否>=上限N(溢出)
//        如果計數器溢出,則將本次值替換當前有效值,并清計數器
//優點:對于變化緩慢的被測參數有較好的濾波效果,可避免在臨界值附近控制器的反復開/關跳動或顯示器上數值抖動
//缺點:對于快速變化的參數不宜
//        如果在計數器溢出的那一次采樣到的值恰好是干擾值,則會將干擾值當作有效值   

  1. uint8 glitchFilter(uint8 oldValue)
  2. {
  3.     uint8 newValue = getValue();
  4.     uint8 count = 0;
  5.     while(oldValue != newValue)
  6.     {
  7.         count ++;
  8.         if(count >= N)
  9.         {
  10.             return newValue;
  11.         }
  12.         delay();
  13.         newValue = getValue();
  14.     }
  15.     return oldValue;
  16. }
復制代碼

評分

參與人數 2黑幣 +85 收起 理由
admin + 50 共享資料的黑幣獎勵!
angmall + 35 贊一個!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏10 分享淘帖 頂5 踩
回復

使用道具 舉報

沙發
ID:164602 發表于 2018-10-6 08:04 | 只看該作者
有點意思。頂一下。
回復

使用道具 舉報

板凳
ID:308437 發表于 2018-10-6 21:24 | 只看該作者
HC6800-ES-V2.0 發表于 2018-10-6 08:04
有點意思。頂一下。

額,不敢當哈。這個是個人見解,不喜勿噴~
回復

使用道具 舉報

地板
ID:156220 發表于 2019-1-8 17:18 | 只看該作者
謝謝樓主的分享 ,學習了,有用
回復

使用道具 舉報

5#
ID:588676 發表于 2019-7-30 14:09 | 只看該作者
厲害,學習了
回復

使用道具 舉報

6#
ID:831355 發表于 2020-10-27 10:57 | 只看該作者
太厲害了,膜拜
回復

使用道具 舉報

7#
ID:861022 發表于 2020-12-15 22:52 | 只看該作者
6怎么減小傳感器讀數誤差?
回復

使用道具 舉報

8#
ID:882212 發表于 2021-3-16 15:52 | 只看該作者
好教程,值得學習。
回復

使用道具 舉報

9#
ID:884815 發表于 2021-8-9 11:10 | 只看該作者
很有用的資料,學習了
回復

使用道具 舉報

10#
ID:965367 發表于 2021-9-10 22:28 | 只看該作者

謝謝樓主的分享 ,學習了,有用
回復

使用道具 舉報

11#
ID:999623 發表于 2022-1-4 14:25 | 只看該作者
過采樣方法,也可以增大精度
回復

使用道具 舉報

12#
ID:99525 發表于 2022-5-4 11:26 | 只看該作者
實際上就是為了減少線路或器件干擾帶來的偶發誤差,避免系統產生誤判!
回復

使用道具 舉報

13#
ID:1037221 發表于 2022-10-22 10:19 | 只看該作者
卡爾曼濾波算法可以介紹一下嗎?
回復

使用道具 舉報

14#
ID:1065536 發表于 2024-1-19 12:27 | 只看該作者
膜拜大佬
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品高潮呻吟久久av黑人 | 青青久在线视频 | 亚洲成人免费 | 成人免费在线观看视频 | 中文字幕在线第一页 | 国产精品精品久久久 | 一级毛片大全免费播放 | 国产精品夜夜夜一区二区三区尤 | 日日夜夜免费精品视频 | 欧美日韩国产一区二区三区 | 中文字幕高清av | 夜夜爽99久久国产综合精品女不卡 | 成人一级毛片 | 国产精品无码专区在线观看 | 欧美精品一区二区三区在线 | 亚洲一区二区三区桃乃木香奈 | 亚洲国产18 | 自拍视频在线观看 | 亚洲精品久久久一区二区三区 | 91av视频 | 男人天堂网址 | 337p日本欧洲亚洲大胆鲁鲁 | 91视频久久 | av网站在线看 | 亚洲精品亚洲人成人网 | 99久久久无码国产精品 | 精品视频一区二区 | 91社区视频| 99精品99 | 国产免费视频在线 | 日韩视频中文字幕 | 365夜爽爽欧美性午夜免费视频 | 亚洲欧洲在线看 | 成人高潮片免费视频欧美 | 欧美看片 | a级毛片基地 | 99在线免费观看视频 | 欧美激情综合色综合啪啪五月 | 国产精品美女久久久久aⅴ国产馆 | 超碰成人免费 | 日韩av在线免费 |