rusefi-1/firmware/hw_layer/sensors/cj125_logic.cpp

140 lines
4.2 KiB
C++

/*
* @file CJ125_logic.cpp
*
* @date Feb 1, 2019
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#include "cj125_logic.h"
#include "engine.h"
#include "error_handling.h"
EXTERN_ENGINE;
CJ125::CJ125() : wboHeaterControl("wbo"),
heaterPid(&heaterPidConfig) {
}
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) const {
return state != CJ125_ERROR && state != CJ125_INIT && state != CJ125_IDLE;
}
void CJ125::StartHeaterControl(pwm_gen_callback *stateChangeCallback DECLARE_ENGINE_PARAMETER_SUFFIX) {
// todo: use custom pin state method, turn pin off while not running
startSimplePwmExt(&wboHeaterControl, "wboHeaterPin",
&engine->executor,
CONFIG(wboHeaterPin),
&wboHeaterPin, CJ125_HEATER_PWM_FREQ, 0.0f, stateChangeCallback);
SetIdleHeater(PASS_ENGINE_PARAMETER_SIGNATURE);
}
/**
* @return true in case of positive SPI identification
* false in case of unexpected SPI response
*/
bool CJ125::cjIdentify(void) {
efiAssert(OBD_PCM_Processor_Fault, spi!= NULL, "No SPI pointer", false);
// read Ident register
int ident = spi->ReadRegister(IDENT_REG_RD) & CJ125_IDENT_MASK;
// set initial registers
spi->WriteRegister(INIT_REG1_WR, CJ125_INIT1_NORMAL_17);
spi->WriteRegister(INIT_REG2_WR, CJ125_INIT2_DIAG);
// check if regs are ok
int init1 = spi->ReadRegister(INIT_REG1_RD);
int init2 = spi->ReadRegister(INIT_REG2_RD);
diag = spi->ReadRegister(DIAG_REG_RD);
scheduleMsg(logger, "cj125: Check ident=0x%x diag=0x%x init1=0x%x init2=0x%x", ident, diag, init1, init2);
if (ident != CJ125_IDENT) {
scheduleMsg(logger, "cj125: Error! Wrong ident! Cannot communicate with CJ125!");
errorCode = CJ125_ERROR_WRONG_IDENT;
state = CJ125_ERROR;
return false;
}
if (init1 != CJ125_INIT1_NORMAL_17 || init2 != CJ125_INIT2_DIAG) {
scheduleMsg(logger, "cj125: Error! Cannot set init registers! Cannot communicate with CJ125!");
errorCode = CJ125_ERROR_WRONG_INIT;
state = CJ125_ERROR;
return false;
}
#if 0
if (diag != CJ125_DIAG_NORM) {
scheduleMsg(logger, "cj125: Diag error!");
}
#endif
return true;
}
void CJ125::cjSetMode(cj125_mode_e m) {
if (mode == m)
return;
switch (m) {
case CJ125_MODE_NORMAL_8:
spi->WriteRegister(INIT_REG1_WR, CJ125_INIT1_NORMAL_8);
amplCoeff = 1.0f / 8.0f;
break;
case CJ125_MODE_NORMAL_17:
spi->WriteRegister(INIT_REG1_WR, CJ125_INIT1_NORMAL_17);
amplCoeff = 1.0f / 17.0f;
break;
case CJ125_MODE_CALIBRATION:
spi->WriteRegister(INIT_REG1_WR, CJ125_INIT1_CALBRT);
amplCoeff = 0.0f;
break;
default:
;
}
mode = m;
}
bool CJ125::isValidState() const {
// check if controller is functioning
if (!isWorkingState())
return false;
// check if amplification is turned on
if (amplCoeff == 0.0f)
return false;
// check if UA calibration value is valid
if (vUaCal < CJ125_UACAL_MIN || vUaCal > CJ125_UACAL_MAX)
return false;
return true;
}
void CJ125::cjInitPid(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
if (engineConfiguration->cj125isLsu49) {
heaterPidConfig.pFactor = CJ125_PID_LSU49_P;
heaterPidConfig.iFactor = CJ125_PID_LSU49_I;
} else {
heaterPidConfig.pFactor = CJ125_PID_LSU42_P;
heaterPidConfig.iFactor = CJ125_PID_LSU42_I;
}
heaterPidConfig.dFactor = 0.0f;
heaterPidConfig.minValue = 0;
heaterPidConfig.maxValue = 1;
heaterPidConfig.offset = 0;
// todo: period?
heaterPidConfig.periodMs = 1.0f;
heaterPid.reset();
}