//Injection_LoggerV3.0_071220Mod_050321 //Ajouté DinjDel +/- 3ms Ncoupe TPS coupe //PotCor changé pour plus moins 3ms //Avec verification du run juste terminé //Connecté en parallèle sur le Nano d'injection, il lit: //Temps, Nt/mn ,Angle pap deg, Dinj I4 µs,PapDot %/s, AFR, Vbat, Tmot deg, Tair deg //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 //PapDot, vitesse du papillon, est la dérivé: position/temps= vitesse = ((TPS - TPSprec) / D720) * 1000000; //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 = 1; //Periode de l'affichage sur Sphone en secondes //////////////////////////////////////////////////////////////// #include"TimerOne.h" #include //Pour carte SD #include #include //Pour Bluetooth BT File myFile; //Un objet myFile de type File est créé SoftwareSerial BT(2, 3); // RX,TX respectivement vers le HC05/06 à 115200bps #define Cible A5 //Cible AàC sur A5 #define I4 A4//Injecteur 4 #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 carte SD #define Smot A2 //Sonde de temperature moteur, entrée analogique #define Sair A0 //Sonde de température air ambiant, entrée analogique #define Vbat A6 //Batterie #define PotCor A7 //Potar corrige le temps d'injection #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 Vp5 4.8 //En V, tension réelle de valeur théorique +5V pour convertisseur analogique #define Rtm 1000 //Resistance talon sonde température moteur, en ohms #define Rta 1000 //Resistance talon sonde température air, en ohms #define Ncoupe 2500 //Pied levé #define TPScoupe 5 //Pied levé 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 int N = 0; //N en t/mn int APu = 0; //AP en unités 0-1023 float TPS;//Throttle Position Sensor de 0 à 100% 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 int PotCoru = 0; //PotCor en unités 0-1023 int Vbatu = 0; //Vbat en unités 0-1023 int Vmu = 0; //temp mot en unités 0-1023 int Vau = 0; //temp air en unités 0-1023 float Vmv = 0; //V temp mot en volts float Vav = 0; //V temp air en unités 0-1023 float Vbatterie = 0; //A partir de Vbat float CorTmot = 100; //en % correctif temperature moteur float CorTair = 100; //en % correctif temperature air float CorPot = 1; //correctif modulation de l'injection par potard ex 50 à 120% byte RunF = 0; //Flag etat d'un run: 0pas de run, 1 en cours, 2 en pause 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% float Rm = 0; //Resistance de la sonde Tmoteur, en ohms float Ra = 0; //Resistance de la sonde Tair, en ohms int DegM = 0; // Température moteur en degrès int DegA = 0; // Température air en degrès 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 DinjDel = 0; //Par Potcor +/-3ms //************************************************************* 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("Dinj 4 mics ")); Serial.println(D14); BT.print(F("Dinj 4 mics ")); BT.println(D14); BT.print(F("PapDot ")); BT.println(PapDot); BT.print(F("AFR ")); BT.println(AFRv); BT.print(F("Vbatterie ")); BT.println(Vbatterie); BT.print(F("Tmot ")); BT.println(DegM); BT.print(F("Tair ")); BT.println(DegA); // BT.print(F("CorPot ")); BT.println(CorPot); BT.print(F("CorPot ")); BT.println(DinjDel); BT.print(F(" Dernier Run N° ")); BT.println(RunNb); //N° de run BT.print(F(" Taille en caractères ")); BT.println(CtC); } 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); switch (carS) //d pour Durée, a pour Arret, l pour Log sans specifier de durée { case 'a': RunTerminer(); break; case 'l': LogPrep(); break; //Lance un run de durée par défaut default : Serial.println(); BT.println(); Serial.println("?"); BT.println("?"); delay(3000); //Erreur } } void InitSDcard()///////////////////////////////// { Serial.print(F("Initializing SD card...")); BT.println(F("Initialisation de la carte SD")); if (!SD.begin(CS)) { //SD.begin(4) = 1 , 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("initialization OK")); Serial.println(F("initialization 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 exists.")); BT.println(F("NextR.txt exists.")); } 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% } void Lec_Vbat()////////////////////////////////// { Vbatu = analogRead(Vbat); Vbatterie = Vbatu * 0.0153; // Pont diviseur de 10k et 4.7k } void LecD14()//////////////////////////////////////////////////// { while (digitalRead(I4) == 0); //Attente gate = 1, injecteurs 1/4 ON D14 = micros(); // Noter l'heure while (digitalRead(I4) == 1); //Attente gate = 0, injecteurs 1/4 OFF D14 = micros() - D14; // Durée } void LecPotCor()///////////////////////////////////////////////////// //Pour une correction en %,-30 à +30% { PotCoru = analogRead(PotCor); // if (PotCoru < 10)CorPot = 1; //Pot au mini, pas de correction // else CorPot = map(PotCoru, 0, 1023, 70, 130) / 100.; //Modulera Dinj // // Serial.print ("CorPot= "); Serial.println (CorPot); DinjDel = map(PotCoru, 0, 1023, 0, 6000); DinjDel = DinjDel - 3000; //Correction Dinj en µs, + à - 3000µs } 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 LecTair()///////////////////////////////////////////// { CorTair = 1; Vau = analogRead(Sair); //De 0 à 1023 Vav = (float)Vau * (Vp5 / 1023); //Convertir en V Ra = (float)Vav * (Rta / (Vp5 - Vav)); //R du capteur if (Ra >= 1050)DegA = (float)((3453 - Ra) / 55.7);//Première droite else { DegA = (float)((1662 - Ra) / 13.6);//Seconde droite } } void LecTmot()///////////////////////////////////////////// { CorTmot = 1; Vmu = analogRead(Smot); //De 0 à 1023 Vmv = (float)Vmu * (Vp5 / 1023); //Convertir en V Rm = (float)Vmv * (Rtm / (Vp5 - Vmv)); //R du capteur if (Rm >= 1500)DegM = (float)((4880 - Rm) / 110.);// Première droite else { if (Rm >= 500)DegM = (float)((2700 - Rm) / 40.);//Deuxième droite else { DegM = (float)((1257 - Rm) / 12.8); //Troisième droite } } } void LogPrep()//////////////////////////////////////////////////////////// { if (LogPrem == 1)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(" INJECTION Alpine A110 1600S"); myFile.println("; ; ; ; ; ; ; ; ; ; ; ;"); //Leading blank line String header = "Temps ms;Nt/mn ;TPS en %;D4 mics;PapDot;AFR;Vbatterie;Tmot;Tair;DinjDel ";// les entêtes de colonnes myFile.println(header);// ensuite les lignes seront ajoutées par EcrireLigne() 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 delay(1000); } void PrepLigne() //Lecture de toutes les entrées, affichage ou stockage////////////////////////////////// { while (digitalRead(Cible) == 1); //attente du passage à 0 de la cible D720 = micros() - prec_H; // Cible arrivée, durée de 2 tours vilo = 1 tour AàC prec_H = micros(); //Nouvelle heure de reference N = 120000000 / D720; //N en t/mn Lec_AP(); //Position des papillon, TPS en % D14 = 0; //Pied levé quand N>Ncoupe et TPS Ncoupe) && (TPS <= TPScoupe))) LecD14(); //Temps d'activité de la gate de l' IGBT pourI4 sauf si Dinj=0 Lec_AFR(); Lec_Vbat(); LecTmot(); // LecTair(); //Trop long LecPotCor(); PapDot = ((TPS - TPSprec) / D720) * 1000000; //Dérivée de la position/temps= vitesse CtAff = CtAff + D720; //cumul les temps if (CtAff >= AffPerMic) { //Afficher toutes les AffPer secondes CtAff = 0; AffLigne(); } if (RunF == 1) //Run en cours { Ligne = String(Temps) + ";" + String(N) + ";" + String(TPS) + ";" + String(D14) + ";" + String(PapDot) + ";" + String(AFRv) + ";" + String(Vbatterie) + ";" + String(DegM) + ";" + String(DegA) + ";" + String(DinjDel) + ";"; myFile.println(Ligne); //Ecrire la carte SD, sans la fermer Dcum = Dcum + D720; //Pour afficher la duree en fin de run Temps = millis() - Hdr; //Temps ecoulé en ms depuis le debut du run Dialog(); //Voir si arret demandé } TPSprec = TPS; //Noter precedent while (digitalRead(Cible) == 0);//Option:oui ou non attendre fin du 0 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.println(F("Run termine: numero, duree en s, nb de caractères ")); Serial.println(F("Run termine: numero et duree en s ")); BT.println(RunNb); Serial.println(RunNb); BT.println(Dcum / 1000000); Serial.println(Dcum / 1000000); BT.println(CtC); Serial.println(CtC); //Si <200 rien d'enregistré! delay(5000); RunF = 0; //Pas de run en cours } //void Tst_BT() //Ceci est un test de BT, à lancer depuis setup()/////////////////// //{ int BTdata = 0; // //**************Vers PC // Serial.println("Bonjour "); // Serial.println("Le caractere entre sur l'Android doit se retrouver ci dessous"); // //***************Vers module // BT.println(" "); // BT.println(" "); // BT.println("Bonjour sur Android"); // BT.println(" "); // BT.println("HC05, la led doit clignoter 2 flash, 1s Off, 2flash..."); // BT.println(" "); // BT.println("HC06, led On fixe"); // BT.println(""); // BT.println("Entrer un caractere "); // BT.println("S'il se retouve sur le PC, tout va bien..."); // while (1) // { if (BT.available()) //Car pret en entrée sur Serie soft? // { BTdata = BT.read(); //oui, le clavier Android BT a émis un car // BT.println(" ");//Aller à la ligne sur sphone // Serial.write(BTdata);//ecrire le car sur le PC // Serial.println(); // } // } //} void setup() ///////////////////////////////////////////////////// { Serial.begin(115200); //Pour moniteur PC Serial.println("Hello"); Serial.println(); BT.begin(115200); //Pour Sphone, Bluetooth BT.println(F("****************************")); BT.println(F("Logger pour injection Alpine 1600S")); Serial.println(F("Hello world")); BT.println(F("****************************")); // Tst_BT(); //Boucle infinie pour test liaison BT BT.println(F("l pour Lancer le log")); BT.println(F("a pour Arreter le log")); delay(5000); pinMode(Cible, INPUT_PULLUP); //Vient du capteur Hall pinMode(I4, INPUT); //Gate de l'IGBT AffPerMic = AffPer * 1000000; //Periode d'affichage en µs } void loop() ////////////////////////////////////////////////////////////////////////// { PrepLigne(); Dialog(); }