//Injection_V2.0_12092 //Pour Circuit Imprimé changé piste pour I13 .Ecart ajustable entre injections //Première version qui va bien sauf pauvre en acceleration >4500t/mn //Sans capteur de temp DS18B20, avec AFR pour logger et pot à distance //Avec traitement de l'acceleration //Injection dès la detection de la cible au PMH allumage du cylindre 2 //Dinj extrait de TabDinj 11x11( merci G A pour la table complète!) //Dinj interpollée sur 4 cases //Correction multiplicative par DinjCor en %, via potard et au demarrage //Pap à zero, mesuré 0.3V sur AP soit 61 u sous 5V, pris 40 par securité //0.5V 5%, 3.9V 100% //Injecteur de 240cc/mn soit 4cc/s,0.25s=250ms par cc. //Mesuré sur carbu Weber DCOE 45, un jet de pompe de reprise = 0.2cc //50ms = 0.2cc pour une acceleration, et au demarrage, 3 jets = 0.6cc soit 150ms //*************Eventuellement ajustable****************** byte SS_SG = 1; //Semi sequentielle=1 une fois par cycle , Semi Full Group=2, 2 injections par cycle #define Ndem 400 //t/mn On admet quel'on est sous demarreur si N < Ndem #define Damorce 50 //ms A chaque mise de contact sauf si papillon >TPSdenoie. 0.2cc pour 50ms #define Dbp 150 //Durée d'injection en ms pour chaque impulsion sur le BP. 0.6cc pour 150ms #define TPSdenoie 70 //% mode denoyage si TPS >TPCdenoie, pas d'injection à la mise du contact ou sous demarreur #define DinjCorDem 400 //en % enrichissement sous demarreur #define AccCorMax 130 //Plafonnement de la correction d'acceleration en %, ex 130 #define PapDotPla 250 //Vitesse d'ouverture papillon en %/s , au delà Plafonnement de AccCor à AccCorMax, ex 250 #define Pente (AccCorMax - 100)/PapDotPla //Pente de la courbe d'acceleration voir AccelDetect() #define AccCycles 20 //Nombre de cycles enrichis pendant une acceleration, ex 20 //******************************************************* #include"TimerOne.h" #include //#include Capteur de température moteur DS18B20 //#include Bus 1 fil //const int busPin = 10; //Capteur de temperature moteur Sur D10 //OneWire bus(busPin); //Cree une instance de bus //DallasTemperature sensors(&bus); //DeviceAddress sensor; #define Cible A2 //Cible AàC #define I14 A3 //Paire d'injecteurs 1 et 4 activée par A0 #define I23 13//Paire d'injecteurs 2 et 3 activée par D13 #define AP A4 //Potard angle papillon.Sera traduit en TPS % Throttle Position Sensor #define PotCor A0 //OPTION: Potard pour correction manuelle d'injection #define AFR A6 //0 à 5V fourni par la sonde lambda linéaire Innovate #define Tmot A5 //Temperature moteur #define Tair A7 //Température air ambiant #define Vbat A1 //Tension de la batterie #define BP 2 //Bouton Poussoir pour injecter essence #define APumin 40 // unité de AP quand papillons au minimum absolu, 0.3V pour 7805=5V, théorie 61 #define APumax 794 // unité de AP quand papillons au maximum, 3.88V pour 7805=5V #define R 0.25 //Coefficient pour écart entre 2 injections du cycle.Voir Deig //0.25 donne 720deg*0.25 = 180deg, 0.75 donne 720deg*0.75 = 540deg. #define T0 0 // les TPS % ,lignes de TabDinj #define T1 3 #define T2 8 #define T3 15 #define T4 25 #define T5 35 #define T6 50 #define T7 65 #define T8 80 #define T9 90 #define T10 100 #define N0 700 // les t/mn,colonnes de TabIDinj #define N1 1100 #define N2 1500 #define N3 2100 #define N4 2700 #define N5 3300 #define N6 3900 #define N7 4500 #define N8 5100 #define N9 5600 #define N10 6000 byte TabDinj [11][11] = { //Durées d'injection brutes en unités de 100µs //6 13 18 22 28 33 38 43 47 50 Hz f Hz = N/120 //7 11 15 21 27 33 39 45 51 56 60 t/mn *100 {20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20}, //TPS% 0 {22, 22, 23, 23, 24, 24, 24, 24, 24, 24, 24}, //3 {26, 27, 27, 28, 28, 29, 29, 29, 29, 29, 29}, //8 {31, 32, 32, 33, 34, 35, 35, 35, 35, 35, 35}, //15 {38, 39, 40, 41, 43, 44, 46, 46, 46, 46, 46}, //25 {45, 46, 47, 49, 51, 53, 54, 55, 55, 55, 55}, //35 {45, 48, 52, 55, 58, 61, 65, 67, 68, 68, 69}, //50 {45, 48, 51, 54, 59, 64, 70, 73, 75, 75, 75}, //65 {45, 49, 51, 55, 61, 65, 72, 76, 79, 80, 82}, //80 {45, 48, 51, 56, 61, 67, 72, 77, 81, 83, 84}, //90 {45, 48, 52, 55, 61, 67, 73, 79, 82, 84, 86} //100 }; float Sv; float Sp; byte Pap = 0; //Papillon (ligne)pour entrer dans TabDinj, de 0 à PapMax byte Reg = 0; //Regime (colonne) pour entrer dans TabDinj, de 0 à RegMax byte PapMax = 10; //Denière ligne 0 à 10 byte RegMax = 10; //NDernière colonne 0 à 10 byte Prem = 1 ;//Flag pour ignorer la première injection int long unsigned K = 0; //Pour fonction d'attente DelayK() Kµs float TPS = 0; //Throttle Position Sensor, donc AP converti entre 0 et 100% float DinjCor = 0 ; //en %, correctif de durée d'injection imposée par potard ou au demarrage float AccCor = 100; //Correction en % type pompe de reprise durant une acceleration int long unsigned prec_H = 0; //Heure precedente en µs float D720 = 0; // Durée du cycle en cours en µs, 720°vilo, 2 tours //float D180 = 0; //Durée de 180° en µS pour le cycle en cours float Deig = 0; //Durée en µs entre deux injections dans un cycle: 180 ou 540deg par exemple, voir R float N = 0; //N en t/mn float Dinj = 0; //Durée d'une injection en µs, pour les TIMERs int Dsup = 0; //en ms, injection supplementaire, demarrage ou BP int APu = 0; //AP en unités 0-1023 Angle Papillon int AFRu = 0; //AFR en unités 0-1023 int PotCoru = 0; //PotCor en unités 0-1023 float CT = 0; //Coefficient des TPS% pour interpollation float CN = 0; //Coefficient des Nt/mn pour interpollation int micro_delay = 0; // Pour attendre Deig µs <16000µs int milli_delay = 0; // ::::::::::::::::::::: au delà float Tm = 0; //Temperature moteur int TPSprec = 0; //TPS du cycle precedent pour detecter un acceleration float PapDot = 0; //Dérivée de TPS par rapport au temps, typique 200% en acceleration, mini 25% int AccCt = 0; //Compteur de cycles enrichis pendant une acceleration //***********************FONCTIONS************************************** void AccDetect()///////////////////////////////////////////////// { //Correction de l'injection, type pompe de reprise si vitesse du papillon assez grande //L'enrichissement AccCor sera maintenu pendant AccCt cycles // if((TPS-TPSprec)>=3) //Ignorer le petites variations AccCor = 100; //Pas de correction, 100% AccCt = 0; PapDot = ((TPS - TPSprec) / D720) * 1000000; //Dérivée de la position/temps= vitesse TPSprec = TPS; //On memorise l'ancienne position du papillon if (PapDot >= 25) //On ignore les petites vitesses { AccCt = AccCycles; // Initialise le compteur de cycles à enrichir AccCor = PapDot * Pente + 100; //Calcul de la correction à appliquer à Dinj if (AccCor >= AccCorMax)AccCor = AccCorMax; //On plafonne la correction } // Serial.print(PapDot); Serial.print(TPS); Serial.println(TPSprec); } void Active1423()/////////////////////////////////////////////////////////// { if (Dinj != 0) //Injecte sauf si Dinj=0, en denoyage { //Dinj = Dinj + 900; //0.9ms ajoutés pour etre proportionnel Timer1.initialize(Dinj);//Lancer TMR1 qui coupera l'injection digitalWrite(I14, 1); //Alimenter les injecteurs 1 et 4 // digitalWrite(Led, 1); K = Deig; DelayK(); // Attendre entre 2 injections //FlexiTimer2 unité mini =10µs,mais 100µs plus precis donc on divise Dinj par 100 FlexiTimer2::set(Dinj / 100, 0.1 / 1000, isr_Fin_23); // Definition 100µs FlexiTimer2::start(); digitalWrite(I23, 1); //Alimenter les injecteurs 2 et 3 // digitalWrite(Led, 1);//Allume la led } } void CalcReg()//////////////////////////////////////////////////////////////// //Calcul le numero de colonne en fonction du régime N //ainsi que le coefficient CN pour interpoller Dinj dans la table { // N10 limite supérieure, on commence à comparer à N9 if (N > N9) { Reg = 9;//Reg numero de colonne dans TabDinj CN = (N - N9) / (N10 - N9); // Pour interpollation return; } if (N > N8) { Reg = 8; CN = (N - N8) / (N9 - N8); return; } if (N > N7) { Reg = 7; CN = (N - N7) / (N8 - N7); return; } if (N > N6) { Reg = 6; CN = (N - N6) / (N7 - N6); return; } if (N > N5) { Reg = 5; CN = (N - N5) / (N6 - N5); return; } if (N > N4) { Reg = 4; CN = (N - N4) / (N5 - N4); return; } if (N > N3) { Reg = 3; CN = (N - N3) / (N4 - N3); return; } if (N > N2) { Reg = 2; CN = (N - N2) / (N3 - N2); return; } if (N > N1) { Reg = 1; CN = (N - N1) / (N2 - N1); return; } Reg = 0; CN = (N - N0) / (N1 - N0); } void CalcPap()////////////////////////////////////////////////////////// //Calcul le numero de ligne en fonction du TPS //ainsi que le coefficient CT pour interpoller { // T10 limite supérieure, on commence à comparer à T9 if (TPS > T9) { Pap = 9; CT = (TPS - T9) / (T10 - T9); // Pour interpollation return; } if (TPS > T8) { Pap = 8; CT = (TPS - T8) / (T9 - T8); return; } if (TPS > T7) { Pap = 7; CT = (TPS - T7) / (T8 - T7); return; } if (TPS > T6) { Pap = 6; CT = (TPS - T6) / (T7 - T6); return; } if (TPS > T5) { Pap = 5; CT = (TPS - T5) / (T6 - T5); return; } if (TPS > T4) { Pap = 4; CT = (TPS - T4) / (T5 - T4); return; } if (TPS > T3) { Pap = 3; CT = (TPS - T3) / (T4 - T3); return; } if (TPS > T2) { Pap = 2; CT = (TPS - T2) / (T3 - T2); return; } if (TPS > T1) { Pap = 1; CT = (TPS - T1) / (T2 - T1); return; } Pap = 0; CT = (TPS - T0) / (T1 - T0); } void DelayK()//////////////////////////////////////////////////////////// { if (K < 14000) { // delayMicroseconds est limité à 16383µs delayMicroseconds(K); //OK pas trop long } else { milli_delay = ((K / 1000) - 2);//Pour ces Deig longs,utiliser delay()en ms micro_delay = (K - (milli_delay * 1000)); delay(milli_delay); // delayMicroseconds(micro_delay); } // Affiche();// Affiche N, AP et Dinj sur Sphone } void InjBP()/////////////////////////////////////////// { while (digitalRead(BP) == 0) //BP poussé? injection manuelle { Dsup = Dbp; //Dbp typique pour 1cc InjSup();//Injecter Dsup ms delay(500); //Attendre un peu } } void InjSup()///////////////////////////////// { //Attention, ms et non µs. //Injection supplementaire au BP ou à la mise du contact ou sous demarreur digitalWrite(I14, 1); //Alimenter les 4 injecteurs simultanément digitalWrite(I23, 1); delay(Dsup); //Ex 250ms = 1cc pour injecteur de 240cc/mn digitalWrite(I14, 0); //Arreter l'injection digitalWrite(I23, 0); } void isr_Fin_14()///////////////////////////////////////////// { Timer1.stop(); digitalWrite(I14, 0); //Couper les injecteurs 1 et 4 // digitalWrite(Led, 0); } void isr_Fin_23()//////////////////////////////////////////////////// { FlexiTimer2::stop(); digitalWrite(I23, 0); //Couper les injecteurs 2 et 3 // digitalWrite(Led, 0); } //void Lec_AFR() //{ AFRu = analogRead(AFR); // AFRv = map(AFRu, 0, 1023, 74, 221); // AFR valeur entre 7.4 et 22.1 //} void Lec_AP()//////////////////////////////////////////////////////////// { APu = analogRead(AP); TPS = map(APu, APumin, APumax, 0, 100); // TPS 0 à 100% if (TPS >= 100)TPS = 100; //A tout hasard //Serial.print("TPS et prec ");Serial.print(TPS);Serial.println(TPSprec); } void Lec_PotCor() ////////////////////////////////////////////////////////// //Pour une correction en %, 80 à gauche, 100 au milieu 120 à droite //S'applique au DinjCor precedent quelqu'il soit { PotCoru = analogRead(PotCor); DinjCor = (DinjCor * map(PotCoru, 0, 1023, 80, 120)) / 100; //Pour DinjCor } //void LecTempMot()////////////////////////////////////////// //{ // sensors.requestTemperatures(); // Tmot = sensors.getTempC(sensor); // Serial.println(Tmot); // delay(1000); //} void Prep_Dinj()/////////////////////////////////////////////////////////////// { Lec_PotCor();//Ajuste DinjCor CalcPap(); //Calcul la ligne de TabDinj suivant l'ouverture TPS CalcReg(); //Calcul la colonne de TabDinj suivant le regime N Dinj = TabDinj[Pap][Reg] ; //Extrait la durée d'injection brute en unités de 100µs // Sv=Dinj; // Serial.print("Pap"); Serial.println(Pap); // Serial.print("Reg"); Serial.println(Reg); // Serial.print("Dinj brut");Serial.println(Dinj); // Serial.print("CT"); Serial.println(CT); // Serial.print("CN"); Serial.println(CN); // Serial.print("Dinj µs avant interp "); Serial.println(Dinj * 100); //Dinj calculé par interpollation sur les 4 valeurs de la case puis convertie en µs Dinj = (TabDinj[Pap][Reg] * (1 - CT) * (1 - CN) + TabDinj[Pap + 1][Reg] * CT * (1 - CN) + TabDinj[Pap + 1][Reg + 1] * CT * CN + TabDinj[Pap][Reg + 1] * (1 - CT) * CN) * 100; //Sp=Dinj; // Serial.println(N); Serial.println(Dinj); // Serial.print("Dinj aprés interp "); Serial.println(Dinj); Dinj = Dinj * DinjCor / 100; //Dinj final aprés les correction en % cumulées dans DinjCor, sous demarreur ou potard // Serial.println(AccCor); Serial.println(AccCt); if (AccCt >= 1) { //En phase d'acceleration, un cycle de plus Dinj = Dinj * AccCor / 100; AccCt--; } } void setup()///////////////////////////////////////////////////////////////////////////////// { pinMode(A0, OUTPUT); pinMode(A1, INPUT_PULLUP); Serial.begin(115200); //Pour moniteur PC Serial.println("Hello"); // BT.begin(115200); //Pour Sphone, Bluetooth pinMode(Cible, INPUT_PULLUP); //Vient du capteur Hall, detection sur frontdescendant pinMode(I14, OUTPUT); //Gate de l'IGBT pinMode(I23, OUTPUT); //Gate de l'IGBT // pinMode(Led, OUTPUT); //Suit les injections pinMode(BP, INPUT_PULLUP); //BP d'injection d'essence //Simule "Coup d'accelerateur, pompe de reprise carbu" à chaque démarrage. Dsup = Damorce; //Preparer un jet de 1cc environ if (TPS <= TPSdenoie)InjSup(); //sauf si pédale au plancher= denoyage Timer1.attachInterrupt(isr_Fin_14); //Tmr1 deconnectera le couple 14 // Pour Timer2 qui deconnectera le couple 23 voir Active1423() //Detection du capteur de temperature DS18B20 // sensors.begin(); // if (!sensors.getAddress(sensor, 0)) //Va lire rechercher sur 8 bytes du capteur // { // Serial.println("NO DS18B20 FOUND!"); //Probleme! // } } void loop()/////////////////////////////////////////////////////////////////////////////////// { InjBP(); //Injection manuelle? while (digitalRead(Cible) == 1)InjBP(); //Pendant l'attente du passage à 0 de la cible, injection manuelle? //Cible detectée D720 = micros() - prec_H; // Durée de 2 tours vilo = 1 tour AàC prec_H = micros(); //Nouvelle heure de reference //D180 = D720 / 4; //Delai entre l'injection des 2 paires Deig = D720 *R; //Delai entre l'injection des 2 paires, typique 180 ou 540deg N = 120000000 / D720; //N en t/mn Lec_AP();// Angle TPS prend environ 200µs //TPS=100; //Serial.println(micros()- prec_H);// if (Prem != 1) //Pour la première injection, Prem = 1, ne rien faire { //Serial.println(N); DinjCor = 100; //Pas de correction //Au demarrage, soit on denoie( pas d'injection) soit on enrichit if (N < Ndem) { if (TPS >= TPSdenoie)DinjCor = 0; //A moduler avec Tmot, plus tard else DinjCor = DinjCorDem; //Enrichir, typique 400% } // AccDetect(); if (AccCt == 0)AccDetect(); //Pas d'acceleration en cours voir si on accélère assez fort pour simuler les pompes de reprise Prep_Dinj();//Calcul Dinj en µs, et applique le correctif DinjCor // Serial.println(Dinj); { if (SS_SG == 2)Dinj = Dinj / 2; // Semi full group on injecte en 2 fois Active1423(); if (SS_SG == 2) { K = Deig; DelayK(); Active1423(); //Injection en 2 fois } } } while (digitalRead(Cible) == 0); //Attente retour à 1, cible dépassée Prem = 0; // La première injection a été ignorée // Serial.print("Dinj v");Serial.println(Sv); // Serial.print("Dinj p");Serial.println(Sp); } // sketch_08_02_OneWire_DS18B20 // Affiche(); //Serial.print(TabDinj [2][3]); //while (1)// Pour afficher les potards //{Lec_AP(); // Serial.print("TPS= ");Serial.println(TPS); Serial.println(APu); Serial.println(); // delay(3000); // Lec_PotCor(); // Serial.print("DinjCor = ");Serial.println(DinjCor); Serial.println(PotCoru);Serial.println(); // delay(3000); //} //void Affiche()/////////////////////////////////////////////////////////////// //{ Serial.println("****Essais injection****");// BT.println("****Essais injection****"); // Serial.println();// BT.println(); // Serial.print("N t/mn "); Serial.println(N); // // BT.print("N t/mn "); BT.println(N); // Serial.print("Angle Pap % "); Serial.println(TPS); // // BT.print("Angle Pap % "); BT.println(TPS); // Serial.print("Dinj µs "); Serial.println(Dinj); // // BT.print("Dinj µs "); BT.println(Dinj); // // Serial.print("DinjCor µs "); Serial.println(DinjCor); // Serial.print("Pap "); Serial.println(Pap); // Serial.print("Reg "); Serial.println(Reg); //}