level shift DAC output

Ok, I have what i think is a pretty simple question about voltage level, but I cant seem to find a clear answer out there.

Im using an UNO to drive an I2C DAC which outputs a 0-5V value. I want to be able to amplify the DAC output so that it is centered between the rails of an external ±30V power supply. Most of the other posts I read suggested a cap in series with the output to remove the DC component of an audio signal. But I want to be able to hold the voltage constant at any given value and vary it slowly, so I'm not sure the cap is going to work for me.

My first thought is just use a summing op amp and subtract off 2.5v from the DAC output, then send that to and op amp to take up to final voltage. I'm pretty much a newbie though so I'm hoping to find a cleaner and or more clever solution here.

the op amp I have for the amplifier stage.

also, Im looking for as much precision as I can get here for the final voltage, and it would be helpful if the final output was very well centered around ground. I have a feeling the latter would not really be possible with the summing op amp idea....

thanks for helping!

The DAC is good, the OpAmp is good, and that will work. Accuracy is a problem.
I think you only need resistors and one OpAmp to level shift and amplify the signal.
My first idea is to use two resistors for 2.5V for positive input and inject the negative input with current from 5V via a same resistor as the resistor from output to negative input. I don't know if that will work.

Can you tell how much current is needed ?
What is the output of -30V...+30V for ? Can you tell about the project ?

It will be -30 to +30V with 12-bit.
60V / 12-bit = 15mV resolution.
But the resistors are inaccurate and they depend on the temperature, and the DAC might be only 10 or 11 bit. I guess you can get accurate near 0V with about 50mV. Is that good enough ?

How accurate is the 5V ?
If that drops to 4.8, the output will be -28.8 to +28.8V.
It is possible to read the output voltage with the Arduino, but then it will be too complex and that doesn't increase the reliability.

There is an other option: PWM.
To amplify a PWM signal to -30...+30V is simple. Use a filter to make it an analog signal, and that's it.
When you use a 16-bit timer for it, it might also be accurate.

thanks for the reply, sounds encouraging so far.

Can you tell how much current is needed ?

The op amps say they can supply ±15ma of current, I'm hoping that's enough, but if not there's some suggestions in the application notes for increasing current output that I think I could use if needed. Im trying to make a very precise positioning device. So I want to be able to apply some fixed voltage to a piezo ceramic to make it deform a given amount, hold it there as long as needed and be able to move to any other position from there. I would like to be able to assign a voltage output to a given point in space. So, any time I send say '1024' to the DAC, I would hope to end up very close to the same position in space every time.

So, voltage resolution is pretty critical. 15mv step size is definitely acceptable, I am hoping its possible to achieve this. If I can get this up in running, I would probably try to find the lower limit on that, see if i could get 5mv resolution and if it would result in finer positioning...

and the DAC might be only 10 or 11 bit.

why would that be? i hope its 12, thats what they sell it as...

I guess you can get accurate near 0V with about 50mV.

could you explain this? you mean, the full range of the final output could be centered at 0V ± 50mV ?...if so i think i would be ok with that.

How accurate is the 5V ?
If that drops to 4.8, the output will be -28.8 to +28.8V.

measuring just from a multimeter, it does look like about 0-4.8V. The good thing is I'm still pretty flexible with the power supply, I built an adjustable one with this voltage regulator. So I can get to ±57 volts if needed. Ive seen some other similar project where they used voltages that high, so Im not worried about the piezo just yet, but larger range gives me larger voltage steps, and lower positional resolution, so id like to go as small as possible I guess. Also, I don't think I would let the opa output get too close to the rails to avoid saturation, so this will reduce my voltage range again.

I think the output current of the OpAmp is enough for a piezo.

The 5V for the DAC should be accurate. I don't know if a LM317 is good enough for that.

The 15mV accuracy in the output voltage is what you get with 12-bit DAC (in theory, not for real). That is 5V / 12-bit * gain 12 = 15mV.
The OpAmp has 1mV typical offset error, resulting in 12mV output error (your gain is 12 since 60/5 = 12).
So you have alreay 15+12 = 27mV inaccuracy. And the resistor add more to that.

When you want to go to 5mV accuracy, you better buy a 16-bits DAC and tune the OpAmp with the hardware or in software.

The 50mV was just a guess for the complete circuit. I guess the accuracy can be 20mV to 500mV, so 50mV was in the middle.

Since you want a fixed voltage for a piezo, there are many more options. The PWM as I said, but also a controlled loop with a boost converter. Or even a voltage multiplier circuit, again with a loop, so the Arduino would measure the output voltage. But that is just nuts, the DAC with the OpAmp is a good and straightforward setup without running into trouble.

Is there some reason you chose the MCP4725 DAC? Would you be open to changing your choice?

If so, I'd point you towards the MCP4726 instead. It looks to be functionally identical (but not pin-compatible) to the 4725, with the important difference that it has a external Vref pin instead of an address pin. This way, you can reference the DAC's output to a precise 2.5 V reference instead of relying on whatever Vcc happens to be. It will be much more stable.

But yeah, there's really no way to level shift without a summing amplifier of some kind. I actually have this exact same problem with my current function generator project, trying to inject a DC offset into a sine/triangle wave signal. I solved it using the amplifier train shown in the schematic below. Ignore the first three stages, only the last two are what you need (ignore R6 too, the first stage will just be an inverter).

Going from a range of 0V-2.5V to -30V-30V requires an overall gain of 24. Let's make it 25 so it's easier to split across two stages (5x and 5x). You'll just have to recalibrate the maximum and minimum you can go before you hit the rails. If you want to keep it at 24x, you'll have to recalculate the resistors.

By my calculations, the resistors should have the following values:
R7 = 10k
R8 = 50k
R9 = 10k
R10 = 4k
R11 = 50k

The Vin for the first stage is your DAC's output (labelled 2.048 on my schematic). The Vin for the second stage is the output of the first stage + the DAC's 2.5 V voltage reference (labelled 4.096 on my schematic).

Am I wrong, or is it possible to inject a current from a fixed voltage for shifting, and also have a gain in a single OpAmp ?

archy587, I suggest to just build a circuit and start the tests with the piezo. You can make a better one after you have done some tests and see what needs improvements.

Peter_n:
Am I wrong, or is it possible to inject a current from a fixed voltage for shifting, and also have a gain in a single OpAmp ?

It is possible, but you'd need to generate a negative voltage in order to subtract from the positive offset.

Or you could use a difference amplifier (Operational amplifier applications - Wikipedia). Use a 1.25 V reference, set the gain of the DAC to x2, have x24 gain in the amplifier. Your two inputs will be the voltage reference and the DAC output.

Actually, the difference amplifier might be the elegant solution you're looking for. You just need 4 resistors and a voltage reference.

thanks for the help guys.

I think I agree with peter that I should just wire it up and see what I can get out, then move from there.

Think Ill start by making an offset voltage with a voltage divider from the negative supply rail, and go for a level shift+amp in one stage.

The 5V for the DAC should be accurate. I don't know if a LM317 is good enough for that.

so far Ive been using the UNO 5v output to supply the DAC, and the LM317 just to supply the opamps. Do you think the UNO 5v is better/good enough?

archy587:
so far Ive been using the UNO 5v output to supply the DAC, and the LM317 just to supply the opamps. Do you think the UNO 5v is better/good enough?

From USB? No, not even close. USB sucks. From an external power source through the DC jack? Maybe. It should be pretty stable around 1% tolerance.

archy587:
Im using an UNO to drive an I2C DAC which outputs a 0-5V value. I want to be able to amplify the DAC output so that it is centered between the rails of an external ±30V power supply. Most of the other posts I read suggested a cap in series with the output to remove the DC component of an audio signal. But I want to be able to hold the voltage constant at any given value and vary it slowly, so I'm not sure the cap is going to work for me.

+/- 30V is well beyond the range of standard opamps, you'll need to track down
a high-voltage device.

The standard difference-amplifer configuration for the opamp is what you need.

I was wander, what is required update rate? How often do you need to re-position your piezo? Probably, not too fast, as piezo 'd be bad choice with it's high capacitance.
If so, than why to get all this struggle with analog design, instead of using PWM? You 'd get better resolution - up to 16-bits, simple circuits, 1 transistors with a few caps and resistors . Couple inductors 'd make nice 2-nd order LPF

If so, than why to get all this struggle with analog design, instead of using PWM? You 'd get better resolution - up to 16-bits, simple circuits, 1 transistors with a few caps and resistors . Couple inductors 'd make nice 2-nd order LPF

I considered this before deciding to go with a DAC because I didnt think the filtered DC from PWM would be a very clean/stable/constant signal. do you disagree? With the PWM setup, I would keep the PWM frequency constant, and just vary the duty cycle to get a different DC voltage from the filter output?

So to get the 60V range I described above (±30V), I would look for a PWM that output at 60V, or amplify a 5v PWM signal up to 60v?

I was wander, what is required update rate?

you're correct. I don't plan to update very fast, but as fast as I can I suppose. What do you think is the limit? 1khz update would be possible?

+/- 30V is well beyond the range of standard opamps, you'll need to track down
a high-voltage device.

The standard difference-amplifer configuration for the opamp is what you need.

thanks, i do have high voltage amps rated to ±45

What do you think is the limit? 1khz update would be possible?

sorry, this was a confusing way to write this. I was trying to say change from one DAC output value to the next adjacent DAC output value (DAC value +1) at a rate of 1000 updates per second. With the 12bit DAC this would mean it would take over 4 seconds for me to go from the lowest possible voltage to the highest. I think this is well within reason, and acceptable for my application.

Quote
If so, than why to get all this struggle with analog design, instead of using PWM? You 'd get better resolution - up to 16-bits, simple circuits, 1 transistors with a few caps and resistors . Couple inductors 'd make nice 2-nd order LPF

I considered this before deciding to go with a DAC because I didnt think the filtered DC from PWM would be a very clean/stable/constant signal. do you disagree? With the PWM setup, I would keep the PWM frequency constant, and just vary the duty cycle to get a different DC voltage from the filter output?

Yes, I disagree. It's not relevant how clean signal you 'd have, all depends on filtering circuitry.
Considering DAC, you may have fast update rate, let's say 400 kHz I2C / 12 bits ~= 33 kHz or so, you can change settings from 0 to 4095 (full scale) in less than 30 usec.
PWM is slower, arduino UNO 16 MHz / 4096 (12-bits) ~= 3.906 kHz at the best, giving 5-10 times for simple filter design and update rate can't go faster than 390 - 780 Hz.
But, I think in most circumstances it's more than necessary. Look at regular servo motor, having update rate only 50 Hz, it's moves 180 degree fast and easy. PWM is very low cost, you ' d drive 1 transistor from +5V output of the arduino and have what ever voltage you need (depends on transistor, of course ) +60 or +6000V at the collector. All you need after - a filter, look on-line (wiki) for simple RC filters. Don't need DAC, OPA with low offset, precision, low drift etc. etc. .....

Magician:
PWM is slower, arduino UNO 16 MHz / 4096 (12-bits) ~= 3.906 kHz at the best, giving 5-10 times for simple filter design and update rate can't go faster than 390 - 780 Hz.

ATmega328P does not support hardware PWM of 12-bits. 10-bits in the highest it goies on Timer1.

But, I think in most circumstances it's more than necessary. Look at regular servo motor, having update rate only 50 Hz, it's moves 180 degree fast and easy.

A servo signal isn't a drive signal for the motor though, it's a control signal for the motor controller, which translates that into positional information and uses a more advanced algorithm to run the actual motor.

PWM is very low cost, you ' d drive 1 transistor from +5V output of the arduino and have what ever voltage you need (depends on transistor, of course ) +60 or +6000V at the collector. All you need after - a filter, look on-line (wiki) for simple RC filters. Don't need DAC, OPA with low offset, precision, low drift etc. etc. .....

How would he generate the -30V offset he's looking for without analog circuitry of some kind?

ATmega328P does not support hardware PWM of 12-bits. 10-bits in the highest it goies on Timer1.

Not a problem , use any mode from 8 to 15, setting ICR1 (or OCR1A) you define the number of bits. For example, mode 8 , ICR1 = 4095, no preselector, than using ether OCR1A or OCR1B you setting PWM width writing value from 0 to 4095, and voale, 0- 100 % PWM.

A servo signal isn't a drive signal for the motor though, it's a control signal for the motor controller, which translates that into positional information and uses a more advanced algorithm to run the actual motor.

Motor controller? what is that?
I think servo comes to live long before than "controller" word was invented.

How would he generate the -30V offset he's looking for without analog circuitry of some kind?

  1. Level shifting. (+1 transistor).
  2. Bridge.

ATmega328P does not support hardware PWM of 12-bits. 10-bits in the highest it goies on Timer1.

Not a problem , use any mode from 8 to 15, setting ICR1 (or OCR1A) you define the number of bits. For example, mode 8 , ICR1 = 4095, no preselector, than using ether OCR1A or OCR1B you setting PWM width writing value from 0 to 4095, and voale, 0- 100 % PWM.

How would he generate the -30V offset he's looking for without analog circuitry of some kind?

I haven't say w/o any circuitry.

  1. Level shifting. (+1 transistor, two overall).
  2. Bridge.
  3. Audio PA

Jiggy-Ninja:
ATmega328P does not support hardware PWM of 12-bits. 10-bits in the highest it goies on Timer1.

Incorrect, timer1 is 16 bit. However with a 16MHz clock a 16 bit PWM can only run
at 244Hz. However 12 bit is going to work well.

Look at the datasheet and choose modes 8 or 14 as appropriate, program period in ICR1,
ie ICR = 0xFFF for 12 bit.