O-ESD/v1.0/Software/OESD.ino
2025-05-12 10:44:25 +02:00

1303 lines
50 KiB
C++

//--- 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>-8)
{
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<8)
{
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;
}