char Ver[] = "JcapResDuino_Bluetooth_090418"; //Avec alarmes Ludo //Jauge à carburant capacitive, etalonnable en BlueTooth //Directement dérivé du logiciel ACA, Adaptateur Capteur Afficheur //http://a110a.free.fr/SPIP172/article.php3?id_article=168 détails de l'ACA //Par l'utilisation d'un smartphone (ou tablette) sous Android, //la partie materiel est simplifiée au maximum, 4 ou 5 composants + Nano Arduino et module Bluetooth HC05/06 //Ceci permet de se passer éventuellement de circuit imprimé //Le module Bluetooth ne sert que pour l'etalonnage et peut donc être retiré en utilisation normal //En option on peut ajouter 2 Led d'alarme, voir ci dessous //*****************CABLAGE selon capteur******************* //*CAPTEUR CAPACITIF,à connecter entre A2 et A0, et connecter 220pF entre A0 et la masse //**************************************** //*CAPTEUR RESISTIF, à connecter entre A0 et la masse, //ensuite connecter une resistance de 100 ohms 1/4 W entre +5V et A0 //et enfin connecter A6 à +5V //******************************** //Pour debug:au lieu d'entrer "e" pour etalonnage, entrer "d" et on affiche CC brut et capa en pF #include #include SoftwareSerial BT(10, 11); // RX,TX respectivement vers le HC05/06 à 9600bps #define LedMini 4 //(optionel)Led alarme minimum (C4)à connecter sur D5+resistance //*****************Ajustables si necessaire****************** const int TAFF = 1000; //Durée d'affichage en ms,pour z,a,b,c,d au demarrage const int TdelCad = 1000;//Pas en ms de delCad //*********************************************************** const int delCad = 5; //Pas du cadran pour etalonnage const int FlagRes = A6;//Pour capteur resistif connecter au +5const const int IN_PIN = A0;//Pour capteur capacitif, lit Vc puis decharge C.Sinon lit le capteur resistif const int CADRAN = 9; //Sortie vers afficheur const int OUT_PIN = A2;//Pour capteur capacitif,charge puis decharge C. const float IN_CAP_TO_GND = 240;//Capacite parasite typique, environ 20 à 45 pF // Si on voulait mesurer la capacité avec precision il faudrait etalonner cette valeur //mais en réalité il suffit d'enregistrer la tension du diviseur capacitif float inCap ;//Tension du capteur en unites de 5mV environ int CC; // C'est inCap mais contraint entre C0 et C4 char carLu;//Recoit le car entré ou '@' si aucune action au clavier char EtCouA;//Etalonmage capt ou aff int CapF ; //Juste pour info car c'est la tension CC qui sera stockée //Affichage du cadran/afficheur // Le PWM a une periode de 2ms. Donc une u = 2000/255 = 78 µs environ int tcad ;//Période T à afficher PWM de 0 à 255 int Cap_ou_Res ;//0 si capteur capacitif, 1 pour resistif int C0, C1, C2, C3, C4; //10 valeurs remplies depuis l'EEprom au démarrage int T0, T1, T2, T3, T4; //Périodes d'affichage de z,a,b,c,d const int TCAD_MAX = 255; //Affichage maxi du cadran, en unités PWM int eepC = 0; // pointeur à l'EEPROM: int eepCref = 0; //Pointeur de reference pendant etalonnage, 0 ou 10 int tcadC = 0; //Periode courante du cadran en cours d'étalonnage int stoRe = 0; //Valeur 16bits à ecrire en EEPROM int fromEep = 0; //Valeur 16bits relue de l'EEPROM int hiB = 0; //Lu de l'EEPROM 16 bits int loB = 0; ///Lu de l'EEPROM 8 bits int eW = 0; //pointeur en ecriture à l'EEPROM dans RecopyEeprom() int lByte = 0;//nombre de bytes à lire/ecrire pour l'EEPROM int debFlag = 0; //Si 1, affiche sur Sphone CC brut et valeur de capa en pF //*********************DEFINITION DES FONCTIONS ***************** void Aff5() //////////////////while (1){}///// { //Affiche les 5 points de l'afficheur au demarrage LecEep();//Lit les 5 valeurs capteur et les 5 afficheur depuis l'EEPROM,plus Cap_ouRes PrintEeprom16();//Sur PC et Sphone //Affiche z +les 4 a,b,c,d analogWrite (CADRAN, T0); delay(TAFF); analogWrite (CADRAN, T1); delay(TAFF); analogWrite (CADRAN, T2); delay(TAFF); analogWrite (CADRAN, T3); delay(TAFF); analogWrite (CADRAN, T4); delay(TAFF); } void AfficTcad()/////////while (1){}//////////////// { Serial.print("Ligne_"); Serial.print(__LINE__); Serial.print(" Periode de l'afficheur 0-255: tcad = "); Serial.println (tcad); Serial.println(); analogWrite (CADRAN, tcad); BT.print("Capteur = "); BT.println(CC);//Affiche les valeurs actuelles BT.print("Afficheur = "); BT.println(tcad); } void CalculTcad()///while (1){}/////////////////////////// { //Interpolle pour la periode de l'afficheur CC = constrain(CC, C0, C4); //On contraint CC entre C0 et C4 avant interpollation Serial.print("Ligne_"); Serial.print(__LINE__); Serial.print(" V capteur CC contraint = "); Serial.println(CC); if (CC <= C1) { tcad = (float)((( CC - C0) * (T1 - T0) / (C1 - C0) + T0)); return; } if (CC <= C2) { tcad = (float)((( CC - C1) * (T2 - T1) / (C2 - C1) + T1)); return; } if (CC <= C3) { tcad = (float)((( CC - C2) * (T3 - T2) / (C3 - C2) + T2)); return; } // Donc CC entre C3 et C4 tcad = (float)((( CC - C3) * (T4 - T3) / (C4 - C3) + T3)); } void DetecteCapteur()//////////////////////////////////// { //Detecte le type de capteur connecté et l' enregistre en Eeprom 20 if (analogRead(FlagRes) > 1020) Cap_ou_Res = 1; //Si A6 à + 5 V c'est un capteur resistif qui est connecté else Cap_ou_Res = 0; //Capteur capacitif connecté stoRe = Cap_ou_Res; eepC = 20; //Stocker en 20 le type de capteur WriteEep16(); BT.print("Capteur juste detecte: "); Serial.print("Capteur juste detecte: "); if (Cap_ou_Res == 0) { BT.println("Capacitif"); Serial.println("Capacitif"); } else { BT.println("Resistif"); Serial.println("Resistif"); } // pinMode(OUT_PIN, OUTPUT); //Restore Serial.println(); } void GetValeurAfficheur()//while (1){}/////////// //Augmente la valeur de l'affichage et verifie inferieure au max de l'echelle { analogWrite(CADRAN, tcadC);//Afficher en deplacant l'aiguille tcadC = tcadC + delCad; //Augmenter de delCad l'affichage if (tcadC >= TCAD_MAX )tcadC = 0; //Revenir à 0, on depasse } void GetValeurCapteur()//while (1){}/////////// //Fait la moyenne des nech capas lues et calcul int CC { pinMode(IN_PIN, INPUT);//Initialiser en Input int nech = 100; //Nb d'echantillon à moyenner long int acc = 0; //accumulation des echantillons for (int i = 1; i <= nech; i++) { // Serial.print("Cap_ou_Res =="); Serial.println(Cap_ou_Res ); if (Cap_ou_Res == 1)inCap = analogRead(IN_PIN); //Resistif else { //Pour lire le Vin du diviseur capacitif C/Cparasite pinMode(OUT_PIN, OUTPUT); pinMode(IN_PIN, INPUT);//Ici se trouve, soit la capacité, soit la resistance variables digitalWrite(OUT_PIN, HIGH);//Charge la capa C et la capa parasite en série. inCap = analogRead(IN_PIN); // Lecture de la tension via le convertisseur analogique/numerique digitalWrite(OUT_PIN, LOW);// première decharge pinMode(IN_PIN, OUTPUT);//deuxiéme decharge CapF = (float)inCap * IN_CAP_TO_GND / (float)(1023 - inCap);//Calul approximatif en pF } acc = acc + inCap; //cumul delay(10);//tous les 10ms } inCap = (float)acc / (float)nech; //moyenne sur nech CC = (int)inCap; Serial.print("Ligne_"); Serial.print(__LINE__); Serial.print(" V capteur brut CC = "); Serial.println(CC); if (Cap_ou_Res == 0) { Serial.print("Ligne_"); Serial.print(__LINE__); Serial.print(" Capacite en pF environ "); Serial.print( CapF); Serial.println(" pF"); if (debFlag == 1) { BT.print("***Capteur brut CC "); BT.println(CC); BT.print("***Capacite en pF environ "); BT.print( CapF); BT.println(" pF"); delay(2000); } } } void LecEep()//while (1){}/////////////////////////////////// { //Relit l'Eeprom en memoire eepC = 0; //pointeur à l'EEprom, on lit de 0 à 20 soit 11 valeurs de 16 bits ReadEep16(); C0 = fromEep; //En 0,1 ReadEep16(); C1 = fromEep; ReadEep16(); C2 = fromEep; ReadEep16(); C3 = fromEep; ReadEep16(); C4 = fromEep; ReadEep16(); T0 = fromEep; //En 10,11 ReadEep16(); T1 = fromEep; ReadEep16(); T2 = fromEep; ReadEep16(); T3 = fromEep; ReadEep16(); T4 = fromEep; ReadEep16(); Cap_ou_Res = fromEep; //En 19 et 20 type de capteur } void Liste_zabcd()////////////////////////////////////// { //Liste les 5 valeurs , soit pour le capteur soit pour l'afficheur eepC = eepCref;//0 ou 10 BT.println(); if (eepC == 0)BT.println("Valeurs Capteur en memoire"); else BT.println("Valeurs Afficheur en memoire"); ReadEep16();//Lit, ecrit 16 bits dans fromEep,et index eePc BT.print("z = "); BT.println(fromEep); ReadEep16(); BT.print("a = "); BT.println(fromEep); ReadEep16(); BT.print("b = "); BT.println(fromEep); ReadEep16(); BT.print("c = "); BT.println(fromEep); ReadEep16(); BT.print("d = "); BT.println(fromEep); delay(3000);//Le temps d'admirer } void LitCar()//////////////////////////////////////// { //Attendre l'arrivée d'un car imprimable donc valable while (BT.available() > 0)carLu = BT.read(); //Purge while (1) //On elimine les car de controle tels CR(13) ou LF/NL (10) { carLu = ""; while (BT.available() <= 0);//rien à lire carLu = BT.read();// 1 car arrivé if ((carLu >= 33) && (carLu <= 122))break; //Car valable, on sort } delay(100); } void ModeEtalonnage() ////////////////////////////////////// { TestSiCarRecu(); //Purge le buffer { while (1) { BT.println(); // BT.print("Capteur de type "); // if (Cap_ou_Res == 0)BT.println("Capacitif"); // else BT.println("Resistif"); BT.println("Pour etalonner le capteur: c"); BT.println("Pour etalonner l'afficheur: a"); LitCar(); if (carLu == 'c' || carLu == 'a')break; BT.println("?"); } EtCouA = carLu; //Sauver le mode if (EtCouA == 'c')eepCref = 0 ; //Capteur, debut Eprom else eepCref = 10; //Afficheur Eprom 10 while (1) { Liste_zabcd();//Afficher les 5 valeurs en memoire // if (EtCouA == 'c')LireCapteur(); //Capteur à lire // else LireAfficheur();// Afficheur à actionner puis le lire SelectionnerPointFixe(); //Faire defiler des valeurs pour un choix Liste_zabcd();//Afficher les 5 valeurs en memoire BT.println(); BT.print("Enregistrer "); BT.print(stoRe); BT.println(" en memoire comme"); BT.println("z, ou a, ou b, ou c, ou d ?"); BT.println("ou annuler par k ?"); BT.println("Pour quitter l'etalonnage, q "); LitCar(); //store contient deja CC, la valeur du capteur BT.println(carLu); if (carLu == 'q') return;//Sortir de l'etalonnage eepC = 100; //Utilisé comme flag if (carLu == 'z') eepC = eepCref; //eePc est 0 ou 10 if (carLu == 'a') eepC = eepCref + 2; if (carLu == 'b') eepC = eepCref + 4; if (carLu == 'c') eepC = eepCref + 6; if (carLu == 'd') eepC = eepCref + 8; if (eepC < 100) { //C'est bon, memoriser et sortir WriteEep16(); BT.print("enregistre comme "); BT.println(carLu); LecEep();//Recopie en C0-C4,T0-T4 les valeurs juste ecrites en EEp } } } } void PrintEeprom16()//while (1){}////////////////////// { eepC = 0; Serial.println( "EEPROM de 0 a 21, C0-C4, T0-T4, Type de capteur"); // BT.println( "EEPROM de 0 a 21, C0-C4, T0-T4, Type de capteur"); while (eepC < 22) { ReadEep16(); //les 5 C, les 5T,Cap_ou_Res Serial.println( fromEep); //BT.println( fromEep); } Serial.println();// BT.println( fromEep); } void PropEtal()/////////////////////////// { //Propose l'etalonnage du capteur ou de l'afficheur BT.println(); BT.println("Pour executer un etalonnage touche e puis touche d'envoi"); delay(3000); TestSiCarRecu(); if (carLu == 'e')ModeEtalonnage(); if (carLu == 'd')debFlag = 1; //Pour imprimer CC brut et capa en pF BT.println(); } void RazEeprom(int ad1, int nB) //while (1){}////////////// //A partir de l'adresse ad1, on met à 0 nB bytes { for (int i = 0; i < nB; i++) EEPROM.write(ad1 + i, 0); } void ReadEep16()//while (1){}////////////////////// { //Termine en indexant eePc hiB = EEPROM.read(eepC);// Serial.print("hiB__");Serial.println(hiB); eepC++; loB = EEPROM.read(eepC);//Serial.print("loB__");Serial.println(loB); eepC++; //preparer prochaine adresse fromEep = (hiB << 8) + loB; } void RestoreEtalonnage()//////while (1);///////////////////////////// { //A utiliser eventuellement depuis setup() //Pour ecrire en EEPROM les 10+1 const int à saisir ci dessous // En 20 mettre 0 ou 1 selon capteur capa ou resistif //const int C0 = 153; C1 = 196, C2 = 220, C3 = 239, C4 = 260 ; //Capacité de la jauge en pF,cable compris // const int T0 = 0; T1 = 89, T2 = 119, T3 = 154, T4 = 240; // cadran Veglia A110 avec JcapRes duino const int T0 = 75; T1 = 95, T2 = 125, T3 = 165, T4 = 245; // cadran Veglia A110 avec ACA const int C0 = 441; C1 = 451, C2 = 481, C3 = 500, C4 = 517 ; //Capacitif avec ACA relevé sur A110 // const int T0 = 50, T1 = 93, T2 = 123, T3 = 157, T4 = 230; //Cadran Osculatti FUEL(bleu) // const int C0 = 17; C1 = 453, C2 = 686, C3 = 778, C4 = 899 ; //Resistif 1kohms // const int T0 = 230, T1 = 157, T2 = 123, T3 = 93, T4 = 50; //Cadran Osculatti FUEL(bleu)Simulé inversé // const int C0 = 22; C1 = 56, C2 = 130, C3 = 276, C4 = 485 ; //Capacitif capa variable: 50, 80,150,300,500pF eepC = 0; //Debut d'EP stoRe = C0; WriteEep16(); stoRe = C1; WriteEep16(); stoRe = C2; WriteEep16(); stoRe = C3; WriteEep16(); stoRe = C4; WriteEep16(); stoRe = T0; WriteEep16(); stoRe = T1; WriteEep16(); stoRe = T2; WriteEep16(); stoRe = T3; WriteEep16(); stoRe = T4; WriteEep16(); //////////////////Ne pas oublier!!!!!!!!!!!!!!!! stoRe = 1; WriteEep16();//En eep 20, 0 capteur capacitif, 1 resistif } void SelectionnerPointFixe()/////////////////////////////////// { //Revient avec la valeur dans sTore TestSiCarRecu(); //Purge le buffer tcadC = 0; //Afficheur à 0 while (1) { if (EtCouA == 'c') { GetValeurCapteur();//Etalonnage du capteur BT.print("Valeur capteur actuelle : "); BT.println(CC); BT.println("Pour la figer f"); delay(2000); stoRe = CC;// preparer à stocker en Ep,eventuellement } else { GetValeurAfficheur();//Etalonnage de l'affichage BT.print("Valeur afficheur actuelle : "); BT.println(tcadC); BT.println("Pour la figer f"); delay(TdelCad); //Attente pour afficher cette valeur de tcadC stoRe = tcadC;// preparer à stocker en Ep,eventuellement } TestSiCarRecu();//Voir si on a tapé " f" if (carLu == 'f' ) { BT.println("Confirmer c, ou reprendre le defilement d "); LitCar(); if (carLu == 'c')return; //Sortir du defilement if (carLu == 'd') ; //Continuer à defiler else BT.println("?"); //Continuer à defiler } } if (carLu != '@' )BT.println("?"); } void TestSiCarRecu()//////////////////////////////////////////////////////// { // On lit au vol un car s'il est present dans le buffer, sans s'attarder carLu = '@';//Char donc simple quote, pas une String, double quote if (BT.available() > 0) //Le buffer n'est pas vide { carLu = BT.read() ;//Garder le premier car char cpurge; //Purger le buffer while (BT.available() > 0 ) cpurge = BT.read(); } } void VerifAlarme() //////////////////////////////// { //Test si CC C4 if (CC < C0)digitalWrite(LedMini, 1); else digitalWrite(LedMini, 0); if (CC > C4)digitalWrite(LedMaxi, 1); else digitalWrite(LedMaxi, 0); } void WriteEep16() ///////while (1);/////////////// { //Ecrit stoRe en Eep puis indexe eePc // Serial.print("Write_eepC__stoRe_ "); Serial.println(eepC); Serial.println(stoRe); //while (1){} EEPROM.write(eepC, highByte (stoRe)); //MSByte eepC ++; EEPROM.write(eepC, lowByte (stoRe)); //LSByte eepC ++; //preparer prochaine adresse } ///////////////////////******************************************** void setup() { pinMode(FlagRes, INPUT);// A + 5V si capteur resistif pinMode(OUT_PIN, OUTPUT);//Charge puis decharge C, à la masse si resistif pinMode(IN_PIN, INPUT);// Lit Vc puis decharge C, lit Vin resistif pinMode(CADRAN, OUTPUT); //Sortie PWM vers l'afficheur pinMode(LedMini, OUTPUT); //Alarme basse pinMode(LedMaxi, OUTPUT); //Alarme haute BT.begin(9600);//La liaison série soft D10 et D11 vers module Bt HC05 ou 06 !!!VERIFIER cette vitesse!! Serial.begin(9600); BT.println(); Serial.println(); BT.println(); Serial.println(); Serial.println(__DATE__); Serial.println(__TIME__); BT.println(__DATE__); BT.println(__TIME__); BT.print(" "); Serial.println(Ver); BT.println(Ver); BT.println(); BT.println(); Serial.println("Bonjour"); BT.println("Bonjour"); BT.println(); BT.println(); // RestoreEtalonnage();//Utiliser avec precaution Aff5(); // Affiche 0 +a,b,c,d au demarrage DetecteCapteur();//Initialise Cap_ou_Res } ///////////////******************************************** void loop() { PropEtal();//Proposer l'etalonnage GetValeurCapteur();//Lire CC VerifAlarme();//Les 2 Led d'alarme haute et basse CalculTcad();// Interpolle pour calculer Tcad, 0 à 255 AfficTcad(); //PWM Tcad, vers l'afficheur } //Pour differents cadrans sur établi //const int C0= 175, C1= 200, C2= 220, C3= 235, C4= 255 ;//Capacité de la jauge en pF //const int T0= 10,T1= 23,T2= 69,T3= 100,T4= 179;// cadran Veglia //Température 40°,60°,80°,100° logique inversée //const int T0= 100,T1= 117,T2= 133,T3= 155,T4= 200;// 13V important! pour ces cadrans //const int T0= 50, T1= 93,T2= 123,T3= 157,T4= 230;//Cadran Osculatti FUEL(bleu) //Mesuré avec des capas en labo //picoFarad: 40 70 100 150 200 250 300 350 400 //CC unité: 520 650 730 800 854 882 905 920 932