2015-12-31 13:02:30 -08:00
|
|
|
/**
|
2020-01-07 21:02:40 -08:00
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
2015-12-31 13:02:30 -08:00
|
|
|
*/
|
2017-11-24 16:16:00 -08:00
|
|
|
#include "engine.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
#include "tps.h"
|
|
|
|
#include "interpolation.h"
|
2019-09-19 22:06:15 -07:00
|
|
|
#include "adc_inputs.h"
|
2019-04-29 22:21:09 -07:00
|
|
|
#if EFI_PROD_CODE
|
|
|
|
#include "settings.h"
|
|
|
|
#endif /* EFI_PROD_CODE */
|
2015-07-10 06:01:56 -07:00
|
|
|
|
2019-04-29 22:21:09 -07:00
|
|
|
EXTERN_ENGINE;
|
2017-11-16 11:44:53 -08:00
|
|
|
|
2019-05-27 11:21:12 -07:00
|
|
|
#if !EFI_PROD_CODE
|
2017-11-16 07:29:40 -08:00
|
|
|
/**
|
|
|
|
* this allows unit tests to simulate TPS position
|
|
|
|
*/
|
2019-05-27 12:56:12 -07:00
|
|
|
void setMockTpsAdc(percent_t tpsPosition DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
2020-02-01 13:41:07 -08:00
|
|
|
engine->mockTpsAdcValue = tpsPosition;
|
2017-11-16 07:29:40 -08:00
|
|
|
}
|
|
|
|
|
2019-05-27 12:56:12 -07:00
|
|
|
void setMockTpsValue(percent_t tpsPosition DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
|
|
|
engine->mockTpsValue = tpsPosition;
|
2019-05-27 11:21:12 -07:00
|
|
|
}
|
|
|
|
#endif /* EFI_PROD_CODE */
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* We are using one instance for read and another for modification, this is how we get lock-free thread-safety
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
static tps_roc_s states[2];
|
|
|
|
|
2016-01-31 18:02:03 -08:00
|
|
|
// todo if TPS_FAST_ADC
|
|
|
|
//int tpsFastAdc = 0;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
static volatile int tpsRocIndex = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* this method is lock-free thread-safe if invoked only from one thread
|
|
|
|
*/
|
2016-02-04 11:01:38 -08:00
|
|
|
void saveTpsState(efitimeus_t now, float curValue) {
|
2015-07-10 06:01:56 -07:00
|
|
|
int tpsNextIndex = (tpsRocIndex + 1) % 2;
|
|
|
|
tps_roc_s *cur = &states[tpsRocIndex];
|
|
|
|
tps_roc_s *next = &states[tpsNextIndex];
|
|
|
|
|
|
|
|
next->prevTime = cur->curTime;
|
|
|
|
next->prevValue = cur->curValue;
|
|
|
|
next->curTime = now;
|
|
|
|
next->curValue = curValue;
|
|
|
|
|
2019-02-21 02:44:45 -08:00
|
|
|
//int diffSysticks = overflowDiff(now, cur->curTime);
|
2016-02-04 11:01:38 -08:00
|
|
|
float diffSeconds = 0;// TODO: do we need this? diffSysticks * 1.0 / CH_FREQUENCY;
|
2015-07-10 06:01:56 -07:00
|
|
|
next->rateOfChange = (curValue - cur->curValue) / diffSeconds;
|
|
|
|
|
|
|
|
// here we update volatile index
|
|
|
|
tpsRocIndex = tpsNextIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* this read-only method is lock-free thread-safe
|
|
|
|
*/
|
|
|
|
float getTpsRateOfChange(void) {
|
|
|
|
return states[tpsRocIndex].rateOfChange;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return current TPS position based on configured ADC levels, and adc
|
|
|
|
*
|
|
|
|
* */
|
2020-02-01 13:41:07 -08:00
|
|
|
percent_t getTpsValue(int index, float adc DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
2019-06-17 18:37:11 -07:00
|
|
|
|
2019-09-01 10:56:46 -07:00
|
|
|
DISPLAY_STATE(Engine)
|
2019-06-27 03:47:13 -07:00
|
|
|
DISPLAY_TAG(TPS_SECTION);
|
2019-06-30 10:24:55 -07:00
|
|
|
DISPLAY_SENSOR(TPS)
|
|
|
|
DISPLAY_TEXT(EOL)
|
|
|
|
|
2019-06-27 03:47:13 -07:00
|
|
|
|
2019-06-17 18:37:11 -07:00
|
|
|
DISPLAY_TEXT(Analog_MCU_reads);
|
|
|
|
engine->engineState.currentTpsAdc = adc;
|
|
|
|
#if !EFI_UNIT_TEST
|
|
|
|
engine->engineState.DISPLAY_FIELD(tpsVoltageMCU) = adcToVolts(adc);
|
|
|
|
#endif
|
2019-06-17 19:00:34 -07:00
|
|
|
DISPLAY_TEXT(Volts);
|
2019-06-30 11:28:47 -07:00
|
|
|
DISPLAY_TEXT(from_pin) DISPLAY(DISPLAY_CONFIG(tps1_1AdcChannel))
|
2019-06-17 18:37:11 -07:00
|
|
|
DISPLAY_TEXT(EOL);
|
|
|
|
|
|
|
|
DISPLAY_TEXT(Analog_ECU_reads);
|
|
|
|
engine->engineState.DISPLAY_FIELD(tpsVoltageBoard) =
|
|
|
|
DISPLAY_TEXT(Rdivider) engine->engineState.tpsVoltageMCU * CONFIG(DISPLAY_CONFIG(analogInputDividerCoefficient));
|
|
|
|
DISPLAY_TEXT(EOL);
|
|
|
|
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
if (engineConfiguration->tpsMin == engineConfiguration->tpsMax) {
|
2017-01-22 06:03:08 -08:00
|
|
|
warning(CUSTOM_INVALID_TPS_SETTING, "Invalid TPS configuration: same value %d", engineConfiguration->tpsMin);
|
2015-07-10 06:01:56 -07:00
|
|
|
return NAN;
|
|
|
|
}
|
2019-06-17 18:37:11 -07:00
|
|
|
|
|
|
|
DISPLAY_TEXT(Current_ADC)
|
|
|
|
DISPLAY(DISPLAY_FIELD(currentTpsAdc))
|
|
|
|
DISPLAY_TEXT(interpolate_between)
|
2019-12-09 21:07:46 -08:00
|
|
|
|
|
|
|
DISPLAY(DISPLAY_CONFIG(tpsMax))
|
|
|
|
DISPLAY_TEXT(and)
|
|
|
|
DISPLAY(DISPLAY_CONFIG(tpsMin))
|
|
|
|
|
|
|
|
int tpsMax = index == 0 ? CONFIG(tpsMax) : CONFIG(tps2Max);
|
|
|
|
int tpsMin = index == 0 ? CONFIG(tpsMin) : CONFIG(tps2Min);
|
|
|
|
|
2020-03-24 17:22:01 -07:00
|
|
|
const char *msg = index == 0 ? "TPS1" : "TPS2";
|
|
|
|
float result = interpolateMsg(msg, tpsMax, 100, tpsMin, 0, adc);
|
2016-12-17 09:03:02 -08:00
|
|
|
if (result < engineConfiguration->tpsErrorDetectionTooLow) {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_PROD_CODE
|
2017-03-03 20:24:32 -08:00
|
|
|
// too much noise with simulator
|
2018-01-23 09:05:14 -08:00
|
|
|
warning(OBD_Throttle_Position_Sensor_Circuit_Malfunction, "TPS too low: %.2f", result);
|
2017-03-03 20:24:32 -08:00
|
|
|
#endif /* EFI_PROD_CODE */
|
2016-12-17 09:03:02 -08:00
|
|
|
}
|
|
|
|
if (result > engineConfiguration->tpsErrorDetectionTooHigh) {
|
2019-04-12 19:07:03 -07:00
|
|
|
#if EFI_PROD_CODE
|
2017-03-03 20:24:32 -08:00
|
|
|
// too much noise with simulator
|
2018-01-23 09:05:14 -08:00
|
|
|
warning(OBD_Throttle_Position_Sensor_Range_Performance_Problem, "TPS too high: %.2f", result);
|
2017-03-03 20:24:32 -08:00
|
|
|
#endif /* EFI_PROD_CODE */
|
2016-12-17 09:03:02 -08:00
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
// this would put the value into the 0-100 range
|
|
|
|
return maxF(0, minF(100, result));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return TPS ADC readings.
|
|
|
|
* We need ADC value because TunerStudio has a nice TPS configuration wizard, and this wizard
|
|
|
|
* wants a TPS value.
|
2019-12-09 21:07:46 -08:00
|
|
|
* @param index [0, ETB_COUNT)
|
2015-07-10 06:01:56 -07:00
|
|
|
*/
|
2020-02-07 18:20:14 -08:00
|
|
|
static float getTPS10bitAdc(int index DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
2015-07-10 06:01:56 -07:00
|
|
|
#if !EFI_PROD_CODE
|
2019-05-27 12:56:12 -07:00
|
|
|
if (engine->mockTpsAdcValue != MOCK_UNDEFINED) {
|
|
|
|
return engine->mockTpsAdcValue;
|
2017-11-16 07:29:40 -08:00
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
#endif
|
2019-06-30 11:28:47 -07:00
|
|
|
if (engineConfiguration->tps1_1AdcChannel == EFI_ADC_NONE)
|
2015-07-10 06:01:56 -07:00
|
|
|
return -1;
|
|
|
|
#if EFI_PROD_CODE
|
2016-01-31 18:02:03 -08:00
|
|
|
|
2019-11-29 16:06:50 -08:00
|
|
|
if (index == 0) {
|
2020-02-01 13:41:07 -08:00
|
|
|
return convertVoltageTo10bitADC(getVoltageDivided("tps10", engineConfiguration->tps1_1AdcChannel));
|
2019-11-29 16:06:50 -08:00
|
|
|
} else {
|
2020-02-01 13:41:07 -08:00
|
|
|
return convertVoltageTo10bitADC(getVoltageDivided("tps20", engineConfiguration->tps2_1AdcChannel));
|
2019-11-29 16:06:50 -08:00
|
|
|
}
|
2016-01-31 18:02:03 -08:00
|
|
|
// return tpsFastAdc / 4;
|
2015-07-10 06:01:56 -07:00
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif /* EFI_PROD_CODE */
|
|
|
|
}
|
|
|
|
|
2019-04-29 22:21:09 -07:00
|
|
|
void grabTPSIsClosed() {
|
|
|
|
#if EFI_PROD_CODE
|
2019-09-01 13:11:35 -07:00
|
|
|
printTPSInfo();
|
2020-02-01 13:41:07 -08:00
|
|
|
engineConfiguration->tpsMin = getTPS10bitAdc(0);
|
2019-04-29 22:21:09 -07:00
|
|
|
printTPSInfo();
|
|
|
|
#endif /* EFI_PROD_CODE */
|
|
|
|
}
|
|
|
|
|
|
|
|
void grabTPSIsWideOpen() {
|
|
|
|
#if EFI_PROD_CODE
|
2019-09-01 13:11:35 -07:00
|
|
|
printTPSInfo();
|
2020-02-01 13:41:07 -08:00
|
|
|
engineConfiguration->tpsMax = getTPS10bitAdc(0);
|
2019-04-29 22:21:09 -07:00
|
|
|
printTPSInfo();
|
|
|
|
#endif /* EFI_PROD_CODE */
|
|
|
|
}
|
|
|
|
|
2019-04-30 15:46:39 -07:00
|
|
|
void grabPedalIsUp() {
|
|
|
|
#if EFI_PROD_CODE
|
2019-09-22 06:56:06 -07:00
|
|
|
float voltage = getVoltageDivided("pPS", engineConfiguration->throttlePedalPositionAdcChannel PASS_ENGINE_PARAMETER_SUFFIX);
|
2019-04-30 15:46:39 -07:00
|
|
|
engineConfiguration->throttlePedalUpVoltage = voltage;
|
2019-09-02 19:58:36 -07:00
|
|
|
printTPSInfo();
|
2019-04-30 15:46:39 -07:00
|
|
|
#endif /* EFI_PROD_CODE */
|
|
|
|
}
|
|
|
|
|
|
|
|
void grabPedalIsWideOpen() {
|
|
|
|
#if EFI_PROD_CODE
|
2019-09-22 06:56:06 -07:00
|
|
|
float voltage = getVoltageDivided("pPS", engineConfiguration->throttlePedalPositionAdcChannel PASS_ENGINE_PARAMETER_SUFFIX);
|
2019-04-30 15:46:39 -07:00
|
|
|
engineConfiguration->throttlePedalWOTVoltage = voltage;
|
2019-09-02 19:58:36 -07:00
|
|
|
printTPSInfo();
|
2019-04-30 15:46:39 -07:00
|
|
|
#endif /* EFI_PROD_CODE */
|
|
|
|
}
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
/**
|
|
|
|
* @brief Position on physical primary TPS
|
|
|
|
*/
|
2019-12-09 21:07:46 -08:00
|
|
|
static percent_t getPrimaryRawTPS(int index DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
2020-02-01 13:41:07 -08:00
|
|
|
float adcValue = getTPS10bitAdc(index PASS_ENGINE_PARAMETER_SUFFIX);
|
2019-12-09 21:07:46 -08:00
|
|
|
percent_t tpsValue = getTpsValue(index, adcValue PASS_ENGINE_PARAMETER_SUFFIX);
|
2015-07-10 06:01:56 -07:00
|
|
|
return tpsValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define NO_TPS_MAGIC_VALUE 66.611
|
|
|
|
|
2020-01-09 23:02:22 -08:00
|
|
|
bool hasSecondThrottleBody(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2019-12-13 09:50:34 -08:00
|
|
|
return engineConfiguration->tps2_1AdcChannel != EFI_ADC_NONE;
|
|
|
|
}
|
|
|
|
|
2020-02-07 18:20:14 -08:00
|
|
|
static bool hasTpsSensor(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2019-06-30 11:28:47 -07:00
|
|
|
return engineConfiguration->tps1_1AdcChannel != EFI_ADC_NONE;
|
2016-12-17 08:01:40 -08:00
|
|
|
}
|
|
|
|
|
2019-11-29 16:06:50 -08:00
|
|
|
percent_t getTPSWithIndex(int index DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
2019-05-27 11:21:12 -07:00
|
|
|
#if !EFI_PROD_CODE
|
2019-05-27 12:56:12 -07:00
|
|
|
if (!cisnan(engine->mockTpsValue)) {
|
|
|
|
return engine->mockTpsValue;
|
2019-05-27 11:21:12 -07:00
|
|
|
}
|
|
|
|
#endif /* EFI_PROD_CODE */
|
2017-05-15 20:28:49 -07:00
|
|
|
if (!hasTpsSensor(PASS_ENGINE_PARAMETER_SIGNATURE))
|
2015-07-10 06:01:56 -07:00
|
|
|
return NO_TPS_MAGIC_VALUE;
|
|
|
|
// todo: if (config->isDualTps)
|
|
|
|
// todo: blah blah
|
|
|
|
// todo: if two TPS do not match - show OBD code via malfunction_central.c
|
|
|
|
|
2019-12-09 21:07:46 -08:00
|
|
|
return getPrimaryRawTPS(index PASS_ENGINE_PARAMETER_SUFFIX);
|
2019-11-29 16:06:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
percent_t getTPS(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|
|
|
return getTPSWithIndex(0 PASS_ENGINE_PARAMETER_SUFFIX);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int convertVoltageTo10bitADC(float voltage) {
|
|
|
|
// divided by 2 because of voltage divider, then converted into 10bit ADC value (TunerStudio format)
|
2020-02-01 13:41:07 -08:00
|
|
|
return (int) (voltage * TPS_TS_CONVERSION);
|
2015-07-10 06:01:56 -07:00
|
|
|
}
|