forked from kr4fty/ArduProj
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathardutester.ino
5047 lines (4899 loc) · 194 KB
/
ardutester.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 v1.1a 9/01/2016
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/
This Arduino program version:Villem Vannas
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)
- 26/11/2015 v08w LCD_I2C interface (VVA)
- 25/12/2015 v08w replaced lcd_clear(2)-->lcd_clear(1), lcd_clear_line(2) --> lcd_clear_line(1). problem with SCL&SDA ADC set/reset when probing. WatchDog for 8s
- 26/12/2015 v09w replaced PORTB --> PORTD. When D port then we need to use port pins 2,3,4,5,6,7, because pins 0,1 are used for communication.
Mask values shifted 2 additional bits (R_SHIFT) and when setting pin mode we should use DDRD = DDRD | B11111100
- 2.01.2016 v1.0 Different C++ display modules are working in same scheme and confg.h separated from main module
modules are: SerialDisplay - as DEBUG_PRINT, LcdDisplay - as LCD_PRINT with I2C interface, GraphicDisplay - as LCD_DOGM128
- 3.01.2016 v1.0 Graphical prsesentation of components and pins, stabilisation: diode and resistor testing loop occurs due to A3 pin mode; P-mosfet hanging due to infinite loop;
- 5.01.2016 PWM tooli with Timer1 improvements when DOGM128 display uses SPI interface and shares PB2 pin (using CD4066 chip in hardware platform)
- 7.01.2016 v1.1 PWM tool works now with all display modes
- 9.01.2016 v1.1a Zener
-15.01.2016 v1.1b Frequency measurement up to 1000Hz
-17.01.2016 v1.1c Frequency input amplifier and control with PB4 pin.
*/
//WorkAround for IDE ifndef bug
char foo;
#include "config.h"
//Check features
#if not defined(__AVR_ATmega328P__)
#error Sorry, this program works only on Arduino Uno
#endif
#if defined(LCD_PRINT) && defined(DEBUG_PRINT) && defined(LCD_DOGM128) && defined(LCD_PCD8544) && defined(LCD_SSD1306)
#error Invalid Parameters: Use LCD_PRINT or DEBUG_PRINT or LCD_DOGM128 or LCD_PCD8544 or LCD_SSD1306
#endif
#if !defined(LCD_PRINT) && !defined(DEBUG_PRINT) && !defined(LCD_DOGM128) && !defined(LCD_PCD8544) && !defined(LCD_SSD1306)
#error Invalid Parameters: Choose one of them: LCD_PRINT or DEBUG_PRINT or LCD_DOGM128 or LCD_PCD8544
#endif
//Includes
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <EEPROM.h>
// Only one of following three preprocessor variables should be set in config.h
// Graphic LCD
#ifdef LCD_DOGM128
#include "graphicdisplay.h"
GraphicDisplay lcd(13,11,10,9,U8G_PIN_NONE);
#endif
#ifdef LCD_PCD8544
#include "graphicdisplay.h"
GraphicDisplay lcd(2,3,5,4,6);
#endif
//LCD I2C Output
#ifdef LCD_PRINT
#include "display.h"
LcdDisplay lcd(I2C_ADDR);
#endif
#ifdef LCD_SSD1306
#include "oleddisplay.h"
OledDisplay lcd;
#define LCD_DOGM128
#endif
#ifdef DEBUG_PRINT
#include "serial.h"
SerialDisplay lcd;
#endif
//UINT32_MAX
#define UINT32_MAX ((uint32_t)-1)
//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))) //#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 = "Probing...";
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 = "done!";
const unsigned char Select_str[] PROGMEM = "Select";
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 Freq_str[] PROGMEM = "Measure Frequency";
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 = "Ardutester ";
const unsigned char Version_str[] PROGMEM = "v1.1c";
#if defined( DEBUG_PRINT) || defined(LCD_DOGM128) || defined(LCD_PCD8544)
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
// Function prototypes
void LoadAdjust(void);
byte TestKey(unsigned int Timeout, byte Mode);
void SetADCHiz(void);
void SetADCLow(void);
void UpdateProbes(byte Probe1, byte Probe2, byte Probe3);
byte ShortedProbes(byte Probe1, byte Probe2);
byte AllProbesShorted(void);
void DischargeProbes(void);
void PullProbe(byte Mask, byte Mode);
unsigned long RescaleValue(unsigned long Value, signed char Scale, signed char NewScale);
unsigned int GetFactor(unsigned int U_in, byte ID);
void CheckProbes(byte Probe1, byte Probe2, byte Probe3);
unsigned int ReadU(byte Probe);
unsigned int ReadU_5ms(byte Probe);
unsigned int ReadU_20ms(byte Probe);
void waitus(byte microsec);
unsigned long Get_hFE_C(byte Type);
void GetGateThreshold(byte Type);
unsigned int GetLeakageCurrent(void);
void CheckDiode(void);
void VerifyMOSFET(void);
void CheckBJTorEnhModeMOSFET(byte BJT_Type, unsigned int U_Rl);
void CheckDepletionModeFET(unsigned int U_Rl_L);
byte CheckThyristorTriac(void);
unsigned int SmallResistor(byte ZeroFlag);
void CheckResistor(void);
signed char CmpValue(unsigned long Value1, signed char Scale1, unsigned long Value2, signed char Scale2);
byte NumberOfDigits(unsigned long Value);
byte NumberOfDigits(unsigned long Value);
byte LargeCap(Capacitor_Type *Cap);
byte SmallCap(Capacitor_Type *Cap);
void MeasureCap(byte Probe1, byte Probe2, byte ID);
byte MeasureInductance(uint32_t *Time, byte Mode);
byte MeasureInductor(Resistor_Type *Resistor);
void DisplayValue(unsigned long Value, signed char Exponent, unsigned char Unit);
void DisplaySignedValue(signed long Value, signed char Exponent, unsigned char Unit);
void ShortCircuit(byte Mode);
byte TestKey(unsigned int Timeout, byte Mode);
void ShowFail(void);
void ShowError();
void ShowDiode_Uf(Diode_Type *Diode);
void ShowDiode_C(Diode_Type *Diode);
void ShowDiode(void);
void ShowBJT(void);
void Show_FET_IGBT_Extras(byte Symbol);
void ShowFET(void);
void ShowIGBT(void);
void ShowSpecial(void);
void ShowResistor(void);
void ShowCapacitor(void);
void LoadAdjust(void);
byte SelfTest(void);
byte SelfAdjust(void);
void ShowAdjust(void);
void PWM_Tool(unsigned int Frequency);
void SaveEEP(void);
void ReadEEP(void);
unsigned int EEPROMReadInt(int p_address);
void EEPROMWriteInt(int p_address, int p_value);
void MainMenu(void);
unsigned int selFreq(void);
void LcdMenu(void);
byte MenuTool(byte Items, byte Type, void *Menu[], unsigned char *Unit);
void DefaultPar(void);
void StartFreqMeasure(void);
//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)+R_SHIFT)), (1 << ((TP2 * 2)+R_SHIFT)), (1 << ((TP3 * 2)+R_SHIFT))};
//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
byte Millis; // Millis counter
//Frequency measure function variables
volatile unsigned int overflows = 0; // Timer/Counter 1.
volatile unsigned long edges = 0; // A variable to keep track of how many rising edges of the signal have been counted.
volatile unsigned long tstart = 0; // A variable to keep track of the count on Timer/Counter 1 when I start counting the edges of the signal.
volatile unsigned long tstop = 0; // A variable to keep track of the count on Timer/Counter 1 when I stop counting the edges of the signal.
volatile unsigned long tnow = 0; // A variable to store temporarily store the count on Timer/Counter 1.
const unsigned long cycles = 1000; // This specifies how many cycles over which I want to average the frequency.
float frequency = 0; // A variable to store the currently measured frequency
ISR(TIMER1_OVF_vect)
{
overflows += 1;
}
ISR(ANALOG_COMP_vect)
{
tnow = TCNT1; // current time
edges += 1;
if (edges == 1)
{ // Start counting edges.
tstart = overflows*65536 + tnow;
} else if (edges == cycles + 1) { // Stop counting edges.
tstop = overflows*65536 + tnow;
// Turn off Timer/Counter 1 and the comparator.
ACSR = 0;
TCCR1B = 0;
}
}
SIGNAL(TIMER2_COMPA_vect)
{
#ifdef LCD_DOGM128 || LCD_PCD8544
Millis++;
if( Millis == 255) {
lcd.update();
}
#endif
}
void measureFreq(void) {
#ifdef DEBUG_PRINT
int displayed = 0;
int ed = 0;
#endif
edges = 0L;
tstop = 0L;
tstart = 0L;
tnow = 0L;
ACSR = ACSR | B01000010; // enable analog comparator interrupt
// on failing edge (bit 1) which would actually capture a rising
// edge of the signal and use the internal bandgap reference
// voltage as the positive input (bit 6).
delay(5); // A short wait for bandgap voltage to stabilize.
overflows = 0;
TCCR1A = B00000000; // Set Timer/Counter 1 in normal mode where
// it will count to 0xFFFF then repeat.
TIMSK1 = TIMSK1 | B00000001; // Turn on Timer/Counter 1 overflow
// interrupt (bit 0).
// Turn on the counter with no prescaler.
TCCR1B = TCCR1B | B00000001;
ACSR = ACSR | B00001000; // Enable analog comparator interrupt
// (bit 3).
#ifdef BUTTON_INST
pinMode(TEST_BUTTON, INPUT_PULLUP); //Reinitialize the pushbutton pin as an input
#endif
while (edges < (cycles+1)) {
// Do something, dislay progess...
#ifdef DEBUG_PRINT
ed = edges;
if((ed % 100) == 0) {
if( displayed != ed ) {
displayed = ed;
DisplayValue(ed,0,0); Serial.println();
}
}
#else
lcd.setCursor(2,0);
DisplayValue(edges,0,0);
#endif
#ifdef BUTTON_INST
// Test is button pressed
if (!(digitalRead(TEST_BUTTON))) //If key is pressed
{
delay(500);
break;
}
#endif
}
// Calculate the frequency.
frequency = (float)16000000*(float)cycles/(float)(tstop - tstart);
}
//Setup function
void setup()
{
byte Test; //Test value
//Disable power on spi, twi, timer2
#ifndef LCD_DOGM128
// timer2 is used by dogm128 display loop interrupt
// SPI is used by dogm128 interface
#ifdef LCD_PCD8544
power_spi_disable();
#endif
power_timer2_disable();
#endif
#if !defined(LCD_PRINT) && !defined(LCD_SSD1306)
// twi i2c is used by lcd interface
power_twi_disable();
#endif
#if (R_SHIFT != 0)
// Set portB0 output and Low value
pinMode(8, OUTPUT); // PB0
digitalWrite( 8, LOW); // PB0
pinMode(12, OUTPUT); // PB4
digitalWrite(12, LOW); // PB4
#endif
#ifdef DEBUG_PRINT
Serial.begin(9600); //Serial Output
#else
#ifdef DEBUG_
Serial.begin(9600);
Serial.println("Start debugging!");
#endif
#endif
lcd.begin(16,2);
delay(5);
// Switch on the backlight
//lcd.setBacklightPin(BACKLIGHT_PIN,NEGATIVE);
//lcd.setBacklight(LED_ON);
// Print on the LCD
lcd.backlight();
lcd.lcd_clear();
lcd.setCursor(0,0);
//#endif
#ifdef LCD_PRINT
//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
#endif
lcd.home();
lcd.lcd_clear_line(0);
lcd.lcd_fixed_string(Splash_str);
#ifdef LCD_PCD8544
lcd.lcd_line(1);
#endif
lcd.lcd_fixed_string(Version_str);
#ifdef LCD_DOGM128 || LCD_PCD8544
lcd.update();
#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
#if defined(DEBUG_) || defined(DEBUG_PRINT)
Serial.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 Villem Vannas"));
Serial.println(X("Arduino initial version 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);
#if defined(LCD_DOGM128) || defined(LCD_PCD8544)
// Setting up timer2 for dogm128 update
OCR2A = 0xFF;
TIMSK2 |= _BV(OCIE2A);
#endif
}
//Main loop
void loop()
{
byte Test;
#ifdef DEBUG_
Serial.println("Testing key");
#endif
#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_8S); //Enable watchdog (timeout 2s --> 8s)
#endif
//Reset variables
lcd.component(COMPONENT_NONE);
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
//#ifdef LCD_PRINT
lcd.begin(16,2);
lcd.lcd_clear(); //Clear LCD
lcd.lcd_fixed_string(Splash_str);
#ifdef LCD_PCD8544
lcd.lcd_line(1);
#endif
lcd.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.lcd_fixed_string(Remove_str); //Display: Remove/Create
lcd.lcd_line(1);
lcd.lcd_fixed_string(ShortCircuit_str); //Display: short circuit!
}
else
{
//Display start of probing
lcd.lcd_line(1); //Move to line #2
lcd.lcd_fixed_string(Running_str); //Display: probing...
DischargeProbes();
if (Check.Found == COMP_ERROR) //Discharge failed
{ //Only for Standalone Version!
lcd.lcd_fixed_string(DischargeFailed_str); //Display: Battery?
//Display probe number and remaining voltage
lcd.lcd_line(1);
lcd.lcd_testpin(Check.Probe);
lcd.lcd_data(':');
lcd.lcd_space();
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);
#ifdef LCD_PRINT
lcd.begin(16,2);
#endif
//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.lcd_clear_line(1);
lcd.lcd_fixed_string(Running_str);
lcd.lcd_data('.');
#endif
//Check all possible combinations
MeasureCap(TP3, TP1, 0);
#ifdef LCD_PRINT
lcd.lcd_data('.');
#endif
MeasureCap(TP3, TP2, 1);
#ifdef LCD_PRINT
lcd.lcd_data('.');
#endif
MeasureCap(TP2, TP1, 2);
}
//Clear LCD
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
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();
}
//Component was found
RunsMissed = 0; //Reset counter
RunsPassed++; //Increase counter
}
#ifdef LCD_DOGM128 || LCD_PCD8544
lcd.update();
#endif
}
}
#ifdef DEBUG_
Serial.println("Text displayed...wait");
#endif
delay(1000); //Let the user read the text
wdt_disable(); //Disable watchdog
#ifdef DEBUG_
Serial.println("WDT disabled. back to loop");
#endif
}
//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)+R_SHIFT)) | (2 << ((TP2 * 2)+R_SHIFT)) | (2 << ((TP3 * 2)+R_SHIFT));
R_DDR |= (1 << ((TP1 * 2)+R_SHIFT)) | (1 << ((TP2 * 2)+R_SHIFT)) | (1 << ((TP3 * 2)+R_SHIFT));
//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;