//Injection_Logger141019 //Lit les parametres de la carte d'injection //Les ecrit sur une carte SD et les affiche sur Sphone, toutes les AffPer µsecondes unsigned long AffPer = 2; //Periode de l'affichage sur Sphone en secondes unsigned long DureeDef = 10;//Dures du log d'un run en secondes, quand non specifiée (mode 'L") #include"TimerOne.h" #include #include #include //Pour Bluetooth BT File myFile; //Un objet myFile de type File est créé SoftwareSerial BT(7, 8); // 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 AFR A1 //0 à 5V fourni par sonde Innovate #define PotCor A2 //OPTION: Potard pour correction manuelle d'injection #define Led 13 //Celle de l'Arduino #define CS 4 //Chip Select du circuit de carte SD //#define Tmot A3 //Temperature moteur +tard //#define Tmot A4 //Temperature d'air ambiant +tard volatile byte Cycle = 0; //Flag de detection de la cible de PMH. "Volatile" indispensable!? volatile unsigned long prec_H = 0; //Compteur de µs float D720 = 0; // Durée du cycle en cours en µs, 720°vilo, 2 tours unsigned long D14 = 0; //Durée de commande d'injection paire 1/4 unsigned long D23 = 0; //Durée de commande d'injection paire 2/3 int N = 0; //N en t/mn byte TPS;//Throttle Position Sensor de 0 à 100% byte AFRv = 0; //Valeur de AFR entre 74 et 221 signed long DinjCor = 0; //Potard de correction +/-5ms 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 byte AffF = 0; //Flag On pour l'affichage au Sphone, Off en mode dialogue int RunActif = 0; //N° de run, 1,2,... byte RunF = 0; //Flag etat d'un run: 0pas de run, 1 en cours, 2 en pause unsigned long RunD = 0; //En µs durée requise unsigned long Dcum = 0; //Cumul pour calcul durée d'un run. String Ligne = ""; //Sera ecrite dans la SD signed long Val = 0; //Entier tapé au clavier int RunNb = 0; //N° de run, toujours croissant, initialisé depuis NextR.txt String RunFile = ""; //C'estle nom du fichier contenant le run "RunNb.xls" ex 21.xls char carLu; // Stock le car lu String L = ""; //Accumule les carLu unsigned long AffPerMic = 0;//Periode d'affichage en µs //************************************************************* void AffLigne()//Sur Sphone et PC { //Serial.println("****Essais injection Logger****"); BT.println("****Essais injection Logger****"); Serial.println(); BT.println(); Serial.print(F("N t/mn ")); Serial.println(N); BT.print(F("N t/mn ")); BT.println(N); Serial.print(F("Angle Pap % ")); Serial.println(TPS); BT.print(F("Angle Pap % ")); BT.println(TPS); Serial.print(F("Dinj1/4 mics ")); Serial.println(D14); BT.print(F("Dinj1/4 mics ")); BT.println(D14); Serial.print(F("Dinj2/3 mics ")); Serial.println(D23); BT.print(F("Dinj2/3 mics ")); BT.println(D23); Serial.print(F("DinjCor mics ")); Serial.println(DinjCor); BT.print(F("DinjCor mics ")); BT.println(DinjCor); Serial.print(F("AFR ")); Serial.println(AFRv); BT.print(F("AFR ")); BT.println(AFRv); } void Dialog() { if (BT.available() <= 0)return; //Pas de car de dialogue tapé, sortir AffF = 0; //QQchose a été tapé. Arreter l'affichage durant le dialogue carLu = BT.read();//Lit le car tapé char carS = carLu; //Sauver ce car while (BT.available() != 0)carLu = BT.read(); //Purge BT.println(carS); switch (carS) //d pour Durée, a pour Arret, l pour Log sans specifier de durée { case 'd':LireDuree(); if(RunD!=0)Log();break;//Si duree valable lance le log du run case 'a': RunTerminer(); break; case 'l': RunD = DureeDef*1000000; Log(); break;//Lance un run de durée par défaut default : Serial.println(); BT.println(); Serial.println("?"); BT.println("?"); delay(3000); //Erreur } AffF = 1;//Fin de dialogue relancer l'affichage des lignes } 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_Affic() //Toutes les AffPer µs, affiche au Sphone { Timer1.stop(); if (AffF == 1)AffLigne();//Affichage OK, pas en mode dialogue Timer1.initialize(AffPerMic);//en µs, reinit } 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, 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 LecD14() { while (digitalRead(I14) == 0); //Attente gate = 1, injecteurs 1/4 ON D14 = micros(); // Noter l'heure while (digitalRead(I14) == 1); //Attente gate = 0, injecteurs 1/4 OFF D14 = micros() - D14; // Durée } void LecD23() { while (digitalRead(I23) == 0); //Attente gate = 1, injecteurs 2/3 ON D23 = micros(); // Noter l'heure while (digitalRead(I23) == 1); //Attente gate = 0, injecteurs 2/3 OFF D23 = micros() - D23; // Durée } void LecFic()//Lit un enregistrement de fichier { //Lire le numero de run RunNb, seul enregistrement du fichier NextR.txt myFile = SD.open("NextR.txt");//Ouvert pour lecture seulemnt et non WRITE char carLu; // Stock le car lu String L = ""; //Accumule les car reçus de la carte SD if (myFile) { while (myFile.available()) { carLu = myFile.read();//Lecture de 1 car delay(100); //Indispensable ? if ((carLu == 13 ) || (carLu == 10)) break;//Sortir L = L + carLu; //cumuler } RunNb = L.toInt();//Conversion en entier // Serial.print("RunNb= "); BT.println("RunNb= "); // Serial.println(RunNb); BT.println(RunNb); } myFile.close(); } void LireDuree() {//Dure non valable, on sort avec Rund=0 BT.println("Lancer un run"); Serial.println("Lancer un run"); BT.println("Duree en secondes (0 pour sortir, 3600 maxi): "); Serial.println("Duree en secondes (0 pour sortir, 3600 maxi): "); LireVal(); //On entre soit 2 par ex pour 2s soit 0 pour sortir if ((Val==0) ||(Val>3600)){//0 veut dire sortir tt de suite. Limite 1h Serial.println(); BT.println(); Serial.println("?"); BT.println("?"); delay(3000); RunD=0; //Erreur ;//0 ou plus d'une heure, ignorer on sort } else RunD = 1000000*Val; } void LireVal() //Au clavier du Sphone //Attend une ligne de car terminée par CR ou LF et la convertit en entier Val { while (1) { //On en sortira par CR ou LF // while (Serial.available() == 0); //Attendre un car pour le moniteur while (BT.available() == 0); //Attendre un car // carLu = Serial.read(); //Lit ce car pour le moniteur carLu = BT.read(); //Lit ce car delay(100); //Indispensable if ((carLu == 13 ) || (carLu == 10)) break;//Sortir L = L + carLu; //cumuler } Val = L.toInt(); // convertir en entier // while (Serial.available() != 0)carLu = Serial.read(); //Purge pour le moniteur while (BT.available() != 0)carLu = BT.read(); //Purge } void PrepLigne() //Lecture de toutes les entrées { while (Cycle == 0); Cycle = 0; //reset du flag LecD14(); LecD23(); N = 120000000 / D720; //N en t/mn Lec_AP(); Lec_AFR(); Lec_PotCor(); Ligne = String(N) + ";" + String(TPS) + ";" + String(D14) + ";" + String(D23) + ";" + String(DinjCor) + ";" + String(AFRv); if (RunF == 1) //Run en cours { myFile.println(Ligne); Dcum = Dcum + D720; if (Dcum > RunD)RunTerminer(); } } void Log() {//Prepare les fichiers et met RunF=1 { //Lire le numero de run RunNb, seul enregistrement du fichier NextR.txt LecFic();// SD.remove("NextR.txt");//MàJ du N° de run, effacer l'ancien fichier // car on veut écrire en première position myFile = SD.open("NextR.txt", FILE_WRITE);//Le recreer myFile.println(String(RunNb + 1) );//Avec RunNb++ myFile.close(); Serial.print("Lancement du Run "); Serial.println(RunNb); BT.print("Lancement du Run "); BT.println(RunNb); Serial.print("Duree en s "); Serial.println(RunD / 1000000); BT.print("Duree en s "); BT.println(RunD / 1000000); BT.println("Run en cours"); Serial.println("Run en cours"); delay(3000); //Création du nouveau fichier pour le run qui démarre, d'abord son nom, ex "21.xls" RunFile = String(RunNb) + ".csv";//Composer le nom du fichier run à demarrer myFile = SD.open(RunFile, FILE_WRITE); myFile.println(" INJECTION Alpine A110 1600S"); myFile.println("; ; ; ; ;"); //Leading blank line String header = "Nt/mn ;TPS en %;D14 mics;D23 mics;Cor mics ;AFR ";// les entêtes de colonnes myFile.println(header);// ensuite les lignes seront ajoutées par EcrireLigne() Dcum = 0; //Calcul de la durée RunF = 1; //Run en cours } AffF = 1; //Re autoriser l'affichage des lignes sur le Sphone } void RunTerminer() { BT.println(F("Run termine: numero et duree en s ")); Serial.println(F("Run termine: numero et duree en s ")); BT.println(RunNb); Serial.println(RunNb); BT.println(Dcum / 1000000); Serial.println(Dcum / 1000000); myFile.close();//Enregistre le fichier des lignes delay(5000); RunF = 0; //Pas de run en cours } void setup() { Serial.begin(115200); //Pour moniteur PC BT.begin(115200); //Pour Sphone, Bluetooth BT.println(F("Hello world")); Serial.println(F("Hello world")); attachInterrupt(0, isr_Cible, FALLING); //D2,capteur Hall saturé, 0 quand cible detectée Timer1.attachInterrupt( isr_Affic);//Affiche au Sphone toutes les AffPerµs pinMode(Cible, INPUT_PULLUP); //Vient du capteur Hall pinMode(I14, INPUT); //Gate de l'IGBT pinMode(I23, INPUT); //Gate de l'IGBT pinMode(Led, OUTPUT); //Suit les injections Serial.print(F("Initializing SD card...")); BT.print(F("Initializing SD card...")); if (!SD.begin(CS)) { //SD.begin(4) = 1 si carte OK*************************** Serial.println(F("initialization failed!")); BT.println(F("initialization failed!")); } else { BT.println(F("initialization OK")); Serial.println(F("initialization OK")); } delay(5000); AffPerMic= AffPer*1000000;//Periode d'affichage en µs AffF = 1;//Afficher au Sphone } void loop() { PrepLigne(); Dialog(); }