學(xué)院真空實(shí)驗(yàn)室的熱偶真空計(jì)表頭損壞了,托人找了許多儀器儀表商店、公司,買不到型號相符的。前些天,王博找到我,讓我做一個(gè)數(shù)字式表頭取代之(原表頭乃是指針式的),已知基本數(shù)據(jù)如下: 熱偶內(nèi)阻:未知 表頭內(nèi)阻:要求在40R~~300R之間的某一值,但該值未知 儀器處于“測量”檔位時(shí),熱偶的輸出電壓可能通過了一個(gè)限流電阻加在了表頭上(阻值未知),通過表頭的電壓:0~~10mV; 電壓對應(yīng)于真空室的壓強(qiáng):260.00Pa~~0.10Pa(詳見數(shù)據(jù)表格) 儀器處于“加熱”檔位時(shí),表頭與一個(gè)未知阻值電阻并聯(lián),要求正確顯示干路總電流(范圍:20.0~40.0mA),以便對熱偶真空規(guī)管的工作電流進(jìn)行控制、校準(zhǔn),使之正常工作。由于外部并聯(lián)的小電阻阻值未知,通過表頭的電流亦不能事先確定(根據(jù)實(shí)際測試數(shù)據(jù)估算,應(yīng)不大于2mA) 熱偶真空計(jì)輸出電壓與電流關(guān)系: 原始表格: 電壓(mV) 壓強(qiáng)(Pa)
0.8 266.000
0.9 200.500
1.0 201.191
1.1 136.381
1.3 106.386
1.4 88.344
1.6 76.475
1.7 67.260
1.9 59.942
2.0 54.052
2.2 49.441
2.4 45.134
2.5 40.935
2.7 37.576
2.8 34.458
3.0 31.893
3.1 29.704
3.3 27.514
3.5 25.616
3.6 23.932
3.8 22.389
3.9 21.004
4.1 19.798
4.2 18.532
4.4 17.518
4.5 16.542
4.7 15.645
4.9 14.834
5.0 14.072
5.2 13.319
5.3 12.594
5.5 11.869
5.6 11.142
5.8 10.460
5.9 9.912
6.1 9.364
6.3 8.841
6.4 8.321
6.6 7.824
6.7 7.364
6.9 6.903
7.0 6.445
7.2 5.991
7.3 5.536
7.5 5.119
7.7 4.744
7.8 4.368
8.0 3.994
8.1 3.659
8.3 3.325
8.4 2.990
8.6 2.657
8.8 2.350
8.9 2.042
9.1 1.735
9.2 1.428
9.4 1.080
9.5 0.837
9.7 0.569
9.8 0.294
10.0 0.010
原始曲線:
首先,需要數(shù)據(jù)表格轉(zhuǎn)換成電壓以0.1mV步進(jìn)的新表格:使用origin75繪圖軟件,把原始數(shù)據(jù)擬合成一條電最相近的曲線,然后對曲線進(jìn)行重新取點(diǎn),得出以0.1mV電壓步進(jìn)的“電壓—壓強(qiáng)”數(shù)據(jù)表格。
新的數(shù)據(jù)表格: 電壓(mV) 壓強(qiáng)(Pa) 0.8 260.00
0.9 210.94
1.0 164.99
1.1 138.95
1.2 117.94
1.3 101.91
1.4 90.34
1.5 81.51
1.6 75.29
1.7 69.62
1.8 64.18
1.9 59.63
2.0 55.56
2.1 52.29
2.2 49.56
2.3 46.44
2.4 44
2.5 41.09
2.6 38.88
2.7 36.96
2.8 34.95
2.9 33.03
3.0 31.65
3.1 29.96
3.2 28.81
3.3 27.29
3.4 26.15
3.5 25
3.6 24.11
3.7 22.86
3.8 22.06
3.9 21.07
4.0 20.27
4.1 19.42
4.2 18.62
4.3 18.03
4.4 17.4
4.5 16.74
4.6 16.13
4.7 15.64
4.8 15.1
4.9 14.64
5.0 14.16
5.1 13.62
5.2 13.16
5.3 12.68
5.4 12.22
5.5 11.76
5.6 11.28
5.7 10.82
5.8 10.36
5.9 10.06
6.0 9.69
6.1 9.26
6.2 9.1
6.3 8.73
6.4 8.39
6.5 8.02
6.6 7.69
6.7 7.4
6.8 7.11
6.9 6.84
7.0 6.55
7.1 6.25
7.2 5.92
7.3 5.65
7.4 5.36
7.5 5.1
7.6 4.84
7.7 4.62
7.8 4.4
7.9 4.14
8.0 3.92
8.1 3.71
8.2 3.49
8.3 3.27
8.4 3.06
8.5 2.84
8.6 2.64
8.7 2.46
8.8 2.25
8.9 2.07
9.0 1.85
9.1 1.67
9.2 1.46
9.3 1.26
9.4 0.87
9.5 0.9
9.6 0.73
9.7 0.55
9.8 0.37
9.9 0.19
10.0 0.01
新的曲線:
硬件電路:
電路比較簡單:使用OP07進(jìn)行兩級同相放大,輸出電壓送至M8的AD0中進(jìn)行AD采樣(內(nèi)部2.56V參考電壓),經(jīng)M8處理之后,送到液晶進(jìn)行顯示。第一級同相輸入端通過一個(gè)1K的精調(diào)電阻并接到地,以便控制表頭的輸入電阻(內(nèi)阻)為0R~1000R的任意值。
軟件算法律: AD采樣的值經(jīng)M8內(nèi)部處理,轉(zhuǎn)換成電壓顯示數(shù)據(jù),一方面進(jìn)行顯示,一方面換算成對應(yīng)的壓強(qiáng)與電流數(shù)據(jù),分別進(jìn)行顯示。值得一提的是,電流與電壓之間必然具有線性關(guān)系,表現(xiàn)為具有一個(gè)等效電阻R=V/I,由于R的值未知,可能在0.00~600.00R之間,應(yīng)此另外設(shè)置按鍵控制R的值在0.00~600.00之間,當(dāng)然,設(shè)置的值必須存于M8內(nèi)部非易失性存儲器EEPROM中,以便永久保存。 由于M8引IO引腳較少,只設(shè)置兩個(gè)控制鍵以節(jié)省IO口。兩個(gè)控制鍵,一個(gè)加,一個(gè)減,完全可以實(shí)現(xiàn)控制。為了使提高控制速度,每個(gè)控鍵均具有長按、短按、連發(fā)功能。短按一次,加0.01或減0.01;長按(長于1s屬于),則每隔300ms加1或減1。 另外,為了減少運(yùn)算量,幾乎所有的小數(shù)運(yùn)算皆代以整數(shù)運(yùn)算進(jìn)行。例如,100.72-50.61,在程序中表示為10072-5061,運(yùn)算結(jié)果為5011,最終顯示時(shí),先顯示5011/100(整數(shù)部分),再顯示“.”(打小數(shù)點(diǎn)),最后顯示5011%100(小數(shù)部分),顯示實(shí)際效果為:50.11,與原始運(yùn)算結(jié)果一致。這種顯示方式顯然稍復(fù)雜一些,但由于不使用浮點(diǎn)運(yùn)算,大大減少了程序代碼及運(yùn)算時(shí)間,提高了程序效率。 本設(shè)計(jì)的濾波設(shè)計(jì)頗有特點(diǎn)(主要是指軟件濾波)。除硬件上注重退耦濾波之外,在軟件上設(shè)置采樣頻率為50HZ(也可以是100HZ、200HZ等),這樣可以去除市電工頻工擾,使顯示相當(dāng)?shù)姆(wěn)定。測試7.4mV電壓,若以30Hz、48Hz、60Hz等與50不成整倍數(shù)關(guān)系的采樣頻率,顯示電壓將在7.2mV~7.6mV之間隨機(jī)跳動;而若以25、50Hz、100Hz進(jìn)行采樣,則顯示將穩(wěn)定在7.2mV,連續(xù)觀測60s未出現(xiàn)波動,比數(shù)字萬用表的測量結(jié)果還穩(wěn)定。除此之外,為進(jìn)一步提高測量精度與穩(wěn)定性(主要是穩(wěn)定性),采取連續(xù)采樣50次求平均值的辦法。
這里指出一個(gè)屢試不爽的經(jīng)驗(yàn)結(jié)論:采樣測量系統(tǒng)中,使用過采樣技術(shù),具有微量紋波的信號比純凈的穩(wěn)定信號的測量更精確。例如,使用過采樣技術(shù),10的AD以128倍于信號紋波頻率的頻率采樣,理論上可以獲得最高17位的精度!曾有人使用AVR的10AD做電阻測量,做到了16位精度。故而,某些時(shí)候,為了用較低位數(shù)的AD獲得較高的采樣精度,甚至需要給被測信號人為加入某種頻率的紋波。令人震驚!——為什么呢?因?yàn),過采樣技術(shù)可以提高采樣精度——但對于純凈的直流信號無效!!
好了,不羅嗦了,下面發(fā)程序:
/***************************************************************************** 單 位:廣西民族大學(xué)物理與電子工程學(xué)院07物本班
文件名稱:ZD0-2熱偶真空計(jì)表頭.c
摘 要:ZD0-2熱偶真空計(jì)表頭主程序文件
當(dāng)前版本:V2.0
作 者:白 羽
完成日期:2010年10月5日 *****************************************************************************/
#define CRYSTAL 7.3728 //設(shè)置晶振頻率
#define LCD_RS P(PORTD,2) //設(shè)置液晶與M8的引腳連接
#define LCD_EN P(PORTD,3)
#define LCD_DN P(PORTD,H) #include<iom8v.h>
#include<eeprom.h>
#include<白羽AVR庫\LCD.h>
#include<白羽AVR庫\Timer.h> const UINT16 VPdata[93] = { //“電壓—壓強(qiáng)”表格
26000,21094,16499, /* 0.8--1.0 */
13895,11794,10191,9034,8151,7529,6962,6418,5963,5556, /* 1.1--2.0 */
5229 ,4956 ,4644 ,4400,4109,3888,3696,3495,3303,3165, /* 2.1--3.0 */
2996 ,2881 ,2729 ,2615,2500,2411,2286,2206,2107,2027, /* 3.1--4.0 */
1942 ,1862 ,1803 ,1740,1674,1613,1564,1510,1464,1416, /* 4.1--5.0 */
1362 ,1316 ,1268 ,1222,1176,1128,1082,1036,1006,969 , /* 5.1--6.0 */
926 ,910 ,873 ,839 ,802 ,769 ,740 ,711 ,684 ,655 , /* 6.1--7.0 */
625 ,592 ,565 ,536 ,510 ,484 ,462 ,440 ,414 ,392 , /* 7.1--8.0 */
371 ,349 ,327 ,306 ,284 ,264 ,246 ,225 ,207 ,185 , /* 8.1--9.0 */
167 ,146 ,126 ,87 ,90 ,73 ,55 ,37 ,19 ,1 /* 9.1--10.0*/
}; UINT8 flag = 0; //10ms中斷標(biāo)志
UINT8 count = 0; //10ms累加標(biāo)志
UINT16 AdData = 0; //電壓 (mV)*10
UINT32 AdSum = 0; //50次AD采樣和
UINT16 Rin = 1254; //輸入電阻*100
UINT16 KeyCount = 0; //控鍵按下時(shí)間 union EUINT16
{
UINT16 edata;
UINT8 echar[2];
}; void StartAdc(void); //啟動模數(shù)轉(zhuǎn)換
void RingBell(UINT8 Pascal); //低壓強(qiáng)時(shí)響鈴
void LcdShowVoltage(UINT16 AdData); //顯示電壓數(shù)據(jù)
void LcdShowCurrent(UINT16 AdData); //顯示電流數(shù)據(jù)
void LcdShowPascal(UINT8 AdData); //顯示壓強(qiáng)數(shù)據(jù)
UINT8 ScanfKey(void); //按鍵處理程序
void EEPROMWriteData(UINT16 data)
{
union EUINT16 eRin;
eRin.edata = data;
EEPROMWriteBytes(10,eRin.echar,2); //寫temp[3]到以10為首的eeprom中
}
UINT16 EEPROMReadData(void)
{
union EUINT16 eRin;
EEPROMReadBytes(10,eRin.echar,2); //寫temp[3]到以10為首的eeprom中
return eRin.edata;
}
void main(void)
{
LcdInit();
Rin = EEPROMReadData(); //讀取eeprom值
Timer1Period(2,21702); //10ms定時(shí)
StartAdc(); //啟動AD轉(zhuǎn)換
Enable_OC1A();
Enable_INTERRUPTS();
while(1)
{
if(flag == 1)
{
flag = 0;
count++;
AdSum += ADC;
StartAdc();
if(count == 50)
{
static UINT8 VIflag = 0;
count = 0;
AdData = AdSum/75.1; //50次的平均電壓值(mV)*10 [8--100]
AdSum = 0;
/**********************************/ //500mS
if(AdData < 120) //小于12.0mV,是電壓采樣信號
{
if(VIflag == 0)
{
VIflag = 1;
Disable_INTERRUPTS();
LcdInit();
Enable_INTERRUPTS();
}
LcdLocate(1,12);LcdShowString(" V ");
LcdLocate(2,12);LcdShowString("Heat");
LcdLocate(1,3); LcdShowVoltage(AdData); //顯示電壓
LcdLocate(2,2); LcdShowPascal(AdData); //顯示壓強(qiáng)
}
else //大于12.0mV,是電流采樣信號
{
if(VIflag == 1)
{
VIflag = 0;
Disable_INTERRUPTS();
LcdInit();
Enable_INTERRUPTS();
}
LcdLocate(1,12);LcdShowString(" I ");
LcdLocate(2,12);LcdShowString("Test");
LcdLocate(1,3); LcdShowVoltage(AdData); //顯示電壓
LcdLocate(2,3); LcdShowCurrent(AdData); //顯示電流
}
/**********************************/
}
/***************************************************/ //10mS
{
UINT8 key = ScanfKey();
if(key == BIT(2)) //左鍵
{
if(KeyCount == 2) //短按
{
Rin++;
}
else if((KeyCount > 50) && (KeyCount <= 60000)) //長按
{
if((KeyCount%15) == 0) //每500ms加100
{
Rin += 100;
}
}
EEPROMWriteData(Rin);
}
else if(key == BIT(0)) //右鍵
{
if(KeyCount == 2)
{
Rin--;
}
else if((KeyCount > 50) && (KeyCount <= 60000)) //長按
{
if((KeyCount%15) == 0) //每500ms加100
{
Rin -= 100;
}
}
EEPROMWriteData(Rin);
}
}
/***************************************************/
}
}
} //啟動AD轉(zhuǎn)換
void StartAdc(void)
{
ADMUX = BIT(6)|BIT(7) + 0; //通道0、內(nèi)部2.56V
ADCSRA = BIT(ADEN)|BIT(ADSC)|BIT(ADIF) + 6; //ADC使能、開始轉(zhuǎn)換、清標(biāo)志
} //顯示電壓(mV):兩位小數(shù)
void LcdShowVoltage(UINT16 AdData)
{
if(AdData >= 100)
{
LcdShowNumber(AdData/10,2);
}
else
{
LcdShowChar(' ');
LcdShowNumber(AdData/10,1);
}
LcdShowChar('.');
LcdShowNumber(AdData%10,1);
LcdShowString("0mV");
} //顯示電流(mA):兩位小數(shù)
void LcdShowCurrent(UINT16 AdData)
{
UINT32 Current = (UINT32)AdData * 10000 / Rin;
if(Current%10 >= 5)
{
Current += 10;
}
Current /= 10;
if(Current >= 10000)
{
LcdShowString(" I=****");
return;
}
if(Current >= 1000)
{
LcdShowNumber(Current/100,2);
}
else
{
LcdShowChar(' ');
LcdShowNumber(Current/100,1);
}
LcdShowChar('.');
LcdShowNumber(Current%100,2);
LcdShowString("mA ");
} //顯示壓強(qiáng)
void LcdShowPascal(UINT8 AdData)
{
UINT16 Pascal;
static UINT8 flag = 0;
//電壓數(shù)據(jù)變換成壓強(qiáng)數(shù)據(jù)
if(AdData < 8) //壓強(qiáng)很大(電壓小于0.8mV)
{
Pascal = 26001; //用一個(gè)很大的值表示超量程
}
else if(AdData <= 100) //正常壓強(qiáng)范圍
{
Pascal = *(VPdata + AdData - 8);
}
else //壓強(qiáng)很小(電壓大于10.0mV)
{
Pascal = 0; //用一個(gè)很小的值表示小壓強(qiáng)
}
//壓強(qiáng)數(shù)據(jù)小于10(即壓強(qiáng)小于0.1Pa)時(shí)提醒0.5秒
if(Pascal <= 10)
{
if(flag < 2)
{
DDRB |= BIT(1);
PORTB |= BIT(1);
flag++;
}
else
{
PORTB &= ~BIT(1);
flag = 2;
}
}
else
{
flag = 0;
}
//將壓強(qiáng)數(shù)據(jù)送至液晶進(jìn)行顯示
if(Pascal > 26000)
{
LcdShowString(" P=**** ");
return;
}
else if(Pascal >= 10000)
{
LcdShowNumber(Pascal/100,3);
}
else if(Pascal >= 1000)
{
LcdShowChar(' ');
LcdShowNumber(Pascal/100,2);
}
else
{
LcdShowString(" ");
LcdShowNumber(Pascal/100,1);
}
LcdShowChar('.');
LcdShowNumber(Pascal%100,2);
LcdShowString("Pa");
}
UINT8 ScanfKey(void)
{
UINT8 flag = 0;
static UINT8 NewKey = 0, OldKey = 0;
DDRB |= BIT(0)|BIT(2);
PORTB |= BIT(0)|BIT(2);
NewKey = PINB & (BIT(0) | BIT(2));
if(NewKey == OldKey) //兩次相等
{
if(NewKey == (BIT(0) | BIT(2))) //兩次相等但為空
{
flag = 0; //返回空
KeyCount = 0;
}
else //兩次相等且非空
{
flag = 1; //返回鍵值
KeyCount++;
}
}
OldKey = NewKey;
return (flag == 1) ? NewKey : 0;
}
#pragma interrupt_handler Timer1_10ms_ISR:iv_OC1A
void Timer1_10ms_ISR(void)
{
flag = 1;
}
/********************************END END END END *******************************************************/
通過設(shè)計(jì)這個(gè)表頭,我有兩點(diǎn)體會: 一、深切體會到設(shè)計(jì)一個(gè)完整理的系統(tǒng)與單獨(dú)完成一個(gè)簡單的功能,那是相差很遠(yuǎn)的兩種境界。后者通常簡單,由此很容易得出前者“也不難”的結(jié)論。而實(shí)際上,前者比后者難實(shí)現(xiàn)多了!完成前者,需要一整套的理論知識、一整套的工程思想、一整套處理困難的方法,一整套的實(shí)踐經(jīng)驗(yàn),還要相當(dāng)?shù)募?xì)心、考察現(xiàn)實(shí)中所有可能夠的情形并區(qū)別對待,要關(guān)注盡可能多的Bug(系統(tǒng)漏洞)并做好相應(yīng)的防范措施。系統(tǒng)還要做足硬件保護(hù),不僅要保護(hù)本身,還要保護(hù)與這銜接的外部系統(tǒng);當(dāng)兩者矛盾時(shí),還要懂得折中處理。 二、軟件編程上,強(qiáng)烈需要一個(gè)多任務(wù)操作系統(tǒng)。沒有這個(gè)系統(tǒng),多任務(wù)的程序編寫將大受限制。目前,技術(shù)領(lǐng)域中,AVR單片機(jī)尚未有成熟的操作系統(tǒng),我還是有必要實(shí)現(xiàn)一個(gè),哪怕有一點(diǎn)Bug。
|