// =================================================================== // Inclusion de librairie et initialisation de l'écran LCD #include #include LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // =================================================================== // Initialisation des touches #define rightKey 0 #define upKey 1 #define downKey 2 #define leftKey 3 #define selectKey 4 #define NUM_KEYS 5 // =================================================================== // Création de Caractere speciaux: fleche haut et fleche bas byte flHaut[9] = { B00100, B01110, B11111, B11111, B00000, B00000, B00000, B00000, }; byte flBas[9] = { B00000, B00000, B00000, B00000, B11111, B11111, B01110, B00100, }; // Initialisation des entrées/sorties int ledPin = 13; //Menu racine (nombre de mode et titre) #define nbMode 3 char tableauDesModes[5][17] = {" INTERVALL. >", "< MICRO DETECT.>", "< IR DETECT. >", "< FONCTION4. >", "< FONCTION5. "}; //Nombre de reglage par mode byte nbReglageINTERVALL = 5; byte nbReglageMICROSENSOR = 6; byte nbReglageIR = 6; // Reglage de l'intervallometre: int periodeUnite = 0; int periodeValeur = 0; int dureeUnite = 0; int dureeValeur = 0; // Reglage du seuil par défaut (le seuil est commun au micro et l'infrarouge. // Il est redefinit lors de la phase de detection du niveau actuel: int seuil = 500; // Reglage de retard et repetition generique int tempsUnite = 0; int tempsValeur = 0; int occurence = 1; //Maintenance du niveau de navigation et du choix de fonction byte actualArbo = 0; byte modeChoisi = 0; void setup() { pinMode(ledPin, OUTPUT); // Initialisation du Lcd, de l'arduino et des caractères lcd.createChar(0, flHaut); lcd.createChar(1, flBas); lcd.begin(16, 2); lcd.clear(); lcd.print("BrOOgLanD Photos"); lcd.setCursor(0,1); lcd.print("Enjoy !!!"); // On reinitialise les variables de navigation (au cas ou) actualArbo = 0; modeChoisi = 0; // On laisse 2s de temps de démarrage avant d'afficher le menu delay(2000); lcd.clear(); lcd.print(tableauDesModes[modeChoisi]); lcd.setCursor(0,1); lcd.write((uint8_t)1); lcd.setCursor(0,0); } // =================================================================== // Boucle principale avec detection d'appui touche int keyEvent = -1; int lastEvent = -1; // Fonction update screen: Navigation et rafraichissement d'écran void updateScreen() { lcd.clear(); lcd.print(tableauDesModes[modeChoisi]); lcd.setCursor(0,1); lcd.write((uint8_t)1); lcd.setCursor(0,0); switch (modeChoisi) { case 0: switch (actualArbo) { case 0: menuRacineSelect( keyEvent ); break; case 1: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print("Unite periode? "); regTempsUnite ( keyEvent ); break; case 2: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print("Valeur periode?"); regTempsValeur ( keyEvent ); break; case 3: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print("Unite duree? "); regTempsUnite ( keyEvent ); break; case 4: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print("Valeur duree? "); regTempsValeur ( keyEvent ); break; case 5: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print(" INTERVALL Go>>"); declenchementIntervalGo ( keyEvent ); break; default: break; } break; case 1: switch (actualArbo) { case 0: menuRacineSelect( keyEvent ); break; case 1: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print("MIC Niv. Actuel"); detectionNivActuel ( keyEvent, 2 ); break; case 2: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print("MIC Niv. detect"); regSeuilDetection ( keyEvent, 50 ); break; case 3: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print("Unite retard ?"); regTempsUnite( keyEvent ); break; case 4: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print("Valeur retard ?"); regTempsValeur( keyEvent ); break; case 5: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print("Nb repetition ?"); regRepetition( keyEvent ); break; case 6: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print(" MIC Go>>>>>>> "); declenchementGo( keyEvent, 2 ); break; default: break; } break; case 2: switch (actualArbo) { case 0: menuRacineSelect( keyEvent ); break; case 1: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print(" IR Niv. Actuel"); detectionNivActuel ( keyEvent, 1 ); break; case 2: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print(" IR Niv. Detect"); regSeuilDetection ( keyEvent, 1 ); break; case 3: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print("Unite retard ?"); regTempsUnite( keyEvent ); break; case 4: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print("Valeur retard ?"); regTempsValeur( keyEvent ); break; case 5: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print("Nb repetition ?"); regRepetition( keyEvent ); break; case 6: lcd.clear(); lcd.setCursor(0,0); lcd.write((uint8_t)0); lcd.setCursor(1,0); lcd.print(" INFRARED Go>>"); declenchementGo ( keyEvent, 1 ); break; default:break; } break; default: break; } } // Fonction loop: Navigation et rafraichissement d'écran void loop() { int keyEvent = detectKey(); if (keyEvent >= 0) { switch (keyEvent) { case upKey: if (actualArbo > 0) actualArbo--; updateScreen(); break; case downKey: case selectKey: switch (modeChoisi) { case 0: if (actualArbo < nbReglageINTERVALL) actualArbo++; updateScreen(); break; case 1: if (actualArbo < nbReglageMICROSENSOR) actualArbo++; updateScreen(); break; case 2: if (actualArbo < nbReglageIR) actualArbo++; updateScreen(); break; default: break; } break; case rightKey: case leftKey: switch (modeChoisi) { case 0: switch (actualArbo) { case 0: menuRacineSelect( keyEvent ); break; case 1: case 3: regTempsUnite ( keyEvent ); break; case 2: case 4: regTempsValeur ( keyEvent ); break; case 5: declenchementIntervalGo ( keyEvent ); break; default: break; } break; case 1: switch (actualArbo) { case 0: menuRacineSelect( keyEvent ); break; case 1: detectionNivActuel ( keyEvent, 2 ); break; case 2: regSeuilDetection ( keyEvent, 50 ); break; case 3: regTempsUnite ( keyEvent ); break; case 4: regTempsValeur( keyEvent ); break; case 5: regRepetition( keyEvent ); break; case 6: declenchementGo( keyEvent, 2 ); break; default: break; } break; case 2: switch (actualArbo) { case 0: menuRacineSelect( keyEvent ); break; case 1: detectionNivActuel ( keyEvent, 1 ); break; case 2: regSeuilDetection ( keyEvent, 1 ); break; case 3: regTempsUnite( keyEvent ); break; case 4: regTempsValeur( keyEvent ); break; case 5: regRepetition( keyEvent ); break; case 6: declenchementGo ( keyEvent, 1 ); break; default: break; } break; default: break; } break; default: break; } } } // Gestion de la navigation menu racine (choix des fonctions) void menuRacineSelect( int keyEvent ) { switch (keyEvent) { case rightKey: if (modeChoisi < nbMode-1) modeChoisi++; break; case leftKey: if (modeChoisi > 0) modeChoisi--; break; default: break; } lcd.setCursor(0,0); lcd.print( tableauDesModes[modeChoisi] ); } //***================================================================================================ //=================================================================================================== // ********** FONCTION INTERVALLOMETRE ************** // On peut regler la période (mS jusqu'a plusieurs jours), la durée (1S jusqu'a plusieurs jours) // Utilise les fonctions generique regTempsUnite et regTempsValeurs (pour la période et la duree) //******************* declenchementIntervalGo //******************* Declenchement de la sortie en fonction des paramétres regle précédement (valable uniquement pour intervallometre) void declenchementIntervalGo( int keyEvent ) { // Initialisation des variables de la fonction int j = 1; long periode = 1; long duree = 1; // Verification de l'unite de la periode si on est en micro seconde on interdit le declenchement // Verification de l'unite de la duree si on est en micro seconde ou en milli seconde on interdit le declenchement if (periodeUnite > 0 || dureeUnite > 1) { // Convertion en milliseconde de la période d'interval if (periodeUnite == 1) { // Temps mS periode = periodeValeur; } else if (periodeUnite == 2) { // Temps S periode = periodeValeur*1000; } else if (periodeUnite == 3) { // Temps M periode = periodeValeur*60000; } else if (periodeUnite == 4) { // Temps H periode = periodeValeur*3600000; } else if (periodeUnite == 5) { // Temps J periode = periodeValeur*86400000; } // Convertion en milliseconde de la durée de l'intervallomètre if (dureeUnite == 2) { // Temps S duree = dureeValeur*1000; } else if (dureeUnite == 3) { // Temps M duree = dureeValeur*60000; } else if (dureeUnite == 4) { // Temps H duree = dureeValeur*3600000; } else if (dureeUnite == 5) { // Temps J duree = dureeValeur*86400000; } // Création du compteur (nb de declenchement): j = duree/periode; lcd.setCursor(0,0); lcd.print(" INTERVALLOMETRE" ); lcd.setCursor(1,1); lcd.print( "<< Go? >> "); // Lancement ou non de l'intervallometre switch (keyEvent) { case rightKey: // Lancement lcd.setCursor(1,1); lcd.print (" "); if(duree >= periode) { // Uniquement si la durée totale est superieur a la periode for (int i=1; i<=j; i++) { // Debut de l'intervallometre digitalWrite(ledPin, HIGH); // Allumer la LED delay(300); // Temps de declenchement pour voir la led digitalWrite(ledPin, LOW); // Eteindre la LED delay(periode); // Attendre le temps de la periode lcd.setCursor(1,1); lcd.print(i); lcd.print (" / "); // Comptage du nombre de photo du timelapse lcd.print(j); } } else { // Sinon on affiche une erreur lcd.setCursor(1,1); lcd.print( "Err:Periode>Dure"); } lcd.setCursor(1,1); lcd.print( " Fini ! "); // On precise la fin de l'intervallometre break; case leftKey: // Annulation on retourne sur le menu précedent if (actualArbo > 0) actualArbo--; updateScreen(); break; default: break; } } else { lcd.setCursor(0,0); lcd.print("Err: Trop petit" ); lcd.setCursor(1,1); lcd.print( "Unite et Periode"); } } //=================================================================================================== //=================================================================================================== //================================================================================================*** //***================================================================================================ //=================================================================================================== // ********** FONCTION GENERIQUE ************** // Plusieurs fonction disponible (la plupart orienté pour le micro et l'infrarouge mais peuvent être réutilisé pour d'autres capteurs // detectionNivActuel: Detecte le niveau actuel du capteur (de 0 a 1023), cela aidera pour définir le seuil de declenchement // regSeuilDetection: Reglage du seuil de detection pour le declenchement (la valeur de pas est définit lors de l'appel a la fonction) // regTempsUnite: Reglage de l'unite du compteur de temps (delai, periode, duree pour le moment) // regTempsValeur: Reglage de la valeur du compteur de temps (delai, periode, duree pour le moment) // regRepetition: Reglage du nombre d'occurence (nombre de fois ou on s'attend a une detection) // declenchementGo: Declenchement générique en fonction de la detection de l'évenement, adapté pour le micro et l'infrarouge pr le moment) //******************* detectionNivActuel //******************* Si micOrIr = 2 c'est detection micro si 1 c'est detection Infrarouge void detectionNivActuel ( int keyEvent, int micOrIr ) { lcd.setCursor(0,1); lcd.write((uint8_t)1); lcd.print( " " ); lcd.setCursor(1,1); lcd.print( "Val: "); if (micOrIr == 2) { // Seuil micro on regarde une fois le bruit ambiant pour adapter le seuil lcd.print(seuil); delay(300); } else if (micOrIr == 1) { //Seuil infrarouge on regarde pendant 20s la lumiere ambiante et le taux avec coupure pour adapter le seuil au besoin for(int i=0; i<60; i++){ lcd.print(analogRead(micOrIr)); delay(150); lcd.setCursor(0,1); lcd.write("-"); delay(150); lcd.setCursor(0,1); lcd.write("|"); lcd.setCursor(6,1); } lcd.setCursor(0,1); lcd.write((uint8_t)1); } seuil = analogRead(micOrIr); // On enregistre le niveau actuel (qu'on envoi vers la variable seuil) } //******************* regSeuilDetection //******************* micOrIr permet d'adapter le pas de reglage //******************* En general un pas de 50 pour le micro et un pas de 1 pour la led infrarouge sont suffisants void regSeuilDetection ( int keyEvent, int micOrIr ) { lcd.setCursor(0,1); lcd.write((uint8_t)1); lcd.print( " " ); lcd.setCursor(1,1); lcd.print( "Seuil: "); switch (keyEvent) { case rightKey: // Augmentation du seuil de detection if (seuil >= 0 && seuil < 1023) { seuil = seuil + micOrIr; if (seuil > 1023) { // Securité si apres le Pas le seuil monte au dessus de 1023 seuil = 1023; } } else { seuil = seuil; } break; case leftKey: // Diminution du seuil de detection if (seuil > 0) { seuil = seuil - micOrIr; if (seuil < 0) { // Securité si apres le Pas le seuil descend en dessous de 0 seuil = 0; } } else { seuil = seuil; } break; } if (seuil > 0) { lcd.print("<"); } else { lcd.print(" "); } lcd.print(seuil); if (seuil < 1023) { lcd.print(">"); } else { lcd.print(" "); } } //******************* regTempsUnite //******************* Choix de l'unite de temps: uS, mS, S, M, H, J void regTempsUnite ( int keyEvent ) { lcd.setCursor(0,1); lcd.write((uint8_t)1); lcd.print( " " ); lcd.setCursor(1,1); lcd.print( "Unite: "); switch (keyEvent) // Gestion de l'unite choisit { case rightKey: if(tempsUnite <5){ tempsUnite++; } break; case leftKey: if(tempsUnite >0){ tempsUnite--; } break; } if (tempsUnite > 0) { lcd.print("<"); } else { lcd.print(" "); } switch(tempsUnite) { // Gestion de l'affichage de l'unite case 0: lcd.print("uS"); break; case 1: lcd.print("mS"); break; case 2: lcd.print(" S"); break; case 3: lcd.print(" M"); break; case 4: lcd.print(" H"); break; case 5: lcd.print(" J"); break; } if (tempsUnite < 5) { lcd.print(">"); } else { lcd.print(" "); } if (modeChoisi == 0) { // Cas specifique intervallometre: On définit les variables intervallometre si on est dans le cas de l'intervallomètre switch(actualArbo){ case 1: periodeUnite = tempsUnite; break; case 3: dureeUnite = tempsUnite; break; default: break; } } } //******************* regTempsValeur //******************* Choix de la valeur de temps: de 0 à 10000 void regTempsValeur ( int keyEvent ) { lcd.setCursor(0,1); lcd.write((uint8_t)1); lcd.print( " " ); lcd.setCursor(1,1); lcd.print( "Valeur: "); switch (keyEvent) // Incrementation de la valeur { case rightKey: // Augmentation if (tempsValeur < 20) { tempsValeur = tempsValeur + 1; } else if (tempsValeur >= 20 && tempsValeur < 100) { tempsValeur = tempsValeur + 5; } else if (tempsValeur >= 100 && tempsValeur < 200) { tempsValeur = tempsValeur + 10; } else if (tempsValeur >= 200 && tempsValeur < 500) { tempsValeur = tempsValeur + 20; } else if (tempsValeur >= 500 && tempsValeur < 2000) { tempsValeur = tempsValeur + 50; } else if (tempsValeur >= 2000 && tempsValeur < 10000) { tempsValeur = tempsValeur + 100; } else { tempsValeur = tempsValeur; } break; case leftKey: // Diminution if (tempsValeur >= 1 && tempsValeur <= 20) { tempsValeur = tempsValeur - 1; } else if (tempsValeur >= 20 && tempsValeur <= 100) { tempsValeur = tempsValeur - 5; } else if (tempsValeur > 10 && tempsValeur <= 200) { tempsValeur = tempsValeur - 10; } else if (tempsValeur > 200 && tempsValeur <= 500) { tempsValeur = tempsValeur - 20; } else if (tempsValeur > 500 && tempsValeur <= 2000) { tempsValeur = tempsValeur - 20; } else if (tempsValeur > 2000 ) { tempsValeur = tempsValeur - 100; } else { tempsValeur = tempsValeur; } break; } if (tempsValeur > 0) { lcd.print("<"); } else { lcd.print(" "); } lcd.print(tempsValeur); if (tempsValeur < 10000) { lcd.print(">"); } else { lcd.print(" "); } if (modeChoisi == 0) { // Cas specifique intervallometre: On définit les variables intervallometre si on est dans le cas de l'intervallomètre switch(actualArbo){ case 2: periodeValeur = tempsValeur; break; case 4: dureeValeur = tempsValeur; break; default: break; } } } //******************* regRepetition //******************* Choix du nombre d'occurence: par pas de 1 void regRepetition ( int keyEvent ) { lcd.setCursor(0,1); lcd.write((uint8_t)1); lcd.print( " " ); lcd.setCursor(1,1); lcd.print( "Repeat: "); switch (keyEvent) { case rightKey: //Augmentation if (occurence < 50) { occurence = occurence + 1; } else { occurence = occurence; } break; case leftKey: // Diminution if (occurence > 1 && occurence <= 50) { occurence = occurence - 1; } else { occurence = occurence; } break; } if (occurence > 1) { lcd.print("<"); } else { lcd.print(" "); } lcd.print(occurence); if (occurence < 50) { lcd.print(">"); } else { lcd.print(" "); } } //******************* declenchementGo //******************* Declenchement de la sortie en fonction des paramétres regle précédement (valable pour micro et infrarouge) void declenchementGo ( int keyEvent, int micOrIr ) { lcd.setCursor(0,0); if ( micOrIr == 2){ // Detection du mode pour afficher le texte en fonction lcd.print(" MICRO SENSOR " ); lcd.setCursor(1,1); lcd.print( "<< Go? >> "); } else if (micOrIr == 1) { lcd.print(" INFRARED " ); lcd.setCursor(1,1); lcd.print( "<< Go? >> "); } switch (keyEvent) { case rightKey: // Lancement du declenchement sur seuil de detection lcd.setCursor(1,1); lcd.print (" "); lcd.setCursor(1,1); lcd.print( " Attente ! "); for(int i=1;i<=occurence;i++) { while (analogRead(micOrIr) < seuil) { } if(tempsUnite == 0) { // Temps uS delayMicroseconds(tempsValeur); } else if (tempsUnite == 1) { // Temps mS delay(tempsValeur); } else if (tempsUnite == 2) { // Temps S int ret = tempsValeur*1000; delay(ret); } else if (tempsUnite == 3) { // Temps M int ret = tempsValeur*60000; delay(ret); } else if (tempsUnite == 4) { // Temps H int ret = tempsValeur*3600000; delay(ret); }else if (tempsUnite == 5) { // Temps J int ret = tempsValeur*86400000; delay(ret); } digitalWrite(ledPin, HIGH); // Activation de la sortie delay(300); // Attente de 300ms (voir si il faut rendre cette variable reglable) digitalWrite(ledPin, LOW); // Desactivation de la sortie lcd.setCursor(1,1); lcd.print (" "); lcd.setCursor(1,1); lcd.print(i); lcd.print (" / "); lcd.print(occurence); } lcd.setCursor(1,1); lcd.print( " Fini ! "); break; case leftKey: // Annulation if (actualArbo > 0) actualArbo--; updateScreen(); break; } } //=================================================================================================== //=================================================================================================== //================================================================================================*** // *** GESTION DES APPUIES TOUCHES // =================================================================== // Convert ADC value to key number int adc_key_val[NUM_KEYS] ={ 50, 160, 360, 535, 760 }; int get_key(unsigned int input) { int k; for (k = 0; k < NUM_KEYS; k++) { if (input < adc_key_val[k]) return k; } if (k >= NUM_KEYS) k = -1; // No valid key pressed return k; } // =================================================================== // new key detection routine, without delays! int lastKeyEvent = 0; int curKeyEvent = 0; int keyToReturn = 0; boolean keyToProcess = false; int adc_key_in = 0; int detectKey() { keyToReturn = -1; adc_key_in = analogRead(0); // read the value from the sensor curKeyEvent = get_key(adc_key_in); // convert into key press if (curKeyEvent != lastKeyEvent) { if (!keyToProcess) { lastKeyEvent = curKeyEvent; keyToProcess = true; } else { keyToReturn = lastKeyEvent; lastKeyEvent = -1; keyToProcess = false; } } return keyToReturn; } // =================================================================== // ***