-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathArduinoTester.ino
2433 lines (2290 loc) · 83.5 KB
/
ArduinoTester.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
#include "arduino_secrets.h"
//Test with program in
#include <avr/io.h>
#include <util/delay.h>
#include <avr/sleep.h>
#include <stdlib.h>
#include "stdint.h" //JLG
#include <string.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <math.h>
#define MAIN_C
#include "Makefile.h" //JLG
#include "Transistortester.h"
#include "config.h"
#include "part_defs.h"
#include "lcd_routines.h"
#include "lcd_defines.h"
#include "wait1000ms.h"
#include "autoconf.h"
#include "tt_function.h"
#include "tt_resistor.h"
#include "bitmaps.h"
#include "font.h"
#include "24x32update_bitmaps.h"
/* defines global variables in RAM and EEprom from file tt_globals.h */
/* removed ifdef MAIN_C because always defined */
#define COMMON
#ifdef AUTO_CAL
const int8_t RefDiff EEMEM = REF_R_KORR; // correction of internal Reference Voltage
// const uint16_t cap_null EEMEM = C_NULL; // Zero offset of capacity measurement
const int16_t ref_offset EEMEM = REF_C_KORR; // default correction of internal reference voltage for capacity measurement
// the zero offset for capacity measurement for all pin combinations
// LoPin:HiPin 2:1 3:1 1:2 marker 3:2 1:3 2:3
const uint8_t c_zero_tab[] EEMEM = { C_NULL,C_NULL,C_NULL+TP2_CAP_OFFSET,C_NULL+2,C_NULL+TP2_CAP_OFFSET,C_NULL,C_NULL }; //table of zero offsets
// if the marker position of c_zero_tab is not equal the first position, the calibration has not run before
#endif
#ifdef SamplingADC
const uint16_t c_zero_tab2_lo[] EEMEM = { C_NULL*100,C_NULL*100,C_NULL*100,C_NULL*100,C_NULL*100,C_NULL*100,C_NULL*100 }; // zero offsets for SamplingADC capacitance measurement, in 0.01 pF, lo voltage
const uint16_t c_zero_tab2_hi[] EEMEM = { C_NULL*100,C_NULL*100,C_NULL*100,C_NULL*100,C_NULL*100,C_NULL*100,C_NULL*100 }; // same, hi voltage
#endif
#ifdef WITH_MENU
const int8_t big_cap_corr EEMEM = C_H_KORR; // default correction for big capacity measurement
#if defined(WITH_FREQUENCY_DIVIDER) && !defined(NO_FREQ_COUNTER)
#ifndef FREQ_SCALER
#define FREQ_SCALER 0 // 1<<0 = 1
#endif
const uint8_t f_scaler EEMEM = FREQ_SCALER; // default scaler for frequency measurement
#endif
#endif
const uint8_t EE_ESR_ZEROtab[] EEMEM = {ESR_ZERO, ESR_ZERO, ESR_ZERO, ESR_ZERO}; // zero offset of ESR measurement
#ifdef WITH_ROTARY_SWITCH
// const uint8_t EE_RotarySwitch EEMEM = 0; // rotation switch is not detected
#endif
#if ((LCD_ST_TYPE == 7565) || (LCD_ST_TYPE == 1306) || (LCD_ST_TYPE == 8812) || (LCD_ST_TYPE == 8814) || defined(LCD_DOGM))
const uint8_t EE_Volume_Value EEMEM = VOLUME_VALUE; // Volume Value for ST7565 controller
#endif
#ifdef LCD_CHANGE_COLOR
const uint8_t EE_BG_COLOR1 EEMEM = LCD_BG_COLOR & 0xff; // lower bits of background color
const uint8_t EE_BG_COLOR2 EEMEM = LCD_BG_COLOR >> 8; // higher bits of background color
const uint8_t EE_FG_COLOR1 EEMEM = LCD_FG_COLOR & 0xff; // lower bits of foreground color
const uint8_t EE_FG_COLOR2 EEMEM = LCD_FG_COLOR >> 8; // higher bits of foreground color
#endif
struct Diode_t {
uint8_t Anode[6];
uint8_t Cathode[6];
unsigned int Voltage[6];
};
COMMON struct Diode_t diodes;
struct Switch_t {
union {
unsigned long Pw; // combined Mask
uint8_t R[4]; // mask to switch a Pin with R_L, mask to switch a Pin with R_H
} Pin;
};
COMMON uint8_t NumOfDiodes;
COMMON uint8_t diode_sequence;
typedef struct {
unsigned long hfe; //current amplification factor
unsigned int uBE; //B-E-voltage of the Transistor or RDS for E-MOS; Idss for JFET
unsigned int current; // current of Drain in 1uA
unsigned int ice0; // for BJT ICEO in 1uA; for FET cut-off voltage in mV
unsigned int gthvoltage; //Gate-threshold voltage
// for bipolar gthvoltage is ICEs in 1uA
#define ices gthvoltage
// note: don't change the total size of the above fields, since the offsets of the following 3 fields are hard-coded in PinLayout.S
uint8_t b,c,e; //pins of the Transistor
uint8_t count;
}trans_t;
COMMON trans_t ptrans; // parameters of P type transistor
COMMON trans_t ntrans; // parameters of N type transistor
COMMON trans_t *_trans; // pointer to trans_t structure
COMMON uint8_t tmpval, tmpval2;
COMMON unsigned int ref_mv; //Reference-voltage in mV units (as read with ADC)
COMMON unsigned int ref_mv_offs; //Reference-voltage in mV units with eeprom offset for C
COMMON unsigned int adc_internal_reference; //internal reference voltage of ADC in mV units
COMMON unsigned int adc_vcc_reference; // reference voltage of ADC,if switched to VCC in mV units
COMMON unsigned int RHmultip; // Multiplier for capacity measurement with R_H (470KOhm)
#ifdef WITH_MENU
COMMON union t_frq{
unsigned long dw;
uint16_t w[2];
uint8_t b[4];
} ext_freq; // external frequency
//COMMON unsigned long ext_period;
COMMON unsigned int pinchange_count;
COMMON unsigned int pinchange_max;
#endif
COMMON struct cap_t {
// Attention! If you change this structure, you must also change defines in GetESR.S !!!!
unsigned long cval; // capacitor value
unsigned long cval_max; //capacitor with maximum value
union t_combi{
unsigned long dw; // capacity value without corrections
uint16_t w[2];
} cval_uncorrected;
#if FLASHEND > 0x1fff
unsigned int esr; // serial resistance of C in 0.01 Ohm
unsigned int v_loss; // voltage loss 0.1%
#endif
uint8_t ca, cb; //pins of capacitor
int8_t cpre; //Prefix for capacitor value -12=p, -9=n, -6=µ, -3=m
int8_t cpre_max; //Prefix of the biggest capacitor
} cap;
unsigned int cell_mv[3]; //remaining load voltages after discharge cycle
#ifndef INHIBIT_SLEEP_MODE
/* with sleep mode we need a global ovcnt16 */
COMMON volatile uint16_t ovcnt16;
COMMON volatile uint8_t unfinished;
#endif
COMMON int16_t load_diff; // difference voltage of loaded capacitor and internal reference
COMMON uint8_t WithReference; // Marker for found precision voltage reference = 1
COMMON uint8_t PartFound; // type of the found part
COMMON uint8_t PartMode; // description of the found part
COMMON char outval[10]; // String for ASCII-output i2lcd, u2lcd
//COMMON char OutBuffer[10]; // String for ASCII-output DisplayValue
COMMON uint8_t empty_count; // counter for max count of empty measurements
COMMON uint8_t mess_count; // counter for max count of nonempty measurements
COMMON struct ADCconfig_t {
uint8_t Samples; // number of ADC samples to take
uint8_t RefFlag; // save Reference type VCC of IntRef
uint16_t U_Bandgap; // Reference Voltage in mV
uint16_t U_AVCC; // Voltage of AVCC
} ADCconfig;
#ifdef AUTO_CAL
COMMON uint8_t pin_combination; // coded Pin-combination 2:1,3:1,1:2,x:x,3:2,1:3,2:3
COMMON uint16_t resis680pl; // port output resistance + 680
COMMON uint16_t resis680mi; // port output resistance + 680
COMMON uint16_t pin_rmi; // port output resistance to GND side, 0.1 Ohm units
COMMON uint16_t pin_rpl; // port output resistance to VCC side, 0.1 Ohm units
COMMON uint8_t UnCalibrated; // 0, if the tester is calibrated
#endif
#ifdef WITH_ROTARY_SWITCH
#define ROT_MSK 0x03 /* must be power of two - 1: 3,7,15 */
struct Rotary_t {
uint8_t state[(ROT_MSK+1)]; // coded state history of the rotatry switch, bit 0 == state of A-switch, bit 1 = state of B-switch
uint8_t ind; // index to the last entry of the state history (rotary switch)
int8_t count; // count of right steps, negative if left steps
uint8_t incre; // absolute value of step count
#if WITH_ROTARY_SWITCH == 4
// no rotary switch connected, UP and DOWN key is present
uint8_t a_state; // history of switch A state for single UP switch
uint8_t b_state; // history of switch B state for single DOWN switch
#endif
};
COMMON struct Rotary_t rotary;
COMMON uint8_t rotary_switch_present; // is set to 1, if rotary switch movement is detected
// COMMON const uint8_t EE_RotarySwitch; // rotation switch is detected
#endif
#if FLASHEND > 0x1fff
COMMON uint8_t DC_Pwr_mode;
#endif
COMMON uint8_t lcd_text_line;
COMMON uint8_t _lcd_column;
COMMON uint8_t last_line_used;
//#if POWER_OFF+0 > 1
COMMON unsigned int display_time; // display time of measurement in ms units
//#endif
#if (LCD_ST_TYPE == 7920)
COMMON uint8_t lcd_bit_mem[64][16];
#endif
#if ((LCD_ST_TYPE == 7565) || (LCD_ST_TYPE == 1306) || defined(LCD_DOGM))
COMMON const uint8_t EE_Volume_Value EEMEM; // Volume Value for ST7565 controller
#endif
#ifdef LCD_CHANGE_COLOR
COMMON union {
uint16_t w;
uint8_t b[2];
} lcd_bg_color;
#endif
#if defined(LCD_CHANGE_COLOR) || defined(LCD_ICON_COLOR)
COMMON union {
uint16_t w;
uint8_t b[2];
} lcd_fg_color;
#endif
#if defined(LCD_ICON_COLOR)
COMMON union {
uint16_t w;
uint8_t b[2];
} lcd_fg2_color;
#endif
/* END defines global variables in RAM and EEprom from file tt_globals.h */
#ifndef INHIBIT_SLEEP_MODE
// prepare sleep mode
EMPTY_INTERRUPT(TIMER2_COMPA_vect);
#endif
#if !defined(INHIBIT_SLEEP_MODE) || defined(SamplingADC)
// ADC_vect is always required by samplingADC()
EMPTY_INTERRUPT(ADC_vect);
#endif
/**************************************************
*** begin of transistortester program
***************************************************/
void setup() {
#ifdef WITH_HARDWARE_SERIAL
Serial.begin(115200); // Serial Monitor
#endif
//#ifdef ARDUINO_UNO
// pinMode(A3,INPUT_PULLUP);// avoids external 10K Pullup
//#endif
uint8_t ii;
unsigned int max_time;
#ifdef SEARCH_PARASITIC
unsigned long n_cval; // capacitor value of NPN B-E diode, for deselecting the parasitic Transistor
int8_t n_cpre; // capacitor prefix of NPN B-E diode
#endif
#ifdef WITH_GRAPHICS
unsigned char options;
#endif
uint8_t vak_diode_nr; // number of the protection diode of BJT
union {
uint16_t pw;
uint8_t pb[2];
} rpins;
uint8_t x, y, z;
//switch on
ON_DDR = (1<<ON_PIN); // switch to output
ON_PORT = (1<<ON_PIN); // switch power on
#ifndef PULLUP_DISABLE
RST_PORT |= (1<<RST_PIN); // enable internal Pullup for Start-Pin
#endif
uint8_t tmp;
//ADC-Init
ADCSRA = (1<<ADEN) | AUTO_CLOCK_DIV; //prescaler=8 or 64 (if 8Mhz clock)
#ifdef __AVR_ATmega8__
// #define WDRF_HOME MCU_STATUS_REG
#define WDRF_HOME MCUCSR
#else
#define WDRF_HOME MCUSR
#if FLASHEND > 0x3fff
// probably was a bootloader active, disable the UART
UCSR0B = 0; // disable UART, if started with bootloader
#endif
#endif
wait500ms();
#if (PROCESSOR_TYP == 644) || (PROCESSOR_TYP == 1280)
#define BAUD_RATE 9600
// UBRR0H = (F_CPU / 16 / BAUD_RATE - 1) >> 8;
// UBRR0L = (F_CPU / 16 / BAUD_RATE - 1) & 0xff;
// UCSR0B = (1<<TXEN0);
// UCSR0C = (1<<USBS0) | (3<<UCSZ00); // 2 stop bits, 8-bit
// while (!(UCSR0A & (1<<UDRE0))) { }; // wait for send data port ready
#ifdef SWUART_INVERT
SERIAL_PORT &= ~(1<<SERIAL_BIT);
#else
SERIAL_PORT |= (1<<SERIAL_BIT);
#endif
SERIAL_DDR |= (1<<SERIAL_BIT);
#endif
tmp = (WDRF_HOME & ((1<<WDRF))); // save Watch Dog Flag
WDRF_HOME &= ~(1<<WDRF); //reset Watch Dog flag
wdt_disable(); // disable Watch Dog
#ifndef INHIBIT_SLEEP_MODE
// switch off unused Parts
#if PROCESSOR_TYP == 644
#ifdef PRUSART1
PRR0 = (1<<PRTWI) | (1<<PRSPI) | (1<<PRUSART1);
#else
PRR0 = (1<<PRTWI) | (1<<PRSPI) ;
#endif
// PRR1 = (1<<PRTIM3) ;
#elif PROCESSOR_TYP == 1280
PRR0 = (1<<PRTWI) | (1<<PRSPI) | (1<<PRUSART1);
PRR1 = (1<<PRTIM5) | (1<<PRTIM4) | (1<<PRTIM3) | (1<<PRUSART3) | (1<<PRUSART2) | (1<<PRUSART3);
#else
PRR = (1<<PRTWI) | (1<<PRSPI) | (1<<PRUSART0);
#endif
// disable digital inputs of Analog pins, but TP1-3 digital inputs must be left enabled for VGS measurement
DIDR0 = ((1<<ADC5D) | (1<<ADC4D) | (1<<ADC3D) | (1<<ADC2D) | (1<<ADC1D) | (1<<ADC0D)) & ~((1<<TP3) | (1<<TP2) | (1<<TP1));
TCCR2A = (0<<WGM21) | (0<<WGM20); // Counter 2 normal mode
TCCR2B = CNTR2_PRESCALER; //prescaler set in autoconf
#endif /* INHIBIT_SLEEP_MODE */
sei(); // enable interrupts
lcd_init(); //initialize LCD
// ADC_PORT = TXD_VAL;
// ADC_DDR = TXD_MSK;
if(tmp) {
// check if Watchdog-Event
// this happens, if the Watchdog is not reset for 2s
// can happen, if any loop in the Program doen't finish.
lcd_line1();
lcd_MEM_string(TestTimedOut); //Output Timeout
wait_about3s(); // time to read the Timeout message
switch_tester_off();
return 0;
}
#ifdef PULLUP_DISABLE
#ifdef __AVR_ATmega8__
SFIOR = (1<<PUD); // disable Pull-Up Resistors mega8
#else
MCUCR = (1<<PUD); // disable Pull-Up Resistors mega168 family
#endif
#endif
//#if POWER_OFF+0 > 1
// tester display time selection
#ifndef USE_EEPROM
EE_check_init(); // init EEprom, if unset
#endif
#ifdef WITH_ROTARY_SWITCH
// rotary_switch_present = eeprom_read_byte(&EE_RotarySwitch);
rotary.ind = ROT_MSK+1; //initilize state history with next call of check_rotary()
#endif
#ifdef WITH_HARDWARE_SERIAL
// ii = 60;
ii = 30;
#else
#if 1
for (ii=0; ii<60; ii++) {
if (RST_PIN_REG & (1 << RST_PIN))
break; // button is released
wait_about10ms();
}
#else
ii = 0;
if (!(RST_PIN_REG & (1<<RST_PIN))) {
// key is still pressed
ii = wait_for_key_ms(700);
}
#endif
display_time = OFF_WAIT_TIME; // LONG_WAIT_TIME for single mode, else SHORT_WAIT_TIME
if (ii > 30) {
display_time = LONG_WAIT_TIME; // ... set long time display anyway
}
#endif // WITH_HARDWARE_SERIAL
#if POWER_OFF+0 > 1
empty_count = 0;
mess_count = 0;
#endif
ADCconfig.RefFlag = 0;
Calibrate_UR(); // get Ref Voltages and Pin resistance
#ifdef WDT_enabled
wdt_enable(WDTO_2S); //Watchdog on
#endif
#ifdef WITH_MENU
if (ii >= 60) {
while(function_menu()); // selection of function
}
#endif
//*****************************************************************
//Entry: if start key is pressed before shut down
loop_start:
#if ((LCD_ST_TYPE == 7565) || (LCD_ST_TYPE == 1306))
lcd_command(CMD_DISPLAY_ON);
lcd_command(CMD_SET_ALLPTS_NORMAL); // 0xa4
#endif
lcd_clear(); // clear the LCD
ADC_DDR = TXD_MSK; // activate Software-UART
init_parts(); // reset parts info to nothing found
Calibrate_UR(); // get Ref Voltages and Pin resistance
lcd_line1(); // Cursor to 1. row, column 1
#ifdef BAT_CHECK
// Battery check is selected
Battery_check();
#else
lcd_MEM_string(VERSION_str); // if no Battery check, Version .. in row 1
#endif /* BAT_CHECK */
// begin tests
#if FLASHEND > 0x1fff
if (WithReference) {
/* 2.5V precision reference is checked OK */
#if POWER_OFF+0 > 1
if ((mess_count == 0) && (empty_count == 0))
#endif
{
/* display VCC= only first time */
lcd_line2();
lcd_MEM_string(VCC_str); // VCC=
Display_mV(ADCconfig.U_AVCC,3); // Display 3 Digits of this mV units
lcd_refresh(); // write the pixels to display, ST7920 only
wait_about1s(); // time to read the VCC= message
}
}
#endif
#ifdef WITH_VEXT
unsigned int Vext;
// show the external voltage
while (!(RST_PIN_REG & (1<<RST_PIN))) {
lcd_clear_line2();
lcd_MEM_string(Vext_str); // Vext=
ADC_DDR = 0; //deactivate Software-UART
Vext = W5msReadADC(TPext); // read external voltage
// ADC_DDR = TXD_MSK; //activate Software-UART
uart_newline(); // MAURO replaced uart_putc(' ') by uart_newline(), 'Z'
#if EXT_NUMERATOR <= (0xffff/U_VCC)
Display_mV(Vext*EXT_NUMERATOR/EXT_DENOMINATOR,3); // Display 3 Digits of this mV units
#else
DisplayValue((unsigned long)Vext*EXT_NUMERATOR/EXT_DENOMINATOR,-3,'V',3); // Display 3 Digits of this mV units
#endif
lcd_refresh(); // write the pixels to display, ST7920 only
wait_about300ms(); // delay to read the Vext= message
}
#endif /* WITH_VEXT */
#ifndef DebugOut
lcd_line2(); //LCD position row 2, column 1
#endif
EntladePins(); // discharge all capacitors!
if(PartFound == PART_CELL) {
lcd_clear();
lcd_MEM_string(Cell_str); // display "Cell!"
#if FLASHEND > 0x3fff
lcd_line2(); // use LCD line 2
Display_mV(cell_mv[0],3);
lcd_space();
Display_mV(cell_mv[1],3);
lcd_space();
Display_mV(cell_mv[2],3);
#endif
#ifdef WITH_SELFTEST
lcd_refresh(); // write the pixels to display, ST7920 only
wait_about2s();
AutoCheck(0x11); // full Selftest with "Short probes" message
#endif
goto tt_end;
}
#ifdef WITH_SELFTEST
#ifdef AUTO_CAL
lcd_cursor_off();
UnCalibrated = (eeprom_read_byte(&c_zero_tab[3]) - eeprom_read_byte(&c_zero_tab[0]));
if (UnCalibrated != 0) {
// if calibrated, both c_zero_tab values are identical! c_zero_tab[3] is not used otherwise
lcd_cursor_on();
}
#endif
#ifdef WITH_MENU
AutoCheck(0x00); //check, if selftest should be done, only calibration
#else
AutoCheck(0x01); //check, if selftest should be done, full selftest without MENU
#endif
#endif
#if FLASHEND > 0x1fff
lcd_clear_line2(); //LCD position row2, column 1
#else
lcd_line2(); //LCD position row2, column 1
#endif
lcd_MEM_string(TestRunning); //String: testing...
lcd_refresh(); // write the pixels to display, ST7920 only
#ifdef WITH_UART
uart_putc(0x03); // ETX, start of new measurement
uart_newline(); // MAURO Added
#endif
//
// check all 6 combinations for the 3 pins
// High Low Tri
CheckPins(TP1, TP2, TP3);
CheckPins(TP2, TP1, TP3);
CheckPins(TP1, TP3, TP2);
CheckPins(TP3, TP1, TP2);
CheckPins(TP2, TP3, TP1);
CheckPins(TP3, TP2, TP1);
// Capacity measurement is only possible correctly with two Pins connected.
// A third connected pin will increase the capacity value!
// if(((PartFound == PART_NONE) || (PartFound == PART_RESISTOR) || (PartFound == PART_DIODE)) ) {
if(PartFound == PART_NONE) {
// If no part is found yet, check separate if is is a capacitor
#ifdef DebugOut
lcd_data('C');
#endif
EntladePins(); // discharge capacities
//measurement of capacities in all 3 combinations
ReadCapacity(TP3, TP1);
#ifdef DebugOut
lcd_data('K');
#endif
#if DebugOut != 10
ReadCapacity(TP3, TP2);
#ifdef DebugOut
lcd_data('K');
#endif
ReadCapacity(TP2, TP1);
#ifdef DebugOut
lcd_data('K');
#endif
#endif
}
#ifdef WITH_UJT
// check for UJT
if (PartFound==PART_DIODE
&& NumOfDiodes==2 // UJT is detected as 2 diodes E-B1 and E-B2...
// && ResistorsFound==1 // ...and a resistor B1-B2
&& diodes.Anode[0]==diodes.Anode[1] // check diodes have common anode
// && (unsigned char)(ResistorList[0]+diodes.Anode[0])==2 // and resistor is between cathodes
)
// note: there also exist CUJTs (complementary UJTs); they seem to be (even) rarer than UJTs, and are not supported for now
{
CheckUJT();
}
#endif /* defined WITH_UJT */
#ifdef WITH_XTAL
if (PartFound==PART_NONE || ((PartFound==PART_CAPACITOR) && (cap.cpre_max == -12))) {
// still not recognized anything? then check for ceramic resonator or crystal
// these tests are time-consuming, so we do them last, and only on TP1/TP3
sampling_test_xtal();
}
#endif
//All checks are done, output result to display
#ifdef DebugOut
// only clear two lines of LCD
lcd_clear_line1();
#else
lcd_clear(); // clear total display
#endif
_trans = &ntrans; // default transistor structure to show
if (PartFound == PART_THYRISTOR) {
#ifdef WITH_GRAPHICS
lcd_big_icon(THYRISTOR|LCD_UPPER_LEFT);
lcd_draw_trans_pins(-8, 16);
lcd_set_cursor(0,TEXT_RIGHT_TO_ICON); // position behind the icon, Line 1
lcd_MEM_string(Thyristor); //"Thyristor"
#else
lcd_MEM_string(Thyristor); //"Thyristor"
PinLayout(Cathode_char,'G','A'); // CGA= or 123=...
#endif
goto TyUfAusgabe;
}
if (PartFound == PART_TRIAC) {
#ifdef WITH_GRAPHICS
lcd_big_icon(TRIAC|LCD_UPPER_LEFT);
lcd_draw_trans_pins(-8, 16);
lcd_set_cursor(0,TEXT_RIGHT_TO_ICON); // position behind the icon, Line 1
lcd_MEM_string(Triac); //"Triac"
#else
lcd_MEM_string(Triac); //"Triac"
PinLayout('1','G','2'); // CGA= or 123=...
#endif
goto TyUfAusgabe;
}
#ifdef WITH_PUT
if (PartFound == PART_PUT) {
static const unsigned char PUT_str[] MEM_TEXT = "PUT";
lcd_MEM_string(PUT_str);
_trans=&ptrans;
PinLayout('A','G',Cathode_char);
goto TyUfAusgabe;
}
#endif
#ifdef WITH_UJT
if (PartFound == PART_UJT) {
static const unsigned char UJT_str[] MEM_TEXT = "UJT";
lcd_MEM_string(UJT_str);
PinLayout('1','E','2');
#ifdef SamplingADC
static const unsigned char eta_str[] MEM_TEXT = " eta=";
lcd_next_line(0);
ResistorChecked[ntrans.e - TP_MIN + ntrans.c - TP_MIN - 1] = 0; // forget last resistance measurement
GetResistance(ntrans.c, ntrans.e); // resistor value is in ResistorVal[resnum]
DisplayValue(ResistorVal[ntrans.e - TP_MIN + ntrans.c - TP_MIN - 1],-1,LCD_CHAR_OMEGA,2);
lcd_MEM_string(eta_str); //"eta="
DisplayValue(ntrans.gthvoltage,0,'%',3);
#else /* ! SamplingADC */
static const unsigned char R12_str[] MEM_TEXT = "R12=";
lcd_next_line(0);
lcd_MEM_string(R12_str); //"R12="
DisplayValue(ResistorVal[ntrans.e - TP_MIN + ntrans.c - TP_MIN - 1],-1,LCD_CHAR_OMEGA,2);
lcd_data(',');
DisplayValue(((RR680PL * (unsigned long)(ADCconfig.U_AVCC - ntrans.uBE)) / ntrans.uBE)-RRpinPL,-1,LCD_CHAR_OMEGA,3);
#endif /* SamplingADC */
goto tt_end;
}
#endif /* WITH_UJT */
if (PartFound == PART_CAPACITOR) {
#if FLASHEND > 0x3fff
if ((cap.ca + cap.cb) == (TP1 + TP3)) {
show_Cap13(); // repeated capacity measurement
goto shut_off; // key was pressed or timeout
}
show_cap(0); // show capacity in normal way and measure additional parameters
#else
show_cap_simple(); // show capacity in normal way and measure additional parameters
#endif
goto tt_end;
} /* end PartFound == PART_CAPACITOR */
#ifdef WITH_XTAL
if (PartFound == PART_CERAMICRESONATOR) {
// static const unsigned char cerres_str[] MEM_TEXT = "Cer.resonator ";
lcd_MEM_string(cerres_str);
if (sampling_measure_xtal()) goto loop_start;
goto tt_end;
}
if (PartFound == PART_XTAL) {
// static const unsigned char xtal_str[] MEM_TEXT = "Crystal ";
lcd_MEM_string(xtal_str);
if (sampling_measure_xtal()) goto loop_start;
goto tt_end;
}
#endif
// ========================================
if(PartFound == PART_DIODE) {
// ========================================
if(NumOfDiodes == 1) { //single Diode
// lcd_MEM_string(Diode); //"Diode: "
#if FLASHEND > 0x1fff
// enough memory (>8k) to sort the pins and additional Ir=
DiodeSymbol_withPins(0);
GetIr(diodes.Cathode[0],diodes.Anode[0]); // measure and output Ir=x.xuA
#else
// too less memory to sort the pins
DiodeSymbol_withPins(0);
#endif
UfAusgabe(0x70); // mark for additional resistor and output Uf= in line 2
#ifndef SamplingADC
/* load current of capacity is (5V-1.1V)/(470000 Ohm) = 8298nA */
ReadCapacity(diodes.Cathode[0],diodes.Anode[0]); // Capacity opposite flow direction
if (cap.cpre < -3) { /* capacity is measured */
#if (LCD_LINES > 2)
lcd_line3(); // output Capacity in line 3
#endif
lcd_MEM_string(Cap_str); //"C="
#if LCD_LINE_LENGTH > 16
DisplayValue(cap.cval,cap.cpre,'F',3);
#else
DisplayValue(cap.cval,cap.cpre,'F',2);
#endif
}
#else // SamplingADC
showdiodecap:
cap.cval=sampling_cap(diodes.Cathode[0],diodes.Anode[0],0); // at low voltage
lcd_next_line_wait(0); // next line, wait 5s and clear line 2
DisplayValue(cap.cval,sampling_cap_pre,'F',2);
#ifdef PULLUP_DISABLE
lcd_data('-');
cap.cval=sampling_cap(diodes.Cathode[0],diodes.Anode[0],1); // at high voltage
if (cap.cval < 0) cap.cval = 0; // don't show negativ value
DisplayValue(cap.cval,sampling_cap_pre,'F',2);
#if LCD_LINE_LENGTH > 16
lcd_MEM_string(AT05volt); // " @0-5V"
#else
lcd_MEM_string(AT05volt+1); // "@0-5V"
#endif
uart_newline(); // MAURO Diode ('A')
#else
#warning Capacity measurement from high to low not possible for diodes without PULLUP_DISABLE option!
#endif /* PULLUP_DISABLE */
#endif
goto end3;
} else if(NumOfDiodes == 2) { // double diode
lcd_data('2');
lcd_MEM_string(Dioden); //"diodes "
if(diodes.Anode[0] == diodes.Anode[1]) { //Common Anode
DiodeSymbol_CpinApin(0); // 1-|<-2
DiodeSymbol_ACpin(1); // ->|-3
UfAusgabe(0x01);
#ifdef SamplingADC
goto showdiodecap; // double diodes are often varicap; measure capacitance of one of them
#else
goto end3;
#endif
}
if(diodes.Cathode[0] == diodes.Cathode[1]) { //Common Cathode
DiodeSymbol_ApinCpin(0); // 1->|-2
DiodeSymbol_CApin(1); // -|<-3
UfAusgabe(0x01);
#ifdef SamplingADC
goto showdiodecap; // double diodes are often varicap; measure capacitance of one of them
#else
goto end3;
#endif
// else if ((diodes.Cathode[0] == diodes.Anode[1]) && (diodes.Cathode[1] == diodes.Anode[0]))
}
if (diodes.Cathode[0] == diodes.Anode[1]) {
// normaly two serial diodes are detected as three diodes, but if the threshold is high
// for both diodes, the third diode is not detected.
// can also be Antiparallel
diode_sequence = 0x01; // 0 1
SerienDiodenAusgabe();
goto end3;
}
if (diodes.Cathode[1] == diodes.Anode[0]) {
diode_sequence = 0x10; // 1 0
SerienDiodenAusgabe();
goto end3;
}
} else if(NumOfDiodes == 3) {
//Serial of 2 Diodes; was detected as 3 Diodes
diode_sequence = 0x33; // 3 3
/* Check for any constellation of 2 serial diodes:
Only once the pin No of anyone Cathode is identical of another anode.
two diodes in series is additionally detected as third big diode.
*/
if (diodes.Cathode[0] == diodes.Anode[1]) {
diode_sequence = 0x01; // 0 1
}
if (diodes.Anode[0] == diodes.Cathode[1]) {
diode_sequence = 0x10; // 1 0
}
if (diodes.Cathode[0] == diodes.Anode[2]) {
diode_sequence = 0x02; // 0 2
}
if (diodes.Anode[0] == diodes.Cathode[2]) {
diode_sequence = 0x20; // 2 0
}
if (diodes.Cathode[1] == diodes.Anode[2]) {
diode_sequence = 0x12; // 1 2
}
if (diodes.Anode[1] == diodes.Cathode[2]) {
diode_sequence = 0x21; // 2 1
}
// if((ptrans.b<3) && (ptrans.c<3))
if(diode_sequence < 0x22) {
lcd_data('3');
lcd_MEM_string(Dioden); //"Diodes "
SerienDiodenAusgabe();
goto end3;
}
} // end (NumOfDiodes == 3)
lcd_MEM_string(Bauteil); //"Bauteil"
lcd_MEM_string(Unknown); //" unbek."
lcd_line2(); //2. row
lcd_data(NumOfDiodes + '0');
lcd_data('*');
lcd_MEM_string(AnKat_str); //"->|-"
lcd_MEM_string(Detected); //" detected"
goto not_known;
// end (PartFound == PART_DIODE)
// ========================================
} else if (PartFound == PART_TRANSISTOR) {
// ========================================
#ifdef SEARCH_PARASITIC
if ((ptrans.count != 0) && (ntrans.count !=0)) {
// Special Handling of NPNp and PNPn Transistor.
// If a protection diode is built on the same structur as the NPN-Transistor,
// a parasitic PNP-Transistor will be detected.
ReadCapacity(ntrans.e, ntrans.b); // read capacity of NPN base-emitter
n_cval = cap.cval; // save the found capacity value
n_cpre = cap.cpre; // and dimension
ReadCapacity(ptrans.b, ptrans.e); // read capacity of PNP base-emitter
// check if one hfe is very low. If yes, simulate a very low BE capacity
if ((ntrans.hfe < 500) && (ptrans.hfe >= 500)) n_cpre = -16; // set NPN BE capacity to low value
if ((ptrans.hfe < 500) && (ntrans.hfe >= 500)) cap.cpre = -16; // set PNP BE capacity to low value
if (((n_cpre == cap.cpre) && (cap.cval > n_cval))
|| (cap.cpre > n_cpre)) {
// the capacity value or dimension of the PNP B-E is greater than the NPN B-E
PartMode = PART_MODE_PNP;
} else {
PartMode = PART_MODE_NPN;
}
} /* end ((ptrans.count != 0) && (ntrans.count !=0)) */
#endif
// not possible for mega8, change Pin sequence instead.
if ((ptrans.count != 0) && (ntrans.count != 0)
&& (!(RST_PIN_REG & (1 << RST_PIN)))) {
// if the Start key is still pressed, use the other Transistor
#if 0
if (PartMode == PART_MODE_NPN) {
PartMode = PART_MODE_PNP; // switch to parasitic transistor
} else {
PartMode = PART_MODE_NPN; // switch to parasitic transistor
}
#else
PartMode ^= (PART_MODE_PNP - PART_MODE_NPN);
#endif
}
#ifdef WITH_GRAPHICS
lcd_set_cursor(0,TEXT_RIGHT_TO_ICON); // position behind the icon, Line 1
lcd_big_icon(BJT_NPN|LCD_UPPER_LEFT); // show the NPN Icon at lower left corner
if(PartMode == PART_MODE_NPN) {
// _trans = &ntrans; is allready selected a default
lcd_MEM_string(NPN_str); //"NPN "
if (ptrans.count != 0) {
lcd_data('p'); // mark for parasitic PNp
}
} else {
_trans = &ptrans; // change transistor structure
lcd_update_icon(bmp_pnp); // update for PNP
lcd_MEM_string(PNP_str); //"PNP "
if (ntrans.count != 0) {
lcd_data('n'); // mark for parasitic NPn
}
}
#else /* only character display */
if(PartMode == PART_MODE_NPN) {
// _trans = &ntrans; is allready selected a default
lcd_MEM_string(NPN_str); //"NPN "
if (ptrans.count != 0) {
lcd_data('p'); // mark for parasitic PNp
}
} else {
_trans = &ptrans; // change transistor structure
lcd_MEM_string(PNP_str); //"PNP "
if (ntrans.count != 0) {
lcd_data('n'); // mark for parasitic NPn
}
}
lcd_space();
#endif
// show the protection diode of the BJT
vak_diode_nr = search_vak_diode();
if (vak_diode_nr < 5) {
// no side of the diode is connected to the base, this must be the protection diode
#ifdef WITH_GRAPHICS
options = 0;
if (_trans->c != diodes.Anode[vak_diode_nr])
options |= OPT_VREVERSE;
lcd_update_icon_opt(bmp_vakdiode,options); // show the protection diode right to the Icon
#else /* only character display, show the diode in correct direction */
char an_cat; // diode is anode-cathode type
an_cat = 0;
#ifdef EBC_STYLE
#if EBC_STYLE == 321
// Layout with 321= style
an_cat = (((PartMode == PART_MODE_NPN) && (ntrans.c < ntrans.e)) ||
((PartMode != PART_MODE_NPN) && (ptrans.c > ptrans.e)));
#else
// Layout with EBC= style
an_cat = (PartMode == PART_MODE_NPN);
#endif
#else
// Layout with 123= style
an_cat = (((PartMode == PART_MODE_NPN) && (ntrans.c > ntrans.e))
|| ((PartMode != PART_MODE_NPN) && (ptrans.c < ptrans.e)));
#endif
if (an_cat) {
lcd_MEM_string(AnKat_str); //"->|-"
} else {
lcd_MEM_string(KatAn_str); //"-|<-"
}
#endif /* !WITH_GRAPHICS */
} /* endif vak_diode_nr < 6 */
#ifdef WITH_GRAPHICS
lcd_draw_trans_pins(-7, 16); // show the pin numbers
lcd_next_line(TEXT_RIGHT_TO_ICON); // position behind the icon, Line 2
lcd_MEM_string(hfe_str); //"B=" (hFE)
DisplayValue(_trans->hfe,-2,0,3);
lcd_next_line(TEXT_RIGHT_TO_ICON+1-LOW_H_SPACE); // position behind the icon+1, Line 3
lcd_data('I');
if (_trans->current >= 10000) {
lcd_data('e'); // emitter current has 10mA offset
_trans->current -= 10000;
} else {
lcd_data('c');
}
lcd_equal(); // lcd_data('=');
DisplayValue16(_trans->current,-6,'A',2); // display Ic or Ie current
lcd_next_line(TEXT_RIGHT_TO_ICON); // position behind the icon, Line 4
lcd_MEM_string(Ube_str); //"Ube="
Display_mV(_trans->uBE,3-LOW_H_SPACE);
last_line_used = 1;
#ifdef SHOW_ICE
if (_trans->ice0 > 0) {
lcd_next_line_wait(TEXT_RIGHT_TO_ICON-1-LOW_H_SPACE); // position behind the icon, Line 4 & wait and clear last line
lcd_MEM2_string(ICE0_str); // "ICE0="
DisplayValue16(_trans->ice0,-6,'A',2); // display ICEO
}
if (_trans->ices > 0) {
lcd_next_line_wait(TEXT_RIGHT_TO_ICON-1-LOW_H_SPACE); // position behind the icon, Line 4 & wait and clear last line
lcd_MEM2_string(ICEs_str); // "ICEs="
DisplayValue16(_trans->ices,-6,'A',2); // display ICEs
}
#endif
#else /* character display */
PinLayout('E','B','C'); // EBC= or 123=...
lcd_line2(); //2. row
lcd_MEM_string(hfe_str); //"B=" (hFE)
DisplayValue(_trans->hfe,-2,0,3);
#if FLASHEND > 0x1fff
lcd_space();
lcd_data('I');
if (_trans->current >= 10000) {
lcd_data('e'); // emitter current has 10mA offset
_trans->current -= 10000;
} else {
lcd_data('c');
}
lcd_equal(); // lcd_data('=');
DisplayValue16(_trans->current,-6,'A',2); // display Ic or Ie current
#endif
#if defined(SHOW_ICE)
lcd_next_line_wait(0); // next line, wait 5s and clear line 2
lcd_MEM_string(Ube_str); //"Ube="
Display_mV(_trans->uBE,3);
if (_trans->ice0 > 0) {
lcd_next_line_wait(0); // next line, wait 5s and clear line 2
lcd_MEM2_string(ICE0_str); // "ICE0="
DisplayValue16(_trans->ice0,-6,'A',3);
}
if (_trans->ices > 0) {
lcd_next_line_wait(0); // next line, wait 5s and clear line 2
lcd_MEM2_string(ICEs_str); // "ICEs="
DisplayValue16(_trans->ices,-6,'A',3);
}
#endif
#endif /* WITH_GRAPHICS */
#ifdef SHOW_VAKDIODE
if (vak_diode_nr < 5) {
lcd_next_line_wait(0); // next line, wait 5s and clear line 2/4
DiodeSymbol_withPins(vak_diode_nr);
lcd_MEM_string(Uf_str); //"Uf="
mVAusgabe(vak_diode_nr);
uart_newline(); // MAURO not verified ('D')
} /* end if (vak_diode_nr < 5) */
#endif
#ifdef WITH_GRAPHICS
PinLayoutLine('E','B','C'); // Pin 1=E ...
uart_newline(); // MAURO OK BJT ('E')
#endif
goto tt_end;
// end (PartFound == PART_TRANSISTOR)
// ========================================
} else if (PartFound == PART_FET) { /* JFET or MOSFET */
// ========================================
#ifdef WITH_GRAPHICS
unsigned char fetidx = 0;
lcd_set_cursor(0,TEXT_RIGHT_TO_ICON); // position behind the icon, Line 1
#endif
if((PartMode&P_CHANNEL) == P_CHANNEL) {
lcd_data('P'); //P-channel
_trans = &ptrans;
#ifdef WITH_GRAPHICS