rusEFI
The most advanced open source ECU
init_tps.cpp
Go to the documentation of this file.
1 #include "pch.h"
2 
3 #include "adc_subscription.h"
4 #include "functional_sensor.h"
5 #include "redundant_sensor.h"
6 #include "redundant_ford_tps.h"
7 #include "proxy_sensor.h"
8 #include "linear_func.h"
9 #include "tps.h"
10 #include "auto_generated_sensor.h"
11 #include "defaults.h"
12 
13 struct TpsConfig {
14  adc_channel_e channel;
15  float closed;
16  float open;
17  float min;
18  float max;
19 };
20 
21 class FuncSensPair {
22 public:
23 AdcSubscriptionEntry *adc = nullptr;
24  FuncSensPair(float divideInput, SensorType type)
25  : m_func(divideInput)
26  , m_sens(type, MS2NT(10))
27  {
28  m_sens.setFunction(m_func);
29  }
30 
31  bool init(const TpsConfig& cfg) {
32  // If the configuration was invalid, don't continue to configure the sensor
33  if (!configure(cfg)) {
34  return false;
35  }
36 
37  adc = AdcSubscription::SubscribeSensor(m_sens, cfg.channel, /*lowpassCutoffHz*/ 200);
38 
39  return m_sens.Register();
40  }
41 
42  void deinit() {
44  }
45 
46  SensorType type() const {
47  return m_sens.type();
48  }
49 
50  const char* name() const {
51  return m_sens.getSensorName();
52  }
53 
54 private:
55  bool configure(const TpsConfig& cfg) {
56  // Only configure if we have a channel
57  if (!isAdcChannelValid(cfg.channel)) {
58 #if EFI_UNIT_TEST
59  printf("Configured NO hardware %s\n", name());
60 #endif
61  return false;
62  }
63 
64  float scaledClosed = cfg.closed / m_func.getDivideInput();
65  float scaledOpen = cfg.open / m_func.getDivideInput();
66 
67  float split = absF(scaledOpen - scaledClosed);
68 
69  // If the voltage for closed vs. open is very near, something is wrong with your calibration
70  if (split < 0.5f) {
71  firmwareError(ObdCode::OBD_TPS_Configuration, "\"%s\" problem: open %.2f/closed %.2f cal values are too close together. Check your calibration and wiring!", name(),
72  cfg.open,
73  cfg.closed);
74  return false;
75  }
76 
77  m_func.configure(
78  cfg.closed, 0,
79  cfg.open, POSITION_FULLY_OPEN,
80  cfg.min, cfg.max
81  );
82 
83 #if EFI_UNIT_TEST
84  printf("Configured YES %s\n", name());
85 #endif
86  return true;
87  }
88 
89  LinearFunc m_func;
90  FunctionalSensor m_sens;
91 };
92 
93 struct RedundantPair {
94 public:
95  RedundantPair(FuncSensPair& pri, FuncSensPair& sec, SensorType outputType)
96  : m_pri(pri)
97  , m_sec(sec)
98  , m_redund(outputType, m_pri.type(), m_sec.type())
99  {
100  }
101 
102  void init(bool isFordTps, RedundantFordTps* fordTps, float secondaryMaximum, const TpsConfig& primary, const TpsConfig& secondary, bool allowIdenticalSensors = false) {
103  bool hasFirst = m_pri.init(primary);
104  if (!hasFirst) {
105  // no input if we have no first channel
106  return;
107  }
108 
109  if (!allowIdenticalSensors) {
110  // Check that the primary and secondary aren't too close together - if so, the user may have done
111  // an unsafe thing where they wired a single sensor to both inputs. Don't do that!
112  bool hasBothSensors = isAdcChannelValid(primary.channel) && isAdcChannelValid(secondary.channel);
113  bool tooCloseClosed = absF(primary.closed - secondary.closed) < 0.2f;
114  bool tooCloseOpen = absF(primary.open - secondary.open) < 0.2f;
115 
116  if (hasBothSensors && tooCloseClosed && tooCloseOpen) {
117  firmwareError(ObdCode::OBD_TPS_Configuration, "Configuration for redundant pair %s/%s are too similar - did you wire one sensor to both inputs...?", m_pri.name(), m_sec.name());
118  return;
119  }
120  }
121 
122  bool hasSecond = m_sec.init(secondary);
123 
124  if (engineConfiguration->etbSplit <= 0 || engineConfiguration->etbSplit > MAX_TPS_PPS_DISCREPANCY) {
125  engineConfiguration->etbSplit = MAX_TPS_PPS_DISCREPANCY;
126  }
127 
128  if (isFordTps && fordTps) {
129  // we have a secondary
130  fordTps->configure(engineConfiguration->etbSplit, secondaryMaximum);
131  fordTps->Register();
132  } else {
133  // not ford TPS
134  m_redund.configure(engineConfiguration->etbSplit, !hasSecond);
135 #if EFI_UNIT_TEST
136 printf("init m_redund.Register() %s\n", getSensorType(m_redund.type()));
137 #endif
138  m_redund.Register();
139  }
140  }
141 
142  void deinit(bool isFordTps, RedundantFordTps* fordTps) {
143  m_pri.deinit();
144  m_sec.deinit();
145 
146  if (isFordTps && fordTps) {
147  fordTps->unregister();
148  } else {
149  m_redund.unregister();
150  }
151 
152  }
153 
154  void updateUnfilteredRawValues() {
155  engine->outputChannels.rawRawPpsPrimary = m_pri.adc == nullptr ? 0 : m_pri.adc->sensorVolts;
156  engine->outputChannels.rawRawPpsSecondary = m_sec.adc == nullptr ? 0 : m_sec.adc->sensorVolts;
157  }
158 
159 private:
160  FuncSensPair& m_pri;
161  FuncSensPair& m_sec;
162 
163  RedundantSensor m_redund;
164 };
165 
166 static FuncSensPair tps1p(TPS_TS_CONVERSION, SensorType::Tps1Primary);
167 static FuncSensPair tps1s(TPS_TS_CONVERSION, SensorType::Tps1Secondary);
168 static FuncSensPair tps2p(TPS_TS_CONVERSION, SensorType::Tps2Primary);
169 static FuncSensPair tps2s(TPS_TS_CONVERSION, SensorType::Tps2Secondary);
170 
171 // Used in case of "normal", non-Ford ETB TPS
172 static RedundantPair analogTps1(tps1p, tps1s, SensorType::Tps1);
173 static RedundantPair tps2(tps2p, tps2s, SensorType::Tps2);
174 
176 
177 // Used only in case of weird Ford-style ETB TPS
181 
182 // Pedal sensors and redundancy
186 
188  pedal.updateUnfilteredRawValues();
189 }
190 
191 // This sensor indicates the driver's throttle intent - Pedal if we have one, TPS if not.
193 
194 // These sensors are TPS-like, so handle them in here too
195 static FuncSensPair wastegate(PACK_MULT_VOLTAGE, SensorType::WastegatePosition);
196 static FuncSensPair idlePos(PACK_MULT_VOLTAGE, SensorType::IdlePosition);
197 
200 }
201 
202 void initTps() {
203  criticalAssertVoid(engineConfiguration != nullptr, "null engineConfiguration");
206 
208  bool isFordTps = engineConfiguration->useFordRedundantTps;
209  bool isFordPps = engineConfiguration->useFordRedundantPps;
210 
211  float tpsSecondaryMaximum = engineConfiguration->tpsSecondaryMaximum;
212  if (tpsSecondaryMaximum < 20) {
213  // don't allow <20% split point
214  tpsSecondaryMaximum = 20;
215  }
216 
217 
218  if (isDigitalTps1()) {
219  sentTps.Register();
220  } else {
221  analogTps1.init(isFordTps, &fordTps1, tpsSecondaryMaximum,
222  { engineConfiguration->tps1_1AdcChannel, (float)engineConfiguration->tpsMin, (float)engineConfiguration->tpsMax, minTpsPps, maxTpsPps },
224  );
225  }
226 
227  tps2.init(isFordTps, &fordTps2, tpsSecondaryMaximum,
228  { engineConfiguration->tps2_1AdcChannel, (float)engineConfiguration->tps2Min, (float)engineConfiguration->tps2Max, minTpsPps, maxTpsPps },
230  );
231 
232  float ppsSecondaryMaximum = engineConfiguration->ppsSecondaryMaximum;
233  if (ppsSecondaryMaximum < 20) {
234  // don't allow <20% split point
235  ppsSecondaryMaximum = 20;
236  }
237 
238  // Pedal sensors
239  pedal.init(isFordPps, &fordPps, ppsSecondaryMaximum,
243  );
244 
245  // TPS-like stuff that isn't actually a TPS
248  }
249 
250  // Route the pedal or TPS to driverIntent as appropriate
253  } else {
255  }
256 
258 }
259 
260 void deinitTps() {
261  bool isFordTps = activeConfiguration.useFordRedundantTps;
262  bool isFordPps = activeConfiguration.useFordRedundantPps;
263 
264  analogTps1.deinit(isFordTps, &fordTps1);
265  tps2.deinit(isFordTps, &fordTps2);
266  pedal.deinit(isFordPps, &fordPps);
267 
269 
270  wastegate.deinit();
271  idlePos.deinit();
272 }
bool isAdcChannelValid(adc_channel_e hwChannel)
Definition: adc_inputs.h:20
const char * getSensorType(SensorType value)
beuint16_t adc[4]
static void UnsubscribeSensor(FunctionalSensor &sensor)
static AdcSubscriptionEntry * SubscribeSensor(FunctionalSensor &sensor, adc_channel_e channel, float lowpassCutoffHZ, float voltsPerAdcVolt=0.0f)
TunerStudioOutputChannels outputChannels
Definition: engine.h:96
Class for sensors that convert from some raw floating point value (ex: voltage, frequency,...
void setProxiedSensor(SensorType proxiedSensor)
Definition: proxy_sensor.h:20
void configure(float maxDifference, float secondaryMaximum)
bool Register()
Definition: sensor.cpp:131
void unregister()
Definition: sensor.cpp:135
adc_channel_e
engine_configuration_s & activeConfiguration
Engine * engine
void firmwareError(ObdCode code, const char *fmt,...)
void updateUnfilteredRawPedal()
Definition: init_tps.cpp:187
void initTps()
Definition: init_tps.cpp:202
bool isDigitalTps1()
Definition: init_tps.cpp:198
static RedundantFordTps fordPps(SensorType::AcceleratorPedal, SensorType::AcceleratorPedalPrimary, SensorType::AcceleratorPedalSecondary)
static RedundantFordTps fordTps1(SensorType::Tps1, SensorType::Tps1Primary, SensorType::Tps1Secondary)
static FuncSensPair tps1s(TPS_TS_CONVERSION, SensorType::Tps1Secondary)
static RedundantPair tps2(tps2p, tps2s, SensorType::Tps2)
static RedundantPair pedal(pedalPrimary, pedalSecondary, SensorType::AcceleratorPedal)
static FuncSensPair tps2s(TPS_TS_CONVERSION, SensorType::Tps2Secondary)
static FuncSensPair tps1p(TPS_TS_CONVERSION, SensorType::Tps1Primary)
static FuncSensPair idlePos(PACK_MULT_VOLTAGE, SensorType::IdlePosition)
static RedundantPair analogTps1(tps1p, tps1s, SensorType::Tps1)
static FuncSensPair tps2p(TPS_TS_CONVERSION, SensorType::Tps2Primary)
void deinitTps()
Definition: init_tps.cpp:260
static ProxySensor driverIntent(SensorType::DriverThrottleIntent)
static FuncSensPair pedalSecondary(1, SensorType::AcceleratorPedalSecondary)
static FuncSensPair wastegate(PACK_MULT_VOLTAGE, SensorType::WastegatePosition)
SentTps sentTps
Definition: init_tps.cpp:175
static FuncSensPair pedalPrimary(1, SensorType::AcceleratorPedalPrimary)
static RedundantFordTps fordTps2(SensorType::Tps2, SensorType::Tps2Primary, SensorType::Tps2Secondary)
@ OBD_TPS_Configuration
engine_configuration_s * engineConfiguration
bool isBrainPinValid(brain_pin_e brainPin)
A sensor to duplicate a sensor to an additional SensorType.
float percent_t
Definition: rusefi_types.h:73
SensorType
Definition: sensor_type.h:18
@ AcceleratorPedalPrimary
@ AcceleratorPedalSecondary
@ DriverThrottleIntent
Definition: tps.h:25
printf("\n")