• Welcome to Redshift Project Depot.
 

voltage divider for measuring voltage; current limiting resistors for LED

Started by Louis L, December 16, 2017, 03:53:47 PM

Previous topic - Next topic

Louis L

During the development of the rev 2.1 Fleetbots, I had an email exchange with Kyle on the use and implementation of a voltage divider and subsequent measuring of that voltage on the Arduino. Below is that email exchange with some edits. This is useful for people interested in electronics and the application of concepts like Ohm's Law. Note that the underlying purpose of the exchange is to educate and explain; not just tell what to do.

Me:
   
The 2K resistors are meant to be used with the analog inputs to measure the battery voltage.
The 150 ohm resistors are meant to be used as current limiting resistors for the LED's RGB anodes.

See if you can figure out how the above resistors will be used !


K:

I was able to measure the voltage of a 9V battery with the Arduino, using 1 analog input pin and ground. It requires (for what I was using) a 100k Ohm and a 1M Ohm resistor to measure the voltage. The tutorial I was using says that this can go to 50V before it can damage the Arduino, which is unnecessary for what we're doing, but I don't know how to change this and still have the circuit work. It seems to work well, considering it is very close to the readings on my multimeter, and works with a battery connected to anything else in the circuit, as far as I can tell. If we were to use this method on the Fleetbots, we would also need to connect an additional wire to the + and - terminals of the battery, in addition to the clip.
Source: https://startingelectronics.org/articles/arduino/measuring-voltage-with-arduino/

Me:

Since you've already done this, I'd like you to take some time to understand what you're doing and not just do it. This way you get to learn something, which will then help you be able to design something. Without understanding things, you're just blindly copying.

So here's lesson 1.

So go to that web page you provided and look at the circuit with the 2 resistors under "Voltage Divider Circuit". I took a quick read and it's doing pretty much what I want to do only with different values for the resistors. So the question is - what dictates the values of the resistors? How important are they?

First off, notice I got 1% resistors (the article mentions them later under "calibration"). We can't calibrate our design because we want to install the same code in each robot without worrying about the specific hardware. So what does 1% mean? All resistors are rated by 3 main features (there are others but not important here) - resistance value measures in ohms, power handling rated in watts and tolerance rated in percent. The % just says how close or away from the actual value this device can be and still be considered good. So a 100 ohm resistor with a 5% tolerance is good from 95 to 105 ohms. Cheap carbon resistors can be as far off as 5, 10 or even 20 %! So a 1% resistor is very accurate, down to 1 part in 100.

The 2 resistor circuit (also called a "network") is in the classic "voltage divider" appearance. This network is connected top and bottom to +V and -V (or ground). You'll see this in the diagram as a connection to the battery. The total resistance is 1.1 M-ohms (1M + 100K). Now imagine that the 1M resistor was really ten 100K resistors (10 x 100K = 1M). There would be a total of eleven 100K resistors. As the electrons from the battery goes through each resistor there will be a voltage drop across each. Kirchhoff's voltage law applies here and it says that the sum of all the voltages (including the battery) equals 0. In other words each of the 11 resistors will have a voltage drop such that their sum is equal to that of the voltage on the battery. This makes perfect sense in an intuitive kind of way.

I had you break the the 1M into ten 100K resistors to make things easier to visualize. With 11 now identical resistors, it makes sense to believe that each resistor, being equal, will have the same voltage drop. Since there are 11 and their sum must equal the battery we know that each resistor has a voltage drop equal to 1/11 of the battery. The point of measure is after the first resistor (R2) so it's just 1/11 above ground (0V). This is therefore 1/11 of V-battery. You'll notice that they say this is a divide-by-11 circuit. Or put another way, the voltage measured by the input pin A2 is equal to:

     (R2 / (R1 + R2) ) * V-battery

Notice that the resistors form a ratio so they have no units and the end result is a unit in Volts.

So where does the 50V max in the web page come from ? Well the arduino can measure up to its input power supply voltage of +5V. If the input test voltage is divide by 11, it can theoretically handle a test voltage up to 55V and still work. Above that the input is too high to be read.

Does this mean that we can use this circuit as-is? Or should we change it? Given what I've told you so far, what do you think?

K:

It seems as if as long as R1 and R2 are in a 10:1 ratio, then  it will work for up to 55V (for Arduino's 5V), and if it is in a 2:1 ratio, it will work up to 15V. So, according to this, very small resistor values will do, as long as they are in the correct ratio. Is the ratio the only thing that matters in voltage divider circuits?

Me:

You're right. The ratio is what guides the divider. So the 2 things that are important are the input range of the arduino (0 to 5V) and the input voltage you're trying to measure.

On the forum I suggested that we be able to measure the 2 voltages at possibly different max values.
For the logic, the max is 12V because that's what the arduino can endure.
For the motor, the max is 9V because that's what you'll get if you put 6 x AA alkaline batteries (by accident) into the holder. Actually this would be closer to 10V with fresh alkalines (each alkaline AA over 1.6V when new)

So what divider ratios would you use for the 2 inputs?

Notice that we're only talking about ratios. We haven't talked about the actual values themselves. That's lesson 2 :)

K:

For logic: 7:5
For motor: 4:5 (1:1 if 10V max)

Me:

The ratios you gave me would maximize the input range to the arduino measurement range. From a resistor point of view it's overkill. We can simplify this somewhat like this:

For logic: 1/3 divider which means a max of 12V becomes 4V at the AIN (analog input).
For motor: 1/2 divider which means a max of 9V becomes 4.5V at the AIN (or 1:1 as you put it).

So how do we decide what is appropriate and what resistor values to use?

lesson 2 - resolution

The Anglog Input (AIN) on the Arduino delivers a 10 bit measurement result. That's 2^10 or 1024 different values. In practice, this means (best case) you get 9 bits of data and 1 bit of noise. In other words, the Least Significant Bit (LSB) is questionable. Think of it this way - a 10 bit value looks likes this:
  BBBBBBBBBX
where each 'B' is a bit (a 0 or a 1). The last bit is marked as 'X'. It is the least significant bit of the 10 (it represents the one's column). When taking a measurement, it's the one bit that is most likely to be wrong because it can waver between a 0 or a 1. It's like taking a multimeter and measuring a battery and seeing the least significant digit moving around a somewhat.

So let's say we do have 10 bits of resolution (we ignore the LSB error) what we have is this:
0000000000 = 0V input at AIN
1111111111 = 5V input at AIN
This adds up to 2^10 or 1024 different measurement values. Do the math and (assuming the Analog to Digital Converter or ADC is operating linearly) you see that each measurement has a resolution of

5V / 1024 = 4.88 mV or 0.00488 V

That is to say the best we can hope to measure is in 4.88 mV increments.

Keep in mind that when I say "5V" I really mean whatever the voltage regulator on the Arduino is delivering. On the Mega 2560, this is an ON Semiconductor NCP1117 and it is rated to deliver between 4.9V and 5.1V or 2% error. For now we'll assume it's 5V.

Now let's go back to our AIN and voltage divider. If we were to use a divide-by-11 network and we tried to measure a 6V motor battery pack, we would measure

6/11= 0.5454 volts at AIN.
Divide 0.5454 / .00488 = 111 (truncated).

This means that of the 1024 discrete measurement we can take, we'll only be using 111 of them max. We've wasted the other 913 (from 6V to 55V). Now if we take the 6V input and divide again we get:

6V / 111 = 54 mV

So the best we can do is measure the 6V battery pack in increments of 54mV. This is of course 11 times worse than the 4.88  mV native resolution of the ADC.

So hopefully it's clear and obvious that we want to take the entire input range and map it to the 0-5V AIN range of the Arduino ADC in order to get the best actual measurement resolution. Above, I suggested a divide by 3 and divide by 2.

For logic - we use a 9V battery. If it's an alkaline, it'll start out at about 9.5 before dropping quickly. If it's a LiOn, it's really about 8 before settling to 7.4 Let's assume it's 9V.
Our system resolution is 3x worse than without a divider so we have

4.88 mV * 3 = 14.6 mV

For the motor - we can divide by 2 which gives a resolution of

4.88 mV * 2 = 9.76 mV

Are these enough for what we want/need?

For the motor battery we're using NiMH batteries. Here's a PDF that shows a typical discharge curve:
http://data.energizer.com/pdfs/nickelmetalhydride_appman.pdf
You can see that it levels off at 1.2V with a slight taper. At the end of life, it drops sharply. This curve will change under load - when the motor is running.

LiON has a different shape on its curve.
http://batteryuniversity.com/learn/article/lithium_based_batteries
It's less flat so it's easier to predicts when it'll die. Again this varies with load.

We should be able to get a decent measurement of the battery from both of these dividers. Even a 14.6 mV resolution is more than enough from LiOn since it drops off more sharply than NiMH.

By the way, if you look at the discharge curve of alkaline batteries, you'll see why they make very poor batteries for motors.

So if you had to implement a divide-by-3 and divide-by-2 from the parts I got (2Kohn 1% resistors) how would you do it?

K:

Would it be this?
1/3: R1= 2 resistors, R2= 1 resistor
1/2: Both= 1 resistor

Me:

Yes, using multiple resistors would be one way to get the ratios we want. But there's yet more to consider.

Lesson 3 - current draw and noise.

Let's look at the divide-by-3 case. We effectively have a 4K and 2K resistor in series (where the 4K is made from 2 x 2K). This means that there is 6K ohms connecting 5V to ground all the time. Current is traveling through those resistors whenever power is on. How much power? By ohm's law we have:

  5V / 6000 ohms = 833 microamps (0.833 milliamps) or
  5 * 5 / 6000 = 4.17 milliwatts
 
So our resistor must be rated for at least that much power (this is not a problem for discrete resistors like the ones I bought).
If we increase the resistance but maintain the same ratio (ex: we use 40K and 20K instead of 4K and 2K respectively) we will keep the dividing ratio the same but reduce the current flow and power dissipation. So why don't we?

The Arduino AIN needs to draw some current in order to make its measurement. It can't draw too much current because doing so will affect the very circuit it's trying to measure. The AIN input has a large impedance on the order 100 Mohm when it is not sampling the input. But whenever the AIN takes a sample, this drops. According to the spec, the recommended output impedance of the circuit driving the AIN pin should be less than 10K. This is to allow the internal capacitor in the chip to charge up. Too much impedance and the sampling time increases and the measurement gets noisy. So our 4K/2K split fits nicely within these limits.

So that pretty much wraps up what it takes to decide on the voltage divider network. I bough the 2K resistors because this place sold them in bulk (we need multiples per robot, times 6 robot). I didn't have a choice on the value; it just so happened that the 2K worked out nicely. Oh, and I was looking for 1% resistors. Being able to build a divide-by-2 and -3 from a single part also makes things easier - we don't have to find different values of resistors.

So now we move on to the RGB LED. The ones I bought were also a bulk pack. These are 5mm LEDs. I really wanted to get a jumbo 10mm LED but the smaller ones were cheaper. We need 3 resistors, one for each of R, G and B. I bought 150 ohm resistors.

Is 150 ohms the right value? Is so, why? If not, what is the right value and how do we use the 150ohm resistors?

K:

The equation I found for this was: Resistance = (Supply Voltage - LED Forward Voltage) / LED Current
According to the site for the LEDs you bought, they are 2.4V at 25 mA for the red LED, which has the lowest maximum voltage (blue/green were both 3V). If you plug these values in, with a supply voltage of 5V (this comes from the Arduino), you get 104 ohms. Since this isn't a standard resistor value, you would round up, which I think is where you got the 150 ohm resistor. Is this right?

Me:

Your equation is right. Let's make sure you understand what it says before we go any further.

Let's go back to Kirchhoff's law. We have a diode (LED) and a resistor in series that's effectively between 5V and ground. So the sum of the voltage drops must equal 5. The forward voltage drop defines the portion for the LED (2.4V for red) so the rest must go to the resistor (2.6V). Diodes are semiconductor devices that allow electricity to flow in one direction and not in the other. In the case of an LED, it also happens to emit some light. Given the opportunity, the diode will let pass a lot of current; more than is good for it. So the resistor used here is called a current-limiting resistor. It will protect the diode.

The 25mA rating on the diode is the max value. Most of the time, we don't run it close to max. So we pick a desired current and apply Ohm's law. For the max of 25 mA we have:
  2.6V  / .025 A = 104 ohms.

What this spec doesn't give (some others do) is the relative brightness of R, G and B.

So we want to experiment a bit and compare the relative brightness of the 3 colors. Then we'll play with resistance values until we get colors that look decent. The 150 ohm resistor lets us come close to common values used for LEDs. We can get 150, 225 and 300 pretty easily. Those 3 values should suffice but if we need others I have some resistors at home I can bring in.

One last thing. The Arduino's output can drive only 20 mA so even though our LED can handle 25 mA, our real target is to be inder 20 mA.

So that's sums it up. We'll run some experiments when the parts arrive.

Louis L

I did leave out a few things in the previous long post that I should at least mention.


       
  • I had mentioned that the LSB of a measurement has some uncertainty associated with it. If we take this into account, our 10 bit ADC is really more a 9 bit ADC. Our resolution is cut is half - with only 512 measurements between 0 and 511. Do the math and our effective 29.2 mV for the divide-by-3 and 19.52 mV for the divide-by-2 circuit. Is this ok for our needs? Well that depends on what we're trying to accomplish. By the way, I'm dropping the LSB to show that a measurement has some uncertainty. There are ways to calculate the effective number of bits in the measurement but it's outside the scope of this discussion.
  • As noted, the Mega's onboard regulator is good for 2% (4.9 to 5.1 on the 5.0 V supply) accuracy. This raises or lowers the ceiling on the measurement of the ADC and therefore changes the accuracy of the measurement by the same 2%. So (from above #1) 29.2 mV at 2% variation is +/- 0.58 mV. Likewise 19.52 mV at 2% is +/- 0.39 mV
  • In actual use, the power supply voltage will fluctuate with demand from the robot. The motor supply will waver the most - as motors draw current, the voltage will sag a bit. If we measure all of the supplies continuously at regular intervals, we may find readings all over the place depending on what the robot is doing. This is the greatest level of inaccuracy that swamps items #1 and #2. Even the 5V supply on the Mega which is only used for the logic will dance around when the robot is driving. It will try and stay within its 2% range unless the 9V battery dips below about 6.2V (1.2V dropout).
  • So this brings up the questions - when is a voltage reading useful? If we know that voltage sags will occur, are they a bad thing? And if the voltages return to "normal" (whatever that is!) when the motors are not running, does that mean the battery is ok? Is there a way to average out the voltage readings over time? Or do we only read voltages when the motors are not running? Or do we just have a low floor value and if a reading fails to meet that floor, we raise a flag for awareness? How much historical data to we save? How do we take the inaccuracies of a voltage reading into account? There are a lot of possibilities here and it's up the the developers to decide what to do!