//simplest, one relay
//define pins
#define Live_Relay 6
#define Pilot_Output 3
#define Prox_Output 2
#define Pilot_Read A1
#define Prox_Read A0
#define Charge_Pot A2
#define Cable_Connected 8
#define EV_Connected 9
#define Communicating 10
#define Charging 11
#define Tripped 12
#define Error 13
//define voltage levels
//Pilot voltages
//SAE_J1772 specifications allow +/- 0.5V from the +12V, and +/- 1V on the +9V, 6V
#define Min_12V 909
#define Max_12V 950
#define Min_9V 805
#define Max_9V 867
#define Min_6V 712
#define Max_6V 778
#define Min_Neg12 162
#define Max_Neg12 203
//Proximity voltages
#define Min_13A 2.9
#define Max_13A 3.1
#define Min_20A 1.924
#define Max_20A 2.124
#define Min_32A 0.733
#define Max_32A 0.933
#define Min_63A 0.355
#define Max_63A 0.555
//global variables
int findPilotVoltage();
float V_Max = 0;
float V_Min = 0;
float current_voltage;
int EVSE_State =1 ;
//int Charge_Req = 6; ///just placing this here temporaroily in stead of a selection medthod.
//int Charge_Level = 0;
//setup loop ( runs once)
void setup() {
pinMode(Pilot_Read, INPUT);
pinMode(Prox_Read, INPUT);
pinMode(Pilot_Output, OUTPUT);
// pwm behavior
TCCR2B = TCCR2B & 0b11110000 | 0B00001011 ; //adjust prescaler and set counter mode to custom
OCR2A = 0xF8; //tweak the PWM counter to get 1kHZ
pinMode(Prox_Output, OUTPUT);
pinMode(Live_Relay, OUTPUT);
}
//main loop (runs continuously)
void loop() {
//local variables
int Cable_rating = 0;
int Charge_Req = 0 ;
int Charge_Level = 0;
// cable detection code
//the proximity detection
float prox_value = analogRead(Prox_Read);
//1024 divisions of the arduino internal ADC so to calculate voltage;
float prox_voltage = (prox_value * 5.0) / 1024.0;
//cable rating detection
if ((prox_voltage > Min_13A) && (prox_voltage < Max_13A)) {
Cable_rating = 13;
} else if ((prox_voltage > Min_20A) && (prox_voltage < Max_20A)) {
Cable_rating = 20;
} else if ((prox_voltage > Min_32A) && (prox_voltage < Max_32A)) {
Cable_rating = 32;
} else if ((prox_voltage > Min_63A) && (prox_voltage < Max_63A)) {
Cable_rating = 63;
} else {
Cable_rating = 0;
}
// pilot detection code
//the pilot voltage
float pilot_value = analogRead(Pilot_Read);
//1024 divisions of the arduino internal ADC so to calculate voltage;
float pilot_voltage = (pilot_value * 5.0) / 1024.0;
// deciding charge level
// input from pot to decide charge level
Charge_Req = analogRead(Charge_Pot) / 20 ; //1024 steps, devided by 20 maxes a max value of 51.2A
Charge_Level = 4.25 * min(Charge_Req, Cable_rating); //this makes sure the requested charge is not higher than the cable rating, then converts it to the PWM scale
//use switch case to decide on charge state
switch (EVSE_State) {
case 1: //waiting for cable
delay (1000);
digitalWrite(Prox_Output,HIGH); //activate 5V prox signal
delay (1000);
if (Cable_rating > 10) {
EVSE_State = 2;
digitalWrite(Cable_Connected,HIGH);
}
break;
case 2: //waiting for car to connect
digitalWrite(Live_Relay,LOW); //open live relay
analogWrite(Pilot_Output, 255); //activate PWM pilot pin (100% cycle to make continuous 12V signal )
delay (3000);
findPilotVoltage();
if (Cable_rating < 10){
EVSE_State = 1;}
else if ((Cable_rating > 10) && (V_Max > Min_9V) && (V_Max < Max_9V)) //&& (V_Min > Min_Neg12) && (V_Min <Max_Neg12))
{
EVSE_State = 3;
digitalWrite(EV_Connected,HIGH);
}
break;
case 3: // car connected
delay (100);
analogWrite(Pilot_Output, Charge_Level); //activate PWM pilot pin//activate pilot PWM (approriate cycle duty to cable rating and requested charge speed)
delay (1000);
findPilotVoltage();
if (Cable_rating < 10)
{
EVSE_State = 1;
}
else if ((Cable_rating > 10) && (V_Max > Min_12V) && (V_Max < Max_12V)) //&& (V_Min > Min_Neg12) && (V_Min <Max_Neg12))
{
EVSE_State = 2;
}
else if ((Cable_rating > 10) && (V_Max > Min_6V) && (V_Max < Max_6V)) //&& (V_Min > Min_Neg12) && (V_Min <Max_Neg12))
{
EVSE_State = 4;
digitalWrite(Communicating,HIGH);
}
break;
case 4:
delay (1000);
digitalWrite(Live_Relay,HIGH); //close live relay
delay (500);
findPilotVoltage();
if ((Cable_rating > 10) && (V_Max > Min_6V) && (V_Max < Max_6V)) //&& (V_Min > Min_Neg12) && (V_Min <Max_Neg12))
{
digitalWrite(Charging,HIGH);
}
else EVSE_State = 5;
break;
case 5: //tripping
digitalWrite(Live_Relay,LOW); //open live relay
digitalWrite(Prox_Output,LOW); //swtich off prox signal
delay (1000);
digitalWrite(Tripped,HIGH);
break;
default: //unknown condition
digitalWrite(Live_Relay,LOW); //open live relay
digitalWrite(Error,HIGH);
break;
}
}
// function to find max and min voltages on pilot A1
int findPilotVoltage() {
int i = 0;
V_Max = 556;
V_Min = 556;
current_voltage = 556;
while (i < 99) {
current_voltage = analogRead(Pilot_Read);
if (current_voltage > V_Max) {
V_Max = current_voltage;
}
if (current_voltage < V_Min) {
V_Min = current_voltage;
}
i++;
}
return V_Max;
return V_Min;
}