2015-07-10 06:01:56 -07:00
|
|
|
|
/**
|
|
|
|
|
* @file electronic_throttle.cpp
|
2019-04-24 17:47:38 -07:00
|
|
|
|
* @brief Electronic Throttle driver
|
2015-07-10 06:01:56 -07:00
|
|
|
|
*
|
2020-02-22 20:18:02 -08:00
|
|
|
|
* @see test test_etb.cpp
|
|
|
|
|
*
|
2019-12-30 07:25:52 -08:00
|
|
|
|
*
|
2020-04-29 15:41:40 -07:00
|
|
|
|
* Limited user documentation at https://github.com/rusefi/rusefi/wiki/HOWTO_electronic_throttle_body
|
2019-12-30 07:25:52 -08:00
|
|
|
|
*
|
2015-07-10 06:01:56 -07:00
|
|
|
|
* todo: make this more universal if/when we get other hardware options
|
|
|
|
|
*
|
2020-06-01 05:50:54 -07:00
|
|
|
|
* May 2020 two vehicles have driver 500 miles each
|
2019-09-07 19:16:56 -07:00
|
|
|
|
* Sep 2019 two-wire TLE9201 official driving around the block! https://www.youtube.com/watch?v=1vCeICQnbzI
|
2020-12-17 13:59:02 -08:00
|
|
|
|
* by the way 9201 does not like getting above 8khz - it starts to get warm
|
2019-09-28 06:59:40 -07:00
|
|
|
|
* May 2019 two-wire TLE7209 now behaves same as three-wire VNH2SP30 "eBay red board" on BOSCH 0280750009
|
2019-04-24 17:47:38 -07:00
|
|
|
|
* Apr 2019 two-wire TLE7209 support added
|
2019-05-05 15:09:52 -07:00
|
|
|
|
* Mar 2019 best results so far achieved with three-wire H-bridges like VNH2SP30 on BOSCH 0280750009
|
2019-02-10 16:13:04 -08:00
|
|
|
|
* Jan 2019 actually driven around the block but still need some work.
|
2017-01-27 18:04:23 -08:00
|
|
|
|
* Jan 2017 status:
|
2017-05-25 09:09:07 -07:00
|
|
|
|
* Electronic throttle body with it's spring is definitely not linear - both P and I factors of PID are required to get any results
|
2017-01-27 18:04:23 -08:00
|
|
|
|
* PID implementation tested on a bench only
|
|
|
|
|
* it is believed that more than just PID would be needed, as is this is probably
|
|
|
|
|
* not usable on a real vehicle. Needs to be tested :)
|
|
|
|
|
*
|
2019-11-18 19:25:07 -08:00
|
|
|
|
* https://raw.githubusercontent.com/wiki/rusefi/rusefi_documentation/oem_docs/VAG/Bosch_0280750009_pinout.jpg
|
2017-05-25 09:09:07 -07:00
|
|
|
|
*
|
2017-05-24 20:53:07 -07:00
|
|
|
|
* ETB is controlled according to pedal position input (pedal position sensor is a potentiometer)
|
2019-02-10 16:52:06 -08:00
|
|
|
|
* pedal 0% means pedal not pressed / idle
|
2017-05-24 20:53:07 -07:00
|
|
|
|
* pedal 100% means pedal all the way down
|
2017-05-25 09:09:07 -07:00
|
|
|
|
* (not TPS - not the one you can calibrate in TunerStudio)
|
2017-05-24 20:53:07 -07:00
|
|
|
|
*
|
|
|
|
|
*
|
2017-05-25 09:09:07 -07:00
|
|
|
|
* See also pid.cpp
|
|
|
|
|
*
|
2017-05-29 20:36:08 -07:00
|
|
|
|
* Relevant console commands:
|
|
|
|
|
*
|
2019-02-27 05:55:56 -08:00
|
|
|
|
* ETB_BENCH_ENGINE
|
|
|
|
|
* set engine_type 58
|
|
|
|
|
*
|
2017-05-29 20:36:08 -07:00
|
|
|
|
* enable verbose_etb
|
|
|
|
|
* disable verbose_etb
|
|
|
|
|
* ethinfo
|
2018-01-30 19:04:33 -08:00
|
|
|
|
* set mock_pedal_position X
|
2017-05-24 20:53:07 -07:00
|
|
|
|
*
|
2018-12-01 13:41:40 -08:00
|
|
|
|
*
|
|
|
|
|
* set debug_mode 17
|
|
|
|
|
* for PID outputs
|
|
|
|
|
*
|
2019-03-01 20:09:33 -08:00
|
|
|
|
* set etb_p X
|
|
|
|
|
* set etb_i X
|
|
|
|
|
* set etb_d X
|
2019-04-23 20:18:48 -07:00
|
|
|
|
* set etb_o X
|
2019-03-01 20:09:33 -08:00
|
|
|
|
*
|
2019-09-21 19:15:34 -07:00
|
|
|
|
* set_etb_duty X
|
2019-03-01 20:09:33 -08:00
|
|
|
|
*
|
2017-01-27 18:04:23 -08:00
|
|
|
|
* http://rusefi.com/forum/viewtopic.php?f=5&t=592
|
|
|
|
|
*
|
2015-07-10 06:01:56 -07:00
|
|
|
|
* @date Dec 7, 2013
|
2020-01-13 18:57:43 -08:00
|
|
|
|
* @author Andrey Belomutskiy, (c) 2012-2020
|
2015-07-10 06:01:56 -07:00
|
|
|
|
*
|
|
|
|
|
* This file is part of rusEfi - see http://rusefi.com
|
|
|
|
|
*
|
|
|
|
|
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
|
|
|
|
|
* the GNU General Public License as published by the Free Software Foundation; either
|
|
|
|
|
* version 3 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
|
|
|
|
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License along with this program.
|
|
|
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2018-09-16 19:26:57 -07:00
|
|
|
|
#include "global.h"
|
2019-04-09 19:52:03 -07:00
|
|
|
|
|
2019-04-12 19:07:03 -07:00
|
|
|
|
#if EFI_ELECTRONIC_THROTTLE_BODY
|
2019-04-09 19:52:03 -07:00
|
|
|
|
|
2020-12-06 22:27:27 -08:00
|
|
|
|
#include "electronic_throttle_impl.h"
|
|
|
|
|
#include "engine.h"
|
2015-07-10 06:01:56 -07:00
|
|
|
|
#include "tps.h"
|
2020-04-01 17:21:03 -07:00
|
|
|
|
#include "sensor.h"
|
2019-03-29 06:11:13 -07:00
|
|
|
|
#include "dc_motor.h"
|
2020-03-03 14:56:50 -08:00
|
|
|
|
#include "dc_motors.h"
|
2017-09-21 20:21:03 -07:00
|
|
|
|
#include "pid_auto_tune.h"
|
2019-07-05 16:00:44 -07:00
|
|
|
|
|
|
|
|
|
#if defined(HAS_OS_ACCESS)
|
|
|
|
|
#error "Unexpected OS ACCESS HERE"
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-11-21 10:35:57 -08:00
|
|
|
|
#ifndef ETB_MAX_COUNT
|
2019-07-05 16:00:44 -07:00
|
|
|
|
#define ETB_MAX_COUNT 2
|
2019-11-21 10:35:57 -08:00
|
|
|
|
#endif /* ETB_MAX_COUNT */
|
2019-07-05 16:00:44 -07:00
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
|
static LoggingWithStorage logger("ETB");
|
2020-09-10 15:44:10 -07:00
|
|
|
|
static pedal2tps_t pedal2tpsMap("Pedal2Tps");
|
2019-02-10 16:52:06 -08:00
|
|
|
|
|
2019-03-10 09:58:27 -07:00
|
|
|
|
EXTERN_ENGINE;
|
|
|
|
|
|
2019-09-22 20:28:11 -07:00
|
|
|
|
static bool startupPositionError = false;
|
|
|
|
|
|
2019-09-27 20:01:47 -07:00
|
|
|
|
#define STARTUP_NEUTRAL_POSITION_ERROR_THRESHOLD 5
|
2019-09-22 20:28:11 -07:00
|
|
|
|
|
2020-12-25 21:57:23 -08:00
|
|
|
|
static const float hardCodedetbHitachiBiasBins[8] = {0.0, 19.0, 21.0, 22.0, 23.0, 25.0, 30.0, 100.0};
|
|
|
|
|
|
|
|
|
|
static const float hardCodedetbHitachiBiasValues[8] = {-18.0, -17.0, -15.0, 0.0, 16.0, 20.0, 20.0, 20.0};
|
|
|
|
|
|
|
|
|
|
/* Generated by TS2C on Thu Aug 20 21:10:02 EDT 2020*/
|
|
|
|
|
void setHitachiEtbBiasBins(DECLARE_CONFIG_PARAMETER_SIGNATURE) {
|
|
|
|
|
MEMCPY(engineConfiguration->etbBiasBins, hardCodedetbHitachiBiasBins);
|
|
|
|
|
MEMCPY(engineConfiguration->etbBiasValues, hardCodedetbHitachiBiasValues);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-09-28 13:33:07 -07:00
|
|
|
|
static SensorType functionToPositionSensor(etb_function_e func) {
|
|
|
|
|
switch(func) {
|
|
|
|
|
case ETB_Throttle1: return SensorType::Tps1;
|
|
|
|
|
case ETB_Throttle2: return SensorType::Tps2;
|
|
|
|
|
case ETB_IdleValve: return SensorType::IdlePosition;
|
|
|
|
|
case ETB_Wastegate: return SensorType::WastegatePosition;
|
|
|
|
|
default: return SensorType::Invalid;
|
2020-04-02 18:33:49 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-28 13:33:07 -07:00
|
|
|
|
static SensorType functionToTpsSensorPrimary(etb_function_e func) {
|
|
|
|
|
switch(func) {
|
|
|
|
|
case ETB_Throttle1: return SensorType::Tps1Primary;
|
2020-05-18 11:32:00 -07:00
|
|
|
|
default: return SensorType::Tps2Primary;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-28 13:33:07 -07:00
|
|
|
|
static SensorType functionToTpsSensorSecondary(etb_function_e func) {
|
|
|
|
|
switch(func) {
|
|
|
|
|
case ETB_Throttle1: return SensorType::Tps1Secondary;
|
2020-05-18 11:32:00 -07:00
|
|
|
|
default: return SensorType::Tps2Secondary;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-23 20:46:33 -07:00
|
|
|
|
#if EFI_TUNER_STUDIO
|
2020-09-28 13:33:07 -07:00
|
|
|
|
static TsCalMode functionToCalModePriMin(etb_function_e func) {
|
|
|
|
|
switch (func) {
|
|
|
|
|
case ETB_Throttle1: return TsCalMode::Tps1Min;
|
2020-08-23 20:41:35 -07:00
|
|
|
|
default: return TsCalMode::Tps2Min;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-28 13:33:07 -07:00
|
|
|
|
static TsCalMode functionToCalModePriMax(etb_function_e func) {
|
|
|
|
|
switch (func) {
|
|
|
|
|
case ETB_Throttle1: return TsCalMode::Tps1Max;
|
2020-08-23 20:41:35 -07:00
|
|
|
|
default: return TsCalMode::Tps2Max;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-28 13:33:07 -07:00
|
|
|
|
static TsCalMode functionToCalModeSecMin(etb_function_e func) {
|
|
|
|
|
switch (func) {
|
|
|
|
|
case ETB_Throttle1: return TsCalMode::Tps1SecondaryMin;
|
2020-08-23 20:41:35 -07:00
|
|
|
|
default: return TsCalMode::Tps2SecondaryMin;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-28 13:33:07 -07:00
|
|
|
|
static TsCalMode functionToCalModeSecMax(etb_function_e func) {
|
|
|
|
|
switch (func) {
|
|
|
|
|
case ETB_Throttle1: return TsCalMode::Tps1SecondaryMax;
|
2020-08-23 20:41:35 -07:00
|
|
|
|
default: return TsCalMode::Tps2SecondaryMax;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-08-23 20:46:33 -07:00
|
|
|
|
#endif // EFI_TUNER_STUDIO
|
2020-08-23 20:41:35 -07:00
|
|
|
|
|
2019-07-12 04:48:28 -07:00
|
|
|
|
static percent_t directPwmValue = NAN;
|
2017-09-21 20:21:03 -07:00
|
|
|
|
static percent_t currentEtbDuty;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
2019-05-04 21:42:50 -07:00
|
|
|
|
#define ETB_DUTY_LIMIT 0.9
|
2019-07-12 04:48:28 -07:00
|
|
|
|
// this macro clamps both positive and negative percentages from about -100% to 100%
|
2020-04-20 10:52:20 -07:00
|
|
|
|
#define ETB_PERCENT_TO_DUTY(x) (clampF(-ETB_DUTY_LIMIT, 0.01f * (x), ETB_DUTY_LIMIT))
|
2019-02-27 14:54:25 -08:00
|
|
|
|
|
2020-12-08 03:24:20 -08:00
|
|
|
|
bool EtbController::init(etb_function_e function, DcMotor *motor, pid_s *pidParameters, const ValueProvider3D* pedalMap, bool initializeThrottles) {
|
2020-09-28 13:33:07 -07:00
|
|
|
|
if (function == ETB_None) {
|
|
|
|
|
// if not configured, don't init.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_function = function;
|
|
|
|
|
m_positionSensor = functionToPositionSensor(function);
|
2020-12-08 03:24:20 -08:00
|
|
|
|
|
|
|
|
|
// If we are a throttle, require redundant TPS sensor
|
|
|
|
|
if (function == ETB_Throttle1 || function == ETB_Throttle2) {
|
|
|
|
|
// We don't need to init throttles, so nothing to do here.
|
|
|
|
|
if (!initializeThrottles) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!Sensor::isRedundant(m_positionSensor)) {
|
|
|
|
|
firmwareError(
|
|
|
|
|
OBD_Throttle_Position_Sensor_Circuit_Malfunction,
|
|
|
|
|
"Use of electronic throttle requires %s to be redundant.",
|
|
|
|
|
Sensor::getSensorName(m_positionSensor)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-10 16:37:04 -08:00
|
|
|
|
m_motor = motor;
|
|
|
|
|
m_pid.initPidClass(pidParameters);
|
2020-04-20 11:34:45 -07:00
|
|
|
|
m_pedalMap = pedalMap;
|
2020-09-28 13:33:07 -07:00
|
|
|
|
|
2020-10-14 19:02:09 -07:00
|
|
|
|
reset();
|
|
|
|
|
|
2020-09-28 13:33:07 -07:00
|
|
|
|
return true;
|
2019-12-10 16:37:04 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EtbController::reset() {
|
|
|
|
|
m_shouldResetPid = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EtbController::onConfigurationChange(pid_s* previousConfiguration) {
|
2020-04-28 13:52:40 -07:00
|
|
|
|
if (m_motor && !m_pid.isSame(previousConfiguration)) {
|
2019-12-10 16:37:04 -08:00
|
|
|
|
m_shouldResetPid = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EtbController::showStatus(Logging* logger) {
|
|
|
|
|
m_pid.showPidStatus(logger, "ETB");
|
2019-11-22 17:53:54 -08:00
|
|
|
|
}
|
2019-11-20 21:49:38 -08:00
|
|
|
|
|
2020-04-19 14:18:47 -07:00
|
|
|
|
expected<percent_t> EtbController::observePlant() const {
|
2020-07-26 02:55:35 -07:00
|
|
|
|
return Sensor::get(m_positionSensor);
|
2020-04-19 14:18:47 -07:00
|
|
|
|
}
|
2019-09-22 20:28:11 -07:00
|
|
|
|
|
2020-04-20 13:26:35 -07:00
|
|
|
|
void EtbController::setIdlePosition(percent_t pos) {
|
|
|
|
|
m_idlePosition = pos;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-18 18:57:04 -07:00
|
|
|
|
void EtbController::setWastegatePosition(percent_t pos) {
|
|
|
|
|
m_wastegatePosition = pos;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-19 14:18:47 -07:00
|
|
|
|
expected<percent_t> EtbController::getSetpoint() const {
|
2020-09-28 13:33:07 -07:00
|
|
|
|
switch (m_function) {
|
|
|
|
|
case ETB_Throttle1:
|
|
|
|
|
case ETB_Throttle2:
|
|
|
|
|
return getSetpointEtb();
|
|
|
|
|
case ETB_IdleValve:
|
|
|
|
|
return getSetpointIdleValve();
|
|
|
|
|
case ETB_Wastegate:
|
|
|
|
|
return getSetpointWastegate();
|
|
|
|
|
default:
|
|
|
|
|
return unexpected;
|
2019-11-22 17:53:54 -08:00
|
|
|
|
}
|
2020-09-28 13:33:07 -07:00
|
|
|
|
}
|
2019-04-26 10:46:58 -07:00
|
|
|
|
|
2020-09-28 13:33:07 -07:00
|
|
|
|
expected<percent_t> EtbController::getSetpointIdleValve() const {
|
2020-07-26 02:55:35 -07:00
|
|
|
|
// VW ETB idle mode uses an ETB only for idle (a mini-ETB sets the lower stop, and a normal cable
|
|
|
|
|
// can pull the throttle up off the stop.), so we directly control the throttle with the idle position.
|
2020-07-26 12:07:45 -07:00
|
|
|
|
#if EFI_TUNER_STUDIO
|
2020-09-28 13:33:07 -07:00
|
|
|
|
tsOutputChannels.etbTarget = m_idlePosition;
|
2020-07-26 12:07:45 -07:00
|
|
|
|
#endif // EFI_TUNER_STUDIO
|
2020-09-28 13:33:07 -07:00
|
|
|
|
return clampF(0, m_idlePosition, 100);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expected<percent_t> EtbController::getSetpointWastegate() const {
|
2020-10-18 18:57:04 -07:00
|
|
|
|
return clampF(0, m_wastegatePosition, 100);
|
2020-09-28 13:33:07 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expected<percent_t> EtbController::getSetpointEtb() const {
|
|
|
|
|
// A few extra preconditions if throttle control is invalid
|
|
|
|
|
if (startupPositionError) {
|
|
|
|
|
return unexpected;
|
2020-07-26 02:55:35 -07:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-20 11:34:45 -07:00
|
|
|
|
// If the pedal map hasn't been set, we can't provide a setpoint.
|
|
|
|
|
if (!m_pedalMap) {
|
|
|
|
|
return unexpected;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-01 17:21:03 -07:00
|
|
|
|
auto pedalPosition = Sensor::get(SensorType::AcceleratorPedal);
|
2017-09-21 20:21:03 -07:00
|
|
|
|
|
2020-04-28 13:52:40 -07:00
|
|
|
|
// If the pedal has failed, just use 0 position.
|
|
|
|
|
// This is safer than disabling throttle control - we can at least push the throttle closed
|
|
|
|
|
// and let the engine idle.
|
|
|
|
|
float sanitizedPedal = clampF(0, pedalPosition.value_or(0), 100);
|
2020-04-20 10:52:20 -07:00
|
|
|
|
|
2020-04-03 04:48:12 -07:00
|
|
|
|
float rpm = GET_RPM();
|
2020-04-20 14:29:03 -07:00
|
|
|
|
float targetFromTable = m_pedalMap->getValue(rpm / RPM_1_BYTE_PACKING_MULT, sanitizedPedal);
|
|
|
|
|
engine->engineState.targetFromTable = targetFromTable;
|
2020-04-20 13:26:35 -07:00
|
|
|
|
|
|
|
|
|
percent_t etbIdlePosition = clampF(
|
|
|
|
|
0,
|
|
|
|
|
CONFIG(useETBforIdleControl) ? m_idlePosition : 0,
|
|
|
|
|
100
|
|
|
|
|
);
|
|
|
|
|
percent_t etbIdleAddition = 0.01f * CONFIG(etbIdleThrottleRange) * etbIdlePosition;
|
2019-11-22 17:53:54 -08:00
|
|
|
|
|
2020-04-20 14:29:03 -07:00
|
|
|
|
// Interpolate so that the idle adder just "compresses" the throttle's range upward.
|
|
|
|
|
// [0, 100] -> [idle, 100]
|
|
|
|
|
// 0% target from table -> idle position as target
|
|
|
|
|
// 100% target from table -> 100% target position
|
|
|
|
|
percent_t targetPosition = interpolateClamped(0, etbIdleAddition, 100, 100, targetFromTable);
|
2020-04-19 14:18:47 -07:00
|
|
|
|
|
2019-06-15 11:33:41 -07:00
|
|
|
|
#if EFI_TUNER_STUDIO
|
2020-09-28 13:33:07 -07:00
|
|
|
|
if (m_function == ETB_Throttle1) {
|
2020-04-20 14:29:03 -07:00
|
|
|
|
tsOutputChannels.etbTarget = targetPosition;
|
2019-11-22 17:53:54 -08:00
|
|
|
|
}
|
2020-07-26 12:07:45 -07:00
|
|
|
|
#endif // EFI_TUNER_STUDIO
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
2020-04-20 14:29:03 -07:00
|
|
|
|
return targetPosition;
|
2020-04-19 14:18:47 -07:00
|
|
|
|
}
|
2017-11-16 11:44:34 -08:00
|
|
|
|
|
2020-04-19 14:18:47 -07:00
|
|
|
|
expected<percent_t> EtbController::getOpenLoop(percent_t target) const {
|
2020-11-19 17:51:30 -08:00
|
|
|
|
float ff = 0;
|
|
|
|
|
|
|
|
|
|
// Don't apply open loop for wastegate/idle valve, only real ETB
|
|
|
|
|
if (m_function != ETB_Wastegate
|
|
|
|
|
&& m_function != ETB_IdleValve) {
|
|
|
|
|
ff = interpolate2d("etbb", target, engineConfiguration->etbBiasBins, engineConfiguration->etbBiasValues);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-19 14:18:47 -07:00
|
|
|
|
engine->engineState.etbFeedForward = ff;
|
2020-11-19 17:51:30 -08:00
|
|
|
|
|
2020-04-19 14:18:47 -07:00
|
|
|
|
return ff;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-22 19:22:28 -07:00
|
|
|
|
expected<percent_t> EtbController::getClosedLoopAutotune(percent_t actualThrottlePosition) {
|
|
|
|
|
// Estimate gain at 60% position - this should be well away from the spring and in the linear region
|
|
|
|
|
bool isPositive = actualThrottlePosition > 60.0f;
|
|
|
|
|
|
|
|
|
|
float autotuneAmplitude = 20;
|
|
|
|
|
|
|
|
|
|
// End of cycle - record & reset
|
|
|
|
|
if (!isPositive && m_lastIsPositive) {
|
|
|
|
|
efitick_t now = getTimeNowNt();
|
|
|
|
|
|
|
|
|
|
// Determine period
|
|
|
|
|
float tu = NT2US((float)(now - m_cycleStartTime)) / 1e6;
|
|
|
|
|
m_cycleStartTime = now;
|
|
|
|
|
|
|
|
|
|
// Determine amplitude
|
|
|
|
|
float a = m_maxCycleTps - m_minCycleTps;
|
|
|
|
|
|
|
|
|
|
// Filter - it's pretty noisy since the ultimate period is not very many loop periods
|
|
|
|
|
constexpr float alpha = 0.05;
|
|
|
|
|
m_a = alpha * a + (1 - alpha) * m_a;
|
|
|
|
|
m_tu = alpha * tu + (1 - alpha) * m_tu;
|
|
|
|
|
|
|
|
|
|
// Reset bounds
|
|
|
|
|
m_minCycleTps = 100;
|
|
|
|
|
m_maxCycleTps = 0;
|
|
|
|
|
|
|
|
|
|
// Math is for Åström–Hägglund (relay) auto tuning
|
|
|
|
|
// https://warwick.ac.uk/fac/cross_fac/iatl/reinvention/archive/volume5issue2/hornsey
|
|
|
|
|
|
|
|
|
|
// Publish to TS state
|
|
|
|
|
#if EFI_TUNER_STUDIO
|
2020-05-06 05:39:02 -07:00
|
|
|
|
// Amplitude of input (duty cycle %)
|
|
|
|
|
float b = 2 * autotuneAmplitude;
|
|
|
|
|
|
|
|
|
|
// Ultimate gain per A-H relay tuning rule
|
|
|
|
|
float ku = 4 * b / (3.14159f * m_a);
|
|
|
|
|
|
|
|
|
|
// The multipliers below are somewhere near the "no overshoot"
|
|
|
|
|
// and "some overshoot" flavors of the Ziegler-Nichols method
|
|
|
|
|
// Kp
|
|
|
|
|
float kp = 0.35f * ku;
|
|
|
|
|
float ki = 0.25f * ku / m_tu;
|
|
|
|
|
float kd = 0.08f * ku * m_tu;
|
|
|
|
|
|
|
|
|
|
// Every 5 cycles (of the throttle), cycle to the next value
|
|
|
|
|
if (m_autotuneCounter == 5) {
|
|
|
|
|
m_autotuneCounter = 0;
|
|
|
|
|
m_autotuneCurrentParam++;
|
|
|
|
|
|
|
|
|
|
if (m_autotuneCurrentParam >= 3) {
|
|
|
|
|
m_autotuneCurrentParam = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_autotuneCounter++;
|
|
|
|
|
|
|
|
|
|
// Multiplex 3 signals on to the {mode, value} format
|
|
|
|
|
tsOutputChannels.calibrationMode = static_cast<TsCalMode>(m_autotuneCurrentParam + 3);
|
|
|
|
|
|
|
|
|
|
switch (m_autotuneCurrentParam) {
|
|
|
|
|
case 0:
|
|
|
|
|
tsOutputChannels.calibrationValue = kp;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
tsOutputChannels.calibrationValue = ki;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
tsOutputChannels.calibrationValue = kd;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Also output to debug channels if configured
|
2020-04-22 19:22:28 -07:00
|
|
|
|
if (engineConfiguration->debugMode == DBG_ETB_AUTOTUNE) {
|
|
|
|
|
// a - amplitude of output (TPS %)
|
|
|
|
|
tsOutputChannels.debugFloatField1 = m_a;
|
|
|
|
|
// b - amplitude of input (Duty cycle %)
|
|
|
|
|
tsOutputChannels.debugFloatField2 = b;
|
|
|
|
|
// Tu - oscillation period (seconds)
|
|
|
|
|
tsOutputChannels.debugFloatField3 = m_tu;
|
|
|
|
|
|
|
|
|
|
tsOutputChannels.debugFloatField4 = ku;
|
2020-05-06 05:39:02 -07:00
|
|
|
|
tsOutputChannels.debugFloatField5 = kp;
|
|
|
|
|
tsOutputChannels.debugFloatField6 = ki;
|
|
|
|
|
tsOutputChannels.debugFloatField7 = kd;
|
2020-04-22 19:22:28 -07:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_lastIsPositive = isPositive;
|
|
|
|
|
|
|
|
|
|
// Find the min/max of each cycle
|
|
|
|
|
if (actualThrottlePosition < m_minCycleTps) {
|
|
|
|
|
m_minCycleTps = actualThrottlePosition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (actualThrottlePosition > m_maxCycleTps) {
|
|
|
|
|
m_maxCycleTps = actualThrottlePosition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Bang-bang control the output to induce oscillation
|
|
|
|
|
return autotuneAmplitude * (isPositive ? -1 : 1);
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-29 02:22:31 -07:00
|
|
|
|
expected<percent_t> EtbController::getClosedLoop(percent_t target, percent_t observation) {
|
2020-04-19 14:18:47 -07:00
|
|
|
|
if (m_shouldResetPid) {
|
|
|
|
|
m_pid.reset();
|
|
|
|
|
m_shouldResetPid = false;
|
|
|
|
|
}
|
2019-03-03 12:27:49 -08:00
|
|
|
|
|
2020-04-19 14:18:47 -07:00
|
|
|
|
// Only report the 0th throttle
|
2020-09-28 13:33:07 -07:00
|
|
|
|
if (m_function == ETB_Throttle1) {
|
2020-04-19 14:18:47 -07:00
|
|
|
|
#if EFI_TUNER_STUDIO
|
|
|
|
|
// Error is positive if the throttle needs to open further
|
2020-07-29 02:22:31 -07:00
|
|
|
|
tsOutputChannels.etb1Error = target - observation;
|
2020-04-19 14:18:47 -07:00
|
|
|
|
#endif /* EFI_TUNER_STUDIO */
|
|
|
|
|
}
|
2020-04-11 19:15:49 -07:00
|
|
|
|
|
2020-09-28 13:33:07 -07:00
|
|
|
|
// Only allow autotune with stopped engine, and on the first throttle
|
|
|
|
|
if (GET_RPM() == 0
|
|
|
|
|
&& engine->etbAutoTune
|
|
|
|
|
&& m_function == ETB_Throttle1) {
|
2020-07-29 02:22:31 -07:00
|
|
|
|
return getClosedLoopAutotune(observation);
|
2020-04-11 19:15:49 -07:00
|
|
|
|
} else {
|
|
|
|
|
// Normal case - use PID to compute closed loop part
|
2020-07-29 02:22:31 -07:00
|
|
|
|
return m_pid.getOutput(target, observation, 1.0f / ETB_LOOP_FREQUENCY);
|
2020-04-19 14:18:47 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EtbController::setOutput(expected<percent_t> outputValue) {
|
|
|
|
|
#if EFI_TUNER_STUDIO
|
|
|
|
|
// Only report first-throttle stats
|
2020-09-28 13:33:07 -07:00
|
|
|
|
if (m_function == ETB_Throttle1) {
|
2020-04-19 14:18:47 -07:00
|
|
|
|
tsOutputChannels.etb1DutyCycle = outputValue.value_or(0);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (!m_motor) return;
|
|
|
|
|
|
2020-04-28 13:52:40 -07:00
|
|
|
|
// If output is valid and we aren't paused, output to motor.
|
|
|
|
|
if (outputValue && !engineConfiguration->pauseEtbControl) {
|
2020-04-19 14:18:47 -07:00
|
|
|
|
m_motor->enable();
|
|
|
|
|
m_motor->set(ETB_PERCENT_TO_DUTY(outputValue.Value));
|
|
|
|
|
} else {
|
|
|
|
|
m_motor->disable();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-18 10:47:49 -07:00
|
|
|
|
void EtbController::update() {
|
2020-09-28 13:33:07 -07:00
|
|
|
|
// If we didn't get initialized, fail fast
|
|
|
|
|
if (!m_motor) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-19 14:18:47 -07:00
|
|
|
|
#if EFI_TUNER_STUDIO
|
2020-09-28 13:33:07 -07:00
|
|
|
|
// Only debug throttle #1
|
|
|
|
|
if (m_function == ETB_Throttle1) {
|
2020-04-19 14:18:47 -07:00
|
|
|
|
// set debug_mode 17
|
|
|
|
|
if (engineConfiguration->debugMode == DBG_ELECTRONIC_THROTTLE_PID) {
|
|
|
|
|
m_pid.postState(&tsOutputChannels);
|
|
|
|
|
tsOutputChannels.debugIntField5 = engine->engineState.etbFeedForward;
|
|
|
|
|
} else if (engineConfiguration->debugMode == DBG_ELECTRONIC_THROTTLE_EXTRA) {
|
|
|
|
|
// set debug_mode 29
|
|
|
|
|
tsOutputChannels.debugFloatField1 = directPwmValue;
|
|
|
|
|
}
|
2020-04-11 19:15:49 -07:00
|
|
|
|
}
|
2020-04-19 14:18:47 -07:00
|
|
|
|
#endif /* EFI_TUNER_STUDIO */
|
2020-04-11 19:15:49 -07:00
|
|
|
|
|
2020-04-19 14:18:47 -07:00
|
|
|
|
if (!cisnan(directPwmValue)) {
|
|
|
|
|
m_motor->set(directPwmValue);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
2020-04-19 14:18:47 -07:00
|
|
|
|
#if EFI_TUNER_STUDIO
|
2020-04-28 16:31:41 -07:00
|
|
|
|
if (engineConfiguration->debugMode == DBG_ETB_LOGIC) {
|
2020-04-19 14:18:47 -07:00
|
|
|
|
tsOutputChannels.debugFloatField1 = engine->engineState.targetFromTable;
|
|
|
|
|
tsOutputChannels.debugFloatField2 = engine->engineState.idle.etbIdleAddition;
|
|
|
|
|
}
|
2020-04-28 16:31:41 -07:00
|
|
|
|
#endif
|
2020-04-19 14:18:47 -07:00
|
|
|
|
|
|
|
|
|
m_pid.iTermMin = engineConfiguration->etb_iTermMin;
|
|
|
|
|
m_pid.iTermMax = engineConfiguration->etb_iTermMax;
|
2019-05-04 21:42:50 -07:00
|
|
|
|
|
2019-11-22 17:53:54 -08:00
|
|
|
|
if (engineConfiguration->isVerboseETB) {
|
2019-12-10 16:37:04 -08:00
|
|
|
|
m_pid.showPidStatus(&logger, "ETB");
|
2019-11-22 17:53:54 -08:00
|
|
|
|
}
|
2019-06-26 16:24:32 -07:00
|
|
|
|
|
2020-04-28 04:22:31 -07:00
|
|
|
|
ClosedLoopController::update();
|
2020-04-19 14:18:47 -07:00
|
|
|
|
|
2019-11-22 17:53:54 -08:00
|
|
|
|
DISPLAY_STATE(Engine)
|
2020-06-17 16:03:10 -07:00
|
|
|
|
DISPLAY(DISPLAY_IF(1))
|
2019-11-22 17:53:54 -08:00
|
|
|
|
DISPLAY_TEXT(Electronic_Throttle);
|
|
|
|
|
DISPLAY_SENSOR(TPS)
|
|
|
|
|
DISPLAY_TEXT(eol);
|
|
|
|
|
|
|
|
|
|
DISPLAY_TEXT(Pedal);
|
|
|
|
|
DISPLAY_SENSOR(PPS);
|
|
|
|
|
DISPLAY(DISPLAY_CONFIG(throttlePedalPositionAdcChannel));
|
|
|
|
|
DISPLAY_TEXT(eol);
|
|
|
|
|
|
|
|
|
|
DISPLAY_TEXT(Feed_forward);
|
|
|
|
|
DISPLAY(DISPLAY_FIELD(etbFeedForward));
|
|
|
|
|
DISPLAY_TEXT(eol);
|
|
|
|
|
|
|
|
|
|
DISPLAY_STATE(ETB_pid)
|
|
|
|
|
DISPLAY_TEXT(input);
|
|
|
|
|
DISPLAY(DISPLAY_FIELD(input));
|
|
|
|
|
DISPLAY_TEXT(Output);
|
|
|
|
|
DISPLAY(DISPLAY_FIELD(output));
|
|
|
|
|
DISPLAY_TEXT(iTerm);
|
|
|
|
|
DISPLAY(DISPLAY_FIELD(iTerm));
|
|
|
|
|
DISPLAY_TEXT(eol);
|
|
|
|
|
DISPLAY(DISPLAY_FIELD(errorAmplificationCoef));
|
|
|
|
|
DISPLAY(DISPLAY_FIELD(previousError));
|
|
|
|
|
DISPLAY_TEXT(eol);
|
|
|
|
|
|
|
|
|
|
DISPLAY_TEXT(Settings);
|
|
|
|
|
DISPLAY(DISPLAY_CONFIG(ETB_PFACTOR));
|
|
|
|
|
DISPLAY(DISPLAY_CONFIG(ETB_IFACTOR));
|
|
|
|
|
DISPLAY(DISPLAY_CONFIG(ETB_DFACTOR));
|
|
|
|
|
DISPLAY_TEXT(eol);
|
|
|
|
|
DISPLAY(DISPLAY_CONFIG(ETB_OFFSET));
|
|
|
|
|
DISPLAY(DISPLAY_CONFIG(ETB_PERIODMS));
|
|
|
|
|
DISPLAY_TEXT(eol);
|
|
|
|
|
DISPLAY(DISPLAY_CONFIG(ETB_MINVALUE));
|
|
|
|
|
DISPLAY(DISPLAY_CONFIG(ETB_MAXVALUE));
|
2019-08-31 14:07:21 -07:00
|
|
|
|
/* DISPLAY_ELSE */
|
2019-11-22 17:53:54 -08:00
|
|
|
|
DISPLAY_TEXT(No_Pedal_Sensor);
|
2019-08-31 14:07:21 -07:00
|
|
|
|
/* DISPLAY_ENDIF */
|
2019-11-22 17:53:54 -08:00
|
|
|
|
}
|
2019-02-10 16:52:06 -08:00
|
|
|
|
|
2020-04-28 16:31:41 -07:00
|
|
|
|
void EtbController::autoCalibrateTps() {
|
2020-09-28 13:33:07 -07:00
|
|
|
|
// Only auto calibrate throttles
|
|
|
|
|
if (m_function == ETB_Throttle1 || m_function == ETB_Throttle2) {
|
|
|
|
|
m_isAutocal = true;
|
|
|
|
|
}
|
2020-04-28 16:31:41 -07:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 04:22:31 -07:00
|
|
|
|
#if !EFI_UNIT_TEST
|
2020-04-28 05:05:18 -07:00
|
|
|
|
/**
|
|
|
|
|
* Things running on a timer (instead of a thread) don't participate it the RTOS's thread priority system,
|
|
|
|
|
* and operate essentially "first come first serve", which risks starvation.
|
|
|
|
|
* Since ETB is a safety critical device, we need the hard RTOS guarantee that it will be scheduled over other less important tasks.
|
|
|
|
|
*/
|
2020-04-28 04:22:31 -07:00
|
|
|
|
#include "periodic_thread_controller.h"
|
2020-09-18 10:47:49 -07:00
|
|
|
|
struct EtbImpl final : public EtbController {
|
|
|
|
|
void update() override {
|
2020-04-28 16:31:41 -07:00
|
|
|
|
#if EFI_TUNER_STUDIO
|
|
|
|
|
if (m_isAutocal) {
|
|
|
|
|
// Don't allow if engine is running!
|
|
|
|
|
if (GET_RPM() > 0) {
|
|
|
|
|
m_isAutocal = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto motor = getMotor();
|
|
|
|
|
if (!motor) {
|
|
|
|
|
m_isAutocal = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-28 13:33:07 -07:00
|
|
|
|
auto myFunction = getFunction();
|
2020-04-28 16:31:41 -07:00
|
|
|
|
|
|
|
|
|
// First grab open
|
|
|
|
|
motor->set(0.5f);
|
|
|
|
|
motor->enable();
|
|
|
|
|
chThdSleepMilliseconds(1000);
|
2020-09-28 13:33:07 -07:00
|
|
|
|
float primaryMax = Sensor::getRaw(functionToTpsSensorPrimary(myFunction)) * TPS_TS_CONVERSION;
|
|
|
|
|
float secondaryMax = Sensor::getRaw(functionToTpsSensorSecondary(myFunction)) * TPS_TS_CONVERSION;
|
2020-04-28 16:31:41 -07:00
|
|
|
|
|
|
|
|
|
// Let it return
|
|
|
|
|
motor->set(0);
|
|
|
|
|
chThdSleepMilliseconds(200);
|
|
|
|
|
|
|
|
|
|
// Now grab closed
|
|
|
|
|
motor->set(-0.5f);
|
|
|
|
|
chThdSleepMilliseconds(1000);
|
2020-09-28 13:33:07 -07:00
|
|
|
|
float primaryMin = Sensor::getRaw(functionToTpsSensorPrimary(myFunction)) * TPS_TS_CONVERSION;
|
|
|
|
|
float secondaryMin = Sensor::getRaw(functionToTpsSensorSecondary(myFunction)) * TPS_TS_CONVERSION;
|
2020-04-28 16:31:41 -07:00
|
|
|
|
|
|
|
|
|
// Finally disable and reset state
|
|
|
|
|
motor->disable();
|
|
|
|
|
|
2020-05-18 11:32:00 -07:00
|
|
|
|
// Write out the learned values to TS, waiting briefly after setting each to let TS grab it
|
2020-09-28 13:33:07 -07:00
|
|
|
|
tsOutputChannels.calibrationMode = functionToCalModePriMax(myFunction);
|
2020-05-18 11:32:00 -07:00
|
|
|
|
tsOutputChannels.calibrationValue = primaryMax;
|
|
|
|
|
chThdSleepMilliseconds(500);
|
2020-09-28 13:33:07 -07:00
|
|
|
|
tsOutputChannels.calibrationMode = functionToCalModePriMin(myFunction);
|
2020-05-18 11:32:00 -07:00
|
|
|
|
tsOutputChannels.calibrationValue = primaryMin;
|
|
|
|
|
chThdSleepMilliseconds(500);
|
|
|
|
|
|
2020-09-28 13:33:07 -07:00
|
|
|
|
tsOutputChannels.calibrationMode = functionToCalModeSecMax(myFunction);
|
2020-05-18 11:32:00 -07:00
|
|
|
|
tsOutputChannels.calibrationValue = secondaryMax;
|
2020-04-28 16:31:41 -07:00
|
|
|
|
chThdSleepMilliseconds(500);
|
2020-09-28 13:33:07 -07:00
|
|
|
|
tsOutputChannels.calibrationMode = functionToCalModeSecMin(myFunction);
|
2020-05-18 11:32:00 -07:00
|
|
|
|
tsOutputChannels.calibrationValue = secondaryMin;
|
|
|
|
|
chThdSleepMilliseconds(500);
|
|
|
|
|
|
2020-04-28 16:31:41 -07:00
|
|
|
|
tsOutputChannels.calibrationMode = TsCalMode::None;
|
|
|
|
|
|
|
|
|
|
m_isAutocal = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif /* EFI_TUNER_STUDIO */
|
|
|
|
|
|
2020-09-18 10:47:49 -07:00
|
|
|
|
EtbController::update();
|
2020-04-28 04:22:31 -07:00
|
|
|
|
}
|
2020-09-18 10:47:49 -07:00
|
|
|
|
};
|
2020-04-28 04:22:31 -07:00
|
|
|
|
|
2020-09-18 10:47:49 -07:00
|
|
|
|
// real implementation (we mock for some unit tests)
|
|
|
|
|
static EtbImpl etbControllers[ETB_COUNT];
|
|
|
|
|
|
|
|
|
|
struct EtbThread final : public PeriodicController<512> {
|
|
|
|
|
EtbThread() : PeriodicController("ETB", NORMALPRIO + 3, ETB_LOOP_FREQUENCY) {}
|
|
|
|
|
|
|
|
|
|
void PeriodicTask(efitick_t) override {
|
|
|
|
|
// Simply update all controllers
|
2020-10-18 17:49:42 -07:00
|
|
|
|
for (int i = 0 ; i < ETB_COUNT; i++) {
|
2020-09-18 10:47:49 -07:00
|
|
|
|
etbControllers[i].update();
|
|
|
|
|
}
|
2020-04-28 04:22:31 -07:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2020-09-18 10:47:49 -07:00
|
|
|
|
static EtbThread etbThread;
|
|
|
|
|
|
2020-04-28 04:22:31 -07:00
|
|
|
|
#endif
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
|
|
|
|
static void showEthInfo(void) {
|
2019-11-19 23:18:17 -08:00
|
|
|
|
#if EFI_PROD_CODE
|
2017-09-21 20:21:03 -07:00
|
|
|
|
scheduleMsg(&logger, "etbAutoTune=%d",
|
|
|
|
|
engine->etbAutoTune);
|
|
|
|
|
|
2020-04-05 06:11:25 -07:00
|
|
|
|
scheduleMsg(&logger, "TPS=%.2f", Sensor::get(SensorType::Tps1).value_or(0));
|
2019-11-20 21:49:38 -08:00
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
2018-01-23 09:05:14 -08:00
|
|
|
|
scheduleMsg(&logger, "etbControlPin1=%s duty=%.2f freq=%d",
|
2019-11-30 14:38:33 -08:00
|
|
|
|
hwPortname(CONFIG(etbIo[0].controlPin1)),
|
2017-05-29 20:36:08 -07:00
|
|
|
|
currentEtbDuty,
|
|
|
|
|
engineConfiguration->etbFreq);
|
2020-10-18 17:49:42 -07:00
|
|
|
|
|
|
|
|
|
for (int i = 0; i < ETB_COUNT; i++) {
|
2020-05-06 17:06:50 -07:00
|
|
|
|
scheduleMsg(&logger, "ETB%d", i);
|
|
|
|
|
scheduleMsg(&logger, " dir1=%s", hwPortname(CONFIG(etbIo[i].directionPin1)));
|
|
|
|
|
scheduleMsg(&logger, " dir2=%s", hwPortname(CONFIG(etbIo[i].directionPin2)));
|
|
|
|
|
scheduleMsg(&logger, " control=%s", hwPortname(CONFIG(etbIo[i].controlPin1)));
|
|
|
|
|
scheduleMsg(&logger, " disable=%s", hwPortname(CONFIG(etbIo[i].disablePin)));
|
|
|
|
|
showDcMotorInfo(&logger, i);
|
|
|
|
|
}
|
2019-11-20 21:49:38 -08:00
|
|
|
|
|
2019-11-19 23:18:17 -08:00
|
|
|
|
#endif /* EFI_PROD_CODE */
|
2015-07-10 06:01:56 -07:00
|
|
|
|
}
|
|
|
|
|
|
2019-12-13 09:50:34 -08:00
|
|
|
|
static void etbPidReset(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2020-10-18 17:49:42 -07:00
|
|
|
|
for (int i = 0 ; i < ETB_COUNT; i++) {
|
|
|
|
|
if (auto controller = engine->etbControllers[i]) {
|
|
|
|
|
controller->reset();
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-28 12:24:30 -08:00
|
|
|
|
}
|
2019-11-27 19:07:36 -08:00
|
|
|
|
}
|
|
|
|
|
|
2019-12-13 09:50:34 -08:00
|
|
|
|
#if !EFI_UNIT_TEST
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* At the moment there are TWO ways to use this
|
|
|
|
|
* set_etb_duty X
|
|
|
|
|
* set etb X
|
|
|
|
|
* manual duty cycle control without PID. Percent value from 0 to 100
|
|
|
|
|
*/
|
|
|
|
|
void setThrottleDutyCycle(percent_t level) {
|
|
|
|
|
scheduleMsg(&logger, "setting ETB duty=%f%%", level);
|
|
|
|
|
if (cisnan(level)) {
|
|
|
|
|
directPwmValue = NAN;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float dc = ETB_PERCENT_TO_DUTY(level);
|
|
|
|
|
directPwmValue = dc;
|
2020-10-18 17:49:42 -07:00
|
|
|
|
for (int i = 0 ; i < ETB_COUNT; i++) {
|
2020-03-03 14:56:50 -08:00
|
|
|
|
setDcMotorDuty(i, dc);
|
2019-12-13 09:50:34 -08:00
|
|
|
|
}
|
|
|
|
|
scheduleMsg(&logger, "duty ETB duty=%f", dc);
|
|
|
|
|
}
|
2015-07-10 06:01:56 -07:00
|
|
|
|
|
2019-09-27 20:37:40 -07:00
|
|
|
|
static void setEtbFrequency(int frequency) {
|
|
|
|
|
engineConfiguration->etbFreq = frequency;
|
|
|
|
|
|
2020-10-18 17:49:42 -07:00
|
|
|
|
for (int i = 0 ; i < ETB_COUNT; i++) {
|
2020-03-03 14:56:50 -08:00
|
|
|
|
setDcMotorFrequency(i, frequency);
|
2019-11-20 21:49:38 -08:00
|
|
|
|
}
|
2019-09-27 20:37:40 -07:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-02 12:04:42 -08:00
|
|
|
|
static void etbReset() {
|
2019-03-09 20:31:47 -08:00
|
|
|
|
scheduleMsg(&logger, "etbReset");
|
2019-05-04 21:42:50 -07:00
|
|
|
|
|
2020-10-18 17:49:42 -07:00
|
|
|
|
for (int i = 0 ; i < ETB_COUNT; i++) {
|
2020-03-03 14:56:50 -08:00
|
|
|
|
setDcMotorDuty(i, 0);
|
2019-11-20 21:49:38 -08:00
|
|
|
|
}
|
2019-12-10 16:37:04 -08:00
|
|
|
|
|
2019-11-27 19:07:36 -08:00
|
|
|
|
etbPidReset();
|
2019-03-02 12:04:42 -08:00
|
|
|
|
}
|
2019-11-19 23:18:17 -08:00
|
|
|
|
#endif /* EFI_PROD_CODE */
|
|
|
|
|
|
2019-11-20 05:46:54 -08:00
|
|
|
|
#if !EFI_UNIT_TEST
|
2019-11-19 23:18:17 -08:00
|
|
|
|
/**
|
|
|
|
|
* set etb_p X
|
|
|
|
|
*/
|
|
|
|
|
void setEtbPFactor(float value) {
|
|
|
|
|
engineConfiguration->etb.pFactor = value;
|
2019-11-27 19:07:36 -08:00
|
|
|
|
etbPidReset();
|
2019-11-19 23:18:17 -08:00
|
|
|
|
showEthInfo();
|
|
|
|
|
}
|
2019-03-02 12:04:42 -08:00
|
|
|
|
|
2019-03-01 20:09:33 -08:00
|
|
|
|
/**
|
|
|
|
|
* set etb_i X
|
|
|
|
|
*/
|
2017-01-06 14:01:28 -08:00
|
|
|
|
void setEtbIFactor(float value) {
|
2015-11-11 20:01:18 -08:00
|
|
|
|
engineConfiguration->etb.iFactor = value;
|
2019-11-27 19:07:36 -08:00
|
|
|
|
etbPidReset();
|
2018-09-24 20:57:03 -07:00
|
|
|
|
showEthInfo();
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-01 20:09:33 -08:00
|
|
|
|
/**
|
|
|
|
|
* set etb_d X
|
|
|
|
|
*/
|
2018-09-24 20:57:03 -07:00
|
|
|
|
void setEtbDFactor(float value) {
|
|
|
|
|
engineConfiguration->etb.dFactor = value;
|
2019-11-27 19:07:36 -08:00
|
|
|
|
etbPidReset();
|
2018-11-26 19:17:16 -08:00
|
|
|
|
showEthInfo();
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-03 12:27:49 -08:00
|
|
|
|
/**
|
|
|
|
|
* set etb_o X
|
|
|
|
|
*/
|
2018-11-26 19:17:16 -08:00
|
|
|
|
void setEtbOffset(int value) {
|
|
|
|
|
engineConfiguration->etb.offset = value;
|
2019-11-27 19:07:36 -08:00
|
|
|
|
etbPidReset();
|
2015-07-10 06:01:56 -07:00
|
|
|
|
showEthInfo();
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 16:31:41 -07:00
|
|
|
|
void etbAutocal(size_t throttleIndex) {
|
|
|
|
|
if (throttleIndex >= ETB_COUNT) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-18 18:57:04 -07:00
|
|
|
|
if (auto etb = engine->etbControllers[throttleIndex]) {
|
2020-04-28 16:31:41 -07:00
|
|
|
|
etb->autoCalibrateTps();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* !EFI_UNIT_TEST */
|
2019-11-20 05:46:54 -08:00
|
|
|
|
|
2020-04-10 05:12:16 -07:00
|
|
|
|
/**
|
|
|
|
|
* This specific throttle has default position of about 7% open
|
|
|
|
|
*/
|
|
|
|
|
static const float boschBiasBins[] = {
|
|
|
|
|
0, 1, 5, 7, 14, 65, 66, 100
|
|
|
|
|
};
|
|
|
|
|
static const float boschBiasValues[] = {
|
|
|
|
|
-15, -15, -10, 0, 19, 20, 26, 28
|
|
|
|
|
};
|
|
|
|
|
|
2019-09-21 21:16:46 -07:00
|
|
|
|
void setBoschVNH2SP30Curve(DECLARE_CONFIG_PARAMETER_SIGNATURE) {
|
2020-04-10 05:12:16 -07:00
|
|
|
|
copyArray(CONFIG(etbBiasBins), boschBiasBins);
|
|
|
|
|
copyArray(CONFIG(etbBiasValues), boschBiasValues);
|
2019-08-31 17:17:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-21 21:16:46 -07:00
|
|
|
|
void setDefaultEtbParameters(DECLARE_CONFIG_PARAMETER_SIGNATURE) {
|
2019-06-15 10:33:14 -07:00
|
|
|
|
CONFIG(etbIdleThrottleRange) = 5;
|
|
|
|
|
|
2019-11-22 20:27:24 -08:00
|
|
|
|
setLinearCurve(config->pedalToTpsPedalBins, /*from*/0, /*to*/100, 1);
|
|
|
|
|
setLinearCurve(config->pedalToTpsRpmBins, /*from*/0, /*to*/8000 / RPM_1_BYTE_PACKING_MULT, 1);
|
2019-06-10 20:38:44 -07:00
|
|
|
|
|
2019-06-10 20:57:35 -07:00
|
|
|
|
for (int pedalIndex = 0;pedalIndex<PEDAL_TO_TPS_SIZE;pedalIndex++) {
|
|
|
|
|
for (int rpmIndex = 0;rpmIndex<PEDAL_TO_TPS_SIZE;rpmIndex++) {
|
|
|
|
|
config->pedalToTpsTable[pedalIndex][rpmIndex] = config->pedalToTpsPedalBins[pedalIndex];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-14 19:02:09 -07:00
|
|
|
|
// Default is to run each throttle off its respective hbridge
|
|
|
|
|
engineConfiguration->etbFunctions[0] = ETB_Throttle1;
|
|
|
|
|
engineConfiguration->etbFunctions[1] = ETB_Throttle2;
|
|
|
|
|
|
2020-04-28 04:22:31 -07:00
|
|
|
|
engineConfiguration->etbFreq = DEFAULT_ETB_PWM_FREQUENCY;
|
2019-06-10 20:57:35 -07:00
|
|
|
|
|
2020-04-28 04:22:31 -07:00
|
|
|
|
// voltage, not ADC like with TPS
|
|
|
|
|
engineConfiguration->throttlePedalUpVoltage = 0;
|
|
|
|
|
engineConfiguration->throttlePedalWOTVoltage = 5;
|
2017-05-29 19:35:24 -07:00
|
|
|
|
|
2020-04-10 05:12:16 -07:00
|
|
|
|
engineConfiguration->etb = {
|
|
|
|
|
1, // Kp
|
|
|
|
|
10, // Ki
|
|
|
|
|
0.05, // Kd
|
|
|
|
|
0, // offset
|
2020-04-28 04:22:31 -07:00
|
|
|
|
0, // Update rate, unused
|
2020-04-10 05:12:16 -07:00
|
|
|
|
-100, 100 // min/max
|
|
|
|
|
};
|
|
|
|
|
|
2020-04-28 04:22:31 -07:00
|
|
|
|
engineConfiguration->etb_iTermMin = -30;
|
|
|
|
|
engineConfiguration->etb_iTermMax = 30;
|
2015-07-10 06:01:56 -07:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-27 20:01:41 -07:00
|
|
|
|
void onConfigurationChangeElectronicThrottleCallback(engine_configuration_s *previousConfiguration) {
|
2020-04-28 04:22:31 -07:00
|
|
|
|
#if !EFI_UNIT_TEST
|
2019-12-10 16:37:04 -08:00
|
|
|
|
for (int i = 0; i < ETB_COUNT; i++) {
|
2019-12-13 10:52:34 -08:00
|
|
|
|
etbControllers[i].onConfigurationChange(&previousConfiguration->etb);
|
2019-11-28 12:24:30 -08:00
|
|
|
|
}
|
2020-04-28 04:22:31 -07:00
|
|
|
|
#endif
|
2017-05-27 20:01:41 -07:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 17:07:55 -08:00
|
|
|
|
#if EFI_PROD_CODE && 0
|
2017-09-21 20:21:03 -07:00
|
|
|
|
static void setTempOutput(float value) {
|
|
|
|
|
autoTune.output = value;
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-25 20:13:03 -08:00
|
|
|
|
/**
|
|
|
|
|
* set_etbat_step X
|
|
|
|
|
*/
|
|
|
|
|
static void setAutoStep(float value) {
|
|
|
|
|
autoTune.reset();
|
2018-11-22 20:06:06 -08:00
|
|
|
|
autoTune.SetOutputStep(value);
|
2017-09-21 20:21:03 -07:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-19 23:18:17 -08:00
|
|
|
|
#endif /* EFI_PROD_CODE */
|
2018-11-26 18:40:41 -08:00
|
|
|
|
|
2020-04-10 05:12:16 -07:00
|
|
|
|
static const float defaultBiasBins[] = {
|
|
|
|
|
0, 1, 2, 4, 7, 98, 99, 100
|
|
|
|
|
};
|
|
|
|
|
static const float defaultBiasValues[] = {
|
|
|
|
|
-20, -18, -17, 0, 20, 21, 22, 25
|
|
|
|
|
};
|
|
|
|
|
|
2019-09-21 21:16:46 -07:00
|
|
|
|
void setDefaultEtbBiasCurve(DECLARE_CONFIG_PARAMETER_SIGNATURE) {
|
2020-04-10 05:12:16 -07:00
|
|
|
|
copyArray(CONFIG(etbBiasBins), defaultBiasBins);
|
|
|
|
|
copyArray(CONFIG(etbBiasValues), defaultBiasValues);
|
2018-12-09 10:50:13 -08:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-10 09:58:27 -07:00
|
|
|
|
void unregisterEtbPins() {
|
2019-12-13 10:52:34 -08:00
|
|
|
|
// todo: we probably need an implementation here?!
|
2019-03-10 09:58:27 -07:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-19 05:04:27 -07:00
|
|
|
|
static pid_s* getEtbPidForFunction(etb_function_e function DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
|
|
|
|
switch (function) {
|
|
|
|
|
case ETB_Wastegate: return &CONFIG(etbWastegatePid);
|
|
|
|
|
default: return &CONFIG(etb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-01 21:37:02 -07:00
|
|
|
|
void doInitElectronicThrottle(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
2019-12-13 10:52:34 -08:00
|
|
|
|
efiAssertVoid(OBD_PCM_Processor_Fault, engine->etbControllers != NULL, "etbControllers NULL");
|
2019-09-21 21:36:13 -07:00
|
|
|
|
#if EFI_PROD_CODE
|
2017-05-29 19:08:55 -07:00
|
|
|
|
addConsoleAction("ethinfo", showEthInfo);
|
2019-03-02 12:04:42 -08:00
|
|
|
|
addConsoleAction("etbreset", etbReset);
|
2019-09-27 20:37:40 -07:00
|
|
|
|
addConsoleActionI("etb_freq", setEtbFrequency);
|
2019-09-21 21:36:13 -07:00
|
|
|
|
#endif /* EFI_PROD_CODE */
|
2019-09-21 21:16:46 -07:00
|
|
|
|
|
2020-10-08 14:09:00 -07:00
|
|
|
|
pedal2tpsMap.init(config->pedalToTpsTable, config->pedalToTpsPedalBins, config->pedalToTpsRpmBins);
|
2020-10-02 17:51:02 -07:00
|
|
|
|
|
2020-12-08 03:24:20 -08:00
|
|
|
|
bool shouldInitThrottles = Sensor::hasSensor(SensorType::AcceleratorPedalPrimary);
|
2020-10-14 19:02:09 -07:00
|
|
|
|
bool anyEtbConfigured = false;
|
|
|
|
|
|
2020-10-18 14:26:38 -07:00
|
|
|
|
for (int i = 0 ; i < ETB_COUNT; i++) {
|
2020-11-16 17:07:12 -08:00
|
|
|
|
auto motor = initDcMotor(engineConfiguration->etbIo[i], i, CONFIG(etb_use_two_wires) PASS_ENGINE_PARAMETER_SUFFIX);
|
2020-03-03 14:56:50 -08:00
|
|
|
|
|
|
|
|
|
// If this motor is actually set up, init the etb
|
|
|
|
|
if (motor)
|
|
|
|
|
{
|
2020-10-14 19:02:09 -07:00
|
|
|
|
auto controller = engine->etbControllers[i];
|
|
|
|
|
if (!controller) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-18 14:26:38 -07:00
|
|
|
|
auto func = CONFIG(etbFunctions[i]);
|
2020-10-19 05:04:27 -07:00
|
|
|
|
auto pid = getEtbPidForFunction(func PASS_ENGINE_PARAMETER_SUFFIX);
|
2020-09-28 13:33:07 -07:00
|
|
|
|
|
2020-12-08 03:24:20 -08:00
|
|
|
|
anyEtbConfigured |= controller->init(func, motor, pid, &pedal2tpsMap, shouldInitThrottles);
|
2020-03-03 14:56:50 -08:00
|
|
|
|
INJECT_ENGINE_REFERENCE(engine->etbControllers[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-15 19:04:42 -07:00
|
|
|
|
if (!anyEtbConfigured) {
|
|
|
|
|
// It's not valid to have a PPS without any ETBs - check that at least one ETB was enabled along with the pedal
|
2020-12-08 03:24:20 -08:00
|
|
|
|
if (shouldInitThrottles) {
|
2020-10-15 19:04:42 -07:00
|
|
|
|
firmwareError(OBD_PCM_Processor_Fault, "A pedal position sensor was configured, but no electronic throttles are configured.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Don't start the thread if no throttles are in use.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-29 11:00:04 -07:00
|
|
|
|
#if 0 && ! EFI_UNIT_TEST
|
2019-09-22 20:28:11 -07:00
|
|
|
|
percent_t startupThrottlePosition = getTPS(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
|
if (absF(startupThrottlePosition - engineConfiguration->etbNeutralPosition) > STARTUP_NEUTRAL_POSITION_ERROR_THRESHOLD) {
|
|
|
|
|
/**
|
2020-03-28 17:56:58 -07:00
|
|
|
|
* Unexpected electronic throttle start-up position is worth a critical error
|
2019-09-22 20:28:11 -07:00
|
|
|
|
*/
|
|
|
|
|
firmwareError(OBD_Throttle_Actuator_Control_Range_Performance_Bank_1, "startup ETB position %.2f not %d",
|
|
|
|
|
startupThrottlePosition,
|
|
|
|
|
engineConfiguration->etbNeutralPosition);
|
|
|
|
|
startupPositionError = true;
|
|
|
|
|
}
|
2019-09-22 21:41:35 -07:00
|
|
|
|
#endif /* EFI_UNIT_TEST */
|
2019-09-22 20:28:11 -07:00
|
|
|
|
|
2020-09-18 10:47:49 -07:00
|
|
|
|
#if !EFI_UNIT_TEST
|
|
|
|
|
etbThread.Start();
|
|
|
|
|
#endif
|
2015-07-10 06:01:56 -07:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-01 21:32:03 -07:00
|
|
|
|
void initElectronicThrottle(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
|
|
|
|
|
if (hasFirmwareError()) {
|
2020-04-02 05:04:12 -07:00
|
|
|
|
return;
|
2020-04-01 21:32:03 -07:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 04:22:31 -07:00
|
|
|
|
#if !EFI_UNIT_TEST
|
2020-04-01 21:32:03 -07:00
|
|
|
|
for (int i = 0; i < ETB_COUNT; i++) {
|
|
|
|
|
engine->etbControllers[i] = &etbControllers[i];
|
|
|
|
|
}
|
2020-04-28 04:22:31 -07:00
|
|
|
|
#endif
|
2020-04-02 05:04:12 -07:00
|
|
|
|
|
2020-04-01 21:32:03 -07:00
|
|
|
|
doInitElectronicThrottle(PASS_ENGINE_PARAMETER_SIGNATURE);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-20 13:26:35 -07:00
|
|
|
|
void setEtbIdlePosition(percent_t pos DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
2020-11-26 16:21:42 -08:00
|
|
|
|
if (!Sensor::hasSensor(SensorType::AcceleratorPedal)) {
|
|
|
|
|
firmwareError(CUSTOM_NO_ETB_FOR_IDLE, "No ETB to use for idle");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-20 13:26:35 -07:00
|
|
|
|
for (int i = 0; i < ETB_COUNT; i++) {
|
2020-10-18 18:57:04 -07:00
|
|
|
|
if (auto etb = engine->etbControllers[i]) {
|
2020-04-20 13:26:35 -07:00
|
|
|
|
etb->setIdlePosition(pos);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-18 18:57:04 -07:00
|
|
|
|
void setEtbWastegatePosition(percent_t pos DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
|
|
|
|
for (int i = 0; i < ETB_COUNT; i++) {
|
|
|
|
|
if (auto etb = engine->etbControllers[i]) {
|
|
|
|
|
etb->setWastegatePosition(pos);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-25 21:57:23 -08:00
|
|
|
|
static void toyota89281_33010_pedal_position_sensor(DECLARE_CONFIG_PARAMETER_SIGNATURE) {
|
|
|
|
|
engineConfiguration->throttlePedalUpVoltage = 0;
|
|
|
|
|
engineConfiguration->throttlePedalWOTVoltage = 4.1;
|
|
|
|
|
engineConfiguration->throttlePedalSecondaryUpVoltage = 0.73;
|
|
|
|
|
engineConfiguration->throttlePedalSecondaryWOTVoltage = 4.9;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setProteusHitachiEtbDefaults(DECLARE_CONFIG_PARAMETER_SIGNATURE) {
|
|
|
|
|
// EFI_ADC_12: "Analog Volt 3"
|
|
|
|
|
engineConfiguration->tps1_2AdcChannel = EFI_ADC_12;
|
|
|
|
|
// EFI_ADC_13: "Analog Volt 4"
|
|
|
|
|
engineConfiguration->tps2_1AdcChannel = EFI_ADC_13;
|
|
|
|
|
// EFI_ADC_0: "Analog Volt 5"
|
|
|
|
|
engineConfiguration->tps2_2AdcChannel = EFI_ADC_0;
|
|
|
|
|
// EFI_ADC_1: "Analog Volt 6"
|
|
|
|
|
engineConfiguration->throttlePedalPositionAdcChannel = EFI_ADC_1;
|
|
|
|
|
toyota89281_33010_pedal_position_sensor(PASS_CONFIG_PARAMETER_SIGNATURE);
|
|
|
|
|
|
|
|
|
|
// EFI_ADC_2: "Analog Volt 7"
|
|
|
|
|
engineConfiguration->throttlePedalPositionSecondAdcChannel = EFI_ADC_2;
|
|
|
|
|
|
|
|
|
|
setHitachiEtbBiasBins(PASS_CONFIG_PARAMETER_SIGNATURE);
|
|
|
|
|
|
|
|
|
|
engineConfiguration->etb.pFactor = 2.7999;
|
|
|
|
|
engineConfiguration->etb.iFactor = 25.5;
|
|
|
|
|
engineConfiguration->etb.dFactor = 0.053;
|
|
|
|
|
engineConfiguration->etb.offset = 0.0;
|
|
|
|
|
engineConfiguration->etb.periodMs = 5.0;
|
|
|
|
|
engineConfiguration->etb.minValue = -100.0;
|
|
|
|
|
engineConfiguration->etb.maxValue = 100.0;
|
|
|
|
|
|
|
|
|
|
// Nissan 60mm throttle
|
|
|
|
|
CONFIG(tpsMin) = CONFIG(tps2Min) = 113;
|
|
|
|
|
CONFIG(tpsMax) = CONFIG(tps2Max) = 846;
|
|
|
|
|
CONFIG(tps1SecondaryMin) = CONFIG(tps2SecondaryMin) = 897;
|
|
|
|
|
CONFIG(tps1SecondaryMax) = CONFIG(tps2SecondaryMax) = 161;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-10 06:01:56 -07:00
|
|
|
|
#endif /* EFI_ELECTRONIC_THROTTLE_BODY */
|