//Logger_Carbu_AFR_2023_02Fev_10 //Dérivé de Injection_LoggerV3.0_071220Mod_050321 //Modifié JLP pour ajout Angle Ouverture Premier Corps 32DIR58 //Alterne log/arret par toute touche du clavier //Peut sauter des étincelles avant d'ecrire la SD //LogNetin K :log après K=1 ou 2 (chaque tour moteur) ou 3 ou 4 ...étincelles, //N<7000 evite parasite sur front montant //Pas ce pb sur front descendant //Mesure Nt/mn et AFR //Transmet ces données via Bluetooth et possibilté d'enregistrement sur carte SD //Affiche sur Sphone, toutes les AffPer secondes //Les 2 modes à entrer au clavier du smartphone //'l' l_og ( l_ancer le log) .Le log continuera jusqu'à l'entrée de "a" au clavier //'a' a_rreter le log //La carte SD contient un seul fichier texte, NextR.txt qui contient //une unique valeur,i, le N° du prochain Run. //Ensuite les fichiers de Run se nomment i.csv, avec i++ à chaque Run, au format Excel //Polling sur Cible, pas d'IT //Pour ajouter un champs:AffLigne(), puis dans LogPrep() voir StringHeader //puis dans PrepLigne() ajouter à Ligne=.. /////////////////////////1 VALEURS AJUSTABLE/////////////////////////// unsigned long AffPer = 2; //Periode de l'affichage sur Sphone en secondes byte LogNetin = 4; //log après 1 ou 2 ou 3 ou 4 ...étincelles //Valeur de 0 à 255 - Pour éviter la confusion avec la sortie 4 affectée à LedRun. #include "TimerOne.h" #include //Pour carte SD #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 ATTENTION, affectation cosses différente (2 & 3) sur Injection #define Cible 2 //D2 front montant pour une étincelle, fonctionne mal ave le descendant ATTENTION sur Injection PhL utilise un capteur Hall pour les tr/mn #define AP A3 //Potar angle papillon #define AFR A1 //0 à 5V fourni par sonde lambda large bande Innovate #define CS 9 //Chip Select du circuit de la carte SD #define LedRun 4 //Led ON pendant un run #define APumin 608 //608=1023/5x2.97 unité de AP quand papillons au minimum absolu, 2.99V-sécurité = 2.97V pour éviter les erreurs de 0, Tension relevée avec Potentio"métal" 5kOhms projet JLP -Etalonnage du 5/10/23 // 516=1023/5x2.52 unité de AP quand papillons au minimum absolu, 2.54V-sécurité = 2.52V pour éviter les erreurs de 0, Tension relevée avec Potentio"métal" 5kOhms projet JLP -Etalonnage du 6/04/23 #define APumax 917 // 917=1023/5x4.48 unité de AP quand papillons au maximum, 4.48V pour 7805=4.96V -Etalonnage du 5/10/23 // 837=1023/5x4.09 unité de AP quand papillons au maximum, 4.09V pour 7805=4.96V -Etalonnage du 6/04/23 #define Vp5 4.8 //En V, tension réelle de valeur théorique +5V pour convertisseur analogique. Cette ligne est-elle nécessaire dans mon cas ? unsigned long prec_H = 0; //Compteur de µs float T = 0; // Entre deux étincelles, typique 5ms à 6000t/mn unsigned int N = 0; //N en t/mn était unsigned long chez PhL unsigned int Narrondi = 0; // tr/mn arrondi par pas de 250tr/mn, ajout 3/04/23 int APu = 0; //AP en unités 0-1023 byte TPS; //Throttle Position Sensor de 0 à 100% byte TPSarrondi; //TPS arrondi par pas de 10%, ajout 3/04/23 float TPSprec; //Throttle Position Sensor precedent byte AFRv = 0; //Valeur de AFR entre 74 et 221 int AFRu = 0; //AFR en unités 0-1023 byte RunF = 1; //Flag etat d'un run: 0pas de run, 1 en cours float 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'est le nom du fichier contenant le run "RunNb.xls" ex 21.xls char carLu; // Stock le car lu float AffPerMic = 0; //Periode d'affichage en µs byte LogPrem = 1; // Flag de Premier log, pour initialiser la carte SD unsigned long CtAff = 0; //Compteur pour affichage float PapDot = 0; //Dérivée de TPS par rapport au temps, entre 0 et 1000%, mini 25%. J’ignore si cette info me sera utile … unsigned long Temps = 0; //le temps durant le run unsigned long Hdr = 0; //Heure début de run en ms char careLu; //car relu de la carte SD unsigned long CtC = 0; //Compteur de car relus int CtEtin = 0; //Compteur d'étincelle comparé à LogNetin //************************************************************* void setup() ///////////////////////////////////////////////////// { pinMode(7, INPUT); pinMode(8, OUTPUT); pinMode(9, OUTPUT); Serial.begin(115200); //Pour moniteur PC Serial.println("Hello"); Serial.println(); BT.begin(9600); //Pour Sphone, Bluetooth BT.println(F("****************************")); BT.println(F("Logger pour AFR")); Serial.println(F("Hello world")); BT.println(F("****************************")); BT.println(F("Utiliser les touches ")); BT.println(F("Marche / Arret")); delay(5000); pinMode(Cible, INPUT_PULLUP); //Vient du moins bobine, front montant Je conserve ce mode d’obtention des tr/mn. AffPerMic = AffPer * 1000000; //Periode d'affichage en µs pinMode(LedRun, OUTPUT); // InitSDcard(); } //********************************************* void AffLigne() //Sur Sphone et PC////////////////////////////////////// { Serial.println("****Essais Logger AFR****"); BT.println("****Essais Logger AFR****"); Serial.println(); BT.println(); Serial.print(F("N t/mn ")); Serial.print(N);Serial.print(F("/")); Serial.println(Narrondi); BT.print(F("N t/mn : ")); BT.print(N); BT.print(F("/")); BT.println(Narrondi); Serial.print(F("Angle Pap % ")); Serial.print(TPS); Serial.print(F("/")); Serial.println(TPSarrondi); BT.print(F("Angle Pap % : ")); BT.print(TPS); BT.print(F("/")); BT.println(TPSarrondi); BT.print(F("AFR : ")); BT.println(AFRv); if (RunF == 1) { BT.print(F(" Run Numero ")); BT.println(RunNb); //N° de run BT.print(F(" En cours ")); BT.println(); } } void Dialog() /////////////////////////////////////////////////////// { if (BT.available() <= 0) return; //Pas de car de dialogue tapé, sortir carLu = BT.read(); //Lire le car tapé char carS = carLu; //Sauver ce car while (BT.available() != 0) carLu = BT.read(); //Purge BT.println(carS); BT.println(F("RunF = ")); BT.println(RunF); Serial.print(F("RunF = ")); Serial.println(RunF); // Rajout affichages RunF pour essai if (RunF == 0) LogPrep(); else RunTerminer(); // switch (carS) //a pour Arret, l pour Log sans specifier de durée // { // case 'a': RunTerminer(); break; //Arret du run // case 'l': LogPrep(); break; //Lance un run // default: // Serial.println(); // BT.println(); // Serial.println("?"); // BT.println("?"); // delay(3000); // return; //Erreur, mais continuer run // } } void InitSDcard() ///////////////////////////////// { Serial.print(F("Initializing SD card...")); BT.println(F("Initialisation de la carte SD")); if (!SD.begin(CS)) { //Chip Select = 1 si carte OK*************************** Serial.println(F("initialization failed!")); BT.println(F("Initialisation impossible, vérifier la carte SD")); BT.println(F("Relancer le programme")); while (1) ; //Rester bloqué ici } else { BT.println(F("initialisation OK")); Serial.println(F("initialisation OK")); } delay(2000); // Créer le fichier des numeros de log s'il n'existe pas if (SD.exists("NextR.txt")) { //************************************* Serial.println(F("NextR.txt existe")); BT.println(F("NextR.txt existe")); } else { myFile = SD.open("NextR.txt", FILE_WRITE); //Le creer myFile.println(String(1)); //Avec RunNb =1 myFile.close(); } LogPrem = 0; //Pour ne pas revenir dans cette fonction } void Lec_AFR() /////////////////////////////////////////// { AFRu = analogRead(AFR); //1v correspond à 2.92 points d'AFR + 7.4 AFRv = map(AFRu, 0, 1023, 74, 221); // AFR valeur entre 7.4 et 22.1 } void Lec_AP() /////////////////////////////////////////////////// { APu = analogRead(AP); //Position papillons Throttle Position Sensor en % TPS = map(APu, APumin, APumax, 0, 100); // TPS 0 à 100% TPSarrondi = int ((TPS+5)/10)*10; // Angle papillon arrondi par pas de 10% } void LecRunNb() ///////////////////////////////////////////////////// { //Lire depuis NextR.txt le numero RunNb du prochain Run 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 de la chaine de caractères } myFile.close(); } void LogPrep() //////////////////////////////////////////////////////////// { InitSDcard(); //Initialiser la carte SD, bloquera si problème //Lire le numero de run RunNb, seul enregistrement du fichier NextR.txt LecRunNb(); // 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); 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("Enregistrement tr/mn, AFR & angle papillon (d'après www.loutrel.org)"); myFile.println("; ; ; ; ; ; ; ; ; ; ; ;"); //Leading blank line String header = "Temps ms;Nt/mn ;AFR ;% Ouv. Pap.;Tr/mn par pas;% Ouv par pas"; // les entêtes de colonnes myFile.println(header); // ensuite les lignes seront ajoutées par PrepLigne() Dcum = 0; //Calcul de la durée Hdr = millis(); //Heure de début de run Temps = millis() - Hdr; //Temps ecoulé en ms depuis le debut du run RunF = 1; //Demarre Run digitalWrite(LedRun, 1); delay(1000); } void PrepLigne() //Lecture de toutes les entrées, affichage ou stockage////////////////////////////////// { while (digitalRead(Cible) == 0) ; //attente du passage à 1 de la cible T = micros() - prec_H; // Cible arrivée prec_H = micros(); //Nouvelle heure de reference N = 30000000 / T; //N en t/mn Narrondi = (int ((N+125) / 250)) * 250 ; //N en tr/mn classé par pas de 250tr/mn if (N < 7000) { Lec_AFR(); Lec_AP(); //Position des papillon, TPS en % CtAff = CtAff + T; //cumul les temps if (CtAff >= AffPerMic) { //Afficher toutes les AffPer secondes CtAff = 0; AffLigne(); } if (RunF == 1) //Run en cours { CtEtin++; //une étincelle de plus if (CtEtin == LogNetin) //Log après LogEtin étincelle, si atteint on ecrit la SD { Ligne = String(Temps) + ";" + String(N) + ";" + String(AFRv) + ";" + String(TPS) + ";" + String(Narrondi) + ";" + String(TPSarrondi) + ";"; myFile.println(Ligne); //Ecrire la carte SD, sans la fermer CtEtin = 0; //Reset } Dcum = Dcum + T; //Pour afficher la duree en fin de run Temps = millis() - Hdr; //Temps ecoulé en ms depuis le debut du run // delay(1); Dialog(); //Voir si arret demandé } } TPSprec = TPS; //Noter precedent while (digitalRead(Cible) == 1) ; //Option:oui ou non attendre fin du 1 de la cible c'estpareil! } void RunTerminer() //////////////////////////////////////////////////////////// { myFile.close(); //Enregistre le fichier des lignes myFile = SD.open(RunFile); //Le reouvrir pour compter les car while (myFile.available()) { //La relire en entier careLu = myFile.read(); CtC++; //Compter les car // Serial.write(myFile.read());// Recopie la ligne courante ************ } myFile.close(); //End of File encountered, stop reading**************** BT.print(F("Run termine: numero, ")); // Serial.println(F("Run termine: numero et duree en s ")); BT.println(RunNb); // Serial.println(RunNb); BT.print(F("duree en s,")); BT.println(Dcum / 1000000); // Serial.println(Dcum / 1000000); BT.print(F("nb de caractères ")); BT.println(CtC); // Serial.println(CtC); //Si <200 rien d'enregistré! delay(5000); RunF = 0; //Pas de run en cours digitalWrite(LedRun, 0); } void loop() ////////////////////////////////////////////////////////////////////////// { PrepLigne(); //Attend cible puis affiche N et AFR Dialog(); //Voir si car entré au clavier }