ESR meter with Arduino

@nurbit

If you have time and will follow the link at the start of the topic to dr. Le Hung's page from where I got the original schematic you can find some good information on how this ESR meter works.

Until then I will try to explain in a few words some basic things that will help you understand why some components are used. To calculate the ESR we use ohm's law for which the formula is V = I * R, for us the ESR is represented by the R from this equation, thus R = V / I, now we have to get these two values from somewhere so we can compute a result.

For this we setup a circuit which will connect the DUT to a [u]known current[/u] that in turn will produce a [u]voltage drop[/u] on the DUT which we can measure through the analog pin of the arduino, depending on the resistance (esr) we need to measure we might need different current values, the sketch implements just the 50 mA branch, a 5mA branch is available on the schematic and can be easily used switching to the proper pin for higher ESR measurement (in case of lower value capacitors, let's say 10uF and smaller) thus it can be implemented as an auto-range function.

How we obtain the constant current: For a 50 mA current we have: (I = V / R) = 5 / 100 = 0.05 A. Values are from: for Vcc = 5, this is supplied by the arduino's on board voltage regulator and R = 100 (obtained from R8 + the resistance of the transistor at saturation which should be very close to 0 ohm, thus 100 ohm). [u]So the reason to use low tolerance resistor in the current circuit is to ensure the value of the current is exactly as expected and calculated.[/u]

The 1 k ohm 1% resistor (R4) branch can give us a current of 5 mA (I = V / R) = 5 / 1000 = 0.005 A. I have to mention that the 5 mA current is not implemented in the sketch, so you can leave it out for now, this is necessary if you want to measure higher ESR or higher value resistors.

Some more things about the way we measure: we need to pulse the DUT with a very short pulse so that the capacitor we are measuring (especially if is a lower value) will not have time to charge and mess up the reading, plus charging and discharging fast is needed so that we measure the capacitor with a frequency as high as possible so capacitive reactance will be negligible (this is the reason I tried to speed up the analog read by changing the prescaller).

Conclusion: you can use 5% resistor (you can try to calibrate the device from the variables in the sketch), I guess the A1015 should be good too for a 50mA current, give it a try and see what are the results :)

Hi szmeu

Thanks for that explanation... it did help. I haven't yet studied the link you supplied but I will do after posting this :)

Your explanation has made things MUCH clearer as to why you've shoen the parts you have. I'll go and put the circuit together and get some new parts ordered so that I can replace my alternative parts when they arrive.

Thanks again for the explanation and your time.

Is the updated sketch posted here still updated to the posted schematic? Except for the ESR pin which is A0, the pulse pin does not seem to match the schematic based from the sketch.

Will this ESR work in circuit? What is the output voltage P-P? Thanks!

@alyas You are right, for the sketch to work with the schematic you should edit the define lines (I updated the sketch also):

//define the input and output pin we will use
#define DISCHARGE_PIN 7
#define ESR_PIN A0
#define PULSE_SMALL 8 //this is not used in the sketch, implement it as needed (for 5mA current needed for smaller cap value measurement)
#define PULSE_PIN 9
#define BUTTON_PIN 0

and for the lcd use pin 5, 6, 10, 11, 12, 13 as in schematic.

@bseishen Yes, this should work in circuit, voltage P-P should be 300mV (max permited by antiparalel Schottky diodes.)

Thank you for sharing your ESR with Arduino, nicely done.

You said "The DUT should be connected to CN1 between GND (pin3,pin4) and pulse and AIN0 (pin1,pin2) using a setup with four wires." I am assuming that you would attach/solder probes to use for testing, but to which wires? (you have four).

Thanks.

@qz9090

To be honest I did use only two wires to the DUT and worked well (one wire from gnd and only one wire from AIN0 and pulse, this means that on CN1 you tie together pin1 and pin2 thus resulting the point of connection for the probe), for more accuracy a four terminal sensing should give better results, you can read more here http://en.wikipedia.org/wiki/Four-terminal_sensing

:)

Thank you for sharing your excellent circuit and code. I made a PCB from your circuit image and used 2n2222 & 2N2907 transistors and 1% resistors. I didn’t have a non-polar cap, so I soldered the anodes of two 100uF caps together. As a test, I tried adding parallel diodes to the caps, but found they made no difference in my readings. On a pair of used 2200uF 10V caps I got 0.0 Ohms on one that looks good, and 5.600 Ohms on one with a slight top bulge, so it finds bad caps.

The problem I am having is that I am unable to calibrate it. Using a one Ohm resistor I had to set “double current = 0.007460;” to get the meter to read 1.012, but then a 1/3 Ohm resistor reads .090. Could the transistors or DIY capacitor cause this? I'm a beginner, so your post was highly educational and I got a new test tool as well! Thanks again.

Ron

@ronx I think [u]I made some mistakes in my sketch and assumed wrong how the original circuit worked[/u] when reverse engineered Lee Hung's schematic. I assumed it was a constant current circuit, which as I see it now it is not. The formula used in the sketch thus will not give correct results, funny thing is when I tried it by measuring different value resistors, readings were pretty sound. I currently don't have the possibility to test the following but if you have time please replace the formula and post back if this works better.

As I see it now in the circuit we have a voltage divider (see Wikipedia article on this http://en.wikipedia.org/wiki/Voltage_divider) (from there we get the formula for calculating Z2 = (Vout*Z1)/(Vin-Vout))

replace this line

esrVal = (miliVolt)/current - esrCal;//calculate ESR in miliOhm

with this

esrVal = (miliVolt*100)/(4.9-miliVolt);//calibration should be done by changing the value of 100 (This is the 1% reference resistor) and/or changing the 4.9 value which is the Vin and it is given by the the voltage regulator on the arduino board

When I have a litle spare time I'll test it.

Greeatings

Thanks for the reply szmeu. I did find the problem, and it was me... I checked my circuit and for R8 (on the PCB) and found 1 Ohm rather than a 100. I must have put my 1 Ohms and 100 Ohms in the same bag last time I cleaned up ;-) After the fix I calibrated using the original code until I got 1001 on a 1 Ohm resistor. The 1/3 Ohm reads 363, and a 10 Ohm reads 4450 (it's all I have to test with). Am I correct in assuming this pretty accurate and the 10 Ohm is just too big? I tried the voltage divider modification, but it gives negative numbers (-112 and -143). Thanks again for the great code, and sorry for the confusion. I think this is an extremely useful tool and have built both an arduino shield and a self-contained ardweeny powered meter housed in an old external hard drive case.

Regards, Ron

@ron

I’m glad you found the “bug” in your circuit and managed to get better readings, I will answer to your questions now:

  • your assumption are right, with the 100 ohm branch max reading is around 6 ohm (R = U/I) = 0.300/0.05 = 6 ohm (0.300 is max voltage allowed by schottky diode 1N5822), if you need more range there is R4 branch with the 1k ohm 1% resistor (on D8), (you can implement this in the code and can have upper range that will give you the range of the 100 ohm resistor X 10, I think the same way a lower range could be implemented with a proper transistor that can source 500mA of current through resistor of 10 ohm 1%).
  • you mentioned in your first post that did not use the diodes, I just want to explain now the role of the two groups of diodes, the first group of antiparalel 1N5822 diodes is to allow in circuit measurements, this diodes assure that we will get max 0.3 V on the probes and will not damage components on the board, the second group of diodes 1N4004 are there to protect the input of the Atmega from charged capacitors, good practice is to discharge caps before measurements.
  • 65536 comes from 2^16(using oversampling in code we can have a mapped value between 0 and 65535), if we would take a simple measurement on a AIN pin we would get a 10 bit result which is 1024, but as we are enhancing our reading we get a 16 bit result that needs the proper scaling, thus dividing it by 65535, see http://arduino.cc/en/Reference/AnalogRead.

I wonder where I am wrong with the voltage divider formula, I currently don’t have the hardware assembled and no possibility to test it, if you have spare time and in mood please try the following (would be nice to get better results from this simple hardware):
I think the problem comes from mixing Volts with mVolts in the formula I gave you, probably the reason for negative numbers too, display on your LCD the value of miliVolt and see the representation for a known resistor, say 1 ohm, this should be around 0.05 V or 50 mV:

if milivolt (not good)
esrVal = (miliVolt*100)/(4.9-miliVolt) = (50 * 100) / (4.9 - 50) = 5000 / -45.1 = -110

if volt
esrVal = (miliVolt*100)/(4.9-miliVolt) = (0.05 * 100) / (4.9 - 0.05) = 5 / 4.85 = 1.03 ohm

I have to say it’s great to have someone to help testing and give feedback, otherwise it gets boring and can lose interest.

Thanks and glad if I could help :slight_smile:

That's it! With "esrVal = (miliVolt * 100)/(4.9-(miliVolt/100)); " I get 339 on the 1/3 Ohm resistor, 987 on the 1 Ohm and 6582 on the 10 Ohm. My 10V-2200uF good-cap, bad-cap pair now read 21 and 3774 respectively. Perfect! I didn't mention the diodes in my first post as they are the same as you used. I just wanted to verify your PCB works, as do homemade non-polar caps and 2N2222 / 2N2907 transistors.

This is such a useful tool; and so cheap and easy to build. I really hope others build this, make their own modifications, and post their results. If the arduino has enough processing power it would be great to have an audible tone to check caps without looking at the LCD. When I have more time I hope to learn how your code works and make the circuit in Eagle Cad so I can experiment. Thanks again for posting this great project and all your help.

Hi,

I'd like to build this project but I don't seem to get the thing about the four wire connection to the DUT:

Why use four wires to connect a capacitor that has only two wires? Why not connect pin1 and pin2 of CN1 directly? I've seen other esr meters that use very short wires to connect to the DUT, is this something about wire capacities or something of this kind?

Also, in the original schematic by Le Hung there is an additional BS170 mosfet in the circuit, could anybody clear up what that is about?

I know how a esr-meter works in principle, but this really puzzles me.

Cheers,

Ali

Hi there, 1. You can use 2 wires no problem, no need for the 4 wire setup to understand why initially proposed that setup read back as I explained in a previous post. 2. The schematic that uses BS170 is a newer one, version 4.0, the esr meter presented here is based on an older schematic version 3.0 from lee hung. I see the new version has a bunch of modifications compared to ver 3.0. I guess the adition of see it BS170 would be to discharge the cap. If you build the esr meter with Arduino read the post on this thread as you will find answers and some important modifications to the code.

Restecp ;)

I've built the circuit on a breadboard and it works fine. But for production use I'm aiming at eliminating the whole arduino and building a board with a stand alone atmega 328.

The problem is, I can't really decide on how to build the power supply:

I understand that a clean supply voltage is crucial, so just hooking up a 4*AA-battery-pack is out of the question.

But do I have to power the circuit with 5V or will 3.3V also work (with some adjustments to the code, of course)? And if so, can I use a switching regulator instead of a linear one? The Arduino as well as other ESR-meter-projects (including Le Hung's) use linear regulators, so maybe using a switching regulator might not be a good idea, because of the ripple it might introduce. Then again, maybe this issue could be addressed with a few caps..

Any input on this is appreciated!

Cheers,

Ali

Can anybody repost zip file from first post in this topic?

Here it is

esr_meter.zip (131 KB)

I can't download any attachment from the forum, that's why I've asked for a repost :). If you can host it somewhere online, I would be thankful.

I get a "Error 503 Service Unavailable" if I try to download the file from the forum...

Hi all, A few weeks ago I was looking for an ESR meter to build and ran across this thread. Thank you szmeu! I have built this up and it works very well. I just wanted to share some observations. First, the hardware is a great circuit, simple and effective. Thanks again. And the circuit is very tolerant of the non-polarized capacitor value (47microFarad in the original). I used a 10micro I had and it works fine. Second, you are correct that the pulse is not from a current source and what you want is to calculate as a voltage divider. (BTW, the original code will get you close enough to serve the purpose, especially at low values of ESR.) Let's say that Vin is your source voltage (near 5V here), Vout is the value between the two resistors (you measure that at AIN0), Rs is the upper resistance (the 100 Ohm resister) and the lower resistance, the ESR, we'll call Rm. The formula is given as follows. Rm = Rs / ((Vin/Vout) - 1) It is important to not mix units, so here is an example. Say your AIN0 measurement, 'milliVolts' variable in the code, is 20. So, Vout is 20mV. Using the value of 5V for the source voltage, Vin, we need to express that in millVolts because that's the unit we're using for Vout. So, Vin is 5000mV. Rs is 100 Ohms so the result will be in Ohms. Rm (in Ohms) = 100 / ((5000/20)-1) = 100 / 249 = 0.402 Ohms To get milliOhms, multiply times 1000 or 402 milliOhms!

Here is my re-write of the ESR calc routine. This combines the oversample routine with some things were outside in the original code. A couple of lines are re-ordered. The big calculation difference is at the end.

// ESR calculation routine
// discharge, start a current pulse, measure the voltage at the ESR_PIN, stop the pulse
// repeat 4096 times and average the results ('oversampling and decimation')
// refer to Atmel Application Note AVR121: 'Enhancing ADC resolution by oversampling'
// http://www.atmel.com/images/doc8003.pdf
double calcESR()
{
  unsigned long accumulator = 0;
  unsigned int sample = 0;
  int i = 0;
  // oversampling 4096 times (for 16 bit is 4^(desiredResolution - ADCresolution))
  while ( i++ < 4096 )
  {
    digitalWrite( DISCHARGE_PIN, HIGH ); // discharge the capacitors
    delayMicroseconds( 600 ); // discharge wait time
    digitalWrite( DISCHARGE_PIN, LOW ); // disable discharging
    cli(); // disable interrupts for the pulse measure
    digitalWrite( PulsePin, PulseActive ); // start current pulse
    delayMicroseconds( 1 );
    // on the scope it appears that after enabling the pulse
    // a small delay is needed for oscillations to fade away
    sample = analogRead( ESR_PIN ); // read ADC value
    sei(); // measured, enable interrupts
    digitalWrite( PulsePin, ! PulseActive ); // stop current pulse
    accumulator += sample; // accumulate
  }
  // sampling is done
  esrSamples = accumulator >> 6; // decimate the accumulated result
  // calculate voltage on AIN0 pin...
  milliVolts = (esrSamples * vRef) / 65.536;
  // calculate ESR in milliOhms...
  double Rm = Rs / ((Vin / milliVolts) - 1); // Rm is in Ohms
  return Rm * 1000; // milliOhms
}

This now consistently measures my 0.1 Ohm and 1 Ohm precision resistors within about 2%. And a 4.7 Ohm resistor reads 4.68. Super!

BTW, I used all those extra pins on the Arduino to drive a 3-digit, 7-segment display. (That's why the code above has interrupt disable/enable calls to protect the pulse measure from the display multiplex interrupts.)

  • Totoro