//Injection_V1.1_021019 //Pas de PotCor ni affichage dans DelayK //D4 devenu D5............ //Injection dès la detection de la cible ¨PMH allumage du cylindre 2 // Dinj extrait de TabDinj ( Gégé) 6x6 pour commencer //Correction additive à Dinj par PotCor //Dinj interpollée sur 4 cases byte SS_SG = 1; //Semi sequentielle=1, Semi Full Group=2 //C'est le nombre d'injection par cycle ( 2 tours de vilo) pour un cylindre #include"TimerOne.h" #include #include //Pour Bluetooth BT SoftwareSerial BT(10, 11); // RX,TX respectivement vers le HC05/06 à 115200bps #define Cible 2 //Cible AàC sur D2, Interruption 0 #define I14 5//Paire d'injecteurs 1 et 4 activée par D5 #define I23 3//Paire d'injecteurs 2 et 3 activée par D3 #define AP A0 //Potard angle papillon #define PotCor A2 //OPTION: Potard pour correction manuelle d'injection #define Led 13 //Celle de l'Arduino #define T0 0 // les TPS % ,lignes de TabInj #define T1 3 #define T2 8 #define T3 15 #define T4 25 #define T5 35 #define N0 700 // les t/mn,colonnes de TabInj #define N1 1100 #define N2 1500 #define N3 2100 #define N4 2700 #define N5 3300 byte TabDinj [6][6] = { //Durées d'injection brutes en unités de 100µs {20, 20, 20, 20, 20, 20}, {22, 22, 23, 23, 24, 25}, {26, 27, 27, 28, 29, 29}, {31, 32, 32, 33, 34, 35}, {38, 39, 40, 41, 43, 44}, {45, 46, 47, 49, 51, 53} }; //#define AFR A1 //0 à 5V fourni par la sonde lambda linéaire Innovate //#define Tmot A3 //Temperature moteur //#define Tmot A4 //Temperature d'air ambiant 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 = 5; //Nombre de lignes byte RegMax = 5; //Nombre de colonnes int long unsigned K = 0; //Pour fonction d'attente DelayK() Kµs volatile byte Cycle = 0; //Flag de detection de la cible de PMH. "Volatile" indispensable!? byte TPS = 0; //Throttle Position Sensor, donc AP converti entre 0 et 100% int long DinjCor = 0 ; //Durée d'injection corrigée par potard, 1000 à 15000µs volatile 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 N = 0; //N en t/mn float Dinj = 0; //Durée d'une injection en µs, pour les TIMERs int APu = 0; //AP en unités 0-1023 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 milli_delay = 0; // Pour attendre D180µs int micro_delay = 0; // Pour attendre D180µs //byte DebInjDeg = 60; //Debuter l'injection DebInjDeg degrès après la cible //int long unsigned D1 = 0; // Durée de 1° en µS pour le cycle en cours //int long unsigned DebInj = 0;// Debuter l'injection DebInj µs après la cible //int AFRv = 0; //Valeur de l'AFR entre 90 et 220, soit 9 et 22 //************************************************************* void Active1423() { Timer1.initialize(Dinj);//Lancer TMR1 qui coupera l'injection digitalWrite(I14, 1); //Alimenter l'injecteur digitalWrite(Led, 1); K = D180; DelayK(); // Attendre //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 l'injecteur digitalWrite(Led, 1);//Allume la led } 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); } void CalcReg() //Calcul le numero de colonne en fonction du régime N //ainsi que le coefficient CN pour interpoller Dinj dans la table { // N5 limite supérieure, on commence à comparer à N4 if (N > N4) { Reg = 4;//Reg numero de colonne dans TabDinj CN = (N - N4) / (N5 - N4); // Pour interpollation return; } if (N > N3) { Reg = 3; CN = (N - N3) / (N4 - N3); // Pour interpollation return; } if (N > N2) { Reg = 2; CN = (N - N2) / (N3 - N2); // Pour interpollation return; } if (N > N1) { Reg = 1; CN = (N - N1) / (N2 - N1); // Pour interpollation return; } Reg = 0; CN = (N - N0) / (N1 - N0); // Pour interpollation } void CalcPap() //Calcul le numero de ligne en fonction du TPS //ainsi que le coefficient CT pour interpoller { // T5 limite supérieure, on commence à comparer à T4 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 D180 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 isr_Cible() { D720 = micros() - prec_H; // Durée de 2 tours vilo = 1 tour AàC prec_H = micros(); //Nouvelle heure de reference Cycle = 1; //Flag de detection de cible } 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, 9, 220); // AFR valeur entre 9 et 22 //} void Lec_AP() { APu = analogRead(AP); TPS = map(APu, 0, 1023, 0, 100); // TPS 0 à 100% } void Lec_PotCor() { PotCoru = analogRead(PotCor); DinjCor = map(PotCoru, 0, 1023, 0, 10000); //DinjCore entre 0 et 10ms //On decale pour aller de -5ms à +5ms DinjCor = DinjCor - 5000;//Le zero est à mi-course du potard, negatif à gauche, positif à droite } void Prep_Dinj() { // Renverra Dinj en µs avec toutes les corrections.Pas en V1.0 Lec_AP();// Angle TPS Lec_PotCor();//En µs 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 // 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; // Serial.print("Dinj aprés interp "); Serial.println(Dinj); // if ((Dinj + DinjCor) >= 1)Dinj = Dinj + DinjCor; //Potard de correction éventuelle } void setup() { Serial.begin(115200); //Pour moniteur PC BT.begin(115200); //Pour Sphone, Bluetooth attachInterrupt(0, isr_Cible, FALLING); //D2,capteur Hall saturé, 0 quand cible detectée Timer1.attachInterrupt(isr_Fin_14); //Tmr1 deconnecte le couple 14 // Pour Timer2 voir Active1423() pinMode(Cible, INPUT_PULLUP); //Vient du capteur Hall pinMode(I14, OUTPUT); //Gate de l'IGBT pinMode(I23, OUTPUT); //Gate de l'IGBT pinMode(Led, OUTPUT); //Suit les injections 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 loop() { while (Cycle == 0); Cycle = 0; //reset du flag N = 120000000 / D720; //N en t/mn D180 = D720 / 4; //Delai entre l'injection des 2 paires Prep_Dinj();//Calcul Dinj en µs, y compris toutes les corrections if (SS_SG == 2)Dinj = Dinj / 2; // Semi full group on injecte en 2 fois Active1423(); if (SS_SG == 2) { K = D180; DelayK(); Active1423(); //Injection en 2 fois } }