Progress Bar

Skip to main content

Jaycar
...

Resistor & Capacitor Tester

Resistor & Capacitor Tester

Difficulty
Test & Tools

Summary

Here's another easy to build project similar to the LED tester, and using the same hardware. This project will try to work out whether it's connected to a resistor or capacitor and then show you the value (resistance or capacitance) of it. If it's a resistor, it'll also suggest the nearest resistor from the Jaycar range of ½W resistors. Of course, using off the shelf components, it's not a high accuracy device, but handy to have if you're sorting through your junk drawer and are having trouble with the colour codes. There's about ten solder joins that need to be made to complete this project.

Materials Required

1Duinotech UNO r3 Main BoardXC4410
1Duinotech Arduino Compatible Prototyping ShieldXC4482
1Duinotech Arduino Compatible 2 X 16 LCD Screen Display with ControllerXC4454
1150 Ohm 0.5 Watt Metal Film Resistors - Pack of 8 RR0552
11.2k Ohm 0.5 Watt Metal Film Resistors - Pack of 8 RR0574
110k Ohm 0.5 Watt Metal Film Resistors - Pack of 8RR0596
1150mm Plug to Plug Jumper Leads - 40 PieceWC6024

The resistor values aren't critical, but the smallest one can't be smaller than 125R as this will overload the Uno's outputs. If you use different values, check the notes in the code about the changes that need to be made.

I used two plug-plug jumper cables as my probes, but you could just use any small wire (eg speaker cable) that is lying around. You'll also need a small piece of wire to make a connection on the Protoshield.

Apart from plugging the shields into the Uno, the hard part is soldering the three resistors and probe leads onto the proto shield. See the diagram and photo below.

Rct2Rct3

Once the resistors and wire have been soldered together, plug the Protoshield into the Uno, then plug the LCD Shield into the Protoshield (they should only go one way).

There aren't any extra libraries that are needed for this project as the 'LCD' and 'math' libraries are both included with the IDE. The code should work fine without changes on a Leonardo or Mega board if you have one of these instead.  If you're using different resistors, you'll need to change the definitions of the R1VALUE, R2VALUE or R3VALUE constants. You can also change the pins here too. The code uses some of the functions from the LED tester sketch (such as the key handling), but is mostly completely different.

The component detector works by putting 5V onto the 10k resistor, and if A4 is anything but very close to 5V, then something is connected and pulling the analog reading closer to GND.

The routine for working out if the component is a capacitor or resistor works by assuming it is a capacitor, and discharging it (via 150R resistor to GND), then measuring the voltage on it, then charging it up again and measuring the voltage. If the voltage has changed, then it is a capacitor, if it hasn't changed, then it's a resistor.

To measure a resistor, the three test resistors are each set up as a voltage divider with the test resistor, and the voltage at the junction measured. The resistor which gives a reading nearest 2.5V is chosen (as this will give the best precision), and the resistor value is calculated using the voltage divider formula: R2 = (R1 x V2)/V1. This routine exits when it detects a very high resistance, assuming this means the test resistor has been disconnected.

The capacitor tester starts by trying to discharge the capacitor for half a second (the results are more accurate the less the capacitor is charged). The voltage on it is measured, then it is charged from 5V via the 150R resistor for 0.1s, then the voltage on it is measured again. The ratio between the two voltages gives the proportion of charge (towards fully charged) it has received. When this is combined with the 0.1s time, the time constant for the resistor-capacitor combination can be worked out, and this is simply divided by the resistor value to give the capacitance value. If the capacitor ends up nearly fully charge, then the measurement is not completely accurate, and the test is redone with the 1k2 resistor. The results are then converted to easy to read units, rounded and displayed. Similarly, if this routine detects a very low capacitance, it assumes the test component has been removed and returns to the main detect routine.

The two leads are simply connected to the leads of the component you wish to test. If the component is polarised (eg. electrolytic capacitor), then the lead attached to A4 should go to the positive side and the GND lead to the negative side. I've made the leads different colours to remind me of this. The tester should only be used on circuits that aren't connected to power, especially as the UNO's chip can easily be damaged by voltages more than 6V. Components in circuit may not read correctly, as they will be influenced by other components they may be connected to.

One day, I hope to combine all the functions of the two testers to run off the same sketch (and maybe the same leads). As built, the tester will measure resistance from 0R up to the Megohms, and capacitance from nanofarads up to near a Farad. With some changes to the resistor and timing values, this range could be expanded slightly, but this is mostly limited by the accuracy and internal resistance of the ADC on the UNO. When we get a colour LCD screen, perhaps the resistor colour codes can be added as well. I haven't added a component part number recommendation for the capacitor test routine, because there are so many different voltage rating and capacitor types, that a given capacitor value would probably match up with several part numbers. There's no reason this couldn't be added if you knew (for example) that you were always using 16V electrolytic capacitors.

1
2 /* Arduino Resistor and Capacitor Tester
3
4 D13--10k---+---------------> Positive probe
5 D12--1k2---+
6 D11--150R--+ +-----------> Negative probe
7 | |
8 A4 GND
9
10 Resistor test by voltage divider- uses 3 different resistors to give auto-ranging.
11 Capacitor tester- Capacitance by time constant calculation, ESR by discharge and resistance test. (ESR not accurate so not displayed)
12 3 modes: Auto (on startup, or by pressing select)- tries to autodetect component and then measures
13 Resistor (press left)- assumes resistor and tries to measure resistance
14 Capacitor (press right)- assumes capacitor and tries to measure capacitance
15 */
16
17 //ranging resistor pins and values: R1 should be lowest (use a decimal point to make sure they're floats)
18 //values aren't critical, but should be span a good range
19 //lowest value possible is 125R- lower would overload the pin. Max is probably 100K due to leakage etc.
20 //if you have a good multimeter, you can tweak these values as calibration
21
22 #define R1VALUE 150.0
23 #define R2VALUE 1200.0
24 #define R3VALUE 10000.0
25 #define R1PIN 11
26 #define R2PIN 12
27 #define R3PIN 13
28 #define AIN A4
29 #define MIDRANGE 512
30 #define CAPTIME 0.1
31
32 #include <LiquidCrystal.h>
33 #include <Math.h>
34
35 //pin defs to suit LCD Shield
36 LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
37
38 //pin for buttons
39 #define KEYPIN A0
40
41 //button constants
42 #define btnRIGHT 6
43 #define btnUP 5
44 #define btnDOWN 4
45 #define btnLEFT 3
46 #define btnSELECT 2
47 #define btnNONE (-1)
48
49 //Globals for display
50 //resistors in Jaycar 1/2 W range, part nos start at RR0524 for 10R
51 #define RCOUNT 121
52 long rvals[]={10,11,12,13,15,16,18,20,22,24,27,30,33,36,39,43,47,51,56,62,68,
53 75,82,91,100,110,120,130,150,160,180,200,220,240,270,300,330,360,390,
54 430,470,510,560,620,680,750,820,910,1000,1100,1200,1300,1500,1600,1800,
55 2000,2200,2400,2700,3000,3300,3600,3900,4300,4700,5100,5600,6200,6800,
56 7500,8200,9100,10000,11000,12000,13000,15000,16000,18000,20000,22000,
57 24000,27000,30000,33000,36000,39000,43000,47000,51000,56000,62000,68000,
58 75000,82000,91000,100000,110000,120000,130000,150000,160000,180000,
59 200000,220000,240000,270000,300000,330000,360000,390000,430000,470000,
60 510000,560000,620000,680000,750000,820000,910000,1000000};
61 int cdetect=0; //variable for detected component 1=R, 2=C
62 int cselect=0; //to force component selection 0=auto, 1=R, 2=C
63
64 void setup() {
65 lcd.begin(16, 2); //lcd
66 lcdsplash();
67 lcd.setCursor(0, 1);
68 lcd.print(" Tester");
69 delay(1000);
70 }
71
72 void loop() {
73 waitconnect(); // wait till something is connected
74 if(cselect){cdetect=cselect;}else{cdetect=detect();} //goto selection if made, otherwise autodetect
75 switch(cdetect){
76 case 1:
77 doresistor();
78 lcdsplash(); //redo the splash screen in case it was written over
79 break;
80 case 2:
81 docapacitor();
82 lcdsplash(); //redo the splash screen in case it was written over
83 break;
84 default:
85 doerror();
86 break;
87 }
88 }
89
90 void doresistor(){
91 while(1){ //do it all repeatedly till the resistor is disconnected (see return; below)
92 int a1,a2,a3,a,diff;
93 float rdiv,rcalc,af; //rdiv= Rof divider, rcalc is R of resistor under test, af is float version of analog reading
94 pinMode(R1PIN,OUTPUT);
95 pinMode(R2PIN,INPUT);
96 pinMode(R3PIN,INPUT);
97 digitalWrite(R1PIN,HIGH);
98 delay(1);
99 a1=analogRead(AIN); //read with 1st resistor as voltage divider
100 pinMode(R1PIN,INPUT);
101 pinMode(R2PIN,OUTPUT);
102 digitalWrite(R2PIN,HIGH);
103 delay(1);
104 a2=analogRead(AIN); //read with 2nd resistor as voltage divider
105 pinMode(R2PIN,INPUT);
106 pinMode(R3PIN,OUTPUT);
107 digitalWrite(R3PIN,HIGH);
108 delay(1);
109 a3=analogRead(AIN); //read with 3rd resistor as voltage divider
110 pinMode(R3PIN,INPUT); //shut outputs down
111 //find the resistor which gives an analog value closest to 512- middle of the range gives best accuracy
112 a=a1;
113 rdiv=R1VALUE;
114 diff=abs(MIDRANGE-a1); //assume it's R1 and then see if there's a better match
115 if(abs(MIDRANGE-a2)<diff){ //R2 is better
116 a=a2;
117 rdiv=R2VALUE;
118 diff=abs(MIDRANGE-a2);
119 }
120 if(abs(MIDRANGE-a3)<diff){ //R3 is better
121 a=a3;
122 rdiv=R3VALUE;
123 diff=abs(MIDRANGE-a3);
124 }
125 if(a>=1022){ //open circuit, resistor has probably been detached, so go back to main screen, avoid div/0 error
126 return;
127 }else{
128 af=a;
129 rcalc=(af/(1023-af))*rdiv;
130 lcd.setCursor(0, 0);
131 lcd.print("Resistor: ");
132 lcdprintrval(rcalc);
133 int i=rmatch(rcalc); //find index of R that matches rcalc best
134 lcd.setCursor(0, 1);
135 lcd.print("Try ");
136 lcdprintpartno(i);
137 lcd.print("(");
138 lcdprintrval(rvals[i]);
139 lcd.print(")");
140 delay(300); //wait a bit so we get a steady display
141 }
142 }
143 }
144
145 int rmatch(float r){
146 int k=-1; //to store index of best match, default to -1
147 float d=1e9; //very big number, representing difference from matches
148 for(int j=0;j<j++){
149 if(abs(rvals[j]-r)<d){
150 d=abs(rvals[j]-r);
151 k=j;
152 }
153 }
154 return k;
155 }
156
157 void docapacitor(){
158 int alo,ahi;
159 float esr;
160 float c,ts,soc,t,ahif,alof,rvalue;
161 lcd.setCursor(0, 0);
162 lcd.print("Capacitor......."); //measuring caps might take a bit longer, so change display
163 while(1){ //stay in this loop until disconnected
164 pinMode(R1PIN,OUTPUT);
165 digitalWrite(R1PIN,LOW); //R1 to discharge as much as possible
166 pinMode(R2PIN,INPUT);
167 pinMode(R3PIN,INPUT);
168 delay(500);
169 pinMode(R1PIN,INPUT);
170 alo=analogRead(AIN); //to read ESR
171 digitalWrite(R1PIN,HIGH); //turn on power to detect voltage drop across cap-probably not super accurate
172 pinMode(R1PIN,OUTPUT);
173 ahi=analogRead(AIN); //difference with power on
174 digitalWrite(R1PIN,LOW); //R1 to discharge as much as possible
175 if(ahi<alo){ahi=alo;} //to avoid negative values
176 esr=0;
177 if(ahi<1023){
178 esr=((ahi-alo)*R1VALUE)/(1023-ahi);
179 }
180 //measure voltage on cap, charge up for t, measure state of charge, convert to tc's, work out C knowing R
181 digitalWrite(R1PIN,HIGH); //charge it up
182 alo=analogRead(AIN); //to read capacitance
183 delay(CAPTIME*1000);
184 ahi=analogRead(AIN); //to read capacitance
185 digitalWrite(R1PIN,LOW); //discharge (in case we need to do again)
186 rvalue=R1VALUE; //assume this is the one we're using
187 if(ahi>1000){ //very high termination, probably get more accurate results with 2nd resistor
188 rvalue=R2VALUE; //assume this is the one we're using
189 delay(500); //discharge
190 pinMode(R1PIN,INPUT);
191 pinMode(R2PIN,OUTPUT);
192 digitalWrite(R2PIN,HIGH); //charge it up
193 alo=analogRead(AIN); //to read capacitance
194 delay(CAPTIME*1000);
195 ahi=analogRead(AIN); //to read capacitance
196 digitalWrite(R1PIN,LOW); //discharge (in case we need to do again)
197 }
198 alof=alo;
199 ahif=ahi;
200 if((ahi==1023)||(alo>=ahi)){
201 return; //cap has charged up too quick to be measured or is too high value to change voltage
202 }else{
203 soc=(1023-ahif)/(1023-alof); //work out level of charge obtained
204 ts=-log(soc); //this is number of time constants elapsed
205 t=CAPTIME/ts; //time elapsed in seconds
206 c=t/rvalue; //capacitance is time constant divided by resistor
207 }
208 lcd.setCursor(0,1);
209 lcd.print(" "); //clear the line so we don't have stuff from the last reading
210 lcd.setCursor(5,1);
211 int p; //find position of most significant digits using log10- make it an int speed up the maths
212 float m; //multiplier to use
213 p=log10(c);
214 m=pow(10,p-2); //2 sf
215 c=round(c/m+0.5)*m;
216 if(c>1){ //show in Farads
217 lcd.print(c,ndig(c));
218 lcd.print("F");
219 }else if(c>1e-6){ //show in uF
220 c=c*1e6;
221 lcd.print(c,ndig(c));
222 lcd.print("uF");
223 }else{ //show in nF
224 c=c*1e9;
225 lcd.print(c,ndig(c));
226 lcd.print("nF");
227 }
228 delay(300);
229 }
230 }
231
232 int ndig(float c){ //work out how many decimal places to show
233 if(c>100){return 0;}
234 if(c>10){return 1;}
235 return 2;
236 }
237
238 int detect(){ //auto detect whether it's a cap or resistor connected
239 int ahi,alo;
240 lcd.setCursor(0, 1);
241 lcd.print("Detecting R or C");
242 pinMode(R1PIN,OUTPUT);
243 pinMode(R2PIN,INPUT);
244 pinMode(R3PIN,OUTPUT);
245 digitalWrite(R3PIN,LOW); //pull low to discharge- R3 will be used to stop output floating later
246 digitalWrite(R1PIN,LOW); //R1 to discharge as much as possible
247 delay(500);
248 pinMode(R1PIN,INPUT);
249 delay(1);
250 alo=analogRead(AIN); //should be near zero for a resistor
251 pinMode(R1PIN,OUTPUT);
252 digitalWrite(R1PIN,HIGH); //put some charge into it- we should be able to detect almost up to 1F, if not raise delay- not critical, just takes longer
253 delay(300);
254 pinMode(R1PIN,INPUT);
255 delay(1);
256 ahi=analogRead(AIN); //delay between turning output off and reading means very small caps might be discharge- smallest is about 1n
257 if(ahi-alo>4){return 2;}else{return 1;} //small difference > resistor
258 }
259
260 void doerror(){
261 lcd.setCursor(0, 1);
262 lcd.print("Can't autodetect ");
263 delay(1000);
264 }
265
266 void lcdsplash(){
267 lcd.setCursor(0, 0);
268 switch(cselect){
269 case 1:
270 lcd.print("Duinotech R mode");
271 break;
272 case 2:
273 lcd.print("Duinotech C mode");
274 break;
275 default:
276 lcd.print("Duinotech R & C ");
277 break;
278 }
279 }
280
281 void waitconnect(){
282 lcd.setCursor(0, 1);
283 lcd.print("Detecting ");
284 int ahi,alo;
285 int d=0;
286 pinMode(R1PIN,INPUT);
287 pinMode(R2PIN,INPUT);
288 pinMode(R3PIN,OUTPUT);
289 while(1){
290 digitalWrite(R3PIN,LOW);
291 delay(1);
292 alo=analogRead(AIN);
293 digitalWrite(R3PIN,HIGH);
294 delay(1);
295 ahi=analogRead(AIN);
296 if(ahi-alo<1000){return;}
297 d++;
298 if(d>13){d=0;}
299 lcd.setCursor(9+d%7,1);
300 if(d>6){lcd.print(" ");}else{lcd.print(".");}
301 dobuttons();
302 delay(100);
303 }
304 }
305
306 void lcdprintpartno(int index){
307 //part number
308 lcd.write('R');
309 lcd.write('R');
310 lcd.write('0');
311 lcd.write((((index+524)/100)%10)+'0'); //part no's start at RR0524 for 10R
312 lcd.write((((index+524)/10)%10)+'0');
313 lcd.write((((index+524))%10)+'0');
314 }
315
316 void lcdprintrval(long rval){ //print a value in 10k0 format, always outputs 4 characters
317 long mult=1;
318 long modval;
319 if(rval>999){mult=1000;}
320 if(rval>999999){mult=1000000;}
321 modval=(10*rval)/mult; //convert to final format, save a decimal place
322 if(modval>999){ //nnnM
323 lcd.write(((modval/1000)%10)+'0');
324 lcd.write(((modval/100)%10)+'0');
325 lcd.write(((modval/10)%10)+'0');
326 lcdprintmult(mult);
327 }else{
328 if(modval>99){ //nnMn
329 lcd.write(((modval/100)%10)+'0');
330 lcd.write(((modval/10)%10)+'0');
331 lcdprintmult(mult);
332 lcd.write(((modval)%10)+'0');
333 }else{ //_nMn
334 lcd.write(' ');
335 lcd.write(((modval/10)%10)+'0');
336 lcdprintmult(mult);
337 lcd.write(((modval)%10)+'0');
338 }
339 }
340 }
341
342 void lcdprintmult(long mult){ //helper function to print multiplier
343 switch (mult){
344 case 1: lcd.print('R');break;
345 case 1000: lcd.print('k');break;
346 case 1000000: lcd.print('M');break;
347 default: lcd.print('?');break;
348 }
349 }
350
351 int read_LCD_buttons(){
352 int adc_key_in = 0;
353 adc_key_in = analogRead(KEYPIN); // read the value from the sensor
354 delay(5); //switch debounce delay. Increase this delay if incorrect switch selections are returned.
355 int k = (analogRead(KEYPIN) - adc_key_in); //gives the button a slight range to allow for a little contact resistance noise
356 if (5 < abs(k)) return btnNONE; // double checks the keypress. If the two readings are not equal +/-k value after debounce delay, it tries again.
357 // my buttons when read are centered at these values: 0, 144, 329, 504, 741
358 // we add approx 50 to those values and check to see if we are close
359 if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
360 if (adc_key_in < 50) return btnRIGHT;
361 if (adc_key_in < 195) return btnUP;
362 if (adc_key_in < 380) return btnDOWN;
363 if (adc_key_in < 555) return btnLEFT;
364 if (adc_key_in < 790) return btnSELECT;
365 return btnNONE; // when all others fail, return this...
366 }
367
368 void dobuttons(){ //updates variables. debounces by only sampling at intervals
369 int key;
370 key = read_LCD_buttons();
371 if(key==btnLEFT){cselect=1;} //force resistor mode
372 if(key==btnRIGHT){cselect=2;} //force capacitor mode
373 if(key==btnUP){}
374 if(key==btnDOWN){}
375 if(key==btnSELECT){cselect=0;} //auto detect
376 if(key!=btnNONE){lcdsplash();} //update display to show setting
377 }

Similar projects you may be interested in

Portable Soil Moisture Meter
Test & Tools
Portable Soil moisture meter
Difficulty

Test & Tools
Wireless Garden Monitor
Difficulty

Arduino Based LED Tester
Test & Tools
Arduino Based LED Tester
Difficulty

Test & Tools
IoT Smart Wireless Switch
Difficulty