-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathesr_meter_atmduino.ino
4850 lines (4692 loc) · 189 KB
/
esr_meter_atmduino.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
___ ___ _____ ___ ___ ___ ___ ___
/ /\ / /\ / /::\ /__/\ ___ / /\ / /\ ___ / /\ / /\
/ /::\ / /::\ / /:/\:\ \ \:\ / /\ / /:/_ / /:/_ / /\ / /:/_ / /::\
/ /:/\:\ / /:/\:\ / /:/ \:\ \ \:\ / /:/ / /:/ /\ / /:/ /\ / /:/ / /:/ /\ / /:/\:\
/ /:/~/::\ / /:/~/:/ /__/:/ \__\:| ___ \ \:\ / /:/ / /:/ /:/_ / /:/ /::\ / /:/ / /:/ /:/_ / /:/~/:/
/__/:/ /:/\:\ /__/:/ /:/___ \ \:\ / /:/ /__/\ \__\:\ / /::\ /__/:/ /:/ /\ /__/:/ /:/\:\ / /::\ /__/:/ /:/ /\ /__/:/ /:/___
\ \:\/:/__\/ \ \:\/:::::/ \ \:\ /:/ \ \:\ / /:/ /__/:/\:\ \ \:\/:/ /:/ \ \:\/:/~/:/ /__/:/\:\ \ \:\/:/ /:/ \ \:\/:::::/
\ \::/ \ \::/~~~~ \ \:\/:/ \ \:\ /:/ \__\/ \:\ \ \::/ /:/ \ \::/ /:/ \__\/ \:\ \ \::/ /:/ \ \::/~~~~
\ \:\ \ \:\ \ \::/ \ \:\/:/ \ \:\ \ \:\/:/ \__\/ /:/ \ \:\ \ \:\/:/ \ \:\
\ \:\ \ \:\ \__\/ \ \::/ \__\/ \ \::/ /__/:/ \__\/ \ \::/ \ \:\
\__\/ \__\/ \__\/ \__\/ \__\/ \__\/ \__\/
ARDUTESTER v0.X 25/04/2013
Original Source from: http://www.mikrocontroller.net/articles/AVR-Transistortester
Original Software: by Karl-Heinz Kuebbeler ([email protected])
The Ardutester software is based on porting by Markus Reschke ([email protected])
Schematic & Home Page: http://www.pighixxx.com/lavori/ardutester/
Arduino version: PighiXXX ([email protected])
PaoloP (http://www.arduino.cc/forum/index.php?action=profile;u=58300)
- ONLY TTL COMPONENTS!
TODO:
- Detailed Component Analysis
CHANGELOG:
- 01/05/2013 v06e - Waitus Function, String to Flash Functions, Killed 3 Goto :-), Code Cleanup - PighiXXX
- 01/05/2013 v06f - Killed all Goto (Thanks to PaoloP), Implemented Button
- 01/05/2013 v06g - Code Cleanup
- 02/05/2013 v06h - Code Cleanup, SERIAL-LCD Flag, I2C LCD Functions
- 02/05/2013 v06i - Button Flag, Button Function
- 02/05/2013 v06j - PowerSave Function, Code Cleanup, Flag only when more info
- 02/05/2013 v06k - Some fix (By PaoloP)
- 03/05/2013 v06l - Disabled digital input on analog pins (By PaoloP), Minor fixes
- 04/05/2013 v06m - ShowFET() fixed, Code Cleanup, Short Circuit Ok
- 05/05/2013 v06n - CheckResistor Function Ok
- 06/05/2013 v06o - SelfTest Function (v0.3), SelfAdjust, Minor fixes
- 21/05/2013 v06p - Add LCD no I2C, Removed Leonardo support: this sketch work only on ATmega328. (By PaoloP)
- 07/06/2013 v06q - ArduTester Software Client Functions (By PighiXXX)
- 08/07/2013 v07a - SmallResistor() fixes, Inductance Measurement, Leakage Current Measurement, BJT functions fixed, Minor fixes (By PighiXXX)
TODO ReCheck Print Functions & LCD Functions - This is an alpha version! Lightless version!
- 17/07/2013 v07b - MOSFETs function fixed, Minor fixes, Show Functions revisited, I2C LCD Deprecated, Deep debug :-)
Button Function revisited, PWM Tool, Serial Menu, AutoAdjust, EEProm functions (By PighiXXX)
- 21/07/2013 v07c Some fix (By PaoloP), LCD Functions revisited (By PighiXXX)
- 22/07/2013 v07d LCDMenu, Some fix (By PighiXXX)
- 23/07/2013 v07e SetDefault function, Some fix, selFreq optimized, TestKey improvements, Client support (By PighiXXX)
TWI, SPI, TIMER2 disabled (By PaoloP)
- 25/07/2013 v07f ReadU function revisited (By PaoloP), Some fix (By PaoloP & PighiXXX)
*/
//WorkAround for IDE ifndef bug
char foo;
//ARDUTESTER FEATURES
//Remember LCD_PRINT or DEBUG_PRINT
#define BUTTON_INST //Button Installed
#define LCD_PRINT //Print on LCD
//Remember DEBUG_PRINT or ATSW
//#define ATSW //ArduTester Software Client Enabled
//#define DEBUG_PRINT //Print on Serial Port
#define DET_COMP_ANALYSIS //Detailed Component Analysis (Soon)
#define TIMEOUT_BL 600 //LCD Backlight Timeout
#define LONG_PRESS 30 //Button Long Press era26 py2ohh
#define USER_WAIT 3000 //Nexpage Timeout
//Check features
#if not defined(__AVR_ATmega328P__)
#error Sorry, this program works only on Arduino Uno
#endif
#if defined(LCD_PRINT) && defined(DEBUG_PRINT)
#error Invalid Parameters: Use LCD_PRINT or DEBUG_PRINT
#endif
#if defined(DEBUG_PRINT) && defined(ATSW)
#error Invalid Parameters: Use DEBUG_PRINT or ATSW
#endif
//Includes
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <EEPROM.h>
//LCD Output
#ifdef LCD_PRINT
//#include <LiquidCrystal_I2C.h>
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
//LiquidCrystal_I2C lcd(0x27, 16,2);
LiquidCrystal lcd(7,6,5,4,3,2);
#endif
//UINT32_MAX
#define UINT32_MAX ((uint32_t)-1)
//Test probes - Must be an ADC port :-)
#define ADC_PORT PORTC //ADC port data register
#define ADC_DDR DDRC //ADC port data direction register
#define ADC_PIN PINC //Port input pins register
#define TP1 0 //Test pin 1 (=0)
#define TP2 1 //Test pin 2 (=1)
#define TP3 2 //Test pin 3 (=2)
/*
Probe resistors:
The resistors must be connected to the lower 6 pins of the port in
following sequence:
- pin 0: Rl1 680R (test pin 1)3w`12a
- pin 1: Rh1 470k (test pin 1)
- pin 2: Rl2 680R (test pin 2)
- pin 3: Rh2 470k (test pin 2)
- pin 4: Rl3 680R (test pin 3)
- pin 5: Rh3 470k (test pin 3)
*/
#define R_PORT PORTB //Port data register
#define R_DDR DDRB //Port data direction register
//Push button
#define TEST_BUTTON A3 //Test/start push button (low active)
//Button Delay
#define CYCLE_DELAY 3000
//ARDUESTER PARAMETERS
//Maximum number of measurements without any components found.
#define CYCLE_MAX 5
//ADC voltage reference based on Vcc (in mV).
#define UREF_VCC 5001
/*
Offset for the internal bandgap voltage reference (in mV): -100 up to 100
- To compensate any difference between real value and measured value.
- The ADC has a resolution of about 4.88mV for V_ref = 5V (Vcc) and
1.07mV for V_ref = 1.1V (bandgap).
- Will be added to measured voltage of bandgap reference.
*/
#define UREF_OFFSET 0
/*
Exact values of probe resistors.
- Standard value for Rl is 680 Ohms.
- Standard value for Rh is 470k Ohms.
*/
//Rl in Ohms
#define R_LOW 672
//Rh in Ohms
#define R_HIGH 462000
//Offset for systematic error of resistor measurement with Rh (470k) in Ohms.Valor 700
#define RH_OFFSET 700
/*
Resistance of probe leads (in 0.01 Ohms).
- Resistance of two probe leads in series.
- Assuming all probe leads got same/similar resistance.
*/
#define R_ZERO 20
/*
Capacitance of the wires between PCB and terminals (in pF).
Examples:
- 2pF for wires 10cm long ...valor 15
*/
#define CAP_WIRES 5
/*
Capacitance of the probe leads connected to the tester (in pF).
Examples:
capacity length of probe leads
-------------------------------
3pF about 10cm
9pF about 30cm
15pF about 50cm
*/
#define CAP_PROBELEADS 3
//Maximum voltage at which we consider a capacitor being discharged (in mV)valor 2
#define CAP_DISCHARGED 5
/*
Number of ADC samples to perform for each mesurement.
- Valid values are in the range of 1 - 255. valor 25
*/
#define ADC_SAMPLES 25
//Estimated internal resistance of port to GND (in 0.1 Ohms)
#define R_MCU_LOW 200 //Default: 209
//Estimated internal resistance of port to VCC (in 0.1 Ohms)
#define R_MCU_HIGH 220 //Default: 235
//Voltage offset of �Cs analog comparator (in mV): -50 up to 50
#define COMPARATOR_OFFSET 15
//Capacitance of the probe tracks of the PCB and the �C (in pF) valor = 42
#define CAP_PCB 15
//Total default capacitance (in pF): max. 255
#define C_ZERO CAP_PCB + CAP_WIRES + CAP_PROBELEADS
//ATMEGA328, 16Mhz Related
#define ADC_CLOCK_DIV (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0)
#define CPU_FREQ F_CPU
#define OSC_STARTUP 16384
//Components ID's
#define COMP_NONE 0
#define COMP_ERROR 1
#define COMP_MENU 2
#define COMP_RESISTOR 10
#define COMP_CAPACITOR 11
#define COMP_INDUCTOR 12
#define COMP_DIODE 20
#define COMP_BJT 21
#define COMP_FET 22
#define COMP_IGBT 23
#define COMP_TRIAC 24
#define COMP_THYRISTOR 25
//Chars
#define LCD_CHAR_UNSET 0 //Just a place holder
#define LCD_CHAR_DIODE1 1 //Diode icon '>|'
#define LCD_CHAR_DIODE2 2 //Diode icon '|<'
#define LCD_CHAR_CAP 3 //Capacitor icon '||'
#define LCD_CHAR_FLAG 4 //Flag Icon
#define LCD_CHAR_RESIS1 6 //Resistor left icon '['
#define LCD_CHAR_RESIS2 7 //Resistor right icon ']'
#ifdef DEBUG_PRINT
#define LCD_CHAR_OMEGA 79
#define LCD_CHAR_MICRO '\u00B5' //Code for Arduino Serial Monitor
#else
#define LCD_CHAR_OMEGA 244 //Default: 244
#define LCD_CHAR_MICRO 228
#endif
//Error type IDs
#define TYPE_DISCHARGE 1 //Discharge error
//FET type bit masks (also used for IGBTs)
#define TYPE_N_CHANNEL 0b00000001 //n channel
#define TYPE_P_CHANNEL 0b00000010 //p channel
#define TYPE_ENHANCEMENT 0b00000100 //Enhancement mode
#define TYPE_DEPLETION 0b00001000 //Depletion mode
#define TYPE_MOSFET 0b00010000 //MOSFET
#define TYPE_JFET 0b00100000 //JFET
#define TYPE_IGBT 0b01000000 //IGBT (no FET)
//Mode bitmask
#define MODE_LOW_CURRENT 0b00000001 //Low test current
#define MODE_HIGH_CURRENT 0b00000010 //High test current
#define MODE_DELAYED_START 0b00000100 //Delayed start
//BJT (bipolar junction transistor) type IDs
#define TYPE_NPN 1 //NPN
#define TYPE_PNP 2 //PNP
//Tester operation modes
#define MODE_CONTINOUS 0 //Continous
#define MODE_AUTOHOLD 1 //Auto hold
//Multiplicator tables
#define TABLE_SMALL_CAP 1
#define TABLE_LARGE_CAP 2
#define TABLE_INDUCTOR 3
//Bit flags for PullProbe()
#define FLAG_PULLDOWN 0b00000000
#define FLAG_PULLUP 0b00000001
#define FLAG_1MS 0b00001000
#define FLAG_10MS 0b00010000
//Tester modes, offsets and values
typedef struct
{
byte TesterMode; //Tester operation mode
byte SleepMode; //MCU sleep mode
byte Samples; //Number of ADC samples
byte AutoScale; //Flag to disable/enable ADC auto scaling
byte RefFlag; //Internal control flag for ADC
unsigned int U_Bandgap; //Voltage of internal bandgap reference (mV)
unsigned int RiL; //Internal pin resistance of �C in low mode (0.1 Ohms)
unsigned int RiH; //Internal pin resistance of �C in high mode (0.1 Ohms)
unsigned int RZero; //Resistance of probe leads (2 in series) (0.01 Ohms)
byte CapZero; //Capacity zero offset (input + leads) (pF)
signed char RefOffset; //Voltage offset of bandgap reference (mV)
signed char CompOffset; //Voltage offset of analog comparator (mV)
} Config_Type;
//Probes
typedef struct
{
//Probe pins
byte Pin_1; //Probe-1
byte Pin_2; //Probe-2
byte Pin_3; //Probe-3
//Bit masks for switching probes and test resistors
byte Rl_1; //Rl mask for probe-1
byte Rh_1; //Rh mask for probe-1
byte Rl_2; //Rl mask for probe-2
byte Rh_2; //Rh mask for probe-2
byte Rl_3; //Rl mask for probe-3
byte Rh_3; //Rh mask for probe-3
byte ADC_1; //ADC mask for probe-1
byte ADC_2; //ADC mask for probe-2
} Probe_Type;
//Checking/probing
typedef struct
{
byte Done; //Flag for transistor detection done
byte Found; //Component type which was found
byte Type; //Component specific subtype
byte Resistors; //Number of resistors found
byte Diodes; //Number of diodes found
byte Probe; //Error: probe pin
unsigned int U; //Error: voltage left in mV
} Check_Type;
//Resistor
typedef struct
{
byte A; //Probe pin #1
byte B; //Probe pin #2
byte Scale; //Exponent of factor (value * 10^x)
unsigned long Value; //Resistance
} Resistor_Type;
//Capacitor
typedef struct
{
byte A; //Probe pin #1
byte B; //Probe pin #2
signed char Scale; //Exponent of factor (value * 10^x)
unsigned long Value; //Capacitance incl. zero offset
unsigned long Raw; //Capacitance excl. zero offset
} Capacitor_Type;
//Inductor
typedef struct
{
signed char Scale; //Exponent of factor (value * 10^x)
unsigned long Value; //Inductance
} Inductor_Type;
//Diode
typedef struct
{
byte A; //Probe pin connected to anode
byte C; //Probe pin connected to cathode
unsigned int V_f; //Forward voltage in mV (high current)
unsigned int V_f2; //Forward voltage in mV (low current)
} Diode_Type;
//Bipolar junction transistor
typedef struct
{
byte B; //Probe pin connected to base
byte C; //Probe pin connected to collector
byte E; //Probe pin connected to emitter
unsigned long hFE; //Current amplification factor
//U_BE voltage
unsigned int I_CE0; //Leakage current (in �A)
} BJT_Type;
//FET
typedef struct
{
byte G; //Test pin connected to gate
byte D; //Test pin connected to drain
byte S; //Test pin connected to source
unsigned int V_th; //Threshold voltage of gate in mV
} FET_Type;
//Error (failed discharge) - Deprecated
typedef struct
{
} Error_Type;
//Output buffers
char OutBuffer[12];
char PRGBuffer[32];
//Configuration
Config_Type Config; //Tester modes, offsets and values
//Probing
Probe_Type Probes; //Test probes
Check_Type Check; //Checking/testing
//Components
Resistor_Type Resistors[3]; //Resistors (3 combinations)
Capacitor_Type Caps[3]; //Capacitors (3 combinations)
Diode_Type Diodes[6]; //Diodes (3 combinations in 2 directions)
BJT_Type BJT; //Bipolar junction transistor
FET_Type FET; //FET
Inductor_Type Inductor; //Inductor
//Store String to Flash Functions :-)
class __FlashStringHelper;
#define X(str) (strcpy_P(PRGBuffer, PSTR(str)), PRGBuffer)
//Strings
const unsigned char Mode_str[] PROGMEM = "Mode:";
const unsigned char Continous_str[] PROGMEM = "Continous";
const unsigned char AutoHold_str[] PROGMEM = "Auto Hold";
const unsigned char Running_str[] PROGMEM = "Mengukur...";
const unsigned char Weak_str[] PROGMEM = "weak";
const unsigned char Low_str[] PROGMEM = "low";
const unsigned char Failed1_str[] PROGMEM = "No component";
const unsigned char Failed2_str[] PROGMEM = "found!";
const unsigned char Thyristor_str[] PROGMEM = "SCR";
const unsigned char Triac_str[] PROGMEM = "Triac";
const unsigned char GAK_str[] PROGMEM = "GAC=";
const unsigned char Done_str[] PROGMEM = "selesai!";
const unsigned char Select_str[] PROGMEM = "pilih";
const unsigned char Selftest_str[] PROGMEM = "Selftest";
const unsigned char Adjustment_str[] PROGMEM = "Adjustment";
const unsigned char Default_str[] PROGMEM = "Default Values";
const unsigned char Save_str[] PROGMEM = "Save";
const unsigned char Show_str[] PROGMEM = "Show Values";
const unsigned char Remove_str[] PROGMEM = "Remove";
const unsigned char Create_str[] PROGMEM = "Create";
const unsigned char ShortCircuit_str[] PROGMEM = "Short Circuit!";
const unsigned char DischargeFailed_str[] PROGMEM = "<Battery?>";
const unsigned char Error_str[] PROGMEM = "Error!";
const unsigned char Battery_str[] PROGMEM = "Bat.";
const unsigned char OK_str[] PROGMEM = "ok";
const unsigned char MOS_str[] PROGMEM = "MOS";
const unsigned char FET_str[] PROGMEM = "FET";
const unsigned char Channel_str[] PROGMEM = "-ch";
const unsigned char Enhancement_str[] PROGMEM = "enh.";
const unsigned char Depletion_str[] PROGMEM = "dep.";
const unsigned char IGBT_str[] PROGMEM = "IGBT";
const unsigned char GateCap_str[] PROGMEM = "Cgs=";
const unsigned char GDS_str[] PROGMEM = "GDS=";
const unsigned char GCE_str[] PROGMEM = "GCE=";
const unsigned char NPN_str[] PROGMEM = "NPN";
const unsigned char PNP_str[] PROGMEM = "PNP";
const unsigned char EBC_str[] PROGMEM = "EBC=";
const unsigned char hFE_str[] PROGMEM ="h_FE=";
const unsigned char V_BE_str[] PROGMEM ="V_BE=";
const unsigned char I_CEO_str[] PROGMEM = "I_CEO=";
const unsigned char Vf_str[] PROGMEM = "Vf=";
const unsigned char DiodeCap_str[] PROGMEM = "C=";
const unsigned char Vth_str[] PROGMEM = "Vth=";
const unsigned char I_R_str[] PROGMEM = "I_R=";
const unsigned char URef_str[] PROGMEM = "Vref";
const unsigned char RhLow_str[] PROGMEM = "Rh-";
const unsigned char RhHigh_str[] PROGMEM = "Rh+";
const unsigned char RiLow_str[] PROGMEM = "Ri-";
const unsigned char RiHigh_str[] PROGMEM = "Ri+";
const unsigned char Rl_str[] PROGMEM = "+Rl-";
const unsigned char Rh_str[] PROGMEM = "+Rh-";
const unsigned char ProbeComb_str[] PROGMEM = "12 13 23";
const unsigned char CapOffset_str[] PROGMEM = "C0";
const unsigned char ROffset_str[] PROGMEM = "R0";
const unsigned char CompOffset_str[] PROGMEM = "AComp";
const unsigned char PWM_str[] PROGMEM = "PWM";
const unsigned char Hertz_str[] PROGMEM = "Hz";
const unsigned char Splash_str[] PROGMEM = "ESR METER ";
const unsigned char Version_str[] PROGMEM = "atmduino product";
#ifdef DEBUG_PRINT
const unsigned char Cap_str[] PROGMEM = {'-','|','|', '-',0};
const unsigned char Diode_AC_str[] PROGMEM = {'-', '>', '-', 0};
const unsigned char Diode_CA_str[] PROGMEM = {'-', '<', '-', 0};
const unsigned char Diodes_str[] PROGMEM = {'*', '>', ' ', ' ', 0};
const unsigned char Resistor_str[] PROGMEM = {'-', '[', ']', '-', 0};
#else
const unsigned char Cap_str[] PROGMEM = {'-',LCD_CHAR_CAP, '-',0};
const unsigned char Diode_AC_str[] PROGMEM = {'-', LCD_CHAR_DIODE1, '-', 0};
const unsigned char Diode_CA_str[] PROGMEM = {'-', LCD_CHAR_DIODE2, '-', 0};
const unsigned char Diodes_str[] PROGMEM = {'*', LCD_CHAR_DIODE1, ' ', ' ', 0};
const unsigned char Resistor_str[] PROGMEM = {'-', LCD_CHAR_RESIS1, LCD_CHAR_RESIS2, '-', 0};
#endif
//Diode icon with anode at left side
byte DiodeIcon1[8] = {0x11, 0x19, 0x1d, 0x1f, 0x1d, 0x19, 0x11, 0x00};
//Diode icon with anode at right side
byte DiodeIcon2[8] = {0x11, 0x13, 0x17, 0x1f, 0x17, 0x13, 0x11, 0x00};
//Capacitor icon
byte CapIcon[8] = {0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00};
//Resistor icon #1 (left part)
byte ResIcon1[8] = {0x00, 0x0f, 0x08, 0x18, 0x08, 0x0f, 0x00, 0x00};
//Resistor icon #2 (right part)
byte ResIcon2[8] = {0x00, 0x1e, 0x02, 0x03, 0x02, 0x1e, 0x00, 0x00};
//Flag Icon
byte FlagIcon[8] = {0x1f, 0x11, 0x0e, 0x04, 0x0a, 0x15, 0x1f, 0x00};
//Prefix Table
const unsigned char Prefix_table[] = {'p', 'n', LCD_CHAR_MICRO, 'm', 0, 'k', 'M'};
//PWM menu: frequencies
const unsigned int PWM_Freq_table[] = {100, 250, 500, 1000, 2500, 5000, 10000, 25000};
//Voltage based factors for large caps (using Rl)
const unsigned int LargeCap_table[] = {23022, 21195, 19629, 18272, 17084, 16036, 15104, 14271, 13520, 12841, 12224, 11660, 11143, 10668, 10229, 9822, 9445, 9093, 8765, 8458, 8170, 7900, 7645, 7405, 7178, 6963, 6760, 6567, 6384, 6209, 6043, 5885, 5733, 5589, 5450, 5318, 5191, 5069, 4952, 4839, 4731, 4627, 4526, 4430, 4336};
//Voltage based factors for small caps (using Rh)
const unsigned int SmallCap_table[] = {954, 903, 856, 814, 775, 740, 707, 676, 648};
//Ratio based factors for inductors
const unsigned int Inductor_table[] = {4481, 3923, 3476, 3110, 2804, 2544, 2321, 2128, 1958, 1807, 1673, 1552, 1443, 1343, 1252, 1169, 1091, 1020, 953, 890, 831, 775, 721, 670, 621, 574, 527, 481, 434, 386, 334, 271};
//Bitmasks for Rl probe resistors based on probe ID
const unsigned char Rl_table[] = {(1 << (TP1 * 2)), (1 << (TP2 * 2)), (1 << (TP3 * 2))};
//Bitmasks for ADC pins based on probe ID
const unsigned char ADC_table[] = {(1 << TP1), (1 << TP2), (1 << TP3)};
//Function prototype
byte SmallCap(Capacitor_Type *Cap);
byte LargeCap(Capacitor_Type *Cap);
byte MeasureInductor(Resistor_Type *Resistor);
void ShowDiode_Uf(Diode_Type *Diode);
void ShowDiode_C(Diode_Type *Diode);
//Program control
byte RunsPassed; //Counter for successful measurements
byte RunsMissed; //Counter for failed/missed measurements
byte ErrFnd; //An Error is occured
//Setup function
void setup()
{
byte Test; //Test value
//Disable power on spi, twi, timer2
//power_spi_disable();
//power_twi_disable();
//power_timer2_disable();
#ifdef LCD_PRINT
//lcd.init();
//lcd.backlight();
lcd.begin(16,2);
delay(5);
//Symbols for components
lcd.createChar(LCD_CHAR_DIODE1,DiodeIcon1); //Diode symbol |<|
lcd.createChar(LCD_CHAR_DIODE2,DiodeIcon2); //Diode symbol |<|
lcd.createChar(LCD_CHAR_CAP,CapIcon); //Capacitor symbol ||
lcd.createChar(LCD_CHAR_RESIS1,ResIcon1); //Resistor symbol [
lcd.createChar(LCD_CHAR_RESIS2,ResIcon2); //Resistor symbol ]
lcd.createChar(LCD_CHAR_FLAG,FlagIcon); //Flag symbol
lcd.home();
lcd.setCursor(3,0);
lcd_fixed_string(Splash_str);
lcd.setCursor(0,1);
lcd_fixed_string(Version_str);
#endif
#ifdef ATSW //Client Begin
Serial.begin(19200);
#endif
#ifdef DEBUG_PRINT
Serial.begin(9600); //Serial Output
#endif
//Setup �C
ADCSRA = (1 << ADEN) | ADC_CLOCK_DIV; //Enable ADC and set clock divider
MCUSR &= ~(1 << WDRF); //Reset watchdog flag
DIDR0 = 0b00110111;
wdt_disable(); //Disable watchdog
//Default offsets and values
Config.Samples = ADC_SAMPLES; //Number of ADC samples
Config.AutoScale = 1; //Enable ADC auto scaling
Config.RefFlag = 1; //No ADC reference set yet
delay(100);
//Reset variables
RunsMissed = 0;
RunsPassed = 0;
Config.TesterMode = MODE_CONTINOUS; //Set default mode: continous
#ifdef BUTTON_INST
pinMode(TEST_BUTTON, INPUT_PULLUP); //Initialize the pushbutton pin as an input
#endif
//Init
LoadAdjust(); //Load adjustment values
#ifdef DEBUG_PRINT
lcd.print(X("A R D U T E S T E R "));
lcd_fixed_string(Version_str); //Print Ardutester Version
Serial.println();
Serial.println(X(" By PighiXXX & PaoloP"));
Serial.println(X("original version by Markus Reschke"));
Serial.println();
#ifdef BUTTON_INST
Serial.print(X("Press Button to Probe"));
Serial.println(X(", long press enter Menu"));
#endif
#endif
delay(100);
}
//Main loop
void loop()
{
byte Test;
#ifdef BUTTON_INST
Test = TestKey(0, 0); //Wait user
#else
delay(3000); //No button installed, Wait 3 seconds
Test=1; //No button, no menu :-)
#endif
#ifdef WDT_enabled
wdt_enable(WDTO_2S); //Enable watchdog (timeout 2s)
#endif
//Reset variables
Check.Found = COMP_NONE;
Check.Type = 0;
Check.Done = 0;
Check.Diodes = 0;
Check.Resistors = 0;
BJT.hFE = 0;
BJT.I_CE0 = 0;
//Reset hardware
SetADCHiz(); //Set all pins of ADC port as input
lcd_clear(); //Clear LCD
#ifdef LCD_PRINT
lcd.setCursor(3,0); //proses pembacaan komponen
lcd_fixed_string(Splash_str);
//lcd_fixed_string(Version_str);
#endif
//Internal bandgap reference
Config.U_Bandgap = ReadU(0x0e); //Dummy read for bandgap stabilization
Config.Samples = 200; //Do a lot of samples for high accuracy
Config.U_Bandgap = ReadU(0x0e); //Get voltage of bandgap reference
Config.Samples = ADC_SAMPLES; //Set samples back to default
Config.U_Bandgap += Config.RefOffset; //Add voltage offset
if (Test==2) //Long Press
{
wdt_disable(); //Disable watchdog
MainMenu(); //Main Menu
}
else
{
if (AllProbesShorted() == 3) //All probes Shorted!
{
#ifdef DEBUG_PRINT
Serial.println();
#endif
lcd_fixed_string(Remove_str); //Display: Remove/Create
lcd_line(1);
lcd_fixed_string(ShortCircuit_str); //Display: short circuit!
}
else
{
//Display start of probing
lcd_line(1); //Move to line #2
lcd_fixed_string(Running_str); //Display: probing...
DischargeProbes();
if (Check.Found == COMP_ERROR) //Discharge failed
{ //Only for Standalone Version!
lcd.setCursor(3,0);
lcd_fixed_string(DischargeFailed_str); //Display: Battery?
//Display probe number and remaining voltage
lcd_line(1);
lcd.setCursor(0,1);
lcd.print("pin ");
lcd.setCursor(4,1);
lcd_testpin(Check.Probe);
lcd.setCursor(5,1);
lcd.print("(+)");
lcd_data(':');
lcd_space();
lcd.setCursor(10,1);
DisplayValue(Check.U, -3, 'V');
}
else //Skip all other checks
{
//Check all 6 combinations of the 3 probes
CheckProbes(TP1, TP2, TP3);
CheckProbes(TP2, TP1, TP3);
CheckProbes(TP1, TP3, TP2);
CheckProbes(TP3, TP1, TP2);
CheckProbes(TP2, TP3, TP1);
CheckProbes(TP3, TP2, TP1);
//If component might be a capacitor
if ((Check.Found == COMP_NONE) ||
(Check.Found == COMP_RESISTOR))
{
#ifdef DEBUG_PRINT
Serial.println();
Serial.println(X("Wait a moment..."));
#else
//Tell user to be patient with large caps
lcd_clear_line(1);
lcd_fixed_string(Running_str);
lcd_data('.');
#endif
//Check all possible combinations
MeasureCap(TP3, TP1, 0);
#ifdef LCD_PRINT
lcd_data('.');
#endif
MeasureCap(TP3, TP2, 1);
#ifdef LCD_PRINT
lcd_data('.');
#endif
MeasureCap(TP2, TP1, 2);
}
//Clear LCD
lcd_clear();
#ifdef BUTTON_INST
pinMode(TEST_BUTTON, INPUT_PULLUP); //Reinitialize the pushbutton pin as an input
#endif
//Call output function based on component type
#ifdef DEBUG_PRINT
Serial.print("Found: ");
//Components ID's
switch (Check.Found)
{
case COMP_ERROR:
Serial.println(X("Component Error!"));
break;
case COMP_NONE:
Serial.println(X("No Component!"));
break;
case COMP_RESISTOR:
Serial.println(X("Resistor"));
break;
case COMP_CAPACITOR:
Serial.println(X("Capacitor"));
break;
case COMP_INDUCTOR:
Serial.println(X("Inductor"));
break;
case COMP_DIODE:
Serial.println(X("Diode"));
break;
case COMP_BJT:
Serial.println(X("BJT"));
break;
case COMP_FET:
Serial.println(X("FET"));
break;
case COMP_IGBT:
Serial.println(X("IGBT"));
break;
case COMP_TRIAC:
Serial.println(X("TRIAC"));
break;
case COMP_THYRISTOR:
Serial.println(X("Thyristor"));
break;
}
#endif
switch (Check.Found)
{
case COMP_ERROR:
ShowError();
break;
case COMP_DIODE:
ShowDiode();
break;
case COMP_BJT:
ShowBJT();
break;
case COMP_FET:
ShowFET();
break;
case COMP_IGBT:
ShowIGBT();
break;
case COMP_THYRISTOR:
ShowSpecial();
break;
case COMP_TRIAC:
ShowSpecial();
break;
case COMP_RESISTOR:
ShowResistor();
break;
case COMP_CAPACITOR:
ShowCapacitor();
break;
default: //No component found
ShowFail();
}
#ifdef ATSW //Client output
Serial.println("@>");
Serial.println(Check.Found);
Serial.println("|");
Serial.println(Check.Type);
Serial.println("|");
Serial.println(Check.Done);
Serial.println("|");
Serial.println("@<");
//Component spedific output
#endif
//Component was found
RunsMissed = 0; //Reset counter
RunsPassed++; //Increase counter
}
}
}
delay(1000); //Let the user read the text
wdt_disable(); //Disable watchdog
}
//Set ADC port to HiZ mode
void SetADCHiz(void)
{
ADC_DDR &= ~(1<<TP1);
ADC_DDR &= ~(1<<TP2);
ADC_DDR &= ~(1<<TP3);
}
//Set ADC port low
void SetADCLow(void)
{
ADC_PORT &= ~(1<<TP1);
ADC_PORT &= ~(1<<TP2);
ADC_PORT &= ~(1<<TP3);
}
//Setup probes, bitmasks for probes and test resistors
void UpdateProbes(byte Probe1, byte Probe2, byte Probe3)
{
//DSt probe IDs
Probes.Pin_1 = Probe1;
Probes.Pin_2 = Probe2;
Probes.Pin_3 = Probe3;
//Setup masks using bitmask tables
Probes.Rl_1 = Rl_table[Probe1];
Probes.Rh_1 = Probes.Rl_1 + Probes.Rl_1;
Probes.ADC_1 = ADC_table[Probe1];
Probes.Rl_2 = Rl_table[Probe2];
Probes.Rh_2 = Probes.Rl_2 + Probes.Rl_2;
Probes.ADC_2 = ADC_table[Probe2];
Probes.Rl_3 = Rl_table[Probe3];
Probes.Rh_3 = Probes.Rl_3 + Probes.Rl_3;
}
//Check for a short circuit between two probes
byte ShortedProbes(byte Probe1, byte Probe2)
{
byte Flag = 0; //Return value
unsigned int U1; //Voltage at probe #1 in mV
unsigned int U2; //Voltage at probe #2 in mV
/*
Set up a voltage divider between the two probes:
- Probe1: Rl pull-up
- Probe2: Rl pull-down
- third probe: HiZ
*/
R_PORT = Rl_table[Probe1];
R_DDR = Rl_table[Probe1] | Rl_table[Probe2];
//Read voltages
U1 = ReadU(Probe1);
U2 = ReadU(Probe2);
/*
We expect both probe voltages to be about the same and
to be half of Vcc (allowed difference +/- 30mV).
*/
if ((U1 > UREF_VCC/2 - 30) && (U1 < UREF_VCC/2 + 30))
{
if ((U2 > UREF_VCC/2 - 30) && (U2 < UREF_VCC/2 + 30))
{
Flag = 1;
}
}
//Reset port
R_DDR = 0;
return Flag;
}
//Check for a short circuit between all probes
byte AllProbesShorted(void)
{
byte Flag = 0; //Return value
//Check all possible combinations
Flag = ShortedProbes(TP1, TP2);
Flag += ShortedProbes(TP1, TP3);
Flag += ShortedProbes(TP2, TP3);
return Flag;
}
//Try to discharge any connected components, e.g. capacitors
void DischargeProbes(void)
{
byte Counter; //Loop control
byte Limit = 40; //Sliding timeout (2s)
byte ID; //Test pin
byte DischargeMask; //Bitmask
unsigned int U_c; //Current voltage
unsigned int U_old[3]; //Old voltages
//Set probes to a save discharge mode (pull-down via Rh), Set ADC port to HiZ input
SetADCHiz();
SetADCLow();
//All probe pins: Rh and Rl pull-down
R_PORT = 0;
R_DDR = (2 << (TP1 * 2)) | (2 << (TP2 * 2)) | (2 << (TP3 * 2));
R_DDR |= (1 << (TP1 * 2)) | (1 << (TP2 * 2)) | (1 << (TP3 * 2));
//Get current voltages
U_old[0] = ReadU(TP1);
U_old[1] = ReadU(TP2);
U_old[2] = ReadU(TP3);
/*
Try to discharge probes
- We check if the voltage decreases over time.
- A slow discharge rate will increase the timeout to support
large caps.
- A very large cap will discharge too slowly and an external voltage
maybe never :-)
*/
Counter = 1;
ID = 2;
DischargeMask = 0;
while (Counter > 0)
{
ID++; //Next probe
if (ID > 2) ID = 0; //Start with probe #1 again
if (DischargeMask & (1 << ID)) //Skip discharged probe
continue;
U_c = ReadU(ID); //Get voltage of probe
if (U_c < U_old[ID]) //Voltage decreased
{
U_old[ID] = U_c; //Update old value
//Adapt timeout based on discharge rate
if ((Limit - Counter) < 20)
{
//Increase timeout while preventing overflow
if (Limit < (255 - 20)) Limit += 20;
}
Counter = 1; //Reset no-changes counter
}
else //Voltage not decreased
{
//Increase limit if we start at a low voltage
if ((U_c < 10) && (Limit <= 40)) Limit = 80;
Counter++; //Increase no-changes counter
}
if (U_c <= CAP_DISCHARGED) //Seems to be discharged
{
DischargeMask |= (1 << ID); //Set flag
}
else if (U_c < 800) //Extra pull-down
{
//It's save now to pull-down probe pin directly
ADC_DDR |= ADC_table[ID];
}
if (DischargeMask == 0b00000111) //All probes discharged
{
Counter = 0; //End loop
}
else if (Counter > Limit) //No decrease for some time
{
//Might be a battery or a super cap
Check.Found = COMP_ERROR; //Report error
Check.Type = TYPE_DISCHARGE; //Discharge problem
Check.Probe = ID; //Save probe
Check.U = U_c; //Save voltage
Counter = 0; //End loop
}
else //Go for another round
{
wdt_reset(); //Reset watchdog
delay(50); //Wait for 50ms
}
}
//Reset probes
R_DDR = 0; //Set resistor port to input mode
SetADCHiz(); //Set ADC port to input mode
}
//Pull probe up/down via probe resistor for 1 or 10 ms
void PullProbe(byte Mask, byte Mode)
{
//Set pull mode
if (Mode & FLAG_PULLUP) R_PORT |= Mask; //Pull-up
else R_PORT &= ~Mask; //Pull-down
R_DDR |= Mask; //Enable pulling
if (Mode & FLAG_1MS) delay(1); //Wait 1ms
else delay(10); //Wait 10ms
//Reset pulling
R_DDR &= ~Mask; //Set to HiZ mode
R_PORT &= ~Mask; //Set 0
}
//Rescale value
unsigned long RescaleValue(unsigned long Value, signed char Scale, signed char NewScale)
{
unsigned long NewValue;
NewValue = Value; //Take old value
while (Scale != NewScale) //Processing loop
{
if (NewScale > Scale) //Upscale
{
NewValue /= 10;
Scale++;
}
else //Downscale
{
NewValue *= 10;
Scale--;
}
}
return NewValue;
}
//Lokup a voltage/ratio based factor in a table and interpolate it's value
unsigned int GetFactor(unsigned int U_in, byte ID)
{
unsigned int Factor; //Return value
unsigned int U_Diff; //Voltage difference to table start
unsigned int Fact1, Fact2; //Table entries
unsigned int TabStart; //Table start voltage
unsigned int TabStep; //Table step voltage
unsigned int TabIndex; //Table entries (-2)
unsigned int *Table;