Re: 使用ADC時配合FVR的問題

作者 chrC475 於 2018年10月20日 14:44:40
一個星期了,先回個follow up...

LM35的輸出精確度倒不是只有整數這麼差...

經過多次測試後,我已將部分使用LM35的專案當中的LM358電路移除,變相就是MCU可以直接讀取LM35,並同時更新程式,配合FVR,節省了不少空間和執行時間之餘結果出來還不錯,準確度亦比更新前的高,但數值跳動幅度比在之前麵包板上測試的還是大一點。

而部分同樣有使用LM35配合LM358的,因為該MCU不是Enhanced mid-range(使用16F685),該固定參考電壓亦只有0.6V一個選項,但因為沒有打算更換MCU,LM358的電路仍得繼續使用。

因為程式碼冗長而且還在修改中,我寫流程代替。以下流程中R和Q為unsigned int全域變數,為數據收集器。

直接讀取LM35的Enhanced mid-range的作業流程如下:
1.先透過快速讀取AN輸入64次取得平均值,放入Q
2.連續讀取16次AN輸入,每讀取一次後加入到暫存器A(區域變數)
3.將這個暫存器A收集到的總數值除以16
4.將暫存器A的結果加到R
5.當R收集過64次之後,將除以64的結果加到Q,之後將R歸零(步驟2-4不斷重複)
6.每次Q有新的數值加入後都要除以2以取得最新平均值
7.將Q的結果顯示出來(重複步驟5-6)
步驟1的函數只執行一次,而步驟2的則會重複執行

經LM358讀取LM35的Mid-range作業流程:
1.先透過快速讀取AN輸入64次取得平均值,放入Q
2.讀取一次AN輸入,放到A
3.因為A並非每次都準確,如果A數值超過Q平均值+/-20的話,A就取+/-20後的值,否則不用更動
4.將數值加入到R
5.當R收集過64次之後,將除以64的結果加到Q,之後R歸零(重複步驟2-4)
6.每次Q有新的數值加入後都要除以2以取得最新平均值
7.將Q的結果顯示出來(重複步驟5-6)
步驟1的函數只執行一次,而步驟2的則會重複執行

步驟3的偽代碼:

UB
=Q+20;
LB=Q-20;

A=ADCread(LM35_CHN);
if(
A>UB){
  
A=UB;
}
else
if(
A<LB){
  
A=LB;
}
R+=A;


LM35的輸出經LM358後是放大了約5倍,在伏特計測量下是看到穩定的電壓,可是從MCU讀取到的數值來看就完全不是這一回事。以LM35輸出0.275V為例,經LM358後就是1.375V,但MCU經LM358讀取到的ADC值可以低至224,高至367,這些極大誤差的數值基本上就是完全沒有可靠性可言。在作業流程中第3步中,除了上述的方法,另一個考慮的方法就是直接取用Q的值代替。

程式碼更新前數據收集需求量為200,收集器要使用到long,但平均值沒有比收集64次的更準,而且使用的空間還很多,所以才有這個修改的動機。收集最多64次的話,就不需要用到long,int就夠(1023 x 64 = 65472),還可免去使用編譯器提供的32位元除法函數(375 words大小),而且使用2的指數做乘除更只需要移動位元的操作(除以16所需的空間比除以20的小)。

此外還有一些乘除法上取巧的地方,例如計算華氏:

T x 9
/5 + 32
= T x 1.8 + 32
= (2-0.2)T + 32
= 2T - T/5 + 32

來自: http://www.microchip.com.tw/newbb/viewtopic.php?forum=1&topic_id=22422&post_id=78799