1. 4-20mA电流源背景概述
一般仪器仪表的信号电流都为4-20mA,指最小电流为4mA,最大电流为20mA 。
传输信号时候,要考虑到导线上也有电阻,如果用电压传输则会在导线的产生一定的压降,那接收端的信号就会产生一定的误差了~所以使用电流信号作为变送器的标准传输~
双绞线特性阻抗 是50欧姆左右,相隔1CM宽的0.2平方毫米的导线特性阻抗300欧姆左右,所以负载电阻选择50-300欧姆比较理想,为了AD转换方便,负载上的信号最大量程值一般5-10V比较合适,那么权衡所有,负载电阻250欧姆,电流20mA,负载压降5V比较满意。那么为什么选择4-20mA而不是0-20mA呢?为了减少接线的复杂性,传感器选择2线要比多线简单的多,2线既要传输信号,又要给传感器供电,所以设计者从中盗窃4mA电流给传感器放大电路供电,这样4-20mA的标准就确定了。
2. 如何利用ADI公司差动放大器AD8276和运放AD8603制作高精度、低成本电流源
图1是利用低功耗差动放大器AD8276和运算放大器AD8603构建的电流源,不仅经济、灵活、小巧,而且初始误差、温度漂移和功耗等性能也都非常出色。
图1 高精度电流源原理图
电流源电路如图1所示。基准电压VREF加在AD8276的同相输入端,该电压控制输出电流量 IO。 AD8276的反相输入端则直接接地。该器件内置四个40 kΩ激光调整电阻,分别与输入引脚、REF引脚和SENSE引脚相连。如果需要高电流输出,则AD8276的输出可用来驱动一个晶体管。
如果电阻完全匹配,R1上的电压即输入电压VREF,从而产生恒定的负载电流IO,它等于VREF/R1。
由于运算放大器AD8603具有低偏置电流(最大值为1 pA)和低失调电压(小于50 μV)特性,所以在电路的反馈环路中选用该器件。低偏置电流特性使它能与高阻抗负载接口,而不会引入明显的失调误差。低温度漂移特性(最大值为4.5 μV/°C)使它能在较宽的温度范围内工作,而且该放大器还具有低噪声以及轨到轨输入和输出特性。
为保证精度,R1的精度非常重要,其公差应达到0.1%或更佳,此误差可通过校准来消除。
3.应用实例
本文以电厂风门开度调节系统为例,由于工作环境恶劣,需要将开度数据经过检测后传输到控制室,这个过程需要长线传输,传输电流为4-20mA,采样电阻为250欧姆,也就是最后给控制器的电压是1V-5V的电压量。
为了将开度转化为电流,设计中利用ADUC7026单片机对开度进行检测,并用ADUC7026内置的DAC产生VREF(见图1),调节电流输出,R1选为100欧姆,0.1%精度。
软件程序如下,包括了开度距离测量,计算滤波,及DA输出
/********************************************************************* Author : Wang Yan Date : Aug. 2012 Hardware : Currently targetting ADuC7026. Description : DISTANCE MEASURING *********************************************************************/ #include#include /**********全局变量声明**************/ float w; float d,pred,distance; int m = 0; const static unsigned int TableS[8] = { 0x07FF0000, 0x0DA70000, 0x0FFF0000, 0x0DA70000, 0x07FF0000, 0x02570000, 0x00000000, 0x02570000 }; /********中断服务*******/ void IRQ_Handler() __irq { DAC0DAT = TableS[m] ; m++; m &= 0x07; T1CLRI = 0x01; } /**********ADC上电程序**************/ void ADCpoweron(int time) { ADCCON = 0x20; // power-on the ADC while (time >=0) // wait for ADC to be fully powered on time--; } /***********************交换两个数的值,供中值滤波用(整型)*******************************************/ void Swap(int *x,int *y) { int temp; temp = *x; *x = *y; *y = temp; } /***********************************中值滤波程序,是寻找具有奇数(odd)个数的采样序列的中值(整型)***************************/ int FindMedian(int n,int SortData[]) { // int i,j,k; // float sum=0.0, avg=0.0; int i,j; for(i = 0;i< n;i++) { for(j = n-1;j > i;j--) { if(SortData[j] < SortData[j-1]) { Swap(&SortData[j],&SortData[j-1]); } } } return SortData[(n-1)/2]; /* for(k =1;k< n-1;k++) { sum += SortData[k]; avg = sum/(n-2); } sum=0.0; return avg ; */ } /***********************交换两个数的值,供中值滤波用(浮点型)*******************************************/ void Swap1(float *x,float *y) { float temp; temp = *x; *x = *y; *y = temp; } /***********************************中值滤波程序,是寻找具有奇数(odd)个数的采样序列的中值(浮点型)***************************/ float FindMedian1(int n,float SortData[]) { // int i,j,k; int k; float sum=0.0, avg=0.0; /* for(i = 0;i< n;i++) { for(j = n-1;j > i;j--) { if(SortData[j] < SortData[j-1]) { Swap1(&SortData[j],&SortData[j-1]); } } } */ for(k =0;k< n;k++) { sum += SortData[k]; avg = sum/n; } sum=0.0; return avg; // return SortData[(n-1)/2]; } /*******测量正弦波发生电路产生的源信号均值,ADC1************/ float ReadSource() { float SourceValue; int i,SampleData[15]; ADCCP = 0x01; for(i = 0;i < 15;i++) { ADCCON = 0x7E3; while(!ADCSTA){} ADCCON &=0xF7F; SampleData[i] = (ADCDAT >> 16); } SourceValue = FindMedian(15,SampleData); return SourceValue; } /*******测量电感分压信号均值,ADC2************/ float ReadOutput() { float OutputValue; int i,SampleData[15]; ADCCP = 0x02; for(i = 0;i < 15;i++) { ADCCON = 0x7E3; while(!ADCSTA){} ADCCON &=0xF7F; SampleData[i] = (ADCDAT >> 16); } OutputValue = FindMedian(15,SampleData); return OutputValue; } /****************低通平缓滤波*******************/ float LowPassFilter2(float Factor,float NowData,float PreData) { return (1-Factor)*PreData + Factor * NowData; } /*******************供打印输出距离使用****************************/ int putchar(int ch) { /* Write character to Serial Port */ if (ch == '\n') { while(!(0x020==(COMSTA0 & 0x020))) {} COMTX = 0x0D; /* output CR */ } while(!(0x020==(COMSTA0 & 0x020))) {} return (COMTX = ch); } /********************延时函数*********************/ void delay(int length) { while(length>=0) length--; } /**************主函数****************/ int main (void) { float Vs=3000.0,Vo=3000.0; int j=0,DAC1value; float ComData[185]; //此处修改数据更新频率!!!!!!!! // PLLKEY1=0xAA; // PLLCON=0x01; // PLLKEY2=0x55; POWKEY1 = 0x01; POWCON = 0x00; POWKEY2 = 0xF4; // DAC configuration DAC0CON = 0x12; // DAC configuration DAC1CON = 0x12; // DAC configuration REFCON = 0x01; // range AREF/AGND // DAC1 is updated with falling edge of core clock DAC0DAT = 0x08000000; // start from midscale DAC1DAT = 655; // 400mV----4mA T1LD = 0x80; // Counter Value ,0x90=36khz,0x80=40khz; T1CON = 0xC0; // Enabled,Periodic,Binary and CLK/16 IRQEN = GP_TIMER_BIT; // Enable XIRQ0 and Timer1 IRQ ADCpoweron(20000); // power on ADC ADCCP = 0x02; // REFCON = 0x01; // connect internal 2.5V reference to Vref pin GP0CON = 0x010100000; // enable ECLK output on P0.7, and ADCbusy on P0.5 // GP4DAT = 0x04000000; // P4.2 configured as an output. LED is turned on GP1CON = 0x011; // Setup tx & rx pins on P1.0 and P1.1 // Setting up UART at 9600 (CD=0) COMCON0 = 0x80; // Setting DLAB COMDIV0 = 0x88; // COMDIV1 = 0x00; COMCON0 = 0x07; // Clearing DLAB while(1) { // t = ADCRead(); // w = t/100.0; // d = 0.0657351*w*w*w*w*w - 9.1878362*w*w*w*w + 513.6387866*w*w*w - 14355.5936574*w*w + 200581.1607954*w -1120847.94507; // d = 0.1698214*w*w*w*w - 18.8880471*w*w*w + 787.933324*w*w - 14608.094629*w + 101539.6810149-0.2; GP4DAT = 0x02000000; for(j = 0;j < 185;j++) { Vs = ReadSource(); Vo = ReadOutput(); w = (Vs+0.000001)/(Vo+0.000001)*30.0; // ComData[j] = 0.4696771683*w*w*w*w - 51.9252290524*w*w*w + 2152.6956573411*w*w - 39667.9356070098*w + 274163.653; ComData[j] = 0.3813314*w*w*w*w - 42.2315498*w*w*w + 1754.0923438*w*w - 32387.8436677*w + 224332.59168; } d = FindMedian1(185,ComData); // distance= LowPassFilter2(0.5,d,pred); if(d<0.0) { d=0.0; } DAC1value=(int)(655.2+262.08*d); if(DAC1value>4095) { DAC1value=4095; } // DAC1DAT = DAC1value<<16; DAC1DAT = 0x2BC<<16; GP4DAT = 0x04000000; printf("%f\n",Vs); // printf("%f\n",d); } }
提供单通道高精度运放OK8551 零温漂 双通道OK8552 4通道高精密运放OK8554