| 通常,在測(cè)量220V或380V工頻電壓時(shí),并不要求非常高的精度,一般的控制系統(tǒng)中,能精確到1%就足夠了。在這里向大家介紹一種我設(shè)計(jì)的非常簡單的測(cè)量方法,實(shí)踐證明,該方法實(shí)用、可靠,成本低廉,完全能夠滿足一般監(jiān)控系統(tǒng)的要求。 硬件電路:僅用一個(gè)220V/6V-1W的普通電源變壓器,經(jīng)過全波整流,小電容濾波,濾除其高頻干擾諧波,然后電阻分壓成適合A/D轉(zhuǎn)換的帶有紋波的電壓。直接連接到A/D輸入腳。如果測(cè)量380V的電壓,將兩只220V的變壓器串聯(lián)使用即可。 軟件設(shè)計(jì): 1、先進(jìn)行一次A/D轉(zhuǎn)換,存入一個(gè)變量x中,作為參考值; 2、再進(jìn)行一次A/D轉(zhuǎn)換,與上次比較,如果小于x,說明正處于交流電壓的下降沿,存入 x中;繼續(xù)A/D轉(zhuǎn)換,至到大于前次的轉(zhuǎn)換值,說明已經(jīng)進(jìn)入了交流電壓的上升沿,存入x; 3、繼續(xù)A/D轉(zhuǎn)換,如果轉(zhuǎn)換結(jié)果大于x,存入x;直到轉(zhuǎn)換結(jié)果小于x,說明x中保存的就是交流電壓的最大值! 4、然后把x除以一個(gè)常數(shù),得出你想顯示出的值即可。完成一次測(cè)量。 這樣完成一次測(cè)量最長時(shí)間是10ms,最短時(shí)間只需三次A/D轉(zhuǎn)換時(shí)間。如果軟件還執(zhí)行其它操作,便轉(zhuǎn)入其它子程序,之后繼續(xù)1-4的步驟,將每次結(jié)果累加。 測(cè)量n次后,求算術(shù)平均值。也可以采取其它數(shù)字濾波的方法。 為避免測(cè)量0電壓程序進(jìn)入死循環(huán),可以設(shè)置一個(gè)A/D轉(zhuǎn)換次數(shù)計(jì)數(shù)器,轉(zhuǎn)換一定次數(shù)之后退出。 校準(zhǔn)電壓可以在分壓電阻中設(shè)置一個(gè)電位器,也可以軟件校準(zhǔn)。軟件校準(zhǔn)的方法:例如在380V點(diǎn)校準(zhǔn),把結(jié)果乘以380,再除以380,假如得382。那么,把除數(shù)變成382即可。 這樣測(cè)量交流電壓,在寬范圍內(nèi)的線性不是太好,主要原因是全波整流的二極管電壓降是一個(gè)常數(shù)(約1.4V)。但針對(duì)220V或380V的電壓測(cè)量來講,電壓波動(dòng)不可能超過30%,在此范圍內(nèi)的線性誤差還是可以接受的。我曾以一只0.5級(jí)的電壓表與采取該方法的測(cè)量顯示值相比較,基本一致。 附一段測(cè)量程序: //電壓測(cè)量程序 int mesure(void) { uchar m_cAdccount; //ADC轉(zhuǎn)換次數(shù) uint m_nAdcValue; //當(dāng)前ADC轉(zhuǎn)換值 uint m_nPreAdcValue; //前次ADC轉(zhuǎn)換值 // enum condition eX; //定義A口為輸入,A0無上拉電阻,A1~A7有上拉電阻 DDRA=0X00; PORTA=0XFE; //有關(guān)變量初始化 m_nAdcValue=0; m_nPreAdcValue=0; //內(nèi)部2.56V參考電壓,0通道 ADMUX=0Xc0; //使能ADC, 時(shí)鐘:ck/32 ADCSRA=_BV(ADEN)|_BV(ADPS2)|_BV(ADPS0); //開始第一次轉(zhuǎn)換 ADCSRA|=_BV(ADSC); //等待轉(zhuǎn)換結(jié)束 while(ADCSRA&_BV(ADSC)) ; //讀取第一次轉(zhuǎn)換值 m_nAdcValue=ADCL; m_nAdcValue|=(uint)(ADCH<<8); for(m_nPreAdcValue=m_nAdcValue,m_cAdccount=0; (m_nAdcValue<=m_nPreAdcValue)&&(m_cAdccount<100); m_cAdccount++) { m_nPreAdcValue=m_nAdcValue; ADCSRA|=_BV(ADSC); //等待轉(zhuǎn)換結(jié)束 while(ADCSRA&_BV(ADSC)) ; m_nAdcValue=ADCL; m_nAdcValue|=(uint)(ADCH<<8); } for(m_nPreAdcValue=m_nAdcValue,m_cAdccount=0; (m_nAdcValue>=m_nPreAdcValue)&&(m_cAdccount<100); m_cAdccount++) { m_nPreAdcValue=m_nAdcValue; ADCSRA|=_BV(ADSC); //等待轉(zhuǎn)換結(jié)束 while(ADCSRA&_BV(ADSC)) ; m_nAdcValue=ADCL; m_nAdcValue|=(uint)(ADCH<<8); } if(g_nBaseVoltage==100) m_nPreAdcValue=m_nPreAdcValue/4; else m_nPreAdcValue=m_nPreAdcValue/2; return(m_nPreAdcValue); } | 
|  |