数控直流电流源.docx
《数控直流电流源.docx》由会员分享,可在线阅读,更多相关《数控直流电流源.docx(20页珍藏版)》请在冰豆网上搜索。
![数控直流电流源.docx](https://file1.bdocx.com/fileroot1/2022-12/11/98c7f87f-586a-4878-9afd-0b981a871a7c/98c7f87f-586a-4878-9afd-0b981a871a7c1.gif)
数控直流电流源
数控直流电流源
摘要:
本设计由三个部分组成,键盘与显示,基于单片机的控制器,稳流电源。
以89C52为主控单元,以数模转换器DAC0832输出参考电压,以该参考电压控制电压转换模块LM350K的输出电压大小,设计实用,精度高。
Abstract:
Thisdesignisconsistedofthreeelements,Thecontrollerbasedonmicrointrollers89C52,Keyboardanddisplay,Stableelectriccurrentsource.The51synthesizedwithHD7279,achievetheaimtocontroltheoutputcurrent.
一、方案论证与比较
1、电源部分
(1)开关电源
采用单极开关电源,由220V交流整流后,经开关电源稳压输出。
该方案的优点是电路的效率较高,可以达到70%—80%,在电联接较好的情况下效率可以达到90%左右。
但是此方案产生的直流纹波和干扰较大,而且开关电源结构复杂,在以后的电路中很难加以控制,很可能造成设计的失败和技术参数的超标,鉴于时间和电路可靠性的考虑没有选择这套方案。
(2)线性电源
交流电压经桥式电路整流滤波输出,直接进入稳流电路。
这种方案的优点是,电路简单,容易实现,并且调试起来比较方便,只是功率损耗稍大,但是在这种小型非连续工作电源中这些功率损耗可以承受。
2、稳流部分
(1)内环反馈
在稳流部分加入一个负反馈,在DAC0832输出电压值之后与LM350K输出电压相比较,使其产生误差信号,运用负反馈原理降低误差,使输出性能较理想。
电路连接图如图1所示:
图1内环反馈
(2)双闭环控制
在内环反馈基础上再加上一个外部的负反馈。
如图2所示,即把输出后电压值经过A/D转换之后,再与D/A转换之前的电压值相比较,然后经过内环反馈,即经过了两次负反馈过程。
理论上讲这种方案比单独内环反馈要更精确,但我们在实际调试中已经调试通过了单片机软硬件及算法的设计,但经过比较,我们觉得在本系统没有必要再加上外环控制。
所以本设计选用了内环单独控制。
图2双闭环控制
二、主要元器件选择
1、HD7279A与8279
8279单个芯片就能实现键盘输入管理和LED显示控制两种功能。
但是8279的局限性是,对于LED显示没有驱动功能,需要外接显示驱动电器,增加了电路的复杂性;且占用并行接口口线较多。
本系统采用HD7279A代替8279,取得了很好的效果。
这种芯片不仅能实现8279的大部分功能,而且解决了它的不足。
HD7279A的主要功能:
同时驱动8位共阴式七段LED数码管(或64只独立的LED),提供了两种译码方式和消隐、闪烁、移位等多种控制功能,能管理多达64键的键盘矩阵,采用串行接口,节约单片机的I/O口线,特别适用于内嵌ROM的单片机不作总线扩展,仅使用片上的I/O接口的情况。
这样,既节省了布线空间,又简化了电路设计,使仪表的进一步微型化成为可能。
图3单片机与HD7279A的连接电路
2、LM317与LM350K
LM317在输出电压范围为1.2—37V时可以提供1.5A的电流,本产品要求的最大电流为2A,所以必须用两个LM317并联,但是由于并联后两个LM317工作电流负载不均衡,使电路稳定性降低。
鉴于以上原因,本设计采用了单片LM350K。
LM350K可以提供最大为5A电流,满足本设计要求,而且不存在两片芯片同时运行中所产生的不同步问题,故性能比较优良,且电路稳定性提高。
本主电路的原理是通过MCU控制D/A的输出电压大小,通过放大器放大,给电压模块作为最终输出的参考电压,真正的电压,电流还是由电压模块LM350K输出。
为了达到2A的输出电流,LM350K必须选用金属外壳封装,并且带稍大面积的散热片
3、DAC0832
为了实现对输出电流的数字控制,该设计选用了DAC0832。
DAC0832是一款常用的数模有两种连接模式,一种是电压输出模式,另外一种是电流输出模式,为了设计的方便,选用电压输出模式,引脚Iout1和Iout2之间接一参考电压。
它有三种工作方式:
不带缓冲工作方式,单缓冲工作方式,双缓冲工作方式。
电路采用双缓冲模式,由于/WR2=/XFER=0,DAC寄存处于直通状态。
又由于ILE=1,故只要在选中该片(/CS=0)的地址时,写入(/WR=0)数字量,则该数字信号立即传送到输入寄存器,并直通至DAC寄存器,经过短暂的建立时间,即可以获得相应的模拟电压,一旦写入操作结束,/WR1和/CS立即变为高电平,则写入的数据被输入寄存器锁存,直到再次写入刷新。
三、电路设计
1、键盘与显示部分
本部分选用HD7279A,该芯片单片就可以完成LED显示,实现键盘接口的全部功能。
通过键盘输入电流给定值(程序设定最小值20mA,最大值2000mA),运行程序后,液晶显示器前四位显示实际输出值(此功能通过ADC0809转换实现),后四位显示给定值。
本部分电路图如图4所示:
图4键盘显示部分电路
2、控制部分
采用常用的89C52芯片作为控制器,P0口和DAC0832的数据口直接相连,D/A的/CS接P2.3,/WR2和/WR2接P3.6接地,让D/A工作在双缓冲方式下。
通过调节可调电阻调节LM350K的输出电压为5.12V,所以在DAC的8脚输出电压的分辨率为5.12V/256=0.02V,也就是说DA输入数据端每增加1,电压增加0.02V。
D/A的电压输出端接放大器OP07CP的输入端,放大器的放大倍数为10,输出到电压模块LM350K的电压分辨率为0.02V×10=0.2V。
所以,当MCU输出数据增加1的时候,最终输出电压增加10mA,当调节电流的时候,可以以每次10mA的梯度增加或者降低电压。
电路图如下:
3、电源部分
该部分输入电流为220-240V,频率为50Hz,经过变压器E66X32-A15降压为15V,经过RS507L电路桥变为直流。
图中0.5Ω的两电阻用于电压采样,LM350K用于电压的调节与输出。
给定值经过DAC0832数模转换控制电流输出,后经HA17741I-V变换控制电压输出,后经OP07CP的电压比较反馈给LM350K进行调整。
电路图如下:
四、结果分析与调试
1、输出电流范围:
20mA—2000mA,并且特别设置了限制功能,键盘输入在20mA以下或者2000mA以上无法进行输入,保证了系统的安全,达到了本题目发挥部分的要求。
2、可以通过键盘来设置输出电流给定值,并且可以同时显示实测值,本系统中没有采用外闭环,为了验证我们已实现了该项功能,将A/D直接连在D/A上,显示数值正确。
在20mA—2000mA的范围内不会出现输出电流大于给定值的1%+10mA的情况,完全符合设计要求。
如下表:
次数
1
2
3
4
5
6
7
8
9
单位
给定值
2000
1800
1600
1200
800
400
200
50
20
mA
测量值
0.4979
0.4489
0.3995
0.2984
0.202
0.1002
0.0544
0.012
0.0048
V
电流值
1991.6
1795.6
1598
1193.6
808
400.8
217.6
49.2
19.2
mA
偏差值
8.4
4.4
2
6.4
-8
-0.8
-17.6
0.8
0.8
mA
给定值1%+10mA
30
28
26
22
18
14
12
10.5
10.2
mA
3、本设计具有非常突出的“+”,“-”步进功能,可以单独步进1mA,10mA,100mA,使步进调整过程更加快捷方便,而且在任何情况下不会超出设定值的上下限。
4、改变负载电阻,当输出电压在10V以内变化时,输出电流值的变化与输出电流值的大小比较如下,满足设计的要求,并且电流值变化很小,达到了很高的精度,下表为输出电流是1000mA时测量值:
次数
1
2
3
4
5
6
单位
电阻值
1
3
5
7
9
12
Ω
测量值
0.2484
0.2488
0.2489
0.2491
0.249
0.2496
V
电流值
0.9936
0.9952
0.9956
0.9964
0.998
0.9984
A
符合指标要求。
5、芯片的供电部分是基本的电源电路,没有必要自制,处于时间因素考虑,用成品电源。
恒流源部分是由可调式线性稳压块结合闭环控制而制成的,具有精度高,线性性能好等特点。
五、结语
该数控电压源经过时间实际使用说明,具有精度高,使用方便,硬件电路简单等特点。
如果要做成产品,还需要增加电流测量和显示部分,对这部分电路请参考相关资料。
本文主要对如何控制功率输出电压大小做出个例子,该电路对测量领域,以及马达调速方面都可以扩展使用。
附:
程序流程图
//include
#include
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#definevalve10
//sbitdat=P3^5;
//sbitkey=P3^2;
//sbitcls=P3^4;
//sbitclk=P3^3;
sbitdat=P1^4;
sbitkey=P1^5;
sbitcls=P1^6;
sbitclk=P1^7;
sbitDQ=P1^0;
sbitad_busy=P3^3;
ucharA[4]={0,2,0,0};
uchararrAD[4]={0,0,0,0};
ucharAIndex=0;
ucharxdata*da=0xA000;
ucharxdata*ad=0x9FF8;
ucharadin()
{
uchari=0;
*ad=0;
i=1;//fordelay
i=1;//fordelay
i=1;//fordelay
while(ad_busy==1)
{;}
return*ad;
}
voiddelay(intnum)
{
while(num--);
}
voiddelay50us(uintnum)
{
uinti,j;
for(i=0;ifor(j=0;j<6;j++)
;
}
voidsenddata(uchardata1)
{
uchartempdata,i;
tempdata=data1;
cls=0;
delay50us
(1);
for(i=0;i<8;i++)
{
dat=(tempdata&0x80)>>7;
clk=1;
tempdata=tempdata<<1;
delay
(1);
clk=0;
delay
(1);
}
dat=0;
}
ucharkeyscan()
{
uchari,tempdata=0;
if(key==0)
{
senddata(0x15);
dat=1;
delay50us
(1);
for(i=0;i<8;i++)
{
clk=1;
delay
(1);
tempdata=(tempdata<<1)|dat;
clk=0;
delay
(1);
}
dat=0;
returntempdata;
}
else
return0xFF;
}
//一些列的延时函数,都是在晶振频率为12MHz的情况下使用的
voiddelay1ms(uintnum)
{
uinti;
while((num--!
=0)&&(keyscan()==0xFF))
{
for(i=0;i<72;i++)
;
}
}
voidinitkey()
{
P1=0xFF;
delay1ms(25);
senddata(0xA4);
cls=1;
}
//setupatstartup
voidMission1()
{
ucharkey1=0;
uchartmpA[4]={0,0,0,0};
uinttmp=0;
A[0]=0;
A[1]=2;
A[2]=0;
A[3]=0;
AIndex=0;
//send0toDA
*da=10;
while(key1!
=0x05)
{
//show1D0200
senddata(0xCF);
senddata(0x01);//display"1"inthe8th
senddata(0xCE);
senddata(0x0D);//display"d"inthe7th
senddata(0x85);
senddata(0x0F);//display""inthe6th
senddata(0x84);
senddata(0x0F);//display""inthe5th
senddata(0x83);
senddata(A[3]);//displaythousandinthe4th
senddata(0x82);
senddata(A[2]);//displayhundredinthe3th
senddata(0x81);
senddata(A[1]);//displayteninthe2th
senddata(0x80);
senddata(A[0]);//displayoneinthe1th
senddata(0x88);
senddata(~(0x01<key1=keyscan();
if(key1!
=0xFF)
{
while(keyscan()!
=0xFF)
;
tmpA[0]=A[0];
tmpA[1]=A[1];
tmpA[2]=A[2];
tmpA[3]=A[3];
}
switch(key1)
{
case1:
//add1
if(tmpA[AIndex]==9)
{
tmpA[AIndex]=0;
}
else
tmpA[AIndex]=tmpA[AIndex]+1;
tmp=tmpA[3]*1000+tmpA[2]*100+tmpA[1]*10+tmpA[0];
if((tmp<=2000)&&(tmp>=20))
A[AIndex]=tmpA[AIndex];
break;
case2:
//minus1
if(tmpA[AIndex]==0)
{
tmpA[AIndex]=9;
}
else
tmpA[AIndex]=tmpA[AIndex]-1;
tmp=tmpA[3]*1000+tmpA[2]*100+tmpA[1]*10+tmpA[0];
if((tmp<=2000)&&(tmp>=20))
A[AIndex]=tmpA[AIndex];
break;
case3:
//moveleft
if(AIndex==3)
{
AIndex=0;
}
else
AIndex=AIndex+1;
break;
case4:
//moveright
if(AIndex==0)
{
AIndex=3;
}
else
AIndex=AIndex-1;
break;
}
}
}
voidMission2()
{
ucharkey1=0;
ucharcAD=0;
uintiAD=0;
uintiDA=0;
ucharcDA=0;
ucharcSendDA=0;
senddata(0x88);
senddata(0xFF);//stopflash
*da=1;//send10toDAwhentheprogramstartrun.
cSendDA=A[3]*100+A[2]*10+A[1]+((A[0]>=5)?
1:
0);
while(key1!
=0x05)
{
//getAD0andshowinthe8765LED
delay1ms(500);
cAD=adin();
//cAD=cDA;
//iAD=(int)((int)cAD/255*2000);
//去抖动
/*iAD=arrAD[3]*1000+arrAD[2]*100+arrAD[1]*10+arrAD[0];
if(abs(iAD-(int)cAD*10)>valve)
{
iAD=cAD*10;
arrAD[3]=(uchar)(iAD/1000);
iAD=iAD%1000;
arrAD[2]=(uchar)(iAD/100);
iAD=iAD%100;
arrAD[1]=(uchar)(iAD/10);
iAD=iAD%10;
arrAD[0]=(uchar)iAD;
}
*/
iAD=cAD*10;
arrAD[3]=(uchar)(iAD/1000);
iAD=iAD%1000;
arrAD[2]=(uchar)(iAD/100);
iAD=iAD%100;
arrAD[1]=(uchar)(iAD/10);
iAD=iAD%10;
arrAD[0]=(uchar)iAD;
//showADin8765LED
senddata(0x87);
senddata(arrAD[3]);//displaythousandinthe8th
senddata(0x86);
senddata(arrAD[2]);//displayhundredinthe7th
senddata(0x85);
senddata(arrAD[1]);//displayteninthe6th
senddata(0x84);
senddata(arrAD[0]);//displayoneinthe5th
senddata(0x83);
//showsettingin4321LED
senddata(A[3]);//displaythousandinthe4th
senddata(0x82);
senddata(A[2]);//displayhundredinthe3th
senddata(0x81);
senddata(A[1]);//displayteninthe2th
senddata(0x80);
senddata(A[0]);//displayoneinthe1th
if(cAD<(A[3]*100+A[2]*10+A[1]+(A[0]>=5?
1:
0)))
{
if(cSendDA<230)
cSendDA=cSendDA+1;
}
elseif(cAD>(A[3]*100+A[2]*10+A[1]+((A[0]>=5)?
1:
0)))
{
if(cSendDA>1)
cSendDA=cSendDA-1;
}
//sendtoDA
iDA=A[3]*1000+A[2]*100+A[1]*10+A[0];
//iDA=A[3]*100+A[2]*10+A[1];
//cDA=iDA/2000*255;
//cDA=A[3]*100+A[2]*10+A[1];
*da=cSendDA;
key1=keyscan();
if(key1!
=0xFF)
{
while(keyscan()!
=0xFF)
;
}
switch(key1)
{
case1:
//add1mA
if(iDA<=1999)
{
iDA=iDA+1;
A[3]=(uchar)(iDA/1000);
iDA=iDA%1000;
A[2]=(uchar)(iDA/100);
iDA=iDA%100;
A[1]=(uchar)(iDA/10);
iDA=iDA%10;
A[0]=iDA;
}
cSendDA=A[3]*100+A[2]*10+A[1]+((A[0]>=5)?
1:
0);
break;
case2:
//minus1mA
if(iDA>=21)
{
iDA=iDA-1;
A[3]=(uchar)(iDA/1000);
iDA=iDA%1000;
A[2]=(uchar)(iDA/100);
iDA=iDA%100;
A[1]=(uchar)(iDA/10);
iDA=iDA%10;
A[0]=iDA;
}
cSendDA=A[3]*100+A[2]*10+A[1]+((A[0]>=5)?
1:
0);
break;
case3:
//add100mA
if(iDA<=1900)
{
iDA=iDA+100;
A[3]=(uchar)(iDA/1000);
iDA=iDA%1000;
A[2]=(uchar)(iDA/100);
iDA=iDA%100;
A[1]=(uchar)(iDA/10);
iDA=iDA%10;
A[0]=iDA;
}
cSendDA=A[3]*100+A[2]*10+A[1]+((A[0]>=5)?
1:
0);
break;
case4:
//minus100mA
if(iDA>=120)
{
iDA=iDA-100;
A[3]=(uc