An Isolated DAC Using PWM Output

Arduino‘s (ATmega328P) PWM outputs via analogWrite can be conveniently turned into analog voltage levels through the use of simple RC filters. Since the PWM outputs are not isolated, using them to drive other devices directly could be potentially dangerous. This is especially true if the target circuit uses a higher supply voltage.

Fortunately, it is quite easy to isolate the PWM output using an optocoupler. The following schematic shows how we can build such a fully isolated DAC:

Isolated DAC

The PWM output pin from the MCU drives the emitter side of the optocoupler. Most MCU output pins can deliver at least a few mA current so driving an optocoupler directly via a current limiting resistor should not be an issue. In my implementation, a 4N35 optocoupler is used, but you can pretty much use any optocouplers.

The output waveform from 4N35 is inverted with regard to the input as the optotransistor within 4N35 operates like an inverter. The inverted PWM signal is flipped once again through the unity gain inverting amplifier. An RC low-pass filter (R5 and C1) turns the PWM output into DC voltage and finally this DC voltage is buffered through a voltage follower to the output. The RC constant needs to be chosen so that it is significantly larger than the PWM interval. The PWM frequency via Arduino’s analogWrite is roughly 490 Hz (roughly a 2 ms cycle), and the RC constant in the example above is 100 ms, which is sufficiently large to guarantee a smooth output. Note that the circuits on either side of the optocoupler do not have to share the ground reference as illustrated in the schematics above.

I used LM358 as the OpAmp. Since LM358 is not a rail-to-rail OpAmp, the DAC output range is going to be limited by the supply rail. If your application requires higher accuracy, you could either use a rail-to-rail OpAmp or use a slightly higher voltage dual supply rail to power the OpAmp.

Be Sociable, Share!

21 Comments

  1. Marc says:

    Hello,

    My 0,02$ advice, you should better use IC1A as a Schmitt Trigger than as an amplifier (10x) as you can’t be shure of opto-iso transfer function (might be non linear). Schmitt trigger will produce “beautiful” square waves in respect of the original timing (PWM).

    Regards,

    Marc

  2. perfect_d says:

    Hey really cool circuit! I like the use of the optocoupler. I’m new electronics and would like to understand your circuit better. Why did you decided to use a dual opamp? Why not put R2 below the optocoupler and just take the point between the bottom of the opto and R2 and feed it directly into the rc filter? What is the purpose of R3 and R4? Would it make sense to put a high value resistor (10M?) from the input to the second opamp to ground to improve the responsiveness of the dac when lowering the output. As I said really neat circuit I can totally see myself using this thanks for any reponse.

    • kwong says:

      Yes you could configure the phototransistor as an emitter follower as you mentioned. Using an op-amp here improves the output PWM waveform. R3 and R4 sets the gain of the inverting opamp to -1. R5 and R6 provides a virtual ground reference.

      A resistor between the positive input of the second opamp and ground is not necessary as the capacitor charges and discharges through R5.

      • perfect_d says:

        Thanks for your response! I totally forgot the op and will source and sink current so an extra resistor would be a complete waste. I also figured you were using R5 and R6 as a voltage divider to set the non inverting input between VCC and GND I guess I didn’t understand why the values for R3 and R4 couldn’t just be 0 isn’t the inverting amp formula vout=-(rfeedback/rinput)/vin so wouldn’t 10k/10k be the same as .000001/.000001 (where .000001 is the really small resistance of the wire or traces)? Thanks for your feedback great blog.

  3. Per says:

    Hi Kwong
    Thanks for the design! I built it today and was a little bit surprised when the output was 1,25V lower than the supply. I then re-read you last note and looked in the data sheet for the op amp and it clearly states Vcc -1,5V as output. I’m going to use it to control a 0-10V signal and the power stage generating it’s own ref 10V. So a reduced signal means not reaching top speed. Do you think the design is suitable if i go for rail-to-rail Op Amps? PWM is at 60KHz and the needed rate of change on the out signal is very low, 1s is ok. The isolated and buffered property’s of this design is exactly what I have been looking for.

    Once again thanks
    //Per

    • kwong says:

      Yep. Pretty much any rail-to-rail Opamp that meets your Vcc requirements could be used for this purpose.

      • Per says:

        Hi Again,
        I bought some high end rail to rail opamps and that solves the high voltage issue but exposes a low side problem.
        It appears the circuit never goes to zero. (@ t=0) If OK1 floats, implying a desired 0 out, you always get a value smaller on 2 than on 3. This is due to R2+R3 / R4 < R6 / R7. So to get a zero value R4 needs to be at least equal to R2+R3. What will happen to the rest of the circuit and function if we make R4 25K? I don't know much about electronic so some help is needed :-)

        Best regards
        Per

        • kwong says:

          I don’t think the IC1A circuit is the problem as it simply inverts the output signal from the Opto-coupler. You can see this by placing a scope at the output of IC1A.

          What’s the output voltage you get if you short C1 to ground? If the OpAmp is rail-to-rail, you should get an output voltage very close to 0V.

          • Per says:

            Hi

            If I short C1 to ground I of course get 0V (0,003V) out of IC1B since I get 0 in.

            With this circuit you get two different gains. You get -1 when the OK is on and you get -1/2 when it is off. I get a full swing (-0,05 v @20V) when the OK is on and I get (Vcc/2)/2 when the OK is off. This is exactly according to the the theory. Vout = -Rf/Ri x Vin since Ri varies between 10K and 10K+10K.

            When I changed Rf to 27K it works perfect for the digital purpose even though it is not ideal for analog transfers.

            Anyhow thanks for the initial design.
            //Per

          • kwong says:

            OK… I see your point now. Thanks!

  4. marko says:

    I have put R6 and R7 33kohm resistors and get 2.5 Volt output when there is no PWM.

    Can somebody explain me calculations?

  5. Per says:

    Hi Kwong

    A few things learned:
    For a standard PWM (around 20KHz) you need a seriously fast opto. You want the filter to do the DA work not the opto. For me at 65 KHz and 8 bit res I would need an opto capable of handling a minimum of 65000*255= 16,5MHz and that will still give me large errors on small values.

    I was able to set a pre-scale on my pwm to 255 to get a pwm at 256 Hz. This still gives me errors on small values with a cheap opto, rise and fall at 20us.

    I completely removed the feedback resistor to get it to work properly.

  6. Javier Loureiro says:

    the opto has a floating base. you should connect it to ground using a large resistor, otherwise it is like an antena injecting noise in the circuit

  7. Ross says:

    I am using your PWM/DAC to drive a Minarik motor controller from a TinyG CNC board. I’ve assembled the circuit based on your schematic with no modifications. It works in controlling the speed but the signal is inverted. When the pulse width is short the speed/voltage to the Minarik is higher and a longer pulse width produces a lower speed/voltage. Also when the power is initially applied the motor will run at full speed until a speed setting is given.

    Any help would be appreciated.

    Best Regards,

    Ross

  8. […] here is the specifications for this project. TVout support for the video. PWM to DAC converter to control analog signals. Keypad controlled with analog pins to keep the digital freed up […]

Leave a Reply