(cherry picked from commit fd09ad7b4f)
This commit is contained in:
Matthew Kennedy 2023-02-21 01:21:52 -05:00 committed by Andrey
parent d6521492b7
commit 7396d466c4
56 changed files with 7 additions and 1359 deletions

View File

@ -1,5 +1,3 @@
#define ts_show_hip9011 false
#define ts_show_cj125 false
#define ts_show_gps false
#define ts_show_software_knock true

View File

@ -1,5 +1,3 @@
#define ts_show_hip9011 false
#define ts_show_cj125 false
#define ts_show_gps false
#define ts_show_software_knock true

View File

@ -1,5 +1,3 @@
#define ts_show_hip9011 false
#define ts_show_cj125 false
#define ts_show_gps false
#define ts_show_software_knock true

View File

@ -1,5 +1,3 @@
#define ts_show_hip9011 false
#define ts_show_cj125 false
#define ts_show_gps false
#define ts_show_software_knock true

View File

@ -1,5 +1,3 @@
#define ts_show_hip9011 false
#define ts_show_cj125 false
#define ts_show_gps false
#define ts_show_software_knock true

View File

@ -94,8 +94,6 @@ void setBoardDefaultConfiguration() {
engineConfiguration->afr.hwChannel = EFI_ADC_14;
engineConfiguration->accelerometerSpiDevice = SPI_DEVICE_1;
engineConfiguration->hip9011SpiDevice = SPI_DEVICE_2;
engineConfiguration->cj125SpiDevice = SPI_DEVICE_2;
// engineConfiguration->gps_rx_pin = Gpio::B7;
// engineConfiguration->gps_tx_pin = Gpio::B6;

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/2chan"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/4chan"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/8chan"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/harley81"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/gm-e38"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/gm-e67"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,12 +1,9 @@
#define MAIN_HELP_URL "https://rusefi.com/s/hellen154hyuindai"
#define ts_show_hip9011 false
#define ts_show_cj125 false
#define ts_show_can_terminator true
#define ts_show_egt false
#define ts_show_gps false
#define ts_show_etb_pins false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/hellenNB1"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/hellen121nissan"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/hellen121vag"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/hellen128merc"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/hellen154hyuindai"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/hellenNA6"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/hellen72"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/hellen81"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/hellen88bmw"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/hellenNA96"
#define ts_show_hip9011 false
#define ts_show_cj125 false

View File

@ -22,7 +22,7 @@ DDEFS += -DEFI_USE_UART_DMA=FALSE
# maybe a way to disable SPI2 privately
#DDEFS += -DSTM32_SPI_USE_SPI2=FALSE
DDEFS += -DEFI_CJ125=FALSE -DBOARD_L9779_COUNT=0
DDEFS += -DBOARD_L9779_COUNT=0
DDEFS += -DFIRMWARE_ID=\"microRusEFI\"
DDEFS += -DEFI_SOFTWARE_KNOCK=TRUE -DSTM32_ADC_USE_ADC3=TRUE

View File

@ -8,7 +8,6 @@ export EXTRA_PARAMS="-DDUMMY \
-DEFI_LOGIC_ANALYZER=FALSE \
-DEFI_TOOTH_LOGGER=FALSE \
-DEFI_LUA=FALSE \
-DEFI_CJ125=FALSE \
-DEFI_MALFUNCTION_INDICATOR=FALSE \
-DEFI_AUX_PID=FALSE \
-DEFI_MAX_31855=FALSE \

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://rusefi.com/s/microrusefi"
#define ts_show_hip9011 false
#define ts_show_cj125 false
! https://rusefi.com/forum/viewtopic.php?p=43270#p43270

View File

@ -197,16 +197,6 @@ void setBoardDefaultConfiguration() {
engineConfiguration->hipOutputChannel = EFI_ADC_10; // PC0
engineConfiguration->isHip9011Enabled = true;
engineConfiguration->cj125SpiDevice = SPI_DEVICE_3;
engineConfiguration->cj125ua = is469 ? EFI_ADC_9 : EFI_ADC_8;
engineConfiguration->cj125ur = EFI_ADC_12;
engineConfiguration->cj125CsPin = Gpio::A15;
engineConfiguration->cj125CsPinMode = OM_OPENDRAIN;
engineConfiguration->wboHeaterPin = Gpio::C13;
engineConfiguration->o2heaterPin = Gpio::C13;
//engineConfiguration->isCJ125Enabled = true;
engineConfiguration->isCJ125Enabled = false;
engineConfiguration->canTxPin = Gpio::B9;
engineConfiguration->canRxPin = Gpio::B8;

View File

@ -1,4 +1,3 @@
! https://github.com/andreika-git/prometheus/raw/master/hardware/prometheus-wiring-diagram.pdf
#define ts_show_hip9011 false
#define ts_show_etb false

View File

@ -14,7 +14,7 @@ DDEFS += $(VAR_DEF_ENGINE_TYPE)
DDEFS += -DEFI_MAIN_RELAY_CONTROL=TRUE
# Turn off stuff proteus doesn't have/need
DDEFS += -DEFI_CJ125=FALSE -DEFI_MAX_31855=FALSE -DBOARD_L9779_COUNT=0 -DBOARD_TLE8888_COUNT=0
DDEFS += -DEFI_MAX_31855=FALSE -DBOARD_L9779_COUNT=0 -DBOARD_TLE8888_COUNT=0
# Any Proteus-based adapter boards with discrete-VR decoder are controlled via a 5v ignition output
DDEFS += -DVR_SUPPLY_VOLTAGE=5

View File

@ -1,7 +1,5 @@
#define MAIN_HELP_URL "https://github.com/rusefi/rusefi/wiki/Proteus-Manual"
#define ts_show_hip9011 false
#define ts_show_cj125 false
#define ts_show_full_pinout false
#define ts_show_egt false
#define ts_show_gps false

View File

@ -209,8 +209,6 @@ void setBoardDefaultConfiguration() {
engineConfiguration->maxAcRpm = 3000;
engineConfiguration->acIdleRpmBump = 200;
engineConfiguration->isCJ125Enabled = false;
/* CAN */
engineConfiguration->canTxPin = Gpio::D1;
engineConfiguration->canRxPin = Gpio::D0;

View File

@ -1,7 +1,6 @@
!TODO: understand this.
#define ts_show_hip9011 true
#define ts_show_cj125 false
#define ts_show_egt false
#define ts_show_gps false
#define ts_show_etb_pins true

View File

@ -30,8 +30,6 @@ void setDodgeNeon1995EngineConfiguration() {
// engineConfiguration->spi2mosiPin = Gpio::B15;
// engineConfiguration->spi2misoPin = Gpio::B14;
// engineConfiguration->spi2sckPin = Gpio::B13;
engineConfiguration->cj125CsPin = Gpio::B0; // rev 0.4
engineConfiguration->isCJ125Enabled = true;
engineConfiguration->is_enabled_spi_2 = true;

View File

@ -202,10 +202,6 @@
#define EFI_HIP_9011 FALSE
#endif
#ifndef EFI_CJ125
#define EFI_CJ125 TRUE
#endif
#if !defined(EFI_MEMS)
#define EFI_MEMS FALSE
#endif

View File

@ -9,9 +9,6 @@
#undef EFI_MC33816
#define EFI_MC33816 FALSE
#undef EFI_CJ125
#define EFI_CJ125 FALSE
#undef BOARD_TLE6240_COUNT
#undef BOARD_MC33972_COUNT
#undef BOARD_TLE8888_COUNT

View File

@ -70,10 +70,6 @@
#include "flash_main.h"
#endif
#if EFI_CJ125
#include "cj125.h"
#endif /* EFI_CJ125 */
#if EFI_MAP_AVERAGING
#include "map_averaging.h"
#endif
@ -791,11 +787,6 @@ DcHardware *getdcHardware();
tsOutputChannels->debugIntField2 = instance.invalidResponsesCount;
break;
#endif /* EFI_HIP_9011 */
#if EFI_CJ125 && HAL_USE_SPI
case DBG_CJ125:
cjPostState(tsOutputChannels);
break;
#endif /* EFI_CJ125 && HAL_USE_SPI */
#if EFI_MAP_AVERAGING
case DBG_MAP:
postMapState(tsOutputChannels);

View File

@ -624,8 +624,6 @@ static void setDefaultEngineConfiguration() {
engineConfiguration->alternatorPwmFrequency = 300;
engineConfiguration->cj125isUaDivided = true;
engineConfiguration->isAlternatorControlEnabled = false;
engineConfiguration->driveWheelRevPerKm = 1000;

View File

@ -278,7 +278,7 @@ typedef enum __attribute__ ((__packed__)) {
DBG_INSTANT_RPM = 22,
UNUSED23 = 23,
DBG_24 = 24,
DBG_CJ125 = 25,
DBG_25 = 25,
DBG_26 = 26,
DBG_MAP = 27,
DBG_METRICS = 28,
@ -482,7 +482,7 @@ typedef enum {
TS_WIDEBAND = 21,
TS_BENCH_CATEGORY = 22,
TS_UNUSED_23 = 23,
TS_UNUSED_CJ125_CALIB = 24,
TS_UNUSED_24 = 24,
TS_SOLENOID_CATEGORY = 25,
TS_UNUSED_26 = 26,
TS_UNUSED_27 = 27,

View File

@ -34,7 +34,6 @@
#include "periodic_thread_controller.h"
#include "electronic_throttle.h"
#include "electronic_throttle_impl.h"
#include "cj125.h"
#include "malfunction_central.h"
#include "trigger_emulator_algo.h"
#include "microsecond_timer.h"
@ -493,12 +492,6 @@ void executeTSCommand(uint16_t subsystem, uint16_t index) {
handleBenchCategory(index);
break;
case TS_UNUSED_CJ125_CALIB:
#if EFI_CJ125 && HAL_USE_SPI
cjStartCalibration();
#endif /* EFI_CJ125 */
break;
case TS_SET_ENGINE_TYPE:
fatalErrorForPresetApply();
setEngineType(index);

View File

@ -92,10 +92,6 @@
#include "pwm_tester.h"
#endif /* EFI_PROD_CODE */
#if EFI_CJ125
#include "cj125.h"
#endif /* EFI_CJ125 */
#if !EFI_UNIT_TEST
/**
@ -666,13 +662,6 @@ void initEngineController() {
}
#endif /* EFI_LOGIC_ANALYZER */
#if EFI_CJ125
/**
* this uses SimplePwm which depends on scheduler, has to be initialized after scheduler
*/
initCJ125();
#endif /* EFI_CJ125 */
if (hasFirmwareError()) {
return;
}

View File

@ -3,8 +3,6 @@
*
* EGO Exhaust Gas Oxygen, also known as AFR Air/Fuel Ratio :)
*
* todo: rename this class? refactor since there is also CJ125?
*
* rusEfi has three options for wideband:
* 1) integration with external widebands using liner analog signal wire
* 2) 8-point interpolation curve to emulate a wide-band with a narrow-band sensor.
@ -15,10 +13,6 @@
#include "cyclic_buffer.h"
#if EFI_CJ125
#include "cj125.h"
#endif /* EFI_CJ125 */
#ifdef EFI_NARROW_EGO_AVERAGING
// Needed by narrow EGOs (see updateEgoAverage()).
// getAfr() is called at ~50Hz, so we store at most (1<<3)*32 EGO values for ~5 secs.
@ -96,11 +90,6 @@ bool hasAfrSensor() {
return true;
}
#if EFI_CJ125 && HAL_USE_SPI
if (engineConfiguration->isCJ125Enabled) {
return cjHasAfrSensor();
}
#endif /* EFI_CJ125 && HAL_USE_SPI */
return isAdcChannelValid(engineConfiguration->afr.hwChannel);
}
@ -112,11 +101,6 @@ float getAfr(SensorType type) {
return InnovateLC2AFR;
#endif
#if EFI_CJ125 && HAL_USE_SPI
if (engineConfiguration->isCJ125Enabled) {
return cjGetAfr();
}
#endif /* EFI_CJ125 && HAL_USE_SPI */
afr_sensor_s * sensor = &engineConfiguration->afr;
if (!isAdcChannelValid(type == SensorType::Lambda1 ? engineConfiguration->afr.hwChannel : engineConfiguration->afr.hwChannel2)) {

View File

@ -429,14 +429,6 @@ static void setMainRelayPin(const char *pinName) {
setIndividualPin(pinName, &engineConfiguration->mainRelayPin, "main relay");
}
static void setCj125CsPin(const char *pinName) {
setIndividualPin(pinName, &engineConfiguration->starterRelayDisablePin, "starter disable relay");
}
static void setCj125HeaterPin(const char *pinName) {
setIndividualPin(pinName, &engineConfiguration->wboHeaterPin, "cj125 heater");
}
static void setTriggerSyncPin(const char *pinName) {
setIndividualPin(pinName, &engineConfiguration->debugTriggerSync, "trigger sync");
}
@ -634,10 +626,6 @@ static void enableOrDisable(const char *param, bool isEnabled) {
engine->etbAutoTune = isEnabled;
} else if (strEqualCaseInsensitive(param, "verboseKLine")) {
engineConfiguration->verboseKLine = isEnabled;
} else if (strEqualCaseInsensitive(param, "cj125")) {
engineConfiguration->isCJ125Enabled = isEnabled;
} else if (strEqualCaseInsensitive(param, "cj125verbose")) {
engineConfiguration->isCJ125Verbose = isEnabled;
} else if (strEqualCaseInsensitive(param, "step1limimter")) {
engineConfiguration->enabledStep1Limiter = isEnabled;
#if EFI_PROD_CODE
@ -754,13 +742,7 @@ static void getValue(const char *paramStr) {
}
}
if (strEqualCaseInsensitive(paramStr, "isCJ125Enabled")) {
efiPrintf("isCJ125Enabled=%d", engineConfiguration->isCJ125Enabled);
#if EFI_PROD_CODE
} else if (strEqualCaseInsensitive(paramStr, "bor")) {
showBor();
#endif // EFI_PROD_CODE
} else if (strEqualCaseInsensitive(paramStr, "tps_min")) {
if (strEqualCaseInsensitive(paramStr, "tps_min")) {
efiPrintf("tps_min=%d", engineConfiguration->tpsMin);
} else if (strEqualCaseInsensitive(paramStr, "tps_max")) {
efiPrintf("tps_max=%d", engineConfiguration->tpsMax);
@ -1028,8 +1010,6 @@ void initSettings(void) {
addConsoleActionS(CMD_IDLE_PIN, setIdlePin);
addConsoleActionS("set_main_relay_pin", setMainRelayPin);
addConsoleActionS("set_starter_relay_pin", setStarterRelayPin);
addConsoleActionS("set_cj125_cs_pin", setCj125CsPin);
addConsoleActionS("set_cj125_heater_pin", setCj125HeaterPin);
addConsoleActionS("set_trigger_sync_pin", setTriggerSyncPin);
addConsoleActionS("bench_clearpin", benchClearPin);

View File

@ -22,7 +22,6 @@
// Less critical harware
#define PRIO_SERVO (NORMALPRIO + 5)
#define PRIO_STEPPER (NORMALPRIO + 5)
#define PRIO_CJ125 (NORMALPRIO + 5)
// Logging buffer flush is *slightly* above PRIO_CONSOLE so that we don't starve logging buffers during initialization and console commands
#define PRIO_TEXT_LOG (NORMALPRIO + 4)

View File

@ -365,11 +365,6 @@ void applyNewHardwareSettings() {
void setBor(int borValue) {
efiPrintf("setting BOR to %d", borValue);
BOR_Set((BOR_Level_t)borValue);
showBor();
}
void showBor(void) {
efiPrintf("BOR=%d", (int)BOR_Get());
}
#endif /* EFI_PROD_CODE */

View File

@ -58,7 +58,6 @@ void initHardware();
#endif /* EFI_PROD_CODE */
void showBor(void);
void setBor(int borValue);
class ButtonDebounce;

View File

@ -1,665 +0,0 @@
/*
* @file CJ125.cpp
*
* https://github.com/rusefi/rusefi/tree/master/hardware/CJ125_board
*
* https://github.com/rusefi/hw_modular/tree/master/cj125_Module
*
*
* See vag_18_Turbo for test configuration
* set engine_type 102
*
* @date: Jun 24, 2016
* @author Andrey Belomutskiy, (c) 2012-2020
*
*/
#include "pch.h"
#include "cj125.h"
#if EFI_CJ125
#if HAL_USE_SPI
#include "mpu_util.h"
#endif /* HAL_USE_SPI */
//#define CJ125_DEBUG
//#define CJ125_DEBUG_SPI
#include "hardware.h"
#include "backup_ram.h"
static CJ125 globalInstance;
#if ! EFI_UNIT_TEST
static THD_WORKING_AREA(cj125ThreadStack, UTILITY_THREAD_STACK_SIZE);
#endif /* EFI_UNIT_TEST */
#if HAL_USE_SPI
static SPIDriver *driver;
static SPIConfig cj125spicfg = {
.circular = false,
.end_cb = NULL,
.ssport = NULL,
.sspad = 0,
.cr1 =
SPI_CR1_MSTR | SPI_CR1_CPHA |
SPI_CR1_8BIT_MODE,
.cr2 =
SPI_CR2_8BIT_MODE
};
#endif /* HAL_USE_SPI */
static uint32_t lastSlowAdcCounter = 0;
// LSU conversion tables. See cj125_sensor_type_e
// For LSU4.2, See http://www.bosch-motorsport.com/media/catalog_resources/Lambda_Sensor_LSU_42_Datasheet_51_en_2779111435pdf.pdf
// See LSU4.9, See http://www.bosch-motorsport.com/media/catalog_resources/Lambda_Sensor_LSU_49_Datasheet_51_en_2779147659pdf.pdf
// Pump current, mA
static constexpr float pumpCurrentLsu42[] = {
// LSU 4.2
-1.85f, -1.08f, -0.76f, -0.47f, 0.0f, 0.34f, 0.68f, 0.95f, 1.4f
};
static constexpr float pumpCurrentLsu49[] = {
// LSU 4.9
-2.0f, -1.602f, -1.243f, -0.927f, -0.8f, -0.652f, -0.405f, -0.183f, -0.106f, -0.04f, 0, 0.015f, 0.097f, 0.193f, 0.250f, 0.329f, 0.671f, 0.938f, 1.150f, 1.385f, 1.700f, 2.000f, 2.150f, 2.250f
};
// Corresponding lambda values for the above pump current
static constexpr float lambdaLsu42[] = {
// LSU 4.2
0.7f, 0.8f, 0.85f, 0.9f, 1.009f, 1.18f, 1.43f, 1.7f, 2.42f
};
static constexpr float lambdaLsu49[] = {
// LSU 4.9
0.65f, 0.7f, 0.75f, 0.8f, 0.822f, 0.85f, 0.9f, 0.95f, 0.97f, 0.99f, 1.003f, 1.01f, 1.05f, 1.1f, 1.132f, 1.179f, 1.429f, 1.701f, 1.990f, 2.434f, 3.413f, 5.391f, 7.506f, 10.119f
};
static uint8_t cjReadRegister(uint8_t regAddr) {
#if ! EFI_UNIT_TEST
spiSelect(driver);
spiPolledExchange(driver, regAddr);
uint8_t result = spiPolledExchange(driver, 0xFF);
spiUnselect(driver);
#ifdef CJ125_DEBUG_SPI
efiPrintf("cjReadRegister: addr=%d answer=%d", regAddr, result);
#endif /* CJ125_DEBUG_SPI */
return result;
#else /* EFI_UNIT_TEST */
return 0;
#endif /* EFI_UNIT_TEST */
}
static void cjWriteRegister(uint8_t regAddr, uint8_t regValue) {
#ifdef CJ125_DEBUG_SPI
efiPrintf("cjWriteRegister: addr=%d value=%d", regAddr, regValue);
#endif /* CJ125_DEBUG_SPI */
// todo: extract 'sendSync' method?
#if HAL_USE_SPI
spiSelect(driver);
spiPolledExchange(driver, regAddr);
spiPolledExchange(driver, regValue);
spiUnselect(driver);
#endif /* HAL_USE_SPI */
}
static float getUr() {
#if ! EFI_UNIT_TEST
if (isAdcChannelValid(engineConfiguration->cj125ur)) {
#if EFI_PROD_CODE
if (!engineConfiguration->cj125isUrDivided) {
// in case of directly connected Ur signal from CJ125 to the ADC pin of MCU
return getVoltage("cj125ur", engineConfiguration->cj125ur);
} else {
// if a standard voltage division scheme with OpAmp is used
return getVoltageDivided("cj125ur", engineConfiguration->cj125ur);
}
#endif /* EFI_PROD_CODE */
}
return 0.0f;
#else /* EFI_UNIT_TEST */
return 0;
#endif /* EFI_UNIT_TEST */
}
static float getUa() {
#if ! EFI_UNIT_TEST
if (isAdcChannelValid(engineConfiguration->cj125ua)) {
#if EFI_PROD_CODE
if (engineConfiguration->cj125isUaDivided) {
return getVoltageDivided("cj125ua", engineConfiguration->cj125ua);
} else {
return getVoltage("cj125ua", engineConfiguration->cj125ua);
}
#endif /* EFI_PROD_CODE */
}
return 0.0f;
#else /* EFI_UNIT_TEST */
return 0;
#endif /* EFI_UNIT_TEST */
}
static float getVoltageFrom16bit(uint32_t stored) {
return ((float)stored) / CJ125_VOLTAGE_TO_16BIT_FACTOR;
}
static uint32_t get16bitFromVoltage(float v) {
return (uint32_t)(v * CJ125_VOLTAGE_TO_16BIT_FACTOR);
}
static const char * getCjState(cj125_state_e stateCode) {
switch (stateCode) {
case CJ125_INIT:
return "INIT";
case CJ125_IDLE:
return "IDLE";
case CJ125_CALIBRATION:
return "CALIBRATION";
case CJ125_PREHEAT:
return "PREHEAT";
case CJ125_HEAT_UP:
return "HEAT UP";
case CJ125_READY:
return "READY";
case CJ125_OVERHEAT:
return "OVERHEAT";
case CJ125_ERROR:
return "ERROR";
default:
return "UNKNOWN";
}
}
static void cjPrintErrorCode(cj125_error_e errCode) {
const char *errString = nullptr;
switch (errCode) {
case CJ125_ERROR_HEATER_MALFUNCTION:
errString = "Heater malfunction (Too long preheat)";
break;
case CJ125_ERROR_OVERHEAT:
errString = "Sensor overheating";
break;
case CJ125_NO_ERROR:
errString = "N/A";
break;
case CJ125_ERROR_WRONG_IDENT:
errString = "W_IDENT";
break;
case CJ125_ERROR_WRONG_INIT:
errString = "W_INIT";
break;
case CJ125_ERROR_DISABLED:
errString = "DISABLED";
break;
}
efiPrintf("cj125 ERROR: %s.", errString);
}
static void cjPrintState() {
efiPrintf("cj125: state=%s diag=0x%x (current Ua=%.3f Ur=%.3f) (calibration Ua=%.3f Ur=%.3f)",
getCjState(globalInstance.state), globalInstance.diag,
globalInstance.vUa, globalInstance.vUr,
globalInstance.vUaCal, globalInstance.vUrCal);
globalInstance.printDiag();
if (globalInstance.state == CJ125_ERROR) {
cjPrintErrorCode(globalInstance.errorCode);
}
efiPrintf("cj125 P=%f I=%f D=%f",
globalInstance.heaterPidConfig.pFactor,
globalInstance.heaterPidConfig.iFactor,
globalInstance.heaterPidConfig.dFactor);
}
static void cjSetP(float value) {
globalInstance.heaterPidConfig.pFactor = value;
}
static void cjSetI(float value) {
globalInstance.heaterPidConfig.iFactor = value;
}
static void cjInfo() {
cjPrintState();
#if HAL_USE_SPI
printSpiConfig("cj125", engineConfiguration->cj125SpiDevice);
#endif /* HAL_USE_SPI */
}
static void cjPrintData() {
#if ! EFI_UNIT_TEST
if (engineConfiguration->isCJ125Verbose) {
cjPrintState();
}
#endif /* EFI_UNIT_TEST */
}
class RealSpi : public Cj125SpiStream {
public:
uint8_t ReadRegister(uint8_t reg) override {
return cjReadRegister(reg);
}
void WriteRegister(uint8_t regAddr, uint8_t regValue) override {
cjWriteRegister(regAddr, regValue);
}
};
static RealSpi spi;
static void cjUpdateAnalogValues() {
#if EFI_PROD_CODE
// todo: some solution for testing
waitForSlowAdc(lastSlowAdcCounter);
#endif /* EFI_PROD_CODE */
globalInstance.vUr = getUr();
globalInstance.vUa = getUa();
#if EFI_PROD_CODE
// todo: some solution for testing
lastSlowAdcCounter = getSlowAdcCounter();
#endif /* EFI_PROD_CODE */
}
void CJ125::calibrate() {
cjIdentify();
efiPrintf("cj125: Starting calibration...");
cjSetMode(CJ125_MODE_CALIBRATION);
int init1 = cjReadRegister(INIT_REG1_RD);
// check if our command has been accepted
if (init1 != CJ125_INIT1_CALBRT) {
efiPrintf("cj125: Calibration error (init1=0x%02x)! Failed!", init1);
cjSetMode(CJ125_MODE_NORMAL_17);
return;
}
#if EFI_PROD_CODE
// todo: some testing solution
// wait for the start of the calibration
chThdSleepMilliseconds(CJ125_CALIBRATION_DELAY);
#endif /* EFI_PROD_CODE */
vUaCal = 0.0f;
vUrCal = 0.0f;
// wait for some more ADC samples
for (int i = 0; i < CJ125_CALIBRATE_NUM_SAMPLES; i++) {
cjUpdateAnalogValues();
cjPrintData();
#if EFI_TUNER_STUDIO
// todo: reimplement as explicit CJ PID status if desired cjPostState(&engine->outputChannels);
#endif /* EFI_TUNER_STUDIO */
vUaCal += vUa;
vUrCal += vUr;
}
// find average
vUaCal /= (float)CJ125_CALIBRATE_NUM_SAMPLES;
vUrCal /= (float)CJ125_CALIBRATE_NUM_SAMPLES;
// restore normal mode
cjSetMode(CJ125_MODE_NORMAL_17);
#if EFI_PROD_CODE
// todo: testing solution
chThdSleepMilliseconds(CJ125_CALIBRATION_DELAY);
#endif
// check if everything is ok
diag = cjReadRegister(DIAG_REG_RD);
cjUpdateAnalogValues();
cjPrintData();
// store new calibration data
uint32_t storedLambda = get16bitFromVoltage(vUaCal);
uint32_t storedHeater = get16bitFromVoltage(vUrCal);
efiPrintf("cj125: Done! Saving calibration data (%d %d).", storedLambda, storedHeater);
#if EFI_PROD_CODE
backupRamSave(BACKUP_CJ125_CALIBRATION_LAMBDA, storedLambda);
backupRamSave(BACKUP_CJ125_CALIBRATION_HEATER, storedHeater);
#endif /* EFI_PROD_CODE */
state = CJ125_IDLE;
}
static void cjStart() {
if (!engineConfiguration->isCJ125Enabled) {
efiPrintf("cj125 is disabled.");
return;
}
globalInstance.cjIdentify();
// Load calibration values
#if EFI_PROD_CODE
uint32_t storedLambda = backupRamLoad(BACKUP_CJ125_CALIBRATION_LAMBDA);
uint32_t storedHeater = backupRamLoad(BACKUP_CJ125_CALIBRATION_HEATER);
#else
uint32_t storedLambda = 0;
uint32_t storedHeater = 0;
#endif
// if no calibration, try to calibrate now and store new values
if (storedLambda == 0 || storedHeater == 0) {
/**
* open question if we need special considerations for calibration. Some controllers insist on open air calibration
*/
globalInstance.calibrate();
} else {
efiPrintf("cj125: Loading stored calibration data (%d %d)", storedLambda, storedHeater);
globalInstance.vUaCal = getVoltageFrom16bit(storedLambda);
globalInstance.vUrCal = getVoltageFrom16bit(storedHeater);
// Start normal measurement mode
globalInstance.cjSetMode(CJ125_MODE_NORMAL_17);
}
cjPrintData();
#if EFI_PROD_CODE
// todo: testig solution
lastSlowAdcCounter = getSlowAdcCounter();
#endif
}
void CJ125::setError(cj125_error_e errCode) {
errorCode = errCode;
state = CJ125_ERROR;
cjPrintErrorCode(errorCode);
// This is for safety:
efiPrintf("cj125: Controller Shutdown!");
SetHeater(0);
// Software-reset of CJ125
cjWriteRegister(INIT_REG2_WR, CJ125_INIT2_RESET);
}
static bool cjStartSpi() {
#if HAL_USE_SPI
globalInstance.cj125Cs.initPin("cj125 CS", engineConfiguration->cj125CsPin,
&engineConfiguration->cj125CsPinMode);
// Idle CS pin - SPI CS is high when idle
globalInstance.cj125Cs.setValue(true);
cj125spicfg.cr1 += getSpiPrescaler(_150KHz, engineConfiguration->cj125SpiDevice);
cj125spicfg.ssport = getHwPort("cj125", engineConfiguration->cj125CsPin);
cj125spicfg.sspad = getHwPin("cj125", engineConfiguration->cj125CsPin);
driver = getSpiDevice(engineConfiguration->cj125SpiDevice);
if (driver == NULL) {
// error already reported
return false;
}
efiPrintf("cj125: Starting SPI driver %s", getSpi_device_e(engineConfiguration->cj125SpiDevice));
spiStart(driver, &cj125spicfg);
#endif /* HAL_USE_SPI */
return true;
}
/**
* @return true if currently in IDLE or ERROR state
*/
static bool cj125periodic(CJ125 *instance) {
{
efitick_t nowNt = getTimeNowNt();
bool isStopped = engine->rpmCalculator.isStopped();
cjUpdateAnalogValues();
// If the controller is disabled
if (instance->state == CJ125_IDLE || instance->state == CJ125_ERROR) {
return true;
}
if (instance->state == CJ125_CALIBRATION) {
globalInstance.calibrate();
// Start normal operation
instance->state = CJ125_INIT;
globalInstance.cjSetMode(CJ125_MODE_NORMAL_17);
}
globalInstance.diag = cjReadRegister(DIAG_REG_RD);
// check heater state
if (globalInstance.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;
instance->startHeatingNt = instance->prevNt = getTimeNowNt();
globalInstance.cjSetMode(CJ125_MODE_NORMAL_17);
}
} else if (instance->vUr > CJ125_UR_GOOD_THR) {
instance->state = CJ125_HEAT_UP;
} else if (instance->vUr < CJ125_UR_OVERHEAT_THR) {
instance->state = CJ125_OVERHEAT;
} else {
// This indicates that the heater temperature is optimal for UA measurement
instance->state = CJ125_READY;
}
if (isStopped && instance->isWorkingState()) {
instance->state = CJ125_INIT;
instance->SetIdleHeater();
}
#if 0
// Change amplification if AFR gets lean/rich for better accuracy
globalInstance.cjSetMode(globalInstance.lambda > 1.0f ? CJ125_MODE_NORMAL_17 : CJ125_MODE_NORMAL_8);
#endif
switch (instance->state) {
case CJ125_PREHEAT:
// use constant-speed startup heat-up
if (nowNt - instance->prevNt >= CJ125_HEATER_PREHEAT_PERIOD) {
float periodSecs = (float)(nowNt - instance->prevNt) / NT_PER_SECOND;
// maintain speed at ~0.4V/sec
float preheatDuty = instance->heaterDuty + periodSecs * CJ125_HEATER_PREHEAT_RATE;
instance->SetHeater(preheatDuty);
// If we are heating too long, and there's still no result, then something is wrong...
if (nowNt - instance->startHeatingNt > NT_PER_SECOND * CJ125_PREHEAT_TIMEOUT) {
instance->setError(CJ125_ERROR_HEATER_MALFUNCTION);
}
cjPrintData();
instance->prevNt = nowNt;
}
break;
case CJ125_HEAT_UP:
case CJ125_READY:
// use PID for normal heater control
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 vUr<vUrCal then the error will cause the heater to increase it's duty cycle. But it's not exactly what we want! Lesser vUr means HOTTER cell. That's why we even have this safety check for overheating: (vUr < CJ125_UR_OVERHEAT_THR)...
* So the simple trick is to inverse the error by swapping the target and input values.
*/
float duty = globalInstance.heaterPid.getOutput(globalInstance.vUr, globalInstance.vUrCal, MS2SEC(CJ125_TICK_DELAY));
instance->SetHeater(duty);
if (engineConfiguration->isCJ125Verbose) {
globalInstance.heaterPid.showPidStatus("cj heater");
cjPrintData();
}
instance->prevNt = nowNt;
}
break;
case CJ125_OVERHEAT:
if (nowNt - instance->prevNt >= CJ125_HEATER_OVERHEAT_PERIOD) {
instance->setError(CJ125_ERROR_OVERHEAT);
instance->prevNt = nowNt;
}
default:
;
}
}
return false;
}
#if ! EFI_UNIT_TEST
static msg_t cjThread()
{
chRegSetThreadName("cj125");
chThdSleepMilliseconds(500);
globalInstance.startHeatingNt = 0;
globalInstance.prevNt = getTimeNowNt();
while (1) {
bool needIdleSleep = cj125periodic(&globalInstance);
chThdSleepMilliseconds(needIdleSleep ? CJ125_IDLE_TICK_DELAY : CJ125_TICK_DELAY);
}
return -1;
}
static bool cjCheckConfig() {
if (!engineConfiguration->isCJ125Enabled) {
efiPrintf("cj125 is disabled. Failed!");
return false;
}
return true;
}
void cjStartCalibration(void) {
if (!cjCheckConfig())
return;
if (globalInstance.isWorkingState()) {
// todo: change this later for the normal thread operation (auto pre-heating)
efiPrintf("cj125: Cannot start calibration. Please restart the board and make sure that your sensor is not heating");
return;
}
globalInstance.state = CJ125_CALIBRATION;
}
void cjRestart(void) {
if (!cjCheckConfig())
return;
globalInstance.state = CJ125_INIT;
globalInstance.errorCode = CJ125_NO_ERROR;
cjInfo();
cjStart();
}
#endif /* EFI_UNIT_TEST */
#ifdef CJ125_DEBUG
static void cjSetInit1(int v) {
cjWriteRegister(INIT_REG1_WR, v & 0xff);
v = cjReadRegister(INIT_REG1_RD);
efiPrintf("cj125 INIT_REG1=0x%02x.", v);
}
static void cjSetInit2(int v) {
cjWriteRegister(INIT_REG2_WR, v & 0xff);
v = cjReadRegister(INIT_REG2_RD);
efiPrintf("cj125 INIT_REG2=0x%02x.", v);
}
#endif /* CJ125_DEBUG */
float cjGetAfr() {
// See CJ125 datasheet, page 6
float pumpCurrent = (globalInstance.vUa - globalInstance.vUaCal) * globalInstance.amplCoeff * (CJ125_PUMP_CURRENT_FACTOR / CJ125_PUMP_SHUNT_RESISTOR);
if (engineConfiguration->cj125isLsu49) {
globalInstance.lambda = interpolate2d(pumpCurrent, pumpCurrentLsu49, lambdaLsu49);
} else {
globalInstance.lambda = interpolate2d(pumpCurrent, pumpCurrentLsu42, lambdaLsu42);
}
// todo: make configurable stoich ratio
return globalInstance.lambda * CJ125_STOICH_RATIO;
}
bool cjHasAfrSensor() {
if (!engineConfiguration->isCJ125Enabled)
return false;
return globalInstance.isValidState();
}
#if EFI_TUNER_STUDIO
// used by DBG_CJ125
void cjPostState(TunerStudioOutputChannels *tsOutputChannels) {
tsOutputChannels->debugFloatField1 = globalInstance.heaterDuty;
tsOutputChannels->debugFloatField2 = globalInstance.heaterPid.getIntegration();
tsOutputChannels->debugFloatField3 = globalInstance.heaterPid.getPrevError();
tsOutputChannels->debugFloatField4 = globalInstance.vUa;
tsOutputChannels->debugFloatField5 = globalInstance.vUr;
tsOutputChannels->debugFloatField6 = globalInstance.vUaCal;
tsOutputChannels->debugFloatField7 = globalInstance.vUrCal;
tsOutputChannels->debugIntField1 = globalInstance.state;
tsOutputChannels->debugIntField2 = globalInstance.diag;
}
#endif /* EFI_TUNER_STUDIO */
void initCJ125() {
globalInstance.spi = &spi;
if (!engineConfiguration->isCJ125Enabled) {
globalInstance.errorCode = CJ125_ERROR_DISABLED;
return;
}
if (!isAdcChannelValid(engineConfiguration->cj125ur) || !isAdcChannelValid(engineConfiguration->cj125ua)) {
efiPrintf("cj125 init error! cj125ur and cj125ua are required.");
warning(CUSTOM_CJ125_0, "cj ur ua");
globalInstance.errorCode = CJ125_ERROR_DISABLED;
return;
}
if (!isBrainPinValid(engineConfiguration->wboHeaterPin)) {
efiPrintf("cj125 init error! wboHeaterPin is required.");
warning(CUSTOM_CJ125_1, "cj heater");
globalInstance.errorCode = CJ125_ERROR_DISABLED;
return;
}
globalInstance.cjInitPid();
if (!cjStartSpi())
return;
efiPrintf("cj125: Starting heater control");
globalInstance.StartHeaterControl();
cjStart();
#ifdef CJ125_DEBUG
// addConsoleActionF("cj125_heater", cjConsoleSetHeater);
addConsoleActionI("cj125_set_init1", cjSetInit1);
addConsoleActionI("cj125_set_init2", cjSetInit2);
#endif /* CJ125_DEBUG */
#if ! EFI_UNIT_TEST
addConsoleAction("cj125_info", cjInfo);
addConsoleActionF("cj125_set_p", cjSetP);
addConsoleActionF("cj125_set_i", cjSetI);
addConsoleAction("cj125_restart", cjRestart);
addConsoleAction("cj125_calibrate", cjStartCalibration);
chThdCreateStatic(cj125ThreadStack, sizeof(cj125ThreadStack), PRIO_CJ125, (tfunc_t)(void*) cjThread, NULL);
#endif /* ! EFI_UNIT_TEST */
}
#endif /* EFI_CJ125 && HAL_USE_SPI */
#if EFI_CJ125
// engineConfiguration->spi2SckMode = PAL_STM32_OTYPE_OPENDRAIN; // 4
// engineConfiguration->spi2MosiMode = PAL_STM32_OTYPE_OPENDRAIN; // 4
// engineConfiguration->spi2MisoMode = PAL_STM32_PUDR_PULLUP; // 32
// engineConfiguration->cj125CsPin = Gpio::A15;
// engineConfiguration->cj125CsPinMode = OM_OPENDRAIN;
void cj125defaultPinout() {
engineConfiguration->cj125ua = EFI_ADC_13; // PC3
engineConfiguration->cj125ur = EFI_ADC_4; // PA4
engineConfiguration->wboHeaterPin = Gpio::C13;
engineConfiguration->spi2mosiPin = Gpio::B15;
engineConfiguration->spi2misoPin = Gpio::B14;
engineConfiguration->spi2sckPin = Gpio::B13;
engineConfiguration->cj125CsPin = Gpio::B0;
engineConfiguration->isCJ125Enabled = true;
engineConfiguration->is_enabled_spi_2 = true;
engineConfiguration->cj125SpiDevice = SPI_DEVICE_2;
}
#endif /* EFI_CJ125 */

View File

@ -1,111 +0,0 @@
/*
* @file cj125.h
*
* @date: Jul 17, 2016
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#pragma once
#include "cj125_logic.h"
/**********************************************************************************
* Courtesy "Turbo SOB"
* http://www.turbo-mopar.com/forums/showthread.php?77041-Wideband-O2-Controller-Project-with-EGT-A2D-DAQ-Diagnostic-Etc&p=1110559#post1110559
INIT_REG1 - CJ125 Initialization Register 1
00x000x0
||||||||---- VL - Pump Current Sense Amplifier - 0 = x8, 1 = x17
If VL is set to "0" the amplification of Ip is 8.
If VL is "1" the amplification is 17. The higher
amplification is needed for a better resolution
at Lambda > 1, amplification 8 for Lambda < 1.
Note: It seems to make no difference, always set to 1.
|||||||----- Unused
||||||------ LA - Pump Current Sense Amplifier - 0 = measurement, 1 = calibration
If LA is "0" the measurement mode for Ip is active.
The current pump current is displayed on Ua. If LA is
set to "1" the calibration mode is active. The shown
voltage on Ua must been subtracted from the later measurement.
|||||------- Undocumented Bit - Note: CJ125 only seems to work when set to 1.
||||-------- RA - Measurement Current for Ri - 0 = measurement, 1 = calibration
If RA is "0" the measurement mode for Ri is active and
the current resistance of the probe is "displayed" on Ur.
If RA is "1" the calibration mode is active. You get the
optimal voltage for the inner resistance of the probe on Ur.
|||--------- Unused
||---------- PA - Pump Current Control - Set to 0 to be active
|----------- ENABLE/HOLD - Must be set to 1 to enable
***********************************************************************************/
/**********************************************************************************
INIT_REG2 - CJ125 Initialization Register 1
xxx00000
||||||||---- PR0 - Reference Pump Current (10 uA)
|||||||----- PR1 - Reference Pump Current (20 uA)
||||||------ PR2 - Reference Pump Current (40 uA)
|||||------- PR3 - Reference Pump Current (80 uA)
||||-------- ENSCUN - Enables diagnostics for pin UN of the CJ125
|||--------- Unused
||---------- Unused
|----------- Unused
***********************************************************************************/
/**********************************************************************************
DIAG_REG - CJ125 Diagnostic Register Definition (Read Only)
00000000
||||||||---- Sensor VM Diagnostic Bit 0
|||||||----- Sensor VM Diagnostic Bit 1
||||||------ Sensor UN Diagnostic Bit 0
|||||------- Sensor UN Diagnostic Bit 1
||||-------- Sensor IA/IP Diagnostic Bit 0
|||--------- Sensor IA/IP Diagnostic Bit 1
00 = Short circuit to ground
01 = Low Battery
10 = Short circuit to Vbatt
11 = No Failure
||---------- Ext. Heater DIAHD Diagnostic Bit
|----------- Ext. Heater DIAHG Diagnostic Bit
00 = Short circuit to ground
01 = Open Load
10 = Short circuit to Vbatt
11 = No Failure
***********************************************************************************/
#define CJ125_CALIBRATION_DELAY 1000 // 1 sec
#define CJ125_TICK_DELAY 20 // 20 ms
#define CJ125_IDLE_TICK_DELAY 1000 // 1 sec
#define CJ125_CALIBRATE_NUM_SAMPLES 10
#define CJ125_UR_PREHEAT_THR 2.0f // Ur > 2.0 Volts is too cold to control with PID
#define CJ125_UR_OVERHEAT_THR 0.5f // Ur < 0.5 Volts is overheat
#define CJ125_UR_GOOD_THR 1.4f
#define CJ125_PREHEAT_MIN_DUTY 0.9f
//#define CJ125_PREHEAT_TIMEOUT 90 // 90 secs
#define CJ125_PREHEAT_TIMEOUT 300
#define CJ125_VOLTAGE_TO_16BIT_FACTOR 4096.0f
#define CJ125_PUMP_SHUNT_RESISTOR 61.9f
#define CJ125_STOICH_RATIO STOICH_RATIO
#define CJ125_PUMP_CURRENT_FACTOR 1000.0f
// Returned if there's no valid measurement
#define CJ125_AFR_NAN 0.0f
#if EFI_TUNER_STUDIO
void cjPostState(TunerStudioOutputChannels *tsOutputChannels);
#endif /* EFI_TUNER_STUDIO */
void initCJ125();
void cjRestart(void);
void cjStartCalibration(void);
float cjGetAfr();
bool cjHasAfrSensor();
void cj125defaultPinout();

View File

@ -1,9 +0,0 @@
Use _cj125_ command in rusEfi console to confirm SPI communication.
Use _cj125_calibrate_ command in rusEfi console for calibration.
Use Debug Mode = CJ125 for heater validation.
See https://github.com/rusefi/rusefi/wiki/WBO for more info.

View File

@ -1,165 +0,0 @@
/*
* @file CJ125_logic.cpp
*
* @date Feb 1, 2019
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#include "pch.h"
#include "cj125_logic.h"
#define LOW_VOLTAGE "Low Voltage"
CJ125::CJ125() : wboHeaterControl("wbo"),
heaterPid(&heaterPidConfig) {
}
void CJ125::SetHeater(float value) {
// limit duty cycle for sensor safety
// todo: would be much nicer to have continuous function (vBatt)
float maxDuty = (Sensor::get(SensorType::BatteryVoltage).value_or(VBAT_FALLBACK_VALUE) > 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
efiPrintf("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() {
// small preheat for faster start & moisture anti-shock therapy for the sensor
SetHeater(CJ125_HEATER_IDLE_RATE);
}
bool CJ125::isWorkingState(void) const {
return state != CJ125_ERROR && state != CJ125_INIT && state != CJ125_IDLE;
}
void CJ125::StartHeaterControl() {
// todo: use custom pin state method, turn pin off while not running
startSimplePwmExt(&wboHeaterControl, "wboHeaterPin",
&engine->executor,
engineConfiguration->wboHeaterPin,
&wboHeaterPin, CJ125_HEATER_PWM_FREQ, 0.0f);
SetIdleHeater();
}
static void printDiagCode(const char *msg, int code, const char *code1message) {
switch(code & 0x3) {
case 0:
efiPrintf("%s Short to GND", msg);
return;
case 1:
efiPrintf("%s %s", msg, code1message);
return;
case 2:
efiPrintf("%s Short to Vbatt", msg);
return;
case 3:
efiPrintf("%s LOOKS GOOD", msg);
return;
}
}
void CJ125::printDiag() {
if (diag == CJ125_DIAG_NORM) {
efiPrintf("cj125: diag Looks great!");
} else {
efiPrintf("cj125: diag NOT GOOD");
printDiagCode("VM", diag, LOW_VOLTAGE);
printDiagCode("UN", diag >> 2, LOW_VOLTAGE);
printDiagCode("IA", diag >> 4, LOW_VOLTAGE);
printDiagCode("HR", diag >> 6, "open load");
/* todo: do we want to throw CRITICAL on diag start-up error? probably not?
firmwareError(CUSTOM_ERR_CJ125_DIAG, "CJ125 is not well");
*/
}
}
/**
* @return true in case of positive SPI identification
* false in case of unexpected SPI response
*/
bool CJ125::cjIdentify() {
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);
efiPrintf("cj125: Check ident=0x%x diag=0x%x init1=0x%x init2=0x%x", ident, diag, init1, init2);
if (ident != CJ125_IDENT) {
efiPrintf("cj125: Error! Wrong ident! Cannot communicate with CJ125!");
setError(CJ125_ERROR_WRONG_IDENT);
return false;
}
if (init1 != CJ125_INIT1_NORMAL_17 || init2 != CJ125_INIT2_DIAG) {
efiPrintf("cj125: Error! Cannot set init registers! Cannot communicate with CJ125!");
setError(CJ125_ERROR_WRONG_IDENT);
return false;
}
printDiag();
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() {
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;
/**
* See hard-coded CJ125_TICK_DELAY - we run PID at 50Hz
*/
heaterPid.reset();
}

View File

@ -1,155 +0,0 @@
/*
* @file CJ125_logic.h
*
* @date Feb 1, 2019
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#pragma once
#include "engine_configuration.h"
#include "pwm_generator_logic.h"
#include "efi_pid.h"
typedef enum {
CJ125_LSU_42 = 0,
CJ125_LSU_49 = 1,
} cj125_sensor_type_e;
typedef enum {
CJ125_INIT = 0,
CJ125_IDLE = 1,
CJ125_CALIBRATION = 2,
CJ125_PREHEAT = 3,
CJ125_HEAT_UP = 4,
CJ125_READY = 5,
CJ125_OVERHEAT = 6,
CJ125_ERROR = 7,
} cj125_state_e;
typedef enum {
CJ125_NO_ERROR = 0,
CJ125_ERROR_HEATER_MALFUNCTION = 1,
CJ125_ERROR_OVERHEAT = 2,
CJ125_ERROR_WRONG_IDENT = 3,
CJ125_ERROR_WRONG_INIT = 4,
CJ125_ERROR_DISABLED = 5,
} cj125_error_e;
typedef enum {
CJ125_MODE_NONE,
CJ125_MODE_NORMAL_8,
CJ125_MODE_NORMAL_17,
CJ125_MODE_CALIBRATION,
} cj125_mode_e;
class Cj125SpiStream {
public:
virtual uint8_t ReadRegister(uint8_t regAddr) = 0;
virtual void WriteRegister(uint8_t regAddr, uint8_t regValue) = 0;
};
class CJ125 {
public:
CJ125();
Cj125SpiStream *spi = nullptr;
SimplePwm wboHeaterControl;
// Chip diagnostics register contents
int diag = 0;
efitick_t startHeatingNt;
efitick_t prevNt;
float heaterDuty = 0.0f;
pid_s heaterPidConfig;
Pid heaterPid;
cj125_mode_e mode = CJ125_MODE_NONE;
// Amplification coefficient, needed by cjGetAfr()
float amplCoeff = 0.0f;
// Calculated Lambda-value
float lambda = 1.0f;
// Current values
// lambda
float vUa = 0.0f;
// heater
float vUr = 0.0f;
// Calibration values
// lambda
float vUaCal = 0.0f;
// header
float vUrCal = 0.0f;
OutputPin wboHeaterPin;
OutputPin cj125Cs;
// Used by CJ125 driver state machine
cj125_state_e state = CJ125_INIT;
// Last Error code
cj125_error_e errorCode = CJ125_NO_ERROR;
void setError(cj125_error_e errCode);
bool isWorkingState(void) const;
void SetHeater(float value);
void SetIdleHeater();
void StartHeaterControl();
bool cjIdentify();
void printDiag();
void calibrate();
void cjSetMode(cj125_mode_e m);
bool isValidState() const;
void cjInitPid();
};
// 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.
// CJ125 SPI Registers
#define IDENT_REG_RD 0x48 // Read Identity Register
#define INIT_REG1_WR 0x56 // Write To Initialization Register 1
#define INIT_REG2_WR 0x5A // Write To Initialization Register 2
#define INIT_REG1_RD 0x6C // Read Initialization Register 1
#define DIAG_REG_RD 0x78 // Read Diagnostics Register
#define INIT_REG2_RD 0x7E // Read Initialization Register 2
#define CJ125_IDENT 0x60 // 96
#define CJ125_IDENT_MASK 0xF8
#define CJ125_INIT1_NORMAL_8 0x88 // 0b10001000 (Normal mode, Amplification 8)
#define CJ125_INIT1_NORMAL_17 0x89 // 0b10001001 (Normal mode, Amplification 17)
#define CJ125_INIT1_CALBRT 0x9D // 0b10011101 (Calibration mode, LA=1, RA=1)
#define CJ125_INIT2_NORMAL 0x00 // 0b00000000, (Normal mode)
#define CJ125_INIT2_DIAG 0x10 // 0b00010000, (Extended diagnostics mode, SET_DIA_Q=1)
#define CJ125_INIT2_RESET 0x40 // 0b01000000, SRESET=1
#define CJ125_DIAG_NORM 0xFF // no errors
#define CJ125_UACAL_MIN 1.0f // Calibration UA values range
#define CJ125_UACAL_MAX 2.0f
// Some experimental magic values for heater PID regulator
#define CJ125_PID_LSU42_P (80.0f / 16.0f * 5.0f / 1024.0f)
#define CJ125_PID_LSU42_I (25.0f / 16.0f * 5.0f / 1024.0f)
#define CJ125_PID_LSU49_P (8.0f)
#define CJ125_PID_LSU49_I (0.003f)

View File

@ -3,8 +3,6 @@ HW_SENSORS_DIR=$(PROJECT_DIR)/hw_layer/sensors
HW_SENSORS_INC=$(HW_SENSORS_DIR)
HW_SENSORS_CPP = \
$(HW_SENSORS_DIR)/cj125.cpp \
$(HW_SENSORS_DIR)/cj125_logic.cpp \
$(HW_SENSORS_DIR)/yaw_rate_sensor.cpp \
$(HW_SENSORS_DIR)/accelerometer.cpp \
$(HW_SENSORS_DIR)/lps25.cpp \

View File

@ -46,15 +46,11 @@ static void initOldAnalogInputs() {
}
initIfValid("AFR", engineConfiguration->afr.hwChannel);
initIfValid("AUXF#1", engineConfiguration->auxFastSensor1_adcChannel);
initIfValid("CJ125 UR", engineConfiguration->cj125ur);
initIfValid("CJ125 UA", engineConfiguration->cj125ua);
}
static void deInitOldAnalogInputs() {
deInitIfValid("AFR", activeConfiguration.afr.hwChannel);
deInitIfValid("AUXF#1", activeConfiguration.auxFastSensor1_adcChannel);
deInitIfValid("CJ125 UR", activeConfiguration.cj125ur);
deInitIfValid("CJ125 UA", activeConfiguration.cj125ua);
}
static void initAuxDigital() {

View File

@ -316,7 +316,7 @@ float baseFuel;Base mass of the per-cylinder fuel injected during cranking. This
int16_t rpm;This sets the RPM limit below which the ECU will use cranking fuel and ignition logic, typically this is around 350-450rpm. \nset cranking_rpm X;"RPM", 1, 0, 0, 3000, 0
end_struct
#define debug_mode_e_enum "INVALID", "TPS acceleration enrichment", "INVALID", "Stepper Idle Control", "Engine Load accl enrich", "Trigger Counters", "Soft Spark Cut", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "SD card", "sr5", "Knock", "INVALID", "Electronic Throttle", "Executor", "Bench Test / TS commands", "INVALID", "Analog inputs #1", "INSTANT_RPM", "INVALID", "Status", "CJ125", "INVALID", "MAP", "Metrics", "INVALID", "Ion Sense", "TLE8888", "Analog inputs #2", "Dwell Metric", "INVALID", "INVALID", "Boost Control", "INVALID", "INVALID", "ETB Autotune", "Composite Log", "INVALID", "INVALID", "INVALID", "Dyno_View", "Logic_Analyzer", "INVALID", "TCU", "Lua"
#define debug_mode_e_enum "INVALID", "TPS acceleration enrichment", "INVALID", "Stepper Idle Control", "Engine Load accl enrich", "Trigger Counters", "Soft Spark Cut", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "INVALID", "SD card", "sr5", "Knock", "INVALID", "Electronic Throttle", "Executor", "Bench Test / TS commands", "INVALID", "Analog inputs #1", "INSTANT_RPM", "INVALID", "Status", "INVALID", "INVALID", "MAP", "Metrics", "INVALID", "Ion Sense", "TLE8888", "Analog inputs #2", "Dwell Metric", "INVALID", "INVALID", "Boost Control", "INVALID", "INVALID", "ETB Autotune", "Composite Log", "INVALID", "INVALID", "INVALID", "Dyno_View", "Logic_Analyzer", "INVALID", "TCU", "Lua"
custom debug_mode_e 1 bits, U08, @OFFSET@, [0:5], @@debug_mode_e_enum@@
#define vvt_mode_e_enum "Inactive", "Single Tooth Second Half", "2JZ", "Miata NB2", "Single Tooth First Half", "Bosch Quick Start", "4/1", "ST 170", "Ford Barra 3+1", "Nissan VQ", "Honda K Intake", "Nissan MR18", "Mitsu 3A92", "VTwin by MAP", "Mitsu 6G75", "Mazda Skyactiv", "Honda K Exhaust", "Mitsubishi 4G92/93/94", "Mitsubishi 4G63"
@ -461,13 +461,9 @@ bit enableFan2WithAc;Turn on this fan when AC is on.
bit disableFan1WhenStopped;Inhibit operation of this fan while the engine is not running.
bit disableFan2WhenStopped;Inhibit operation of this fan while the engine is not running.
bit enableTrailingSparks;Enable secondary spark outputs that fire after the primary (rotaries, twin plug engines).
bit isCJ125Verbose;enable cj125verbose/disable cj125verbose
bit cj125isUaDivided;Is your UA CJ125 output wired to MCU via resistor divider? Ua can go over 3.3v but only at lambda >3, i.e very lean AFR above 44.1\nWhen exposed to free air and 17x gain, Ua will be 4.17 volt
bit cj125isLsu49
bit etb_use_two_wires;TLE7209 uses two-wire mode. TLE9201 and VNH2SP30 do NOT use two wire mode.
bit isDoubleSolenoidIdle;Subaru/BMW style where default valve position is somewhere in the middle. First solenoid opens it more while second can close it more than default position.
bit useEeprom
bit cj125isUrDivided;Is your UR CJ125 output wired to MCU via resistor divider?\nLooks like 3v range should be enough, divider generally not needed.
bit useCicPidForIdle;Switch between Industrial and Cic PID implementation
bit useTLE8888_cranking_hack;
bit kickStartCranking
@ -685,8 +681,6 @@ switch_input_pin_e clutchDownPin;Some cars have a switch to indicate that clutch
Gpio[DIGIPOT_COUNT iterate] digitalPotentiometerChipSelect;
pin_output_mode_e electronicThrottlePin1Mode;
Gpio wboHeaterPin;set_cj125_heater_pin XXX
Gpio cj125CsPin;set_cj125_cs_pin XXX
spi_device_e max31855spiDevice;
Gpio debugTriggerSync;
@ -739,7 +733,7 @@ pin_input_mode_e throttlePedalUpPinMode;
pin_output_mode_e[TRIGGER_SIMULATOR_PIN_COUNT iterate] triggerSimulatorPinModes;
adc_channel_e maf2AdcChannel
output_pin_e o2heaterPin;Narrow band o2 heater, not used for CJ125. 'ON' if engine is running, 'OFF' if stopped or cranking. See wboHeaterPin
output_pin_e o2heaterPin;On-off O2 sensor heater control. 'ON' if engine is running, 'OFF' if stopped or cranking.
pin_output_mode_e o2heaterPinModeTodO;
@ -760,7 +754,6 @@ bit is_enabled_spi_2
bit verboseTLE8888
bit enableVerboseCanTx;CAN broadcast using custom rusEFI protocol\nenable can_broadcast/disable can_broadcast
bit etb1configured
bit isCJ125Enabled;enable cj125/disable cj125
bit etb2configured
bit measureMapOnlyInOneCylinder;Useful for individual intakes
bit stepperForceParkingEveryRestart
@ -1231,8 +1224,6 @@ int16_t tps2Max;Full throttle#2. tpsMax value as 10 bit ADC value. Not Voltage!\
output_pin_e[CAM_INPUTS_COUNT iterate] vvtPins;VVT output\nTODO: rename to vvtOutputs
spi_device_e cj125SpiDevice;
pin_output_mode_e cj125CsPinMode;
pin_output_mode_e sdCardCsPinMode;
int crankingIACposition;This is the IAC position during cranking, some engines start better if given more air during cranking to improve cylinder filling.;"percent", 1, 0, -100, 100, 0
@ -1302,8 +1293,6 @@ custom stepper_num_micro_steps_e 1 bits, U08, @OFFSET@, [0:3], @@stepper_num_mic
Gpio mc33816_driven
switch_input_pin_e brakePedalPin;Brake pedal switch
adc_channel_e cj125ua;lambda input
adc_channel_e cj125ur;heater input
pin_input_mode_e brakePedalPinMode;
@ -2160,7 +2149,6 @@ end_struct
#define ts_show_vr_threshold_2 true
#define ts_show_main_relay true
#define ts_show_main_relay_microRusEFI_message false
#define ts_show_cj125 true
#define ts_show_etb true
#define ts_show_etb_pins true
#define ts_show_full_pinout true

View File

@ -1832,7 +1832,6 @@ menuDialog = main
subMenu = egoSettings, "EGO sensor"
subMenu = widebandConfig, "rusEFI Wideband Controller", 0, { canReadEnabled && canWriteEnabled }
subMenu = narrowToWideOxygenCurve, "Narrow to Wideband approximation"
subMenu = cj125Function, "CJ125 settings (wbo decoder)" @@if_ts_show_cj125
subMenu = std_separator
# Misc sensors
@ -1990,7 +1989,6 @@ cmd_burn_without_flash = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_X14_16_h
cmd_set_wideband_idx_0 = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_WIDEBAND_16_hex@@\x00\x00"
cmd_set_wideband_idx_1 = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_WIDEBAND_16_hex@@\x00\x01"
cmd_cj125_calibrate = "@@TS_IO_TEST_COMMAND_char@@\x00\x18\x00\x00"
cmd_call_from_pit = "@@TS_IO_TEST_COMMAND_char@@\x00\x20\x34\x56"
cmd_stop_engine = "@@TS_IO_TEST_COMMAND_char@@\x00\x79\x00\x00"
@ -3372,22 +3370,6 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_
field = "SPI device", hip9011SpiDevice, {isHip9011Enabled == 1}
panel = knockThresholdCurve
; Engine->cj125 Settings
dialog = cj125Function, "CJ125 Settings (wbo decoder)"
field = "Enabled", isCJ125Enabled
commandButton = "Calibrate", cmd_cj125_calibrate
field = "Using 4.9 sensor?", cj125isLsu49
field = "!ECU reboot needed to apply these settings"
field = "ChipSelect pin", cj125CsPin, {isCJ125Enabled == 1}
field = "ChipSelect mode", cj125CsPinMode, {isCJ125Enabled == 1}
field = "!See also 'Controller-SPI setting'"
field = "SPI device", cj125SpiDevice
field = "Heater output", wboHeaterPin, {isCJ125Enabled == 1}
field = "UA input", cj125ua, {isCJ125Enabled == 1}
field = "UR input", cj125ur, {isCJ125Enabled == 1}
field = "Is UA input divided?" cj125isUaDivided, {isCJ125Enabled == 1}
field = "Is UR input divided?" cj125isUrDivided, {isCJ125Enabled == 1}
dialog = spiFunction, "SPI settings"
field = "!ECU reboot needed to apply these settings"
field = "SPI1 enable", is_enabled_spi_1

View File

@ -1,63 +0,0 @@
/*
* @file test_cj125.cpp
*
* Created on: Jan 3, 2019
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#include "pch.h"
#include "cj125_logic.h"
class TestSpi : public Cj125SpiStream {
public:
MOCK_METHOD1(ReadRegister, uint8_t(uint8_t));
MOCK_METHOD2(WriteRegister, void(uint8_t, uint8_t));
};
TEST(testCJ125, testInitialState) {
CJ125 cj;
ASSERT_EQ(cj.state, CJ125_INIT);
ASSERT_FALSE(cj.isWorkingState());
ASSERT_EQ(cj.heaterDuty, 0);
EngineTestHelper eth(FORD_ASPIRE_1996);
cj.StartHeaterControl();
ASSERT_EQ(cj.heaterDuty, CJ125_HEATER_IDLE_RATE);
TestSpi mock;
cj.spi = &mock;
EXPECT_CALL(mock, ReadRegister(IDENT_REG_RD)).Times(1).WillOnce(Return(CJ125_IDENT));
EXPECT_CALL(mock, ReadRegister(INIT_REG1_RD)).Times(1).WillOnce(Return(CJ125_INIT1_NORMAL_17));
EXPECT_CALL(mock, ReadRegister(INIT_REG2_RD)).Times(1).WillOnce(Return(CJ125_INIT2_DIAG));
EXPECT_CALL(mock, ReadRegister(DIAG_REG_RD)).Times(1);
cj.cjIdentify();
// validate that error state was not set
ASSERT_EQ(cj.state, CJ125_INIT);
}
TEST(testCJ125, testFailedIdentify) {
CJ125 cj;
ASSERT_EQ(cj.state, CJ125_INIT);
TestSpi mock;
cj.spi = &mock;
EngineTestHelper eth(FORD_ASPIRE_1996);
cj.cjIdentify();
ASSERT_EQ(cj.errorCode, CJ125_ERROR_WRONG_IDENT);
ASSERT_EQ(cj.state, CJ125_ERROR);
}
TEST(testCJ125, testMode) {
}

View File

@ -47,7 +47,6 @@ TESTS_SRC_CPP = \
tests/lua/test_lua_Leiderman_Khlystov.cpp \
tests/lua/test_can_filter.cpp \
tests/lua/test_lua_vin.cpp \
tests/sensor/test_cj125.cpp \
tests/test_change_engine_type.cpp \
tests/util/test_scaled_channel.cpp \
tests/util/test_timer.cpp \