diff --git a/Makefile b/Makefile index c78cd63..4d54e09 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ OBJSL = main.o hwinit.o stm32scheduler.o params.o terminal.o terminal_prj.o \ param_save.o errormessage.o stm32_can.o canhardware.o canmap.o cansdo.o \ picontroller.o terminalcommands.o \ ipv6.o tcp.o \ - connMgr.o modemFinder.o pevStateMachine.o temperatures.o acOBC.o \ + connMgr.o modemFinder.o pevStateMachine.o temperatures.o acOBC.o wakecontrol.o \ hardwareInterface.o hardwareVariants.o pushbutton.o udpChecksum.o \ homeplug.o myHelpers.o qca7000.o \ appHandEXIDatatypesDecoder.o ByteStream.o EncoderChannel.o \ diff --git a/ccs/acOBC.cpp b/ccs/acOBC.cpp index 99e617d..3dde4b2 100644 --- a/ccs/acOBC.cpp +++ b/ccs/acOBC.cpp @@ -56,6 +56,12 @@ static void evaluateProximityPilot(void) float U_refAdc, U_pull, U_meas, Rv, R; float iLimit; uint8_t blPlugPresent; + + if (wakecontrol_isPpMeasurementInvalid()) { + /* in case there are conditions which corrupt the PP resistance measurement, we discard the measurement, + and just live with the last valid value. Strategy: Better an old, valid value than a corrupted value. */ + return; + } /* Step 1: Provide the raw AD value (0 to 4095) for analysis purposes. */ Param::SetFloat(Param::AdcProximityPilot, temp); diff --git a/ccs/ccs32_globals.h b/ccs/ccs32_globals.h index 2867692..8ff6433 100644 --- a/ccs/ccs32_globals.h +++ b/ccs/ccs32_globals.h @@ -35,6 +35,7 @@ #include "hwinit.h" #include "errormessage.h" #include "my_string.h" +#include "wakecontrol.h" /* temporary stubs */ #define publishStatus(x, y) diff --git a/ccs/hardwareInterface.h b/ccs/hardwareInterface.h index 68a90c5..9527dd4 100644 --- a/ccs/hardwareInterface.h +++ b/ccs/hardwareInterface.h @@ -36,6 +36,7 @@ extern int16_t hardwareInterface_getChargingTargetVoltage(void); extern int16_t hardwareInterface_getChargingTargetCurrent(void); extern void hardwareInterface_WakeupOtherPeripherals(); extern void hardwareInterface_LogTheCpPpPhysicalData(); +extern uint8_t hardwareInterface_isPpMeasurementInvalid(void); extern void hardwareInterface_cyclic(void); extern void hardwareInterface_init(void); diff --git a/ccs/wakecontrol.cpp b/ccs/wakecontrol.cpp new file mode 100644 index 0000000..31d05a5 --- /dev/null +++ b/ccs/wakecontrol.cpp @@ -0,0 +1,75 @@ +/* wakecontrol: controlling the keep_power_on and similar things */ + +#include "ccs32_globals.h" + +uint8_t wakecontrol_timer; +uint8_t allowSleep; + +#define WAKECONTROL_TIMER_MAX 20 /* 20*100ms = 2s cycle time */ +#define WAKECONTROL_TIMER_NEARLY_EXPIRED 5 /* 5*100ms = 500ms keep_power_on activation time */ +#define WAKECONTROL_TIMER_END_OF_CYCLE__MEASUREMENT_ALLOWED 3 /* after turning the keep_power_on, 200ms time for + in-rush and adc sampling until measurement is considered as valid. */ + +uint8_t wakecontrol_isPpMeasurementInvalid(void) { + /* The PP measurement is not valid, if the voltage on the PP is pulled up by the wakeup path. + Discussion was here: https://openinverter.org/forum/viewtopic.php?p=75629#p75629 */ + if (allowSleep==0) return 0; /* as long as we are not ready to sleep, the PP is valid. */ + if (wakecontrol_timer<=WAKECONTROL_TIMER_END_OF_CYCLE__MEASUREMENT_ALLOWED) return 0; /* valid because cyclic pulsing and sufficient propagation delay */ + return 1; /* no PP measurement possible, because corrupted by KEEP_POWER_ON. */ +} + +void wakecontrol_mainfunction(void) /* runs in 100ms cycle */ +{ + static uint32_t lastValidCp = 0; + if (Param::GetInt(Param::ControlPilotDuty) > 3) + lastValidCp = rtc_get_counter_val(); + + //If no frequency on CP we allow shut down after 10s + if ((rtc_get_counter_val() - lastValidCp) > 1000) + { + bool ppValid = Param::GetInt(Param::ResistanceProxPilot) < 2000; + + bool CanActive = Param::GetInt(Param::CanAwake); + + //WAKEUP_ONVALIDPP implies that we use PP for wakeup. So as long as PP is valid + //Do not clear the supply pin as that will skew the PP measurement and we can't turn off anyway + if(!CanActive) + { + if ((Param::GetInt(Param::WakeupPinFunc) & WAKEUP_ONVALIDPP) == 0 || !ppValid) + { + allowSleep = 1; + } + } + } + + if (!allowSleep) { + DigIo::keep_power_on.Set(); /* Keep the power on */ + wakecontrol_timer=WAKECONTROL_TIMER_MAX; + } else { + /* we could go to sleep. But there may be hardware situations, when we keep running, even if we turned-off the keep_power_on. + In this case, we need to set the keep_power_on to active, to allow correct PP resistance measurement. */ + if (wakecontrol_timer==WAKECONTROL_TIMER_MAX) { + /* at the beginning of the "sleep allowed" phase, we try to shutdown */ + DigIo::keep_power_on.Clear(); + wakecontrol_timer--; + } else if (wakecontrol_timer==WAKECONTROL_TIMER_NEARLY_EXPIRED) { + /* we tried to shut down, but something keeps us running. So turn the keep_power_on active for a moment. */ + DigIo::keep_power_on.Set(); + wakecontrol_timer--; + } else if (wakecontrol_timer==0) { + /* timer is expired. Start a new cycle. */ + wakecontrol_timer = WAKECONTROL_TIMER_MAX; + } else { + /* just in the middle of the counting */ + wakecontrol_timer--; + } + + } +} + +void wakecontrol_init(void) { + DigIo::keep_power_on.Set(); /* Make sure board stays awake. */ + allowSleep=0; +} + + diff --git a/ccs/wakecontrol.h b/ccs/wakecontrol.h new file mode 100644 index 0000000..895a3b5 --- /dev/null +++ b/ccs/wakecontrol.h @@ -0,0 +1,18 @@ +/* Interface header for wakecontrol.c */ + +/* Global Defines */ + +/* Global Variables */ + +/* Global Functions */ +#ifdef __cplusplus +extern "C" { +#endif + +extern uint8_t wakecontrol_isPpMeasurementInvalid(void); +extern void wakecontrol_mainfunction(void); +extern void wakecontrol_init(void); + +#ifdef __cplusplus +} +#endif diff --git a/src/main.cpp b/src/main.cpp index 9e9f1cb..0b77386 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -55,7 +55,7 @@ #include "pushbutton.h" #include "hardwareVariants.h" #include "acOBC.h" - +#include "wakecontrol.h" #define PRINT_JSON 0 @@ -72,8 +72,6 @@ static CanSdo* canSdo; static void Ms100Task(void) { - static uint32_t lastValidCp = 0; - DigIo::led_alive.Toggle(); //The boot loader enables the watchdog, we have to reset it //at least every 2s or otherwise the controller is hard reset. @@ -141,29 +139,7 @@ static void Ms100Task(void) { Param::SetInt(Param::CanAwake,0); } - - - if (Param::GetInt(Param::ControlPilotDuty) > 3) - lastValidCp = rtc_get_counter_val(); - - //If no frequency on CP shut down after 10s - if ((rtc_get_counter_val() - lastValidCp) > 1000) - { - bool ppValid = Param::GetInt(Param::ResistanceProxPilot) < 2000; - - bool CanActive = Param::GetInt(Param::CanAwake); - - //WAKEUP_ONVALIDPP implies that we use PP for wakeup. So as long as PP is valid - //Do not clear the supply pin as that will skew the PP measurement and we can't turn off anyway - if(!CanActive) - { - if ((Param::GetInt(Param::WakeupPinFunc) & WAKEUP_ONVALIDPP) == 0 || !ppValid) - { - DigIo::keep_power_on.Clear(); - } - } - } - + wakecontrol_mainfunction(); canMap->SendAll(); } @@ -261,7 +237,7 @@ extern "C" int main(void) write_bootloader_pininit(); //Instructs boot loader to initialize certain pins gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON, AFIO_MAPR_TIM3_REMAP_FULL_REMAP | AFIO_MAPR_TIM2_REMAP_FULL_REMAP); - DigIo::keep_power_on.Set(); //Make sure board stays awake + wakecontrol_init(); //Make sure board stays awake hardwareInterface_setStateB(); hw_evaluateHardwareVariants();