//Aepl-Duino_16_09_22 //Electronic programable ignition TCI - Arduino Nano et compatibles //*********Details : http://loutrel.org/aeduino.php ************* //********* Only 6 lines to setup ***** //**********They are : Na Anga Ncyl AngleCapteur CaptOn Dwell** //___1___ Na[] RPM //Na[] and Anga[] must start and end with 0, and all other numbers must be >=1 //The last Na defines the red line, meaning the ignition is cut. //The numbers of rpm points is free. the advance is fixed at 0° at 0 uo tp Nplancher rpm, plancher = bottom in french, so it means lowest , to set further down below //For example , a curve in " V " in the beginning to improve stationnairy rpm int Na[] = {0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4200, 4600, 5100, 7000, 0};crank RPM //__2__Anga [] degrees advance crankshaft corresponding to the rpm's above (can go up and down) int Anga[] = {0, 16 , 10 , 16 , 18, 22, 26, 28, 28, 28, 29, 30, 32, 0};//stat. rpm in "V" //int Anga[] = {0, 0 , 0 , 0 , 12, 14, 26, 28, 28, 28, 29, 30, 32, 0}; //__3__Ncyl # of cylinder's, for a 4-stroke engine, multiply by 2 for 2-strokes int Ncyl = 4; //__4__Position of the Hall sensor (or other) before the TDP of the 1st cylinder in degrees const int AngleCapteur = 50; //In general arround 50° (capteur = sensor in french) //__5__CapteurOn = 1 triggered RISING (for example a saturated Hall sensor) //CapteurOn = 0 triggered FALLING (for example a non-saturated Hall sensord), see end of listing (par ex. capteur Hall "non saturé").Voir fin du listing const int CaptOn = 0; //__6__Dwell = 1 to charge the coil permanently except 1ms/cycle . Only for cols that do not suffer from heating up //Dwell = 2 to charge the coil for a specific time (3ms for example, can be changed further down the file, look for "const int trech = 1000" in the file) //DWELL 2 = MANDATORY for "electronic" coils with low primary resistance (between 0.5 and 2 ohm's, adjust "trech", otherwise they will burn ! //Dwell = 3 to simulate an ignition with points : coil is charged 2/3 of the cycle (66%). //Dwell = 4 to optimise the spark at high rpm's, but the coil heat's a little more. const int Dwell = 2; //*************************************************************** //**********************GENERALITY'S ***************************** //Works with all types of sensors, be it on the crank, camshaft or distributer //The Led(D13) that all Arduino's have, follows the current through the coil : Led on = coil being charged //For engines with 1, 3 ou 5 cylinders 4 strokes, the sensor must be in the distributer or on the camshaft //For a single cylinder 4 stroke, you can also use a single sensor on the crank and use wasted-spark ignition by using Ncyl =2. //Advance 0° up to bottom rpm (Nplancher) as anti-kick-back . //In option, adjustment of stationairy rpm by dynamique adjustement of advance //In option, multi-sparkes at low rpm's for "cleaning" the sparkplug (drowned engine ?) (French : étincelles à bas régime pour denoyer les bougies) //In option, variable Dwell //In option, accurate rpm counter //In option, 2 extra curves possible, B and C seclectable though D! or Dç or smartphone //In option, total ignition curve can be advanced/retarded instantly by potentiometer //For N cylindres,2,4,6,8,12,16, 4 strokes, you need N cam's in the distributer or N/2 sensor's on the crank //**********************OPTIONS********************** //*************Regulation of stationnairy rpm by dynamicaly adjusting the advance //* Based on an idea by Antoine Zorgati //* The advance for stationnairy rpm is totaly independant of the ignition advance curve set above //* you set a starting advance AvR = 10 degree's and a zone consignated for the stationnary rpm with a tolerance, for example 800+-50 rpm //* if the rpm's fall outside the consignated zone, you correct the advance with 1 degree more or less //* you keep that advance for a time given to CtCyInit of rotation's per minute to stabilise the rpm //* than the new rpm is verified : if the stat. rpm is inside the consignated zone, the advance is left alone, if not the advance is again corrected by 1 degree //* Thus following the stat. zone is defined by NrMin and NrMax... const int Nr =800; //Consignated zone stat. rpm 800 for example. If set to 0 nothing needs to be regulated. //***********************Multi-Sparks****************** //If multi-sparks are wanted up to N_multi, adjust the following lines : const int Multi = 1 ;//1 for multi-sparks, 0 for non const int N_multi = 1300; //1300 rpm for 4 cylinders for example //especialy usefull against drowned spark plugs at low rpm //************Options for Dwell ************** //If Dwell=2, coil charging time, 3ms= 3000µs, 7ms for certain motorcycles const int trech = 3000; //If Dwell=4, duration of the spark below Ntrans const int Ntrans = 3000; //"transition rpm and max displayed RPM Smartphone" ? (Fr: Regime de transition et maxi affichage RPM Smartphone) const int tetin = 500; //Typical 500 to 1000µs, spark duration rpm's below Ntrans //*********************Rev counter************************ //Connect a HC05/06 to +5V, ground, connect RX to 11 on the arduino, TX to 10 //IMPORTANT: set the HC05/06 in 115200 bps (baut rate) mode through an AT command //http://www.loutrel.org/BlueToothArduino.html to perform this action //install on the smartphone an aplication like "Bluetooth Terminal HC-05" //or "BlueTerm+" or equivalent. //Only the first time :register the module on the smartphone with pin code 1234.. //This shows the rpm's (rev's per minute/10) and the advance in degrees on the smartphone or tablet //Especialy usefull as a precise rev counter for setting the carburation on stat. rpm #define Naff 20 //to show on smartphone the number of rev's to ignore between 2 displayed numbers //Maxi 3000t/mn //*******************MULTI CURVES************************** // Connect D8 or D9 to ground to select curve b or c //or use a smartphone and a Blue Tooth module //**********Curve b connect D8 to ground or enter 8 on smartphone //Curve b int Nb[] = {0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4200, 4600, 5100, 7000, 0};//rpm crank int Angb[] = {0, 8 , 10 , 22 , 24, 26, 28, 30, 30, 30, 32, 32, 32, 0}; //*********Curve c connect D9 to ground or enter 9 on Smartphone // curve c int Nc[] = {0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4200, 4600, 5100, 7000, 0};//rpm crank int Angc[] = {0, 6 , 10 , 16 , 18, 22, 26, 28, 28, 28, 29, 30, 32, 0}; //*******************Moving the curve up or down******** //with a Bluetooth module HC05 or 06 //Enter 1 to 6 to ad 1 to 6 degrees to the entire curve //Enter 11 to 16 lower the advance 1 to 6 degrees //Attention.....No full throttle with too much advance, risk of burning your piston's //Instead of Bluetooth, connect a potentiometer of 100k to A0 and adjust the advance in delPot //Potentiometer 100k has 3 positions: 0 degrees if <1.5V //Add delPot degrees at +/- 2 V, 2*delPot degrees from +/- 3V //************Valeu's modifiable if needed***************** //they are: Nplancher, Dsecu const int Nplancher = 500; // speed in rpm up to where the advance is 0 degrees const int unsigned long Dsecu = 1000000;//For security : coil charge stopped after Dsecu µs //***********************SOFTWARE***************************** #include "TimerOne.h" #include //For module Bluetooth HC05 or 06 SoftwareSerial BT(10, 11); //Create an input/output dedicated to D10(RX on HC) and D11(TX on HC) //***********************Sketch variables************************************ #define Bob 4 //Output D4 to coil . In option, one can connect a Led with R=330ohms to ground #define Cible 2 //Input to D2 from sensor , with R PullUp #define Pot A0 //Input analog to A0 for potentiometer to change curves, with R PullUp #define Led13 13 //Led on all Arduino, follow's the current through the coil #define Courbe_b 8 //Input D8 R PullUp.Connect to ground for curve b (courbe = curve) #define Courbe_c 9 //Input D9 R PullUp. Connect to ground for curve c int valPot = 0; //0 to 1023 depending on the potentiometer input int delPot = 2; // the steps in degrees the curve's are altered (b and c) float modC1 = 0; //Corrector/patch?? (FR:Correctif) for C1[], move the curve if a potentiometer is connected int unsigned long D = 0; //Delay in µs to wait after the sensor has passed for the spark (FR:a attendre apres passage de la cible pour l'etincelle) int milli_delay = 0; int micro_delay = 0; float RDzero = 0; //to calculate the delay advance 0degrees < Nplancher rpm float Tplancher = 0; //idem int tcor = 140; //correction in µs for the time to calculate D (what is D???) int unsigned long Davant_rech = 0; //Delay in µs before the coil is charged (avant = before) int unsigned long prec_H = 0; //"Time to previous signal?" (FR:Heure du front precedent en µs) int unsigned long T = 0; //Period in progress int unsigned long Tprec = 0;//"Period preceding the T in progress?" (FR:Periode precedant la T en cours), to calculate Drech int N1 = 0; //FR:Couple N,Ang beginning of segment int Ang1 = 0; //Advance angle crank in degrees int N2 = 0; //Couple N,Ang end of segment int Ang2 = 0; int* pN = &Na[0];//pointer to the table of rpm's. Na will be the default curve int* pA = &Anga[0];//pointer to the table of advance. Anga will be the default advance float k = 0;//Constant for calculation of C1 and C2 float C1[30]; //Table of constants , calculate the current advance float C2[30]; //Table of constants , calculate the current advance float Tc[30]; //Table of Ti corresponding to Ni //If nescesary, raise these 3 values :Ex C1[40],C2[40],Tc[40] int Tlim = 0; //Minimal period , limit, for the red line int j_lim = 0; //index max for N , so also Ang int unsigned long NT = 0;//Conversion factor between N and T at given Ncyl int unsigned long NTa = 0;//Conversion factor between N and T to display on smartphone int ctNaff = 0; // Counteur off/calculate? Naff int AngleCibles = 0;//Angle between 2 target's, 180° for 4 cyl, 120° for 6 cyl, as exemple (cible = target) int UneEtin = 1; //=1 for each spark, tested and reset to zero by isr_GestionIbob() int Ndem = 60;//Estimated speed of crank by the startermotor in rpm int unsigned long Tdem = 0; //Period corresponding to Ndem,forced by the first rev int Mot_OFF = 0;//Will be 1 if detected that the engine has stopped by isr_GestionIbob() (FR:Sera 1 si moteur detecté arrété par l'isr_GestionIbob() ) int unsigned long Ttrans; //T transition of Dwell 4 and also display threshold on smartphone int unsigned long T_multi = 0; //Minimum period for multi-sparks //Permits to identify the first front and force T=Tdem, thus Ibob=1, to start at the first front (FR:Permet d'identifier le premier front et forcer T=Tdem, ainsi que Ibob=1, pour demarrer au premier front) String Ligne; //Stock une ligne du smartphone,ex "5" pour augmenter l'avance de 5 degree (ligne = line) char carLu;//"Will be cumulated in Line?" (FR:Sera cumulé dans Ligne) int delAv = 0; //look up advance-regulation from Smartphone(FR:Demander au clavier du Sphone, le decalage d'avance) //choice of curve chosen on smartphone : 7 curve a, 8 curve b, 9 curve c int Ncourbe = 7; //Number of the current curve to be display on smartphone , when starting it's 7 so curve a int NrMin = 600; //the rpm range of stationary rpm from NrMin to NrMax int NrMax = 1150; int unsigned long TrMax = 0; //(FR:Pour s'ejecter du ralenti rapidement) int Nrinf = 750; //The regulation zone is from Nrinf to Nrsup int Nrsup = 850; int CtCy = 0; //Count the cycles/periods between 2 mesaurements of regulated stat. rpm int CtCyInit = 20;//Or CtCyInit/2 revolutions of the crank on 4 cylindres int AvR = 10; //Dynamicaly adjusted advance for the regulated stat.rpm int AvRMin = 1; //(FR:Bornes pour l'avance au ralenti reguler) int AvRMax = 25; //20 or 25 or 30 degrees will also do int N = 0; //In rpm's to test the regulated stat. rpm void setup()/////////////// ///////////////////////////////////////////////////////////////////////// { Serial.begin(115200);//Next line, 3 macrco's in C pragramming language Serial.println(__FILE__); Serial.println(__DATE__); Serial.println(__TIME__); BT.begin(115200);//To BlueTooth module HC05/06 BT.flush();//"By any chance" (FR:A tout hasard) BT.println(__FILE__); BT.println(__DATE__); BT.println(__TIME__); BT.println("***Hi*****************************************"); BT.println("******************************************************"); pinMode(Cible, INPUT_PULLUP); //Input front of signal to D2 pinMode(Bob, OUTPUT); //Output to D4 , controls current to coil pinMode(Pot, INPUT_PULLUP); //Input for pot.meter 10kOhm, optional pinMode(Courbe_b, INPUT_PULLUP); //Input to ground to select curve b pinMode(Courbe_c, INPUT_PULLUP); //Input to ground to select curve c pinMode(Led13, OUTPUT);//Original LED on Arduino, shows current to coil // Tst_BT(); //Option to test Bluetooth, "loop here, if not to comment" (FR:boucle ici, sinon à commenter). Init();// Execute once at starting } /////////////////////////////////////////////////////////////////////////// //********************FUNCTIONS************************* void CalcD ()////////////////// // Noter que T1>T2>T3... (noter = note) { for (int j = 1; j <= j_lim; j++)//it begins with the longest T and go back (FR:On commence par T la plus longue et on remonte) { if (T >= Tc[j]) { //we have found the good segment of the advance curve D = float(T * ( C1[j] - modC1 ) + C2[j]) ;//D in µs, C2 incorporates the time to calcule tcor,modC1 offset by Sphone if ( T > Tplancher)D = T * RDzero;//Imposes 0degrees of advance from 0 to 500 rpm break; //"Leave, we have D" (FR:Sortir, on a D) } } } void CalcD_Test() /////////////////////////////////////// { if (T < TrMax)CalcD(); //outside stat. rpm else { if (Nr == 0)CalcD(); //stzt. rpm without regulation else RegRalenti(); } } void Etincelle ()////////// (étincelle = spark) { if (D < 14000) { // 16383 µs seems to be the maximum for the delayMicroseconds(D) function delayMicroseconds(D); //Wait D } } else { milli_delay = ((D / 1000) - 2);//"For those long D 's, delayMicroseconds(D)no longer goes. micro_delay = (D - (milli_delay * 1000)); delay(milli_delay); // delayMicroseconds(micro_delay); } digitalWrite(Bob, 0);//Cut the current, so we have a spark digitalWrite(Led13, 0); //Lights up arduino LED //Now that we had spark, we have to restore Ibob at the right time if (Dwell != 2 && Multi && (T >= T_multi))Genere_multi(); //Except if Dwell=2, look up if multi-sparks are required else { switch (Dwell) //Wait for the current to be cut dpending on Dwell type { case 1: //Ibob cut 1ms each cycle only, the coil must withstand heating up Davant_rech = 1000; //1ms off each cycle break; case 2: //Coil type with low resistance, "electronique" type" Davant_rech = 2 * T - Tprec - trech;//We have to consider the rpm variations of the engine Tprec = T; //major? of the previous futture period (FR:Maj de la future periode precedente) break; case 3: //Type "points", Off 1/3, On 2/3 Davant_rech = T / 3; // (avant = before) break; case 4: //Type optimised for high rev's if ( T > Ttrans )Davant_rech = T / 3; // Lower than N trans, typicaly 3000t/mn else Davant_rech = tetin; // Beyond Ntrans, the spark duration is limited, typicaly 0.5ms break; } Timer1.initialize(Davant_rech);//Wait Drech µs before restoring current to coil } UneEtin = 1; //To signale that the engine is running at l'isr_GestionIbob(). Tst_Pot();//Check to see if a pot.meter is connected to set-off the curve if (T > Ttrans)Smartphone(); //If not too fast manage the sphone (FR: Si pas trop vite gèrer le sphone) } void Genere_multi()////////// { //The main spark has just been generated delay(1); //Wait for end of spark 1ms digitalWrite(Bob, 1);//Restore the current delay(3); //Recharge 3ms digitalWrite(Bob, 0);//First secondary spark delay(1); //Wait for end of spark 1ms digitalWrite(Bob, 1);//Restore the current delay(2); //Recharge 2 ms digitalWrite(Bob, 0);//Second secundary spark delay(1); //Wait for end of spark 1ms digitalWrite(Bob, 1);//Restore the current for main spark } void Init ()///////////// //Calculate the 3 tables C1,C2 et Tc needed to calculate D, time to waite //between the sensor signal detection and the spark timing //Both C1,C2 are determined by the period T between 2 signals, corrsponding at //the right segment of the advance curve entered by the user : T is compared to Tc { AngleCibles = 720 / Ncyl; //Signals on the crank. for example 4 cylinders 180°, 120° for 6 cylinders NT = 120000000 / Ncyl; //Conversion factor Nt/mn motor, Tµs between 3 TDC sparks (FR:entre deux PMH étincelle) //that is 2 signals from the crank or 2 signal's in the distributer : Nt/mn = NT/Tµs NTa = NT / 10; ///Conversion factor Nt/min motor to display N/10 on smartphone TrMax = NT / NrMax; //For regulated stat. rpm Ttrans = NT / Ntrans; //Calculation of the transition for Dwell 4 and display on Sphone T_multi = NT / N_multi; //Minimal period to generate multi sparks modC1 = 0; // No adjusting the advance Tdem = NT / Ndem; //Imposed period for the first spark that has no value prec_H Tplancher = 120000000 / Nplancher / Ncyl; //T at lowest speed in rpm : below advance= 0° (FR:vitesse plancher ..., avance centrifuge = 0) RDzero = float(AngleCapteur) / float(AngleCibles); Prep_Courbe(); //Calculation of the segments of the advance curve specified by Ncourbe // Serial.print("Ligne_"); Serial.println(__LINE__); // Serial.print("Tc = "); for (i = 1 ; i < 15; i++)Serial.println(Tc[i]); // Serial.print("Tlim = "); Serial.println(Tlim); // Serial.print("C1 = "); for (i = 1 ; i < 15; i++)Serial.println(C1[i]); // Serial.print("C2 = "); for (i = 1 ; i < 15; i++)Serial.println(C2[i]); //Timer1 has 2 roles: //1)cut the current in the coil in absence of sparks longer than Dsecu µs //2)after a spark, to wait for a delay Drech before restoring current to the coil //The current is not restored but trech ms before the next spark, "condition crucial" (FR:condition indispensable) //for a coil with low primary resistance (+/- lower than 3 ohms).Typicaly trech = 3ms to 7ms Timer1.attachInterrupt(isr_GestionIbob);//IT d'overflow de Timer1 (16 bits) Timer1.initialize(Dsecu);//the current through the coil will be cut if there is no spark during Dsecu µs Mot_OFF = 1;// Signals to loop() the first front digitalWrite(Bob, 0); //"as a priciple" (FR: par principe), cut current to coil digitalWrite(Led13, 0); //Flash arduine LED } void isr_GestionIbob()////////// { Timer1.stop(); //stop "break down" of timer (Fr = Arreter le decompte du timer) if (UneEtin == 1) { digitalWrite(Bob, 1); //the engine is running, restore current to coil digitalWrite(Led13, 1);//flash arduino LED } else { digitalWrite(Bob, 0); digitalWrite(Led13, 0); //Flash arduino LED//Witness engine has stopped, protect coil by cutting current Mot_OFF = 1;//Permits loop() to detect the front of the sensor signal } UneEtin = 0; //Reset the spatk detection to 0 Timer1.initialize(Dsecu);//In case the engine has stopped, cut the current to coil after Dsecu µs } void Lect_delAv()///////////////////Only if T> Ttrans, typicaly N <3000rpm //Reading of smartphone { // With 7,8 or 9 the curve is changed, if not delta from +1 deg to +6 deg or negative 11 to 16, 0 for non-modified curve Ligne = ""; //"We gather the result recieved from Sphone" (FR:On y accumule les car reçus du sphone, Ligne = line) while (BT.available() > 0) //"Nb de car" in the buffer recieved from Sphone (FR:Nb de car dans le buffer venant du sphone) { carLu = BT.read(); //Yes there is a "car" at least, but we filter 1 to 9 only if ((carLu >= 48 ) && (carLu <= 57) )Ligne = Ligne + carLu; //if between 0 and 9 } // Serial.println( Ligne); if (Ligne != "") //A value has been send to Sphone { delAv = Ligne.toInt(); // conver to in full (FR: convertir en entier) // Serial.println( delAv); if ((delAv == 8) || (delAv == 9) || (delAv == 7)) { { Ncourbe = delAv; //Save to dislay Prep_Courbe(); //Curve is being changed, call Select_Courbe() } } else //Delta on current curvevof +1 a +6 deg or negatif { if ((delAv >= 0) && (delAv <= 16)) { if (delAv >= 11)delAv = 10.0 - delAv; // for example 12 is enterd, for -2° modC1 = float(delAv) / float(AngleCibles); // to calculate the delay before spark BT.println(delAv); // Display on sphone } else delAv = 0; } } } void Prep_Courbe()/////////Calculate the segments of the advance curve { //Ncourbe = 7,8,or 9 for the curve to activate, a or b or c modC1 = 0; //No correction Select_Courbe(); //Adjuste the pointeurs pN et pA for the curve designated by Ncourbe delAv = 0; //"Once? of the offset"? (FR:Raz du decalage) N1 = 0; Ang1 = 0; //All curves start from 0 int i = 0; //"Locale but valid outside of FOR" (FR:locale mais valable hors du FOR) pN++; pA++; //jump the first number of the table, always =0 for (i = 1; *pN != 0; i++)//i for C1,C2 abd Tc. Stop when rpm=0 //pN is a "pointer?" "adresse that points to table N, the pointed content is *pN { N2 = *pN; Ang2 = *pA;//re-copy the values pointed to bu N2 and Ang2 k = float(Ang2 - Ang1) / float(N2 - N1);//"slope?" of segment (1,2) (Fr : pente du segment) C1[i] = float(AngleCapteur - Ang1 + k * N1) / float(AngleCibles); C2[i] = - float(NT * k) / float(AngleCibles) - tcor; //Compensate the duration of calculation of D Tc[i] = float(NT / N2); // N1 = N2; Ang1 = Ang2; //End of segment, start of the next pN++; pA++; //Pointer to the element next in the table } j_lim = i - 1; //Return to the last entered couple (N ? and Ang ?) Tlim = Tc[j_lim]; //Red line } void RegRalenti()//////////////////////////////////// { //To calculate a specific D for the regulated stat. rpm, ignoring the advance curves CtCy++; //"Counter of passage, only testing if all the CtCyInit pass?" (FR:Compteur de passage, on ne teste que tous les CtCyInit passages) if (CtCy >= CtCyInit) //If not, keep AvR for calculation of D { //Verifier AvR CtCy = 0; //Re init the passage counter N = NT / T; //Calculate N for the upcomming tests if (N < Nrinf || N > Nrsup) //If not no correction needed, keep AvR { //necessairy correction for AvR if (N < Nrinf) { AvR++; //To slow if (AvR > AvRMax)AvR = AvRMax; //Cap high (FR:Plafonner haut) } else { AvR--; //To fast if (AvR < AvRMin)AvR = AvRMin; //Cap low (FR:Plafonner bas) } } } D = (T / AngleCibles) * (AngleCapteur - AvR);//Neglect the corrections because at stat. rpm } void Select_Courbe()/////////// //Initialise pN and pA to 1 of 3 curves a , b , c depending on Ncourbe { //Serial.println("********************************Ncourbe**********"); //Serial.println( Ncourbe); if (Ncourbe == 7) //default curve a { pN = &Na[0]; pA = &Anga[0]; } if ((digitalRead(Courbe_b) == 0) || (Ncourbe == 8)) //D8 to ground or 8 on Sphone { pN = &Nb[0]; // pointer to curve b pA = &Angb[0]; } if ((digitalRead(Courbe_c) == 0) || (Ncourbe == 9)) //D9 to ground or 9 on Sphone { pN = &Nc[0]; // pointer to curv c pA = &Angc[0]; } } void Smartphone()/////////////////////////////////////////// { //Si N < Ntrans displayed through Bluetooth the rpm, the advance and posibilityle of offsetting the curve if (ctNaff < Naff)ctNaff++; // typicaly we jump 5 to 10 rev's between displaying 2 N 's else { //display rpm, advance and N° of the curve BT.print(NT / T); //display N and advance on smartphone BT.print("................deg "); BT.println(AngleCapteur - (D + tcor)*AngleCibles / T);//display avance BT.print("Curce "); BT.println(Ncourbe); //display 7 or 8 or 9 for the current curve in use BT.print("Offset "); BT.println(delAv); BT.println(); ctNaff = 0; //(FR:RAZ du compteur d'affichages) Lect_delAv();//Check if offset is demanded by the Sphone } } void Tst_BT() { int BTdata = 0; //**************To PC Serial.println("Hi "); Serial.println("The caracter entered in Android must be below here"); //***************To module BT.println(" "); BT.println(" "); BT.println("Hi"); BT.println(" "); BT.println("HC05, the LED must blink twice, 1s Off, 2flash..."); BT.println(" "); BT.println("HC06, led On fixe"); BT.println(""); BT.println("Enter a caracter "); BT.println("If t's on the screen, everything is well..."); while (1) { if (BT.available()) //"because ready to enter Serie soft ?" (FR:Car pret en entrée sur Serie soft?) { BTdata = BT.read(); //Yes, the keybaord Android BT has issued an "because???" (Fr : oui, le clavier Android BT a émis un car) BT.println(" ");//Go to line on sphone // **************To PC Serial.write(BTdata);//write the engine on the PC Serial.println(); } } } void Tst_Pot()/////////// { valPot = analogRead(Pot);//Potar 100k >1. (Potar = potentio meter) if (valPot < 900) //No pot.meter connected (value of pot =1023 in theory) { //Pot.meter connected, correction 0 or delpot degrees or 2*delPot degrees if (valPot < 240)modC1 = 0; //No correction, approximatly <1.5V else if (valPot < 700)modC1 = float (delPot) / float(AngleCibles); //Add delPot degrees, approx. 2V else modC1 = 2 * float (delPot) / float(AngleCibles);//Add 2*delPot degrees, approx. 3V } // Serial.println(valPot); Serial.println(modC1); } //////////////////////////////////////////////////////////////////////// void loop() //////////////// //////////////////////////////////////////////////////////////////////////// { while (digitalRead(Cible) == !CaptOn); //Wait for front of active signal T = micros() - prec_H; //front active, calculate T prec_H = micros(); //Time of actual front that becomes the previous front if ( Mot_OFF == 1 ) { //Starting : first front of the sensor T = Tdem;//Fournir T = Tdem because prec_H didn't exist before the first spark digitalWrite(Bob, 1);//Charge the coil digitalWrite(Led13, 1); //Flash arduino LED Mot_OFF = 0; //the engine is running } if (T > Tlim) //Below red line? { CalcD_Test(); //Yes ? than genrate spark Etincelle(); } while (digitalRead(Cible) == CaptOn); //Wait if the signal is still active } /////////////////Examples of SENSORS///////////////// //Hall sensor Honeywell cylindrique 1GT101DC, non-saturated type, output high and drops on signal //You need CapteurOn = 0, pull down triggernig //the forked Hall sensor SR 17-J6 is saturated type , output low and high on signal - pull up //you need CapteurOn = 1, pull up on triggering //For Ncyl pairs:2,4,6,8,10,12, the number of sensors on the crank corresponds to Ncyl/2 //In both cases (sensor(s) on crank or in distributor/camshaft) the period between 2 sensor signals is the same because the camshaft runs at half the rpm of the crankshaft //For uneven Ncyl 1,3 5, 7?,9? the sensor must be in the distributer or on camshaft ////////////////DEBUGGING//////////////////////// //see http://www.loutrel.org/Arduinodebugging.php //Macro ps(v) debug dor printing on smartphone ////puis s'arreter definitivement //#define ps(v) Serial.print("Ligne_") ; Serial.print(__LINE__) ; Serial.print(#v) ; Serial.print(" = ") ;Serial.println((v)) ; Serial.println(" Sketch stop"); while (1); //for example, at line 140, the instruction ps(var1); //print "Line_140var1 = 18 Sketch stop" //Macro pc(v) debug for printing the line number ; the variable's name and it's value //than stop and wait for a mouse-click on the "send" button on the top of the screen to continue #define pc(v) Serial.print("Ligne_") ; Serial.print(__LINE__) ; Serial.print(#v) ;Serial.print(" = ") ; Serial.println((v)) ; Serial.println(" Clic button 'Send to continue") ;while (Serial.available()==0);{ int k_ = Serial.parseInt() ;} //Example, on line 145, the instruction pc(var2); // print "Line_145var2 = 25.3 Click button 'Send to continue" //float gf = 0;//"waiting for loop?",gf GLOBALE et FLOAT indispensable // gf = 1; while (gf < 2000)gf++;//10= 100µs,100=1.1ms,2000=21.8ms //void Top()////////// //{ digitalWrite(Bob, 1); //FR : Crée un top sur l'oscillo // gf = 1; while (gf < 10)gf++;//gf MUST be "Global and Float?" 10=100µs,2000=21.8ms, wait/signal=50µs // digitalWrite(Bob, 0); // //}