rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
electronic_throttle_impl.h
Go to the documentation of this file.
1/**
2 * @file electronic_throttle_impl.h
3 *
4 * @date Dec 7, 2013
5 * @author Andrey Belomutskiy, (c) 2012-2020
6 */
7
8#pragma once
9
10// include the "public" ETB interface
11#include "electronic_throttle.h"
12
13#include "sensor.h"
14#include "efi_pid.h"
15#include "error_accumulator.h"
18
19/**
20 * Hard code ETB update speed.
21 * Since this is a safety critical system with no real reason for a user to ever need to change the update rate,
22 * it's locked to 500hz, along with the ADC.
23 * https://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem
24 */
25#define ETB_LOOP_FREQUENCY 500
26#define DEFAULT_ETB_PWM_FREQUENCY 800
27
29public:
30 bool init(dc_function_e function, DcMotor *motor, pid_s *pidParameters, const ValueProvider3D* pedalMap) override;
31 void setIdlePosition(percent_t pos) override;
32 void setWastegatePosition(percent_t pos) override;
33 void reset(const char *reason) override;
34
35 // Update the controller's state: read sensors, send output, etc
36 void update() override;
37
38 // Called when the configuration may have changed. Controller will
39 // reset if necessary.
40 void onConfigurationChange(pid_s* previousConfiguration);
41
42 // Print this throttle's status.
43 void showStatus();
44
45 // Helpers for individual parts of throttle control
46 expected<percent_t> observePlant() override;
47
48 expected<percent_t> getSetpoint() override;
49 expected<percent_t> getSetpointEtb();
50 expected<percent_t> getSetpointWastegate() const;
51 expected<percent_t> getSetpointIdleValve() const;
52
53 expected<percent_t> getOpenLoop(percent_t target) override;
54 expected<percent_t> getClosedLoop(percent_t setpoint, percent_t observation) override;
55 expected<percent_t> getClosedLoopAutotune(percent_t setpoint, percent_t actualThrottlePosition);
56
58
59 void checkJam(percent_t setpoint, percent_t observation);
60
61 void setOutput(expected<percent_t> outputValue) override;
62
63 // Used to inspect the internal PID controller's state
64 const pid_state_s& getPidState() const override { return m_pid; };
65
66 // Override if this throttle needs special per-throttle adjustment (bank-to-bank trim, for example)
67 virtual percent_t getThrottleTrim(float /*rpm*/, percent_t /*targetPosition*/) const {
68 return 0;
69 }
70
71 // pedal-based part of ETB target, without idle and other interventions
72 float getCurrentTarget() const override {
73 return etbCurrentTarget;
74 }
75
76 bool isEtbMode() const override {
77 return m_function == DC_Throttle1 || m_function == DC_Throttle2;
78 }
79
80 // Lua throttle adjustment
81 void setLuaAdjustment(percent_t adjustment) override;
82 float getLuaAdjustment() const;
83
84 float prevOutput = 0;
85
86protected:
87 bool hadTpsError = false;
88 bool hadPpsError = false;
89
90 DcMotor* getMotor() { return m_motor; }
91
92private:
95 DcMotor *m_motor = nullptr;
97 bool m_shouldResetPid = false;
98
100
101 /**
102 * @return true if OK, false if should be disabled
103 */
104 bool checkStatus();
105
107
108 // Pedal -> target map
110
111 float m_idlePosition = 0;
112
113 // This is set if automatic PID cal should be run
114 bool m_isAutotune = false;
115
116 // Autotune helpers
117 bool m_lastIsPositive = false;
119 float m_minCycleTps = 0;
120 float m_maxCycleTps = 0;
121 // Autotune measured parameters: gain and ultimate period
122 // These are set to correct order of magnitude starting points
123 // so we converge more quickly on the correct values
124 float m_a = 8;
125 float m_tu = 0.1f;
126
127#if EFI_TUNER_STUDIO
128 uint8_t m_autotuneCounter = 0;
130#endif
131
133
134 efitimeus_t lastTickUs;
135};
136
137void etbPidReset();
138
139class EtbController1 : public EtbController { };
140
142public:
147
148 percent_t getThrottleTrim(float rpm, percent_t /*targetPosition*/) const override;
149
150private:
152};
153
154template <typename TBase>
155class EtbImpl final : public TBase {
156private:
157 enum class ACPhase {
158 Stopped,
159
160 Start,
161
162 // Drive the motor open
163 Open,
164
165 // Drive the motor closed
166 Close,
167
168 // Write learned values to TS
173 };
174
175public:
176 template <typename... TArgs>
177 EtbImpl(TArgs&&... args) : TBase(std::forward<TArgs>(args)...) { }
178
179 void update() override {
180#if EFI_TUNER_STUDIO
182 ACPhase nextPhase = doAutocal(m_autocalPhase);
183
184 // if we changed phase, reset the phase timer
185 if (m_autocalPhase != nextPhase) {
186 m_autocalTimer.reset();
187 m_autocalPhase = nextPhase;
188 }
189 } else
190#endif /* EFI_TUNER_STUDIO */
191
192 {
193 TBase::update();
194 }
195 }
196
197 void autoCalibrateTps(bool reportToTs) override {
198 // Only auto calibrate throttles
199 if (TBase::getFunction() == DC_Throttle1 || TBase::getFunction() == DC_Throttle2 || TBase::getFunction() == DC_Wastegate) {
200 m_isAutocalTs = reportToTs;
202 }
203 }
204
206 // Don't allow if engine is running!
208 efiPrintf(" ****************** ERROR: Not while RPM ********************");
209 return ACPhase::Stopped;
210 }
211
212 auto motor = TBase::getMotor();
213 if (!motor) {
214 efiPrintf(" ****************** ERROR: No DC motor ********************");
215 return ACPhase::Stopped;
216 }
217
218 TBase::etbErrorCode = (uint8_t)EtbStatus::AutoCalibrate;
219
220 auto myFunction = TBase::getFunction();
221
222 switch (phase) {
223 case ACPhase::Start:
224 // Open the throttle
225 motor->set(0.5f);
226 motor->enable();
227 return ACPhase::Open;
228 case ACPhase::Open:
229 if (m_autocalTimer.hasElapsedMs(1000)) {
230 // Capture open position
233
234 // Next: close the throttle
235 motor->set(-0.5f);
236 return ACPhase::Close;
237 }
238 break;
239 case ACPhase::Close:
240 if (m_autocalTimer.hasElapsedMs(1000)) {
241 // Capture closed position
244
245 // Disable the motor, we're done
246 motor->disable("autotune");
247
248 // Check that the calibrate actually moved the throttle
249 if (std::abs(m_primaryMax - m_primaryMin) < 0.5f) {
250 firmwareError(ObdCode::OBD_TPS_Configuration, "Auto calibrate failed, check your wiring!\r\nClosed voltage: %.1fv Open voltage: %.1fv", m_primaryMin, m_primaryMax);
251 return ACPhase::Stopped;
252 }
253
254 if (!m_isAutocalTs) {
255 if (myFunction == DC_Throttle1) {
260 } else if (myFunction == DC_Throttle2) {
265 } else if (myFunction == DC_Wastegate) {
268 } else {
269 /* TODO */
270 }
271 return ACPhase::Stopped;
272 }
273
274 // Next: start transmitting results
277 }
278 break;
280 if (tsCalibrationIsIdle()) {
283 }
284 break;
286 if (tsCalibrationIsIdle()) {
288 // No secondary sensor?
290 return ACPhase::Stopped;
292 }
293 break;
295 if (tsCalibrationIsIdle()) {
298 }
299 break;
301 if (tsCalibrationIsIdle()) {
302 // Done!
303 return ACPhase::Stopped;
304 }
305 break;
306 case ACPhase::Stopped: break;
307 }
308
309 // by default, stay in the same phase
310 return phase;
311 }
312
313private:
316 // Report calibrated values to TS, if false - set directly to config
318
323};
324
327
328static constexpr electronic_throttle_s const* etbData1_ptr = &etb1;
329static constexpr electronic_throttle_s const* etbData2_ptr = &etb2;
330
331// To be used by LogFields, for LiveData fragments see non constexpr getLiveData() in electronic_throttle.cpp
332template<typename T, size_t idx>
333consteval electronic_throttle_s const* getLiveDataConstexpr() requires std::is_same_v<T, electronic_throttle_s> {
334#if EFI_ELECTRONIC_THROTTLE_BODY
335
336 static_assert(idx < ETB_COUNT);
337
338 if constexpr (idx == 0) {
339 return etbData1_ptr;
340 }
341
342 return etbData2_ptr;
343#else
344 return nullptr;
345#endif
346}
Brushed or brushless DC motor interface.
Definition dc_motor.h:20
const ValueProvider3D & m_throttle2Trim
percent_t getThrottleTrim(float rpm, percent_t) const override
EtbController2(const ValueProvider3D &throttle2TrimTable)
void setWastegatePosition(percent_t pos) override
float getLuaAdjustment() const
bool isEtbMode() const override
const pid_state_s & getPidState() const override
expected< percent_t > getSetpointIdleValve() const
expected< percent_t > getSetpointEtb()
void setIdlePosition(percent_t pos) override
void checkJam(percent_t setpoint, percent_t observation)
expected< percent_t > getSetpoint() override
ErrorAccumulator m_targetErrorAccumulator
virtual percent_t getThrottleTrim(float, percent_t) const
expected< percent_t > getClosedLoopAutotune(percent_t setpoint, percent_t actualThrottlePosition)
void update() override
dc_function_e getFunction() const
bool init(dc_function_e function, DcMotor *motor, pid_s *pidParameters, const ValueProvider3D *pedalMap) override
void setLuaAdjustment(percent_t adjustment) override
expected< percent_t > getClosedLoop(percent_t setpoint, percent_t observation) override
expected< percent_t > getOpenLoop(percent_t target) override
void reset(const char *reason) override
void onConfigurationChange(pid_s *previousConfiguration)
const ValueProvider3D * m_pedalProvider
expected< percent_t > observePlant() override
expected< percent_t > getSetpointWastegate() const
float getCurrentTarget() const override
void setOutput(expected< percent_t > outputValue) override
void autoCalibrateTps(bool reportToTs) override
EtbImpl(TArgs &&... args)
ACPhase doAutocal(ACPhase phase)
void update() override
Definition efi_pid.h:34
virtual float getRaw() const
Definition sensor.h:148
static float getOrZero(SensorType type)
Definition sensor.h:83
static TsCalMode functionToCalModePriMin(dc_function_e func)
static Map3D< ETB2_TRIM_SIZE, ETB2_TRIM_SIZE, int8_t, uint8_t, uint8_t > throttle2TrimTable
static TsCalMode functionToCalModeSecMin(dc_function_e func)
static SensorType functionToTpsSensorPrimary(dc_function_e func)
static TsCalMode functionToCalModePriMax(dc_function_e func)
static SensorType functionToTpsSensorSecondary(dc_function_e func)
static TsCalMode functionToCalModeSecMax(dc_function_e func)
static constexpr electronic_throttle_s const * etbData2_ptr
static constexpr electronic_throttle_s const * etbData1_ptr
consteval electronic_throttle_s const * getLiveDataConstexpr()
void etbPidReset()
EtbImpl< EtbController1 > etb1
EtbImpl< EtbController2 > etb2
static constexpr engine_configuration_s * engineConfiguration
void firmwareError(ObdCode code, const char *fmt,...)
@ OBD_TPS_Configuration
dc_function_e
float percent_t
Base class for sensors. Inherit this class to implement a new type of sensor.
SensorType
Definition sensor_type.h:18
constexpr int convertVoltageTo10bitADC(float voltage)
Definition tps.h:21
void tsCalibrationSetData(TsCalMode mode, float value, float value2, float timeoutMs)
maintainConstantValue implementation header