Hi,
The error #define StartADCwait() ADCSRA = StartADCmsk; /* Start conversion */
came out when I modified just one line: #define PROCESSOR_TYP 328
changed as #define PROCESSOR_TYP 2560
Why? need help please.
Also, the Serial monitor shown some messages which didn't be Serila.printed, where it comes, see picture1?
I added Serial.println("oled i2c -1"); the result is strange,see picture 2.
Thanks
Adam
#include <avr/io.h>
#include <util/delay.h>
#include <avr/sleep.h>
#include <stdlib.h>
#include <string.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <math.h>
#include <stdint.h>
#include <avr/power.h>
//#define LCD1602
//#define LCD_I2C
//#define NOK5110
//#define OLED096
#define OLED_I2C
#ifdef LCD_I2C
#ifndef LCD1602
#define LCD1602
#endif
#endif
#ifdef OLED_I2C
#ifndef OLED096
#define OLED096
#endif
#endif
#ifdef LCD1602
#ifdef LCD_I2C
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#else
#include <LiquidCrystal.h>
#endif
#endif
#ifdef NOK5110
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#endif
#ifdef OLED096
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#endif
// ******** config options for your Semiconductor tester
// Every changing of this Makefile will result in new compiling the whole
// programs, if you call make or make upload.
#define MCU atmega328p
#define F_CPU 16000000UL
// Select your language:
// Available languages are: LANG_ENGLISH, LANG_GERMAN, LANG_POLISH, LANG_CZECH, LANG_SLOVAK, LANG_SLOVENE,
// LANG_DUTCH, LANG_BRASIL, LANG_RUSSIAN, LANG_UKRAINIAN
#define LANG_ENGLISH
// The LCD_CYRILLIC option is necessary, if you have a display with cyrillic characterset.
// This lcd-display don't have a character for Ohm and for u (micro).
// Russian language requires a LCD controller with russian characterset and option LCD_CYRILLIC!
#define LCD_CYRILLIC
// The LCD_DOGM option must be set for support of the DOG-M type of LCD modules with ST7036 controller.
// For this LCD type the contrast must be set with software command.
//#define LCD_DOGM
// Option STRIP_GRID_BOARD selects different board-layout, do not set for standard board!
// The connection of LCD is totally different for both versions.
//#define STRIP_GRID_BOARD
// The WITH_SELFTEST option enables selftest function (only for mega168 or mega328).
//#define WITH_SELFTEST
// AUTO_CAL will enable the autocalibration of zero offset of capacity measurement and
// also the port output resistance values will be find out in SELFTEST section.
// With a external capacitor a additionally correction of reference voltage is figured out for
// low capacity measurement and also for the AUTOSCALE_ADC measurement.
// The AUTO_CAL option is only selectable for mega168 and mega328.
//#define AUTO_CAL
// FREQUENCY_50HZ enables a 50 Hz frequency generator for up to one minute at the end of selftests.
//#define FREQUENCY_50HZ
// The WITH_AUTO_REF option enables reading of internal REF-voltage to get factors for the Capacity measuring.
#define WITH_AUTO_REF
// REF_C_KORR corrects the reference Voltage for capacity measurement (<40uF) and has mV units.
// Greater values gives lower capacity results.
#define REF_C_KORR 12
// REF_L_KORR corrects the reference Voltage for inductance measurement and has mV units.
#define REF_L_KORR 40
// C_H_KORR defines a correction of 0.1% units for big capacitor measurement.
// Positive values will reduce measurement results.
#define C_H_KORR 0
// The WITH_UART option enables the software UART (TTL level output at Pin PC3, 26).
// If the option is deselected, PC3 can be used as external voltage input with a
// 10:1 resistor divider.
//#define WITH_UART
// The CAP_EMPTY_LEVEL defines the empty voltage level for capacitors in mV.
// Choose a higher value, if your Tester reports "Cell!" by unloading capacitors.
#define CAP_EMPTY_LEVEL 4
// The AUTOSCALE_ADC option enables the autoscale ADC (ADC use VCC and Bandgap Ref).
#define AUTOSCALE_ADC
#define REF_R_KORR 3
// The ESR_ZERO value define the zero value of ESR measurement (units = 0.01 Ohm).
//#define ESR_ZERO 29
#define ESR_ZERO 20
// NO_AREF_CAP tells your Software, that you have no Capacitor installed at pin AREF (21).
// This enables a shorter wait-time for AUTOSCALE_ADC function.
// A capacitor with 1nF can be used with the option NO_AREF_CAP set.
#define NO_AREF_CAP
// The OP_MHZ option tells the software the Operating Frequency of your ATmega.
// OP_MHZ 16
// Restart from sleep mode will be delayed for 16384 clock tics with crystal mode.
// Operation with the internal RC-Generator or external clock will delay the restart by only 6 clock tics.
// You must specify this with "#define RESTART_DELAY_TICS=6", if you don't use the crystal mode.
//#define RESTART_DELAY_TICS 6
// The USE_EEPROM option specify where you wish to locate fix text and tables.
// If USE_EEPROM is unset, program memory (flash) is taken for fix text and tables.
//#define USE_EEPROM
// Setting EBC_STYPE will select the old style to present the order of Transistor connection (EBC=...).
// Omitting the option will select the 123=... style. Every point is replaced by a character identifying
// type of connected transistor pin (B=Base, E=Emitter, C=Collector, G=Gate, S=Source, D=Drain).
// If you select EBC_STYLE=321 , the style will be 321=... , the inverted order to the 123=... style.
//#define EBC_STYLE
//#define EBC_STYLE 321
// Setting of NO_NANO avoids the use of n as prefix for Farad (nF), the mikro prefix is used insted (uF).
//#define NO_NANO
// The PULLUP_DISABLE option disable the pull-up Resistors of IO-Ports.
// To use this option a external pull-up Resistor (10k to 30k)
// from Pin 13 to VCC must be installed!
#define PULLUP_DISABLE
// The ANZ_MESS option specifies, how often an ADC value is read and accumulated.
// Possible values of ANZ_MESS are 5 to 200.
#define ANZ_MESS 25
// The POWER_OFF option enables the power off function, otherwise loop measurements infinitely
// until power is disconnected with a ON/OFF switch (#define POWER_OFF).
// If you have the tester without the power off transistors, you can deselect POWER_OFF .
// If you have NOT selected the POWER_OFF option with the transistors installed,
// you can stop measuring by holding the key several seconds after a result is
// displayed. After releasing the key, the tester will be shut off by timeout.
// Otherwise you can also specify, after how many measurements without found part
// the tester will shut down (#define POWER_OFF=5).
// The tester will also shut down with found part,
// but successfull measurements are allowed double of the specified number.
// You can specify up to 255 empty measurements (#define POWER_OFF=255).
//#define POWER_OFF 5
//#define POWER_OFF
// Option BAT_CHECK enables the Battery Voltage Check, otherwise the SW Version is displayed instead of Bat.
// BAT_CHECK should be set for battery powered tester version.
//#define BAT_CHECK
// The BAT_OUT option enables Battery Voltage Output on LCD (if BAT_CHECK is selected).
// If your 9V supply has a diode installed, use the BAT_OUT=600 form to specify the
// threshold voltage of your diode to adjust the output value.
// This threshold level is added to LCD-output and does not affect the voltage checking levels.
//#define BAT_OUT 150
// To adjust the warning-level and poor-level of battery check to the capability of a
// low drop voltage regulator, you can specify the Option BAT_POOR=5400 .
// The unit for this option value is 1mV , 5400 means a poor level of 5.4V.
// The warning level is 0.8V higher than the specified poor level (>5.3V).
// The warning level is 0.4V higher than the specified poor level (>2.9V, <=5.3V).
// The warning level is 0.2V higher than the specified poor level (>1.3V, <=2.9V).
// The warning level is 0.1V higher than the specified poor level (<=1.3V).
// Setting the poor level to low values is not recommended for rechargeable Batteries,
// because this increase the danger for deep discharge!!
#define BAT_POOR 6400
// The sleep mode of the ATmega168 or ATmega328 is normally used by the software to save current.
// You can inhibit this with the option INHIBIT_SLEEP_MODE .
//#define INHIBIT_SLEEP_MODE
// ******** end of selectable options
/* -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- */
// ######## Configuration
#ifndef ADC_PORT
//#define DebugOut 3 // if set, output of voltages of resistor measurements in row 2,3,4
//#define DebugOut 4 // if set, output of voltages of Diode measurement in row 3+4
//#define DebugOut 5 // if set, output of Transistor checks in row 2+3
//#define DebugOut 10 // if set, output of capacity measurements (ReadCapacity) in row 3+4
/*
Port, that is directly connected to the probes.
This Port must have an ADC-Input (ATmega8: PORTC).
The lower pins of this Port must be used for measurements.
Please don't change the definitions of TP1, TP2 and TP3!
The TPREF pin can be connected with a 2.5V precision voltage reference
The TPext can be used with a 10:1 resistor divider as external voltage probe up to 50V
*/
#define ADC_PORT PORTC
#define ADC_DDR DDRC
#define ADC_PIN PINC
#define TP1 0
#define TP2 1
#define TP3 2
#define TPext 3
// Port pin for 2.5V precision reference used for VCC check (optional)
#define TPREF 4
// Port pin for Battery voltage measuring
#define TPBAT 5
/*
exact values of used resistors (Ohm).
The standard value for R_L is 680 Ohm, for R_H 470kOhm.
To calibrate your tester the resistor-values can be adjusted:
*/
#define R_L_VAL 6800 // standard value 680 Ohm, multiplied by 10 for 0.1 Ohm resolution
//#define R_L_VAL 6690 // this will be define a 669 Ohm
#define R_H_VAL 47000 // standard value 470000 Ohm, multiplied by 10, divided by 100
//#define R_H_VAL 47900 // this will be define a 479000 Ohm, divided by 100
#define R_DDR DDRB
#define R_PORT PORTB
/*
Port for the Test resistors
The Resistors must be connected to the lower 6 Pins of the Port in following sequence:
RLx = 680R-resistor for Test-Pin x
RHx = 470k-resistor for Test-Pin x
RL1 an Pin 0
RH1 an Pin 1
RL2 an Pin 2
RH2 an Pin 3
RL3 an Pin 4
RH3 an Pin 5
*/
#define ON_DDR DDRD
#define ON_PORT PORTD
#define ON_PIN_REG PIND
#define ON_PIN 18 // Pin, must be switched to high to switch power on
#ifdef STRIP_GRID_BOARD
// Strip Grid board version
#define RST_PIN 0 // Pin, is switched to low, if push button is pressed
#else
// normal layout version
#define RST_PIN 17 // Pin, is switched to low, if push button is pressed
#endif
// Port(s) / Pins for LCD
#ifdef STRIP_GRID_BOARD
// special Layout for strip grid board
#define HW_LCD_EN_PORT PORTD
#define HW_LCD_EN_PIN 5
#define HW_LCD_RS_PORT PORTD
#define HW_LCD_RS_PIN 7
#define HW_LCD_B4_PORT PORTD
#define HW_LCD_B4_PIN 4
#define HW_LCD_B5_PORT PORTD
#define HW_LCD_B5_PIN 3
#define HW_LCD_B6_PORT PORTD
#define HW_LCD_B6_PIN 2
#define HW_LCD_B7_PORT PORTD
#define HW_LCD_B7_PIN 1
#else
// normal Layout
#define HW_LCD_EN_PORT PORTD
#define HW_LCD_EN_PIN 6
#define HW_LCD_RS_PORT PORTD
#define HW_LCD_RS_PIN 7
#define HW_LCD_B4_PORT PORTD
#define HW_LCD_B4_PIN 5
#define HW_LCD_B5_PORT PORTD
#define HW_LCD_B5_PIN 4
#define HW_LCD_B6_PORT PORTD
#define HW_LCD_B6_PIN 3
#define HW_LCD_B7_PORT PORTD
#define HW_LCD_B7_PIN 2
#endif
// U_VCC defines the VCC Voltage of the ATmega in mV units
#define U_VCC 5000
// integer factors are used to change the ADC-value to mV resolution in ReadADC !
// With the option NO_CAP_HOLD_TIME you specify, that capacitor loaded with 680 Ohm resistor will not
// be tested to hold the voltage same time as load time.
// Otherwise (without this option) the voltage drop during load time is compensated to avoid displaying
// too much capacity for capacitors with internal parallel resistance.
// #define NO_CAP_HOLD_TIME
// U_SCALE can be set to 4 for better resolution of ReadADC function for resistor measurement
#define U_SCALE 4
// R_ANZ_MESS can be set to a higher number of measurements (up to 200) for resistor measurement
#define R_ANZ_MESS 190
// Watchdog
//#define WDT_enabled
/*
If you remove the "#define WDT_enabled" , the Watchdog will not be activated.
This is only for Test or debugging usefull.
For normal operation please activate the Watchdog !
*/
// ######## End of configuration
#if R_ANZ_MESS < ANZ_MESS
#undef R_ANZ_MESS
#define R_ANZ_MESS ANZ_MESS
#endif
#if U_SCALE < 0
// limit U_SCALE
#undef U_SCALE
#define U_SCALE 1
#endif
#if U_SCALE > 4
// limit U_SCALE
#undef U_SCALE
#define U_SCALE 4
#endif
#ifndef REF_L_KORR
#define REF_L_KORR 50
#endif
// the following definitions specify where to load external data from: EEprom or flash
#ifdef USE_EEPROM
#define MEM_TEXT EEMEM
#if E2END > 0X1FF
#define MEM2_TEXT EEMEM
#define MEM2_read_byte(a) eeprom_read_byte(a)
#define MEM2_read_word(a) eeprom_read_word(a)
#define lcd_fix2_string(a) lcd_fix_string(a)
#else
#define MEM2_TEXT PROGMEM
#define MEM2_read_byte(a) pgm_read_byte(a)
#define MEM2_read_word(a) pgm_read_word(a)
#define lcd_fix2_string(a) lcd_pgm_string(a)
#define use_lcd_pgm
#endif
#define MEM_read_word(a) eeprom_read_word(a)
#define MEM_read_byte(a) eeprom_read_byte(a)
#else
#define MEM_TEXT PROGMEM
#define MEM2_TEXT PROGMEM
#define MEM_read_word(a) pgm_read_word(a)
#define MEM_read_byte(a) pgm_read_byte(a)
#define MEM2_read_byte(a) pgm_read_byte(a)
#define MEM2_read_word(a) pgm_read_word(a)
#define lcd_fix2_string(a) lcd_pgm_string(a)
#define use_lcd_pgm
#endif
// RH_OFFSET : systematic offset of resistor measurement with RH (470k)
// resolution is 0.1 Ohm, 3500 defines a offset of 350 Ohm
#define RH_OFFSET 3500
// TP2_CAP_OFFSET is a additionally offset for TP2 capacity measurements in pF units
#define TP2_CAP_OFFSET 2
// CABLE_CAP defines the capacity (pF) of 12cm cable with clip at the terminal pins
#define CABLE_CAP 3
// select the right Processor Typ
/*
#if defined(__AVR_ATmega48__)
#define PROCESSOR_TYP 168
#elif defined(__AVR_ATmega48P__)
#define PROCESSOR_TYP 168
#elif defined(__AVR_ATmega88__)
#define PROCESSOR_TYP 168
#elif defined(__AVR_ATmega88P__)
#define PROCESSOR_TYP 168
#elif defined(__AVR_ATmega168__)
#define PROCESSOR_TYP 168
#elif defined(__AVR_ATmega168P__)
#define PROCESSOR_TYP 168
#elif defined(__AVR_ATmega328__)
#define PROCESSOR_TYP 328
#elif defined(__AVR_ATmega328P__)
#define PROCESSOR_TYP 328
#elif defined(__AVR_ATmega640__)
#define PROCESSOR_TYP 1280
#elif defined(__AVR_ATmega1280__)
#define PROCESSOR_TYP 1280
#elif defined(__AVR_ATmega2560__)
#define PROCESSOR_TYP 1280
#else
#define PROCESSOR_TYP 8
#endif
*/
#define PROCESSOR_TYP 328
///// #define PROCESSOR_TYP 2560
// automatic selection of right call type
#if FLASHEND > 0X1FFF
#define ACALL call
#else
#define ACALL rcall
#endif
// automatic selection of option and parameters for different AVRs
//------------------=========----------
#if PROCESSOR_TYP == 168
//------------------=========----------
#define MCU_STATUS_REG MCUCR
#define ADC_COMP_CONTROL ADCSRB
#define TI1_INT_FLAGS TIFR1
#define DEFAULT_BAND_GAP 1070
#define DEFAULT_RH_FAKT 884 // mega328 1070 mV
// LONG_HFE activates computation of current amplification factor with long variables
#define LONG_HFE
// COMMON_COLLECTOR activates measurement of current amplification factor in common collector circuit (Emitter follower)
#define COMMON_COLLECTOR
#define MEGA168A 17
#define MEGA168PA 18
// Pin resistor values of ATmega168
//#define PIN_RM 196
//#define PIN_RP 225
#define PIN_RM 190
#define PIN_RP 220
// CC0 defines the capacity of empty terminal pins 1 & 3 without cable
#define CC0 36
// Slew rate correction val += COMP_SLEW1 / (val + COMP_SLEW2)
#define COMP_SLEW1 4000
#define COMP_SLEW2 220
#define C_NULL CC0+CABLE_CAP+(COMP_SLEW1 / (CC0 + CABLE_CAP + COMP_SLEW2))
#define MUX_INT_REF 0x0e // channel number of internal 1.1 V
//------------------=========----------
#elif PROCESSOR_TYP == 328
//------------------=========----------
#define MCU_STATUS_REG MCUCR
#define ADC_COMP_CONTROL ADCSRB
#define TI1_INT_FLAGS TIFR1
#define DEFAULT_BAND_GAP 1070
#define DEFAULT_RH_FAKT 884 // mega328 1070 mV
// LONG_HFE activates computation of current amplification factor with long variables
#define LONG_HFE
// COMMON_COLLECTOR activates measurement of current amplification factor in common collector circuit (Emitter follower)
#define COMMON_COLLECTOR
#define PIN_RM 200
#define PIN_RP 220
// CC0 defines the capacity of empty terminal pins 1 & 3 without cable
#define CC0 36
// Slew rate correction val += COMP_SLEW1 / (val + COMP_SLEW2)
#define COMP_SLEW1 4000
#define COMP_SLEW2 180
#define C_NULL CC0+CABLE_CAP+(COMP_SLEW1 / (CC0 + CABLE_CAP + COMP_SLEW2))
#define MUX_INT_REF 0x0e // channel number of internal 1.1 V
//------------------=========----------
#elif PROCESSOR_TYP == 1280
//------------------=========----------
#define MCU_STATUS_REG MCUCR
#define ADC_COMP_CONTROL ADCSRB
#define TI1_INT_FLAGS TIFR1
#define DEFAULT_BAND_GAP 1070
#define DEFAULT_RH_FAKT 884 // mega328 1070 mV
// LONG_HFE activates computation of current amplification factor with long variables
#define LONG_HFE
// COMMON_COLLECTOR activates measurement of current amplification factor in common collector circuit (Emitter follower)
#define COMMON_COLLECTOR
#define PIN_RM 200
#define PIN_RP 220
// CC0 defines the capacity of empty terminal pins 1 & 3 without cable
#define CC0 36
// Slew rate correction val += COMP_SLEW1 / (val + COMP_SLEW2)
#define COMP_SLEW1 4000
#define COMP_SLEW2 180
#define C_NULL CC0+CABLE_CAP+(COMP_SLEW1 / (CC0 + CABLE_CAP + COMP_SLEW2))
#define MUX_INT_REF 0x1e /* channel number of internal 1.1 V */
//------------------=========----------
#else
// ATmega8
//------------------=========----------
#define MCU_STATUS_REG MCUCSR
#define ADC_COMP_CONTROL SFIOR
#define TI1_INT_FLAGS TIFR
#define DEFAULT_BAND_GAP 1298 //mega8 1298 mV
#define DEFAULT_RH_FAKT 740 // mega8 1250 mV
// LONG_HFE activates computation of current amplification factor with long variables
#define LONG_HFE
// COMMON_COLLECTOR activates measurement of current amplification factor in common collector circuit (Emitter follower)
#define COMMON_COLLECTOR
#define PIN_RM 196
#define PIN_RP 240
// CC0 defines the capacity of empty terminal pins 1 & 3 without cable
#define CC0 27
// Slew rate correction val += COMP_SLEW1 / (val + COMP_SLEW2)
#define COMP_SLEW1 0
#define COMP_SLEW2 33
#define C_NULL CC0+CABLE_CAP+(COMP_SLEW1 / (CC0 + CABLE_CAP + COMP_SLEW2))
#define MUX_INT_REF 0x0e /* channel number of internal 1.1 V */
#ifndef INHIBIT_SLEEP_MODE
#define INHIBIT_SLEEP_MODE /* do not use the sleep mode of ATmega */
#endif
#endif
#if PROCESSOR_TYP == 8
// 2.54V reference voltage + correction (fix for ATmega8)
#ifdef AUTO_CAL
#define ADC_internal_reference (2560 + (int8_t)eeprom_read_byte((uint8_t *)&RefDiff))
#else
#define ADC_internal_reference (2560 + REF_R_KORR)
#endif
#else
// all other processors use a 1.1V reference
#ifdef AUTO_CAL
#define ADC_internal_reference (ref_mv + (int8_t)eeprom_read_byte((uint8_t *)&RefDiff))
#else
#define ADC_internal_reference (ref_mv + REF_R_KORR)
#endif
#endif
#ifndef REF_R_KORR
#define REF_R_KORR 0
#endif
#ifndef REF_C_KORR
#define REF_C_KORR 0
#endif
#define LONG_WAIT_TIME 28000
#define SHORT_WAIT_TIME 5000
#ifdef POWER_OFF
// if POWER OFF function is selected, wait 14s
// if POWER_OFF with parameter > 2, wait only 5s before repeating
#if (POWER_OFF+0) > 2
#define OFF_WAIT_TIME SHORT_WAIT_TIME
#else
#define OFF_WAIT_TIME LONG_WAIT_TIME
#endif
#else
// if POWER OFF function is not selected, wait 14s before repeat measurement
#define OFF_WAIT_TIME LONG_WAIT_TIME
#endif
//**********************************************************
// defines for the selection of a correctly ADC-Clock
// will match for 1MHz, 2MHz, 4MHz, 8MHz and 16MHz
// ADC-Clock can be 125000 or 250000
// 250 kHz is out of the full accuracy specification!
// clock divider is 4, when CPU_Clock==1MHz and ADC_Clock==250kHz
// clock divider is 128, when CPU_Clock==16MHz and ADC_Clock==125kHz
#define F_ADC 125000
//#define F_ADC 250000
#if F_CPU/F_ADC == 2
#define AUTO_CLOCK_DIV (1<<ADPS0)
#endif
#if F_CPU/F_ADC == 4
#define AUTO_CLOCK_DIV (1<<ADPS1)
#endif
#if F_CPU/F_ADC == 8
#define AUTO_CLOCK_DIV (1<<ADPS1) | (1<<ADPS0)
#endif
#if F_CPU/F_ADC == 16
#define AUTO_CLOCK_DIV (1<<ADPS2)
#endif
#if F_CPU/F_ADC == 32
#define AUTO_CLOCK_DIV (1<<ADPS2) | (1<<ADPS0)
#endif
#if F_CPU/F_ADC == 64
#define AUTO_CLOCK_DIV (1<<ADPS2) | (1<<ADPS1)
#endif
#if F_CPU/F_ADC == 128
#define AUTO_CLOCK_DIV (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
#endif
//**********************************************************
#define F_ADC_F 500000
#if F_CPU/F_ADC_F == 2
#define FAST_CLOCK_DIV (1<<ADPS0)
#endif
#if F_CPU/F_ADC_F == 4
#define FAST_CLOCK_DIV (1<<ADPS1)
#endif
#if F_CPU/F_ADC_F == 8
#define FAST_CLOCK_DIV (1<<ADPS1) | (1<<ADPS0)
#endif
#if F_CPU/F_ADC_F == 16
#define FAST_CLOCK_DIV (1<<ADPS2)
#endif
#if F_CPU/F_ADC_F == 32
#define FAST_CLOCK_DIV (1<<ADPS2) | (1<<ADPS0)
#endif
#if F_CPU/F_ADC_F == 64
#define FAST_CLOCK_DIV (1<<ADPS2) | (1<<ADPS1)
#endif
#if F_CPU/F_ADC_F == 128
#define FAST_CLOCK_DIV (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
#endif
#ifndef PIN_RP
#define PIN_RP 220 // estimated internal resistance PORT to VCC
// will only be used, if not set before in config.h
#endif
#ifndef PIN_RM
#define PIN_RM 190 // estimated internal resistance PORT to GND
// will only be used, if not set before in config.h
#endif
//**********************************************************
// defines for the WITH_UART option
/*
With define SWUART_INVERT you can specify, if the software-UART operates normal or invers.
in the normal mode the UART sends with usual logik level (Low = 0; High = 1).
You can use this mode for direct connection to a uC, or a level converter like MAX232.
With invers mode the UART sends with invers logik (Low = 1, High = 0).
This is the level of a standard RS232 port of a PC.
In most cases the output of the software UART can so be connected to the RxD of a PC.
The specification say, that level -3V to 3V is unspecified, but in most cases it works.
Is a simple but unclean solution.
Is SWUART_INVERT defined, the UART works is inverse mode
*/
//#define SWUART_INVERT
#define TxD 3 // TxD-Pin of Software-UART; must be at Port C !
#ifdef WITH_UART
#define TXD_MSK (1<<TxD)
#else
#define TXD_MSK 0xF8
#endif
#ifdef SWUART_INVERT
#define TXD_VAL 0
#else
#define TXD_VAL TXD_MSK
#endif
#ifdef INHIBIT_SLEEP_MODE
// save memory, do not use the sleep mode
#define wait_about5ms() wait5ms()
#define wait_about10ms() wait10ms()
#define wait_about20ms() wait20ms()
#define wait_about30ms() wait30ms()
#define wait_about50ms() wait50ms()
#define wait_about100ms() wait100ms()
#define wait_about200ms() wait200ms()
#define wait_about300ms() wait300ms()
#define wait_about400ms() wait400ms()
#define wait_about500ms() wait500ms()
#define wait_about1s() wait1s()
#define wait_about2s() wait2s()
#define wait_about3s() wait3s()
#define wait_about4s() wait4s()
#else
// use sleep mode to save current for user interface
#define wait_about5ms() sleep_5ms(1)
#define wait_about10ms() sleep_5ms(2)
#define wait_about20ms() sleep_5ms(4)
#define wait_about30ms() sleep_5ms(6)
#define wait_about50ms() sleep_5ms(10)
#define wait_about100ms() sleep_5ms(20)
#define wait_about200ms() sleep_5ms(40)
#define wait_about300ms() sleep_5ms(60)
#define wait_about400ms() sleep_5ms(80)
#define wait_about500ms() sleep_5ms(100)
#define wait_about1s() sleep_5ms(200)
#define wait_about2s() sleep_5ms(400)
#define wait_about3s() sleep_5ms(600)
#define wait_about4s() sleep_5ms(800)
#endif
#undef AUTO_RH
#ifdef WITH_AUTO_REF
#define AUTO_RH
#else
#ifdef AUTO_CAL
#define AUTO_RH
#endif
#endif
#undef CHECK_CALL
#ifdef WITH_SELFTEST
// AutoCheck Function is needed
#define CHECK_CALL
#endif
#ifdef AUTO_CAL
// AutoCheck Function is needed
#define CHECK_CALL
#define RR680PL resis680pl
#define RR680MI resis680mi
#define RRpinPL pin_rpl
#define RRpinMI pin_rmi
#else
#define RR680PL (R_L_VAL + PIN_RP)
#define RR680MI (R_L_VAL + PIN_RM)
#define RRpinPL (PIN_RP)
#define RRpinMI (PIN_RM)
#endif
#ifndef ESR_ZERO
// define a default zero value for ESR measurement (0.01 Ohm units)
#define ESR_ZERO 20
#endif
#ifndef RESTART_DELAY_TICS
// define the processor restart delay for crystal oscillator 16K
// only set, if no preset (Makefile) exists.
#define RESTART_DELAY_TICS 16384
// for ceramic oscillator 258 or 1024 Clock tics can be selected with fuses
// for external oscillator or RC-oscillator is only a delay of 6 clock tics.
#endif
// with EBC_STYLE you can select the Pin-description in EBC= style instead of 123=??? style
//#define EBC_STYLE
#if EBC_STYLE == 123
// unset the option for the 123 selection, since this style is default.
#undef EBC_STYLE
#endif
#if defined(NOK5110) || defined(OLED096)
#define LCD_CHAR_DIODE1 0x91
#define LCD_CHAR_DIODE2 0x92
#define LCD_CHAR_CAP 0x93
#define LCD_CHAR_RESIS1 0x94
#define LCD_CHAR_RESIS2 0x95
#define LCD_CHAR_OMEGA 0x90
#define LCD_CHAR_U 0xB5
#else
// self build characters
#define LCD_CHAR_DIODE1 1 // Diode-Icon; will be generated as custom character
#define LCD_CHAR_DIODE2 2 // Diode-Icon; will be generated as custom character
#define LCD_CHAR_CAP 3 // Capacitor-Icon; will be generated as custom character
// numbers of RESIS1 and RESIS2 are swapped for OLED display, which shows a corrupt RESIS1 character otherwise ???
#define LCD_CHAR_RESIS1 7 // Resistor left part will be generated as custom character
#define LCD_CHAR_RESIS2 6 // Resistor right part will be generated as custom character
#ifdef LCD_CYRILLIC
#define LCD_CHAR_OMEGA 4 // Omega-character
#define LCD_CHAR_U 5 // micro-character
#else
#define LCD_CHAR_OMEGA 244 // Omega-character
#define LCD_CHAR_U 228 // micro-character
#endif
#ifdef LCD_DOGM
#undef LCD_CHAR_OMEGA
#define LCD_CHAR_OMEGA 0x1e // Omega-character for DOGM module
#undef LCD_CHAR_U
#define LCD_CHAR_U 5 // micro-character for DOGM module loadable
#endif
#define LCD_CHAR_DEGREE 0xdf // Character for degree
#endif
#endif // #ifndef ADC_PORT
// the hFE (B) can be determined with common collector and common emitter circuit
// with more than 16K both methodes are possible
#ifdef COMMON_COLLECTOR
#if FLASHEND > 0x3fff
#define COMMON_EMITTER
#endif
#else
#define COMMON_EMITTER
#endif
/* -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- */
#define MAIN_C
#if defined (MAIN_C)
#define COMMON
/*
The voltage at a capacitor grows with Uc = VCC * (1 - e**(-t/T))
The voltage 1.3V is reached at t = -ln(3.7/5)*T = 0.3011*T .
Time constant is T = R * C ; also
C = T / R
for the resistor 470 kOhm is C = t / (0.3011 * 470000)
H_Fakt = 707/100 for a result in pF units.
*/
// Big Capacities (>50uF) are measured with up to 500 load-pulses with the 680 Ohm resistor.
// Each of this load-puls has an length of 10ms. After every load-pulse the voltage of the
// capacitor is measured. If the voltage is more than 300mV, the capacity is computed by
// interpolating the corresponding values of the table RLtab and multiply that with the number
// of load pulses (*10).
// Widerstand 680 Ohm 300 325 350 375 400 425 450 475 500 525 550 575 600 625 650 675 700 725 750 775 800 825 850 875 900 925 950 975 1000 1025 1050 1075 1100 1125 1150 1175 1200 1225 1250 1275 1300 1325 1350 1375 1400 mV
const uint16_t RLtab[] MEM_TEXT = {22447,20665,19138,17815,16657,15635,14727,13914,13182,12520,11918,11369,10865,10401, 9973, 9577, 9209, 8866, 8546, 8247, 7966, 7702, 7454, 7220, 6999, 6789, 6591, 6403, 6224, 6054, 5892, 5738, 5590, 5449, 5314, 5185, 5061, 4942, 4828, 4718, 4613, 4511, 4413, 4319, 4228};
#if FLASHEND > 0x1fff
// {0, 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 };
const uint16_t LogTab[] PROGMEM = {0, 20, 41, 62, 83, 105, 128, 151, 174, 198, 223, 248, 274, 301, 329, 357, 386, 416, 446, 478, 511, 545, 580, 616, 654, 693, 734, 777, 821, 868, 916, 968, 1022, 1079, 1139, 1204, 1273, 1347, 1427, 1514, 1609, 1715, 1833, 1966, 2120, 2303, 2526 };
#endif
#ifdef AUTO_RH
// resistor 470000 Ohm 1000 1050 1100 1150 1200 1250 1300 1350 1400 mV
const uint16_t RHtab[] PROGMEM = { 954, 903, 856, 814, 775, 740, 707, 676, 648};
#endif
// with integer factors the ADC-value will be changed to mV resolution in ReadADC !
// all if statements are corrected to the mV resolution.
// Strings in PROGMEM or in EEprom
#if defined(LANG_GERMAN) // deutsch
const unsigned char TestRunning[] MEM_TEXT = "Testen...";
const unsigned char BatWeak[] MEM_TEXT = "gering";
const unsigned char BatEmpty[] MEM_TEXT = "leer!";
const unsigned char TestFailed2[] MEM_TEXT = "defektes ";
const unsigned char Component[] MEM_TEXT = "Bauteil";
// const unsigned char Diode[] MEM_TEXT = "Diode: ";
const unsigned char Triac[] MEM_TEXT = "Triac";
const unsigned char Thyristor[] MEM_TEXT = "Thyristor";
const unsigned char Unknown[] MEM_TEXT = " unbek.";
const unsigned char TestFailed1[] MEM_TEXT = "Kein,unbek. oder";
const unsigned char OrBroken[] MEM_TEXT = "oder defekt ";
const unsigned char TestTimedOut[] MEM_TEXT = "Timeout!";
#define Cathode_char 'K'
#ifdef WITH_SELFTEST
const unsigned char SELFTEST[] MEM_TEXT = "Selbsttest ..";
const unsigned char RELPROBE[] MEM_TEXT = "isolate Probe!";
const unsigned char ATE[] MEM_TEXT = "Test Ende";
#endif
#endif
#if defined(LANG_ENGLISH) // english
const unsigned char TestRunning[] MEM_TEXT = "testing...";
const unsigned char BatWeak[] MEM_TEXT = "weak";
const unsigned char BatEmpty[] MEM_TEXT = "empty!";
const unsigned char TestFailed2[] MEM_TEXT = "damaged ";
const unsigned char Component[] MEM_TEXT = "part";
//const unsigned char Diode[] MEM_TEXT = "Diode: ";
const unsigned char Triac[] MEM_TEXT = "Triac";
const unsigned char Thyristor[] MEM_TEXT = "Thyristor";
const unsigned char Unknown[] MEM_TEXT = " unknown";
const unsigned char TestFailed1[] MEM_TEXT = "No, unknown, or";
const unsigned char OrBroken[] MEM_TEXT = "or damaged ";
const unsigned char TestTimedOut[] MEM_TEXT = "Timeout!";
#define Cathode_char 'C'
#ifdef WITH_SELFTEST
const unsigned char SELFTEST[] MEM_TEXT = "Selftest mode..";
const unsigned char RELPROBE[] MEM_TEXT = "isolate Probe!";
const unsigned char ATE[] MEM_TEXT = "Test End";
#endif
#endif
// Strings, which are not dependent of any language
const unsigned char Bat_str[] MEM_TEXT = "Bat. ";
const unsigned char OK_str[] MEM_TEXT = "OK";
const unsigned char mosfet_str[] MEM_TEXT = "-MOS";
const unsigned char jfet_str[] MEM_TEXT = "JFET";
const unsigned char GateCap_str[] MEM_TEXT = "C=";
const unsigned char hfe_str[] MEM_TEXT ="B=";
const unsigned char NPN_str[] MEM_TEXT = "NPN ";
const unsigned char PNP_str[] MEM_TEXT = "PNP ";
#ifndef EBC_STYLE
const unsigned char N123_str[] MEM_TEXT = " 123=";
//const unsigned char N123_str[] MEM_TEXT = " Pin=";
#else
#if EBC_STYLE == 321
const unsigned char N321_str[] MEM_TEXT = " 321=";
#endif
#endif
const unsigned char Uf_str[] MEM_TEXT = "Uf=";
const unsigned char vt_str[] MEM_TEXT = " Vt=";
const unsigned char Vgs_str[] MEM_TEXT = "@Vgs=";
const unsigned char CapZeich[] MEM_TEXT = {'-',LCD_CHAR_CAP,'-',0};
const unsigned char Cell_str[] MEM_TEXT = "Cell!";
const unsigned char VCC_str[] MEM_TEXT = "VCC=";
#if FLASHEND > 0x1fff
const unsigned char ESR_str[] MEM_TEXT = " ESR=";
const unsigned char VLOSS_str[] MEM_TEXT = " Vloss=";
const unsigned char Lis_str[] MEM_TEXT = "L=";
const unsigned char Ir_str[] MEM_TEXT = " Ir=";
#ifndef WITH_UART
//#define WITH_VEXT
#endif
#else
#ifndef BAT_CHECK
#ifndef WITH_UART
//#define WITH_VEXT
#endif
#endif
#endif
#ifdef WITH_VEXT
const unsigned char Vext_str[] MEM_TEXT = "Vext=";
#define LCD_CLEAR
#endif
const unsigned char VERSION_str[] MEM2_TEXT = "Ttester 1.08.4";
const unsigned char AnKat[] MEM_TEXT = {'-', LCD_CHAR_DIODE1, '-',0};
const unsigned char KatAn[] MEM_TEXT = {'-', LCD_CHAR_DIODE2, '-',0};
const unsigned char Diodes[] MEM_TEXT = {'*',LCD_CHAR_DIODE1, ' ', ' ',0};
const unsigned char Resistor_str[] MEM_TEXT = {'-', LCD_CHAR_RESIS1, LCD_CHAR_RESIS2,'-',0};
#ifdef WITH_SELFTEST
const unsigned char URefT[] MEM2_TEXT = "Ref=";
const unsigned char RHfakt[] MEM2_TEXT = "RHf=";
const unsigned char RH1L[] MEM_TEXT = "RH-";
const unsigned char RH1H[] MEM_TEXT = "RH+";
const unsigned char RLRL[] MEM_TEXT = "+RL- 12 13 23";
const unsigned char RHRH[] MEM_TEXT = "+RH- 12 13 23";
const unsigned char RHRL[] MEM_TEXT = "RH/RL";
const unsigned char R0_str[] MEM2_TEXT = "R0=";
#define LCD_CLEAR
#endif
#ifdef CHECK_CALL
const unsigned char RIHI[] MEM_TEXT = "Ri_Hi=";
const unsigned char RILO[] MEM_TEXT = "Ri_Lo=";
const unsigned char C0_str[] MEM_TEXT = "C0 ";
const unsigned char T50HZ[] MEM_TEXT = " 50Hz";
#endif
#ifdef AUTO_CAL
const unsigned char MinCap_str[] MEM2_TEXT = " >100nF";
const unsigned char REF_C_str[] MEM2_TEXT = "REF_C=";
const unsigned char REF_R_str[] MEM2_TEXT = "REF_R=";
#endif
#ifdef DebugOut
#define LCD_CLEAR
#endif
const unsigned char DiodeIcon1[] MEM_TEXT = { 0x11, 0x19, 0x1d, 0x1f, 0x1d, 0x19, 0x11, 0x00 }; // Diode-Icon Anode left
const unsigned char DiodeIcon2[] MEM_TEXT = { 0x11, 0x13, 0x17, 0x1f, 0x17, 0x13, 0x11, 0x00 }; // Diode-Icon Anode right
const unsigned char CapIcon[] MEM_TEXT = { 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00 }; // Capacitor Icon
const unsigned char ResIcon1[] MEM_TEXT = { 0x00, 0x0f, 0x08, 0x18, 0x08, 0x0f, 0x00, 0x00 }; // Resistor Icon1 left
const unsigned char ResIcon2[] MEM_TEXT = { 0x00, 0x1e, 0x02, 0x03, 0x02, 0x1e, 0x00, 0x00 }; // Resistor Icon2 right
const unsigned char OmegaIcon[] MEM_TEXT = { 0x00, 0x00, 0x0e, 0x11, 0x11, 0x0a, 0x1b, 0x00 }; // Omega Icon
const unsigned char MicroIcon[] MEM_TEXT = { 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0e, 0x09, 0x10 }; // Micro Icon
const unsigned char PinRLtab[] PROGMEM = { (1<<(TP1*2)), (1<<(TP2*2)), (1<<(TP3*2))}; // Table of commands to switch the R-L resistors Pin 0,1,2
const unsigned char PinADCtab[] PROGMEM = { (1<<TP1), (1<<TP2), (1<<TP3)}; // Table of commands to switch the ADC-Pins 0,1,2
/*
// generate Omega- and u-character as Custom-character, if these characters has a number of loadable type
#if LCD_CHAR_OMEGA < 8
const unsigned char CyrillicOmegaIcon[] MEM_TEXT = {0,0,14,17,17,10,27,0}; // Omega
#endif
#if LCD_CHAR_U < 8
const unsigned char CyrillicMuIcon[] MEM_TEXT = {0,17,17,17,19,29,16,16}; // micro
#endif
*/
#ifdef AUTO_CAL
//const uint16_t R680pl EEMEM = R_L_VAL+PIN_RP; // total resistor to VCC
//const uint16_t R680mi EEMEM = R_L_VAL+PIN_RM; // total resistor to GND
const int8_t RefDiff EEMEM = REF_R_KORR; // correction of internal Reference Voltage
#endif
const uint8_t PrefixTab[] MEM_TEXT = { 'p','n',LCD_CHAR_U,'m',0,'k','M'}; // p,n,u,m,-,k,M
#ifdef AUTO_CAL
//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
// LoPin:HiPin 2:1 3:1 1:2 : 3:2 1:3 2:3
const uint8_t c_zero_tab[] EEMEM = { C_NULL,C_NULL,C_NULL+TP2_CAP_OFFSET,C_NULL,C_NULL+TP2_CAP_OFFSET,C_NULL,C_NULL }; // table of zero offsets
#endif
const uint8_t EE_ESR_ZEROtab[] PROGMEM = {ESR_ZERO, ESR_ZERO, ESR_ZERO, ESR_ZERO}; // zero offset of ESR measurement
// End of EEPROM-Strings
// Multiplier for capacity measurement with R_H (470KOhm)
unsigned int RHmultip = DEFAULT_RH_FAKT;
#else
// no MAIN_C
#define COMMON extern
#ifdef WITH_SELFTEST
extern const unsigned char SELFTEST[] MEM_TEXT;
extern const unsigned char RELPROBE[] MEM_TEXT;
extern const unsigned char ATE[] MEM_TEXT;
#endif
#ifdef AUTO_CAL
//extern uint16_t R680pl;
//extern uint16_t R680mi;
extern int8_t RefDiff;
extern uint16_t ref_offset;
extern uint8_t c_zero_tab[];
#endif
extern const uint8_t EE_ESR_ZEROtab[] EEMEM; // zero offset of ESR measurement
extern const uint16_t RLtab[];
#if FLASHEND > 0x1fff
extern uint16_t LogTab[];
extern const unsigned char ESR_str[];
#endif
#ifdef AUTO_RH
extern const uint16_t RHtab[];
#endif
extern const unsigned char PinRLtab[];
extern const unsigned char PinADCtab[];
extern unsigned int RHmultip;
#endif // MAIN_C
struct Diode_t {
uint8_t Anode;
uint8_t Cathode;
unsigned int Voltage;
};
COMMON struct Diode_t diodes[6];
COMMON uint8_t NumOfDiodes;
COMMON struct {
unsigned long hfe[2]; // current amplification factor
unsigned int uBE[2]; // B-E-voltage of the Transistor
uint8_t b,c,e; // pins of the Transistor
}trans;
COMMON unsigned int gthvoltage; // Gate-threshold voltage
COMMON uint8_t PartReady; // part detection is finished
COMMON uint8_t PartMode;
COMMON uint8_t tmpval, tmpval2;
COMMON unsigned int ref_mv; // Reference-voltage in mV units
COMMON struct resis_t{
unsigned long rx; // value of resistor RX
#if FLASHEND > 0x1fff
unsigned long lx; // inductance 10uH or 100uH
int8_t lpre; // prefix for inductance
#endif
uint8_t ra,rb; // Pins of RX
uint8_t rt; // Tristate-Pin (inactive)
} resis[3];
COMMON uint8_t ResistorsFound; // Number of found resistors
COMMON uint8_t ii; // multipurpose counter
COMMON struct cap_t {
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=u, -3=m
int8_t cpre_max; // Prefix of the biggest capacitor
} cap;
#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; // the found part
COMMON char outval[12]; // String for ASCII-outpu
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
#endif
#if POWER_OFF+0 > 1
COMMON unsigned int display_time; // display time of measurement in ms units
#endif
/* -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- */
// definitions of parts
#define PART_NONE 0
#define PART_DIODE 1
#define PART_TRANSISTOR 2
#define PART_FET 3
#define PART_TRIAC 4
#define PART_THYRISTOR 5
#define PART_RESISTOR 6
#define PART_CAPACITOR 7
#define PART_CELL 8
// special definition for different parts
// FETs
#define PART_MODE_N_E_MOS 2
#define PART_MODE_P_E_MOS 3
#define PART_MODE_N_D_MOS 4
#define PART_MODE_P_D_MOS 5
#define PART_MODE_N_JFET 6
#define PART_MODE_P_JFET 7
// Bipolar
#define PART_MODE_NPN 1
#define PART_MODE_PNP 2
/* -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- */
// wait functions
#define wait5s() delay(5000)
#define wait4s() delay(4000)
#define wait3s() delay(3000)
#define wait2s() delay(2000)
#define wait1s() delay(1000)
#define wait500ms() delay(500)
#define wait400ms() delay(400)
#define wait300ms() delay(300)
#define wait200ms() delay(200)
#define wait100ms() delay(100)
#define wait50ms() delay(50)
#define wait40ms() delay(40)
#define wait30ms() delay(30)
#define wait20ms() delay(20)
#define wait10ms() delay(10)
#define wait5ms() delay(5)
#define wait4ms() delay(4)
#define wait3ms() delay(3)
#define wait2ms() delay(2)
#define wait1ms() delay(1)
#define wait500us() delayMicroseconds(500)
#define wait400us() delayMicroseconds(400)
#define wait300us() delayMicroseconds(300)
#define wait200us() delayMicroseconds(200)
#define wait100us() delayMicroseconds(100)
#define wait50us() delayMicroseconds(50)
#define wait40us() delayMicroseconds(40)
#define wait30us() delayMicroseconds(30)
#define wait20us() delayMicroseconds(20)
#define wait10us() delayMicroseconds(10)
#define wait5us() delayMicroseconds(5)
#define wait4us() delayMicroseconds(4)
#define wait3us() delayMicroseconds(3)
#define wait2us() delayMicroseconds(2)
#define wait1us() delayMicroseconds(1)
/* -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- */
// Interfacing of a HD44780 compatible LCD with 4-Bit-Interface mode
// LCD-commands
#define CMD_ClearDisplay 0x01
#define CMD_ReturnHome 0x02
#define CMD_SetEntryMode 0x04
#define CMD_SetDisplayAndCursor 0x08
#define CMD_SetIFOptions 0x20
#define CMD_SetCGRAMAddress 0x40 // for Custom character
#define CMD_SetDDRAMAddress 0x80 // set Cursor
#define CMD1_SetBias 0x10 // set Bias (instruction table 1, DOGM)
#define CMD1_PowerControl 0x50 // Power Control, set Contrast C5:C4 (instruction table 1, DOGM)
#define CMD1_FollowerControl 0x60 // Follower Control, amplified ratio (instruction table 1, DOGM)
#define CMD1_SetContrast 0x70 // set Contrast C3:C0 (instruction table 1, DOGM)
// Makros for LCD
#define lcd_line1() lcd_set_cursor(0,0) // move to beginning of 1 row
#define lcd_line2() lcd_set_cursor(1,0) // move to beginning of 2 row
#define lcd_line3() lcd_set_cursor(2,0) // move to beginning of 3 row
#define lcd_line4() lcd_set_cursor(3,0) // move to beginning of 4 row
#define uart_newline() Serial.println()
/* -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- */
#ifndef INHIBIT_SLEEP_MODE
// prepare sleep mode
EMPTY_INTERRUPT(TIMER2_COMPA_vect);
EMPTY_INTERRUPT(ADC_vect);
#endif
uint8_t tmp = 0;
//unsigned int PRR;
byte TestKey;
byte TestKeyPin = 17; // A3
#ifdef LCD1602
#ifdef LCD_I2C
LiquidCrystal_I2C lcd(0x3F, 16, 2);
#else
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // RS,E,D4,D5,D6,D7
#endif
#endif
#ifdef NOK5110
Adafruit_PCD8544 lcd = Adafruit_PCD8544(3, 4, 5, 6, 7); // CLK,DIN,DC,CE,RST
#endif
#ifdef OLED096
#ifdef OLED_I2C
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET 7
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Adafruit_SSD1306 display(OLED_RESET);
#else
#define OLED_CLK 7 // D0
#define OLED_MOSI 6 // D1
#define OLED_RESET 5 // RES
#define OLED_DC 4 // DC
#define OLED_CS 3 // CS
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS); /////////////////////////////////////////
#endif
#endif
// begin of transistortester program
void setup()
{
Serial.begin(9600);
Serial.println("setup");
pinMode(TestKeyPin, INPUT);
delay(10);
#ifdef LCD1602
#ifdef LCD_I2C
lcd.begin();
#else
lcd.begin(16,2);
#endif
lcd_pgm_custom_char(LCD_CHAR_DIODE1, DiodeIcon1); // Custom-Character Diode symbol >|
lcd_pgm_custom_char(LCD_CHAR_DIODE2, DiodeIcon2); // Custom-Character Diode symbol |<
lcd_pgm_custom_char(LCD_CHAR_CAP, CapIcon); // Custom-Character Capacitor symbol ||
lcd_pgm_custom_char(LCD_CHAR_RESIS1, ResIcon1); // Custom-Character Resistor symbol [
lcd_pgm_custom_char(LCD_CHAR_RESIS2, ResIcon2); // Custom-Character Resistor symbol ]
lcd_pgm_custom_char(LCD_CHAR_OMEGA, OmegaIcon); // load Omega as Custom-Character
lcd_pgm_custom_char(LCD_CHAR_U, MicroIcon); // load Micro as Custom-Character
lcd.home();
lcd_string("TransistorTester");
lcd_set_cursor(1, 0);
lcd_string("forArduino 1.08a");
#endif
#ifdef NOK5110
lcd.begin();
lcd.cp437(true);
lcd.setContrast(40);
lcd.clearDisplay();
#endif
#ifdef OLED096
#ifdef OLED_I2C
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
#else
display.begin(SSD1306_SWITCHCAPVCC);
#endif
display.cp437(true);
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0,0);
#endif
#if defined(NOK5110) || defined(OLED096)
lcd_string("Transistor");
lcd_set_cursor(1, 0);
lcd_string("Tester");
lcd_set_cursor(2, 0);
lcd_string("for Arduino");
lcd_set_cursor(3, 0);
lcd_string("1.08.004");
#endif
//ON_DDR = 0;
//ON_PORT = 0;
/*
// switch on
ON_DDR = (1<<ON_PIN); // switch to output
#ifdef PULLUP_DISABLE
ON_PORT = (1<<ON_PIN); // switch power on
#else
ON_PORT = (1<<ON_PIN)|(1<<RST_PIN); // switch power on , enable internal Pullup for Start-Pin
#endif
*/
// 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
#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
PRR = (1<<PRTWI) | (1<<PRTIM0) | (1<<PRSPI) | (1<<PRUSART0);
DIDR0 = (1<<ADC5D) | (1<<ADC4D) | (1<<ADC3D);
TCCR2A = (0<<WGM21) | (0<<WGM20); // Counter 2 normal mode
#if F_CPU <= 1000000UL
TCCR2B = (1<<CS22) | (0<<CS21) | (1<<CS20); // prescaler 128, 128us @ 1MHz
#define T2_PERIOD 128
#endif
#if F_CPU == 2000000UL
TCCR2B = (1<<CS22) | (1<<CS21) | (0<<CS20); // prescaler 256, 128us @ 2MHz
#define T2_PERIOD 128
#endif
#if F_CPU == 4000000UL
TCCR2B = (1<<CS22) | (1<<CS21) | (0<<CS20); // prescaler 256, 64us @ 2MHz
#define T2_PERIOD 64
#endif
#if F_CPU >= 8000000UL
TCCR2B = (1<<CS22) | (1<<CS21) | (1<<CS20); // prescaler 1024, 128us @ 8MHz, 64us @ 16MHz
#define T2_PERIOD (1024 / (F_CPU / 1000000UL)); // set to 128 or 64 us
#endif
sei(); // enable interrupts
#endif
*/
#define T2_PERIOD (1024 / (F_CPU / 1000000UL)); // set to 128 or 64 us
//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_fix_string(TestTimedOut); // Output Timeout
wait_about3s(); // wait for 3 s
//ON_PORT = 0; // shut off!
//ON_DDR = (1<<ON_PIN); // switch to GND
//return;
}
#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
//DIDR0 = 0x3f; // disable all Input register of ADC
/*
#if POWER_OFF+0 > 1
// tester display time selection
display_time = OFF_WAIT_TIME; // LONG_WAIT_TIME for single mode, else SHORT_WAIT_TIME
if (!(ON_PIN_REG & (1<<RST_PIN))) {
// if power button is pressed ...
wait_about300ms(); // wait to catch a long key press
if (!(ON_PIN_REG & (1<<RST_PIN))) {
// check if power button is still pressed
display_time = LONG_WAIT_TIME; // ... set long time display anyway
}
}
#else
#define display_time OFF_WAIT_TIME
#endif
*/
#define display_time OFF_WAIT_TIME
empty_count = 0;
mess_count = 0;
}
void loop()
{
// Entry: if start key is pressed before shut down
start:
#ifdef NOK5110
lcd.display();
#endif
#ifdef OLED096
display.display();
Serial.print("lcd test");
#endif
TestKey = 1;
while(TestKey) {
TestKey = digitalRead(TestKeyPin);
delay(100);
}
while(!TestKey) {
TestKey = digitalRead(TestKeyPin);
delay(100);
}
lcd_clear();
delay(100);
PartFound = PART_NONE; // no part found
NumOfDiodes = 0; // Number of diodes = 0
PartReady = 0;
PartMode = 0;
WithReference = 0; // no precision reference voltage
ADC_DDR = TXD_MSK; // activate Software-UART
ResistorsFound = 0; // no resistors found
cap.ca = 0;
cap.cb = 0;
#ifdef WITH_UART
uart_newline(); // start of new measurement
#endif
ADCconfig.RefFlag = 0;
Calibrate_UR(); // get Ref Voltages and Pin resistance
lcd_line1(); // 1 row
ADCconfig.U_Bandgap = ADC_internal_reference; // set internal reference voltage for ADC
#ifdef BAT_CHECK
// Battery check is selected
ReadADC(TPBAT); // Dummy-Readout
trans.uBE[0] = W5msReadADC(TPBAT); // with 5V reference
lcd_fix_string(Bat_str); // output: "Bat. "
#ifdef BAT_OUT
// display Battery voltage
// The divisor to get the voltage in 0.01V units is ((10*33)/133) witch is about 2.4812
// A good result can be get with multiply by 4 and divide by 10 (about 0.75%).
//cap.cval = (trans.uBE[0]*4)/10+((BAT_OUT+5)/10); // usually output only 2 digits
//DisplayValue(cap.cval,-2,'V',2); // Display 2 Digits of this 10mV units
cap.cval = (trans.uBE[0]*4)+BAT_OUT; // usually output only 2 digits
DisplayValue(cap.cval,-3,'V',2); // Display 2 Digits of this 10mV units
lcd_space();
#endif
#if (BAT_POOR > 12000)
#warning "Battery POOR level is set very high!"
#endif
#if (BAT_POOR < 2500)
#warning "Battery POOR level is set very low!"
#endif
#if (BAT_POOR > 5300)
// use .8 V difference to Warn-Level
#define WARN_LEVEL (((unsigned long)(BAT_POOR+800)*(unsigned long)33)/133)
#elif (BAT_POOR > 3249)
// less than 5.4 V only .4V difference to Warn-Level
#define WARN_LEVEL (((unsigned long)(BAT_POOR+400)*(unsigned long)33)/133)
#elif (BAT_POOR > 1299)
// less than 2.9 V only .2V difference to Warn-Level
#define WARN_LEVEL (((unsigned long)(BAT_POOR+200)*(unsigned long)33)/133)
#else
// less than 1.3 V only .1V difference to Warn-Level
#define WARN_LEVEL (((unsigned long)(BAT_POOR+100)*(unsigned long)33)/133)
#endif
#define POOR_LEVEL (((unsigned long)(BAT_POOR)*(unsigned long)33)/133)
// check the battery voltage
if (trans.uBE[0] < WARN_LEVEL) {
// Vcc < 7,3V; show Warning
if(trans.uBE[0] < POOR_LEVEL) {
// Vcc <6,3V; no proper operation is possible
lcd_fix_string(BatEmpty); // Battery empty!
wait_about2s();
PORTD = 0; // switch power off
return;
}
lcd_fix_string(BatWeak); // Battery weak
} else { // Battery-voltage OK
lcd_fix_string(OK_str); // "OK"
}
#else
lcd_fix2_string(VERSION_str); // if no Battery check, Version .. in row 1
#endif
#ifdef WDT_enabled
//wdt_enable(WDTO_2S); // Watchdog on
#endif
//wait_about1s(); // add more time for reading batterie voltage
// begin tests
#ifdef AUTO_RH
RefVoltage(); // compute RHmultip = f(reference voltage)
#endif
#if FLASHEND > 0x1fff
if (WithReference) {
// 2.5V precision reference is checked OK
if ((mess_count == 0) && (empty_count == 0)) {
// display VCC= only first time
lcd_line2();
lcd_fix_string(VCC_str); // VCC=
DisplayValue(ADCconfig.U_AVCC,-3,'V',3); // Display 3 Digits of this mV units
//lcd_space();
//DisplayValue(RRpinMI,-1,LCD_CHAR_OMEGA,4);
wait_about1s();
}
}
#endif
#ifdef WITH_VEXT
// show the external voltage
while (!(ON_PIN_REG & (1<<RST_PIN))) {
lcd_line2();
lcd_clear_line();
lcd_line2();
lcd_fix_string(Vext_str); // Vext=
ADC_DDR = 0; // deactivate Software-UART
trans.uBE[1] = W5msReadADC(TPext); // read external voltage
ADC_DDR = TXD_MSK; // activate Software-UART
#ifdef WITH_UART
uart_newline(); // start of new measurement
#endif
DisplayValue(trans.uBE[1]*10,-3,'V',3); // Display 3 Digits of this mV units
wait_about300ms();
}
#endif
lcd_line2(); // LCD position row 2, column 1
lcd_fix_string(TestRunning); // String: testing...
#ifndef DebugOut
lcd_line2(); // LCD position row 2, column 1
#endif
#ifdef NOK5110
lcd.display();
#endif
#ifdef OLED096
display.display();
display.setCursor(0,0);
#endif
delay(5);
EntladePins(); // discharge all capacitors!
if(PartFound == PART_CELL) {
lcd_clear();
lcd_fix_string(Cell_str); // display "Cell!"
goto end2;
}
#ifdef CHECK_CALL
AutoCheck(); // check, if selftest should be done
#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);
// separate check if is is a capacitor
if(((PartFound == PART_NONE) || (PartFound == PART_RESISTOR) || (PartFound == PART_DIODE)) ) {
EntladePins(); // discharge capacities
// measurement of capacities in all 3 combinations
cap.cval_max = 0; // set max to zero
cap.cpre_max = -12; // set max to pF unit
ReadCapacity(TP3, TP1);
ReadCapacity(TP3, TP2);
ReadCapacity(TP2, TP1);
#if FLASHEND > 0x1fff
ReadInductance(); // measure inductance
#endif
}
// All checks are done, output result to display
lcd_clear();
if(PartFound == PART_DIODE) {
if(NumOfDiodes == 1) { // single Diode
//lcd_fix_string(Diode); // "Diode: "
#if FLASHEND > 0x1fff
// enough memory to sort the pins
#if EBC_STYLE == 321
// the higher test pin number is left side
if (diodes[0].Anode > diodes[0].Cathode) {
lcd_testpin(diodes[0].Anode);
lcd_fix_string(AnKat); // "->|-"
lcd_testpin(diodes[0].Cathode);
} else {
lcd_testpin(diodes[0].Cathode);
lcd_fix_string(KatAn); // "-|<-"
lcd_testpin(diodes[0].Anode);
}
#else
// the higher test pin number is right side
if (diodes[0].Anode < diodes[0].Cathode) {
lcd_testpin(diodes[0].Anode);
lcd_fix_string(AnKat); // "->|-"
lcd_testpin(diodes[0].Cathode);
} else {
lcd_testpin(diodes[0].Cathode);
lcd_fix_string(KatAn); // "-|<-"
lcd_testpin(diodes[0].Anode);
}
#endif
#else
// too less memory to sort the pins
lcd_testpin(diodes[0].Anode);
lcd_fix_string(AnKat); // "->|-"
lcd_testpin(diodes[0].Cathode);
#endif
#if FLASHEND > 0x1fff
GetIr(diodes[0].Cathode,diodes[0].Anode);
#endif
UfOutput(0x70);
#if defined(NOK5110) || defined(OLED096)
lcd_line3();
#endif
// load current of capacity is (5V-1.1V)/(470000 Ohm) = 8298nA
lcd_fix_string(GateCap_str); // "C="
ReadCapacity(diodes[0].Cathode,diodes[0].Anode); // Capacity opposite flow direction
DisplayValue(cap.cval,cap.cpre,'F',3);
goto end;
} else if(NumOfDiodes == 2) { // double diode
lcd_data('2');
lcd_fix_string(Diodes); // "diodes "
if(diodes[0].Anode == diodes[1].Anode) { //Common Anode
lcd_testpin(diodes[0].Cathode);
lcd_fix_string(KatAn); // "-|<-"
lcd_testpin(diodes[0].Anode);
lcd_fix_string(AnKat); // "->|-"
lcd_testpin(diodes[1].Cathode);
UfOutput(0x01);
goto end;
} else if(diodes[0].Cathode == diodes[1].Cathode) { //Common Cathode
lcd_testpin(diodes[0].Anode);
lcd_fix_string(AnKat); // "->|-"
lcd_testpin(diodes[0].Cathode);
lcd_fix_string(KatAn); // "-|<-"
lcd_testpin(diodes[1].Anode);
UfOutput(0x01);
goto end;
} else if ((diodes[0].Cathode == diodes[1].Anode) && (diodes[1].Cathode == diodes[0].Anode)) {
// Antiparallel
lcd_testpin(diodes[0].Anode);
lcd_fix_string(AnKat); // "->|-"
lcd_testpin(diodes[0].Cathode);
lcd_fix_string(AnKat); // "->|-"
lcd_testpin(diodes[1].Cathode);
UfOutput(0x01);
goto end;
}
} else if(NumOfDiodes == 3) {
// Serial of 2 Diodes; was detected as 3 Diodes
trans.b = 3;
trans.c = 3;
// Check for any constallation 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[0].Cathode == diodes[1].Anode) {
trans.b = 0;
trans.c = 1;
}
if(diodes[0].Anode == diodes[1].Cathode) {
trans.b = 1;
trans.c = 0;
}
if(diodes[0].Cathode == diodes[2].Anode) {
trans.b = 0;
trans.c = 2;
}
if(diodes[0].Anode == diodes[2].Cathode) {
trans.b = 2;
trans.c = 0;
}
if(diodes[1].Cathode == diodes[2].Anode) {
trans.b = 1;
trans.c = 2;
}
if(diodes[1].Anode == diodes[2].Cathode) {
trans.b = 2;
trans.c = 1;
}
#if DebugOut == 4
lcd_line3();
lcd_testpin(diodes[0].Anode);
lcd_data(':');
lcd_testpin(diodes[0].Cathode);
lcd_space();
lcd_string(utoa(diodes[0].Voltage, outval, 10));
lcd_space();
lcd_testpin(diodes[1].Anode);
lcd_data(':');
lcd_testpin(diodes[1].Cathode);
lcd_space();
lcd_string(utoa(diodes[1].Voltage, outval, 10));
lcd_line4();
lcd_testpin(diodes[2].Anode);
lcd_data(':');
lcd_testpin(diodes[2].Cathode);
lcd_space();
lcd_string(utoa(diodes[2].Voltage, outval, 10));
lcd_line1();
#endif
if((trans.b < 3) && (trans.c < 3)) {
lcd_data('3');
lcd_fix_string(Diodes); // "Diodes "
lcd_testpin(diodes[trans.b].Anode);
lcd_fix_string(AnKat); // "->|-"
lcd_testpin(diodes[trans.b].Cathode);
lcd_fix_string(AnKat); // "->|-"
lcd_testpin(diodes[trans.c].Cathode);
UfOutput( (trans.b<<4)|trans.c);
goto end;
}
}
// end (PartFound == PART_DIODE)
} else if (PartFound == PART_TRANSISTOR) {
if(PartReady != 0) {
if((trans.hfe[0]>trans.hfe[1])) {
// if the amplification factor was higher at first testr: swap C and E !
tmp = trans.c;
trans.c = trans.e;
trans.e = tmp;
} else {
trans.hfe[0] = trans.hfe[1];
trans.uBE[0] = trans.uBE[1];
}
}
if(PartMode == PART_MODE_NPN) {
lcd_fix_string(NPN_str); // "NPN "
} else {
lcd_fix_string(PNP_str); // "PNP "
}
if( NumOfDiodes > 2) { // Transistor with protection diode
#ifdef EBC_STYLE
#if EBC_STYLE == 321
// Layout with 321= style
if (((PartMode == PART_MODE_NPN) && (trans.c < trans.e)) || ((PartMode != PART_MODE_NPN) && (trans.c > trans.e)))
#else
// Layout with EBC= style
if(PartMode == PART_MODE_NPN)
#endif
#else
// Layout with 123= style
if (((PartMode == PART_MODE_NPN) && (trans.c > trans.e)) || ((PartMode != PART_MODE_NPN) && (trans.c < trans.e)))
#endif
{
lcd_fix_string(AnKat); // "->|-"
} else {
lcd_fix_string(KatAn); // "-|<-"
}
}
#if defined(NOK5110) || defined(OLED096)
lcd_line2();
#endif
PinLayout('E','B','C'); // EBC= or 123=...
#if defined(NOK5110) || defined(OLED096)
lcd_line3();
#else
lcd_line2(); // 2 row
#endif
lcd_fix_string(hfe_str); // "B=" (hFE)
DisplayValue(trans.hfe[0],0,0,3);
lcd_space();
#if defined(NOK5110) || defined(OLED096)
lcd_line4();
#endif
lcd_fix_string(Uf_str); // "Uf="
DisplayValue(trans.uBE[0],-3,'V',3);
goto end;
// end (PartFound == PART_TRANSISTOR)
} else if (PartFound == PART_FET) { // JFET or MOSFET
if(PartMode&1) {
lcd_data('P'); // P-channel
} else {
lcd_data('N'); // N-channel
}
lcd_data('-');
tmp = PartMode/2;
if (tmp == (PART_MODE_N_D_MOS/2)) {
lcd_data('D'); // N-D
}
if (tmp == (PART_MODE_N_E_MOS/2)) {
lcd_data('E'); // N-E
}
if (tmp == (PART_MODE_N_JFET/2)) {
lcd_fix_string(jfet_str); // "JFET"
} else {
lcd_fix_string(mosfet_str); // "-MOS "
}
#if defined(NOK5110) || defined(OLED096)
lcd_line2();
#endif
PinLayout('S','G','D'); // SGD= or 123=...
if((NumOfDiodes > 0) && (PartMode < PART_MODE_N_D_MOS)) {
// MOSFET with protection diode; only with enhancement-FETs
#ifdef EBC_STYLE
#if EBC_STYLE == 321
// layout with 321= style
if (((PartMode&1) && (trans.c > trans.e)) || ((!(PartMode&1)) && (trans.c < trans.e)))
#else
// Layout with SGD= style
if (PartMode&1) // N or P MOS
#endif
#else
// layout with 123= style
if (((PartMode&1) && (trans.c < trans.e)) || ((!(PartMode&1)) && (trans.c > trans.e)))
#endif
{
lcd_data(LCD_CHAR_DIODE1); // show Diode symbol >|
} else {
lcd_data(LCD_CHAR_DIODE2); // show Diode symbol |<
}
}
#if defined(NOK5110) || defined(OLED096)
lcd_line3();
#else
lcd_line2(); // 2 row
#endif
if(PartMode < PART_MODE_N_D_MOS) { // enhancement-MOSFET
// Gate capacity
lcd_fix_string(GateCap_str); // "C="
ReadCapacity(trans.b,trans.e); // measure capacity
DisplayValue(cap.cval,cap.cpre,'F',3);
#if defined(NOK5110) || defined(OLED096)
lcd_line4();
#endif
lcd_fix_string(vt_str); // "Vt="
} else {
lcd_data('I');
lcd_data('=');
DisplayValue(trans.uBE[1],-5,'A',2);
#if defined(NOK5110) || defined(OLED096)
lcd_line4();
#endif
lcd_fix_string(Vgs_str); // " Vgs="
}
// Gate-threshold voltage
DisplayValue(gthvoltage,-3,'V',2);
goto end;
// end (PartFound == PART_FET)
} else if (PartFound == PART_THYRISTOR) {
lcd_fix_string(Thyristor); // "Thyristor"
goto gakOutput;
} else if (PartFound == PART_TRIAC) {
lcd_fix_string(Triac); // "Triac"
goto gakOutput;
} else if(PartFound == PART_RESISTOR) {
if (ResistorsFound == 1) { // single resistor
lcd_testpin(resis[0].rb); // Pin-number 1
lcd_fix_string(Resistor_str);
lcd_testpin(resis[0].ra); // Pin-number 2
} else { // R-Max suchen
ii = 0;
if (resis[1].rx > resis[0].rx)
ii = 1;
if (ResistorsFound == 2) {
ii = 2;
} else {
if (resis[2].rx > resis[ii].rx)
ii = 2;
}
char x = '1';
char y = '3';
char z = '2';
if (ii == 1) {
//x = '1';
y = '2';
z = '3';
}
if (ii == 2) {
x = '2';
y = '1';
z = '3';
}
lcd_data(x);
lcd_fix_string(Resistor_str); // "-[=]-"
lcd_data(y);
lcd_fix_string(Resistor_str); // "-[=]-"
lcd_data(z);
}
lcd_line2(); // 2 row
if (ResistorsFound == 1) {
RvalOut(0);
#if FLASHEND > 0x1fff
if (resis[0].lx != 0) {
// resistor have also Inductance
#if defined(NOK5110) || defined(OLED096)
lcd_line3();
#endif
lcd_fix_string(Lis_str); // "L="
DisplayValue(resis[0].lx,resis[0].lpre,'H',3); // output inductance
}
#endif
} else {
// output resistor values in right order
if (ii == 0) {
RvalOut(1);
RvalOut(2);
}
if (ii == 1) {
RvalOut(0);
RvalOut(2);
}
if (ii == 2) {
RvalOut(0);
RvalOut(1);
}
}
goto end;
// end (PartFound == PART_RESISTOR)
// capacity measurement is wanted
} else if(PartFound == PART_CAPACITOR) {
//lcd_fix_string(Capacitor);
lcd_testpin(cap.ca); // Pin number 1
lcd_fix_string(CapZeich); // capacitor sign
lcd_testpin(cap.cb); // Pin number 2
#if FLASHEND > 0x1fff
GetVloss(); // get Voltage loss of capacitor
if (cap.v_loss != 0) {
#if defined(NOK5110) || defined(OLED096)
lcd_line4();
#endif
lcd_fix_string(VLOSS_str); // " Vloss="
DisplayValue(cap.v_loss,-1,'%',2);
}
#endif
lcd_line2(); // 2 row
DisplayValue(cap.cval_max,cap.cpre_max,'F',4);
#if FLASHEND > 0x1fff
cap.esr = GetESR(cap.cb, cap.ca); // get ESR of capacitor
if (cap.esr < 65530) {
#if defined(NOK5110) || defined(OLED096)
lcd_line3();
#endif
lcd_fix_string(ESR_str);
DisplayValue(cap.esr,-2,LCD_CHAR_OMEGA,2);
}
#endif
goto end;
}
if(NumOfDiodes == 0) { // no diodes are found
lcd_fix_string(TestFailed1); // "No, unknown, or"
lcd_line2(); // 2 row
lcd_fix_string(TestFailed2); // "damaged "
lcd_fix_string(Component); // "part"
} else {
lcd_fix_string(Component); // "part"
lcd_fix_string(Unknown); // " unknown"
lcd_line2(); // 2 row
lcd_fix_string(OrBroken); // "or damaged "
lcd_data(NumOfDiodes + '0');
lcd_fix_string(AnKat); // "->|-"
}
empty_count++;
mess_count = 0;
goto end2;
gakOutput:
lcd_line2(); // 2 row
PinLayout(Cathode_char,'G','A'); // CGA= or 123=...
//- - - - - - - - - - - - - - - - - - - - - - - - - - - -
end:
empty_count = 0; // reset counter, if part is found
mess_count++; // count measurements
end2:
//ADC_DDR = (1<<TPREF) | TXD_MSK; // switch pin with reference to GND, release relay
ADC_DDR = TXD_MSK; // switch pin with reference to GND, release relay
goto start;
while(!(ON_PIN_REG & (1<<RST_PIN))); // wait ,until button is released
wait_about200ms();
// wait 14 seconds or 5 seconds (if repeat function)
for(gthvoltage = 0;gthvoltage<display_time;gthvoltage+=10) {
if(!(ON_PIN_REG & (1<<RST_PIN))) {
// If the key is pressed again...
// goto start of measurement
goto start;
}
wdt_reset();
wait_about10ms();
}
#ifdef POWER_OFF
#if POWER_OFF > 127
#define POWER2_OFF 255
#else
#define POWER2_OFF POWER_OFF*2
#endif
#if POWER_OFF+0 > 1
if ((empty_count < POWER_OFF) && (mess_count < POWER2_OFF)) {
goto start; // repeat measurement POWER_OFF times
}
#endif
// only one Measurement requested, shut off
//MCUSR = 0;
ON_PORT &= ~(1<<ON_PIN); // switch off power
// never ending loop
while(1) {
if(!(ON_PIN_REG & (1<<RST_PIN))) {
// The statement is only reached if no auto off equipment is installed
goto start;
}
wdt_reset();
wait_about10ms();
}
#else
goto start; // POWER_OFF not selected, repeat measurement
#endif
return;
} // end main
//******************************************************************
// output of flux voltage for 1-2 diodes in row 2
// bcdnum = Numbers of both Diodes:
// higher 4 Bit number of first Diode
// lower 4 Bit number of second Diode (Structure diodes[nn])
// if number >= 3 no output is done
void UfOutput(uint8_t bcdnum) {
lcd_line2(); // 2 row
lcd_fix_string(Uf_str); // "Uf="
mVOutput(bcdnum >> 4);
mVOutput(bcdnum & 0x0f);
}
void mVOutput(uint8_t nn) {
if (nn < 3) {
// Output in mV units
DisplayValue(diodes[nn].Voltage,-3,'V',3);
lcd_space();
}
}
void RvalOut(uint8_t ii) {
// output of resistor value
#if FLASHEND > 0x1fff
uint16_t rr;
if ((resis[ii].rx < 100) && (resis[0].lx == 0)) {
rr = GetESR(resis[ii].ra,resis[ii].rb);
DisplayValue(rr,-2,LCD_CHAR_OMEGA,3);
} else {
DisplayValue(resis[ii].rx,-1,LCD_CHAR_OMEGA,4);
}
#else
DisplayValue(resis[ii].rx,-1,LCD_CHAR_OMEGA,4);
#endif
lcd_space();
}
//******************************************************************
void ChargePin10ms(uint8_t PinToCharge, uint8_t ChargeDirection) {
// Load the specified pin to the specified direction with 680 Ohm for 10ms.
// Will be used by discharge of MOSFET Gates or to load big capacities.
// Parameters:
// PinToCharge: specifies the pin as mask for R-Port
// ChargeDirection: 0 = switch to GND (N-Kanal-FET), 1= switch to VCC(P-Kanal-FET)
if(ChargeDirection&1) {
R_PORT |= PinToCharge; // R_PORT to 1 (VCC)
} else {
R_PORT &= ~PinToCharge; // or 0 (GND)
}
R_DDR |= PinToCharge; // switch Pin to output, across R to GND or VCC
wait_about10ms(); // wait about 10ms
// switch back Input, no current
R_DDR &= ~PinToCharge; // switch back to input
R_PORT &= ~PinToCharge; // no Pull up
}
// first discharge any charge of capacitors
void EntladePins() {
uint8_t adc_gnd; // Mask of ADC-outputs, which can be directly connected to GND
unsigned int adcmv[3]; // voltages of 3 Pins in mV
unsigned int clr_cnt; // Clear Counter
uint8_t lop_cnt; // loop counter
// max. time of discharge in ms (10000/20) == 10s
#define MAX_ENTLADE_ZEIT (10000/20)
for(lop_cnt=0;lop_cnt<10;lop_cnt++) {
adc_gnd = TXD_MSK; // put all ADC to Input
ADC_DDR = adc_gnd;
ADC_PORT = TXD_VAL; // ADC-outputs auf 0
R_PORT = 0; // R-outputs auf 0
R_DDR = (2<<(TP3*2)) | (2<<(TP2*2)) | (2<<(TP1*2)); // R_H for all Pins to GND
adcmv[0] = W5msReadADC(TP1); // which voltage has Pin 1?
adcmv[1] = ReadADC(TP2); // which voltage has Pin 2?
adcmv[2] = ReadADC(TP3); // which voltage has Pin 3?
if ((PartFound == PART_CELL) || (adcmv[0] < CAP_EMPTY_LEVEL)
& (adcmv[1] < CAP_EMPTY_LEVEL)
& (adcmv[2] < CAP_EMPTY_LEVEL)) {
ADC_DDR = TXD_MSK; // switch all ADC-Pins to input
R_DDR = 0; // switch all R_L Ports (and R_H) to input
return; // all is discharged
}
// all Pins with voltage lower than 1V can be connected directly to GND (ADC-Port)
if (adcmv[0] < 1000) {
adc_gnd |= (1<<TP1); // Pin 1 directly to GND
}
if (adcmv[1] < 1000) {
adc_gnd |= (1<<TP2); // Pin 2 directly to GND
}
if (adcmv[2] < 1000) {
adc_gnd |= (1<<TP3); // Pin 3 directly to GND
}
ADC_DDR = adc_gnd; // switch all selected ADC-Ports at the same time
// additionally switch the leaving Ports with R_L to GND.
// since there is no disadvantage for the already directly switched pins, we can
// simply switch all R_L resistors to GND
R_DDR = (1<<(TP3*2)) | (1<<(TP2*2)) | (1<<(TP1*2)); // Pins across R_L resistors to GND
for(clr_cnt=0;clr_cnt<MAX_ENTLADE_ZEIT;clr_cnt++) {
wdt_reset();
adcmv[0] = W20msReadADC(TP1); // which voltage has Pin 1?
adcmv[1] = ReadADC(TP2); // which voltage has Pin 2?
adcmv[2] = ReadADC(TP3); // which voltage has Pin 3?
if (adcmv[0] < 1300) {
ADC_DDR |= (1<<TP1); // below 1.3V , switch directly with ADC-Port to GND
}
if (adcmv[1] < 1300) {
ADC_DDR |= (1<<TP2); // below 1.3V, switch directly with ADC-Port to GND
}
if (adcmv[2] < 1300) {
ADC_DDR |= (1<<TP3); // below 1.3V, switch directly with ADC-Port to GND
}
if ((adcmv[0] < (CAP_EMPTY_LEVEL+2)) && (adcmv[1] < (CAP_EMPTY_LEVEL+2)) && (adcmv[2] < (CAP_EMPTY_LEVEL+2))) {
break;
}
}
if (clr_cnt == MAX_ENTLADE_ZEIT) {
PartFound = PART_CELL; // mark as Battery
// there is charge on capacitor, warn later!
}
for(adcmv[0]=0;adcmv[0]<clr_cnt;adcmv[0]++) {
// for safety, discharge 5% of discharge time
wait1ms();
}
} // end for lop_cnt
}
#ifdef AUTO_RH
void RefVoltage(void) {
// RefVoltage interpolates table RHtab corresponding to voltage ref_mv .
// RHtab contain the factors to get capacity from load time with 470k for
// different Band gab reference voltages.
// for remember:
// resistor 470000 Ohm 1000 1050 1100 1150 1200 1250 1300 1350 1400 mV
// uint16_t RHTAB[] MEM_TEXT = { 954, 903, 856, 814, 775, 740, 707, 676, 648};
#define Ref_Tab_Abstand 50 // displacement of table is 50mV
#define Ref_Tab_Beginn 1000 // begin of table is 1000mV
unsigned int referenz;
unsigned int y1, y2;
uint8_t tabind;
uint8_t tabres;
#ifdef AUTO_CAL
referenz = ref_mv + (int16_t)eeprom_read_word((uint16_t *)(&ref_offset));
#else
referenz = ref_mv + REF_C_KORR;
#endif
if (referenz >= Ref_Tab_Beginn) {
referenz -= Ref_Tab_Beginn;
} else {
referenz = 0; // limit to begin of table
}
tabind = referenz / Ref_Tab_Abstand;
tabres = referenz % Ref_Tab_Abstand;
tabres = Ref_Tab_Abstand-tabres;
if (tabind > 7) {
tabind = 7; // limit to end of table
}
// interpolate the table of factors
y1 = pgm_read_word(&RHtab[tabind]);
y2 = pgm_read_word(&RHtab[tabind+1]);
// RHmultip is the interpolated factor to compute capacity from load time with 470k
RHmultip = ((y1 - y2) * tabres + (Ref_Tab_Abstand/2)) / Ref_Tab_Abstand + y2;
}
#endif
#ifdef LCD_CLEAR
void lcd_clear_line(void) {
// writes 20 spaces to LCD-Display, Cursor must be positioned to first column
unsigned char ll;
for (ll=0;ll<20;ll++) {
lcd_space();
}
}
#endif
/* ************************************************************************
* display of values and units
* ************************************************************************ */
/*
* display value and unit
* - max. 4 digits excluding "." and unit
*
* requires:
* - value
* - exponent of factor related to base unit (value * 10^x)
* e.g: p = 10^-12 -> -12
* - unit character (0 = none)
* digits = 2, 3 or 4
*/
void DisplayValue(unsigned long Value, int8_t Exponent, unsigned char Unit, unsigned char digits)
{
char OutBuffer[15];
unsigned int Limit;
unsigned char Prefix; // prefix character
uint8_t Offset; // exponent of offset to next 10^3 step
uint8_t Index; // index ID
uint8_t Length; // string length
Limit = 100; // scale value down to 2 digits
if (digits == 3) Limit = 1000; // scale value down to 3 digits
if (digits == 4) Limit = 10000; // scale value down to 4 digits
while (Value >= Limit)
{
Value += 5; // for automatic rounding
Value = Value / 10; // scale down by 10^1
Exponent++; // increase exponent by 1
}
// determine prefix
Length = Exponent + 12;
if ((int8_t)Length < 0) Length = 0; // Limit to minimum prefix
if (Length > 18) Length = 18; // Limit to maximum prefix
Index = Length / 3;
Offset = Length % 3;
if (Offset > 0)
{
Index++; // adjust index for exponent offset, take next prefix
Offset = 3 - Offset; // reverse value (1 or 2)
}
#ifdef NO_NANO
if (Index == 1)
{ // use no nano
Index++; // use mikro instead of nano
Offset += 3; // can be 3,4 or 5
}
#endif
Prefix = MEM_read_byte((uint8_t *)(&PrefixTab[Index])); // look up prefix in table
// display value
// convert value into string
utoa((unsigned int)Value, OutBuffer, 10);
Length = strlen(OutBuffer);
// position of dot
Exponent = Length - Offset; // calculate position
if (Exponent <= 0) // we have to prepend "0."
{
// 0: factor 10 / -1: factor 100
//lcd_data('0');
lcd_data('.');
#ifdef NO_NANO
while (Exponent < 0)
{
lcd_data('0'); // extra 0 for factor 10
Exponent++;
}
#else
if (Exponent < 0) lcd_data('0'); // extra 0 for factor 100
#endif
}
if (Offset == 0) Exponent = -1; // disable dot if not needed
// adjust position to array or disable dot if set to 0
//Exponent--;
// display value and add dot if requested
Index = 0;
while (Index < Length) // loop through string
{
lcd_data(OutBuffer[Index]); // display char
Index++; // next one
if (Index == Exponent) {
lcd_data('.'); // display dot
}
}
// display prefix and unit
if (Prefix != 0) lcd_data(Prefix);
if (Unit) lcd_data(Unit);
}
#ifndef INHIBIT_SLEEP_MODE
// set the processor to sleep state
// wake up will be done with compare match interrupt of counter 2
void sleep_5ms(uint16_t pause){
// pause is the delay in 5ms units
uint8_t t2_offset;
#define RESTART_DELAY_US (RESTART_DELAY_TICS/(F_CPU/1000000UL))
// for 8 MHz crystal the Restart delay is 16384/8 = 2048us
while (pause > 0) {
#if 3000 > RESTART_DELAY_US
if (pause > 1) {
// Startup time is too long with 1MHz Clock!!!!
t2_offset = (10000 - RESTART_DELAY_US) / T2_PERIOD; // set to 10ms above the actual counter
pause -= 2;
} else {
t2_offset = (5000 - RESTART_DELAY_US) / T2_PERIOD; // set to 5ms above the actual counter
pause = 0;
}
OCR2A = TCNT2 + t2_offset; // set the compare value
TIMSK2 = (0<<OCIE2B) | (1<<OCIE2A) | (0<<TOIE2); // enable output compare match A interrupt
set_sleep_mode(SLEEP_MODE_PWR_SAVE);
//set_sleep_mode(SLEEP_MODE_IDLE);
sleep_mode();
// wake up after output compare match interrupt
#else
// restart delay ist too long, use normal delay of 5ms
wait5ms();
#endif
wdt_reset();
}
TIMSK2 = (0<<OCIE2B) | (0<<OCIE2A) | (0<<TOIE2); // disable output compare match A interrupt
}
#endif
// show the Pin Layout of the device
void PinLayout(char pin1, char pin2, char pin3) {
// pin1-3 is EBC or SGD or CGA
#ifndef EBC_STYLE
// Layout with 123= style
lcd_fix_string(N123_str); // " 123="
for (ii=0;ii<3;ii++) {
if (ii == trans.e) lcd_data(pin1); // Output Character in right order
if (ii == trans.b) lcd_data(pin2);
if (ii == trans.c) lcd_data(pin3);
}
#else
#if EBC_STYLE == 321
// Layout with 321= style
lcd_fix_string(N321_str); // " 321="
ii = 3;
while (ii != 0) {
ii--;
if (ii == trans.e) lcd_data(pin1); // Output Character in right order
if (ii == trans.b) lcd_data(pin2);
if (ii == trans.c) lcd_data(pin3);
}
#else
// Layout with EBC= style
lcd_space();
lcd_data(pin1);
lcd_data(pin2);
lcd_data(pin3);
lcd_data('=');
lcd_testpin(trans.e);
lcd_testpin(trans.b);
lcd_testpin(trans.c);
#endif
#endif
}
/* -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- */
void AutoCheck(void) {
#ifdef WITH_SELFTEST
uint8_t tt; // number of running test
uint8_t ww; // counter for repeating the tests
int adcmv[7];
uint16_t u680; // 3 * (Voltage at 680 Ohm)
// define the maximum count of repetitions MAX_REP
#define MAX_REP 4
#ifdef AUTO_CAL
uint8_t cap_found; // counter for found capacitor
#ifdef AUTOSCALE_ADC
int8_t udiff; // difference between ADC Voltage with VCC or Bandgap reference
int8_t udiff2;
#endif
#endif
ADC_PORT = TXD_VAL;
ADC_DDR = TXD_MSK;
#define RequireShortedProbes
if (AllProbesShorted() != 3) return;
lcd_clear();
lcd_fix_string(SELFTEST); // "Selftest mode.."
lcd_line2();
lcd_fix2_string(R0_str); // "R0="
eeprom_write_byte((uint8_t *)(&EE_ESR_ZEROtab[2]), (int8_t)0); // clear zero offset
eeprom_write_byte((uint8_t *)(&EE_ESR_ZEROtab[3]), (int8_t)0); // clear zero offset
eeprom_write_byte((uint8_t *)(&EE_ESR_ZEROtab[1]), (int8_t)0); // clear zero offset
adcmv[0] = GetESR(TP3, TP1);
adcmv[1] = GetESR(TP3, TP2);
adcmv[2] = GetESR(TP2, TP1);
DisplayValue(adcmv[0],-2,' ',3);
DisplayValue(adcmv[1],-2,' ',3);
DisplayValue(adcmv[2],-2,LCD_CHAR_OMEGA,3);
if (adcmv[0] < 60) {
eeprom_write_byte((uint8_t *)(&EE_ESR_ZEROtab[2]), (int8_t)adcmv[0]); // fix zero offset
}
if (adcmv[1] < 60) {
eeprom_write_byte((uint8_t *)(&EE_ESR_ZEROtab[3]), (int8_t)adcmv[1]); // fix zero offset
}
if (adcmv[2] < 60) {
eeprom_write_byte((uint8_t *)(&EE_ESR_ZEROtab[1]), (int8_t)adcmv[2]); // fix zero offset
}
for(tt=0; tt<12; tt++) {
wait_about500ms();
if(!(ON_PIN_REG & (1<<RST_PIN))) {
// if key is pressed, don't repeat
break;
}
} // end for tt
#define TEST_COUNT 8
for(tt=1; tt<TEST_COUNT; tt++) { // loop for all Tests
for(ww=0; ww<MAX_REP; ww++) { // repeat the test MAX_REP times
lcd_line2(); // Cursor to column 1, row 2
lcd_clear_line(); // clear total line
lcd_line1(); // Cursor to column 1, row 1
lcd_clear_line(); // clear total line
lcd_line1(); // Cursor to column 1, row 1
lcd_data('T'); // output the Testmode "T"
lcd_string(utoa(tt, outval, 10)); // output Test number
lcd_space();
if (tt == 1) { // output of reference voltage and factors for capacity measurement
Calibrate_UR(); // get Reference voltage, Pin resistance
lcd_fix2_string(URefT); // "URef="
DisplayValue(ref_mv,-3,'V',4);
lcd_line2(); // Cursor to column 1, row 2
lcd_fix2_string(RHfakt); // "RHf="
lcd_string(utoa(RHmultip, outval, 10));
ADCconfig.Samples = 190; // set number of ADC reads near to maximum
}
if (tt == 2) { // how equal are the RL resistors?
u680 = ((long)ADCconfig.U_AVCC * (PIN_RM + R_L_VAL) / (PIN_RM + R_L_VAL + R_L_VAL + PIN_RP));
R_PORT = 1<<(TP1*2); // RL1 to VCC
R_DDR = (1<<(TP1*2)) | (1<<(TP2*2)); // RL2 to -
adcmv[0] = W20msReadADC(TP1);
adcmv[0] -= u680;
R_DDR = (1<<(TP1*2)) | (1<<(TP3*2)); // RL3 to -
adcmv[1] = W20msReadADC(TP1);
adcmv[1] -= u680;
R_PORT = 1<<(TP2*2); // RL2 to VCC
R_DDR = (1<<(TP2*2)) | (1<<(TP3*2)); // RL3 to -
adcmv[2] = W20msReadADC(TP2);
adcmv[2] -= u680;
lcd_fix_string(RLRL); // "RLRL"
}
if (tt == 3) { // how equal are the RH resistors
R_PORT = 2<<(TP1*2); // RH1 to VCC
R_DDR = (2<<(TP1*2)) | (2<<(TP2*2)); // RH2 to -
adcmv[0] = W20msReadADC(TP1);
adcmv[3] = ADCconfig.U_AVCC / 2;
adcmv[0] -= adcmv[3];
R_DDR = (2<<(TP1*2)) | (2<<(TP3*2)); // RH3 to -
adcmv[1] = W20msReadADC(TP1);
adcmv[1] -= adcmv[3];
R_PORT = 2<<(TP2*2); // RH2 to VCC
R_DDR = (2<<(TP2*2)) | (2<<(TP3*2)); // RH3 to -
adcmv[2] = W20msReadADC(TP2);
adcmv[2] -= adcmv[3];
lcd_fix_string(RHRH); // "RHRH"
}
if (tt == 4) { // Text release probes
lcd_fix_string(RELPROBE); // "Release Probes"
if (AllProbesShorted() != 0) ww = MAX_REP-2;
}
if (tt == 5) { // can we switch the ADC pins to GND across R_H resistor?
R_PORT = 0;
R_DDR = 2<<(TP1*2); // Pin 1 over R_H to GND
adcmv[0] = W20msReadADC(TP1);
R_DDR = 2<<(TP2*2); // Pin 2 over R_H to GND
adcmv[1] = W20msReadADC(TP2);
R_DDR = 2<<(TP3*2); // Pin 3 over R_H to GND
adcmv[2] = W20msReadADC(TP3);
lcd_fix_string(RH1L); // "RH_Lo="
}
if (tt == 6) { // can we switch the ADC pins to VCC across the R_H resistor?
R_DDR = 2<<(TP1*2); // Pin 1 over R_H to VCC
R_PORT = 2<<(TP1*2);
adcmv[0] = W20msReadADC(TP1) - ADCconfig.U_AVCC;
R_DDR = 2<<(TP2*2); // Pin 2 over R_H to VCC
R_PORT = 2<<(TP2*2);
adcmv[1] = W20msReadADC(TP2) - ADCconfig.U_AVCC;
R_DDR = 2<<(TP3*2); // Pin 3 over R_H to VCC
R_PORT = 2<<(TP3*2);
adcmv[2] = W20msReadADC(TP3) - ADCconfig.U_AVCC;
lcd_fix_string(RH1H); // "RH_Hi="
}
if (tt == 7) { // can we switch the ADC pins to VCC across the R_H resistor?
u680 = ((long)ADCconfig.U_AVCC * (PIN_RM + R_L_VAL) / (PIN_RM + R_L_VAL + R_H_VAL*100));
R_PORT = 2<<(TP1*2); // RH1 to VCC
R_DDR = (2<<(TP1*2)) | (1<<(TP1*2)); // RH1 to +, RL1 to -
adcmv[0] = W20msReadADC(TP1);
adcmv[0] -= u680;
R_PORT = 2<<(TP2*2); // RH2 to VCC
R_DDR = (2<<(TP2*2)) | (1<<(TP2*2)); // RH2 to +, RL2 to -
adcmv[1] = W20msReadADC(TP2);
adcmv[1] -= u680;
R_PORT = 2<<(TP3*2); // RH3 to VCC
R_DDR = (2<<(TP3*2)) | (1<<(TP3*2)); // RH3 to +, RL3 to -
adcmv[2] = W20msReadADC(TP3);
adcmv[2] -= u680;
lcd_fix_string(RHRL); // "RH/RL"
}
if (tt > 1) { // output 3 voltages
lcd_line2(); // Cursor to column 1, row 2
lcd_string(itoa(adcmv[0], outval, 10)); // output voltage 1
lcd_space();
lcd_string(itoa(adcmv[1], outval, 10)); // output voltage 2
lcd_space();
lcd_string(itoa(adcmv[2], outval, 10)); // output voltage 3
}
ADC_DDR = TXD_MSK; // all-Pins to Input
ADC_PORT = TXD_VAL; // all ADC-Ports to GND
R_DDR = 0; // all R-Ports to Input
R_PORT = 0;
if(!(ON_PIN_REG & (1<<RST_PIN))) {
// if key is pressed, don't repeat
break;
}
wait_about500ms();
if(!(ON_PIN_REG & (1<<RST_PIN))) {
// if key is pressed, don't repeat
break;
}
wait_about500ms();
} // end for ww
wait_about1s();
} // end for tt
lcd_clear();
lcd_fix_string(RIHI); // "RiHi="
DisplayValue(RRpinPL,-1,LCD_CHAR_OMEGA,3);
lcd_line2();
lcd_fix_string(RILO); // "RiLo="
DisplayValue(RRpinMI,-1,LCD_CHAR_OMEGA,3);
wait_about2s();
//measure Zero offset for Capacity measurement
adcmv[3] = 0;
PartFound = PART_NONE;
ReadCapacity(TP3, TP1);
adcmv[5] = (unsigned int) cap.cval_uncorrected.dw; // save capacity value of empty Pin 1:3
ReadCapacity(TP3, TP2);
adcmv[6] = (unsigned int) cap.cval_uncorrected.dw; // save capacity value of empty Pin 2:3
ReadCapacity(TP2, TP1);
adcmv[2] = (unsigned int) cap.cval_uncorrected.dw; // save capacity value of empty Pin 1:2
ReadCapacity(TP1, TP3);
adcmv[1] = (unsigned int) cap.cval_uncorrected.dw; // save capacity value of empty Pin 3:1
ReadCapacity(TP2, TP3);
adcmv[4] = (unsigned int) cap.cval_uncorrected.dw; // save capacity value of empty Pin 3:2
ReadCapacity(TP1, TP2);
adcmv[0] = (unsigned int) cap.cval_uncorrected.dw; // save capacity value of empty Pin 2:1
lcd_clear();
lcd_fix_string(C0_str); // output "C0 "
DisplayValue(adcmv[5],0,' ',3); // output cap0 1:3
DisplayValue(adcmv[6],0,' ',3); // output cap0 2:3
DisplayValue(adcmv[2],-12,'F',3); // output cap0 1:2
#ifdef AUTO_CAL
for (ww=0;ww<7;ww++) {
if (adcmv[ww] > 70) goto no_c0save;
}
for (ww=0;ww<7;ww++) {
// write all zero offsets to the EEprom
(void) eeprom_write_byte((uint8_t *)(&c_zero_tab[ww]),adcmv[ww]+(COMP_SLEW1 / (CC0 + CABLE_CAP + COMP_SLEW2)));
}
lcd_line2();
lcd_fix_string(OK_str); // output "OK"
no_c0save:
#endif
wait_about2s();
#ifdef AUTO_CAL
// Message C > 100nF
cap_found = 0;
for (ww=0; ww<64; ww++) {
lcd_clear();
lcd_data('1');
lcd_fix_string(CapZeich); // "-||-"
lcd_data('3');
lcd_fix2_string(MinCap_str); // " >100nF!"
PartFound = PART_NONE;
// measure offset Voltage of analog Comparator for Capacity measurement
ReadCapacity(TP3, TP1); // look for capacitor > 100nF
while (cap.cpre < -9) {
cap.cpre++;
cap.cval /= 10;
}
if ((cap.cpre == -9) && (cap.cval > 95) && (cap.cval < 22000)) {
cap_found++;
} else {
cap_found = 0; // wait for stable connection
}
if (cap_found > 1) {
// value of capacitor is correct
(void) eeprom_write_word((uint16_t *)(&ref_offset), load_diff); // hold zero offset + slew rate dependend offset
lcd_clear();
lcd_fix2_string(REF_C_str); // "REF_C="
lcd_string(itoa(load_diff, outval, 10)); // output REF_C_KORR
#if 0
// Test for switching level of the digital input of port TP3
for (ii=0;ii<8;ii++) {
ADC_PORT = TXD_VAL; // ADC-Port 1 to GND
ADC_DDR = 1<<TP1 | TXD_MSK; // ADC-Pin 1 to output 0V
R_PORT = 2<<(TP3*2); // Pin 3 over R_H to VCC
R_DDR = 2<<(TP3*2); // Pin 3 over R_H to VCC
while (1) {
wdt_reset();
if ((ADC_PIN&(1<<TP3)) == (1<<TP3)) break;
}
R_DDR = 0; // Pin 3 without current
R_PORT = 0;
adcmv[0] = ReadADC(TP3);
lcd_line3();
DisplayValue(adcmv[0],-3,'V',4);
R_DDR = 2<<(TP3*2); // Pin 3 over R_H to GND
while (1) {
wdt_reset();
if ((ADC_PIN&(1<<TP3)) != (1<<TP3)) break;
}
R_DDR = 0; // Pin 3 without current
lcd_line4();
adcmv[0] = ReadADC(TP3);
DisplayValue(adcmv[0],-3,'V',4);
wait_about1s();
}
#endif
#ifdef AUTOSCALE_ADC
ADC_PORT = TXD_VAL; // ADC-Port 1 to GND
ADC_DDR = 1<<TP1 | TXD_MSK; // ADC-Pin 1 to output 0V
R_DDR = 2<<(TP3*2); // Pin 3 over R_H to GND
do {
adcmv[0] = ReadADC(TP3);
} while (adcmv[0] > 980);
R_DDR = 0; // all Pins to input
ADCconfig.U_Bandgap = 0; // do not use internal Ref
adcmv[0] = ReadADC(TP3); // get cap voltage with VCC reference
ADCconfig.U_Bandgap = ADC_internal_reference;
adcmv[1] = ReadADC(TP3); // get cap voltage with internal reference
ADCconfig.U_Bandgap = 0; // do not use internal Ref
adcmv[2] = ReadADC(TP3); // get cap voltage with VCC reference
ADCconfig.U_Bandgap = ADC_internal_reference;
udiff = (int8_t)(((signed long)(adcmv[0] + adcmv[2] - adcmv[1] - adcmv[1])) * ADC_internal_reference / (2*adcmv[1]))+REF_R_KORR;
lcd_line2();
lcd_fix2_string(REF_R_str); // "REF_R="
udiff2 = udiff + (int8_t)eeprom_read_byte((uint8_t *)(&RefDiff));
(void) eeprom_write_byte((uint8_t *)(&RefDiff), (uint8_t)udiff2); // hold offset for true reference Voltage
lcd_string(itoa(udiff2, outval, 10)); // output correction voltage
#endif
wait_about4s();
break;
}
lcd_line2();
DisplayValue(cap.cval,cap.cpre,'F',4);
wait_about200ms(); // wait additional time
} // end for ww
#endif
ADCconfig.Samples = ANZ_MESS; // set to configured number of ADC samples
lcd_clear();
lcd_line2();
lcd_fix2_string(VERSION_str); // "Version ..."
lcd_line1();
lcd_fix_string(ATE); // "Selftest End"
#ifdef FREQUENCY_50HZ
//#define TEST_SLEEP_MODE // only select for checking the sleep delay
lcd_fix_string(T50HZ); // " 50Hz"
ADC_PORT = TXD_VAL;
ADC_DDR = 1<<TP1 | TXD_MSK; // Pin 1 to GND
R_DDR = (1<<(TP3*2)) | (1<<(TP2*2));
for(ww=0;ww<30;ww++) { // repeat the signal up to 30 times (1 minute)
for (ii=0;ii<100;ii++) { // for 2 s generate 50 Hz
R_PORT = (1<<(TP2*2)); // Pin 2 over R_L to VCC, Pin 3 over R_L to GND
#ifdef TEST_SLEEP_MODE
sleep_5ms(2); // test of timing of sleep mode call
#else
wait10ms(); // normal delay
#endif
R_PORT = (1<<(TP3*2)); // Pin 3 over R_L to VCC, Pin 2 over R_L to GND
#ifdef TEST_SLEEP_MODE
sleep_5ms(2); // test of timing of sleep mode call
#else
wait10ms(); // normal delay
#endif
wdt_reset();
}
if (!(ON_PIN_REG & (1<<RST_PIN))) {
// if key is pressed, don't repeat
break;
}
}
#endif
PartFound = PART_NONE;
wait_about1s();
#endif
}
#ifdef RequireShortedProbes
/*
* check for a short circuit between two probes
* from Markus R.
*
* requires:
* - ID of first probe (0-2)
* - ID of second probe (0-2)
*
* returns:
* - 0 if not shorted
* - 1 if shorted
*/
uint8_t ShortedProbes(uint8_t Probe1, uint8_t Probe2)
{
uint8_t Flag1 = 0; // return value
unsigned int U1; // voltage at probe #1 in mV
unsigned int U2; // voltage at probe #2 in mV
unsigned int URH; // half of reference voltage
// Set up a voltage divider between the two probes:
// - Probe1: Rl pull-up
// - Probe2: Rl pull-down
R_PORT = pgm_read_byte(&PinRLtab[Probe1]);
R_DDR = pgm_read_byte(&PinRLtab[Probe1]) | pgm_read_byte(&PinRLtab[Probe2]);
// read voltages
U1 = ReadADC(Probe1);
U2 = ReadADC(Probe2);
// We expect both probe voltages to be about the same and
// to be half of Vcc (allowed difference +/- 20mV).
URH = ADCconfig.U_AVCC / 2;
if ((U1 > URH - 20) && (U1 < URH + 20))
{
if ((U2 > URH - 20) && (U2 < URH + 20))
{
Flag1 = 1;
}
}
// reset port
R_DDR = 0;
return Flag1;
}
/*
* check for a short circuit between all probes
* from Markus R.
*
* returns:
* - 0 if no probes are short-circuited
* - number of probe pairs short-circuited (3 = all)
*/
uint8_t AllProbesShorted(void)
{
uint8_t Flag2; // return value
// check all possible combinations
Flag2 = ShortedProbes(TP1, TP2);
Flag2 += ShortedProbes(TP1, TP3);
Flag2 += ShortedProbes(TP2, TP3);
return Flag2;
}
#endif
/* -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- -=- */
//******************************************************************
void CheckPins(uint8_t HighPin, uint8_t LowPin, uint8_t TristatePin) {
/*
Function for checking the characteristic of a component with the following pin assignment
parameters:
HighPin: Pin, which will be switched to VCC at the beginning
LowPin: Pin, which will be switch to GND at the beginning
TristatePin: Pin, which will be undefined at the beginning
TristatePin will be switched to GND and VCC also .
*/
struct {
unsigned int lp_otr;
unsigned int hp1;
unsigned int hp2;
unsigned int hp3;
unsigned int lp1;
unsigned int lp2;
unsigned int tp1;
unsigned int tp2;
} adc;
uint8_t LoPinRL; // mask to switch the LowPin with R_L
uint8_t LoPinRH; // mask to switch the LowPin with R_H
uint8_t TriPinRL; // mask to switch the TristatePin with R_L
uint8_t TriPinRH; // mask to switch the TristatePin with R_H
uint8_t HiPinRL; // mask to switch the HighPin with RL
uint8_t HiPinRH; // mask to switch the HighPin with R_H
uint8_t HiADCp; // mask to switch the ADC port High-Pin
uint8_t LoADCp; // mask to switch the ADC port Low-Pin
uint8_t HiADCm; // mask to switch the ADC DDR port High-Pin
uint8_t LoADCm; // mask to switch the ADC DDR port Low-Pin
uint8_t PinMSK;
uint8_t ii; // temporary variable
#ifdef COMMON_EMITTER
unsigned int tmp16; // temporary variable
#else
#warning "without common emitter hFE"
#endif
#if FLASHEND > 0x1fff
int udiff;
#endif
#ifdef COMMON_COLLECTOR
unsigned long c_hfe; // amplification factor for common Collector (Emitter follower)
#endif
struct resis_t *thisR;
unsigned long lrx1;
unsigned long lirx1;
unsigned long lirx2;
/*
switch HighPin directls to VCC
switch R_L port for LowPin to GND
TristatePin remains switched to input , no action required
*/
wdt_reset();
//#ifdef AUTO_CAL
// uint16_t resis680pl;
// uint16_t resis680mi;
// resis680pl = eeprom_read_word(&R680pl);
// resis680mi = eeprom_read_word(&R680mi);
// #define RR680PL resis680pl
// #define RR680MI resis680mi
//#else
// #define RR680PL (R_L_VAL + PIN_RP)
// #define RR680MI (R_L_VAL + PIN_RM)
//#endif
LoPinRL = pgm_read_byte(&PinRLtab[LowPin]); // instruction for LowPin R_L
LoPinRH = LoPinRL + LoPinRL; // instruction for LowPin R_H
TriPinRL = pgm_read_byte(&PinRLtab[TristatePin]); // instruction for TristatePin R_L
TriPinRH = TriPinRL + TriPinRL; // instruction for TristatePin R_H
HiPinRL = pgm_read_byte(&PinRLtab[HighPin]); // instruction for HighPin R_L
HiPinRH = HiPinRL + HiPinRL; // instruction for HighPin R_H
HiADCp = pgm_read_byte(&PinADCtab[HighPin]); // instruction for ADC High-Pin
LoADCp = pgm_read_byte(&PinADCtab[LowPin]); // instruction for ADC Low-Pin
HiADCm = HiADCp | TXD_MSK;
HiADCp |= TXD_VAL;
LoADCm = LoADCp | TXD_MSK;
LoADCp |= TXD_VAL;
// setting of Pins
R_PORT = 0; // resistor-Port outputs to 0
R_DDR = LoPinRL; // Low-Pin to output and across R_L to GND
ADC_DDR = HiADCm; // High-Pin to output
ADC_PORT = HiADCp; // High-Pin fix to Vcc
// for some MOSFET the gate (TristatePin) must be discharged
ChargePin10ms(TriPinRL,0); // discharge for N-Kanal
adc.lp_otr = W5msReadADC(LowPin); // read voltage of Low-Pin
if (adc.lp_otr >= 977) { // no current now?
ChargePin10ms(TriPinRL,1); // else: discharge for P-channel (Gate to VCC)
adc.lp_otr = ReadADC(LowPin); // read voltage of Low-Pin again
}
#if DebugOut == 5
lcd_line2();
lcd_clear_line();
lcd_line2();
#endif
//if(adc.lp_otr > 92) { // there is some current without TristatePin current
if(adc.lp_otr > 455) { // there is more than 650uA current without TristatePin current
#if DebugOut == 5
lcd_testpin(LowPin);
lcd_data('F');
lcd_testpin(HighPin);
lcd_space();
wait_about1s();
#endif
// Test if N-JFET or if self-conducting N-MOSFET
R_DDR = LoPinRL | TriPinRH; // switch R_H for Tristate-Pin (probably Gate) to GND
adc.lp1 = W20msReadADC(LowPin); // measure voltage at the assumed Source
adc.tp1 = ReadADC(TristatePin); // measure Gate voltage
R_PORT = TriPinRH; // switch R_H for Tristate-Pin (probably Gate) to VCC
adc.lp2 = W20msReadADC(LowPin); // measure voltage at the assumed Source again
// If it is a self-conducting MOSFET or JFET, then must be: adc.lp2 > adc.lp1
if (adc.lp2>(adc.lp1+488)) {
if (PartFound != PART_FET) {
// measure voltage at the Gate, differ between MOSFET and JFET
ADC_PORT = TXD_VAL;
ADC_DDR = LoADCm; // Low-Pin fix to GND
R_DDR = TriPinRH | HiPinRL; // High-Pin to output
R_PORT = TriPinRH | HiPinRL; // switch R_L for High-Pin to VCC
adc.lp2 = W20msReadADC(TristatePin); // read voltage of assumed Gate
if (adc.lp2>3911) { // MOSFET
PartFound = PART_FET; // N-Kanal-MOSFET
PartMode = PART_MODE_N_D_MOS; // Depletion-MOSFET
} else { // JFET (pn-passage between Gate and Source is conducting )
PartFound = PART_FET; // N-Kanal-JFET
PartMode = PART_MODE_N_JFET;
}
#if DebugOut == 5
lcd_data('N');
lcd_data('J');
#endif
//if ((PartReady == 0) || (adc.lp1 > trans.uBE[0]))
// there is no way to find out the right Source / Drain
trans.uBE[0] = adc.lp1;
gthvoltage = adc.lp1 - adc.tp1; // voltage GS (Source - Gate)
trans.uBE[1] = (unsigned int)(((unsigned long)adc.lp1 * 1000) / RR680MI); // Id 0.01mA
trans.b = TristatePin; // save Pin numbers found for this FET
trans.c = HighPin;
trans.e = LowPin;
}
}
ADC_PORT = TXD_VAL; // direct outputs to GND
// Test, if P-JFET or if self-conducting P-MOSFET
ADC_DDR = LoADCm; // switch Low-Pin (assumed Drain) direct to GND,
// R_H for Tristate-Pin (assumed Gate) is already switched to VCC
R_DDR = TriPinRH | HiPinRL; // High-Pin to output
R_PORT = TriPinRH | HiPinRL; // High-Pin across R_L to Vcc
adc.hp1 = W20msReadADC(HighPin); // measure voltage at assumed Source
adc.tp1 = ReadADC(TristatePin); // measure Gate voltage
R_PORT = HiPinRL; // switch R_H for Tristate-Pin (assumed Gate) to GND
adc.hp2 = W20msReadADC(HighPin); // read voltage at assumed Source again
// if it is a self-conducting P_MOSFET or P-JFET , then must be: adc.hp1 > adc.hp2
if (adc.hp1>(adc.hp2+488)) {
if (PartFound != PART_FET) {
// read voltage at the Gate , to differ between MOSFET and JFET
ADC_PORT = HiADCp; // switch High-Pin directly to VCC
ADC_DDR = HiADCm; // switch High-Pin to output
adc.tp2 = W20msReadADC(TristatePin); //read voltage at the assumed Gate
if (adc.tp2<977) { // MOSFET
PartFound = PART_FET; // P-Kanal-MOSFET
PartMode = PART_MODE_P_D_MOS; // Depletion-MOSFET
} else { // JFET (pn-passage between Gate and Source is conducting)
PartFound = PART_FET; // P-Kanal-JFET
PartMode = PART_MODE_P_JFET;
}
#if DebugOut == 5
lcd_data('P');
lcd_data('J');
#endif
gthvoltage = adc.tp1 - adc.hp1; // voltage GS (Gate - Source)
trans.uBE[1] = (unsigned int)(((unsigned long)(ADCconfig.U_AVCC - adc.hp1) * 1000) / RR680PL); // Id 0.01mA
trans.b = TristatePin; // save Pin numbers found for this FET
trans.c = LowPin;
trans.e = HighPin;
}
}
} // end component has current without TristatePin signal