数字与模拟信号的输入输出模块设计指南
基于XMC4300核心板,快速设计EtherCAT工业IO模块。
1、简介:
我们与feecat 进行了沟通及合作,了解到他有关于低成本、高可靠性I/O模块的设计经验,在此与大家分享。
由于大多数方案都是来源于互联网,我们会把原始参考链接都标在后面。
本文面向工业I/O设计者,提供24V PNP模式下标准的:
- 数字输入(2mA/CH)
- 数字输出(500mA/CH)
- 电压电流模拟输入(0-10v及0-20mA)
- 电压电流模拟输出(0-10v及0-20mA)
根据此经验,您可以在一周内使用立创EDA或KICAD创造您自己定制的I/O模块。
2、24V转5V电源设计
电源设计是重中之重,我们使用流行的德州仪器TPS5430做电源,并尽可能和官方的Layout一致,电感都尽量取最大。这个电路可以保证绝大多数情况下12-24v转5v无问题。
上图是我们其中一版设计,后来我们略微修改过,比如删掉R1(不好采购),增加几个电容规格位置和C2、C3一样、SS54替换为B340等,在多数应用下影响都不大,发热也极小。
3、数字输入:
工业常见的数字信号为PNP架构,即输出高低电平,驱动负载,负载的另一端接电源0V输出。我们这里单说输入,即端口上有24V为TRUE,没有24V为FALSE,一般切换点在12V左右。
输入部分参考了https://bbs.21ic.com/icview-2542850-1-2.html ,这是一个比较成熟且通用的输入方案。我将输入电容修改为22nf以和数字输出用一样的物料,并且滤波效果更好。实测输入1000Hz可读,持续电流约为2.2mA。
您可以看到,上图中用了PCF8575扩展I/O模块,我们利用它自带的弱上拉进行判断,对于输入的芯片只读取引脚状态即可,在上位程序中对状态取反。
除此之外,程序上建议做数字滤波以避免i2c总线、输入的偶发异常。一个简单好用的三次数字滤波程序如下:
//InputFilter
inputfilter_1[3]=inputfilter_1[2];
inputfilter_1[2]=inputfilter_1[1];
inputfilter_1[1]=inputfilter_1[0];
if (( inputfilter_1[3] == inputfilter_1[2] ) && ( inputfilter_1[2] == inputfilter_1[1] )){
input_1=inputfilter_1[3];
}
4、数字输出
相对于数字输入来说,数字输出要复杂得多,主要在选型及保护上。
我们尝试过TBD62783,它很便宜,但它不好做限流防短路措施,参考这个结论:
Remember that fuses are fire protections, not for silicon protection. (保险丝响应速度过慢)
即使限流保险丝更改为0.1A可以起到保护作用,我们仍然放弃该方案,转向智能高边开关。
典型的高边开关主要由ST和INFINEON生产,ST的产品相对著名一些,在倍福及西门子的输出模块中用的都是ST的VN808,因此我们也是用VN808作为输出芯片。除此之外还推荐ISO8200或VNI8200来做,但我们没有测试过。英飞凌的产品看着都很ok,但价格几乎都要高30%到50%。
IO端口仍然使用PCF8575扩展,所以默认高电平,拉低后光耦输出。
光耦之后的电路参考了ST的标准设计和西门子设计,报警信号我们没有使用。
实际测试中,单输出口一般使用100mA无问题,短路电流最大可达2A左右,随后前级自恢复保险丝动作。如果没有断开,自恢复保险丝会反复开关直到失效。
5、模拟输入
模拟信号处理比数字信号要复杂一些,但我们制作的IO是工业级,对精度和速率要求都不高。
这里我们使用TI的ADS1015作为模拟输入,它使用广泛,但程序比较繁琐。由于使用了四通道模拟开关,同一时间只能读取一个通道的结果。
此外,我们使用±6.144v量程模式,VCC接+5V(L78M05),输入极限是+5.3V,I2C需要用TXS0102之类器件做电平转换。实际算下来精度为0.006V,合10位多一点。
需注意两点,一是受电阻影响目前这个结构零飘较大,二是电流模式下功率超过了0603封装功率,但实测电阻无发热,老化测试也ok。
程序较为复杂,我们需要先对模拟开关做选择、切换到读模式、读取实际值。由于不能影响其它信号通讯,在一个单片机周期内只对一个通道做读取。具体4通道的程序如下:
//Analog Input
i2c_count=i2c_count+1;
if(i2c_count >= 4){
i2c_count = 0x0;
}
uint8_t aireg[]={0x01,0x40,0xE3};
uint8_t airead = 0x0;
uint8_t aidata[]={0x0,0x0};
switch (i2c_count){
case(0):aireg[1]=0x40;break;
case(1):aireg[1]=0x50;break;
case(2):aireg[1]=0x60;break;
case(3):aireg[1]=0x70;break;
}
I2C_MASTER_Transmit(&I2C_MASTER_1,true,0x90,&aireg[0],3,true);
i2c_wait();
I2C_MASTER_Transmit(&I2C_MASTER_1,true,0x90,&airead,1,true);
i2c_wait();
I2C_MASTER_Receive(&I2C_MASTER_1,true,0x91,&aidata[0],2,true,true);
i2c_wait();
uint16_t aitemp = 0;
aitemp=(uint16_t)aidata[0]<<4|aidata[1]>>4;
if (aitemp>1667){
aitemp=1667;
}
switch (i2c_count){
case(0):AI_1=(aitemp/1667.0)*65535;break;
case(1):AI_2=(aitemp/1667.0)*65535;break;
case(2):AI_3=(aitemp/1667.0)*65535;break;
case(3):AI_4=(aitemp/1667.0)*65535;break;
}
6、模拟输出
模拟输出参考了以下两个链接:
Universal analog output design and protection with LM358
Univerzální analogový výstup
我只把输入的阻容更换掉以取得更小的上升时间(实测10v约500us),并加入了输出的保护。此外,不建议用4-20mA等模式,因为零飘略微高了一点,4mA时零位大约在4.1mA。
JPx短接方式和原始原理图一致,一般推荐0-10V和0-20mA两种模式,分别对应短接2、4和3、4。
使用的芯片为MicroChip的MCP4728,它是4通道12位输出芯片,VDD接5V以获得0-5V基准输出。
程序方面,MCP4728程序很简单,只需要按照规定格式做数组,并修改几个固定位置即可。
//Analog Output
uint8_t senddata[] = {0x40,0x07,0xFF,0x42,0x07,0xFF,0x44,0x00,0xFF,0x46,0x00,0xFF};
uint16_t temp = 0;
temp=(AO_1/65535.0)*4095.0;
senddata[1]=temp>>8&0xFF;
senddata[2]=temp&0xFF;
temp=(AO_2/65535.0)*4095.0;
senddata[4]=temp>>8&0xFF;
senddata[5]=temp&0xFF;
temp=(AO_3/65535.0)*4095.0;
senddata[7]=temp>>8&0xFF;
senddata[8]=temp&0xFF;
temp=(AO_4/65535.0)*4095.0;
senddata[10]=temp>>8&0xFF;
senddata[11]=temp&0xFF;
I2C_MASTER_Transmit(&I2C_MASTER_1,true,0xC0,&senddata[0],12,true);
i2c_wait();
7、总结
上图是我们用PulseView抓的I2C记录,通讯速率400KHz,一个周期大约900us,即数字输出和模拟输出每900us更新一次、数字输入每2.7ms更新一次(数字滤波)、模拟输入每3.6ms更新一次(完整更新),可以满足用户需求。
上图是我们用PicoScope抓的I2C放大后的波形,边界清晰、通讯正常。
No Comments