The purpose of this project is to provide a
4-20 mA output from a PWM signal generated by a microcontroller ATmega328 and numerous
other chips, such as the PIC. One of the more interesting applications of this
circuit would be to replace or to realize a smart sensor with Arduino.
Last year I had designed a circuit suitable
only for Arduino Due, this new work makes use of a common Arduino Uno or
similar to create a standard 4-20 mA analog output.
Arduino Uno, or systems based on the ATmega328
chip has no a true analog output. The easiest way is to use one of the PWM
outputs and filter the signal with a passive RC filter to obtain an analog
signal proportional to the duration of the pulses. This expedient creates a
considerable noise due to the frequency of the PWM itself. To eliminate the
noise I used a second order active low-pass filter, Sallen-key type. The
frequency of the Arduino PWM (with 16 MHz clock) on pin 9 is about 490 Hz, so I
used a very low cutoff frequency (11 Hz) but with a bandwidth sufficient for
the majority of industrial controls.
By connecting the filter directly to the PWM output
is obtained a signal which varies from 0 to 5 V which would give an output
current of 0 to 20 mA. The pulses duration is programmed with a word of 8 bits,
losing 1/5 of the full scale. To improve the current resolution from 20/255 to
16/255, I modified the minimum amplitude of pulses from 0 to 1 volts, giving at
the output a 4 to 20mA current. The block diagram is shown in figure 1.
Figure 2 shows the complete diagram of the
circuit. To obtain pulses from 1 to 5 volts I had to use a 1 V source realized
with U1A and the transistor Q1 that works as a switch. The operational U1B
operates as a separator; the filter uses U1C and the voltage / current
converter uses U1D and Q2.
The transistor Q1 inverts the PWM signal, so
the software must complement the number of PWM duty cycle.
The trimmer pot Rp1 is used to adjust the minimum
output current (4 mA) and the Rp2 to adjust the maximum (20 mA). The
theoretical value of the emitter resistor is Re = 5/0.02 = 250 W, but that does not take into
account the tolerances of the voltage supply of Arduino and of the resistors.
The resistor R8 is used as U1D output current
limiter in the situation of absence of load.
A step down converter is a good solution for
powering the system because of the 24 V, this value can be varied from 12 to 30
V, depending of the load circuit.
Arduino Uno has a +5 V output pin, It does not
recommend using it as a power input inasmuch
this would be in parallel with the internal regulator but it can be powered at
+5V using the USB connector, other boards as Arduino Pro Mini, have a +5 V
input.
Hardware components
1x Arduino board,
1x Step-down switching converter,
Components list
R1= 27 kW ±5%
|
R2= 47 kW ±5%
|
R3= 10 kW ±5%
|
R4= 27 kW ±1% metal film
|
R5= 6.2 kW ±1% metal film
|
R6= 100 kW ±1% metal film
|
R7= 100 kW ±1% metal film
|
R8= 1 kW ±5%
|
R9= 270 W ±1% metal film
|
R10= 1.8 kW ±1% metal film
|
Rp1= 1 kW trimmer
|
Rp2= 10 kW trimmer
|
C1= 100nF Mylar
|
C2= 100 nF Mylar
|
C3= 200 nF Mylar
|
C4 = 10 MF,50V Electrolytic
|
C5 = 100 nF Mylar
|
U1= LM324 quad op amp
|
Q1 = 2N3904 or eq.
|
Q2= 2N2219A or eq.
|
The capacitors used for the filter must be
measured with a capacimeter, for my prototype I selected for C3 some 220 nF
capacitors to search for a value that approached 200 nF and C2 have selected a
value half of C3. Q1 is a transistor
that must have a low Vce(sat.) and Q2 must have a current gain of at least 100
and a Vceo of at least 40V with a minimum power of 500mW.
The operational amplifier U1 must be suitable also
for single-rail power supply, such as LM324.
The components layout of my prototype is shown
in Figure 3, the resistor on the top is a precision load used for calibration
of the system. Q2 has a small heat sink because, with at 20 mA and a low
voltage load, as in this case, dissipates: (24-3-5) *0.02 = 320 mW. In these
circumstances is better to reduce the 24 v.
The test program
To test the system I used an Arduino with an
LCD display and a potentiometer connected to analog input A0, as pin PWM I used
D9. The program is very simple: read the potentiometer, converts 10 to 8-bit
Analog reading and produces the PWM.
//
program to test Arduino Uno PWM
// G. Carrera 2 ago 2016
#include <LiquidCrystal.h>
int
PWMpin = 9; // PWM out on digital
pin 9
int
analogPin = 0; // potentiometer
connected toA0
int
val = 0; // variable to store the
read value
char
spacestring[17] ="
";
//
initialize the library with the numbers of the interface pins
LiquidCrystal
lcd(7, 6, 5, 4, 3, 2);
void
setup() {
pinMode(PWMpin,
OUTPUT); // sets the pin as output
lcd.begin(16, 2);// set up number of columns
and rows
lcd.setCursor(0, 0);// set the cursor to
column 0, line 0
lcd.print("Stalker PWM test");//
Print a message to the LCD
}
void
loop() {
val = analogRead(analogPin) >> 2;// 10
to 8 bit conversion
analogWrite(PWMpin, val);
lcd.setCursor(0,
1);
lcd.print(spacestring);
lcd.setCursor(0, 1);
lcd.print(val);
delay(500);
}
I reported on the spreadsheet the PWM values
and the measurements in volts made on a precision resistor (150 W ±0.5%) that worked as a load,. The
PWM / output current diagram is shown in Figure 4.
The linearity is very good as confirmed by the coefficient
of determination R2 = 0.999992.
If you want a positive slope, the value must be
complemented to 255 in this mode:
val
= 255-val;
In my program, you could generate a new value
every 500 milliseconds (2 Hz), but you could reduce this period of up to 100 ms
(10 Hz).
I have questions, what potentiometer connected to A0? i dont see it on the schematic. thanks
ReplyDeleteMr. Giovanni,
ReplyDeleteplease ignore my previous question. I have new question. When AO is 0 V the output is 20 mA, when A0 is 5 V the output is 4 mA, how to invert it?
Regards
Hi Yogie,
Deletethe answer to the first question is that you can use a linear potentiometer from 1 to 100 kilohms.
For the second question, just complement the value by including the statement:
val= 255-val;
Regards
Mr. Giovanni,
DeleteThank you for the answers .. this potentiometer is connected to A0 input and power source, is that correct?
Mr. Giovanni,
DeleteWhat if i am also want voltage output, instead current output?
I have a task to build 4 channel voltage output (1-5 V), and 4 channel current output (4-20 mA).
Please advise.
Regards
Mr. Yogie,
Deleteyes, the potentiometer cursor is connected to A0 and and the two ends are connected respectively to ground and + 5V.
The 1-5V signal is available at the output of the amplifier U1C (pin 8).
Regards
Mr. Giovanni,
ReplyDeleteI tested the voltage signal on pin 8, U1C. It is a little bit higher than A0 input voltage.
Thank you
Mr.Yogie,
ReplyDeletethe output voltage is proportional to the input, but there are two conversions (ADC and PWM) and the output resolution is only 8 bits. My program was just an example to test the system. Greetings
Mr. Giovanni,
ReplyDeleteYour circuit and test program is suitable for my project, it is what i am looking for. I wonder how you came up with an idea to create that circut. Using your circuit, from single Arduino Board, i can generate multiple current/voltage sources.
For my project, 8 bit is enough. So for Voltage source at Pin 8, i think i have to find a way, so that the output is the same as the input.
Your circuit is help me a lot. Thank you
Mr.Yogie,
DeleteI'm glad that my projects are useful to someone.
For a 0-5V out, the circuit is greatly simplified, you should connect the pin 5 of U1B to Arduino D9. Also you need to remove: R1, R2, Q1, R4, Rp1, R5. U1a is no longer used. Regards
at pin 9 default frequency is 490Hz, but you can change to 3905Hz or to 31250Hz (see http://playground.arduino.cc/Code/PwmFrequency )
ReplyDeleteI know it well, just change the divisor of the prescaler, but an optocoupler with slow switching times starts to create problems. Now I'm testing a new project with 0-5V (or more) output range and a different optocoupler.
ReplyDeleteWhy did you choose a cut off frequency of 11Hz? I really don't understand that part.
ReplyDeleteA second order filter has a slope of -40 dB per decade. The frequency of the PWM output pulse creates a noise which should be reduced as much as possible. The chosen frequency is a good compromise between output signal bandwidth and noise attenuation.
DeleteAlright, I did some reading and I understand that now. Is it safe to assume the PWM has a DC component that you filter out using the second order Sallen Key Low pass filter?
DeleteNo, the useful signal is the DC component, while the filter have to eliminate the AC component that is created just by the PWM pulses. You can also use a simple RC filter, but is much less efficient: the slope is only -20 dB/decade.
DeleteThanks. You have been very helpful.
DeleteHi Giovanni,
ReplyDeleteI must admit, your technical skills are superb!
This circuit works great.
Just one question regarding the positive slope.
The Val=255-Val works OK but can this be done also in the circuit?
By means of using an opamp as Inverting instead of non-inverting?
The reason is, if the Uno is not working, but the 24V power is present, the output gives 20mA. To make it more save, if would be nice of it gives 4mA. (or 0mA)
Thank you for your compliments, I'm glad to have been useful to someone.
DeleteYou can not use inverters with single power supply if you operate with zero reference as in this case. The simplest way is to power arduino with a dc/dc power supply (in 24V, out 5V), as shown in the diagram. This will shut down everything.
What a great blog...
ReplyDeleteok. Houston we have a problem !!!!!
How to i change this circuit for a gauge, for example http://www.kusauto.com/en/productlist.aspx?pid=7&tid=81
thanks for the answer..
Hi Lemi,
ReplyDeleteyou can modify the output current by changing the resistors R9, R10, but the ratio remains 1:5. Yours sincerely
ahh i'm sory for the 20-60 ma. output of course...
ReplyDeleteFor Imax = 60 mA, Re = 5V/0.06 = 83.33 Ohm (non standard value), using the values you used, you have to change also Rp2 = 2.2k Ohm.
ReplyDeleteImin = 60mA/5 = 12 mA
if you want a current range of 20 to 60 mA, the ratio must be 1/3. You have to change the divider R4, R5 and Rp1 in order to have a voltage of 5/3 = 1.666 V instead of 1V.
I leave this easy calculation to you.
ok.
ReplyDeleteR9 = 90 ohm
R10 = 450 ohm
Rp2 = 2.2 kohm
R4 = 18 kohm
R5 = 6.2 kohm
Circuit give max. current 24.3 ma.
By the way i'm using Q2 = BD139
By increasing the output current the load must have a lower resistance, otherwise it limits the maximum current.
ReplyDelete12 ma to 60 ma. good for me , current ratio 1/5 . I'm changing R4 old value 27k.
ReplyDeleteI'm measuring kus gauge internal resistance Rgauge = 131 ohm.
ReplyDeleteMaybe gauge working theorem not match this circuit.
ReplyDeleteI do not know what's inside your gauge, maybe it's not even linear.
ReplyDeleteTry to increase the voltage, even if 24V should be sufficient.
I'm exploring new state, when i changed R9 = 10 ohm, max current 60 ma. ok. but circuit out of control.
ReplyDeletefor 10 ohm r9, circuit current max. 100 ma. so R10=50 ohm. what value for Rp2 ?
ReplyDeletesorry 500 ma. if R9 10 ohm.
ReplyDeleteDon't change the circuit components. The problem is on your load. Test it with a resistor 100 ohm resistor and an ammeter in series.
ReplyDeleteyes i have returned to the old circuit. problem is caused by gauge. I had two bobbins in these devices as far as I found google,
ReplyDeleteNow I'm investigating how I drive this tool.
Thank you for everything, mr. Giovanni ....
2N2219A -is that transistor or heat sink??
ReplyDeleteas you can see in the picture, just a small heat sink for TO5 case
ReplyDeleteFantastic circuit, works perfect.
ReplyDeleteQ: How can i display the PWM reading as a current value on the LCD Screen. Thanks
Outstanding work. As a person just learning electronics and interested in smart sensors this is extremely interesting and useful. Thank you for sharing.
ReplyDeleteGood Morning,
ReplyDeleteI wonder if the current loop should be isolated. Because when I put the multimeter in the current output it behaves normally, but when I add this circuit to the analog input of the PLC the reading is wrong.
This is possible, it is necessary to use an optocoupler (which inverts the signal, therefore the Arduino driving must be inverted) and a separate power supply. It probably works badly because my circuit works as current sink and not as current source.
DeleteHello Giovanni
ReplyDeleteI am developing an application which is Arduino based. I want to know if you can support me with your work in this post. My application/instrument need to convert 0-5V to 4-20mA. Kindly let me know if you can support me, we will compensate for your support to us. Awaiting your reply.
Hi Parag,
Deletewhat you need is already in my program. You can eliminate the LCD display and use A0 for the 0-5V analog input. If you want to invert the curve just do the complement, the program becomes:
void setup() {
pinMode(9, OUTPUT); // sets the pin as output
}
void loop() {
int val = analogRead(0) >> 2;// 10 to 8 bit conversion
val = 255-val;// complement the output
analogWrite(9, val);
delay(100);// sampling time
}