La reconnaissance vocale n'étant pas fiable, j'ai cherché un autre moyen de piloter mon module.
Je me suis tourné vers un encodeur/switch.
Je vous invite à regarder une page google pour en savoir plus sur les encodeurs.
Recherche google
En gros on récupère un signal de cette forme aux bornes de codeur.
Suivant le décalage De A ou B on connais le sens et la vitesse.
Afin de voir dans un menu le résultat de la rotation du codeur, j'ai ajouter un écran LCD 2×16 en I2C.
Et pour le fun, une led RGB !
Je me suis créer une petit maquette avec le fruit de mes réflexions sur l'émission IR et le capteur de lumière.
Sous eagle comme d'hab.
Comme je voulais laisser la place pour un émetteur/récepteur RF433MHz et un récepteur IF.
J'ai été obligé de laisser les pattes : 2,3,10 et 11 disponibles.
J'avais donc un problème pour le codeur et le switch afin de récupérer une action rapidement.
J'ai découvert que quasi toutes les pattes de l'arduino pouvait générer une interruption, du coup plus de soucis.
J'ai commencé avec la librairie attachinterrupt :
http://www.arduino.cc/en/Reference/AttachInterrupt
Puis utilisé EnableInterrupt qui est plus récent et mis à jour :
https://github.com/GreyGnome/EnableInterrupt
Tout n'est pas de moi !
J'ai pris des exemples à droite et gauche puis assemblé le tout.
Les sources sont cités au début.
Le menu n'a que 5 choix, mais on peu en ajouter plus et même créer des sous menus.
Il n'y a pas la gestion RF et récepteur IF comprise. Pour l'instant je suis sur une maquette.
/* Logiciel des fonctions de la platine * exemple lcd de la lib liquidcrystal_i2c * encodeur sur http://bildr.org/2012/08/rotary-encoder-arduino/ * Encodeur utilise EnableInterrupt * DHT11 http://total-informatique.com/utiliser-le-dht11-avec-un-ecran-lcd/ * RGB http://www.mbeckler.org/microcontrollers/rgb_led/ * Menu https://skyduino.wordpress.com/2014/07/06/arduino-lcd-faire-un-menu-sous-forme-de-liste/ * * Synoptique : * On affiche un message de bienvenue * Affiche température et humidité * Si bouton tourne ou push * Affiche menu * Gestion menu */ #include <avr/pgmspace.h> // library for keeping variables in Flash RAM #include "Wire.h" #include "LiquidCrystal_I2C.h" #include "DHT.h" // Librairie pour le capteur DHT #include <IRremote.h> #include <EnableInterrupt.h> // ### Menu ### prog_char const mainMenu1[] PROGMEM = "1.Television "; prog_char const mainMenu2[] PROGMEM = "2.XBMC "; prog_char const mainMenu3[] PROGMEM = "3.Lum centre "; prog_char const mainMenu4[] PROGMEM = "4.Lum bandeau"; prog_char const mainMenu5[] PROGMEM = "5.Luminosite"; const char* const mainMenu[] PROGMEM = { mainMenu1, mainMenu2, mainMenu3, mainMenu4, mainMenu5}; // Data télécommande #define cmd_code 0xffffffff // remote code pour transmettre. #define Tv_onoff 0x20df10ef // Codes des télécommandes #define Tv_volP 0x20df40bf #define Tv_volM 0x20dfc03f #define Ampli_on 0x7e817e81 #define Ampli_off 0x7e81fe01 #define Ampli3 0x5eA1609e #define Ampli2 0x5eA1c03e #define Ampli_volP 0x5eA158a7 #define Ampli_volM 0x5eA1d827 // Codes des télécommandes // ### Definition DHT ### #define DHTPIN 6 //Pin auquel est connecté le capteur DHT #define DHTTYPE DHT11 //Si vous utiliser le DHT 11 //#define DHTTYPE DHT22 //Si vous utiliser le DHT 22 (AM2302) //#define DHTTYPE DHT21 //Si vous utiliser le DHT 21 (AM2301) // ### Definition RGB ### #define slen 7 // 7 characters, e.g. '#ff6666' /* Définition IR */ #define REMOTE_BIT 3532 #define tempsIR 100 // Temps entre 2 commandes IR // ### Definition senseur lumière ### #define LUM_SENSOR_PIN A0 // lumière sensor connected to this analog pin // Var pour DHT float fltHumidity; //Pourcentage d'humidité mesuré float fltTemperature; //Température mesurée en Celsius float hum; // ancienne val humidité float temp; // ancienne val température // Var pour RGB int redPin = 10; // Red LED, connected to digital pin 9 int greenPin = 9; // Green LED, connected to digital pin 10 int bluePin = 12; // Blue LED, connected to digital pin 11 // ### Definition Encoder ### //these pins can not be changed 2/3 are special pins #define encoderPin1 7 #define encoderPin2 8 #define encoderSwitchPin 4 //push button switch volatile int lastEncoded = 0; volatile long encoderValue = 0; //long lastencoderValue = 0; long ancienencoderValue = 0; // ==== Variables Générales ==== const int intTimePause = 5000; //Par défaut on actualise les valeures toutes les 5 secondes long position = -999; char serInStr[slen]; // array to hold the incoming serial string bytes boolean TV = false; boolean sortm = false; unsigned long TimeOut; char buffer[16]; // make sure this is large enough for the largest string it must hold //char prompt = "Choisissez !"; //IR LED must be connected to Arduino PWM pin 3. IRsend irsend; // innitialise l' IR object LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display DHT dht(DHTPIN, DHTTYPE); //On initialise le capteur DHT boolean bp=false; int r, v, b; void BPtest() { bp=true; // Renvoie bp vrai si bouton pressé } void updateEncoder() { int MSB = digitalRead(encoderPin1); //MSB = most significant bit int LSB = digitalRead(encoderPin2); //LSB = least significant bit int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; lastEncoded = encoded; //store this value for next time // Renvoie la valeur encoderValue contenant la position. } // Attach the interrupt in setup() void setup() { Serial.begin(115200); lcd.init(); // initialize the lcd pinMode(encoderPin1, INPUT_PULLUP); // Défini les pattes de l'encodeur pinMode(encoderPin2, INPUT_PULLUP); pinMode(encoderSwitchPin, INPUT_PULLUP); enableInterrupt(encoderPin1, updateEncoder, CHANGE); enableInterrupt(encoderPin2, updateEncoder, CHANGE); enableInterrupt(encoderSwitchPin, BPtest, CHANGE); pinMode(redPin, OUTPUT); // sets the pins LED RGB as output pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); ancienencoderValue=encoderValue=0; bp=false; // Message de bienvenue sur le LCD. lcd.backlight(); lcd.print("Salut le monde!"); lcd.setCursor(0, 1); lcd.print("Tourne le bouton"); delay(1500); lcd.clear(); } // Affiche une couleur de led void led_rgb(int teinte) { HSVtoRGB(&r, &v, &b, teinte, 255, 255); analogWrite(redPin, r ); analogWrite(greenPin, v ); analogWrite(bluePin, b ); } //Fin du void void loop() { //Affiche la temp/humidité si pas menu tmphum(); // Affiche temp et humidité //Test, gestion menu if (ancienencoderValue != encoderValue) { // Si le bouton tourne Serial.println("tourne"); affmenu3(); } // Affiche une led rouge prete led_rgb(0); } //FIN DE LOOP // *** Affiche le choix du menu suivant la position de l'encoder // Change aussi la couleur de la led *** void affmenu3() { Serial.print("Entree dans le choix"); //Serial.println(bp); /* Variable pour le menu */ int nbItems = 5; // Défini le nb d'irem dans le menu byte selectedMenuItem = 1; // Choix sélectionné byte shouldExitMenu = false; // Devient true quand l'utilisateur veut quitter le menu unsigned long TempMax; boolean boucle = false; // Test de boucle pour aff long color; // Stock la couleur int ValC[ ]= {40, 80, 120, 160, 200}; // Affiche une premiere valeur lcd.clear(); lcd.print("Choisissez !"); strcpy_P(buffer, (char*)pgm_read_word(&(mainMenu[selectedMenuItem-1]))); lcd.setCursor(0, 1); lcd.print(buffer); TempMax=millis(); while ((!bp) && (millis() < TempMax+20000)) { // tant que bp off et tempsMAx < /* change la led rgd */ led_rgb(ValC[selectedMenuItem+1]); /* Gére le sens du codeur */ long encoder = encoderValue - ancienencoderValue; Serial.println(selectedMenuItem); //Serial.print("Encoder :"); Serial.println(encoder); if (encoder != 0) { if (encoder > 0) { // on inc /* S'il existe un choix précédent */ if(selectedMenuItem > 1) { selectedMenuItem--; } } else { // on dec /* S'il existe un choix suivant */ if(selectedMenuItem < nbItems) { /* Passe au choix suivant */ selectedMenuItem++; } else { selectedMenuItem=nbItems; } } // Affiche le nouveau menu lcd.setCursor(0, 1); lcd.print(" "); // Aff ligne vide strcpy_P(buffer, (char*)pgm_read_word(&(mainMenu[selectedMenuItem-1]))); lcd.setCursor(0, 1); lcd.print(buffer); Serial.print("Menu :");Serial.println(selectedMenuItem); } ancienencoderValue=encoderValue; } /* Bouton appuyé */ //Serial.print("bp appuyé :"); Serial.println(bp); if(bp) { displayChoice(selectedMenuItem); } bp=false; led_rgb(0); } // Fin du void void tmphum() { // Lit le capteur et affiche les résultats. fltHumidity = dht.readHumidity(); //On lit le pourcentage d'humidité fltTemperature = dht.readTemperature(); //On lit la température en degrés Celsuis if (isnan(fltTemperature) || isnan(fltHumidity)) //Si les valeures retournées ne sont pas des nombres : { lcd.setCursor(0, 1); //Positionnement du curseur lcd.print(DHTTYPE); //On affiche le type de capteur lcd.setCursor(5, 1); lcd.print(" illisible"); //On affiche l'erreur } else { if ((hum != fltHumidity) || (temp != fltTemperature)) lcd.clear(); //Serial.print("Lecture temp/hum"); Serial.println(fltTemperature); //mise en forme et affichage des informations sur l'écran LCD //lcd.setdelay(intTimePause); //On actualise les informations toutes les x millisecondes.Cursor(0, 0); //Positionnement du curseur if (hum != fltHumidity) { lcd.setCursor(0, 0); lcd.print(" "); // Aff ligne videlcd.print( } lcd.setCursor(0, 0); lcd.print("Degres : "); lcd.setCursor(9, 0); lcd.print(fltTemperature); //Affichage de la température lcd.setCursor(13, 0); lcd.print((char)223); //Affiche le caractère ° (degrés) lcd.setCursor(14, 0); lcd.print("C"); //En degrés Celsuis if (temp != fltTemperature) { lcd.setCursor(0, 1); lcd.print(" "); // Aff ligne videlcd.print( } lcd.setCursor(0, 1); lcd.print("Humidite : "); lcd.setCursor(11, 1); lcd.print(fltHumidity); //Affichage de l'humidité lcd.setCursor(15, 1); lcd.print("%"); } //delay(intTimePause); //On actualise les informations toutes les x millisecondes. temp = fltTemperature; hum = fltHumidity; } /** Affiche le choix de l'utilisateur */ void displayChoice(byte selectedMenuItem) { bp=false; /* Affiche le choix de l'utilisateur */ lcd.clear(); lcd.print(F("Z'avez choisi :")); lcd.setCursor(0, 1); strcpy_P(buffer, (char*)pgm_read_word(&(mainMenu[selectedMenuItem]))); lcd.print(buffer); delay(500); /* Selection de l'ordre */ switch(selectedMenuItem) { case 0 : //television lcd.clear(); lcd.print(F("Television")); if (!TV) { // Tv pas allumé Serial.write("ordre tv on");Serial.println(selectedMenuItem); irsend.sendNEC(Ampli3, REMOTE_BIT); // irsend.sendNEC(cmd_code, REMOTE_BIT); // delay(tempsIR); irsend.sendNEC(0x20df10ef, 3532); // irsend.sendNEC(cmd_code, REMOTE_BIT); // delay(tempsIR); TV=true; } else { Serial.write("ordre tv off"); irsend.sendNEC(Ampli_off, REMOTE_BIT); irsend.sendNEC(cmd_code, REMOTE_BIT); delay(tempsIR); irsend.sendNEC(Tv_onoff, REMOTE_BIT); irsend.sendNEC(cmd_code, REMOTE_BIT); delay(tempsIR); TV=false; } break; case 1 : //XBMC lcd.clear(); lcd.print(F("XBMC")); if (!TV) { // xbmc pas allumé Serial.write("ordre xbmc on"); irsend.sendNEC(Ampli2, REMOTE_BIT); irsend.sendNEC(cmd_code, REMOTE_BIT); delay(tempsIR); irsend.sendNEC(Tv_onoff, REMOTE_BIT); irsend.sendNEC(cmd_code, REMOTE_BIT); delay(tempsIR); TV=true; } else { Serial.write("ordre xbmc off"); irsend.sendNEC(Ampli_off, REMOTE_BIT); irsend.sendNEC(cmd_code, REMOTE_BIT); delay(tempsIR); irsend.sendNEC(Tv_onoff, REMOTE_BIT); irsend.sendNEC(cmd_code, REMOTE_BIT); delay(tempsIR); TV=false; } break; case 2 : //Lumière table lcd.clear(); lcd.print(F("Lum Table")); break; case 3 : //Lumière bandeau lcd.clear(); lcd.print(F("Lum bandeau")); break; case 4 : //Luminosité lumin(); break; delay(2000); } bp=false; Serial.println("Fin d'ordre"); } //Fin displayChoice void lumin() { //Affiche la luminosité meusurée long tempsMax; lcd.clear(); lcd.print(F("Luminosite")); //Serial.print("bp > :"); Serial.println(bp); //delay(50); while (!bp) { tempsMax = millis(); //Serial.print(digitalRead(encoderSwitchPin)); Serial.print(encoderValue); Serial.println(ancienencoderValue); lcd.setCursor(0, 1); lcd.print(" "); // Aff ligne videlcd.print( lcd.setCursor(0, 1); //Positionnement du curseur lcd.print(analogRead(LUM_SENSOR_PIN)); //delay(200); while (millis() < tempsMax+500) { } } bp=false; } //Fin lumin // *** Convertie une lumiére TSV (teinte, saturation, valeur) [HSVen anglais] en RGB (hackable N°6) void HSVtoRGB(int *r, int *g, int *b, int h, int s, int v) { int c; long l, m, n; // saturation zéro, pas de couleur if (s == 0) { *r = *g = *b = v; return; } // chroma c = ((h % 60) * 255) / 60; h /= 60; // intermédiaire l = (v * (256 - s)) / 256; m = (v * (256 - (s * c) / 256)) / 256; n = (v * (256 - (s * (256 - c)) / 256)) / 256; // choix dominante switch (h) { case 0: *r = v; *g = n; *b = l; break; case 1: *r = m; *g = v; *b = l; break; case 2: *r = l; *g = v; *b = n; break; case 3: *r = l; *g = m; *b = v; break; case 4: *r = n; *g = l; *b = v; break; default: *r = v; *g = l; *b = m; break; } } // Fin HSVtoRGB
J'ai pensé mettre ce module dans un cylindre avec 1 bague tournante et l'afficheur en haut derrière un plexi fume.
Les diodes IF seraient à la base tournées dans tout les sens.
On peu prévoir un alim par induction sur un socle.
Le codeur demandera un peu de mécanique pour que la bague l’entraîne mais avec le possibilité d'appuyer pour déclencher le switch.
Un encodeur c'est pas mal à condition d'utiliser les interruptions.
Sinon on loupe des crans, mais malgré les int., on ne peu pas tourner trop vite.
Sous mon code j'ai des pas de 4 à chaque cran, construction du codeur ? Erreur de prog ?
Je ne sais pas, mais il faut y penser dans le code.