diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ffff840 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build/ +.vscode/ + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c3b0e3c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "external/cmake-microchip"] + path = external/cmake-microchip + url = git://github.com/Elemecca/cmake-microchip.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7d42223 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.3) + +# set up the Microchip cross toolchain +set(CMAKE_TOOLCHAIN_FILE external/cmake-microchip/toolchain.cmake) + +# set the default MCU model +set(MICROCHIP_MCU PIC18F26K22) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + +project(xc8-cmake C) + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpedantic") +set(CMAKE_C_FLAGS_DEBUG "-g") +set(CMAKE_C_FLAGS_RELEASE "-O3") + +#add_subdirectory(src/) +add_subdirectory(version2/) diff --git a/README.md b/README.md index 54a7275..c2e4f8c 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,7 @@ Register | Access | Description | Unit | Values 0xA6 | R/W | Charging current | 0.1 A | 6 - 80 0xA7 | R/W | Access bit | | 0:No Access / 1:Access 0xA8 | R/W | EVSE mode (without saving) | | 0:Normal / 1:Smart / 2:Solar +0xA9 | R | Internal Temperature in C° ## Register 0xC*: Configuration @@ -118,6 +119,12 @@ Register | Access | Description | Unit | Values 0xC7 | R/W | External Switch on IO2 | | 0:Disable / 1:Access Push-Button / 2:Access Switch / 3:Smart-Solar Push-Button / 4:Smart-Solar Switch 0xC8 | R/W | Residual Current Monitor on IO3 | | 0:Disable / 1:Enable +## Register 0xD*: Extended Configuration + +Register | Access | Description | Unit | Values +--- | --- | --- | --- | --- +0xD0 | R/W | Disable Menu | | 0: Menu Enabled / 1: Menu Disable + ## Register 0xE*: Load balancing configuration (same on all SmartEVSE) Register | Access | Description | Unit | Values diff --git a/external/cmake-microchip b/external/cmake-microchip new file mode 160000 index 0000000..c7462ae --- /dev/null +++ b/external/cmake-microchip @@ -0,0 +1 @@ +Subproject commit c7462ae5f7487aa49415581675bc235ffa7ea998 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..102b5b7 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,10 @@ +set(SOURCES + CurrentTX.c + EVSE.c + LCD.c +) + +add_executable(version1 ${SOURCES}) +target_include_directories(version1 PRIVATE ./) + +target_link_libraries(version1) diff --git a/version2/CMakeLists.txt b/version2/CMakeLists.txt new file mode 100644 index 0000000..88303e3 --- /dev/null +++ b/version2/CMakeLists.txt @@ -0,0 +1,11 @@ +set(SOURCES + SmartEVSE2.X/bootloader.c + SmartEVSE2.X/EVSE.c + SmartEVSE2.X/GLCD.c + SmartEVSE2.X/utils.c +) + +add_executable(version2 ${SOURCES}) +target_include_directories(version2 PRIVATE SmartEVSE2.X/) + +target_link_libraries(version2) diff --git a/version2/SmartEVSE2.X/EVSE.c b/version2/SmartEVSE2.X/EVSE.c index 73a71d3..a34e301 100644 --- a/version2/SmartEVSE2.X/EVSE.c +++ b/version2/SmartEVSE2.X/EVSE.c @@ -133,6 +133,7 @@ const far char StrNormal[] = "Normal"; const far char StrSolar[] = "Solar"; const far char StrSolenoid[] = "Solenoid"; const far char StrMotor[] = "Motor"; +const far char StrRelay[] = "Relay"; const far char StrDisabled[] = "Disabled"; const far char StrLoadBl[5][9] = {"Disabled", "Master", "Slave 1", "Slave 2", "Slave 3"}; const far char StrSwitch[5][10] = {"Disabled", "Access B", "Access S", "Sma-Sol B", "Sma-Sol S"}; @@ -156,12 +157,15 @@ unsigned int MaxCurrent = MAX_CURRENT; unsigned int MinCurrent = MIN_CURRENT; // Minimal current the EV is happy with (A) double ICal = ICAL; // CT calibration value char Mode = MODE; // EVSE mode (0:Normal / 1:Smart) -char Lock = LOCK; // Cable lock (0:Disable / 1:Solenoid / 2:Motor) +char Lock = LOCK; // Cable lock (0:Disable / 1:Solenoid / 2:Motor / 3:Relay) unsigned int MaxCircuit = MAX_CIRCUIT; // Max current of the EVSE circuit (A) char Config = CONFIG; // Configuration (0:Socket / 1:Fixed Cable) char LoadBl = LOADBL; // Load Balance Setting (0:Disable / 1:Master / 2-4:Slave) char Switch = SWITCH; // External Switch on I/O 2 (0:Disable / 1:Access / 2:Smart-Solar) char RCmon = RC_MON; // Residual Current Monitor on I/O 3 (0:Disable / 1:Enable) + +char EX_disable_menu = 0; // 0: Menu Enabled / 1: Menu Disable + unsigned int StartCurrent = START_CURRENT; unsigned int StopTime = STOP_TIME; unsigned int ImportCurrent = IMPORT_CURRENT; @@ -178,7 +182,7 @@ signed double Irms[3]={0, 0, 0}; // Max 3 phases supported unsigned char State = STATE_A; -unsigned char Error = NO_ERROR; +unsigned int Error = NO_ERROR; unsigned char NextState; unsigned int MaxCapacity; // Cable limit (A) (limited by the wire in the charge cable, set automatically, or manually if Config=Fixed Cable) @@ -365,6 +369,20 @@ void interrupt high_isr(void) } unlocktimer = 0; } + } else if (Lock == 3) { // Cable lock type Relay? + if (Error || (State != STATE_C && NextState != STATE_C)) { + SOLENOID_REALY_OFF; + locktimer = 0; + } else { // State C or NextState C + SOLENOID_REALY_ON; + if (locktimer++ > SOLENOID_REALY_DELAY_MAX) { + if (PORTCbits.RC1 == 1) { // still unlocked... + Error |= ERROR_LOCK; + } else { + Error &= ~ERROR_LOCK; + } + } + } } Timer++; // mSec counter (overflows in 1193 hours) @@ -600,7 +618,7 @@ void ModbusDecode(unsigned char *buf, unsigned char len) { // when checksum == 0 data is ok. if (!crc16(buf, len)) { // CRC OK - // printf("\n valid Modbus packet: Address %02x Function %02x", Modbus.Address, Modbus.Function); + // printf("\n\r valid Modbus packet: Address %02x Function %02x", Modbus.Address, Modbus.Function); switch (Modbus.Function) { case 0x04: // (Read input register) @@ -619,7 +637,7 @@ void ModbusDecode(unsigned char *buf, unsigned char len) { // response packet Modbus.Type = MODBUS_RESPONSE; } else { - printf("\nInvalid modbus packet"); + printf("\n\rInvalid modbus packet"); } } break; @@ -635,7 +653,7 @@ void ModbusDecode(unsigned char *buf, unsigned char len) { // value Modbus.Value = (buf[4] <<8) | buf[5]; } else { - printf("\nInvalid modbus packet"); + printf("\n\rInvalid modbus packet"); } break; case 0x10: @@ -655,7 +673,7 @@ void ModbusDecode(unsigned char *buf, unsigned char len) { // request packet Modbus.Type = MODBUS_REQUEST; } else { - printf("\nInvalid modbus packet"); + printf("\n\rInvalid modbus packet"); } } break; @@ -773,6 +791,8 @@ void validate_settings(void) { if (Mode == MODE_NORMAL) { MainsMeter = 0; PVMeter = 0; } // Disable PV reception if not configured if (MainsMeterMeasure == 0) PVMeter = 0; + // Menu default enabled + if (EX_disable_menu != 1) EX_disable_menu = 0; } void read_settings(void) { @@ -809,6 +829,7 @@ void read_settings(void) { eeprom_read_object(&EMConfig[EM_CUSTOM].IDivisor, sizeof EMConfig[EM_CUSTOM].IDivisor); eeprom_read_object(&ImportCurrent, sizeof ImportCurrent); eeprom_read_object(&Grid, sizeof Grid); + eeprom_read_object(&EX_disable_menu, sizeof EX_disable_menu); validate_settings(); @@ -851,6 +872,7 @@ void write_settings(void) { eeprom_write_object(&EMConfig[EM_CUSTOM].IDivisor, sizeof EMConfig[EM_CUSTOM].IDivisor); eeprom_write_object(&ImportCurrent, sizeof ImportCurrent); eeprom_write_object(&Grid, sizeof Grid); + eeprom_write_object(&EX_disable_menu, sizeof EX_disable_menu); unlock55 = 0; // clear unlock values unlockAA = 0; @@ -889,11 +911,12 @@ unsigned char ReadPilot(void) void ProximityPin(void) { ADCON0 = 0b00000101; // ADC input AN1 (Proximity Pin) - delay(100); // delay 100ms (blocking) + //delay(100); // delay 10ms (blocking) ADCON0bits.GO = 1; // initiate ADC conversion on the selected channel while (ADCON0bits.GO); // wait for conversion to finish (blocking) - MaxCapacity = 13; // No resistor, Max cable current = 13A + MaxCapacity = 0; // cable defective + if ((ADRES > 626) && (ADRES < 666)) MaxCapacity = 13; // Max cable current = 13A 1500R if ((ADRES > 394) && (ADRES < 434)) MaxCapacity = 16; // Max cable current = 16A 680R if ((ADRES > 175) && (ADRES < 193)) MaxCapacity = 32; // Max cable current = 32A 220R if ((ADRES > 88) && (ADRES < 98)) MaxCapacity = 63; // Max cable current = 63A 100R @@ -1310,7 +1333,7 @@ unsigned char getMenuItems (void) { MenuItems[m++] = MENU_CONFIG; // Configuration (0:Socket / 1:Fixed Cable) if (!Config) { // ? Fixed Cable? - MenuItems[m++] = MENU_LOCK; // - Cable lock (0:Disable / 1:Solenoid / 2:Motor) + MenuItems[m++] = MENU_LOCK; // - Cable lock (0:Disable / 1:Solenoid / 2:Motor / 3:Relay) } MenuItems[m++] = MENU_MODE; // EVSE mode (0:Normal / 1:Smart) if (Mode == MODE_SOLAR && LoadBl < 2) { // ? Solar mode and Load Balancing Disabled/Master? @@ -1460,6 +1483,11 @@ unsigned char setItemValue(unsigned char nav, unsigned int val) { if (val == 0) State = STATE_A; } break; + case EX_LOCK_MENU: + EX_disable_menu = val; + if(EX_disable_menu != 1) EX_disable_menu = 0; + ret = 1; + break; default: break; } @@ -1524,6 +1552,9 @@ unsigned int getItemValue(unsigned char nav) { case MENU_EMCUSTOM_IDIVISOR: return EMConfig[EM_CUSTOM].IDivisor; + case EX_LOCK_MENU: + return EX_disable_menu; + case STATUS_STATE: return State + (65 - STATE_A); case STATUS_ERROR: @@ -1536,7 +1567,8 @@ unsigned int getItemValue(unsigned char nav) { return Balanced[0]; case STATUS_ACCESS: return Access_bit; - + case STATUS_TEMP: + return TempEVSE; default: return 0; } @@ -1582,6 +1614,7 @@ const far char * getMenuItemOption(unsigned char nav) { case MENU_LOCK: if (Lock == 1) return StrSolenoid; else if (Lock == 2) return StrMotor; + else if (Lock == 3) return StrRelay; else return StrDisabled; case MENU_SWITCH: return StrSwitch[Switch]; @@ -1652,10 +1685,11 @@ unsigned char mapModbusRegister2ItemID() { // Modbus.Register / Modbus.RegisterC // 0xA6: Charging current (A * 10) // 0xA7: Access bit // 0xA8: EVSE Mode - else if (Modbus.Register >= 0xA0 && Modbus.Register <= 0xA8) { + // 0xA9: Internal Temperature + else if (Modbus.Register >= 0xA0 && Modbus.Register <= 0xA9) { RegisterStart = 0xA0; ItemStart = STATUS_STATE; - Count = 9; + Count = 10; } // Register 0xC*: Configuration @@ -1674,6 +1708,14 @@ unsigned char mapModbusRegister2ItemID() { // Modbus.Register / Modbus.RegisterC Count = 9; } + // Register 0xD*: Extended Configuration + // 0xD0: Lock Menu / Disable Menu + else if (Modbus.Register >= 0xD0 && Modbus.Register <= 0xD0) { + RegisterStart = 0xD0; + ItemStart = EX_LOCK_MENU; + Count = 1; + } + // Register 0xE*: Load balancing configuration (same on all SmartEVSE) // 0xE0: Max Charge Current of the system // 0xE1: EVSE mode @@ -1735,7 +1777,7 @@ void WriteItemValueResponse(unsigned char ItemID) { OK = setItemValue(ItemID, Modbus.Value); } - if (OK && ItemID < STATUS_STATE) write_settings(); + if (OK && (ItemID < STATUS_STATE || ItemID >= EX_LOCK_MENU)) write_settings(); if (Modbus.Address > 0 || LoadBl == 0) { if (!ItemID) { @@ -1763,7 +1805,7 @@ void WriteMultipleItemValueResponse(unsigned char ItemID) { } } - if (OK && ItemID < STATUS_STATE) write_settings(); + if (OK && (ItemID < STATUS_STATE || ItemID >= EX_LOCK_MENU)) write_settings(); if (Modbus.Address > 0 || LoadBl == 0) { if (!ItemID) { @@ -1790,7 +1832,7 @@ void WriteMultipleItemValueResponse(unsigned char ItemID) { // MAX - Set MAX Charge Current for the EV (16-80) // MIN - Set MIN Charge Current the EV will accept // CAL - Calibrate CT1 -// LOCK - Cable lock Disable/Solenoid/Motor +// LOCK - Cable lock Disable/Solenoid/Motor/Relay // ACCESS - Access control on IO2 // RCMON - Residual Current Monitor on IO3 // L1: 1.2A L2: 5.3A L3: 0.4A (MAX:26A MIN:10A) @@ -1840,6 +1882,9 @@ void RS232cli(void) { } else if (strcmp(U2buffer, (const far char *) "MOTOR") == 0) { Lock = 2; write_settings(); + } else if (strcmp(U2buffer, (const far char *) "RELAY") == 0) { + Lock = 3; + write_settings(); } else if (strcmp(U2buffer, (const far char *) "DISABLE") == 0) { Lock = 0; write_settings(); @@ -1926,6 +1971,8 @@ void RS232cli(void) { printf(VERSION); printf(" for detailed instructions, see www.smartevse.org\r\n"); printf(" Internal Temperature: %2u C\r\n", TempEVSE); + printf(" EVSE state: %c\r\n", State - 1 + 'A'); + printf(" Cable limit: %uA Max: %uA\r\n", MaxCapacity, MaxCurrent); printf("----------------------------------------------------------------------\r\n"); for(i = 0; i < MenuItemsCount - 1; i++) { printf("%-07s - %-50s - ", MenuStr[MenuItems[i]].Key, MenuStr[MenuItems[i]].Desc); @@ -1980,7 +2027,7 @@ void RS232cli(void) { printf("EVSE Circuit Current limit set to: %u A\r\nEnter new limit (10-80): ", MaxCircuit); break; case MENU_LOCK: - printf("Cable lock set to : %s\r\nEnter new Cable lock mode (DISABLE/SOLENOID/MOTOR): ", getMenuItemOption(menu)); + printf("Cable lock set to : %s\r\nEnter new Cable lock mode (DISABLE/SOLENOID/MOTOR/RELAY): ", getMenuItemOption(menu)); break; case MENU_SWITCH: printf("Access Control on pin SW set to : %s\r\nAccess Control on SW (%s", getMenuItemOption(menu), StrSwitch[0]); @@ -2413,6 +2460,9 @@ void main(void) { Error &= ~NO_SUN; Error &= ~LESS_6A; + Error &= ~ERROR_CABLE_DEFECTIVE; + Error &= ~ERROR_LOCK; + ChargeDelay = 0; // Clear ChargeDelay when disconnected. NextState = 0; } else if ( (pilot == PILOT_9V || pilot == STATE_A_TO_C) @@ -2424,26 +2474,39 @@ void main(void) { { DiodeCheck = 0; ProximityPin(); // Sample Proximity Pin - printf("Cable limit: %uA Max: %uA \r\n", MaxCapacity, MaxCurrent); - if (MaxCurrent > MaxCapacity) ChargeCurrent = MaxCapacity * 10; // Do not modify Max Cable Capacity or MaxCurrent (fix 2.05) - else ChargeCurrent = MaxCurrent * 10; // Instead use new variable ChargeCurrent - if (LoadBl > 1) // Load Balancing : Slave - { - // Send command to Master, followed by Max Charge Current - ModbusWriteSingleRequest(LoadBl, 0x02, ChargeCurrent); - printf("02 sent to Master, requested %.1f A\r\n", (double)ChargeCurrent/10); - State = STATE_COMM_B; - Timer = 0; // Clear the Timer - } else { // Load Balancing: Master or Disabled - BalancedMax[0] = MaxCapacity * 10; - Balanced[0] = ChargeCurrent; // Set pilot duty cycle to ChargeCurrent (v2.15) - BalancedState[0] = 1; // Mark as active - State = STATE_B; // switch to State B - ActivationMode = 30; // Activation mode is triggered if state C is not entered in 30 seconds. - BacklightTimer = BACKLIGHT; // Backlight ON - BACKLIGHT_ON; - printf("STATE A->B\r\n"); + if (MaxCapacity == 0) { + if(!(Error & ERROR_CABLE_DEFECTIVE)) { + printf("Cable Proximity Pilot defective!\r\n"); + } + Error |= ERROR_CABLE_DEFECTIVE; + NextState = STATE_A; + count = 0; + ChargeCurrent = 0; + } else { + printf("Cable limit: %uA Max: %uA \r\n", MaxCapacity, MaxCurrent); + Error &= ~ERROR_CABLE_DEFECTIVE; + + if (MaxCurrent > MaxCapacity) ChargeCurrent = MaxCapacity * 10; // Do not modify Max Cable Capacity or MaxCurrent (fix 2.05) + else ChargeCurrent = MaxCurrent * 10; // Instead use new variable ChargeCurrent + + if (LoadBl > 1) // Load Balancing : Slave + { + // Send command to Master, followed by Max Charge Current + ModbusWriteSingleRequest(LoadBl, 0x02, ChargeCurrent); + printf("02 sent to Master, requested %.1f A\r\n", (double)ChargeCurrent/10); + State = STATE_COMM_B; + Timer = 0; // Clear the Timer + } else { // Load Balancing: Master or Disabled + BalancedMax[0] = MaxCapacity * 10; + Balanced[0] = ChargeCurrent; // Set pilot duty cycle to ChargeCurrent (v2.15) + BalancedState[0] = 1; // Mark as active + State = STATE_B; // switch to State B + ActivationMode = 30; // Activation mode is triggered if state C is not entered in 30 seconds. + BacklightTimer = BACKLIGHT; // Backlight ON + BACKLIGHT_ON; + printf("STATE A->B\r\n"); + } } } } else { @@ -2497,7 +2560,17 @@ void main(void) { Timer = 0; // Clear the Timer } else { // Load Balancing: Master or Disabled BalancedMax[0] = ChargeCurrent; - if (IsCurrentAvailable() == 0) { + if (Lock == 3) { + SOLENOID_REALY_ON; + // wait for Lock to engage + // do not enable Contactor befor Lock + Timer = 0; + while(PORTCbits.RC1 == 1 && Timer <= SOLENOID_REALY_DELAY_MAX); + } + if (Lock == 3 && PORTCbits.RC1 == 1) { // still unlocked... + Error |= ERROR_LOCK; + printf("Error Lock Failed\r\n"); + } else if (IsCurrentAvailable() == 0) { BalancedState[0] = 2; // Mark as Charging Balanced[0] = 0; // For correct baseload calculation set current to zero CalcBalancedCurrent(1); // Calculate charge current for all connected EVSE's @@ -2793,7 +2866,7 @@ void main(void) { #endif ModbusDecode(U1packet, ISRFLAG); if (Modbus.Type == MODBUS_RESPONSE) { - //printf("\nModbus Response Address %i / Function %02x / Register %02x",Modbus.Address,Modbus.Function,Modbus.Register); + //printf("\n\rModbus Response Address %i / Function %02x / Register %02x",Modbus.Address,Modbus.Function,Modbus.Register); switch (Modbus.Function) { case 0x04: // (Read input register) if (MainsMeter && Modbus.Address == MainsMeterAddress && Modbus.Register == EMConfig[MainsMeter].IRegister) { @@ -2822,7 +2895,7 @@ void main(void) { break; } } else if (Modbus.Type == MODBUS_REQUEST) { - //printf("\nModbus Request Address %i / Function %02x / Register %02x",Modbus.Address,Modbus.Function,Modbus.Register); + //printf("\n\rModbus Request Address %i / Function %02x / Register %02x",Modbus.Address,Modbus.Function,Modbus.Register); // No timeout reset here, as it is a request, no response!!!! switch (Modbus.Function) { case 0x04: // (Read input register) @@ -2864,7 +2937,7 @@ void main(void) { // 0x01: Balance currents if (Modbus.Register == 0x01 && LoadBl > 1) { // Message for Slave(s) BalancedReceived = (Modbus.Data[(LoadBl - 1) * 2] <<8) | Modbus.Data[(LoadBl - 1) * 2 + 1]; - // printf("\n Address %02x Register %02x BalancedReceived %i ", Modbus.Address, Modbus.Register, BalancedReceived); + // printf("\n\r Address %02x Register %02x BalancedReceived %i ", Modbus.Address, Modbus.Register, BalancedReceived); DataReceived = 2; } @@ -2931,21 +3004,33 @@ void main(void) { if (Modbus.Value == 0) // If chargecurrent is zero, No current is available. { Error |= NOCURRENT; - DEBUG_PRINT(("83 ACK ")); // No current available + DEBUG_PRINT(("83 ACK ")); // No current available } else { - SetCurrent(Modbus.Value); - CONTACTOR_ON; // Contactor ON - DiodeCheck = 0; - State = STATE_C; // switch to STATE_C - ActivationMode = 255; // Disable ActivationMode - LCDTimer = 0; - Timer = 0; // reset msTimer and ChargeTimer - if (!LCDNav) // Don't update the LCD if we are navigating the menu - { - GLCD(); // immediately update LCD + if (Lock == 3) { + SOLENOID_REALY_ON; + // wait for Lock to engage + // do not enable Contactor befor Lock + Timer = 0; + while(PORTCbits.RC1 == 1 && Timer <= SOLENOID_REALY_DELAY_MAX); + } + if (Lock == 3 && PORTCbits.RC1 == 1) { // still unlocked... + Error |= ERROR_LOCK; + printf("Error Lock Failed\r\n"); + } else { + SetCurrent(Modbus.Value); + CONTACTOR_ON; // Contactor ON + DiodeCheck = 0; + State = STATE_C; // switch to STATE_C + ActivationMode = 255; // Disable ActivationMode + LCDTimer = 0; + Timer = 0; // reset msTimer and ChargeTimer + if (!LCDNav) // Don't update the LCD if we are navigating the menu + { + GLCD(); // immediately update LCD + } + DEBUG_PRINT(("83 ACK State C charge current: %.1f A\r\n", (double)Modbus.Value/10)); + printf("STATE B->C\r\n"); } - DEBUG_PRINT(("83 ACK State C charge current: %.1f A\r\n", (double)Modbus.Value/10)); - printf("STATE B->C\r\n"); } break; case 0x84: // Charging Stopped, State B diff --git a/version2/SmartEVSE2.X/EVSE.h b/version2/SmartEVSE2.X/EVSE.h index 7d84680..6a01f3e 100644 --- a/version2/SmartEVSE2.X/EVSE.h +++ b/version2/SmartEVSE2.X/EVSE.h @@ -113,11 +113,17 @@ #define NO_SUN 32 #define Test_IO 64 #define BL_FLASH 128 +#define ERROR_CABLE_DEFECTIVE 256 // PP (Proximity Pilot) defective +#define ERROR_LOCK 512 // Lock failed #define SOLENOID_LOCK {LATAbits.LATA4 = 1;LATAbits.LATA5 = 0;} #define SOLENOID_UNLOCK {LATAbits.LATA4 = 0;LATAbits.LATA5 = 1;} #define SOLENOID_OFF {LATAbits.LATA4 = 1;LATAbits.LATA5 = 1;} +#define SOLENOID_REALY_DELAY_MAX 1000 // max wait time for Lock in Realy mode +#define SOLENOID_REALY_ON {LATAbits.LATA4 = 0;LATAbits.LATA5 = 1;} +#define SOLENOID_REALY_OFF {LATAbits.LATA4 = 0;LATAbits.LATA5 = 0;} + #define CONTACTOR_OFF LATBbits.LATB4 = 0; // Contactor OFF #define CONTACTOR_ON LATBbits.LATB4 = 1; // Contactor ON @@ -159,6 +165,9 @@ #define STATUS_CURRENT 70 #define STATUS_ACCESS 71 #define STATUS_MODE 72 +#define STATUS_TEMP 73 + +#define EX_LOCK_MENU 100 #define EM_SENSORBOX 1 // Mains meter types #define EM_PHOENIX_CONTACT 2 @@ -210,10 +219,12 @@ extern unsigned char PVMeterAddress; extern unsigned char EVSEMeter; // Type of EVSE electric meter (0: Disabled / 10: Phoenix Contact / 20: Finder) extern unsigned char EVSEMeterAddress; +extern unsigned char EX_disable_menu; + extern signed double Irms[3]; // Momentary current per Phase (Amps *10) (23 = 2.3A) extern unsigned char State; -extern unsigned char Error; +extern unsigned int Error; extern unsigned char NextState; extern unsigned int MaxCapacity; // Cable limit (Amps)(limited by the wire in the charge cable, set automatically, or manually if Config=Fixed Cable) @@ -258,7 +269,7 @@ const far struct { {"LOADBL", "LOAD BAL", "Set Load Balancing mode for 2-4 SmartEVSEs", 0, 4, LOADBL}, {"MIN", "MIN", "Set MIN Charge Current the EV will accept", 6, 16, MIN_CURRENT}, {"CIRCUIT","CIRCUIT", "Set EVSE Circuit max Current", 10, 80, MAX_CIRCUIT}, - {"LOCK", "LOCK", "Cable locking actuator type", 0, 2, LOCK}, + {"LOCK", "LOCK", "Cable locking actuator type", 0, 3, LOCK}, {"START", "START", "Surplus energy start Current", 1, 16, START_CURRENT}, {"STOP", "STOP", "Stop solar charging at 6A after this time", 0, 60, STOP_TIME}, {"IMPORT", "IMPORT", "Allow grid power when solar charging", 0, 6, IMPORT_CURRENT}, diff --git a/version2/SmartEVSE2.X/GLCD.c b/version2/SmartEVSE2.X/GLCD.c index 07029f3..724395f 100644 --- a/version2/SmartEVSE2.X/GLCD.c +++ b/version2/SmartEVSE2.X/GLCD.c @@ -428,6 +428,7 @@ void GLCD(void) { unsigned int seconds, minutes; static unsigned char energy_mains = 20; // X position static unsigned char energy_ev = 74; // X position + unsigned char buf[8] = {0}; if (LCDNav) { if (LCDTimer++ == 120) { @@ -477,6 +478,16 @@ void GLCD(void) { GLCD_print2(2, (const far char *) "BOOTLOADER"); GLCD_print2(4, (const far char *) "UPDATE ERR"); return; + } else if (Error & ERROR_LOCK) { + GLCD_print2(2, (const far char *) "ERROR"); + GLCD_print2(4, (const far char *) "LOCK"); + GLCD_print2(6, (const far char *) "FAILED"); + return; + } else if (Error & ERROR_CABLE_DEFECTIVE) { + GLCD_print2(2, (const far char *) "ERROR"); + GLCD_print2(4, (const far char *) "CABLE"); + GLCD_print2(6, (const far char *) "DEFECTIVE"); + return; } } @@ -516,8 +527,11 @@ void GLCD(void) { { // STATE A and STATE B glcd_clrln(0, 0x00); glcd_clrln(1, 0x04); // horizontal line - - if (Access_bit) { + if (Error) { + GLCD_print2(2, (const far char *) "ERROR"); + sprintf(buf, "%d", Error); + GLCD_print2(4, (const far char *) &buf[0]); + } else if (Access_bit) { GLCD_print2(2, (const far char *) "READY TO"); GLCD_print2(4, (const far char *) "CHARGE "); if (ChargeDelay) { // show chargedelay @@ -713,11 +727,13 @@ void GLCDMenu(unsigned char Buttons) { Error &= ~RCD_TRIPPED; // Clear RCD error bit, by pressing any button } - if ((LCDNav == 0) && (Buttons == 0x5) && (ButtonRelease == 0)) // Button 2 pressed ? + if ((LCDNav == 0) && (Buttons == 0x5) && (ButtonRelease == 0) // Button 2 pressed ? + && EX_disable_menu != 1) // menu not disabled { LCDNav = MENU_ENTER; // about to enter menu ButtonTimer = Timer; - } else if (LCDNav == MENU_ENTER && ((ButtonTimer + 2000) < Timer)) // + } else if (LCDNav == MENU_ENTER && ((ButtonTimer + 2000) < Timer) // + && EX_disable_menu != 1) // menu not disabled { LCDNav = MENU_CONFIG; // Main Menu entered ButtonRelease = 1;