搜索
bottom↓
回复: 35

4-20mA 可调的信号源制作 用于校验PLC/DCS设备 在设计上和芯片选用上,大家有什么好的

[复制链接]

出0入0汤圆

发表于 2010-10-17 21:56:11 | 显示全部楼层 |阅读模式
4-20mA 可调的信号源制作 用于校验PLC/DCS设备 在设计上和芯片选用上,大家有什么好的见意,在4-20mA电流输出,是采用单片机Pwm调节三极管还是用集成芯片输出电流,什么芯片好一点,谢谢 !

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入84汤圆

发表于 2010-10-18 08:36:57 | 显示全部楼层
AD421,没什么说的

出0入4汤圆

发表于 2010-10-18 09:01:38 | 显示全部楼层
楼上说的很强大,电池的问题需要解决

出0入4汤圆

发表于 2010-10-18 09:02:56 | 显示全部楼层
产生毫伏信号,电压信号,电流信号,频率信号经模块开关切换,工业调试的确方便

出0入0汤圆

发表于 2010-10-18 09:04:20 | 显示全部楼层
运放就可以解决的!用集成芯片太贵 ,如果做个N路吃不消啊!

出0入0汤圆

 楼主| 发表于 2010-10-29 22:17:24 | 显示全部楼层
回复【4楼】wuliwb
-----------------------------------------------------------------------

具体点,运放怎么使用啊?怎么控制调节电流大小?

出0入0汤圆

 楼主| 发表于 2010-10-29 22:18:03 | 显示全部楼层
回复【1楼】czzhouyun
-----------------------------------------------------------------------

有现成的图吗,发我看看

出0入0汤圆

 楼主| 发表于 2010-10-29 22:19:47 | 显示全部楼层
回复【2楼】electricit
-----------------------------------------------------------------------

电池我打算用锂电池,电压可能会用过24V,用升压芯片升上去,不知道功率问题怎么办,看市面上卖的手提式信号源,电池都能用很长时间

出0入0汤圆

发表于 2010-12-17 17:38:24 | 显示全部楼层
2楼的建议从成本来说很不划算,AD421太贵了,我记得原来用过是80元一片。做这种手持式信号源,关键就是电源,用电池要升压到24v,还要使用时间够长,我也在琢磨要做这发面的工作,正在做实验。

出0入0汤圆

 楼主| 发表于 2010-12-18 10:18:02 | 显示全部楼层
回复【8楼】linlh
-----------------------------------------------------------------------

我也正在打算做个这个,只是想自己用用,因为卖的手持信号发生器都在1000以上,不需要太复杂,主要是4-20ma电流输出,要是可以的话,可以做电阻输出,电压输出

出0入84汤圆

发表于 2010-12-18 10:35:13 | 显示全部楼层
很久了才看到這帖子,根據我的經驗,AD421是最好的,现在价格大约30元一片的样子,不需要调整,16bit的精度,用DA+运放也可以做,精度无法达到16bit,温漂也达不到,用运放顶多是达到类似12bit的精度,成本上做好了应该和AD421相当。

出0入0汤圆

发表于 2010-12-18 11:00:53 | 显示全部楼层
曾经给朋友做过一个调试PLC用的小东西,用M48的PWM生成0-20ma的,还有测量功能...挺好玩的

这是原理图 ourdev_605336A9NYUB.pdf(文件大小:18K) (原文件名:PLChelper原理图.pdf)

出0入0汤圆

发表于 2010-12-18 13:06:56 | 显示全部楼层
楼上可以参考一下程序么?

出0入0汤圆

发表于 2010-12-18 14:30:02 | 显示全部楼层
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[PACK_LENGTH];
unsigned char   receive_dat[PACK_LENGTH];

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[uart_length] = UDR0;

        if(receive_dat[0] == 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[length];
        }
        else
        {
                length = 0;
        }
}

//=================================================================================================
// 比较匹配A 产生定时中断10MS
ISR( TIMER0_COMPA_vect )
{
        static unsigned char pin_delay[PIN_IN_NUM];
               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[n]++;
                        if(pin_delay[n] > 3)            // 防抖时间
                        {
                                _SET_BIT( send_dat[IN_PIN], n );
                        }
                }
                else
                {
                        pin_delay[n] = 0;
                        _CLS_BIT( send_dat[IN_PIN], n );
                }
        }
//-----------------------------------------------
}

//=================================================================================================
void refresh_out(void)
{
        unsigned int long reg;

        if(receive_dat[1] & 1)
        {
                _OUT_PIN1_H;
        }
        else
        {
                _OUT_PIN1_L;
        }

        if(receive_dat[1] & 2)
        {
                _OUT_PIN2_H;
        }
        else
        {
                _OUT_PIN2_L;
        }

        if(receive_dat[1] & 4)
        {
                _OUT_PIN3_H;
        }
        else
        {
                _OUT_PIN3_L;
        }

        if(receive_dat[1] & 8)
        {
                _OUT_PIN4_H;
        }
        else
        {
                _OUT_PIN4_L;
        }

        if(receive_dat[2] > 200)                        // 200 即 20.0mA
        {
                receive_dat[2] = 200;
        }

        reg = (unsigned long) receive_dat[2] * PWM_REF / 200;
        OCR1A = (unsigned int)reg;

        if(receive_dat[3] > 200)
        {
                receive_dat[3] = 200;
        }
        
        reg = (unsigned long) receive_dat[3] * 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[n];
        }*/
        //sum = receive_dat[0];

        if(receive_dat[0] == receive_dat[PACK_LENGTH-1])
        {
                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 1010  8分频

// timer0------------------------------
        TCCR0A = 0x02;          // 0000 0010  CTC 模式
        TCCR0B = 0x05;          // 0000 0101  1024分频 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 0110  8 bit data
        UBRR0H = 0x00;          //            波特率高位
        UBRR0L = 0x47;          // 9600bps    波特率低位

        UCSR0A = 0XE0;          // 1110 0000
        sei();

}

//=================================================================================================

int main(void)
{
        init_devices();

        _delay_ms(200);

        send_dat[0] = ME_ADDR;
        send_dat[4] = ME_ADDR;

        UDR0 = send_dat[0];

        _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[IN_MA] = (unsigned int)sum_dat / 250;  // 换为mA               
                                }
                                else
                                {
                                        ADMUX = 0X60;                                   // 通道0
                                        sum_dat = (sum_dat * 2 * 5 * 10) / 255;
                                        send_dat[IN_VOL] = (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[0] = ME_ADDR;
                                send_dat[4] = ME_ADDR;

                                UDR0 = send_dat[0];
                        }
                }
//-----------------------------------------------
        }
//-----------------------------------------------
}

出0入0汤圆

发表于 2010-12-18 14:33:59 | 显示全部楼层
重新用 Editplus 的工具 “制表符' 换成 “空格”,要不发出来看得晕

出0入0汤圆

发表于 2010-12-21 10:41:31 | 显示全部楼层
11楼用的是外部电源适配器供电吧,没在你的原理图中看到关键的电池升压供电电路。做这个手持式信号源,难点和关键点就是续航能力强的电池升压供电这块。大家都出出主意,既然人家深圳胜利高和优利德都能做到,我想应该有办法的,就是我还没想到,嘻嘻。

出0入0汤圆

发表于 2011-1-11 16:31:38 | 显示全部楼层
楼主,现在进展怎么样了啊?我用的升压芯片是AP3012,价格也便宜不超过3块钱,电池用了3.6V/1500mAH容量的镍氢可充电电池,在输出20mA的情况下,只能工作1个半小时,离我的工作时间3-5小时以上还有差距啊。看来还得换电池,继续试验中。。。

出0入0汤圆

发表于 2011-1-11 18:50:51 | 显示全部楼层
还需要输入键盘、显示,要不你怎么设定输出的电流值?

出0入0汤圆

发表于 2011-1-11 19:24:39 | 显示全部楼层
回复【16楼】linlh
楼主,现在进展怎么样了啊?我用的升压芯片是ap3012,价格也便宜不超过3块钱,电池用了3.6v/1500mah容量的镍氢可充电电池,在输出20ma的情况下,只能工作1个半小时,离我的工作时间3-5小时以上还有差距啊。看来还得换电池,继续试验中。。。
-----------------------------------------------------------------------

有个不成熟的想法,你现在的差距就在于,电池直接DC/DC升压到24V,然后再线性恒流,当然绝大部分的能量都消耗在放大管上了。

是否可以24VDC降压的时候,采用PWM的方式,这样也许可行。

当然,可能你的单片机可能支持不住那么高的频率

假设按照500K,0.1%步进值的PWM的话,单片机的频率需要到500M,还不包括AD以及计算的时间。

这种方法,基本上就是数字电源的方式吧。



个人愚见

出0入0汤圆

 楼主| 发表于 2011-1-22 21:55:09 | 显示全部楼层
回复【16楼】linlh  
-----------------------------------------------------------------------

最近工作一直挺忙,做这个东西只是业余时间在做,进展很慢。现在PCB加工好了,元器件已经焊上了,在调程序,用的是PIC单片机,AD421芯片,LCD1602液晶(感觉挺费电),电池用的是3.7V 2600mAh锂电池,USB方式充电,并管理充电,程序正在调试中,有用过的朋友有什么经验提前告诉我一下,以加快进度,谢谢

出0入0汤圆

 楼主| 发表于 2011-1-22 22:02:32 | 显示全部楼层
回复【18楼】lihuyong  如风似雾
-----------------------------------------------------------------------
电池升压确实是一个大问题,我用34063升压,做实验时忘了关电源,开机了一天,结果电池的电能都被升压管子耗没了,做3.7V升压24V有什么好办法?要求一定要高效。

出0入84汤圆

发表于 2011-1-22 23:59:16 | 显示全部楼层
检测负载,无负载超过一定时间自动关闭休眠节能,以前用过校验仪,12864的液晶,充电一次可以用一天,当然不是一直在用,一段时间无负载关闭

出0入0汤圆

发表于 2011-4-19 11:31:47 | 显示全部楼层
高效DC-DC升压电路

(原文件名:rc4192升压电路图.jpg)

出0入0汤圆

发表于 2011-4-19 11:50:29 | 显示全部楼层
Mark

出0入0汤圆

发表于 2011-4-19 12:30:37 | 显示全部楼层
请问,如果要做多路的4~20mA信号发生器呢?
多用几个AD芯片肯定可以,但是如果要节约成本咋么弄啊?

出0入0汤圆

发表于 2011-6-10 13:38:56 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-6-10 17:37:32 | 显示全部楼层
刚做,TLV5614+AM462

出0入0汤圆

发表于 2011-6-10 17:55:55 | 显示全部楼层
学习了,

出0入4汤圆

发表于 2011-7-25 22:06:05 | 显示全部楼层
现场设备共阴的比较多

出0入0汤圆

发表于 2011-11-12 16:01:22 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-18 00:31:43 | 显示全部楼层
我也正在做4-20mA发生器,基本上已经成功了
0-25mA,步进0.1mA,精度不高,够用就好
方案是:MCU模拟PWM+LM358+34063升压+LCD12232+RTC,稳定性有待测试
用4节电池供电
现在的问题是:电池供电的时间和外壳
哪位有手持外壳链接,帮推荐一下,最好能装4-5节5#电池

出0入0汤圆

发表于 2012-1-18 09:21:41 | 显示全部楼层
搞个XTR110电压到4~20MA即可,下载个手册自己看看吧!非常好用,价格也很贵。

出0入0汤圆

发表于 2012-1-18 16:53:47 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-1-19 13:44:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-3-8 14:09:52 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-3-8 15:43:43 | 显示全部楼层
mark
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 04:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表