diff --git a/firmware/CHANGELOG.md b/firmware/CHANGELOG.md index 457c225f35..5b034d88f8 100644 --- a/firmware/CHANGELOG.md +++ b/firmware/CHANGELOG.md @@ -30,6 +30,7 @@ Release template (copy/paste this for new release): ### Added - Log per-cylinder true ignition timing (includes trim, knock retard, etc) #76 + - Add mode for CLT/IAT sensors that are installed "high side" instead of typical "low side" #116 ### Fixed - Improved bench test resolution (more usable for testing injectors, dwell, etc) diff --git a/firmware/controllers/sensors/converters/resistance_func.cpp b/firmware/controllers/sensors/converters/resistance_func.cpp index e7d2e16e2b..a83b13fb99 100644 --- a/firmware/controllers/sensors/converters/resistance_func.cpp +++ b/firmware/controllers/sensors/converters/resistance_func.cpp @@ -4,9 +4,10 @@ #include "resistance_func.h" -void ResistanceFunc::configure(float supplyVoltage, float pullupResistor) { +void ResistanceFunc::configure(float supplyVoltage, float pullupResistor, bool isPulldown) { m_pullupResistor = pullupResistor; m_supplyVoltage = supplyVoltage; + m_isPulldown = isPulldown; } SensorResult ResistanceFunc::convert(float raw) const { @@ -20,6 +21,12 @@ SensorResult ResistanceFunc::convert(float raw) const { return UnexpectedCode::High; } + if (m_isPulldown) { + // If the sensor is on the high side (fixed resistor is pulldown), + // invert the voltage so the math comes out correctly + raw = m_supplyVoltage - raw; + } + // Voltage is in a sensible range - convert float resistance = m_pullupResistor / (m_supplyVoltage / raw - 1); diff --git a/firmware/controllers/sensors/converters/resistance_func.h b/firmware/controllers/sensors/converters/resistance_func.h index 812834c6bf..a418262ed5 100644 --- a/firmware/controllers/sensors/converters/resistance_func.h +++ b/firmware/controllers/sensors/converters/resistance_func.h @@ -12,7 +12,7 @@ class ResistanceFunc final : public SensorConverter { public: - void configure(float supplyVoltage, float pullupResistor); + void configure(float supplyVoltage, float pullupResistor, bool isPulldown); SensorResult convert(float inputValue) const override; @@ -21,4 +21,5 @@ public: private: float m_supplyVoltage = 5.0f; float m_pullupResistor = 1000.0f; + bool m_isPulldown = false; }; diff --git a/firmware/init/sensor/init_thermistors.cpp b/firmware/init/sensor/init_thermistors.cpp index f1c46c2b35..83e3a35bc4 100644 --- a/firmware/init/sensor/init_thermistors.cpp +++ b/firmware/init/sensor/init_thermistors.cpp @@ -35,7 +35,7 @@ static void validateThermistorConfig(const char *msg, thermistor_conf_s& cfg) { } static SensorConverter& configureTempSensorFunction(const char *msg, - thermistor_conf_s& cfg, FuncPair& p, bool isLinear) { + thermistor_conf_s& cfg, FuncPair& p, bool isLinear, bool isPulldown) { if (isLinear) { p.linear.configure(cfg.resistance_1, cfg.tempC_1, cfg.resistance_2, cfg.tempC_2, -50, 250); @@ -43,7 +43,7 @@ static SensorConverter& configureTempSensorFunction(const char *msg, } else /* sensor is thermistor */ { validateThermistorConfig(msg, cfg); - p.thermistor.get().configure(5.0f, cfg.bias_resistor); + p.thermistor.get().configure(5.0f, cfg.bias_resistor, isPulldown); p.thermistor.get().configure(cfg); return p.thermistor; @@ -54,21 +54,23 @@ static void configTherm(const char *msg, FunctionalSensor &sensor, FuncPair &p, ThermistorConf &config, - bool isLinear) { + bool isLinear, + bool isPulldown) { // nothing to do if no channel if (!isAdcChannelValid(config.adcChannel)) { return; } // Configure the conversion function for this sensor - sensor.setFunction(configureTempSensorFunction(msg, config.config, p, isLinear)); + sensor.setFunction(configureTempSensorFunction(msg, config.config, p, isLinear, isPulldown)); } static void configureTempSensor(const char *msg, FunctionalSensor &sensor, FuncPair &p, ThermistorConf &config, - bool isLinear) { + bool isLinear, + bool isPulldown = false) { auto channel = config.adcChannel; // Only register if we have a sensor @@ -76,7 +78,7 @@ static void configureTempSensor(const char *msg, return; } - configTherm(msg, sensor, p, config, isLinear); + configTherm(msg, sensor, p, config, isLinear, isPulldown); // Register & subscribe AdcSubscription::SubscribeSensor(sensor, channel, 2); @@ -88,13 +90,15 @@ void initThermistors() { clt, fclt, engineConfiguration->clt, - engineConfiguration->useLinearCltSensor); + engineConfiguration->useLinearCltSensor, + engineConfiguration->cltSensorPulldown); configureTempSensor("iat", iat, fiat, engineConfiguration->iat, - engineConfiguration->useLinearIatSensor); + engineConfiguration->useLinearIatSensor, + engineConfiguration->iatSensorPulldown); configureTempSensor("aux1", aux1, diff --git a/firmware/integration/rusefi_config.txt b/firmware/integration/rusefi_config.txt index 6f5b259dd8..ecc10773f2 100644 --- a/firmware/integration/rusefi_config.txt +++ b/firmware/integration/rusefi_config.txt @@ -428,7 +428,8 @@ bit usescriptTableForCanSniffingFiltering bit verboseCan,"Print all","Do not print";Print incoming and outgoing first bus CAN messages in rusEFI console bit artificialTestMisfire,"Danger Mode","No thank you";Experimental setting that will cause a misfire\nDO NOT ENABLE. bit useFordRedundantPps;On some Ford and Toyota vehicles one of the pedal sensors is not linear on the full range, i.e. in the specific range of the positions we effectively have only one sensor. - +bit cltSensorPulldown +bit iatSensorPulldown int16_t tpsMin;Closed throttle, 1 volt = 200 units;"ADC", 1, 0, 0, 1023, 0 int16_t tpsMax;Full throttle, 1 volt = 200 units;"ADC", 1, 0, 0, 1023, 0 diff --git a/firmware/tunerstudio/rusefi.input b/firmware/tunerstudio/rusefi.input index a280e57355..ec285575b8 100644 --- a/firmware/tunerstudio/rusefi.input +++ b/firmware/tunerstudio/rusefi.input @@ -4256,6 +4256,8 @@ dialog = tcuControls, "Transmission Settings" field = "Ford redundant PPS mode", useFordRedundantPps field = "Secondary PPS maximum", ppsSecondaryMaximum, {useFordRedundantPps} field = "ADC vRef voltage", adcVcc + field = "CLT sensor is pulldown instead of pullup", cltSensorPulldown + field = "IAT sensor is pulldown instead of pullup", iatSensorPulldown field = "Analog divider ratio", analogInputDividerCoefficient@@if_ts_show_analog_divider field = "Artificial Misfire", artificialTestMisfire field = "Instant Rpm Range", instantRpmRange diff --git a/unit_tests/tests/sensor/resist_func.cpp b/unit_tests/tests/sensor/resist_func.cpp index 66ceb34290..f9e5088a88 100644 --- a/unit_tests/tests/sensor/resist_func.cpp +++ b/unit_tests/tests/sensor/resist_func.cpp @@ -9,7 +9,7 @@ TEST(resistance, OutOfRange) { ResistanceFunc f; - f.configure(5, 10000); + f.configure(5, 10000, false); // Something in the middle should be valid { @@ -45,7 +45,7 @@ TEST(resistance, OutOfRange) TEST(resistance, InRange) { ResistanceFunc f; - f.configure(5, 10000); + f.configure(5, 10000, false); // 1 volt -> 2500 ohms low side { @@ -76,3 +76,38 @@ TEST(resistance, InRange) EXPECT_FLOAT_EQ(r.Value, 40000); } } + +TEST(resistance, PulldownMode) +{ + ResistanceFunc f; + f.configure(5, 10000, true); + + // 4 volt -> 2500 ohms high side + { + auto r = f.convert(4.0f); + EXPECT_TRUE(r.Valid); + EXPECT_FLOAT_EQ(r.Value, 2500); + } + + // 3 volt -> 6666.667 ohm ohms high side + // 20k/3 gives us an exact result + { + auto r = f.convert(3.0f); + EXPECT_TRUE(r.Valid); + EXPECT_FLOAT_EQ(r.Value, 20000.0f / 3); + } + + // 2 volt -> 15000 ohms high side + { + auto r = f.convert(2.0f); + EXPECT_TRUE(r.Valid); + EXPECT_FLOAT_EQ(r.Value, 15000); + } + + // 1 volt -> 40000 ohms high side + { + auto r = f.convert(1.0f); + EXPECT_TRUE(r.Valid); + EXPECT_FLOAT_EQ(r.Value, 40000); + } +}