4-20mA 可调的信号源制作 用于校验PLC/DCS设备 在设计上和芯片选用上,大家有什么好的
4-20mA 可调的信号源制作 用于校验PLC/DCS设备 在设计上和芯片选用上,大家有什么好的见意,在4-20mA电流输出,是采用单片机Pwm调节三极管还是用集成芯片输出电流,什么芯片好一点,谢谢 ! AD421,没什么说的 楼上说的很强大,电池的问题需要解决 产生毫伏信号,电压信号,电流信号,频率信号经模块开关切换,工业调试的确方便 运放就可以解决的!用集成芯片太贵 ,如果做个N路吃不消啊! 回复【4楼】wuliwb-----------------------------------------------------------------------
具体点,运放怎么使用啊?怎么控制调节电流大小? 回复【1楼】czzhouyun
-----------------------------------------------------------------------
有现成的图吗,发我看看 回复【2楼】electricit
-----------------------------------------------------------------------
电池我打算用锂电池,电压可能会用过24V,用升压芯片升上去,不知道功率问题怎么办,看市面上卖的手提式信号源,电池都能用很长时间 2楼的建议从成本来说很不划算,AD421太贵了,我记得原来用过是80元一片。做这种手持式信号源,关键就是电源,用电池要升压到24v,还要使用时间够长,我也在琢磨要做这发面的工作,正在做实验。 回复【8楼】linlh
-----------------------------------------------------------------------
我也正在打算做个这个,只是想自己用用,因为卖的手持信号发生器都在1000以上,不需要太复杂,主要是4-20ma电流输出,要是可以的话,可以做电阻输出,电压输出 很久了才看到這帖子,根據我的經驗,AD421是最好的,现在价格大约30元一片的样子,不需要调整,16bit的精度,用DA+运放也可以做,精度无法达到16bit,温漂也达不到,用运放顶多是达到类似12bit的精度,成本上做好了应该和AD421相当。 曾经给朋友做过一个调试PLC用的小东西,用M48的PWM生成0-20ma的,还有测量功能...挺好玩的
这是原理图 ourdev_605336A9NYUB.pdf(文件大小:18K) (原文件名:PLChelper原理图.pdf) 楼上可以参考一下程序么? 08年写的,现在看起来...需要理一下了
/*
PLC_test.c
receive form pc :addr , out_pin , out_ma1 , out_ma2 , check .
send to pc :addr , in_pin, in_ma ,in_vol , check .
PIN 状态使用字节的各个位表示,从低到高位表示 PIN1,PIN2,PIN3,PIN4
ma , vol 用实际数10倍的十进制表示,例如:12.1ma表示为 121
经实验测定250欧负载时,PWM值924对应输出20.0ma,以此作为计算标准。
BY: 12145A1@163.COM
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
//=================================================================================================
#define _NOP asm("nop")
#define TRUE 1
#define FALSE 0
#define _SET_BIT(x,b) ( (x) |= 1<<(b) )
#define _CLS_BIT(x,b) ( (x) &= ~( 1<<(b) ) )
//=================================================================================================
#define PWM_REF 914
#define PACK_LENGTH 5
#define PIN_IN_NUM 4
#define ME_ADDR 0X51
#define _IS_ADC_OK bit_is_clear(ADCSRA, ADSC)
#define _START_ADC _SET_BIT(ADCSRA, ADSC)
#define _TXD_H _SET_BIT(PORTD,PD1)
#define _TXD_L _CLS_BIT(PORTD,PD1)
#define _OUT_PIN1_H _SET_BIT(PORTC,PC5)
#define _OUT_PIN1_L _CLS_BIT(PORTC,PC5)
#define _OUT_PIN2_H _SET_BIT(PORTB,PB5)
#define _OUT_PIN2_L _CLS_BIT(PORTB,PB5)
#define _OUT_PIN3_H _SET_BIT(PORTB,PB3)
#define _OUT_PIN3_L _CLS_BIT(PORTB,PB3)
#define _OUT_PIN4_H _SET_BIT(PORTB,PB4)
#define _OUT_PIN4_L _CLS_BIT(PORTB,PB4)
#define _IS_PIN1_H bit_is_set(PINB,PB0)
#define _IS_PIN2_H bit_is_set(PIND,PD7)
#define _IS_PIN3_H bit_is_set(PIND,PD6)
#define _IS_PIN4_H bit_is_set(PIND,PD5)
#define ADDR 0
#define IN_PIN 1
#define IN_MA 2
#define IN_VOL 3
#define CHECK 4
//=================================================================================================
unsigned long sum_dat;
unsigned char num_dat;
unsigned char send_dat;
unsigned char receive_dat;
unsigned char time_10ms;
unsigned char receive_ok;
//=================================================================================================
ISR( USART_RX_vect ) // 接受中断
{
static unsigned char uart_length;
if(uart_length && !time_10ms)
{
uart_length = 0;
}
receive_dat = UDR0;
if(receive_dat == ME_ADDR)
{
uart_length++;
if(uart_length == PACK_LENGTH)
{
uart_length = 0;
receive_ok = TRUE;
}
}
time_10ms = 2; // 两次数据间隔允许时间
}
//=================================================================================================
ISR(USART_TX_vect ) // 发送中断
{
static unsigned char length;
length ++;
if(length < PACK_LENGTH)
{
UDR0 = send_dat;
}
else
{
length = 0;
}
}
//=================================================================================================
// 比较匹配A 产生定时中断10MS
ISR( TIMER0_COMPA_vect )
{
static unsigned char pin_delay;
unsigned char ss_pin;
unsigned char n;
/*static unsigned char ff;
ff++;
if(ff == 40)
{
_TXD_L;
}
else if(ff > 80)
{
ff = 0;
_TXD_H;
}
*/
//-----------------------------------------------
if(time_10ms)
{
time_10ms--;
}
//-----------------------------------------------
sei();
//-----------------------------------------------
ss_pin = 0;
if(_IS_PIN1_H) ss_pin |= 0x80;
ss_pin >>= 1;
if(_IS_PIN2_H) ss_pin |= 0x80;
ss_pin >>= 1;
if(_IS_PIN3_H) ss_pin |= 0x80;
ss_pin >>= 1;
if(_IS_PIN4_H) ss_pin |= 0x80;
ss_pin >>= 4;
for(n=0; n<PIN_IN_NUM; n++)
{
if((ss_pin >> n) & 0x01)
{
pin_delay++;
if(pin_delay > 3) // 防抖时间
{
_SET_BIT( send_dat, n );
}
}
else
{
pin_delay = 0;
_CLS_BIT( send_dat, n );
}
}
//-----------------------------------------------
}
//=================================================================================================
void refresh_out(void)
{
unsigned int long reg;
if(receive_dat & 1)
{
_OUT_PIN1_H;
}
else
{
_OUT_PIN1_L;
}
if(receive_dat & 2)
{
_OUT_PIN2_H;
}
else
{
_OUT_PIN2_L;
}
if(receive_dat & 4)
{
_OUT_PIN3_H;
}
else
{
_OUT_PIN3_L;
}
if(receive_dat & 8)
{
_OUT_PIN4_H;
}
else
{
_OUT_PIN4_L;
}
if(receive_dat > 200) // 200 即 20.0mA
{
receive_dat = 200;
}
reg = (unsigned long) receive_dat * PWM_REF / 200;
OCR1A = (unsigned int)reg;
if(receive_dat > 200)
{
receive_dat = 200;
}
reg = (unsigned long) receive_dat * PWM_REF / 200;
OCR1B = (unsigned int)reg;
}
//=================================================================================================
unsigned char check_dat(void)
{
//unsigned char sum;
/*sum = 0;
for(n=0; n<uart_length-1; n++)
{
sum += receive_dat;
}*/
//sum = receive_dat;
if(receive_dat == receive_dat)
{
return TRUE;
}
else
{
return FALSE;
}
}
//=================================================================================================
void init_devices(void)
{
cli();
PORTB = 0X01; // 0000 0001
DDRB= 0XFE; // 1111 1110
PORTC = 0XDC; // 1101 1100
DDRC= 0X20; // 0010 0000
PORTD = 0Xff; // 1111 1111
DDRD= 0X02; // 0000 0010
// ANA----------------------------------
ACSR = 0X80; // 禁止比较器
// ADC----------------------------------
ADMUX = 0X60; // 数据左对齐
ADCSRA = 0x96; // 1001 0110使能ADC,禁止中断(写1清零),11.0592/64=172.8KHZ
_START_ADC;
while(!_IS_ADC_OK); // 首次转换,初始AD
// PWM1----------------------------------
TCNT1 = 0;
OCR1A = (unsigned int) 40 * PWM_REF / 200; // 默认输出4.0mA
OCR1B = OCR1A;
TCCR1A = 0xa3; // 1010 0011匹配置位,10位pwm
TCCR1B = 0x0a; // 0000 10108分频
// timer0------------------------------
TCCR0A = 0x02; // 0000 0010CTC 模式
TCCR0B = 0x05; // 0000 01011024分频 11.0592/1024=92.6us
OCR0A = 108; // 定时 10000us / 92.6 = 108
TIMSK0 |= 1 << OCIE0A;// 开比较匹配A中断
TIFR0 |= 0X0E; // 0000 1110清零中断标志
// UART---------------------------------
UCSR0B = 0xD8; // 1101 1000允许中断,使能接受 和 发送
UCSR0C = 0x06; // 0000 01108 bit data
UBRR0H = 0x00; // 波特率高位
UBRR0L = 0x47; // 9600bps 波特率低位
UCSR0A = 0XE0; // 1110 0000
sei();
}
//=================================================================================================
int main(void)
{
init_devices();
_delay_ms(200);
send_dat = ME_ADDR;
send_dat = ME_ADDR;
UDR0 = send_dat;
_START_ADC;
while(1)
{
//-----------------------------------------------
if(_IS_ADC_OK)
{
sum_dat += ADCH;
num_dat ++;
if(num_dat == 8)
{
sum_dat /= num_dat;
if(ADMUX == 0X60)
{
ADMUX = 0X61; // 通道1
sum_dat = (sum_dat * 5 * 10000) / 255;
send_dat = (unsigned int)sum_dat / 250;// 换为mA
}
else
{
ADMUX = 0X60; // 通道0
sum_dat = (sum_dat * 2 * 5 * 10) / 255;
send_dat = (unsigned int)sum_dat;
}
sum_dat = 0;
num_dat = 0;
}
_START_ADC;
}
//-----------------------------------------------
if(receive_ok)
{
receive_ok = FALSE;
if( check_dat() )
{
refresh_out();
send_dat = ME_ADDR;
send_dat = ME_ADDR;
UDR0 = send_dat;
}
}
//-----------------------------------------------
}
//-----------------------------------------------
} 重新用 Editplus 的工具 “制表符' 换成 “空格”,要不发出来看得晕 11楼用的是外部电源适配器供电吧,没在你的原理图中看到关键的电池升压供电电路。做这个手持式信号源,难点和关键点就是续航能力强的电池升压供电这块。大家都出出主意,既然人家深圳胜利高和优利德都能做到,我想应该有办法的,就是我还没想到,嘻嘻。 楼主,现在进展怎么样了啊?我用的升压芯片是AP3012,价格也便宜不超过3块钱,电池用了3.6V/1500mAH容量的镍氢可充电电池,在输出20mA的情况下,只能工作1个半小时,离我的工作时间3-5小时以上还有差距啊。看来还得换电池,继续试验中。。。 还需要输入键盘、显示,要不你怎么设定输出的电流值? 回复【16楼】linlh
楼主,现在进展怎么样了啊?我用的升压芯片是ap3012,价格也便宜不超过3块钱,电池用了3.6v/1500mah容量的镍氢可充电电池,在输出20ma的情况下,只能工作1个半小时,离我的工作时间3-5小时以上还有差距啊。看来还得换电池,继续试验中。。。
-----------------------------------------------------------------------
有个不成熟的想法,你现在的差距就在于,电池直接DC/DC升压到24V,然后再线性恒流,当然绝大部分的能量都消耗在放大管上了。
是否可以24VDC降压的时候,采用PWM的方式,这样也许可行。
当然,可能你的单片机可能支持不住那么高的频率
假设按照500K,0.1%步进值的PWM的话,单片机的频率需要到500M,还不包括AD以及计算的时间。
这种方法,基本上就是数字电源的方式吧。
个人愚见 回复【16楼】linlh
-----------------------------------------------------------------------
最近工作一直挺忙,做这个东西只是业余时间在做,进展很慢。现在PCB加工好了,元器件已经焊上了,在调程序,用的是PIC单片机,AD421芯片,LCD1602液晶(感觉挺费电),电池用的是3.7V 2600mAh锂电池,USB方式充电,并管理充电,程序正在调试中,有用过的朋友有什么经验提前告诉我一下,以加快进度,谢谢 回复【18楼】lihuyong如风似雾
-----------------------------------------------------------------------
电池升压确实是一个大问题,我用34063升压,做实验时忘了关电源,开机了一天,结果电池的电能都被升压管子耗没了,做3.7V升压24V有什么好办法?要求一定要高效。 检测负载,无负载超过一定时间自动关闭休眠节能,以前用过校验仪,12864的液晶,充电一次可以用一天,当然不是一直在用,一段时间无负载关闭 高效DC-DC升压电路
http://cache.amobbs.com/bbs_upload782111/files_38/ourdev_632045YCA543.jpg
(原文件名:rc4192升压电路图.jpg) Mark 请问,如果要做多路的4~20mA信号发生器呢?
多用几个AD芯片肯定可以,但是如果要节约成本咋么弄啊? mark 刚做,TLV5614+AM462 学习了, 现场设备共阴的比较多 mark 我也正在做4-20mA发生器,基本上已经成功了
0-25mA,步进0.1mA,精度不高,够用就好
方案是:MCU模拟PWM+LM358+34063升压+LCD12232+RTC,稳定性有待测试
用4节电池供电
现在的问题是:电池供电的时间和外壳
哪位有手持外壳链接,帮推荐一下,最好能装4-5节5#电池 搞个XTR110电压到4~20MA即可,下载个手册自己看看吧!非常好用,价格也很贵。 mark mark mark mark
页:
[1]