rusEFI
The most advanced open source ECU
sensor_checker.cpp
Go to the documentation of this file.
1 #include "pch.h"
2 
3 // Decode what OBD code we should use for a particular [sensor, code] problem
4 static ObdCode getCode(SensorType type, UnexpectedCode code) {
5  switch (type) {
6  case SensorType::Tps1:
8  switch (code) {
9  case UnexpectedCode::Timeout: return ObdCode::OBD_TPS1_Primary_Timeout;
10  case UnexpectedCode::Low: return ObdCode::OBD_TPS1_Primary_Low;
11  case UnexpectedCode::High: return ObdCode::OBD_TPS1_Primary_High;
12  case UnexpectedCode::Inconsistent: return ObdCode::OBD_TPS1_Correlation;
13  default: break;
14  } break;
16  switch (code) {
17  case UnexpectedCode::Timeout: return ObdCode::OBD_TPS1_Secondary_Timeout;
18  case UnexpectedCode::Low: return ObdCode::OBD_TPS1_Secondary_Low;
19  case UnexpectedCode::High: return ObdCode::OBD_TPS1_Secondary_High;
20  default: break;
21  } break;
22  case SensorType::Tps2:
24  switch (code) {
25  case UnexpectedCode::Timeout: return ObdCode::OBD_TPS2_Primary_Timeout;
26  case UnexpectedCode::Low: return ObdCode::OBD_TPS2_Primary_Low;
27  case UnexpectedCode::High: return ObdCode::OBD_TPS2_Primary_High;
28  case UnexpectedCode::Inconsistent: return ObdCode::OBD_TPS2_Correlation;
29  default: break;
30  } break;
32  switch (code) {
33  case UnexpectedCode::Timeout: return ObdCode::OBD_TPS2_Secondary_Timeout;
34  case UnexpectedCode::Low: return ObdCode::OBD_TPS2_Secondary_Low;
35  case UnexpectedCode::High: return ObdCode::OBD_TPS2_Secondary_High;
36  default: break;
37  } break;
38 
41  switch (code) {
42  case UnexpectedCode::Timeout: return ObdCode::OBD_PPS_Primary_Timeout;
43  case UnexpectedCode::Low: return ObdCode::OBD_PPS_Primary_Low;
44  case UnexpectedCode::High: return ObdCode::OBD_PPS_Primary_High;
45  case UnexpectedCode::Inconsistent: return ObdCode::OBD_PPS_Correlation;
46  default: break;
47  } break;
49  switch (code) {
50  case UnexpectedCode::Timeout: return ObdCode::OBD_PPS_Secondary_Timeout;
51  case UnexpectedCode::Low: return ObdCode::OBD_PPS_Secondary_Low;
52  case UnexpectedCode::High: return ObdCode::OBD_PPS_Secondary_High;
53  default: break;
54  } break;
55 
56  case SensorType::Map:
57  switch (code) {
58  case UnexpectedCode::Timeout: return ObdCode::OBD_Map_Timeout;
59  case UnexpectedCode::Low: return ObdCode::OBD_Map_Low;
60  case UnexpectedCode::High: return ObdCode::OBD_Map_High;
61  default: break;
62  } break;
63  case SensorType::Clt:
64  switch (code) {
65  case UnexpectedCode::Timeout: return ObdCode::OBD_Clt_Timeout;
66  case UnexpectedCode::Low: return ObdCode::OBD_Clt_Low;
67  case UnexpectedCode::High: return ObdCode::OBD_Clt_High;
68  default: break;
69  } break;
70  case SensorType::Iat:
71  switch (code) {
72  case UnexpectedCode::Timeout: return ObdCode::OBD_Iat_Timeout;
73  case UnexpectedCode::Low: return ObdCode::OBD_Iat_Low;
74  case UnexpectedCode::High: return ObdCode::OBD_Iat_High;
75  default: break;
76  } break;
78  switch (code) {
79  case UnexpectedCode::Timeout: return ObdCode::OBD_FlexSensor_Timeout;
80  case UnexpectedCode::Low: return ObdCode::OBD_FlexSensor_Low;
81  case UnexpectedCode::High: return ObdCode::OBD_FlexSensor_High;
82  default: break;
83  } break;
84  default:
85  break;
86  }
87 
88  return ObdCode::None;
89 }
90 
91 inline const char* describeUnexpected(UnexpectedCode code) {
92  switch (code) {
93  case UnexpectedCode::Timeout: return "has timed out";
94  case UnexpectedCode::High: return "input too high";
95  case UnexpectedCode::Low: return "input too low";
96  case UnexpectedCode::Inconsistent: return "is inconsistent";
97  case UnexpectedCode::Configuration: return "is misconfigured";
98  case UnexpectedCode::Unknown:
99  default:
100  return "unknown";
101  }
102 }
103 
104 static void check(SensorType type) {
105  // Don't check sensors we don't have
106  if (!Sensor::hasSensor(type)) {
107  return;
108  }
109 
110  auto result = Sensor::get(type);
111 
112  // If the sensor is OK, nothing to check.
113  if (result) {
114  return;
115  }
116 
117  ObdCode code = getCode(type, result.Code);
118 
119  if (code != ObdCode::None) {
120  warning(code, "Sensor fault: %s %s", Sensor::getSensorName(type), describeUnexpected(result.Code));
121  }
122 }
123 
124 #if BOARD_EXT_GPIOCHIPS > 0 && EFI_PROD_CODE
125 #if EFI_ENGINE_CONTROL
127  if (idx < 0 || idx >= MAX_CYLINDER_COUNT) {
128  return ObdCode::None;
129  }
130 
131  if ((diag & PIN_OPEN) || (diag & PIN_SHORT_TO_GND)) {
132  return (ObdCode)((int)ObdCode::OBD_Injector_Circuit_1_Low + (idx * 3));
133  } else if ((diag & PIN_SHORT_TO_BAT) || (diag & PIN_OVERLOAD)) {
134  return (ObdCode)((int)ObdCode::OBD_Injector_Circuit_1_High + (idx * 3));
135  }
136 
137  /* else common error code */
138  return (ObdCode)((int)ObdCode::OBD_Injector_Circuit_1 + idx);
139 }
140 #endif // EFI_ENGINE_CONTROL
141 
143  if (idx < 0 || idx >= MAX_CYLINDER_COUNT) {
144  return ObdCode::None;
145  }
146 
147  // TODO: do something more intelligent with `diag`?
148  UNUSED(diag);
149 
150  return (ObdCode)((int)ObdCode::OBD_Ignition_Circuit_1 + idx);
151 }
152 
153 static uint8_t getTSErrorCode(brain_pin_diag_e diag)
154 {
155  /* Error codes reported to TS:
156  * 0 - output is not used
157  * 1 - ok status/no diagnostic available (TODO: separate codes)
158  * >1 - see brain_pin_diag_e, first least significant 1-bit position + 1 *
159  * Keep in sync with outputDiagErrorList in tunerstudio.template.ini
160  * Note:
161  * diag can be combination of few errors,
162  * while we report only one error to simplify hadling on TS side
163  * find position of least significant 1-bit */
164  return __builtin_ffs(diag) + 1;
165 }
166 #endif // BOARD_EXT_GPIOCHIPS > 0 && EFI_PROD_CODE
167 
169  // Don't check when the ignition is off, or when it was just turned on (let things stabilize)
170  // TODO: also inhibit checking if we just did a flash burn, since that blocks the ECU for a few seconds.
171  bool shouldCheck = m_ignitionIsOn && m_timeSinceIgnOff.hasElapsedSec(5);
172  m_analogSensorsShouldWork = shouldCheck;
173  if (!shouldCheck) {
174  return;
175  }
176 
177  // Check sensors
184 
188 
191 
194 
196 
197 // only bother checking these if we have GPIO chips actually capable of reporting an error
198 #if BOARD_EXT_GPIOCHIPS > 0 && EFI_PROD_CODE
200  // Check injectors
201 #if EFI_ENGINE_CONTROL
202  int unhappyInjector = 0;
203  for (size_t i = 0; i < efi::size(enginePins.injectors); i++) {
205 
206  // Skip not-configured pins
207  if (!isBrainPinValid(pin.brainPin)) {
208  state->injectorDiagnostic[i] = 0;
209  continue;
210  }
211 
212  auto diag = pin.getDiag();
213  if (diag != PIN_OK && diag != PIN_UNKNOWN) {
214  unhappyInjector = 1 + i;
215  auto code = getCodeForInjector(i, diag);
216 
217  char description[32];
218  pinDiag2string(description, efi::size(description), diag);
219  warning(code, "Injector %d fault: %s", i + 1, description);
220  }
221  state->injectorDiagnostic[i] = getTSErrorCode(diag);
222  }
223  engine->fuelComputer.brokenInjector = unhappyInjector;
224  engine->fuelComputer.injectorHwIssue = (unhappyInjector != 0);
225 #endif // EFI_ENGINE_CONTROL
226 
227  // Check ignition
228  for (size_t i = 0; i < efi::size(enginePins.injectors); i++) {
230 
231  // Skip not-configured pins
232  if (!isBrainPinValid(pin.brainPin)) {
233  state->ignitorDiagnostic[i] = 0;
234  continue;
235  }
236 
237  auto diag = pin.getDiag();
238  if (diag != PIN_OK && diag != PIN_UNKNOWN) {
239  auto code = getCodeForIgnition(i, diag);
240 
241  char description[32];
242  pinDiag2string(description, efi::size(description), diag);
243  warning(code, "Ignition %d fault: %s", i + 1, description);
244  }
245  state->ignitorDiagnostic[i] = getTSErrorCode(diag);
246  }
247 #endif // BOARD_EXT_GPIOCHIPS > 0
248 }
249 
251  m_ignitionIsOn = ignitionOn;
252 
253  if (!ignitionOn) {
254  // timer keeps track of how long since the state was turned to on (ie, how long ago was it last off)
255  m_timeSinceIgnOff.reset();
256  }
257 }
uint8_t code
Definition: bluetooth.cpp:39
FuelComputer fuelComputer
Definition: engine.h:118
InjectorOutputPin injectors[MAX_CYLINDER_COUNT]
Definition: efi_gpio.h:122
IgnitionOutputPin coils[MAX_CYLINDER_COUNT]
Definition: efi_gpio.h:124
brain_pin_diag_e getDiag() const
Definition: efi_gpio.cpp:657
brain_pin_e brainPin
Definition: efi_output.h:87
virtual bool hasSensor() const
Definition: sensor.h:155
virtual SensorResult get() const =0
const char * getSensorName() const
Definition: sensor.h:144
EnginePins enginePins
Definition: efi_gpio.cpp:24
Engine * engine
bool warning(ObdCode code, const char *fmt,...)
UNUSED(samplingTimeSeconds)
ObdCode
@ OBD_Clt_Timeout
@ OBD_Map_High
@ OBD_Iat_High
@ OBD_TPS1_Secondary_High
@ OBD_TPS1_Primary_Low
@ OBD_TPS2_Secondary_Low
@ OBD_PPS_Primary_Timeout
@ OBD_TPS1_Primary_High
@ OBD_PPS_Primary_High
@ OBD_Injector_Circuit_1
@ OBD_TPS2_Secondary_High
@ OBD_TPS2_Primary_Low
@ OBD_Ignition_Circuit_1
@ OBD_TPS1_Correlation
@ OBD_PPS_Secondary_High
@ OBD_FlexSensor_High
@ OBD_TPS2_Primary_Timeout
@ OBD_TPS1_Secondary_Timeout
@ OBD_Clt_High
@ OBD_TPS2_Primary_High
@ OBD_TPS2_Correlation
@ OBD_PPS_Correlation
@ OBD_TPS1_Primary_Timeout
@ OBD_Map_Timeout
@ OBD_PPS_Secondary_Low
@ OBD_PPS_Secondary_Timeout
@ OBD_PPS_Primary_Low
@ OBD_FlexSensor_Low
@ OBD_Injector_Circuit_1_High
@ OBD_TPS1_Secondary_Low
@ OBD_TPS2_Secondary_Timeout
@ OBD_FlexSensor_Timeout
@ OBD_Iat_Timeout
@ OBD_Injector_Circuit_1_Low
void pinDiag2string(char *buffer, size_t size, brain_pin_diag_e pin_diag)
bool isBrainPinValid(brain_pin_e brainPin)
brain_pin_diag_e
Definition: rusefi_enums.h:43
static ScState state
static ObdCode getCode(SensorType type, UnexpectedCode code)
static ObdCode getCodeForIgnition(int idx, brain_pin_diag_e diag)
static ObdCode getCodeForInjector(int idx, brain_pin_diag_e diag)
static void check(SensorType type)
static uint8_t getTSErrorCode(brain_pin_diag_e diag)
const char * describeUnexpected(UnexpectedCode code)
SensorType
Definition: sensor_type.h:18
@ FuelEthanolPercent
@ AcceleratorPedalPrimary
@ AcceleratorPedalSecondary
void onSlowCallback() override
Timer m_timeSinceIgnOff
void onIgnitionStateChanged(bool ignitionOn) override
bool m_analogSensorsShouldWork
composite packet size
TunerStudioOutputChannels * getTunerStudioOutputChannels()
Definition: engine.cpp:580