1303 lines
50 KiB
Arduino
1303 lines
50 KiB
Arduino
|
//--- HEADERS ---//
|
||
|
#include <LiquidCrystal.h>
|
||
|
|
||
|
//--- MACRO DEFINITIONS ---//
|
||
|
|
||
|
#define FASTADC 1
|
||
|
#ifndef cbi
|
||
|
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||
|
#endif
|
||
|
#ifndef sbi
|
||
|
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||
|
#endif
|
||
|
|
||
|
//--- PIN DEFINITIONS ---//
|
||
|
|
||
|
// LCD pins definition
|
||
|
#define rs 7
|
||
|
#define en 6
|
||
|
#define d4 5
|
||
|
#define d5 4
|
||
|
#define d6 3
|
||
|
#define d7 2
|
||
|
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
|
||
|
|
||
|
// Encoder pins definition
|
||
|
#define CLK 10
|
||
|
#define DT 9
|
||
|
#define SW 8
|
||
|
|
||
|
// Menu buttons
|
||
|
#define UP_BTN_PIN 11
|
||
|
#define DOWN_BTN_PIN 12
|
||
|
|
||
|
// Discharge button pin definition
|
||
|
#define DISCH_PIN A6
|
||
|
|
||
|
// Excitation pin definition
|
||
|
#define EXC_PIN A1
|
||
|
|
||
|
// Battery level pins
|
||
|
#define BATTERY1_PIN A5
|
||
|
#define BATTERY2_PIN A4
|
||
|
#define BATTERY_CHECK 1000
|
||
|
|
||
|
// Feedback pin
|
||
|
#define FEEDBACK_PIN A3
|
||
|
|
||
|
// Reed-relay control pin
|
||
|
#define RELAY_PIN A2
|
||
|
|
||
|
//--- VARIABLE DECLARATIONS & INITIALIZATIONS ---//
|
||
|
|
||
|
// modes of operation
|
||
|
#define MODE_CONTACT_DISCHARGE 1
|
||
|
#define MODE_AIR_DISCHARGE 2
|
||
|
#define MODE_TEST 3
|
||
|
// default MODE
|
||
|
int Mode=MODE_CONTACT_DISCHARGE;
|
||
|
|
||
|
// Encoder variables
|
||
|
unsigned int currentStateCLK;
|
||
|
unsigned int currentStateDT;
|
||
|
unsigned int lastStateCLK;
|
||
|
String currentDir ="";
|
||
|
unsigned long lastButtonPress = 0;
|
||
|
unsigned long lastButtonPressUP = 0;
|
||
|
unsigned long lastButtonPressDOWN = 0;
|
||
|
bool encoder_change=false;
|
||
|
int btnState;
|
||
|
|
||
|
// Discharge button variables
|
||
|
unsigned long DICHARGElastButtonPress = 0;
|
||
|
int DICHARGEbtnState;
|
||
|
|
||
|
// Menu buttons variables
|
||
|
bool button_UP_pressed=false;
|
||
|
bool button_DOWN_pressed=false;
|
||
|
bool button_UP_status=false;
|
||
|
bool button_DOWN_status=false;
|
||
|
int x, x_check;
|
||
|
|
||
|
// Menu variables
|
||
|
bool Case_0_status=false;
|
||
|
bool Case_1_status=false;
|
||
|
bool Case_2_status=false;
|
||
|
int menu_status;
|
||
|
|
||
|
// At startup, set active menu to menu_status
|
||
|
bool menu_status_CHANGE=true;
|
||
|
|
||
|
// At startup, write on LCD for the first time
|
||
|
bool LCD_CHANGE=true;
|
||
|
|
||
|
float voltage_level=0;
|
||
|
float voltage_step=1;
|
||
|
|
||
|
// Battery status variables
|
||
|
int battery_status=-1;
|
||
|
int battery_status_update=-1;
|
||
|
unsigned int battery_status_counter=BATTERY_CHECK;
|
||
|
unsigned int battery_level=0;
|
||
|
unsigned int battery_level1=0;
|
||
|
unsigned int battery_level2=0;
|
||
|
|
||
|
// Arduino voltage power supply (pin Vin & referent voltage for ADC)
|
||
|
float Vcc=4.73;
|
||
|
|
||
|
// feedback variables
|
||
|
unsigned int vfeedback;
|
||
|
unsigned int rFeedback;
|
||
|
unsigned int xfeedback;
|
||
|
unsigned int feedback_pulses;
|
||
|
unsigned long startMillis;
|
||
|
unsigned long stopMillis;
|
||
|
unsigned long air_time_millis=5000;
|
||
|
bool bFeedbackON=false;
|
||
|
|
||
|
// Time measuring
|
||
|
unsigned long StartTime;
|
||
|
unsigned long CurrentTime;
|
||
|
unsigned long ElapsedTime;
|
||
|
|
||
|
// Pulse generation variables and lookup tables
|
||
|
int puls_freq=12; // frequency in kHz for pulses in testing mode
|
||
|
int us_delay; // delay in micro-seconds
|
||
|
unsigned int num_pulses=100; // number of pulses for HV generation
|
||
|
unsigned int dnum=100; // increment for number of pulses
|
||
|
int voltage=4; // voltage in kV
|
||
|
unsigned int num_ESDs=1; // number of ESD pulses to generate
|
||
|
// lookup table for number of pulses for voltage levels 1kV, 2kV, ... 15kV respectivly (both positive and negative)
|
||
|
unsigned int volt2freq[]={7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10};
|
||
|
unsigned int volt2puls[]={2, 8, 15, 22, 37, 105, 129, 152, 174, 198, 225, 258, 301, 357, 466};
|
||
|
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* setup */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Arduino initialization for O-ESD */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* The function is called when a sketch starts. */
|
||
|
/* It initializes variables, pin modes, start using libraries, etc. */
|
||
|
/* It is run once after power-up or reset of the Arduino board. */
|
||
|
/* */
|
||
|
/* Parameters: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* LCD_startup() */
|
||
|
/* check_battery_status() */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 20/Dec/2024 J.D. & D.O. Created */
|
||
|
/* 28/Apr/2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
void setup()
|
||
|
{
|
||
|
// set default menu_status
|
||
|
switch(Mode)
|
||
|
{
|
||
|
case MODE_CONTACT_DISCHARGE:
|
||
|
{
|
||
|
menu_status=2;
|
||
|
break;
|
||
|
}
|
||
|
case MODE_AIR_DISCHARGE:
|
||
|
{
|
||
|
menu_status=2;
|
||
|
break;
|
||
|
}
|
||
|
case MODE_TEST:
|
||
|
{
|
||
|
menu_status=1;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// LCD startup
|
||
|
LCD_startup();
|
||
|
|
||
|
// Encoder initialization
|
||
|
pinMode(CLK,INPUT);
|
||
|
pinMode(DT,INPUT);
|
||
|
pinMode(SW, INPUT);
|
||
|
lastStateCLK = digitalRead(CLK);
|
||
|
|
||
|
// Output pin initialization
|
||
|
digitalWrite(EXC_PIN, LOW);
|
||
|
pinMode(EXC_PIN, OUTPUT);
|
||
|
|
||
|
// Button pins initialization
|
||
|
pinMode(UP_BTN_PIN, INPUT);
|
||
|
pinMode(DOWN_BTN_PIN, INPUT);
|
||
|
|
||
|
// Battery pins initialization
|
||
|
digitalWrite(BATTERY1_PIN, LOW);
|
||
|
pinMode(BATTERY1_PIN, INPUT);
|
||
|
digitalWrite(BATTERY2_PIN, LOW);
|
||
|
pinMode(BATTERY2_PIN, INPUT);
|
||
|
|
||
|
// Discharge pin
|
||
|
digitalWrite(DISCH_PIN, LOW);
|
||
|
pinMode(DISCH_PIN, INPUT);
|
||
|
|
||
|
// Reed realy pin
|
||
|
pinMode(RELAY_PIN, OUTPUT);
|
||
|
|
||
|
// Serial communication is used only for testing purposes
|
||
|
Serial.begin(9600);
|
||
|
|
||
|
// Read battery
|
||
|
check_battery_status();
|
||
|
LCD_CHANGE=true;
|
||
|
|
||
|
// Set prescaler
|
||
|
#if FASTADC
|
||
|
// set prescaler to 16
|
||
|
sbi(ADCSRA,ADPS2);
|
||
|
cbi(ADCSRA,ADPS1);
|
||
|
cbi(ADCSRA,ADPS0);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* loop */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Arduino main loop for O-ESD */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* Main loop in which O-ESD program changes and responds. */
|
||
|
/* */
|
||
|
/* Parameters: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* handle_encoder() */
|
||
|
/* handle_menu_buttons() */
|
||
|
/* handle_discharge_button() */
|
||
|
/* handle_batteries() */
|
||
|
/* handle_display() */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 15/Dec /2024 J.D. & D.O. Created */
|
||
|
/* 28/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
void loop()
|
||
|
{
|
||
|
|
||
|
// keep reading encoder as long as it changes
|
||
|
while(handle_encoder()){}
|
||
|
|
||
|
handle_menu_buttons();
|
||
|
|
||
|
handle_discharge_button();
|
||
|
|
||
|
handle_batteries();
|
||
|
|
||
|
handle_display();
|
||
|
}
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* handle_display() */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* All LCD (display) activities */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* Based on menu_status_CHANGE & LCD_CHANGE writes on LCD. */
|
||
|
/* */
|
||
|
/* Parameters: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* print_battery_status() */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 10/Feb /2025 J.D. & D.O. Created */
|
||
|
/* 28/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
void handle_display()
|
||
|
{
|
||
|
// update LCD
|
||
|
if(LCD_CHANGE)
|
||
|
{
|
||
|
//lcd.clear();
|
||
|
if(menu_status>=0)
|
||
|
{
|
||
|
switch(Mode)
|
||
|
{
|
||
|
case MODE_TEST:
|
||
|
{
|
||
|
lcd.setCursor(1, 0);
|
||
|
lcd.print("Battery: ");
|
||
|
print_battery_status();
|
||
|
|
||
|
lcd.setCursor(1, 1);
|
||
|
lcd.print("Freq: ");
|
||
|
lcd.setCursor(10,1);
|
||
|
lcd.print(puls_freq);
|
||
|
lcd.print("kHz");
|
||
|
|
||
|
lcd.setCursor(1, 2);
|
||
|
lcd.print("Pulses: ");
|
||
|
lcd.setCursor(10,2);
|
||
|
lcd.print(num_pulses);
|
||
|
|
||
|
lcd.setCursor(1,3);
|
||
|
lcd.print("No.ESDs: ");
|
||
|
lcd.setCursor(10,3);
|
||
|
lcd.print(num_ESDs);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MODE_CONTACT_DISCHARGE:
|
||
|
{
|
||
|
lcd.setCursor(1, 0);
|
||
|
lcd.print("Battery: ");
|
||
|
print_battery_status();
|
||
|
|
||
|
lcd.setCursor(1, 1);
|
||
|
lcd.print("Mode: Contact ");
|
||
|
|
||
|
lcd.setCursor(1, 2);
|
||
|
lcd.print("Voltage: ");
|
||
|
lcd.setCursor(10,2);
|
||
|
if(voltage>0)
|
||
|
{
|
||
|
lcd.print("+");
|
||
|
}
|
||
|
lcd.print(voltage);
|
||
|
lcd.print("kV");
|
||
|
|
||
|
lcd.setCursor(1,3);
|
||
|
lcd.print("No.ESDs: ");
|
||
|
lcd.setCursor(10,3);
|
||
|
lcd.print(num_ESDs);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MODE_AIR_DISCHARGE:
|
||
|
{
|
||
|
lcd.setCursor(1, 0);
|
||
|
lcd.print("Battery: ");
|
||
|
print_battery_status();
|
||
|
|
||
|
lcd.setCursor(1, 1);
|
||
|
lcd.print("Mode: Air ");
|
||
|
|
||
|
lcd.setCursor(1, 2);
|
||
|
lcd.print("Voltage: ");
|
||
|
lcd.setCursor(10,2);
|
||
|
if(voltage>0)
|
||
|
{
|
||
|
lcd.print("+");
|
||
|
}
|
||
|
lcd.print(voltage);
|
||
|
lcd.print("kV");
|
||
|
|
||
|
lcd.setCursor(1,3);
|
||
|
lcd.print("Time : ");
|
||
|
lcd.setCursor(10,3);
|
||
|
lcd.print(air_time_millis/1000);
|
||
|
lcd.print("s");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
LCD_CHANGE=false;
|
||
|
menu_status_CHANGE=true;
|
||
|
}
|
||
|
|
||
|
// batteries extended status (voltages and precentages)
|
||
|
if(menu_status==-1)
|
||
|
{
|
||
|
print_battery_status();
|
||
|
LCD_CHANGE=false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// update active menu item
|
||
|
if(menu_status_CHANGE && menu_status>=0)
|
||
|
{
|
||
|
lcd.setCursor(0, 0);
|
||
|
lcd.print(" ");
|
||
|
lcd.setCursor(0, 1);
|
||
|
lcd.print(" ");
|
||
|
lcd.setCursor(0, 2);
|
||
|
lcd.print(" ");
|
||
|
lcd.setCursor(0, 3);
|
||
|
lcd.print(" ");
|
||
|
|
||
|
lcd.setCursor(0,menu_status);
|
||
|
lcd.print(">");
|
||
|
menu_status_CHANGE=false;
|
||
|
}
|
||
|
}
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* handle_batteries() */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Power supply: batteries, status, voltage, etc. */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* Reads analog pins to measure voltage of batteries. */
|
||
|
/* Initiates display update. */
|
||
|
/* */
|
||
|
/* Parameters: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* check_battery_status() */
|
||
|
/* print_battery_status() */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 10/Feb /2025 J.D. & D.O. Created */
|
||
|
/* 28/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
void handle_batteries()
|
||
|
{
|
||
|
if(battery_status_counter++>BATTERY_CHECK)
|
||
|
{
|
||
|
check_battery_status();
|
||
|
battery_status_counter=0;
|
||
|
}
|
||
|
}
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* LCD_startup */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Everything related to LCD startup */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* LCD initization. */
|
||
|
/* Splash screen & delay. */
|
||
|
/* */
|
||
|
/* Parameters: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 08/Feb /2025 D.O. & J.D. Created */
|
||
|
/* 29/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
void LCD_startup()
|
||
|
{
|
||
|
// LCD initialization
|
||
|
lcd.begin(20, 4);
|
||
|
lcd.clear();
|
||
|
|
||
|
// Splash screen
|
||
|
lcd.setCursor(0,0);
|
||
|
lcd.print(" OPEN HARDWARE FOR ");
|
||
|
lcd.setCursor(0,1);
|
||
|
lcd.print(" ELECTROSTATIC ");
|
||
|
lcd.setCursor(0,2);
|
||
|
lcd.print(" DISCHARGE TESTING ");
|
||
|
lcd.setCursor(0,3);
|
||
|
lcd.print(" v1.0 - 2025. ");
|
||
|
delay(1000);
|
||
|
}
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* check_battery_status */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Measure voltages of batteries */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* Reads analog voltages of batteries. */
|
||
|
/* Battery voltage is read in steps ~5V/1024. */
|
||
|
/* Based on minimal voltage of batteries update battery status. */
|
||
|
/* */
|
||
|
/* Parameters: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* All initializations */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 20/Dec /2024 J.D. Created */
|
||
|
/* 29/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
void check_battery_status()
|
||
|
{
|
||
|
battery_level1=analogRead(BATTERY1_PIN);
|
||
|
battery_level2=analogRead(BATTERY2_PIN);
|
||
|
|
||
|
Serial.print("BATTERY1:");
|
||
|
Serial.print(battery_level1);
|
||
|
Serial.print("\n");
|
||
|
Serial.print("BATTERY2:");
|
||
|
Serial.print(battery_level2);
|
||
|
Serial.print("\n");
|
||
|
|
||
|
// calculate battery level #1 using 75k-75k voltage divider
|
||
|
battery_level1=2*battery_level1-battery_level2;
|
||
|
}
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* print_battery_status */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Prints batteries status line on LCD */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* Based on measurements of battery voltages prints status line. */
|
||
|
/* */
|
||
|
/* Parameters: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* All initializations */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 20/Dec /2024 J.D. & D.O Created */
|
||
|
/* 29/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
void print_battery_status()
|
||
|
{
|
||
|
float vref=Vcc; // reference voltage for measurements on input pins
|
||
|
float vmin=3.3; // minimal voltage allowed for batteries
|
||
|
float vmax=4.2; // maximal voltage for batteries
|
||
|
if(menu_status>=0) // print only battery status line
|
||
|
{
|
||
|
if(min(battery_level1,battery_level2)<=256)
|
||
|
{
|
||
|
lcd.setCursor(10,0);
|
||
|
lcd.print("External");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
lcd.setCursor(10,0);
|
||
|
if(battery_level1<=755 || battery_level2<=755)
|
||
|
{
|
||
|
lcd.print("RECHARGE!");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
float BP;
|
||
|
battery_level=min(battery_level1, battery_level2);
|
||
|
BP=((battery_level*vref)/1024.0-vmin)/(vmax-vmin)*100.0;
|
||
|
lcd.print(BP,0);
|
||
|
lcd.print("%");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(menu_status==-1) // print batteries status details
|
||
|
{
|
||
|
float BL1=(battery_level1*vref)/1024.0;
|
||
|
float BL2=(battery_level2*vref)/1024.0;
|
||
|
float BP1;
|
||
|
float BP2;
|
||
|
|
||
|
lcd.clear();
|
||
|
lcd.setCursor(0,0);
|
||
|
lcd.print(" BATTERY DETAILS");
|
||
|
|
||
|
lcd.setCursor(0,1);
|
||
|
lcd.print(" Battery1:");
|
||
|
lcd.print(BL1,2);
|
||
|
lcd.print("V");
|
||
|
lcd.print("(");
|
||
|
if(BL1>vmin)
|
||
|
{
|
||
|
BP1=((battery_level1*vref)/1024.0-vmin)/(vmax-vmin)*100.0;
|
||
|
if(BP1>99) BP1=99;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BP1=0;
|
||
|
}
|
||
|
lcd.print(BP1,0);
|
||
|
lcd.print("%)");
|
||
|
|
||
|
lcd.setCursor(0,2);
|
||
|
lcd.print(" Battery2:");
|
||
|
lcd.print(BL2,2);
|
||
|
lcd.print("V");
|
||
|
lcd.print("(");
|
||
|
if(BL2>vmin)
|
||
|
{
|
||
|
BP2=((battery_level2*vref)/1024.0-vmin)/(vmax-vmin)*100.0;
|
||
|
if(BP2>99) BP2=99;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BP2=0;
|
||
|
}
|
||
|
lcd.print(BP2,0);
|
||
|
lcd.print("%)");
|
||
|
|
||
|
lcd.setCursor(0,3);
|
||
|
lcd.print(">EXIT");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* handle_menu_buttons */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Handles UP/DOWN menu buttons */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* Reads digital pins associated with UP and DOWN buttons. */
|
||
|
/* Initiates menu changes. */
|
||
|
/* */
|
||
|
/* Parameters: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 20/Dec /2024 J.D. & D.O Created */
|
||
|
/* 29/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
void handle_menu_buttons()
|
||
|
{
|
||
|
// Handle buttons
|
||
|
int btnStateUP = digitalRead(UP_BTN_PIN);
|
||
|
int btnStateDOWN = digitalRead(DOWN_BTN_PIN);
|
||
|
|
||
|
if(btnStateUP==HIGH && btnStateDOWN==HIGH && millis() - lastButtonPressUP > 250)
|
||
|
{
|
||
|
Serial.print("UP&DOWN pressed.\n");
|
||
|
if(Mode==MODE_CONTACT_DISCHARGE || Mode==MODE_AIR_DISCHARGE)
|
||
|
{
|
||
|
Mode=MODE_TEST;
|
||
|
lastButtonPressUP=millis();
|
||
|
LCD_CHANGE=true;
|
||
|
Serial.print("MODE_TEST\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(Mode==MODE_TEST)
|
||
|
{
|
||
|
Mode=MODE_CONTACT_DISCHARGE;
|
||
|
lastButtonPressUP=millis();
|
||
|
LCD_CHANGE=true;
|
||
|
Serial.print("MODE_CONTACT_DISCHARGE\n");
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// UP button
|
||
|
if (btnStateUP == HIGH)
|
||
|
{
|
||
|
if (millis() - lastButtonPressUP > 50)
|
||
|
{
|
||
|
Serial.print("UP pressed.\n");
|
||
|
if (menu_status>0 && menu_status<=3)
|
||
|
{
|
||
|
menu_status=menu_status-1;
|
||
|
menu_status_CHANGE=true;
|
||
|
}
|
||
|
}
|
||
|
lastButtonPressUP = millis();
|
||
|
}
|
||
|
|
||
|
// DOWN button
|
||
|
if (btnStateDOWN == HIGH)
|
||
|
{
|
||
|
if (millis() - lastButtonPressDOWN > 50)
|
||
|
{
|
||
|
Serial.print("DOWN pressed.\n");
|
||
|
if (menu_status<3 && menu_status>=0)
|
||
|
{
|
||
|
menu_status=menu_status+1;
|
||
|
menu_status_CHANGE=true;
|
||
|
}
|
||
|
}
|
||
|
lastButtonPressDOWN = millis();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* handle_encoder */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Handles rotary encoder: rotations and pushbutton */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* Reads three digital pins connected to rotary encoder. */
|
||
|
/* Initiates all changes based on read data. */
|
||
|
/* */
|
||
|
/* Parameters: */
|
||
|
/* None */
|
||
|
/* Returns: true - encoder changes or false - no changes */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 20/Dec /2024 J.D. Created */
|
||
|
/* 29/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
bool handle_encoder()
|
||
|
{
|
||
|
encoder_change=false;
|
||
|
currentStateCLK = digitalRead(CLK);
|
||
|
currentStateDT = digitalRead(DT);
|
||
|
|
||
|
if (currentStateCLK != lastStateCLK && currentStateCLK==1)
|
||
|
{
|
||
|
encoder_change=true;
|
||
|
Serial.print(currentStateCLK);
|
||
|
Serial.print(currentStateDT);
|
||
|
Serial.print(lastStateCLK);
|
||
|
|
||
|
if (currentStateDT != currentStateCLK)
|
||
|
{
|
||
|
Serial.print("ENCODER -.\n");
|
||
|
currentDir ="CCW";
|
||
|
switch(Mode)
|
||
|
{
|
||
|
case MODE_TEST:
|
||
|
{
|
||
|
if(menu_status==1 && puls_freq>1)
|
||
|
{
|
||
|
puls_freq=puls_freq-1;
|
||
|
}
|
||
|
if(menu_status==2 && num_pulses>dnum)
|
||
|
{
|
||
|
num_pulses=num_pulses-dnum;
|
||
|
}
|
||
|
if(menu_status==3 && num_ESDs>1)
|
||
|
{
|
||
|
num_ESDs=num_ESDs-1;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case MODE_CONTACT_DISCHARGE:
|
||
|
{
|
||
|
if(menu_status==2 && voltage>-12)
|
||
|
{
|
||
|
voltage=voltage-1;
|
||
|
}
|
||
|
|
||
|
if(menu_status==3 && num_ESDs>1)
|
||
|
{
|
||
|
num_ESDs=num_ESDs-1;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case MODE_AIR_DISCHARGE:
|
||
|
{
|
||
|
if(menu_status==2 && voltage>-15)
|
||
|
{
|
||
|
voltage=voltage-1;
|
||
|
}
|
||
|
if(menu_status==3 && air_time_millis>1000)
|
||
|
{
|
||
|
air_time_millis=air_time_millis-1000;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Serial.print("ENCODER +.\n");
|
||
|
currentDir ="CW";
|
||
|
switch(Mode)
|
||
|
{
|
||
|
case MODE_TEST:
|
||
|
{
|
||
|
if(menu_status==1 && puls_freq<50)
|
||
|
{
|
||
|
puls_freq=puls_freq+1;
|
||
|
}
|
||
|
if(menu_status==2 && num_pulses<65536-dnum)
|
||
|
{
|
||
|
num_pulses=num_pulses+dnum;
|
||
|
}
|
||
|
if(menu_status==3 && num_ESDs<65534)
|
||
|
{
|
||
|
num_ESDs=num_ESDs+1;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case MODE_CONTACT_DISCHARGE:
|
||
|
{
|
||
|
if(menu_status==2 && voltage<12)
|
||
|
{
|
||
|
voltage=voltage+1;
|
||
|
}
|
||
|
|
||
|
if(menu_status==3 && num_ESDs<65534)
|
||
|
{
|
||
|
num_ESDs=num_ESDs+1;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case MODE_AIR_DISCHARGE:
|
||
|
{
|
||
|
if(menu_status==2 && voltage<15)
|
||
|
{
|
||
|
voltage=voltage+1;
|
||
|
}
|
||
|
|
||
|
if(menu_status==3 && air_time_millis<60000)
|
||
|
{
|
||
|
air_time_millis=air_time_millis+1000;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
LCD_CHANGE=true;
|
||
|
}
|
||
|
lastStateCLK = currentStateCLK;
|
||
|
|
||
|
btnState = digitalRead(SW);
|
||
|
if(btnState == HIGH)
|
||
|
{
|
||
|
if (millis() - lastButtonPress > 250)
|
||
|
{
|
||
|
Serial.print("ENCODER pressed.\n");
|
||
|
switch (menu_status)
|
||
|
{
|
||
|
case -1:
|
||
|
menu_status=0;
|
||
|
break;
|
||
|
|
||
|
case 0:
|
||
|
menu_status=-1;
|
||
|
break;
|
||
|
|
||
|
case 1:
|
||
|
if(Mode==MODE_CONTACT_DISCHARGE)
|
||
|
{
|
||
|
Mode=MODE_AIR_DISCHARGE;
|
||
|
break;
|
||
|
}
|
||
|
if(Mode==MODE_AIR_DISCHARGE)
|
||
|
{
|
||
|
Mode=MODE_CONTACT_DISCHARGE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case 2:
|
||
|
if(Mode==MODE_TEST)
|
||
|
{
|
||
|
if(dnum==100)
|
||
|
{
|
||
|
dnum=1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
dnum=dnum*10;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
Serial.print(menu_status);
|
||
|
Serial.print("\n");
|
||
|
LCD_CHANGE=true;
|
||
|
}
|
||
|
lastButtonPress = millis();
|
||
|
}
|
||
|
|
||
|
return encoder_change;
|
||
|
}
|
||
|
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* handle_discharge_button */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Handles discharge button press */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* Reads digital pin connected to discharge button. */
|
||
|
/* Stops all other functions and initiates discharge. */
|
||
|
/* */
|
||
|
/* Parameters: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* Contact_discharge() */
|
||
|
/* Air_discharge() */
|
||
|
/* Test_discharge() */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 20/Dec /2024 J.D. & D.O. Created */
|
||
|
/* 29/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
void handle_discharge_button()
|
||
|
{
|
||
|
|
||
|
DICHARGEbtnState = analogRead(DISCH_PIN);
|
||
|
if (DICHARGEbtnState <= 400)
|
||
|
{
|
||
|
Serial.print("DISCHARGE pressed.\n");
|
||
|
if (millis() - DICHARGElastButtonPress > 50)
|
||
|
{
|
||
|
switch(Mode)
|
||
|
{
|
||
|
case MODE_CONTACT_DISCHARGE: // Contact discharge
|
||
|
Contact_discharge();
|
||
|
break;
|
||
|
|
||
|
case MODE_AIR_DISCHARGE: // Air discharge
|
||
|
Air_discharge();
|
||
|
break;
|
||
|
|
||
|
case MODE_TEST: // Testing
|
||
|
Test_discharge();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
DICHARGElastButtonPress = millis();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* read_feedback */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Measure high-voltage output (with voltage divider) */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* Reads analog voltage of divider for high-voltage output. */
|
||
|
/* Positive HV is above Vcc/2 (up to Vcc) */
|
||
|
/* Negative HV is below Vcc/2 (down to 0) */
|
||
|
/* */
|
||
|
/* Parameters: */
|
||
|
/* None */
|
||
|
/* Returns int (0-1024) that corresponds to the scaled output */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 25/Jan /2025 D.O. Created */
|
||
|
/* 29/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
unsigned int read_feedback()
|
||
|
{
|
||
|
unsigned int feedback_voltage;
|
||
|
|
||
|
// digital filtering
|
||
|
unsigned int i;
|
||
|
unsigned int nAq=3;
|
||
|
feedback_voltage=0;
|
||
|
for(i=0; i<nAq; i++)
|
||
|
{
|
||
|
feedback_voltage+=analogRead(FEEDBACK_PIN);
|
||
|
}
|
||
|
feedback_voltage=feedback_voltage/nAq;
|
||
|
|
||
|
return feedback_voltage;
|
||
|
}
|
||
|
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* control_target */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Calculate int that corresponds to target output at control pin */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* Based on user-specified voltage calculates target int. */
|
||
|
/* Positive HV is in the range 512-1024 (from 0 to +15kV) */
|
||
|
/* Negative HV is in the range 0-512 (from -15kV to 0) */
|
||
|
/* */
|
||
|
/* Parameters (global): */
|
||
|
/* Returns int that corresponds to target output */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 25/Jan /2025 D.O. Created */
|
||
|
/* 29/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
unsigned int control_target()
|
||
|
{
|
||
|
float R1=1e9;
|
||
|
float R2=150e3;
|
||
|
float N=1024;
|
||
|
float res;
|
||
|
|
||
|
res=(0.5+R2/(R1+R2)*voltage*1000.0/Vcc)*N;
|
||
|
|
||
|
if(res<0)
|
||
|
{
|
||
|
res=0.0;
|
||
|
}
|
||
|
if(res>1024)
|
||
|
{
|
||
|
res=1024.0;
|
||
|
}
|
||
|
|
||
|
return (unsigned int)res;
|
||
|
}
|
||
|
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* Contact_discharge */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Performs all operations for contact discharge. */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* Controls LCD during contact discharge. */
|
||
|
/* Generates HV. */
|
||
|
/* Controls HV reed relay. */
|
||
|
/* */
|
||
|
/* Parameters (global): */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* control_target() */
|
||
|
/* read_feedback() */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 25/Jan /2025 D.O. Created */
|
||
|
/* 29/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
void Contact_discharge()
|
||
|
{
|
||
|
lcd.clear();
|
||
|
lcd.setCursor(1,0);
|
||
|
lcd.print("CONTACT DISCHARGE");
|
||
|
lcd.setCursor(1,1);
|
||
|
lcd.print("Voltage: ");
|
||
|
if(voltage>0)
|
||
|
{
|
||
|
lcd.print("+");
|
||
|
}
|
||
|
lcd.print(voltage);
|
||
|
lcd.print("kV");
|
||
|
lcd.setCursor(1,2);
|
||
|
lcd.print("ESD pulse: ");
|
||
|
|
||
|
|
||
|
num_pulses=volt2puls[abs(voltage)-1];
|
||
|
vfeedback=control_target();
|
||
|
//lcd.setCursor(1,3);
|
||
|
//lcd.print(vfeedback);
|
||
|
//lcd.print("/");
|
||
|
|
||
|
for (int cnt=0; cnt<num_ESDs; cnt++)
|
||
|
{
|
||
|
puls_freq =volt2freq[abs(voltage)-1];
|
||
|
us_delay=1000/(2*puls_freq);
|
||
|
|
||
|
lcd.setCursor(12,2);
|
||
|
lcd.print(cnt+1);
|
||
|
lcd.print("/");
|
||
|
lcd.print(num_ESDs);
|
||
|
|
||
|
// generate high-voltage output
|
||
|
for (int counter=0; counter<num_pulses; counter++)
|
||
|
{
|
||
|
//digitalWrite(EXC_PIN, HIGH);
|
||
|
PORTC = PORTC | B00000010;
|
||
|
delayMicroseconds(us_delay);
|
||
|
//digitalWrite(EXC_PIN, LOW);
|
||
|
PORTC = PORTC ^ B00000010;
|
||
|
delayMicroseconds(us_delay);
|
||
|
}
|
||
|
|
||
|
// correct high-voltage output with feedback (if needed)
|
||
|
bFeedbackON=true;
|
||
|
puls_freq=12;
|
||
|
us_delay=1000/(2*puls_freq);
|
||
|
|
||
|
while(bFeedbackON)
|
||
|
{
|
||
|
rFeedback=read_feedback();
|
||
|
if(voltage>0) bFeedbackON=rFeedback<vfeedback;
|
||
|
else bFeedbackON=rFeedback>vfeedback;
|
||
|
|
||
|
//lcd.setCursor(7,3);
|
||
|
//lcd.print(rFeedback);
|
||
|
|
||
|
if(bFeedbackON)
|
||
|
{
|
||
|
//digitalWrite(EXC_PIN, HIGH);
|
||
|
PORTC = PORTC | B00000010;
|
||
|
delayMicroseconds(us_delay);
|
||
|
//digitalWrite(EXC_PIN, LOW);
|
||
|
PORTC = PORTC ^ B00000010;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// close and open relay
|
||
|
Serial.print("RELAY ON.\n");
|
||
|
//digitalWrite(RELAY_PIN, HIGH);
|
||
|
PORTC=PORTC | B00000100;
|
||
|
delayMicroseconds(5000);
|
||
|
//digitalWrite(RELAY_PIN, LOW);
|
||
|
PORTC=PORTC ^ B00000100;
|
||
|
Serial.print("RELAY OFFs.\n");
|
||
|
|
||
|
// pause for the next discharge
|
||
|
delay(1000);
|
||
|
}
|
||
|
lcd.begin(20,4);
|
||
|
LCD_CHANGE=true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* Air_discharge */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Performs all operations for air discharge. */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* Generates HV. */
|
||
|
/* Controls LCD during air discharge. */
|
||
|
/* */
|
||
|
/* Parameters (global): */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* control_target() */
|
||
|
/* read_feedback() */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 25/Jan /2025 D.O. Created */
|
||
|
/* 29/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
void Air_discharge()
|
||
|
{
|
||
|
lcd.clear();
|
||
|
lcd.setCursor(1,0);
|
||
|
lcd.print("AIR DISCHARGE");
|
||
|
lcd.setCursor(1,1);
|
||
|
lcd.print("Voltage: ");
|
||
|
if(voltage>0)
|
||
|
{
|
||
|
lcd.print("+");
|
||
|
}
|
||
|
lcd.print(voltage);
|
||
|
lcd.print("kV");
|
||
|
lcd.setCursor(1,2);
|
||
|
lcd.print("Hold time: ");
|
||
|
lcd.print(air_time_millis/1000);
|
||
|
lcd.print("s");
|
||
|
|
||
|
|
||
|
if(voltage==0)
|
||
|
{
|
||
|
num_pulses=0;
|
||
|
puls_freq=12;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
num_pulses=volt2puls[abs(voltage)-1];
|
||
|
puls_freq =volt2freq[abs(voltage)-1];
|
||
|
}
|
||
|
|
||
|
us_delay=1000/(2*puls_freq);
|
||
|
|
||
|
for (int counter=0; counter<num_pulses; counter++)
|
||
|
{
|
||
|
//digitalWrite(EXC_PIN, HIGH);
|
||
|
PORTC = PORTC | B00000010;
|
||
|
delayMicroseconds(us_delay);
|
||
|
//digitalWrite(EXC_PIN, LOW);
|
||
|
PORTC = PORTC ^ B00000010;
|
||
|
delayMicroseconds(us_delay);
|
||
|
}
|
||
|
|
||
|
puls_freq=12;
|
||
|
us_delay=1000/(2*puls_freq);
|
||
|
vfeedback=control_target();
|
||
|
//lcd.setCursor(1,3);
|
||
|
//lcd.print(vfeedback);
|
||
|
//lcd.print("/");
|
||
|
//delay(2000);
|
||
|
|
||
|
startMillis=millis();
|
||
|
while(millis()-startMillis<air_time_millis)
|
||
|
{
|
||
|
rFeedback=read_feedback();
|
||
|
if(voltage>0) bFeedbackON=rFeedback<vfeedback;
|
||
|
else bFeedbackON=rFeedback>vfeedback;
|
||
|
|
||
|
// stop on first spark
|
||
|
//if(7*abs(vfeedback-512)>10*abs(rFeedback-512)) break;
|
||
|
|
||
|
if(bFeedbackON)
|
||
|
{
|
||
|
//lcd.setCursor(7,3);
|
||
|
//lcd.print(rFeedback);
|
||
|
|
||
|
//digitalWrite(EXC_PIN, HIGH);
|
||
|
PORTC = PORTC | B00000010;
|
||
|
delayMicroseconds(us_delay);
|
||
|
//digitalWrite(EXC_PIN, LOW);
|
||
|
PORTC = PORTC ^ B00000010;
|
||
|
}
|
||
|
bFeedbackON=false;
|
||
|
}
|
||
|
|
||
|
lcd.begin(20,4);
|
||
|
LCD_CHANGE=true;
|
||
|
}
|
||
|
|
||
|
/************************************************************************/
|
||
|
/* */
|
||
|
/* Test_discharge */
|
||
|
/* */
|
||
|
/* Purpose: */
|
||
|
/* Performs all operations for testing and measuring discharges. */
|
||
|
/* Primary function is for testing and calibrating! */
|
||
|
/* */
|
||
|
/* Description: */
|
||
|
/* Controls LCD during test discharge. */
|
||
|
/* Generates HV based on internal parameters. */
|
||
|
/* */
|
||
|
/* Parameters (global): */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* Required routines: */
|
||
|
/* None */
|
||
|
/* */
|
||
|
/* History: Date Contributors Comment */
|
||
|
/* 25/Jan /2025 D.O. Created */
|
||
|
/* 29/Apr /2025 v1.0 */
|
||
|
/* */
|
||
|
/************************************************************************/
|
||
|
void Test_discharge()
|
||
|
{
|
||
|
lcd.clear();
|
||
|
lcd.setCursor(6,1);
|
||
|
lcd.print("TESTING");
|
||
|
lcd.setCursor(5,2);
|
||
|
lcd.print("DISCHARGE");
|
||
|
//delay(250);
|
||
|
|
||
|
//lcd.clear();
|
||
|
//lcd.noDisplay();
|
||
|
//delay(250);
|
||
|
|
||
|
us_delay=1000/(2*puls_freq);
|
||
|
for (int cnt=0; cnt<num_ESDs; cnt++)
|
||
|
{
|
||
|
for (int counter=0; counter<num_pulses; counter++)
|
||
|
{
|
||
|
//digitalWrite(EXC_PIN, HIGH);
|
||
|
PORTC = PORTC | B00000010;
|
||
|
delayMicroseconds(us_delay);
|
||
|
//digitalWrite(EXC_PIN, LOW);
|
||
|
PORTC = PORTC ^ B00000010;
|
||
|
delayMicroseconds(us_delay);
|
||
|
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Serial.print("RELAY ON.\n");
|
||
|
//digitalWrite(RELAY_PIN, HIGH);
|
||
|
PORTC=PORTC | B00000100;
|
||
|
delayMicroseconds(5000);
|
||
|
//digitalWrite(RELAY_PIN, LOW);
|
||
|
PORTC=PORTC ^ B00000100;
|
||
|
Serial.print("RELAY OFFs.\n");
|
||
|
*/
|
||
|
|
||
|
delay(2000);
|
||
|
}
|
||
|
|
||
|
//lcd.display();
|
||
|
//lcd.clear();
|
||
|
//lcd.setCursor(4,1);
|
||
|
//lcd.print("SUCCESSFULL");
|
||
|
//lcd.setCursor(5,2);
|
||
|
//lcd.print("DISCHARGE");
|
||
|
//delay(2000);
|
||
|
|
||
|
lcd.begin(20,4);
|
||
|
LCD_CHANGE=true;
|
||
|
}
|