It's been ages since I've had to use my old school notes.

I am trying to get an esp32 to read an analog voltage that ranges from -12 to +12. Obviously, the 3.3v esp32 won't like those voltages so I have to come up with a way to scale down and shift the signal.

What I have so far is: enter image description here

So here, V2 is the signal input voltage. In the image it is 12v, but in reality it will be either 12 or -12 at any given moment.

OP2 is an inverting, "attenuator" that will step the +/-12v down to +/-1.65v.

OP3 is a differential amplifier that will, essentially, add a 1.65v bias to the +/-1.65v input signal bringing it to 0-3.3v.

Now looking at this, I can't help but feel there is some optimization to be done here. Is it possible to combine the 2 amp stages into 1? I tried doing it mathematically but I end up with a negative resistance...

Can the two stages be combined into 1? Thanks.

Also, I'd like to make sure nothing outside of 0-3.3v ever comes out of OP3. Is it possible to power OP3 with 3.3v and GND in stead of +/-12v? My simulation software (qucs) doesn't seem to allow me to select the supply voltages...

  • 1
    \$\begingroup\$ Any reason you didn't just use a voltage divider as the attenuator? \$\endgroup\$ Dec 11, 2019 at 3:14
  • \$\begingroup\$ @user1850479 Good question. Originally I had a different design that lead me to use 2 op amps. You are right tho, in this case, I don't need both... Hmm. I think that solves it, actually. Only issue would be that the output is inverted due to going through only one inverting stage, but that's easily compensated for in the software. \$\endgroup\$ Dec 11, 2019 at 3:28

3 Answers 3


Your method needs a Vee that is negative with 1st stage inverting and the output range needs to reach Vdd=3.3V

Design spec

Gain = +3.3/24V (you have 3/22)
Offset=+3.3V/2 Inputs > 0 and outputs 0 to 3.3V

It's a little tricky to use a single supply Rail-to-Rail CMOS Op Amp 0 to 3.3V but your above requirements are simply is the ratios of Out/In reduced down to GAIN & OFFSET specs.... to satisfy your "equation" or design specs, "as we say in the biz."

But since the non-inverting gain \$Av+ = 1+ |Av-|= 1+Rf/Rin~~~ \$the Offset must be lower so that gain >1 and the output offset reaches 1.65V= Vdd/2. So the actual R Ratio for offset is not Vdd/2 but \$Vdd/2+3.3V/24V =1.451V\$ results an output offset of the new midscale point @ 1.65V.

enter image description here

  • 1
    \$\begingroup\$ Not sure I understand... \$\endgroup\$ Dec 11, 2019 at 4:14
  • 1
    \$\begingroup\$ I hope I do, but I think Tony might, due to his immense experience, have skipped the significant part where he'd explain that instead of dividing the voltage between your +/-12V source and GND, you could use a voltage divider between some positive reference voltage (here: 1.451 V) and that source, so that (ref voltage + difference/divider ratio) is always positive. \$\endgroup\$ Dec 11, 2019 at 9:38
  • \$\begingroup\$ To get the transfer function of any analog level shifter you must compute gain & offset by \$\dfrac{Vo_{(max-min)}}{Vi_{(max-min)}}\$ & the average difference of Vo-Vin = 1.65-0. But with non-inverting offset amplified by 1+Av- the ratio for offset must be reduced by that gain.. If the gain was +1 simply from +/-1.65 to 0 to 3.3 then the V/2 offset with unity gain is all you need. capiche?? This makes it possible to use a single supply Op Amp but only if it is the CMOS type that goes rail to rail. Can you follow the scope traces Vi, Vo? with displayed min,max \$\endgroup\$ Dec 11, 2019 at 14:44
  • 1
    \$\begingroup\$ Never Be afraid to ask ..but always explain, which part you understand , and where you are stuck. \$\endgroup\$ Dec 11, 2019 at 14:50
  • 1
    \$\begingroup\$ No the LM358 is BJT, you need a CMOS type digikey.com/products/en/integrated-circuits-ics/… \$\endgroup\$ Dec 11, 2019 at 17:18

Many ESP32 boards have a 220K+100K divider on the input of the Expressif chip itself. The chip itself reads 0~1V approximately from the internal reference.


simulate this circuit – Schematic created using CircuitLab

If your board has the divider you just need to add R1 in series with the +/-12V input and R4 to the +3.3V rail. No need for any op-amps. I've chosen standard E96 values that yield a voltage range just inside the 0-1V range nominally.

If you need to read a slightly larger range, you can re-calculate the values easily with Ohm's law and a bit of algebra.

To find this solution I just strategically picked two points- 0V out and 1V out, for -12in and +12 in respectively. R2 and R3 are are assumed to be 220K and 100K respectively. Any two distinct points will work but the 0V simplifies things.

For +12 in the current through R3 is 10uA (since the voltage across R3 is 1V) so the voltage at node (a) is 3.2V. So we have:

(1) (12-3.2)/R1 + (3.3-3.2)/R4 = 10uA

For -12 in there is no current through R3 (or R2) (because the output voltage is 0V) so we have:

(2) 3.3V/R4 = 12V/R1

That's two equations in two unknowns so it can easily be solved.

R1 = (3.3/12)R4 and substitute into (1) to get

R1 = 916.4K and then R4 = 252K

Fiddle with standard E96 values to get something that works.

That's the design procedure. If you want to calculate the output values, you can use superposition. With 0V in the output is

Vout= (100/320)(3.3V/R4)(R4||R1||320K) R4||R1||320K is 123.1K in the E96 design.

So Vout = 0.498V (Ideal would be 0.500V)

The change due to 12V in (if the 3.3V was 0V) is

\$\Delta\$Vout = (100/320)(12V/R1)(R4||R1||320K) = 0.495V (Ideal would be 0.500V).

So the ADC input voltage should be 0.003V at -12V in and 0.993V at +12V in.

Or, alternate method simply write the equation for the output voltage by inspection:

Vout = (R3/(R1+R3))((Vin/R1)+(3.3V/R2))(R1||R4||(R2+R3)

  • \$\begingroup\$ I had thought of using a voltage divider but the input signal comes from a sort of complex voltage divider already. I have no control or guarantee of the values of the resistors used and so I decided to buffer the output and be done with it. \$\endgroup\$ Dec 11, 2019 at 23:03
  • \$\begingroup\$ If you need a true high impedance input (the one I show is about 1M\$\Omega\$) then you will have to have a buffer and that buffer amplifier will need a +/-12V supply or better. There are a few rail-to-rail amplifiers that will work at those voltages, but it would be better to have something like +/-15V then you could use a cheaper amplifier. Preceding the above circuit with a buffer will work and will yield G\$\Omega\$ input resistance. \$\endgroup\$ Dec 11, 2019 at 23:30
  • \$\begingroup\$ Your initial proposed circuit has an input resistance of 22K, about 50x lower than my unbuffered circuit. \$\endgroup\$ Dec 11, 2019 at 23:44
  • \$\begingroup\$ Good point... I'm going to try simulating your idea. \$\endgroup\$ Dec 12, 2019 at 0:00
  • \$\begingroup\$ Could you run me through the math on this? I've used kirschhof's laws on it and I can't seem to get an answer... I might need to go to bed.. \$\endgroup\$ Dec 12, 2019 at 1:16

If you're trying to sample from a +/-12 modular synth I would suggest using +/-10v as input limit. it's more then enough for most applictions and easier to scale with CV conventions. here is an example for +/-5 v to 0-3.3v (op-amp is 0-3.3v): enter image description here


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.