static void manualIdleController(int positionPercent) { // todo: this is not great that we have to write into configuration here boardConfiguration->manIdlePosition = positionPercent; if (isCranking()) { positionPercent += engineConfiguration->crankingIdleAdjustment; } percent_t cltCorrectedPosition = interpolate2d(engine->engineState.clt, config->cltIdleCorrBins, config->cltIdleCorr, CLT_CURVE_SIZE) / PERCENT_MULT * positionPercent; // let's put the value into the right range cltCorrectedPosition = maxF(cltCorrectedPosition, 0.01); cltCorrectedPosition = minF(cltCorrectedPosition, 99.9); if (engineConfiguration->debugMode == IDLE) { tsOutputChannels.debugFloatField1 = actualIdlePosition; } if (absF(cltCorrectedPosition - actualIdlePosition) < 1) { return; // value is pretty close, let's leave the poor valve alone } actualIdlePosition = cltCorrectedPosition; if (boardConfiguration->useStepperIdle) { iacMotor.setTargetPosition(cltCorrectedPosition / 100 * engineConfiguration->idleStepperTotalSteps); } else { setIdleValvePwm(cltCorrectedPosition); } }
void StepperMotor::initialize(brain_pin_e stepPin, brain_pin_e directionPin, pin_output_mode_e directionPinMode, float reactionTime, int totalSteps, brain_pin_e enablePin, Logging *sharedLogger) { this->reactionTime = maxF(1, reactionTime); this->totalSteps = maxI(3, totalSteps); logger = sharedLogger; if (stepPin == GPIO_UNASSIGNED || directionPin == GPIO_UNASSIGNED) { return; } stepPort = getHwPort("step", stepPin); this->stepPin = getHwPin("step", stepPin); this->directionPinMode = directionPinMode; this->directionPin.initPin("stepper dir", directionPin, &this->directionPinMode); enablePort = getHwPort("enable", enablePin); this->enablePin = getHwPin("enable", enablePin); efiSetPadMode("stepper step", stepPin, PAL_MODE_OUTPUT_PUSHPULL); efiSetPadMode("stepper enable", enablePin, PAL_MODE_OUTPUT_PUSHPULL); palWritePad(this->enablePort, enablePin, true); // disable stepper // All pins must be 0 for correct hardware startup (e.g. stepper auto-disabling circuit etc.). palWritePad(this->stepPort, this->stepPin, false); this->directionPin.setValue(false); this->currentDirection = false; chThdCreateStatic(stThreadStack, sizeof(stThreadStack), NORMALPRIO, (tfunc_t) stThread, this); }
percent_t getPedalPosition(DECLARE_ENGINE_PARAMETER_SIGNATURE) { if (mockPedalPosition != MOCK_UNDEFINED) { return mockPedalPosition; } float voltage = getVoltageDivided("pPS", engineConfiguration->throttlePedalPositionAdcChannel); float result = interpolateMsg("pedal", engineConfiguration->throttlePedalUpVoltage, 0, engineConfiguration->throttlePedalWOTVoltage, 100, voltage); // this would put the value into the 0-100 range return maxF(0, minF(100, result)); }
void hipAdcCallback(adcsample_t value) { if (state == WAITING_FOR_ADC_TO_SKIP) { state = WAITING_FOR_RESULT_ADC; } else if (state == WAITING_FOR_RESULT_ADC) { engine->knockVolts = adcToVoltsDivided(value); hipValueMax = maxF(engine->knockVolts, hipValueMax); engine->knockLogic(engine->knockVolts); float angleWindowWidth = engineConfiguration->knockDetectionWindowEnd - engineConfiguration->knockDetectionWindowStart; if (angleWindowWidth != currentAngleWindowWidth) { currentAngleWindowWidth = angleWindowWidth; prepareHip9011RpmLookup(currentAngleWindowWidth); } int integratorIndex = getIntegrationIndexByRpm(engine->rpmCalculator.rpmValue); int gainIndex = getHip9011GainIndex(boardConfiguration->hip9011Gain); int bandIndex = getBandIndex(); int prescalerIndex = engineConfiguration->hip9011PrescalerAndSDO; if (currentGainIndex != gainIndex) { currentGainIndex = gainIndex; tx_buff[0] = SET_GAIN_CMD + gainIndex; state = IS_SENDING_SPI_COMMAND; spiSelectI(driver); spiStartExchangeI(driver, 1, tx_buff, rx_buff); } else if (currentIntergratorIndex != integratorIndex) { currentIntergratorIndex = integratorIndex; tx_buff[0] = SET_INTEGRATOR_CMD + integratorIndex; state = IS_SENDING_SPI_COMMAND; spiSelectI(driver); spiStartExchangeI(driver, 1, tx_buff, rx_buff); } else if (currentBandIndex != bandIndex) { currentBandIndex = bandIndex; tx_buff[0] = SET_BAND_PASS_CMD + bandIndex; state = IS_SENDING_SPI_COMMAND; spiSelectI(driver); spiStartExchangeI(driver, 1, tx_buff, rx_buff); } else if (currentPrescaler != prescalerIndex) { currentPrescaler = prescalerIndex; tx_buff[0] = SET_PRESCALER_CMD + prescalerIndex; state = IS_SENDING_SPI_COMMAND; spiSelectI(driver); spiStartExchangeI(driver, 1, tx_buff, rx_buff); } else { state = READY_TO_INTEGRATE; } } }
void hipAdcCallback(adcsample_t adcValue) { if (instance.state == WAITING_FOR_ADC_TO_SKIP) { instance.state = WAITING_FOR_RESULT_ADC; } else if (instance.state == WAITING_FOR_RESULT_ADC) { engine->knockVolts = adcValue * engine->adcToVoltageInputDividerCoefficient; hipValueMax = maxF(engine->knockVolts, hipValueMax); engine->knockLogic(engine->knockVolts); instance.handleValue(GET_RPM_VALUE DEFINE_PARAM_SUFFIX(PASS_HIP_PARAMS)); } }
void CJ125::SetHeater(float value DECLARE_ENGINE_PARAMETER_SUFFIX) { // limit duty cycle for sensor safety // todo: would be much nicer to have continuous function (vBatt) float maxDuty = (engine->sensors.vBatt > CJ125_HEATER_LIMITING_VOLTAGE) ? CJ125_HEATER_LIMITING_RATE : 1.0f; heaterDuty = (value < CJ125_HEATER_MIN_DUTY) ? 0.0f : minF(maxF(value, 0.0f), maxDuty); #ifdef CJ125_DEBUG scheduleMsg(logger, "cjSetHeater: %.2f", heaterDuty); #endif // a little trick to disable PWM if needed. // todo: this should be moved to wboHeaterControl.setPwmDutyCycle() // todo: is this really needed?! wboHeaterControl.setFrequency(heaterDuty == 0.0f ? NAN : CJ125_HEATER_PWM_FREQ); wboHeaterControl.setSimplePwmDutyCycle(heaterDuty); }
static int adjustCell(int i, int j, void (*callback)(int, float, float)) { int count = afrs.counts[i][j]; if (count < HOW_MANY_MEASURMENTS_ARE_NEEDED) return 0; float value = avgGetValueByIndexes(&afrs, i, j); afrs.counts[i][j] = 0; afrs.values[i][j] = 0; if (value < TARGET_MIN_AFR) { float currentMult = adjustments.values[i][j]; // printf("adj %d %d. cur=%f\r\n", i, j, currentMult); float newValue = maxF(0.1, MULT_STEP_DOWN * currentMult); adjustments.values[i][j] = newValue; // printf("adj %d %d. new=%f\r\n", i, j, adjustments.values[i][j]); if (callback != NULL) callback(MAX_RPM * i / AVG_TAB_SIZE, 1.0 * MAX_KEY * j / AVG_TAB_SIZE, newValue); return 1; } return 0; }
/* * Return current TPS position based on configured ADC levels, and adc * * */ percent_t getTpsValue(int adc DECLARE_ENGINE_PARAMETER_SUFFIX) { if (engineConfiguration->tpsMin == engineConfiguration->tpsMax) { warning(CUSTOM_INVALID_TPS_SETTING, "Invalid TPS configuration: same value %d", engineConfiguration->tpsMin); return NAN; } float result = interpolateMsg("TPS", TPS_TS_CONVERSION * engineConfiguration->tpsMax, 100, TPS_TS_CONVERSION * engineConfiguration->tpsMin, 0, adc); if (result < engineConfiguration->tpsErrorDetectionTooLow) { #if EFI_PROD_CODE // too much noise with simulator warning(OBD_Throttle_Position_Sensor_Circuit_Malfunction, "TPS too low: %.2f", result); #endif /* EFI_PROD_CODE */ } if (result > engineConfiguration->tpsErrorDetectionTooHigh) { #if EFI_PROD_CODE // too much noise with simulator warning(OBD_Throttle_Position_Sensor_Range_Performance_Problem, "TPS too high: %.2f", result); #endif /* EFI_PROD_CODE */ } // this would put the value into the 0-100 range return maxF(0, minF(100, result)); }
void LECalculator::doJob(Engine *engine, LEElement *element) { switch (element->action) { case LE_NUMERIC_VALUE: stack.push(element->fValue); break; case LE_OPERATOR_AND: { float v1 = pop(LE_OPERATOR_AND); float v2 = pop(LE_OPERATOR_AND); stack.push(float2bool(v1) && float2bool(v2)); } break; case LE_OPERATOR_OR: { float v1 = pop(LE_OPERATOR_OR); float v2 = pop(LE_OPERATOR_OR); stack.push(float2bool(v1) || float2bool(v2)); } break; case LE_OPERATOR_LESS: { // elements on stack are in reverse order float v2 = pop(LE_OPERATOR_LESS); float v1 = pop(LE_OPERATOR_LESS); stack.push(v1 < v2); } break; case LE_OPERATOR_NOT: { float v = pop(LE_OPERATOR_NOT); stack.push(!float2bool(v)); } break; case LE_OPERATOR_MORE: { // elements on stack are in reverse order float v2 = pop(LE_OPERATOR_MORE); float v1 = pop(LE_OPERATOR_MORE); stack.push(v1 > v2); } break; case LE_OPERATOR_ADDITION: { // elements on stack are in reverse order float v2 = pop(LE_OPERATOR_MORE); float v1 = pop(LE_OPERATOR_MORE); stack.push(v1 + v2); } break; case LE_OPERATOR_SUBSTRACTION: { // elements on stack are in reverse order float v2 = pop(LE_OPERATOR_MORE); float v1 = pop(LE_OPERATOR_MORE); stack.push(v1 - v2); } break; case LE_OPERATOR_MULTIPLICATION: { // elements on stack are in reverse order float v2 = pop(LE_OPERATOR_MORE); float v1 = pop(LE_OPERATOR_MORE); stack.push(v1 * v2); } break; case LE_OPERATOR_DIVISION: { // elements on stack are in reverse order float v2 = pop(LE_OPERATOR_MORE); float v1 = pop(LE_OPERATOR_MORE); stack.push(v1 / v2); } break; case LE_OPERATOR_LESS_OR_EQUAL: { // elements on stack are in reverse order float v2 = pop(LE_OPERATOR_LESS_OR_EQUAL); float v1 = pop(LE_OPERATOR_LESS_OR_EQUAL); stack.push(v1 <= v2); } break; case LE_OPERATOR_MORE_OR_EQUAL: { // elements on stack are in reverse order float v2 = pop(LE_OPERATOR_MORE_OR_EQUAL); float v1 = pop(LE_OPERATOR_MORE_OR_EQUAL); stack.push(v1 >= v2); } break; case LE_METHOD_IF: { // elements on stack are in reverse order float vFalse = pop(LE_METHOD_IF); float vTrue = pop(LE_METHOD_IF); float vCond = pop(LE_METHOD_IF); stack.push(vCond != 0 ? vTrue : vFalse); } break; case LE_METHOD_MAX: { float v2 = pop(LE_METHOD_MAX); float v1 = pop(LE_METHOD_MAX); stack.push(maxF(v1, v2)); } break; case LE_METHOD_MIN: { float v2 = pop(LE_METHOD_MIN); float v1 = pop(LE_METHOD_MIN); stack.push(minF(v1, v2)); } break; case LE_METHOD_FSIO_SETTING: { float i = pop(LE_METHOD_FSIO_SETTING); int index = (int) i; if (index >= 0 && index < LE_COMMAND_COUNT) { stack.push(engine->engineConfiguration->bc.fsio_setting[index]); } else { stack.push(NAN); } } break; case LE_UNDEFINED: firmwareError("Undefined not expected here"); break; default: stack.push(getLEValue(engine, &stack, element->action)); } }