Fix afr dropdown, switch AFR to sensor model (#62)

* move presets to ini, like clt/iat

* call deinit

* init lambda using proper sensors

* raw output channel

* init lambda test

* ve blend 1 should use bias table 1, good eye @nmstec
This commit is contained in:
Matthew Kennedy 2023-03-09 11:25:30 -08:00 committed by GitHub
parent b2010b6b8e
commit df03f3c536
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 60 additions and 83 deletions

View File

@ -465,8 +465,7 @@ static void updateRawSensors() {
} }
} }
// TODO: transition AFR to new sensor model engine->outputChannels.rawAfr = Sensor::getRaw(SensorType::Lambda1);
engine->outputChannels.rawAfr = (engineConfiguration->afr.hwChannel == EFI_ADC_NONE) ? 0 : getVoltageDivided("ego", engineConfiguration->afr.hwChannel);
} }
static void updatePressures() { static void updatePressures() {
engine->outputChannels.baroPressure = Sensor::getOrZero(SensorType::BarometricPressure); engine->outputChannels.baroPressure = Sensor::getOrZero(SensorType::BarometricPressure);

View File

@ -3,45 +3,11 @@
* *
* EGO Exhaust Gas Oxygen, also known as AFR Air/Fuel Ratio :) * EGO Exhaust Gas Oxygen, also known as AFR Air/Fuel Ratio :)
* *
* 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.
* 3) CJ125 internal wideband controller is known to work with both 4.2 and 4.9
*
*/ */
#include "pch.h" #include "pch.h"
#include "cyclic_buffer.h" void setEgoSensor(ego_sensor_e type) {
auto sensor = &engineConfiguration->afr;
bool hasAfrSensor() {
if (engineConfiguration->enableAemXSeries || engineConfiguration->enableInnovateLC2) {
return true;
}
return isAdcChannelValid(engineConfiguration->afr.hwChannel);
}
extern float InnovateLC2AFR;
float getAfr(SensorType type) {
#if EFI_AUX_SERIAL
if (engineConfiguration->enableInnovateLC2)
return InnovateLC2AFR;
#endif
afr_sensor_s * sensor = &engineConfiguration->afr;
if (!isAdcChannelValid(type == SensorType::Lambda1 ? engineConfiguration->afr.hwChannel : engineConfiguration->afr.hwChannel2)) {
return 0;
}
float volts = getVoltageDivided("ego", type == SensorType::Lambda1 ? sensor->hwChannel : sensor->hwChannel2);
return interpolateMsg("AFR", sensor->v1, sensor->value1, sensor->v2, sensor->value2, volts)
+ engineConfiguration->egoValueShift;
}
static void initEgoSensor(afr_sensor_s *sensor, ego_sensor_e type) {
switch (type) { switch (type) {
case ES_BPSX_D1: case ES_BPSX_D1:
@ -78,8 +44,3 @@ static void initEgoSensor(afr_sensor_s *sensor, ego_sensor_e type) {
break; break;
} }
} }
void setEgoSensor(ego_sensor_e type) {
engineConfiguration->afr_type = type;
initEgoSensor(&engineConfiguration->afr, type);
}

View File

@ -12,6 +12,4 @@
#include "global.h" #include "global.h"
#include "engine_configuration.h" #include "engine_configuration.h"
float getAfr(SensorType type);
bool hasAfrSensor();
void setEgoSensor(ego_sensor_e type); void setEgoSensor(ego_sensor_e type);

View File

@ -40,6 +40,7 @@ void deinitVbatt();
void deinitTps(); void deinitTps();
void deinitThermistors(); void deinitThermistors();
void deinitFluidPressure(); void deinitFluidPressure();
void deinitLambda();
void deInitFlexSensor(); void deInitFlexSensor();
void deInitVehicleSpeedSensor(); void deInitVehicleSpeedSensor();
void deinitTurbochargerSpeedSensor(); void deinitTurbochargerSpeedSensor();

View File

@ -2,29 +2,13 @@
#include "init.h" #include "init.h"
#include "adc_subscription.h" #include "adc_subscription.h"
#include "function_pointer_sensor.h" #include "linear_func.h"
#include "live_data.h" #include "live_data.h"
struct GetAfrWrapper { static LinearFunc func;
float getLambda() {
return getAfr(SensorType::Lambda1) / 14.7f;
};
float getLambda2() {
return getAfr(SensorType::Lambda2) / 14.7f;
}
};
static GetAfrWrapper afrWrapper; static FunctionalSensor lambdaSensor(SensorType::Lambda1, MS2NT(50));
static FunctionalSensor lambdaSensor2(SensorType::Lambda2, MS2NT(50));
static FunctionPointerSensor lambdaSensor(SensorType::Lambda1,
[]() {
return afrWrapper.getLambda();
});
static FunctionPointerSensor lambdaSensor2(SensorType::Lambda2,
[]() {
return afrWrapper.getLambda2();
});
#include "AemXSeriesLambda.h" #include "AemXSeriesLambda.h"
@ -45,6 +29,15 @@ const wideband_state_s* getLiveData(size_t idx) {
return nullptr; return nullptr;
} }
static void initLambdaSensor(FunctionalSensor& sensor, adc_channel_e channel) {
if (!isAdcChannelValid(channel)) {
return;
}
AdcSubscription::SubscribeSensor(sensor, channel, 10);
sensor.Register();
}
void initLambda() { void initLambda() {
#if EFI_CAN_SUPPORT #if EFI_CAN_SUPPORT
@ -61,6 +54,20 @@ void initLambda() {
} }
#endif #endif
lambdaSensor.Register(); auto& cfg = engineConfiguration->afr;
lambdaSensor2.Register(); float minLambda = (cfg.value1 + engineConfiguration->egoValueShift) / 14.7f;
float maxLambda = (cfg.value2 + engineConfiguration->egoValueShift) / 14.7f;
func.configure(cfg.v1, minLambda, cfg.v2, maxLambda, 0, 5);
lambdaSensor.setFunction(func);
lambdaSensor2.setFunction(func);
initLambdaSensor(lambdaSensor, engineConfiguration->afr.hwChannel);
initLambdaSensor(lambdaSensor2, engineConfiguration->afr.hwChannel2);
}
void deinitLambda() {
AdcSubscription::UnsubscribeSensor(lambdaSensor, engineConfiguration->afr.hwChannel);
AdcSubscription::UnsubscribeSensor(lambdaSensor2, engineConfiguration->afr.hwChannel2);
} }

View File

@ -41,12 +41,10 @@ void deInitIfValid(const char* msg, adc_channel_e channel) {
} }
static void initOldAnalogInputs() { static void initOldAnalogInputs() {
initIfValid("AFR", engineConfiguration->afr.hwChannel);
initIfValid("AUXF#1", engineConfiguration->auxFastSensor1_adcChannel); initIfValid("AUXF#1", engineConfiguration->auxFastSensor1_adcChannel);
} }
static void deInitOldAnalogInputs() { static void deInitOldAnalogInputs() {
deInitIfValid("AFR", activeConfiguration.afr.hwChannel);
deInitIfValid("AUXF#1", activeConfiguration.auxFastSensor1_adcChannel); deInitIfValid("AUXF#1", activeConfiguration.auxFastSensor1_adcChannel);
} }
@ -117,6 +115,7 @@ void stopSensors() {
deinitFluidPressure(); deinitFluidPressure();
deinitVbatt(); deinitVbatt();
deinitThermistors(); deinitThermistors();
deinitLambda();
deInitFlexSensor(); deInitFlexSensor();
deInitVehicleSpeedSensor(); deInitVehicleSpeedSensor();
deinitTurbochargerSpeedSensor(); deinitTurbochargerSpeedSensor();

View File

@ -259,9 +259,6 @@ struct pid_s
int16_t maxValue;Output Max Duty Cycle;"", 1, 0, -30000, 30000, 0 int16_t maxValue;Output Max Duty Cycle;"", 1, 0, -30000, 30000, 0
end_struct end_struct
#define ego_sensor_e_enum "BPSX", "Innovate", "14Point7", "INVALID", "PLX", "Custom"
custom ego_sensor_e 1 bits, S08, @OFFSET@, [0:2], @@ego_sensor_e_enum@@
#define SentEtbType_enum "None", "GM type 1", "Ford type 1" #define SentEtbType_enum "None", "GM type 1", "Ford type 1"
custom SentEtbType 1 bits, S08, @OFFSET@, [0:1], @@SentEtbType_enum@@ custom SentEtbType 1 bits, S08, @OFFSET@, [0:1], @@SentEtbType_enum@@
@ -614,7 +611,7 @@ engineSyncCam_e engineSyncCam;Select which cam is used for engine sync. Other ca
uint16_t autoscale vssGearRatio;Number of turns of your vehicle speed sensor per turn of the wheels. For example if your sensor is on the transmission output, enter your axle/differential ratio. If you are using a hub-mounted sensor, enter a value of 1.0.;"ratio", 0.001, 0, 0, 60, 3 uint16_t autoscale vssGearRatio;Number of turns of your vehicle speed sensor per turn of the wheels. For example if your sensor is on the transmission output, enter your axle/differential ratio. If you are using a hub-mounted sensor, enter a value of 1.0.;"ratio", 0.001, 0, 0, 60, 3
uint8_t vssToothCount;Number of pulses output per revolution of the shaft where your VSS is mounted. For example, GM applications of the T56 output 17 pulses per revolution of the transmission output shaft.;"count", 1, 0, 1, 100, 0 uint8_t vssToothCount;Number of pulses output per revolution of the shaft where your VSS is mounted. For example, GM applications of the T56 output 17 pulses per revolution of the transmission output shaft.;"count", 1, 0, 1, 100, 0
ego_sensor_e afr_type;AFR, WBO, EGO - whatever you like to call it; uint8_t unused499
Gpio l9779_cs; Gpio l9779_cs;

View File

@ -2420,7 +2420,7 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_
field = "#The X axis of the bias table is controlled by the selected blend" field = "#The X axis of the bias table is controlled by the selected blend"
field = "#parameter below." field = "#parameter below."
field = "Blend parameter", veBlends1_blendParameter field = "Blend parameter", veBlends1_blendParameter
panel = veBlend2Bias panel = veBlend1Bias
dialog = veBlend2Cfg, "VE blend 2 config" dialog = veBlend2Cfg, "VE blend 2 config"
field = "#The bias table controls how much of the blend table" field = "#The bias table controls how much of the blend table"
@ -2949,14 +2949,17 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@@@ts_command_e_TS_
field = "MAF ADC input", mafAdcChannel field = "MAF ADC input", mafAdcChannel
field = "MAF 2 ADC input", maf2AdcChannel field = "MAF 2 ADC input", maf2AdcChannel
; Sensors->EGO sensor
dialog = egoSettings_sensor, "EGO sensor" dialog = egoSettings_sensor, "EGO sensor"
field = "Type", afr_type settingSelector = "Common O2 Controllers"
; todo: only use these values for custom! settingOption = "BSPX", afr_v1=0,afr_v2=5,afr_value1=9,afr_value2=19,egoValueShift=0
field = "low voltage", afr_v1 settingOption = "Innovate", afr_v1=0,afr_v2=5,afr_value1=7.35,afr_value2=22.39,egoValueShift=0
field = "low value", afr_value1 settingOption = "14Point7", afr_v1=0,afr_v2=5,afr_value1=9.996,afr_value2=19.992,egoValueShift=0
field = "high voltage", afr_v2 settingOption = "PLX", afr_v1=0,afr_v2=5,afr_value1=10,afr_value2=20,egoValueShift=0
field = "high value", afr_value2
field = "Low voltage", afr_v1
field = "Low AFR", afr_value1
field = "High voltage", afr_v2
field = "High AFR", afr_value2
field = "Correction", egoValueShift field = "Correction", egoValueShift
dialog = egoSettings_IO1, "EGO Sensor 1 I/O" dialog = egoSettings_IO1, "EGO Sensor 1 I/O"

View File

@ -214,10 +214,22 @@ TEST(SensorInit, Clt) {
TEST(SensorInit, Lambda) { TEST(SensorInit, Lambda) {
EngineTestHelper eth(TEST_ENGINE); EngineTestHelper eth(TEST_ENGINE);
// No channel -> no sensor
initLambda(); initLambda();
EXPECT_EQ(nullptr, Sensor::getSensorOfType(SensorType::Lambda1));
EXPECT_EQ(nullptr, Sensor::getSensorOfType(SensorType::Lambda2));
auto s = Sensor::getSensorOfType(SensorType::Lambda1); // Channel -> sensor
ASSERT_NE(nullptr, s); engineConfiguration->afr.hwChannel = EFI_ADC_0;
initLambda();
EXPECT_NE(nullptr, Sensor::getSensorOfType(SensorType::Lambda1));
EXPECT_EQ(nullptr, Sensor::getSensorOfType(SensorType::Lambda2));
// Channel 2 -> sensor 2
engineConfiguration->afr.hwChannel2 = EFI_ADC_1;
initLambda();
EXPECT_NE(nullptr, Sensor::getSensorOfType(SensorType::Lambda1));
EXPECT_NE(nullptr, Sensor::getSensorOfType(SensorType::Lambda2));
} }
TEST(SensorInit, Map) { TEST(SensorInit, Map) {