which optocoupler to read battery voltage?

Hi,

For a battery stack monitor, I want to use opto coupler to read each battery voltage, as was suggested elsewhere.

But I am not sure which one to use, or if this even possible. I want to read a range of 1-100V, with an ESP8266 and MCP3208. Using a voltage divider with a 33K:1K ohm resistor gives me 2.9411V on the output side. I only have resistors to bring down 1000V or 100V to 3V right now.

This now leads me to a conundrum: With that voltage divider, 12.5V input leads to 0.367V behind the voltage divider. This is too little to drive an optocoupler.

So, how does one use an optocoupler to measure high voltages, down to a level than an MCU ADC can read it? The 4N35's I have in stock have a startup voltage of 0.9V

RudiAhlers:
Hi,

For a battery stack monitor, I want to use opto coupler to read each battery voltage, as was suggested elsewhere.

But I am not sure which one to use, or if this even possible. I want to read a range of 1-100V, with an ESP8266 and MCP3208. Using a voltage divider with a 33K:1K ohm resistor gives me 2.9411V on the output side. I only have resistors to bring down 1000V or 100V to 3V right now.

This now leads me to a conundrum: With that voltage divider, 12.5V input leads to 0.367V behind the voltage divider. This is too little to drive an optocoupler.

So, how does one use an optocoupler to measure high voltages, down to a level than an MCU ADC can read it? The 4N35's I have in stock have a startup voltage of 0.9V

One doesn't and can't use an optocoupler to measure any voltage. They are primarily used to pass signals while keeping circuits isolated from each other.

Paul

Paul_KD7HB:
One doesn't and can't use an optocoupler to measure any voltage. They are primarily used to pass signals while keeping circuits isolated from each other.

Paul

Hi Paul,

What signals do they pass? Or why would some people say use opto couples when for measuring high(er) voltage circuits?

Paul_KD7HB:
They are primarily used to pass signals while keeping circuits isolated from each other.

True. So, create a signal that is proportional to voltage. Typically this is done with a Voltage Controlled Oscillator [VCO]. A very inexpensive VCO that works quite well, is contained in a CD4046 Phase Locked Loop [PLL].
Feed your voltage divided voltage into the VCO IN pin and then drive the OptoCoupler with the VCO Out [the phase detectors go unused in this scenario]. What you will get is a linear relationship between voltage and frequency. Use one of the timers, in an Arduino, to count pulses per some time period. The count will be proportional to the voltage you wish to read.

V = kx

Where, 'V' is the voltage, 'x' is the count, and 'k' is some factor that converts counts to voltage.

Example: Say the VCO runs at 10 kHz with 1V on the input, and 20 kHz with 2V in. If the Arduino counts for 100 mS [i.e. a tenth of a second window], then a count of 1,000 is 1.000V, and a count of 2,000 is 2.000V. In this case k = 1/1000 or 0.001 .

If you run the CD4046 at 15V, you'll get a better dynamic range. You could set your voltage sensing range to something like 0 to 14V. Or, how about 0-10V [for 0 - 100V], that way there's an easier conversion. And, I would use a frequency range something like: 1 kHz for 0V to 11 kHz for 10V. Then, subtract 1000 from every count, to get the easy conversion to voltage: A count of 11,000 - 1,000 = 10,000 or 10.000V And, of course, that's really 100.00V. A count of 1,000 -1,000 = 0 or 0.000V. A count of 2,356 - 1,000 = 1,356 or 1.356V which is actually 13.56V. And the formula would be:

V = k(x - 1,000) = 0.01(x - 1,000) = (x - 1,000)/10

To make that division more efficient, use a factor more like:

V = (x - 1,000)/8

That way, you can do a right shift [V = (x - 1,000) >> 3], rather than a time intensive division!

You could power the CD4046 from the 100V source -- as long as 0.5mA, or so, is not too much of a load. Just use the internal Zener, and bias it at a nominal 0.505 mA, then connect the Zener Cathode to VDD [BUT, since that 100V will vary, a little more math is needed to keep that zener biased properly, and to determine if using the Zener is even feasible--as the power dissipation limit of 500mW could be exceeded]. But, since this will run the VCO at around 5V, it will only have around half a milliamp to drive the input LED of the OptoCoupler, so select a sensitive one--not too hard, since the output will be driving an Arduino input, which has a high input impedance. Otherwise, run the CD4046 at 10 to 15V [for optimal linearity -- and better current drive].

You could, also, use the counter to time the period [inverse of frequency]. In which case, the voltage would be inversely proportional to the frequency.

The choice of frequency range will depend on how responsive you want this thing to be -- and, of course, a top frequency capped by the Arduinos limitations.

Be sure to ground all unused inputs on that CD4046.

And, it might be possible to do this with a 555 timer, but the translation of frequency back to voltage might be spooky. But, then, with the right math, anything is possible :wink:

Assuming you really need the capabilities of the MCP3208 (8 channels, 12 bit ADC) -- are you trying to isolate the MCP3208 from your ESP8266, or are you trying to isolate your battery stack from your MCP32028 The first will require four couplers one for each of DIN, DOUT, CLK and ~CS and can be done with just about any coupler like the 4N25. The second will be really tricky if you're trying to hold onto 12 bit resolution.

RudiAhlers:
So, how does one use an optocoupler to measure high voltages, down to a level than an MCU ADC can read it? The 4N35's I have in stock have a startup voltage of 0.9V

Not that you would, necessarily actually do this, but if this were a thing, you do it by converting voltage to current. Thus, the 0.9V concern is moot. And, in this case, you would convert voltage to current, simply, with a resistor. How that would look is, your voltage [100V], connected to a resistor [probably something like: 100V/5mA = 20k and the other end of that resistor connected to the anode of the Opto's LED. And, of course, the cathode connected to ground [the same ground shared with the 100V source].

And, based on this App Note: https://www.vishay.com/docs/83711/appn55.pdf there are OptoCouplers with a very linear transfer function from LED current to Output Transistor current. So, perhaps it is feasible.

See the second answer here for how to get a linear response from an optical isolator operational amplifier - What is the correct way to measure voltage with an optocoupler? - Electrical Engineering Stack Exchange

Note the opto isolators has one LED in it shinning on two optical transistors.

Why not just use a voltage divider? Surely if you are using HV hardware, you have some expensive components. Isn't the cost of an Arduino and a few resistors negligible in comparison? Just make a divider, feed 0-5 v into the Arduino and measure away. That's the whole concept behind "low overhead electronics".

ps, if there was some reason why you require an analog capable isolator, I apologize. Most of the thread was tl:dr.

RudiAhlers:
But I am not sure which one to use, or if this even possible. I want to read a range of 1-100V, with an ESP8266 and MCP3208. Using a voltage divider with a 33K:1K ohm resistor gives me 2.9411V on the output side. I only have resistors to bring down 1000V or 100V to 3V right now.

You need to bring down the voltage more: the ESP8266's ADC input is 0-1V. On the upside it's independent of Vcc which is great for your application.

If you're using a NodeMCU there is a voltage divider on the ADC input so it reads 0-3.3V inputs, but this voltage divider may affect yours as well! You have to keep these resistors in mind when designing your circuit. WeMOS D1 may also have such a voltage divider, I don't know that board well.

Also 100V on 33k+1k would give you a current of 2.9 mA (the 1k resistor is so small there won't be an effect of the NodeMCU divider), and a heat dissipation of 0.29W. That's manageable but for 1000V you have to go for much greater values: 3M3 and 10k would be a good start, also giving you 0.29W of heat dissipated. With all that heat in your components, make sure you have resistors with low thermal coefficient as otherwise the heating up of the large resistor (which takes almost all the heat) will mess up your readings.

ReverseEMF:
True. So, create a signal that is proportional to voltage. Typically this is done with a Voltage Controlled Oscillator [VCO]. A very inexpensive VCO that works quite well, is contained in a CD4046 Phase Locked Loop [PLL].
Feed your voltage divided voltage into the VCO IN pin and then drive the OptoCoupler with the VCO Out [the phase detectors go unused in this scenario]. What you will get is a linear relationship between voltage and frequency. Use one of the timers, in an Arduino, to count pulses per some time period. The count will be proportional to the voltage you wish to read.

V = kx

Where, 'V' is the voltage, 'x' is the count, and 'k' is some factor that converts counts to voltage.

Example: Say the VCO runs at 10 kHz with 1V on the input, and 20 kHz with 2V in. If the Arduino counts for 100 mS [i.e. a tenth of a second window], then a count of 1,000 is 1.000V, and a count of 2,000 is 2.000V. In this case k = 1/1000 or 0.001 .

If you run the CD4046 at 15V, you'll get a better dynamic range. You could set your voltage sensing range to something like 0 to 14V. Or, how about 0-10V [for 0 - 100V], that way there's an easier conversion. And, I would use a frequency range something like: 1 kHz for 0V to 11 kHz for 10V. Then, subtract 1000 from every count, to get the easy conversion to voltage: A count of 11,000 - 1,000 = 10,000 or 10.000V And, of course, that's really 100.00V. A count of 1,000 -1,000 = 0 or 0.000V. A count of 2,356 - 1,000 = 1,356 or 1.356V which is actually 13.56V. And the formula would be:

V = k(x - 1,000) = 0.01(x - 1,000) = (x - 1,000)/10

To make that division more efficient, use a factor more like:

V = (x - 1,000)/8

That way, you can do a right shift [V = (x - 1,000) >> 3], rather than a time intensive division!

You could power the CD4046 from the 100V source -- as long as 0.5mA, or so, is not too much of a load. Just use the internal Zener, and bias it at a nominal 0.505 mA, then connect the Zener Cathode to VDD [BUT, since that 100V will vary, a little more math is needed to keep that zener biased properly, and to determine if using the Zener is even feasible--as the power dissipation limit of 500mW could be exceeded]. But, since this will run the VCO at around 5V, it will only have around half a milliamp to drive the input LED of the OptoCoupler, so select a sensitive one--not too hard, since the output will be driving an Arduino input, which has a high input impedance. Otherwise, run the CD4046 at 10 to 15V [for optimal linearity -- and better current drive].

You could, also, use the counter to time the period [inverse of frequency]. In which case, the voltage would be inversely proportional to the frequency.

The choice of frequency range will depend on how responsive you want this thing to be -- and, of course, a top frequency capped by the Arduinos limitations.

Be sure to ground all unused inputs on that CD4046.

And, it might be possible to do this with a 555 timer, but the translation of frequency back to voltage might be spooky. But, then, with the right math, anything is possible :wink:

Thanx, this explained it very well.

As I want to monitor 16x 12V Lead Acid batteries, connected into 4 banks of 4 batteries to give 48V, this would just complicate my circuit a bit more. But I'll see if I can work these extra components into my budget to try it out.

CurtCarpenter:
Assuming you really need the capabilities of the MCP3208 (8 channels, 12 bit ADC) -- are you trying to isolate the MCP3208 from your ESP8266, or are you trying to isolate your battery stack from your MCP32028 The first will require four couplers one for each of DIN, DOUT, CLK and ~CS and can be done with just about any coupler like the 4N25. The second will be really tricky if you're trying to hold onto 12 bit resolution.

I am only using the MCP3208 for the 12bit resolution. Could have gotten a MCP3202 as well I guess.

So I would like to protect the whole ADC circtuit, including the MCP320x and NodeMCU from potentially dangerous voltage spikes.

ReverseEMF:
Not that you would, necessarily actually do this, but if this were a thing, you do it by converting voltage to current. Thus, the 0.9V concern is moot. And, in this case, you would convert voltage to current, simply, with a resistor. How that would look is, your voltage [100V], connected to a resistor [probably something like: 100V/5mA = 20k and the other end of that resistor connected to the anode of the Opto's LED. And, of course, the cathode connected to ground [the same ground shared with the 100V source].

How would I do this? And how stable / accurate / linear is this approach?

ReverseEMF:
And, based on this App Note: https://www.vishay.com/docs/83711/appn55.pdf there are OptoCouplers with a very linear transfer function from LED current to Output Transistor current. So, perhaps it is feasible.

I got some 4N35 from Vishay which seems like it was rather linear as well

Add a current limiting resistor and clamping diodes (the latter are normally built into the pins already). That will take care of any extreme voltages (the example values are for a 1000V --> 1V divider). These diodes are normally built into the MCU already.
schematic.png

wvmarle:
You need to bring down the voltage more: the ESP8266's ADC input is 0-1V. On the upside it's independent of Vcc which is great for your application.

I don't use the NodeMCU's ADC, but rather an MCP3208 (will probably replace it with MCP3202 in future). I have an ADS1115 as well but couln't get it to work with the resistor divider, so I'm working with the MCP3208 for now. For a stable voltage reference I'm using a 4.095V LM4040 IC and so far I'm very happy with the voltage reading of any single battery.

wvmarle:
If you're using a NodeMCU there is a voltage divider on the ADC input so it reads 0-3.3V inputs, but this voltage divider may affect yours as well! You have to keep these resistors in mind when designing your circuit. WeMOS D1 may also have such a voltage divider, I don't know that board well.

See above :wink:

wvmarle:
Also 100V on 33k+1k would give you a current of 2.9 mA (the 1k resistor is so small there won't be an effect of the NodeMCU divider), and a heat dissipation of 0.29W. That's manageable but for 1000V you have to go for much greater values: 3M3 and 10k would be a good start, also giving you 0.29W of heat dissipated. With all that heat in your components, make sure you have resistors with low thermal coefficient as otherwise the heating up of the large resistor (which takes almost all the heat) will mess up your readings.

Thanx I'll keep that in mind. The resistors I use are all 1%, 0.5W if I can get some, though I'll upgrade to 1W if needed.

wvmarle:
Add a current limiting resistor and clamping diodes (the latter are normally built into the pins already). That will take care of any extreme voltages (the example values are for a 1000V --> 1V divider). These diodes are normally built into the MCU already.
schematic.png

I don't use the NodeMCU's ADC, but an MCP3208 instead.

Which diodes would you recommend in such a case?

From the MCP3208 data sheet:

All inputs and outputs w.r.t. V SS ............... -0.6V to V DD +0.6V

This suggests that clamping diodes are built in - they typically can handle continuous current of up to 1 mA or so, make that 0.5 mA to be safe. Peak currents can normally be higher (by 10-20 times or so for a few ms) without doing damage.

Your input voltage must be really large to have the input go so high that it damages the chip. That 10k resistor means you need 10V for 1 mA, and that's after the voltage divider. By the time your chip gets fried, those resistors will be on fire :slight_smile:

If you really want to add diodes: just about any type will do. Fast switching preferably, such as the 1N4148, or a Schottky type to make sure it will conduct before the built-in diodes start to conduct.

wvmarle:
From the MCP3208 data sheet:This suggests that clamping diodes are built in - they typically can handle continuous current of up to 1 mA or so, make that 0.5 mA to be safe. Peak currents can normally be higher (by 10-20 times or so for a few ms) without doing damage.

Your input voltage must be really large to have the input go so high that it damages the chip. That 10k resistor means you need 10V for 1 mA, and that's after the voltage divider. By the time your chip gets fried, those resistors will be on fire :slight_smile:

If you really want to add diodes: just about any type will do. Fast switching preferably, such as the 1N4148, or a Schottky type to make sure it will conduct before the built-in diodes start to conduct.

This does give some comfort, but what other protection would be necessary? As far as I understand it, zener don't have a linear scale?

RudiAhlers:
...But I'll see if I can work these extra components into my budget to try it out.

The CD4046 is 55¢US @ Mouser: https://www.mouser.com/Semiconductors/Integrated-Circuits-ICs/_/N-6j73k?P=1y95odoZ1z0z63x&Keyword=4046&FS=True
45¢US at Jameco: https://www.jameco.com/z/CD4046BE-National-Semiconductor-Phase-Comparator-16-Pin-PDIP_817951.html?CID=MERCH

But, ChrisTenone makes a good point. Why, exactly, do you feel the need for Isolation?

RudiAhlers:
I am only using the MCP3208 for the 12bit resolution. Could have gotten a MCP3202 as well I guess.

So I would like to protect the whole ADC circtuit, including the MCP320x and NodeMCU from potentially dangerous voltage spikes.

In that case, if it were me, I'd take a close look at the solution ReverseEMF pointed to in the app note https://www.vishay.com/docs/83711/appn55.pdf. Fig.7 there is pretty impressive, and should help you hold onto that 0.01 - 0.02V resolution at 48V you need over temperature. You're going to need to isolate the opamp power somehow though, perhaps taking it from the batteries themselves.

The circuit I gave you should give protection from spikes of 10-100 times the rated battery value. By the time the 10k resistor lets though so much current the diodes can't help, the voltage will be so high that sparks may start flying. The moment a voltage is great enough to start sparking all bets are off, but why would you even get that kind of spikes from batteries? Are you at risk of lightning strikes?