diff --git a/firmware/console/status_loop.cpp b/firmware/console/status_loop.cpp index 6d15c36203..b28dd58149 100644 --- a/firmware/console/status_loop.cpp +++ b/firmware/console/status_loop.cpp @@ -814,11 +814,11 @@ void updateTunerStudioState(TunerStudioOutputChannels *tsOutputChannels DECLARE_ tsOutputChannels->debugIntField2 = instance.invalidHip9011ResponsesCount; break; #endif /* EFI_HIP_9011 */ -#if EFI_CJ125 || defined(__DOXYGEN__) +#if (EFI_CJ125 && HAL_USE_SPI) || defined(__DOXYGEN__) case DBG_CJ125: cjPostState(tsOutputChannels); break; -#endif /* EFI_CJ125 */ +#endif /* EFI_CJ125 && HAL_USE_SPI */ #if EFI_MAP_AVERAGING case DBG_MAP: postMapState(tsOutputChannels); diff --git a/firmware/controllers/sensors/ego.cpp b/firmware/controllers/sensors/ego.cpp index 296991e454..64d46d1c4f 100644 --- a/firmware/controllers/sensors/ego.cpp +++ b/firmware/controllers/sensors/ego.cpp @@ -92,20 +92,20 @@ void initEgoAveraging(DECLARE_ENGINE_PARAMETER_SIGNATURE) { #endif bool hasAfrSensor(DECLARE_ENGINE_PARAMETER_SIGNATURE) { -#if EFI_CJ125 || defined(__DOXYGEN__) +#if (EFI_CJ125 && HAL_USE_SPI) || defined(__DOXYGEN__) if (CONFIGB(isCJ125Enabled)) { return cjHasAfrSensor(PASS_ENGINE_PARAMETER_SIGNATURE); } -#endif /* EFI_CJ125 */ +#endif /* EFI_CJ125 && HAL_USE_SPI */ return engineConfiguration->afr.hwChannel != EFI_ADC_NONE; } float getAfr(DECLARE_ENGINE_PARAMETER_SIGNATURE) { -#if EFI_CJ125 || defined(__DOXYGEN__) +#if (EFI_CJ125 && HAL_USE_SPI) || defined(__DOXYGEN__) if (CONFIGB(isCJ125Enabled)) { return cjGetAfr(PASS_ENGINE_PARAMETER_SIGNATURE); } -#endif /* EFI_CJ125 */ +#endif /* EFI_CJ125 && HAL_USE_SPI */ afr_sensor_s * sensor = &CONFIG(afr); float volts = getVoltageDivided("ego", sensor->hwChannel); diff --git a/firmware/hw_layer/sensors/CJ125.cpp b/firmware/hw_layer/sensors/CJ125.cpp index 5d078e69a5..fa2ae5aba1 100644 --- a/firmware/hw_layer/sensors/CJ125.cpp +++ b/firmware/hw_layer/sensors/CJ125.cpp @@ -12,7 +12,7 @@ #include "rpm_calculator.h" #include "pid.h" -#if EFI_CJ125 || defined(__DOXYGEN__) +#if (EFI_CJ125 && HAL_USE_SPI) || defined(__DOXYGEN__) // looks like 3v range should be enough, divider not needed #define EFI_CJ125_DIRECTLY_CONNECTED_UR TRUE @@ -24,19 +24,11 @@ EXTERN_ENGINE; -#if ! EFI_UNIT_TEST || defined(__DOXYGEN__) #include "hardware.h" #include "backup_ram.h" #include "pin_repository.h" extern TunerStudioOutputChannels tsOutputChannels; -#endif -struct CJ125_state { - efitick_t startHeatingNt; - efitick_t prevNt; -}; - -static SimplePwm wboHeaterControl("wbo"); static OutputPin wboHeaterPin; static OutputPin cj125Cs; static Logging *logger; @@ -45,30 +37,18 @@ static unsigned char rx_buff[1]; static pid_s heaterPidConfig; static Pid heaterPid(&heaterPidConfig); -static float heaterDuty = 0.0f; // todo: only define this variable in EIF_PROD static CJ125 globalInstance; - -#if ! EFI_UNIT_TEST || defined(__DOXYGEN__) - static THD_WORKING_AREA(cjThreadStack, UTILITY_THREAD_STACK_SIZE); static SPIDriver *driver; -#if EFI_PROD_CODE static SPIConfig cj125spicfg = { NULL, /* HW dependent part.*/ NULL, 0, SPI_CR1_MSTR | SPI_CR1_CPHA | SPI_CR1_BR_0 | SPI_CR1_BR_1 | SPI_CR1_BR_2 }; -#endif /* EFI_PROD_CODE */ -#endif /* EFI_UNIT_TEST */ - -CJ125::CJ125() { - state = CJ125_IDLE; - errorCode = CJ125_ERROR_NONE; -} // Chip diagnostics register contents static volatile int diag = 0; @@ -134,7 +114,6 @@ static int cjReadRegister(unsigned char regAddr) { static void cjWriteRegister(unsigned char regAddr, unsigned char regValue) { -#if ! EFI_UNIT_TEST || defined(__DOXYGEN__) #ifdef CJ125_DEBUG_SPI scheduleMsg(logger, "cjWriteRegister: addr=%d value=%d", regAddr, regValue); #endif /* CJ125_DEBUG_SPI */ @@ -143,7 +122,6 @@ static void cjWriteRegister(unsigned char regAddr, unsigned char regValue) { tx_buff[1] = regValue; spiSend(driver, 2, tx_buff); spiUnselect(driver); -#endif /* EFI_UNIT_TEST */ } static float getUr() { @@ -373,51 +351,26 @@ static void cjStart(DECLARE_ENGINE_PARAMETER_SIGNATURE) { #endif } -static void cjSetHeater(float value DECLARE_ENGINE_PARAMETER_SUFFIX) { - // limit duty cycle for sensor safety - float maxDuty = (engine->sensors.vBatt > CJ125_HEATER_LIMITING_VOLTAGE) ? CJ125_HEATER_LIMITING_RATE : 1.0f; - heaterDuty = (value < CJ125_HEATER_MIN_DUTY) ? 0.0f : minF(maxF(value, 0.0f), maxDuty); -#ifdef CJ125_DEBUG - scheduleMsg(logger, "cjSetHeater: %.2f", heaterDuty); -#endif - // a little trick to disable PWM if needed. - // todo: this should be moved to wboHeaterControl.setPwmDutyCycle() - wboHeaterControl.setFrequency(heaterDuty == 0.0f ? NAN : CJ125_HEATER_PWM_FREQ); - wboHeaterControl.setSimplePwmDutyCycle(heaterDuty); -} - -static void cjSetIdleHeater(DECLARE_ENGINE_PARAMETER_SIGNATURE) { - // small preheat for faster start & moisture anti-shock therapy for the sensor - cjSetHeater(CJ125_HEATER_IDLE_RATE PASS_ENGINE_PARAMETER_SUFFIX); -} - static void cjStartHeaterControl(DECLARE_ENGINE_PARAMETER_SIGNATURE) { - if (CONFIGB(wboHeaterPin) != GPIO_UNASSIGNED) { - scheduleMsg(logger, "cj125: Starting heater control"); - // todo: use custom pin state method, turn pin off while not running - startSimplePwmExt(&wboHeaterControl, "wboHeaterPin", - &engine->executor, - CONFIGB(wboHeaterPin), - &wboHeaterPin, CJ125_HEATER_PWM_FREQ, 0.0f, applyPinState); - cjSetIdleHeater(PASS_ENGINE_PARAMETER_SIGNATURE); - } + scheduleMsg(logger, "cj125: Starting heater control"); + // todo: use custom pin state method, turn pin off while not running + startSimplePwmExt(&globalInstance.wboHeaterControl, "wboHeaterPin", + &engine->executor, + CONFIGB(wboHeaterPin), + &wboHeaterPin, CJ125_HEATER_PWM_FREQ, 0.0f, applyPinState); } -void CJ125::cjSetError(cj125_error_e errCode DECLARE_ENGINE_PARAMETER_SUFFIX) { +void CJ125::setError(cj125_error_e errCode DECLARE_ENGINE_PARAMETER_SUFFIX) { errorCode = errCode; state = CJ125_ERROR; cjPrintErrorCode(errorCode); // This is for safety: scheduleMsg(logger, "cj125: Controller Shutdown!"); - cjSetHeater(0 PASS_ENGINE_PARAMETER_SUFFIX); + SetHeater(0 PASS_ENGINE_PARAMETER_SUFFIX); // Software-reset of CJ125 cjWriteRegister(INIT_REG2_WR, CJ125_INIT2_RESET); } -bool CJ125::cjIsWorkingState(void) { - return state != CJ125_ERROR && state != CJ125_INIT && state != CJ125_IDLE; -} - static void cjInitPid(DECLARE_ENGINE_PARAMETER_SIGNATURE) { if(engineConfiguration->cj125isLsu49) { heaterPidConfig.pFactor = CJ125_PID_LSU49_P; @@ -475,7 +428,7 @@ static void cjStartSpi(DECLARE_ENGINE_PARAMETER_SIGNATURE) { /** * @return true if currently in IDLE or ERROR state */ -static bool cj125periodic(CJ125 *instance, CJ125_state *anotherState DECLARE_ENGINE_PARAMETER_SUFFIX) { +static bool cj125periodic(CJ125 *instance DECLARE_ENGINE_PARAMETER_SUFFIX) { { efitick_t nowNt = getTimeNowNt(); bool isStopped = engine->rpmCalculator.isStopped(PASS_ENGINE_PARAMETER_SIGNATURE); @@ -497,12 +450,12 @@ static bool cj125periodic(CJ125 *instance, CJ125_state *anotherState DECLARE_ENG diag = cjReadRegister(DIAG_REG_RD); // check heater state - if (vUr > CJ125_UR_PREHEAT_THR || heaterDuty < CJ125_PREHEAT_MIN_DUTY) { + if (vUr > CJ125_UR_PREHEAT_THR || instance->heaterDuty < CJ125_PREHEAT_MIN_DUTY) { // Check if RPM>0 and it's time to start pre-heating if (instance->state == CJ125_INIT && !isStopped) { // start preheating instance->state = CJ125_PREHEAT; - anotherState->startHeatingNt = anotherState->prevNt = getTimeNowNt(); + instance->startHeatingNt = instance->prevNt = getTimeNowNt(); cjSetMode(CJ125_MODE_NORMAL_17); } } else if (vUr > CJ125_UR_GOOD_THR) { @@ -514,9 +467,9 @@ static bool cj125periodic(CJ125 *instance, CJ125_state *anotherState DECLARE_ENG instance->state = CJ125_READY; } - if (isStopped && instance->cjIsWorkingState()) { + if (isStopped && instance->isWorkingState()) { instance->state = CJ125_INIT; - cjSetIdleHeater(PASS_ENGINE_PARAMETER_SIGNATURE); + instance->SetIdleHeater(PASS_ENGINE_PARAMETER_SIGNATURE); } #if 0 @@ -527,38 +480,38 @@ static bool cj125periodic(CJ125 *instance, CJ125_state *anotherState DECLARE_ENG switch (instance->state) { case CJ125_PREHEAT: // use constant-speed startup heat-up - if (nowNt - anotherState->prevNt >= CJ125_HEATER_PREHEAT_PERIOD) { - float periodSecs = (float)(nowNt - anotherState->prevNt) / US2NT(US_PER_SECOND_LL); + if (nowNt - instance->prevNt >= CJ125_HEATER_PREHEAT_PERIOD) { + float periodSecs = (float)(nowNt - instance->prevNt) / US2NT(US_PER_SECOND_LL); // maintain speed at ~0.4V/sec - float preheatDuty = heaterDuty + periodSecs * CJ125_HEATER_PREHEAT_RATE; - cjSetHeater(preheatDuty PASS_ENGINE_PARAMETER_SUFFIX); + float preheatDuty = instance->heaterDuty + periodSecs * CJ125_HEATER_PREHEAT_RATE; + instance->SetHeater(preheatDuty PASS_ENGINE_PARAMETER_SUFFIX); // If we are heating too long, and there's still no result, then something is wrong... - if (nowNt - anotherState->startHeatingNt > US2NT(US_PER_SECOND_LL) * CJ125_PREHEAT_TIMEOUT) { - instance->cjSetError(CJ125_ERROR_HEATER_MALFUNCTION PASS_ENGINE_PARAMETER_SUFFIX); + if (nowNt - instance->startHeatingNt > US2NT(US_PER_SECOND_LL) * CJ125_PREHEAT_TIMEOUT) { + instance->setError(CJ125_ERROR_HEATER_MALFUNCTION PASS_ENGINE_PARAMETER_SUFFIX); } cjPrintData(); - anotherState->prevNt = nowNt; + instance->prevNt = nowNt; } break; case CJ125_HEAT_UP: case CJ125_READY: // use PID for normal heater control - if (nowNt - anotherState->prevNt >= CJ125_HEATER_CONTROL_PERIOD) { + if (nowNt - instance->prevNt >= CJ125_HEATER_CONTROL_PERIOD) { /* PID doesn't care about the target or the input, it knows only the * error value as the difference of (target - input). and if we swap them we'll just get a sign inversion. If target=vUrCal, and input=vUr, then error=vUrCal-vUr, i.e. if vUrSetHeater(duty PASS_ENGINE_PARAMETER_SUFFIX); cjPrintData(); - anotherState->prevNt = nowNt; + instance->prevNt = nowNt; } break; case CJ125_OVERHEAT: - if (nowNt - anotherState->prevNt >= CJ125_HEATER_OVERHEAT_PERIOD) { - instance->cjSetError(CJ125_ERROR_OVERHEAT PASS_ENGINE_PARAMETER_SUFFIX); - anotherState->prevNt = nowNt; + if (nowNt - instance->prevNt >= CJ125_HEATER_OVERHEAT_PERIOD) { + instance->setError(CJ125_ERROR_OVERHEAT PASS_ENGINE_PARAMETER_SUFFIX); + instance->prevNt = nowNt; } default: ; @@ -567,25 +520,20 @@ static bool cj125periodic(CJ125 *instance, CJ125_state *anotherState DECLARE_ENG return false; } -#if ! EFI_UNIT_TEST || defined(__DOXYGEN__) - -static CJ125_state globalStateInstance; - static msg_t cjThread(void) { chRegSetThreadName("cj125"); chThdSleepMilliseconds(500); - globalStateInstance.startHeatingNt = 0; - globalStateInstance.prevNt = getTimeNowNt(); + globalInstance.startHeatingNt = 0; + globalInstance.prevNt = getTimeNowNt(); while (1) { - bool needIdleSleep = cj125periodic(&globalInstance, &globalStateInstance PASS_ENGINE_PARAMETER_SUFFIX); + bool needIdleSleep = cj125periodic(&globalInstance PASS_ENGINE_PARAMETER_SUFFIX); chThdSleepMilliseconds(needIdleSleep ? CJ125_IDLE_TICK_DELAY : CJ125_TICK_DELAY); } return -1; } -#endif /* EFI_UNIT_TEST */ #if ! EFI_UNIT_TEST || defined(__DOXYGEN__) static bool cjCheckConfig(void) { @@ -599,7 +547,7 @@ static bool cjCheckConfig(void) { static void cjStartCalibration(void) { if (!cjCheckConfig()) return; - if (globalInstance.cjIsWorkingState()) { + if (globalInstance.isWorkingState()) { // todo: change this later for the normal thread operation (auto pre-heating) scheduleMsg(logger, "cj125: Cannot start calibration. Please restart the board and make sure that your sensor is not heating"); return; @@ -649,7 +597,7 @@ bool cjHasAfrSensor(DECLARE_ENGINE_PARAMETER_SIGNATURE) { return false; #if ! EFI_UNIT_TEST // check if controller is functioning - if (!globalInstance.cjIsWorkingState()) + if (!globalInstance.isWorkingState()) return false; #endif /* EFI_UNIT_TEST */ // check if amplification is turned on @@ -664,7 +612,7 @@ bool cjHasAfrSensor(DECLARE_ENGINE_PARAMETER_SIGNATURE) { #if EFI_TUNER_STUDIO || defined(__DOXYGEN__) // used by DBG_CJ125 void cjPostState(TunerStudioOutputChannels *tsOutputChannels) { - tsOutputChannels->debugFloatField1 = heaterDuty; + tsOutputChannels->debugFloatField1 = globalInstance.heaterDuty; tsOutputChannels->debugFloatField2 = heaterPid.getIntegration(); tsOutputChannels->debugFloatField3 = heaterPid.getPrevError(); tsOutputChannels->debugFloatField4 = vUa; @@ -695,24 +643,19 @@ void initCJ125(Logging *sharedLogger DECLARE_ENGINE_PARAMETER_SUFFIX) { cjInitPid(PASS_ENGINE_PARAMETER_SIGNATURE); cjStartSpi(PASS_ENGINE_PARAMETER_SIGNATURE); cjStartHeaterControl(PASS_ENGINE_PARAMETER_SIGNATURE); + globalInstance.SetIdleHeater(PASS_ENGINE_PARAMETER_SIGNATURE); cjStart(PASS_ENGINE_PARAMETER_SIGNATURE); - -#if 1 - globalInstance.state = CJ125_INIT; -#endif #ifdef CJ125_DEBUG - addConsoleActionF("cj125_heater", cjSetHeater); +// addConsoleActionF("cj125_heater", cjConsoleSetHeater); addConsoleActionI("cj125_set_init1", cjSetInit1); addConsoleActionI("cj125_set_init2", cjSetInit2); #endif /* CJ125_DEBUG */ -#if ! EFI_UNIT_TEST || defined(__DOXYGEN__) addConsoleAction("cj125", cjStartTest); addConsoleAction("cj125_calibrate", cjStartCalibration); chThdCreateStatic(cjThreadStack, sizeof(cjThreadStack), LOWPRIO, (tfunc_t)(void*) cjThread, NULL); -#endif /* EFI_UNIT_TEST */ } -#endif /* EFI_CJ125 */ +#endif /* EFI_CJ125 && HAL_USE_SPI */ diff --git a/firmware/hw_layer/sensors/CJ125.h b/firmware/hw_layer/sensors/CJ125.h index aacc61e8e2..defa9bd2bb 100644 --- a/firmware/hw_layer/sensors/CJ125.h +++ b/firmware/hw_layer/sensors/CJ125.h @@ -8,7 +8,7 @@ #ifndef HW_LAYER_SENSORS_CJ125_H_ #define HW_LAYER_SENSORS_CJ125_H_ -#include "engine_configuration.h" +#include "CJ125_logic.h" // CJ125 SPI Registers #define IDENT_REG_RD 0x48 // Read Identity Register @@ -98,18 +98,6 @@ #define CJ125_TICK_DELAY 20 // 20 ms #define CJ125_IDLE_TICK_DELAY 1000 // 1 sec -// Heater params for Idle(cold), Preheating and Control stages -// See http://www.waltech.com/wideband-files/boschsensordatasheet.htm -#define CJ125_HEATER_IDLE_RATE 0.15f // for a very cold sensor (presumably), we allow 15% duty max. -#define CJ125_HEATER_PREHEAT_PERIOD 300 // 300 ms -#define CJ125_HEATER_CONTROL_PERIOD 180 // 180 ms -#define CJ125_HEATER_OVERHEAT_PERIOD 500 // 500 ms -#define CJ125_HEATER_PWM_FREQ 100 // 100 Hz -#define CJ125_HEATER_PREHEAT_RATE (0.4f/14.0f) // Assuming that dutycycle=1.0 equals to 14V, and max.allowed heater rate is 0.4V/sec - -#define CJ125_HEATER_LIMITING_VOLTAGE 12.0f // Do not allow more than 90% heating for high battery voltage (>12V). -#define CJ125_HEATER_LIMITING_RATE 0.92f // This prevents sensor overheating. - #define CJ125_CALIBRATE_NUM_SAMPLES 10 #define CJ125_UR_PREHEAT_THR 2.0f // Ur > 2.0 Volts is too cold to control with PID @@ -119,7 +107,6 @@ #define CJ125_UACAL_MIN 1.0f // Calibration UA values range #define CJ125_UACAL_MAX 2.0f -#define CJ125_HEATER_MIN_DUTY 0.1f #define CJ125_PREHEAT_MIN_DUTY 0.9f //#define CJ125_PREHEAT_TIMEOUT 90 // 90 secs @@ -141,54 +128,6 @@ // Returned if there's no valid measurement #define CJ125_AFR_NAN 0.0f -typedef enum { - CJ125_IDLE, - CJ125_INIT, - CJ125_CALIBRATION, - CJ125_PREHEAT, - CJ125_HEAT_UP, - CJ125_READY, - CJ125_OVERHEAT, - CJ125_ERROR, - -} cj125_state_e; - -typedef enum { - CJ125_ERROR_NONE = 0, - CJ125_ERROR_HEATER_MALFUNCTION = 1, - CJ125_ERROR_OVERHEAT = 2, - CJ125_ERROR_WRONG_IDENT = 3, - CJ125_ERROR_WRONG_INIT = 4, - -} cj125_error_e; - -typedef enum { - CJ125_MODE_NONE, - CJ125_MODE_NORMAL_8, - CJ125_MODE_NORMAL_17, - CJ125_MODE_CALIBRATION, -} cj125_mode_e; - -typedef enum { - CJ125_LSU_42 = 0, - CJ125_LSU_49 = 1, - -} cj125_sensor_type_e; - -class CJ125 { -public: - CJ125(); - - // Used by CJ125 driver state machine - volatile cj125_state_e state; - // Last Error code - volatile cj125_error_e errorCode; - - - void cjSetError(cj125_error_e errCode DECLARE_ENGINE_PARAMETER_SUFFIX); - bool cjIsWorkingState(void); - -}; #if EFI_TUNER_STUDIO || defined(__DOXYGEN__) void cjPostState(TunerStudioOutputChannels *tsOutputChannels); diff --git a/firmware/hw_layer/sensors/CJ125_logic.cpp b/firmware/hw_layer/sensors/CJ125_logic.cpp new file mode 100644 index 0000000000..39b85f7415 --- /dev/null +++ b/firmware/hw_layer/sensors/CJ125_logic.cpp @@ -0,0 +1,38 @@ +/* + * @file CJ125_logic.cpp + * + * @date Feb 1, 2019 + * @author Andrey Belomutskiy, (c) 2012-2019 + */ + +#include "CJ125_logic.h" +#include "engine.h" + +EXTERN_ENGINE; + +CJ125::CJ125() : wboHeaterControl("wbo") { +} + +void CJ125::SetHeater(float value DECLARE_ENGINE_PARAMETER_SUFFIX) { + // limit duty cycle for sensor safety + // todo: would be much nicer to have continuous function (vBatt) + float maxDuty = (engine->sensors.vBatt > CJ125_HEATER_LIMITING_VOLTAGE) ? CJ125_HEATER_LIMITING_RATE : 1.0f; + heaterDuty = (value < CJ125_HEATER_MIN_DUTY) ? 0.0f : minF(maxF(value, 0.0f), maxDuty); +#ifdef CJ125_DEBUG + scheduleMsg(logger, "cjSetHeater: %.2f", heaterDuty); +#endif + // a little trick to disable PWM if needed. + // todo: this should be moved to wboHeaterControl.setPwmDutyCycle() + // todo: is this really needed?! + wboHeaterControl.setFrequency(heaterDuty == 0.0f ? NAN : CJ125_HEATER_PWM_FREQ); + wboHeaterControl.setSimplePwmDutyCycle(heaterDuty); +} + +void CJ125::SetIdleHeater(DECLARE_ENGINE_PARAMETER_SIGNATURE) { + // small preheat for faster start & moisture anti-shock therapy for the sensor + SetHeater(CJ125_HEATER_IDLE_RATE PASS_ENGINE_PARAMETER_SUFFIX); +} + +bool CJ125::isWorkingState(void) { + return state != CJ125_ERROR && state != CJ125_INIT && state != CJ125_IDLE; +} diff --git a/firmware/hw_layer/sensors/CJ125_logic.h b/firmware/hw_layer/sensors/CJ125_logic.h new file mode 100644 index 0000000000..adc79110d1 --- /dev/null +++ b/firmware/hw_layer/sensors/CJ125_logic.h @@ -0,0 +1,83 @@ +/* + * @file CJ125_logic.h + * + * @date Feb 1, 2019 + * @author Andrey Belomutskiy, (c) 2012-2019 + */ + +#ifndef HW_LAYER_SENSORS_CJ125_LOGIC_H_ +#define HW_LAYER_SENSORS_CJ125_LOGIC_H_ + +#include "engine_configuration.h" +#include "pwm_generator_logic.h" + +typedef enum { + CJ125_LSU_42 = 0, + CJ125_LSU_49 = 1, + +} cj125_sensor_type_e; + +typedef enum { + CJ125_INIT, + CJ125_IDLE, + CJ125_CALIBRATION, + CJ125_PREHEAT, + CJ125_HEAT_UP, + CJ125_READY, + CJ125_OVERHEAT, + CJ125_ERROR, + +} cj125_state_e; + +typedef enum { + CJ125_ERROR_NONE = 0, + CJ125_ERROR_HEATER_MALFUNCTION = 1, + CJ125_ERROR_OVERHEAT = 2, + CJ125_ERROR_WRONG_IDENT = 3, + CJ125_ERROR_WRONG_INIT = 4, +} cj125_error_e; + +typedef enum { + CJ125_MODE_NONE, + CJ125_MODE_NORMAL_8, + CJ125_MODE_NORMAL_17, + CJ125_MODE_CALIBRATION, +} cj125_mode_e; + +class CJ125 { +public: + CJ125(); + + SimplePwm wboHeaterControl; + + efitick_t startHeatingNt; + efitick_t prevNt; + float heaterDuty = 0.0f; + + + // Used by CJ125 driver state machine + volatile cj125_state_e state = CJ125_INIT; + // Last Error code + volatile cj125_error_e errorCode = CJ125_ERROR_NONE; + + void setError(cj125_error_e errCode DECLARE_ENGINE_PARAMETER_SUFFIX); + bool isWorkingState(void); + void SetHeater(float value DECLARE_ENGINE_PARAMETER_SUFFIX); + void SetIdleHeater(DECLARE_ENGINE_PARAMETER_SIGNATURE); +}; + +// Heater params for Idle(cold), Preheating and Control stages +// See http://www.waltech.com/wideband-files/boschsensordatasheet.htm +#define CJ125_HEATER_IDLE_RATE 0.15f // for a very cold sensor (presumably), we allow 15% duty max. +#define CJ125_HEATER_PREHEAT_PERIOD 300 // 300 ms +#define CJ125_HEATER_CONTROL_PERIOD 180 // 180 ms +#define CJ125_HEATER_OVERHEAT_PERIOD 500 // 500 ms +#define CJ125_HEATER_PREHEAT_RATE (0.4f/14.0f) // Assuming that dutycycle=1.0 equals to 14V, and max.allowed heater rate is 0.4V/sec + +#define CJ125_HEATER_MIN_DUTY 0.1f +#define CJ125_HEATER_PWM_FREQ 100 // 100 Hz + +#define CJ125_HEATER_LIMITING_VOLTAGE 12.0f // Do not allow more than 90% heating for high battery voltage (>12V). +#define CJ125_HEATER_LIMITING_RATE 0.92f // This prevents sensor overheating. + +#endif /* HW_LAYER_SENSORS_CJ125_LOGIC_H_ */ diff --git a/firmware/hw_layer/sensors/sensors.mk b/firmware/hw_layer/sensors/sensors.mk index f58a5fa75f..7f6ce8f8b2 100644 --- a/firmware/hw_layer/sensors/sensors.mk +++ b/firmware/hw_layer/sensors/sensors.mk @@ -1,2 +1,3 @@ HW_SENSORS_SRC = $(PROJECT_DIR)/hw_layer/sensors/CJ125.cpp \ + $(PROJECT_DIR)/hw_layer/CJ125_logic.cpp \ $(PROJECT_DIR)/hw_layer/sensors/yaw_rate_sensor.cpp \ No newline at end of file diff --git a/firmware/svnversion.h b/firmware/svnversion.h index 376eb717a6..89675198d7 100644 --- a/firmware/svnversion.h +++ b/firmware/svnversion.h @@ -1,5 +1,5 @@ // This file was generated by Version2Header -// Fri Jan 11 08:48:17 EST 2019 +// Fri Feb 01 18:26:44 EST 2019 #ifndef VCS_VERSION -#define VCS_VERSION "16346" +#define VCS_VERSION "16581" #endif diff --git a/unit_tests/Makefile b/unit_tests/Makefile index 5996d2b83e..837f4c5a91 100644 --- a/unit_tests/Makefile +++ b/unit_tests/Makefile @@ -89,6 +89,7 @@ include $(PROJECT_DIR)/controllers/system/system.mk include $(PROJECT_DIR)/controllers/sensors/sensors.mk include $(PROJECT_DIR)/controllers/trigger/trigger.mk include $(PROJECT_DIR)/hw_layer/hw_layer.mk +include $(PROJECT_DIR)/hw_layer/sensors/sensors.mk include test.mk # Define linker script file here @@ -120,7 +121,7 @@ CPPSRC = $(UTILSRC_CPP) \ $(SYSTEMSRC_CPP) \ $(PROJECT_DIR)/controllers/error_handling.cpp \ $(HW_LAYER_EMS_CPP) \ - $(PROJECT_DIR)/hw_layer/sensors/CJ125.cpp \ + $(HW_SENSORS_SRC) \ $(TRIGGER_SRC_CPP) \ main.cpp diff --git a/unit_tests/tests/test_cj125.cpp b/unit_tests/tests/test_cj125.cpp index 0c11835d4f..50501e59a7 100644 --- a/unit_tests/tests/test_cj125.cpp +++ b/unit_tests/tests/test_cj125.cpp @@ -6,9 +6,18 @@ */ #include "gtest/gtest.h" +#include "CJ125_logic.h" +#include "engine_test_helper.h" + +TEST(testCJ125, testInitialState) { + CJ125 cj; + + ASSERT_EQ(cj.state, CJ125_INIT); + ASSERT_FALSE(cj.isWorkingState()); + + WITH_ENGINE_TEST_HELPER(FORD_ASPIRE_1996); + ASSERT_EQ(engine->sensors.vBatt, 0); -TEST(testCJ125, todo) { - EXPECT_EQ(1, 2 - 1); }