Arduino
Forum

> Topics

> Science and
Measurement

> ESR meter with
Arduino

Print
Go Down

Pages: [1] 2 3 ...
7

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

szmeu

Newbie

Posts: 17

Karma: 6  [add]

ESR meter with Arduino

Nov 26, 2011, 05:39 pm Last Edit: Mar 28, 2013,
01:45 pm by szmeu Reason: 1

For
those who are new to this topic and wish to build this simple esr-meter I warmly
recommend to read all the four pages because from the first post that I made,
there were some significant changes that will improve the esr-meter, these
changes were contributed and ironed out by the users of the forum, also reading
the pages you will find a lot of answers. Thanks goes to the users who improved
this simple solution and fixed bugs!

A short resume
of what you will find on reading more than just the first page:
- a
clear understanding off how this esr meter works and many questions
answered;
- the correct formula for calculating the
esr!; (the formula on the first sketch is not the correct one, you will
find the correct one just a bit deeper in the topic)
- a better stand alone
layout and code contributed by users;
- ...

ESR meter for
capacitors with Arduino

Hi,
This is my first for a "project" on a
forum and playing with electronics is a hobby so please take it as is because
this is just amateur work, everything is perfectible.
I was searching for an
easy to build ESR meter on the net, found some great projects which helped me
understand the basics, than I thought this would be an excellent idea for an
Arduino project, so here I am, but before I present this solution I'd like to
write two-three more lines a bit off-topic:

Skip if you find this kind of
boring.
First I'd like to thank to dr. Le Hung here
(http://members.upc.hu/lethanh.hung/LCFESRmero/en/index.htm) for the idea of
this simple ESR schematic, he sells a kit for the ERS-meter but also features
capacitor and inductance measurement.
Second: I'd like to thank the user
tinhead on this forum (http://www.eevblog.com/forum/index.php?topic=1571.0) for
making it easy for me to choose which scope to buy for tinkering with the
current project (thanks for his work on Hantek DSO50xxx series).
Third thanks
for all those people who post and share useful info and projects on the
net!
Skip end.

The ESR project:
For
those who are wondering what is ESR -> Wikipedia
(http://en.wikipedia.org/wiki/Equivalent_series_resistance).
The current
project is intended to help measure resistors with low value (under 1 Ohm) and
capacitor ESR for those times when we want to test capacitors in a SMPS or other
similar situations. Another interesting thing about this project is that it
shows that over sampling is useful and can give very good results and can be
employed successfully in other projects without the need to use external
hardware; I had repeatable results in measuring low ESR capacitors and low value
resistor (0.05 to 1 Ohm can be accurately measured). For information on using
oversampling I highly recommend reading
(http://atmel.com/dyn/resources/prod_documents/doc8003.pdf)

The idea
behind this ESR is this: Using the well known formula U=I*R, we will pulse very
shortly with a known current the cap or resistor, measuring the voltage on the
element we have the necessary information to calculate the resistance. There
would be a lot to write about this method and why this is functioning but
probably more interesting is hand on experience.

The
code: I tried to comment it at every step, it is written only for the
50mA current but very easily can be modified to add more upper range to the
measurement (the hardware part is ready for this). Code could be rewritten for
better performance using interrupts, etc, here is just a basic idea that
works.

The hardware: Schematic is provided
below, I designed a shield to arduino, probably not the best layout, be aware
that the pcb was not tested yet and I'm not 100% is correct, did not use auto
route and tried to make it single side, the schematic is good for sure and
tested.

The schematic and pcb are attached
(you have to sign in to download the atachment)

The DUT should be connected to CN1 between GND (pin3,pin4)
and pulse and AIN0 (pin1,pin2) using a setup with four wires.

Here comes
the rudimentary code:

Code: [Select]
#include
<LiquidCrystal595.h>
#include <avr/eeprom.h>

//we have to
change prescaler for the ADC to make the conversion happen faster
//this code
section was suggested on the arduino forum
#define FASTADC 1
// defines
for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit)
(_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr,
bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

//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

//function prototype
unsigned long
measureESR(void);//measuring function, increases ADC to 16bit resolution through
oversampling

//global variables
unsigned long esrSamples;
double
miliVolt;
double esrVal;
double esrCal;
double vRef = 1.093;//voltage
on the Vref pin (this sketch uses internal voltage reference 1.1V)
double
current = 0.046200;//proper calibration can be done entering the right value for
the current (U=I*R)
//idealy this is 0.05 A, this condition is fulfilled only
if R10 is 100 Ohm, Vcc is exactly 5V and the transistor
//while fully
saturated idealy is at 0 ohm.

//this is my display setup, I'm using
Stephen Hobley's 3 wire setup and class
//exchange to what is good for
you
LiquidCrystal595 lcd(6,4,2);

void
setup(void)
{
lcd.begin(20,2);
lcd.setLED2Pin(HIGH);
lcd.setCursor(0,0);
lcd.print("ESR
meter");
lcd.setCursor(5,1);
lcd.print("version
0.1");
delay(1000);

lcd.print("Seting
up...");

analogReference(INTERNAL);//setting vRef to internal
reference 1.1V

pinMode(ESR_PIN, INPUT);//reading
miliVolt
pinMode(PULSE_PIN,
OUTPUT);
digitalWrite(PULSE_PIN,HIGH);//low enables
T1
pinMode(DISCHARGE_PIN,
OUTPUT);
digitalWrite(PULSE_PIN,HIGH);//low disables
T2
pinMode(BUTTON_PIN,INPUT);//setting up for a button (will use this
for zeroing)
digitalWrite(BUTTON_PIN,HIGH);//enabling the pull up on
the button, when button pressed to the ground zeroes out the
cable
delay(1000);
lcd.clear();
lcd.print("Please
Wait...");

//seting prescaller to 32 for faster adc
(500khz)
//at 500khz  results are still looking good (same values
as if 250khz ADC clock)
// the shorter the pulse on a small value
capacitor it has no time to charge and denaturate de result
if
(FASTADC) {
sbi(ADCSRA,ADPS2);

cbi(ADCSRA,ADPS1);

sbi(ADCSRA,ADPS0);
}

//reading calibration value, it
will be ok if already calibrated, else it might be bogus depends on the content
of EEPROM
//but will be ok after first
calibration
eeprom_read_block((void*)&esrCal, (void*)0,
sizeof(esrCal));
}

void
loop(void)
{
lcd.setLED1Pin(HIGH);
esrSamples =
measureESR();//this function takes a while,)
// so we don't need other
delay for the lcd (this functions time gives the refresh rate for
display
miliVolt = (esrSamples * vRef) / 65.535;//calculating voltage
on AIN0 pin
esrVal = (miliVolt)/current - esrCal;//calculate ESR in
miliOhm (pls read forum for correct
formula)

lcd.clear();
lcd.print("
V:");
lcd.print(miliVolt,4);
lcd.setCursor(13,0);

lcd.print("mV");
lcd.setCursor(0,1);
lcd.print("ESR:");
lcd.print(esrVal,4);
lcd.setCursor(13,1);
lcd.print("m");
lcd.print((char)244);

//for
zeroing the cables, this can be quite a big resistance compared to the values we
intend to measure
//so it is a good idea to try to reduce in any way
possible this influence (short cables, soldering the cables,
etc)
if(!digitalRead(BUTTON_PIN)){

lcd.clear();
lcd.print("Zeroing...");

esrCal = (miliVolt)/current;
lcd.print("
done!");
lcd.setCursor(0,1);
//writing
calibration value into EEPROM so we don't have to calibrate on restart

eeprom_write_block((const void*)&esrCal, (void*)0,
sizeof(esrCal));
lcd.print("saved to EEPROM");

delay(400);
}
}

//this is where the magic happens, it
really works and gives some
//incredibly good results! if you need sub
milivolt accuracy is a good way to go
//noise is good ;) if in doubt must
read oversampling on ADC from AVR docs
unsigned long
measureESR()
{
unsigned long samples = 0;
unsigned int
acumulator = 0;
int i = 0;
//oversampling 4096 times (for 16
bit is 4^(desiredResolution - ADCresolution))
while(i < 4096)
{
digitalWrite(DISCHARGE_PIN,LOW);//disable
discharging
digitalWrite(PULSE_PIN,LOW);//making a miliVolt
pulse of 50mA
delayMicroseconds(1);//on the scope it looks that
after enabling the pulse a litle delay is
//recomended so the
oscillations fade away
acumulator =
analogRead(ESR_PIN);//reading value on AIN0

digitalWrite(PULSE_PIN,HIGH);//stopping pulse

digitalWrite(DISCHARGE_PIN,HIGH);//discharging the capacitors

delayMicroseconds(600);//waiting a bit longer to fully discharge before
another pulse
samples += acumulator;//acumulating the
readings
i++;
}
//we have samples, let's go
and compute value
samples = samples >> 6;//decimating
value
return samples;//all done returning sampled
value
}

esr_meter.zip

131 KB
downloaded 7886 times

pwillard

Edison Member

Posts: 2,155

Karma: 155  [add]

Hardware Hacker

http://www.pwillard.com/

Re: ESR meter with Arduino

#1

Nov 30, 2011, 11:10 am

Nicely Done.

grant1842

Guest

Re: ESR meter with Arduino

#2

Dec 17, 2011, 11:20 pm

Very nice work.
May I ask what software you
used to draw the schmetic that supports the arduino IC

szmeu

Newbie

Posts: 17

Karma: 6  [add]

Re: ESR meter with Arduino

#3

Dec 19, 2011, 05:28 pm

Thank you all for your appreciation, for the
schematic I used the Eagle Cad with freeware licence and the adafruit library
(you can find it here http://www.adafruit.com/blog/2010/02/05/b00m-adafruit-eagle-library-an-arduino-package/).

grant1842

Guest

Re: ESR meter with Arduino

#4

Dec 20, 2011, 03:44 am

I am curious will this get the ESR of a low cap
value (pF, nF);
Thanks for your comments.

szmeu

Newbie

Posts: 17

Karma: 6  [add]

Re: ESR meter with Arduino

#5

Dec 21, 2011, 10:26 pm Last Edit: Dec 21, 2011,
11:09 pm by szmeu Reason: 1

Good question, the smallest capacitor I played
with was 4,7uF value, this was not a problem to measure, the code presented here
uses only the 50mA branch of the schematic (through R8 and the transistor),
using the 5mA branch (through R4, the code must be adapted a bit) lower value
capacitors can be measured (the smallest cap value that can be measured
accurately I don't know). I don't have an reference instrument to compare with,
but I guess if one needs to compare two capacitors and sort out the one with the
smallest ESR this can be done easily with the current schematic, eventually the
schematic can be modified for a lower current (increasing R4's value) so that
when the current is applied to the DUT will not charge the small capacitor to
quickly and distort the reading (increasing frequency should be necessary to),
maybe another schematic with a true sine 100khz constant current generator or
even at higher frequency as this is important for the small value capacitors can
give better results. Sorry I don't have now this on my breadboard and can't test
it. Probably the best way to know if this schematic is good for such small
capacitance (pF, nF range) is necessary to study a bit the theory behind ESR
measurement and make some calculation to know at least the theoretical limits of
this device.

I just took a peak on the net and got to this page where is
a calculator for reactance (http://www.electronics2000.co.uk/calc/reactance-calculator.php),
as it turns out we must use a frequency where reactance will be negligible
versus ESR, as this schematic uses aprox. something around 60khz (more or less)
reactance becomes an issue beginning with the nF range, for pF we need something
with several Mhz oscillations.

Sadly the answer is no measuring the
ESR for (pF) range with this schematic, only the upper range of nF (even here
reactance should be taken in account).

geotek

Guest

Re: ESR meter with Arduino

#6

Dec 26, 2011, 02:50 am

One question, how do you seperate ESR from
ESL?
Some capacitors, especially those designed for low frequency use,
can have very high inductive reactance.  I don't think your device can
distinguish this.  You may think you have a cap that has very high ESR,
but, in fact works very well at 120Hz, not so good at 10KHz.

szmeu

Newbie

Posts: 17

Karma: 6  [add]

Re: ESR meter with Arduino

#7

Dec 30, 2011, 05:47 pm

Good point, probably one way would be to test the
capacitors at two different freq. high an low plus measuring the capacitance
(computing the ideal values from capacitance and freq to get the ideal reactance
and inductance) and than analyze the outcome comparing all the values and decide
upon this result for a proper verdict of what the cap is good for and where it
can be used, would be nice to have some capacitors with the same value and
different ESR and ESL to test for this variable, the sketch could be modified to
use different freq. This gives me an idea of a sketch where we could analyze the
capacitor's response on a frequency range and plot the value and compare this to
the ideal capacitor.

grant1842

Guest

Re: ESR meter with Arduino

#8

Jan 13, 2012, 02:18 am

I am new to Arduino.
I have a  I2C 1602
LCD module.

Quote

http://www.dfrobot.com/index.php?route=product/product&keyword=DFR0063&category_id=0&description=1&model=1&product_id=135

It works.

I am trying to use it with
your code.
I had to comment out 2 lines to get it to compile.
If you could
look at it and tell me if I need to modify this code for it to work.
Thanks
so much for your time.

Code: [Select]

#include <avr/eeprom.h>

//we have to change
prescaler for the ADC to make the conversion happen faster
//this code
section was suggested on the arduino forum
#define FASTADC 1
// defines
for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit)
(_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr,
bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

//define the input and output
pin we will use
#define DISCHARGE_PIN 3
#define ESR_PIN A0
#define
PULSE_SMALL 3
#define PULSE_PIN 5
#define BUTTON_PIN 7

//function
prototype
unsigned long measureESR(void);//measuring function, increases ADC
to 16bit resolution through oversampling

//global variables
unsigned
long esrSamples;
double miliVolt;
double esrVal;
double
esrCal;
double vRef = 1.093;//voltage on the Vref pin (this sketch uses
internal voltage reference 1.1V)
double current = 0.046200;//proper
calibration can be done entering the right value for the current
(U=I*R)
//idealy this is 0.05 A, this condition is fulfilled only if R10 is
100 Ohm, Vcc is exactly 5V and the transistor
//while fully saturated idealy
is at 0 ohm.

//this is my display setup, I'm using Stephen Hobley's 3
wire setup and class
//exchange to what is good for you
#include
<Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C
lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line
display

void setup(void)
{
lcd.begin(20,2);

//lcd.setLED2Pin(HIGH);
lcd.setCursor(0,0);
lcd.print("ESR
meter");
lcd.setCursor(5,1);
lcd.print("version
0.1");
delay(1000);

lcd.print("Seting
up...");

analogReference(INTERNAL);//setting vRef to internal
reference 1.1V

pinMode(ESR_PIN, INPUT);//reading
miliVolt
pinMode(PULSE_PIN, OUTPUT);

digitalWrite(PULSE_PIN,HIGH);//low enables T1
pinMode(DISCHARGE_PIN,
OUTPUT);
digitalWrite(PULSE_PIN,HIGH);//low disables T2

pinMode(BUTTON_PIN,INPUT);//setting up for a button (will use this for
zeroing)
digitalWrite(BUTTON_PIN,HIGH);//enabling the pull up on the
button, when button pressed to the ground zeroes out the cable

delay(1000);
lcd.clear();
lcd.print("Please
Wait...");

//seting prescaller to 32 for faster adc
(500khz)
//at 500khz  results are still looking good (same values
as if 250khz ADC clock)
// the shorter the pulse on a small value
capacitor it has no time to charge and denaturate de result
if
(FASTADC) {
sbi(ADCSRA,ADPS2);

cbi(ADCSRA,ADPS1);
sbi(ADCSRA,ADPS0);
}

//reading calibration value, it will be ok if already calibrated, else it might
be bogus depends on the content of EEPROM
//but will be ok after first
calibration
eeprom_read_block((void*)&esrCal, (void*)0,
sizeof(esrCal));
}

void loop(void)
{

//lcd.setLED1Pin(HIGH);
esrSamples = measureESR();//this function
takes a while,)
// so we don't need other delay for the lcd (this
functions time gives the refresh rate for display
miliVolt =
(esrSamples * vRef) / 65.536;//calculating voltage on AIN0 pin
esrVal
= (miliVolt)/current - esrCal;//calculate ESR in miliOhm

lcd.clear();
lcd.print("  V:");

lcd.print(miliVolt,4);
lcd.setCursor(13,0);

lcd.print("mV");
lcd.setCursor(0,1);

lcd.print("ESR:");
lcd.print(esrVal,4);

lcd.setCursor(13,1);
lcd.print("m");

lcd.print((char)244);

//for zeroing the cables, this can be quite
a big resistance compared to the values we intend to measure
//so it
is a good idea to try to reduce in any way possible this influence (short
cables, soldering the cables, etc)

if(!digitalRead(BUTTON_PIN)){
lcd.clear();

lcd.print("Zeroing...");
esrCal = (miliVolt)/current;

lcd.print(" done!");
lcd.setCursor(0,1);

//writing calibration value into EEPROM so we don't have to calibrate on
restart
eeprom_write_block((const void*)&esrCal, (void*)0,
sizeof(esrCal));
lcd.print("saved to EEPROM");

delay(400);
}
}

//this is where the magic happens, it really
works and gives some
//incredibly good results! if you need sub milivolt
accuracy is a good way to go
//noise is good ;) if in doubt must read
oversampling on ADC from AVR docs
unsigned long measureESR()
{

unsigned long samples = 0;
unsigned int acumulator = 0;
int
i = 0;
//oversampling 4096 times (for 16 bit is 4^(desiredResolution -
ADCresolution))
while(i < 4096) {

digitalWrite(DISCHARGE_PIN,LOW);//disable discharging

digitalWrite(PULSE_PIN,LOW);//making a miliVolt pulse of 50mA

delayMicroseconds(1);//on the scope it looks that after enabling the pulse a
litle delay is
//recomended so the oscillations fade
away
acumulator = analogRead(ESR_PIN);//reading value on
AIN0
digitalWrite(PULSE_PIN,HIGH);//stopping pulse

digitalWrite(DISCHARGE_PIN,HIGH);//discharging the capacitors

delayMicroseconds(600);//waiting a bit longer to fully discharge before
another pulse
samples += acumulator;//acumulating the
readings
i++;
}
//we have samples, let's go
and compute value
samples = samples >> 6;//decimating
value
return samples;//all done returning sampled
value
}

szmeu

Newbie

Posts: 17

Karma: 6  [add]

Re: ESR meter with Arduino

#9

Jan 13, 2012, 09:50 pm

@grant1842

Hi, using your display setup is
ok, looking at the code I saw that I made a mistake when specifying the columns
and rows of my display (16x2) so this code: lcd.begin(20,2) should really be
lcd.begin(16,2), as I saw from your lcd object initialization yours to is 16x2
display, for this reason the code should be:

Code: [Select]
lcd.begin(16,2);

The two lines that I suppose to
which you refer to and commented out are:

Code: [Select]
//lcd.setLED2Pin(HIGH);
//lcd.setLED1Pin(HIGH);
they
have no important role in the code, they just control the back light on my
display and another LED.
If the code compiled, everything should be all
right, you can test your setup using an 1 ohm resistor (or other small values
resistors). If the cables are zero-ed your reading should be accurate (you can
further calibrate the meter modifying the value for the double

Code: [Select]
current =
0.046200; variable.)
For any questions I can answer I will help
gladly.

Respect,
szmeu

grant1842

Guest

Re: ESR meter with Arduino

#10

Jan 14, 2012, 03:17 am

Thanks for your help,.
I do not have any bc337
npn trans in my parts bench.

I do have some 2N4401 . Will this be a
suggestible replacement ?
Thanks again

szmeu

Newbie

Posts: 17

Karma: 6  [add]

Re: ESR meter with Arduino

#11

Jan 15, 2012, 09:17 pm

@grant1842

2N4401 as I see from datasheet
should do the job.

grant1842

Guest

Re: ESR meter with Arduino

#12

Jan 15, 2012, 10:41 pm

Zero Meter.

The lcd I am using is only
useing a 2 wire (A4, A5) to show info.

I am confused on the schematic as
it uses several connections to the lcd .

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

Thanks for your
help.

szmeu

Newbie

Posts: 17

Karma: 6  [add]

Re: ESR meter with Arduino

#13

Jan 17, 2012, 10:08 pm

@grant1842

The button for the zeroing has
nothing to do with the LCD, it is just a button tied to a digital pin (in this
case D0) which has the pull up resistor enabled, when you push the button that
digital pin is put to the ground and this condition is tested in this section of
code:

Code: [Select]
if(!digitalRead(BUTTON_PIN)){

lcd.clear();
lcd.print("Zeroing...");
esrCal =
(miliVolt)/current;
lcd.print(" done!");

lcd.setCursor(0,1);
//writing calibration value into EEPROM so
we don't have to calibrate on restart
eeprom_write_block((const
void*)&esrCal, (void*)0, sizeof(esrCal));
lcd.print("saved
to EEPROM");
delay(400);
}

I suppose
you have some kind of serial interface LCD so you must set up your LCD to use a
proper library, the schematic here shows  HD44780 type LCD wiring using
4bit mode, more on LCD you can find here:
http://arduino.cc/playground/Code/LCD

grant1842

Guest

Re: ESR meter with Arduino

#14

Feb 15, 2012, 01:49 am

Thanks for all your comments.

I have bread
boarded this project and the displays reads(Zeroing Done saved to EEPROM) , it
is like it is stuck in a loop .
I thought I may be doing something wrong so I
used Proteus to do a simulation and I get the same reslut.
Can you look at
the schematic and see if I am doing something wrong.

nnn.jpg

162.48 KB
downloaded 11101 times

Print
Go
Up

Pages: [1] 2 3 ...
7

Loading...