Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

telecommande:ext1 [2019/08/13 10:16] (Version actuelle)
Ligne 1: Ligne 1:
 +====== Test avec un encoder/switch ======
  
 +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.
 +
 +[[http://www.aliexpress.com/snapshot/6536924073.html?orderId=66197489434089|Ma commande aliexpress]]
 +
 +Je vous invite à regarder une page google pour en savoir plus sur les encodeurs.\\
 +[[https://www.google.fr/search?q=arduino+encoder&biw=1920&bih=894&tbm=isch&tbo=u&source=univ&sa=X&ei=9lx0VcTvHMzsUsjugdgL&sqi=2&ved=0CCwQsAQ|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.\\
 +{{wiki:rotaryencoderwaveform.gif?300 |}}  \\ 
 +
 +
 +
 +Afin de voir dans un menu le résultat de la rotation du codeur, j'ai ajouter un écran LCD 2x16 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.
 +
 +====== Schémas ======
 +Sous eagle comme d'hab.
 +
 +
 +====== Programmation ======
 +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]]
 +
 +====== Quelques mots sur le code ======
 +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.
 +
 +<code c++>
 +/* 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
 +
 +
 +</code>
 +
 +
 +======= Quelques mots sur la finalisation du projet =======
 +
 +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.\\
 +
 +
 +======= BILAN =======
 +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.
telecommande/ext1.txt · Dernière modification: 2019/08/13 10:16 (modification externe)
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0