ESR meter with Arduino

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 :wink:

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

Totoro:

Would you make your schematic and code available for others to use. I would like to make a self contained ESR meter that does not need a voltmeter.

Thanks

I am happy to post my code. You can download it from here.
http://vondervotteimittiss.com/belfry/downloads/ESR_Meter.ino.zip
Just keep in mind, it is a work in progress. As it stands, it works with the 'high-current' resistor in the circuit (the 100 ohm resistor which is actually 110 ohm in my circuit and in my code I refer to this as the low range).
As I mentioned, the schematic I used is the same as szmeu originally posted. (OK, not exactly. I use a 110 ohm resistor, because I had one, and a 10microFarad capacitor, because I had one. Adjust the resistor value accordingly in the code.) The pulse generation part of the circuit as szmeu posted is really elegant and needs no change.
The only change I made is in the display. In my breadboard, I use a three-digit, seven-segment display and have programmed the Arduino drive it. (Adjust the SEG_ON/OFF, DIG_ON/OFF defines as appropriate for your display setup and anode/cathode digit switching transistors.)
I am currently working on getting the 'low-current' mode (the 1000 ohm resistor), what in my code is the high range, to work. That should let me measure higher values of ESR, as szmeu suggested.
Please keep in mind that I am new to micro-controller programming! If you have any questions about the code, I'll try to answer as best I can.
And if you have any suggestions how I can improve, please let me know.
Thanks for your interest.

  • Totoro

Hi all,

Since I do not have an Arduino, I have built szmeu's original circuit around an Atmega8.
The only difference is that I'm using 1N5821 instead of 1N5822.
The firmware has been adapted from Totoro's code.
When connecting a cap or small resistor across pins 1+2 and GND, I'm getting nothing, the ADC value is always 0. (2.56V internal reference)
However, when connecting a potentiometer accross +5V and GND with the wiper going to the ADC (ADC0/PC0 in my case), I'm getting values, so the ADC seems to be working ok.
Charging pulses are generated, measuring about 30mV pp at pins 1+2 (maybe too low?)
Any pointers as to what could be wrong?

When you use a resistor to charge-up a capacitor, the current goes down as the capacitor is charging up, exponentially. This is less of a problem initially; but as the capacitor is charged up, the error (from a linear charging up process produced by a ccs) gets bigger (small resistor or small capacitor, or long charge-up time / cycle).

One way to solve this is to taylor-expand the integral of current over time. You only need to expand to its 2nd order derivative to maintain fairly good accuracy.

Sreg,
First, just to be sure we're on the same wavelength, short pins 1 and 2 on CN1 (on szmeu's schematic) together and put the device-under-test (DUT) between these shorted pins and ground. For now, just ignore the possibility for a four-wire setup (actually three wire with the circuit from szmeu).
OK, you've done that. Now, with a 30mV pulse across your DUT, you can do the math and you should have approx. 600milliOhms +/- for the DUT. This assumes that at top of the 100 Ohm resistor, R8, (where it connects to the emitter of Q1) you see a 5V pulse.
If that's the case, then you may want to make sure that the oversampling is set up correctly for your device. You may need to change some of the register set stuff in the original code. This stuff...
sbi(ADCSRA,ADPS2);
cbi(ADCSRA,ADPS1);
sbi(ADCSRA,ADPS0);
Refer to the datasheet for your device and the Atmel document that szmeu mentions.
Then again, it could be something simple like the discharge transistor, Q2, is always on. Or you didn't change the value of Vref in the code. You mention the internal ref on your device is 2.56V. In the code it's 1.1.
This is all just guesses on my part. Maybe you have checked all this stuff. My 2 (euro) cents worth, anyway.
Good luck!

  • Totoro

Totoro, have you designed PCB by any chance?

bobale,
Sorry, I am just a breadboard/point-to-point/proto-board type. My main need for an ESR meter is to troubleshoot old audio gear and test equipment.

I also need it ocasionally, but I would rather build standalone device, but I'm really bad at PCB design, so I'll wait for someone else to do it (someone who needs it more than me) :grin:

Totoro,

thanks for your reply!

Totoro:
Sreg,
First, just to be sure we're on the same wavelength, short pins 1 and 2 on CN1 (on szmeu's schematic) together and put the device-under-test (DUT) between these shorted pins and ground. For now, just ignore the possibility for a four-wire setup (actually three wire with the circuit from szmeu).

Yes 1+2 are shorted together amd DUT is placed between those and GND.

OK, you've done that. Now, with a 30mV pulse across your DUT, you can do the math and you should have approx. 600milliOhms +/- for the DUT. This assumes that at top of the 100 Ohm resistor, R8, (where it connects to the emitter of Q1) you see a 5V pulse.
If that's the case, then you may want to make sure that the oversampling is set up correctly for your device. You may need to change some of the register set stuff in the original code. This stuff...
sbi(ADCSRA,ADPS2);
cbi(ADCSRA,ADPS1);
sbi(ADCSRA,ADPS0);
Refer to the datasheet for your device and the Atmel document that szmeu mentions.

I'm fairly sure my code is ok, but I'd be glad if you could take look at it - please see attachment.
I'm also getting about 3V pulses measured at the emitter of Q1.

Then again, it could be something simple like the discharge transistor, Q2, is always on. Or you didn't change the value of Vref in the code. You mention the internal ref on your device is 2.56V. In the code it's 1.1.

Unfortunatley the Atmega8 has only 2.56V internal reference voltage, but I think I can live with any decrease in resolution this will introduce.
My problem is that no values whatsoever are displayed when connecting the DUT as described above. (ok not entirely true, -1 is displayed since I return -1 from the calculation if millivolts are 0 - please refer to source code).
Q2 should not always be on, I get pulses on its base according to the discharge pulses.

If I get this to work, I'll gladly post my pcb layout.

-- Sreg

ESR-Meter.c (3.19 KB)

Finally got it to work, it seems the BC327 was defective :blush:

Thanks for all the help!
As promised, I attach my layout and source code (built with Atmel Studio 6.0).

-- Sreg

ESR-Meter.zip (362 KB)

wow thx for the layout. I was just starting to design one. Saved a lot of work.

markbee

Sreg,
Great to hear you got it working!
You mentioned above that you return -1 when millVolts is zero. I wondered why, so I took a look at your code. You have helped me to avoid a bad thing, the potential divide-by-zero bug. Thank you!

  • Totoro