Files
hpsg5-controller_v2-stm32g4/Core/Src/injection.c

477 lines
13 KiB
C

/*
* injection.c
*
* Created on: Aug 4, 2025
* Author: herli
*/
#include <id.h>
#include "injection.h"
#include "main.h"
#include "toothed_wheel.h"
#include "tein_detection.h"
#include "fuel_map.h"
#include "temperature.h"
#include "timeouts.h"
#include "timing_manager.h"
#if HAS_PREINJECTION
#include "pre_injection.h"
#endif
static inline void TIM1_OC4_SetSafe(uint16_t ccr4_new);
float INJ_UPDATE_TARGET_EOI();
float PHI_AD = 1.875;
uint8_t angleMode = 0;
volatile uint8_t isInjecting;
volatile uint8_t hasInjected = 0;
volatile uint8_t hasInjectionEnded = 1;
volatile uint8_t hasInjectionEndedFlag = 0;
uint8_t inj_mode = 0;
uint8_t InjectionPrescaler = 16;
float dFi = 0;
uint8_t INJ_EOI_COMPENSATION = 0;
uint32_t T_on = 0; //Time on in microseconds
uint16_t T_peak = 600;
uint32_t T_delayFI = 150;
uint32_t T_delay = 0;
uint32_t T_hold = 0;
uint32_t T_injecting = 0;
float target_eoi = 0;
float boostmult = 0;
uint8_t triggerTeeth;
uint8_t blankInj = 0;
uint8_t cilCount;
uint8_t retardteeth = 1;
float current_Alpha = 0; //Alpha is the angle corresponding to time-on
float current_Beta = 0.0; //Beta is the angle corresponding to FI delay
float corrected_Beta = 0.0;
float forceTemp = 35.6;
extern float next_MT_RPM;
int missed = 0;
void INJ_MT_TASK(){
INJ_END();
if(!hasInjected && !blankInj){
missed++;
}
hasInjected = 0;
hasInjectionEnded = 0;
hasInjectionEndedFlag = 0;
triggerTeeth = 0;
#if HAS_PREINJECTION
PI_EVAL(RPM, ME, MEPI);
#endif
}
extern float nominal_bip_angle;
float lastEOI = 0;
extern float last_accel;
uint8_t awaitingInj = 0;
float INJ_GET_NOMINAL_EOI();
void INJ_UPDATE_ALPHA(){
/*float rp_sum = MT_RPM + last_MT_RPM;
float dt = (PHI1 + dFi) / 90 * (1.0f / CYLINDERS) * (120.0f / rp_sum);
// B) Predict the RPM at that firing time, if you need it
float rpm_at_phiad = MT_RPM + last_accel*dt;*/
//FM_GET_PHIAD(MT_RPM, ME, forceTemp);
//correction_eoi_accel = TM_GET_ACCEL_CORRECTION(last_MT_RPM, MT_RPM, TEETH_RPM);
FM_GET_PHIAD(MT_RPM, ME, forceTemp);
float target = INJ_UPDATE_TARGET_EOI() + correction_eoi;
//current_Alpha = PHI_AD + nominal_bip_angle - corrected_Beta;
current_Alpha = target - (PHI1 + dFi ); //+ correction_beta
//current_Alpha = GetAlpha(RPM, ME, T_ein, forceTemp); //PHIAD map
if (INJ_CLOSING_MARGIN){
current_Alpha += TIMETODEG(INJ_CLOSING_MARGIN, TEETH_RPM);
}
current_Alpha = current_Alpha < 0.1 ? 0 : current_Alpha;
boostmult = BoostMultiplier(inj_mode, RPM, ME);
current_Alpha *= boostmult;
}
void INJ_EVAL_EOI_COMPENSATION(){
/*if(!isInjecting){
compensatingEOI = (current_Alpha > 3 ) ? 1 : 0; //antes estaba con ton, pero si el me va bajando poco a poco, de el anterior pulso tiene ton,
}*/
//esto la verdad no se muy bien para que esta....
}
uint8_t margin_curr_us = 70;
float margin_deg = 0.3;
void INJ_UPDATE_BOI_MARGIN(float rpm){
margin_deg = rpm * (T_delay + margin_curr_us)* USTODEG; //
margin_deg = fclamp(margin_deg, 0.0001, 10);
}
void INJ_PREPARE_ONCE(){
if(RPM < 800){
InjectionPrescaler = 1;
TIM1->PSC = 160-1;
}else{
InjectionPrescaler = 8;
TIM1->PSC = 20-1;
}
INJ_PREPARE_BIP(0);
INJ_UPDATE_ALPHA();
INJ_UPDATE_TYPE();
}
extern float correction_boi_accel_2;
extern float s_boi_corr_deg;
void INJ_PREPARE_BIP(uint8_t teeth){
if(teeth < triggerTeeth || !triggerTeeth)
{
INJ_UPDATE_BOI_TRIGGER();
INJ_UPDATE_ALPHA();
}
//correction_boi_accel_2 = TM_UPDATE_ACCEL_CORRECTION_BIP(last_MT_RPM, MT_RPM, TEETH_RPM);
//correction_beta = s_boi_corr_deg + correction_boi_accel_2;
INJ_UPDATE_T_Delay_phi(); //THIS should be updated more times if it is using predictive rpm
//TM_GET_ACCEL_CORRECTION(last_MT_RPM, MT_RPM, TEETH_RPM);
}
void INJ_UPDATE_T_Delay_phi(){
//float time = TM_INTEGRATE_TIME_BIP(PHI1 + dFi + correction_beta, triggerTeeth) + 0.5f;
//float time = TM_INTEGRATE_TIME_BIP(PHI1 + dFi + correction_beta, triggerTeeth) + 0.5f;
float time = (PHI1 + dFi + correction_beta - triggerTeeth * TW_TOOTH_ALPHA)/(USTODEG * TEETH_RPM)+ 0.5f;
T_delayFI = time - T_ein + TEIN_READING_OFFSET;
}
uint16_t t1, t2, t3, t4;
extern float last_INJECTING_RPM;
float eq_rpm;
void INJ_UPDATE_TYPE(){
if(eq_rpm < 20){ eq_rpm = TEETH_RPM;}///1.8;
//if(eq_rpm < )
T_injecting = DEGTOTIME(current_Alpha, eq_rpm*0.6);
blankInj = T_injecting ? 0 : 1;
T_peak = ((T_ein > 800 && CompensateTein) ? T_ein - 200 : PH_PEAK_DEF);
T_hold = T_injecting ? T_ein + T_injecting - T_peak : 0;
//T_hold = (ME > 0.04 && T_hold < 340)? 340 : T_hold; //a ver si
T_ein_filtered = (T_hold < 260 || !CompensateTein) ? 800 : T_ein_filtered;
compensatingEOI = T_hold < 260 ? 0 : 1; //wtf compensatingEOI
if(!T_hold){
T_peak = 174;
}else if(T_hold < 260){
T_peak = 600;
T_hold = 270;
}
t1 = (T_delayFI - T_delay) * InjectionPrescaler; //
t2 = t1 + T_peak * InjectionPrescaler;
t3 = t1 + AcquisitionTime * InjectionPrescaler;
t4 = blankInj ? t2 + 1 : t2 + (T_hold + INJ_CLOSING_MARGIN) * InjectionPrescaler;
}
uint8_t accel_calc=0;
void EvaluateInjection(){
//AJUSTADO PARA 40mV histeresis de comparador, mayor histeresis mayor retraso de la inyeccion.
if(currentTooth == triggerTeeth && !safetySHUTOFF){
INJ_UPDATE_T_Delay_phi(); //THIS should be updated more times if it is using predictive rpm
t1 = (T_delayFI - T_delay) * InjectionPrescaler; //
t2 = t1 + T_peak * InjectionPrescaler;
t3 = t1 + AcquisitionTime * InjectionPrescaler;
t4 = blankInj ? t2 + 1 : t2 + (T_hold + INJ_CLOSING_MARGIN) * InjectionPrescaler;
if(t1 && t2 && t4){
if(t1 < t2 && t2 <= t4){
TIM1->CCR1 = t1;
TIM1->CCR2 = t2;
TIM1->CCR3 = t3; // End time (sampling end)
TIM1->CCR4 = t4;
}
}
TIM1->CNT = 0;
TIM1->EGR = TIM_EGR_UG;
TIM1->CR1 = TIM_CR1_OPM | TIM_CR1_CEN;
cilCount++;
cilCount%=CYLINDERS;
hasInjected = 1;
awaitingInj = 1;
accel_calc = 0;
eq_rpm = TEETH_RPM;
}
}
void INJ_UPDATE_BOI_TRIGGER(){
//current_Beta = GetBeta(TEETH_RPM, T_ein) + dFi;
/*current_Beta = PHI1 + dFi - T_ein*USTODEG*TEETH_RPM;
current_Beta = fclamp(current_Beta, 0, 90);
corrected_Beta = current_Beta + correction_beta;*/
//triggerTeeth = (corrected_Beta - margin_deg) / TW_TOOTH_ALPHA; //margen a ver si mejora
uint8_t id = TM_GET_TRIGGER_TEETH_FROM_REFERENCE_AND_TIME(PHI1 + dFi + correction_beta, T_ein + T_delay + margin_curr_us);
if(id){
uint8_t idd = id-retardteeth;
if(RPM < 1000){
idd--;
}
triggerTeeth = idd > TW_PERCYL_TEETH ? TW_PERCYL_TEETH : idd;
triggerTeeth = idd < 0 ? 0 : idd;
}
//triggerTeeth = retardteeth;
}
int mode;
float dalpha_teinstatus = 0;
extern float correction_eoi_accel;
extern float actual_phi1;
extern uint8_t real_bip_updated;
uint8_t using_real_phi1 = 0;
float dPHIAD_Tein=0;
float min_dPHIAD_Tein=-21;
float min_alpha=0.3; //1
float lpf_target = 1;
uint8_t closingTooth = 0;
float margin_eoi_tooth = 3;
float INJ_UPDATE_TARGET_EOI(){
//INJ_UPDATE_ALPHA();
//FM_GET_PHIAD(MT_RPM, ME, forceTemp);
dPHIAD_Tein = fclamp(TM_GET_PHIAD_dTEIN(PHI1 + dFi + PHI_AD, MT_RPM), min_dPHIAD_Tein, 0); //+ dPHIAD_Tein + correction_beta
//+ correction_beta
TM_GET_ACCEL_CORRECTION(last_MT_RPM, MT_RPM, TEETH_RPM, triggerTeeth);
//float new_target_eoi = PHI1 + dFi + dPHIAD_Tein + PHI_AD + correction_eoi_accel;//(using_real_phi1 ? actual_phi1 : PHI1 + dFi + correction_beta)
float new_target_eoi = PHI1 + dFi + correction_eoi_accel;//PHI_AD > 1 ?
if(ME > 0.04){
new_target_eoi += fclamp(dPHIAD_Tein + PHI_AD, RPM < 2100 ? min_alpha : 5.5, 90);
}else{
new_target_eoi += dPHIAD_Tein + PHI_AD;
}
//target_eoi = PHI1 + dFi + correction_beta + dPHIAD_Tein + PHI_AD + correction_eoi_accel;//(using_real_phi1 ? actual_phi1 : PHI1 + dFi + correction_beta)
/*if(!T_ein_status){
float d_tein_angle = target_eoi - TM_INTEGRATE_ANGLE_FROM_NEAREST_TOOTH(IC_EOI + 16*PH_PEAK_DEF,1);
new_target_eoi += d_tein_angle ;
}*/
target_eoi += lpf_target*(new_target_eoi-target_eoi);
//target_eoi = new_target_eoi;
//target_eoi = new_target_eoi;
closingTooth = (uint8_t)((target_eoi - margin_eoi_tooth)/TW_TOOTH_ALPHA);
return target_eoi;
}
float INJ_GET_TARGET_EOI(){
return target_eoi;
}
float INJ_GET_NOMINAL_EOI(){
return PHI1 + dFi + PHI_AD + dPHIAD_Tein;
}
uint32_t T_integrated;
extern float real_eoi;
float lpf_fastamount = 1;
float min = -100;
float max = 100;
float K_rpm = .1;
float max_slow = 0.8;
float min_slow = 0.0;
float fastAmount = 0.0;
float fastAmount_lpf = 0.0;
float new_fastAmount = 1.0;
float fA_m = 0.5;
float fA_n = 0;
float margineq = 6;
float lastTooth = 0.0;
void INJ_EVAL_END(){
if(isInjecting && compensatingEOI){ //esto solo lo hace en el ultimo diente, vamos a probar updatearlo en cada diente
uint16_t now = TIM1->CNT;
//float target = INJ_GET_TARGET_EOI() + correction_eoi;
/*if(0){
FM_GET_PHIAD(MT_RPM, ME, forceTemp);
}*/
float target = INJ_UPDATE_TARGET_EOI() + correction_eoi;
//float b_a = target +using_real_phi1*(actual_phi1 -PHI1 - dFi)- TW_TOOTH_ALPHA*currentTooth; //remaining angle + correction_eoi
float b_a = target - TW_TOOTH_ALPHA*currentTooth; //remaining angle + correction_eoi
if(real_bip_updated){
float dif = (actual_phi1 - PHI1 - dFi);
b_a += dif*fA_m;
}
//eq_rpm = fclamp(TEETH_RPM, edgeBuf[triggerTeeth].rpm *fA_m ,edgeBuf[triggerTeeth].rpm);
//if(TIM1->CNT > TIM1->CCR1 + (T_ein + 200) * InjectionPrescaler){
//if(b_a < margineq ){//b_a < 6margin_eoi_tooth
if(currentTooth >= closingTooth ){//b_a < 6margin_eoi_tooth
T_injecting = DEGTOTIME(b_a, TEETH_RPM); //eq_rpm
//T_integrated = T_injecting;
//uint32_t t4 = (T_integrated - TM_GET_T_DELAY_END()) * InjectionPrescaler; //los 25 es por el cambio de topologia, para que cierre al mismo tiempo
TIM1_OC4_SetSafe((uint16_t)(now +(T_injecting - TM_GET_T_DELAY_END()) * InjectionPrescaler));
lastTooth = currentTooth;
compensatingEOI = 0;
return;
//to not compensate nothing more
}else{
T_injecting = DEGTOTIME(b_a, TEETH_RPM*0.9); //retard ass line
TIM1_OC4_SetSafe((uint16_t)(now +(T_injecting - TM_GET_T_DELAY_END()) * InjectionPrescaler));
return;
}
//uint32_t T_current = TIM1->CCR4 - TIM1->CNT;
//float T_remaining_nom = 1.0f * T_current / InjectionPrescaler;
//float T_remaining_comp = T_remaining_nom - lpf_eoi*(T_remaining_nom - b_a/(TEETH_RPM)/USTODEG);
//if(!T_integrated){ T_integrated = T_current;}
//T_integrated = TM_INTEGRATE_TIME_FROM_REFERENCE_Forward(target, currentTooth, PHI1 + dFi) + 0.5f;
T_integrated = TM_INTEGRATE_TIME_TO_EOI(target, currentTooth) + 0.5f ;// - TEIN_NOMINAL
//-!T_ein_status*PH_PEAK_DEF
//T_integrated -= 0.5*(1.0f * T_current - b_a/(TEETH_RPM)/USTODEG);
//T_integrated = T_remaining_comp;
/*if(b_a > 4.5){ //schedule for next teeth + 50%
T_integrated = DEGTOTIME(b_a*1.5, TEETH_RPM);
}else{
T_integrated = TM_INTEGRATE_TIME_FROM_REFERENCE_Forward(target, currentTooth, PHI1 + dFi);
lastEOI = target;
}*/
uint32_t t4 = (T_integrated - TM_GET_T_DELAY_END()) * InjectionPrescaler; //los 25 es por el cambio de topologia, para que cierre al mismo tiempo
TIM1_OC4_SetSafe((uint16_t)(now + t4));
}
}
void INJ_SET_DAC(uint8_t isPeak)
{
if(!awaitingInj) return;
if(isPeak){
isInjecting = 1;
uint16_t dato_dac = (uint16_t)(((isPeak - 1)? V_PEAK : V_HOLD )*4095/3.30); //4095 in 12 bit, 255 in 8 bit
HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, dato_dac); //channel 2 es el que usamos
if(isPeak - 1){
HAL_GPIO_WritePin(HOLD_CONTROL_GPIO_Port, HOLD_CONTROL_Pin, GPIO_PIN_SET);
}
}else{
HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0); //channel 2 es el que usamos
isInjecting = 0;
HAL_GPIO_WritePin(HOLD_CONTROL_GPIO_Port, HOLD_CONTROL_Pin, GPIO_PIN_RESET);
}
}
void INJ_END(){
if(isInjecting){
INJ_SET_DAC(0);
HAL_GPIO_WritePin(HOLD_CONTROL_GPIO_Port, HOLD_CONTROL_Pin, GPIO_PIN_RESET);
TW_DEFER_EOI_EVAL(TIM2->CNT);
hasInjectionEndedFlag = 1;
}
//TW_DEFER_TEIN_VAL(); //freaky aah angle USELESS I THINK
}
void FORCE_INJ_END(){
/*HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 0); //channel 2 es el que usamos
HAL_GPIO_WritePin(HOLD_CONTROL_GPIO_Port, HOLD_CONTROL_Pin, GPIO_PIN_RESET);
TW_DEFER_EOI_EVAL(TIM2->CNT);
hasInjectionEnded = 1;*/
//TW_DEFER_TEIN_VAL(); //freaky aah angle USELESS I THINK
}
float DEGTOTIME(float DEG, float revs){
float TIME = 1000000 / (revs * 6) * DEG; //IN MICROSECONDS
return TIME;
}
float TIMETODEG(float TIME, float revs){
float DEG = (revs * 6) * TIME / 1000000 ; //IN MICROSECONDS
return DEG;
}
static inline void TIM1_OC4_SetSafe(uint16_t ccr4_new)
{
//uint16_t cnt = TIM1->CNT;
if(ccr4_new > TIM1->CCR2){
TIM1->CCR4 = ccr4_new;
}
__DSB(); // ensure the write hits the peripheral before we test
// If the compare time is already due or effectively "now", kill the pulse now.
// Keep the threshold at 0 or 1 tick depending on your clock/propagation.
if (ccr4_new < TIM1->CNT) {
/*// Force OC4 inactive (OC4M = 100)
uint32_t ccmr2 = TIM1->CCMR2;
ccmr2 &= ~TIM_CCMR2_OC4M;
ccmr2 |= (4U << TIM_CCMR2_OC4M_Pos); // Forced inactive
TIM1->CCMR2 = ccmr2;
__DSB();
// Restore back to PWM/OC mode (e.g., PWM1 = 110)
ccmr2 &= ~TIM_CCMR2_OC4M;
ccmr2 |= (6U << TIM_CCMR2_OC4M_Pos);
TIM1->CCMR2 = ccmr2;
__DSB();*/
INJ_END();
}
}
extern uint8_t startupiscar;
void SEND1_Handler(
const struct CanMessageDef *msg,
const uint8_t in_data[8],
CanTxFn tx
)
{
#if defined(T06301)
startupiscar = 1;
#endif
if(!isInjecting && !hasInjectionEnded){
INJ_UPDATE_ALPHA();
}
}