vans52 发表于 2010-10-17 21:56:11

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

4-20mA 可调的信号源制作 用于校验PLC/DCS设备 在设计上和芯片选用上,大家有什么好的见意,在4-20mA电流输出,是采用单片机Pwm调节三极管还是用集成芯片输出电流,什么芯片好一点,谢谢 !

czzhouyun 发表于 2010-10-18 08:36:57

AD421,没什么说的

electricit 发表于 2010-10-18 09:01:38

楼上说的很强大,电池的问题需要解决

electricit 发表于 2010-10-18 09:02:56

产生毫伏信号,电压信号,电流信号,频率信号经模块开关切换,工业调试的确方便

wuliwb 发表于 2010-10-18 09:04:20

运放就可以解决的!用集成芯片太贵 ,如果做个N路吃不消啊!

vans52 发表于 2010-10-29 22:17:24

回复【4楼】wuliwb
-----------------------------------------------------------------------

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

vans52 发表于 2010-10-29 22:18:03

回复【1楼】czzhouyun
-----------------------------------------------------------------------

有现成的图吗,发我看看

vans52 发表于 2010-10-29 22:19:47

回复【2楼】electricit
-----------------------------------------------------------------------

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

linlh 发表于 2010-12-17 17:38:24

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

vans52 发表于 2010-12-18 10:18:02

回复【8楼】linlh
-----------------------------------------------------------------------

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

czzhouyun 发表于 2010-12-18 10:35:13

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

My5A1 发表于 2010-12-18 11:00:53

曾经给朋友做过一个调试PLC用的小东西,用M48的PWM生成0-20ma的,还有测量功能...挺好玩的

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

cuikai12345 发表于 2010-12-18 13:06:56

楼上可以参考一下程序么?

My5A1 发表于 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;
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;
                        }
                }
//-----------------------------------------------
      }
//-----------------------------------------------
}

My5A1 发表于 2010-12-18 14:33:59

重新用 Editplus 的工具 “制表符' 换成 “空格”,要不发出来看得晕

linlh 发表于 2010-12-21 10:41:31

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

linlh 发表于 2011-1-11 16:31:38

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

dszx 发表于 2011-1-11 18:50:51

还需要输入键盘、显示,要不你怎么设定输出的电流值?

lihuyong 发表于 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以及计算的时间。

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


个人愚见

vans52 发表于 2011-1-22 21:55:09

回复【16楼】linlh
-----------------------------------------------------------------------

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

vans52 发表于 2011-1-22 22:02:32

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

czzhouyun 发表于 2011-1-22 23:59:16

检测负载,无负载超过一定时间自动关闭休眠节能,以前用过校验仪,12864的液晶,充电一次可以用一天,当然不是一直在用,一段时间无负载关闭

xinjihua 发表于 2011-4-19 11:31:47

高效DC-DC升压电路
http://cache.amobbs.com/bbs_upload782111/files_38/ourdev_632045YCA543.jpg
(原文件名:rc4192升压电路图.jpg)

DoDo915 发表于 2011-4-19 11:50:29

Mark

mdf1314 发表于 2011-4-19 12:30:37

请问,如果要做多路的4~20mA信号发生器呢?
多用几个AD芯片肯定可以,但是如果要节约成本咋么弄啊?

buliaoqq 发表于 2011-6-10 13:38:56

mark

emouse 发表于 2011-6-10 17:37:32

刚做,TLV5614+AM462

qqcanread 发表于 2011-6-10 17:55:55

学习了,

electricit 发表于 2011-7-25 22:06:05

现场设备共阴的比较多

cookie 发表于 2011-11-12 16:01:22

mark

Ar135 发表于 2012-1-18 00:31:43

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

activeleo 发表于 2012-1-18 09:21:41

搞个XTR110电压到4~20MA即可,下载个手册自己看看吧!非常好用,价格也很贵。

xingkongyao 发表于 2012-1-18 16:53:47

mark

gxy508 发表于 2012-1-19 13:44:23

mark

jinniuxing88 发表于 2012-3-8 14:09:52

mark

minicatcatcn 发表于 2012-3-8 15:43:43

mark
页: [1]
查看完整版本: 4-20mA 可调的信号源制作 用于校验PLC/DCS设备 在设计上和芯片选用上,大家有什么好的