Go Down

Topic: ESR meter with Arduino (Read 79371 times) previous topic - next topic


1. You cannot measure capacitance in-circuit.

2. You can measure ESR, close enough for troubleshooting, in most circuits.

The key is to keep the sensing voltage  below the peak voltage that could turn a semiconductor junction on, including Shottky.

3. You cannot use the same method to measure ESR and ESL over a really wide range of capacitance.

But it doesn't really matter. Mostly it is electrolytic capacitors that fail by increasing ESR. And the values that matter are >=1uF, usually  much larger.

ESR of a few ohms doesn't really matter for audio coupling capacitors, which are normally around 1uF to 10uF. For linear power supplies, ESR of a few ohms matters, but the capacitors are generally in the range of thousands of uF. For switching power supplies, ESR needs to be tenths of an ohm, but capacitance is still >>10uF.

And all those capacitors have varying amounts of parasitic inductance. But that doesn't change, so no real need to measure it. That is why a circuit will have Vcc bypassed by (in addition to the 100s or 1000s of uF of smoothing capacitor) both a 1uF and 1nF bypass capacitor.

For capacitors in the nF range, there are not really many mechanisms for ESR to increase as a failure mode. You can measure ESR as a function of circuit Q.
Steve Greenfield AE7HD
Nick Gammon on multitasking Arduinos:


...is there anyone who has successfully measured low ohmic values??, for example 0.1 or 0.01; appropriate values ??to an ESR meter?

I'm working on it.
Steve Greenfield AE7HD
Nick Gammon on multitasking Arduinos:


... 10 downloads of the attached .zip file with code, images, schematics and PCB design...

Hallo Baravantan,
in your posted listings is an function named UpCap. What is it for? If I press button at input 3, I get a display with 4,7, 6,8, 10, 15, 22 ... 10000 µF. But that is not the Value of the DUT.


To measure really low values, Kelvin leads would be a good idea.

Steve Greenfield AE7HD
Nick Gammon on multitasking Arduinos:


Hi, just thought I'd say thanks for the design, I think I have got it to work, but have a few questions.

I copied the schematic in the first post, although I used a fubarino SD board (I had one lying around). This needed a couple of tweaks to remove avr-specific code (see https://github.com/JamesGlanville/esrmeter). I also used trimpots as I had no 1% resistors.

Are trimpots ok? I seem to remember they have a higher inductance than normal resistors, and I don't know whether this matters here. I have a fairly good LCR meter I used to trim the pots, so I think they are accurate to within 1%.

The fubarino SD board does not have an internal voltage reference, so I'm using the 3.3V supply (and 3.3V for everything apart from LCD power). I think this should be fine, although with less ADC precision. However, with vRef=3.31V (measured, and very stable), I need to set current to 0.02468 to get "good" results. By calculation, it should be 0.0331, a pretty big difference. When I say "good" results, I am getting correct readings to about 2% of 1ohm, 2 ohm, and 2.5ohm resistors. I have no way of testing ESR otherwise,  but my results seem reasonable (my supply of caps is mostly very good, a few ones are terrible). Is my weird current value ok/is there a better way to calibrate the meter?

Thanks again :)


Apr 11, 2014, 12:42 pm Last Edit: Apr 11, 2014, 01:21 pm by zaero Reason: 1
First of all I would like to thank you all for such a great work.

I have been implementing the ESR meter, and checking Totoro's function I saw he is using the voltage supply as a parameter. Then I remembered about the hidden voltmeter to own supply voltage on 168 and 328 chips. I just added it on setup and it improves measurement quality. Actually, helps a lot regarding "well regulated quality supply" requirements ;)

Oh, regarding the coupling capacitor: as a bipolar capacitor I have 2 electros 330µF/35V in a back to back configuration. There is a lack of slope in the scope, which means that it is only measuring ESR. Actually, coupling cap ESR is not that important: 1Ohm ESR would only affect 1% over the 100 Ohm sense resistor. Capacitor value however is important, because a low capacitance value would bother the reading due to capacitor impedance.
Regarding 4wire sensing: as the ground is shared, 4w cannot be used, but 3-wire sensing can and should be used because it is extremely easy to implement.
Regarding Transistors: Transistor models are not important, they are operated as a switching device. However, they should be "fast" to switch. Currently I am using a 2SA733 and 2SC945 that I had in junkbox.

Oh, another thing, adding a decoupling capacitor between PNP transistor emitter and sense ground would be beneficial as well. Location on PCB should be as close as possible to those points.

Edit: Couple mods I think interesting:
Playing with it, I just realized that if capacitors hold (or grow) any charge, readings get (easily) bothered. In the original schematic, there is a 10k capacitor to ground, I decreased it to 470 Ohm: well far to bother reading range and low enough to not grow bald while waiting to discharge 1000µF caps... The modification of the "commercial" schematic with BS170 does that, but I think there is no need for 50mA application.
For LOW ESR Capacitors, original circuit may be a bit "short" in current terms. If increasing current to say 100mA, decoupling is probably needed for good measurement stability. According to my oscilloscope, measurement last 35µs, so I would use over 100µF...


I have been playing a bit with the Code and the ADC, and reading about it.

It is interesting that maximum 10bit speed is specified at 200kHz, FASTADC option of original code sets the ADC speed at 500kHz, which can degrade resolution. Totoro decreased that speed to 250kHz, increasing acquisition time, but it is important to understand how the ADC works (which I didn't know before  :smiley-roll: )
ADC operation is preceded by sample&hold where input is sampled. That takes around 2 ADC cycles and then conversion which may take up to 25cycles. At 250kHz ADC clock, sampling time should be around 8µs, and 4µs when a 500kHz ADC is used. Measuring voltages with oscilloscope, approximated voltage sampling occurs around 10µs and 6µs after pulse activation. Here I attach a picture of a 500kHz ADC sampling a 10µF capacitor. Measurement is pretty close with expected times of around 4µs sample&hold + 1µs delay of micros(1)+ ...

Note that for a 10µF capacitor there is an important charging slope of the capacitor, which sets measurements a bit off. At 50mA and 6µs delay that is ~300mV/C[µF] and 10µs delay ~500mV/C[µF]  Using: deltaV[mV]=50*DELAY[µs]/C_value[µF]
Even setting a prescaler for ADC clock at 1MHz the delay effects would be around 200mV per each µF.

This comment is important because: decoupling cap can be smaller than what I said before  :smiley-roll-blue: and because that with those mV/µF we can find wich is the low-ESR measuring limit for different cap values.

Oh! In Totoro's code, delay added is 5µs, which considering the 250kHz ADC would set the capacitor charging error to ~700mV/µF

Sidenote: The capacitor charging effect and knowing the exact point of S&H can be used to estimate capacitor value as well, even to correct the capacitor charging effects.



My third post in a row...
...finaly I have what seems to be a decent operating capacitor measurement + ESR correction.

Capacitor values found are an estimation, but seem to match with my multimeter readings within 5-10% (tested from 10µF to 1000µF). Then once capacitor value is found, I used to correct the ESR deviation due to DUT charging effects, which can be seen as a resistance at the sampling instant, which if I didn't do much wrong, would be Zequivalent=deltaV/I --> Zeq=6µs/C[µF]
I'd appreciate any comments regarding if this makes sense or I just got crazy here...

Anyways, I attach code for Capacitor measurement function (below 10µF gets high error, so I just cropped under 5µF, I won't use it with such small caps anyway :D
Code: [Select]
double measureC()
  double CAP;
  unsigned long esrSamples;
  unsigned int sampleA = 0;
  unsigned int sampleB = 0;
  int cnt = 0;

  //oversampling is overrided
  digitalWrite(DISCHARGE_PIN,LOW);//disable discharging
  digitalWrite(PULSE_PIN,LOW);//making a miliVolt pulse of 50mA
  delayMicroseconds(1);//Considering S&H is done after 2us, this could even be taken away.
  sampleA = analogRead(ESR_PIN); //First read: T=6us
  while((sampleB<sampleA+100)&&(cnt<40)){  //less than 107mV between samples or 40 times done the loop
    sampleB = analogRead(ESR_PIN); //Second read: T+delay
  // If we are here, either samples have more than 107mV or comparison TimedOut
  digitalWrite(PULSE_PIN,HIGH);//stopping pulse
  digitalWrite(DISCHARGE_PIN,HIGH);//discharging the capacitors
  delayMicroseconds(600);//waiting a bit longer

  //Vsupply is found using 'Hidden Voltmeter in AT328'
  //Resistor value is 100.0 (approximated)
  //45.0 is the delay time between measurements (estimated by measured values).
  CAP=45.0*cnt*Vsupply/100.0/(sampleB-sampleA)/vRef; //50us_delay*times_of_delay * Current / (voltagedifference)
  if(CAP<5)  return(0.0);
  else       return(CAP);

Regarding ESR function, I only altered the last part of the function to correct for capacitors detected but smaller than 1000uf
Code: [Select]

  ESR=1000*100.0 / ((Vsupply / miliVolt) - 1); //100 is sense resistor  //Correct with Cvalue!!!!!
    return ESR-6000.0/Cvalue; //Capacitor nuissance, Req=6/C[µF]
    return ESR;


Thanks for this project everyone, I'm planning to build one of these as soon as I have wrapped my head around all the info in the thread and have had time to design a shield for it.
Will upload the gerber files here if someone would be interested. I'm probably going down the SMD route, since I like tinkering with 0805 components  :smiley-eek:



I'm about to build this project with parts I have and am a bit lost with caps that are being used.

I have a 2A104J greencap to use as the 100uf (C2).

But the 47uf, Bipol (C1) I do not have, only in electrolytic cap form. I am assuming that I need to find a bidirectional cap? is that what you call a cap that can be used either polarity?

I am finding it hard to find an assorted pack of caps which are not electrolytic on ebay.

Also the only transistors I have are BC328 and BC338. The schematic says 327 and 337...Is there a difference?

One more Q, how the hell are all of you guys making your own circuit boards?

Thank you.


I think that I am worndering how to wire up the push button ZERO with my 2 wire LCD display.



I also built a standalone version of this and it seems to be working ok. There is one thing I don't know what to make of, though.

In the original schematic, there's  R4 connected to Arduino digital pin 8. This doesn't seem to be used in any version of the code I found. From what I understand, this was intended to be used as a low current pulse output. Is this correct? If so, isn't the version posted by mikanb http://forum.arduino.cc/index.php?topic=80357.msg1210134#msg1210134.

So let me recap (absolutely no pun what-so-ever intended!):

- The original R4/D8 connection was never used by any version of code seen here on this thread.
- The 1k-PNP-1k implementation by mikanb does what R4/D8 originally intended to do but never did.
- The ak-PNP-1k implementation by mikanb is superior to the original R4/D8 implementation, because it adds a bit more decoupling from the MCU through the PNP.
- In a revised design, I could omit the R4/D8 connection in favour of mikanb's implementation.

Right...? Is it?




right it is! your observations regarding R4/D8 are correct :-)



Thanks for clearing this up!




I'm looking for SMD parts for this, but being pretty noobish I'm not sure what characteristic to look for in the 1N5822 schottky diodes - could anyone help me explain this?
The discussion have been about 300mV voltage drop, but I don't understand what characteristics of the diode this comes from. The specified forward voltage drop on the 1N5822 I've found is 525mV or 950mV.

Go Up