Arduino Infrarouge, relais pour télécommande de lit sans fil

Support pour le kit de communication infra rouge (IR)

Arduino Infrarouge, relais pour télécommande de lit sans fil

Message non lude AlexandreV » Jeu 18 Mai 2017 13:53

Bonjour,

j'ai écrit un code en m'inspirant de tuto et exemple pour créer un système télécommandé par infrarouge avec 4 relais pour monter descendre mon lit et mon dossier de lit.

Pourquoi ? Je suis tétraplégique et une fois couché je peux utiliser seulement une télécommande infrarouge et mon fabriquant de lit à arrêté de commercialisé ce produit qui au bout de 10ans a lâché (il en vendait pas assez m'a dit le représentant, sympa hein :x ).

Du coup si une âme charitable veux bien me donner son avis sa serai très gentil, car c'est mon 1er programme Arduino alors je loupe certainement des trucs importants !

Comme pour
Code: Tout sélectionner
millis();

La doc dit qu'elle revient à 0 après environ 50 jours, alors mon test vous parait bon pour cette éventualité ou elle revient à 0 alors qu'un relai est actif ? La je coupe, l'utilisateur devra relâcher le bouton et appuyer à nouveau, les probabilité que sa arrive sont faible je pense ...

Merci d'avance pour votre aide :oops:.

Code: Tout sélectionner
#include <IRremote.h> // libraries for get infrared code

#define DEBUG // for get debug informations
//#undef DEBUG // for production

//for led usage
#define LED_ON HIGH
#define LED_OFF LOW
#define null -1 // INT - used for check/set if a relay are active

//for relay usage
#define RELAY_ON HIGH
#define RELAY_OFF LOW
#define PIN_RELAY_BED_UP 4 // INT - relay PIN to activate for put bed up
#define PIN_RELAY_BED_DOWN 5 // INT - relay PIN to activate for put bed down
#define PIN_RELAY_BUST_UP 6 // INT - relay PIN to activate for put bust up
#define PIN_RELAY_BUST_DOWN 7 // INT - relay PIN to activate for put bust down

//for infrared usage
#define PIN_IR_RECV 2 // INT - infrared receveir PIN
#define TC_BED_UP 0x20FFEA15 // HEXADECIMAL - remote controller button code for bed going up
#define TC_BED_DOWN 0x20FF1AE5 // HEXADECIMAL - remote controller button code for bed going down
#define TC_BUST_UP 0x20FFAA55 // HEXADECIMAL - remote controller button code for bust bed going up
#define TC_BUST_DOWN 0x20FF6A95 // HEXADECIMAL - remote controller button code for bust bed going down

#define LOOP_DELAY 200 // MILLISECONDS - how much time we wait before check if a new command infrared are send by user
#define TIMEOUT_DELAY 500 // MILLISECONDS - i'm guessing here, this needs to be longer than the IR repeat intervalsend
#define INITIALIZATION_DELAY 4000 // MILLISECONDS - time to wait before end of initialization

IRrecv irReceiver(PIN_IR_RECV); // infrared receiver class
decode_results irResults; // for get result value

int relayOn = null; // we store active relay pin when user press button for put on/off
unsigned long lastButtonTime = millis(); // we store time when we see last time user press button, so we can know how much time since user release button
unsigned long actualButtonTime; // we store atual time - lastButtonTime for check if time are out and we need stop relay on

#ifdef DEBUG
  #define DEBUG_PRINT(Str)  Serial.print(Str)
  #define DEBUG_PRINTLN(Str)  Serial.println(Str)
#else
  #define DEBUG_PRINT(Str)
  #define DEBUG_PRINTLN(Str)
#endif

void setup() {
  #ifdef DEBUG
    Serial.begin(9600);
  #endif
  DEBUG_PRINTLN("Start initialization");

  pinMode(LED_BUILTIN, OUTPUT); // we turn off on board led
  digitalWrite(LED_BUILTIN, LED_OFF);
  DEBUG_PRINTLN("Turned off onboard led");

  //we set correct mode for relay and set them to off
  DEBUG_PRINTLN("Set the relay off");
  pinMode(PIN_RELAY_BED_UP, OUTPUT);
  digitalWrite(PIN_RELAY_BED_UP, RELAY_OFF);
  pinMode(PIN_RELAY_BED_DOWN, OUTPUT);
  digitalWrite(PIN_RELAY_BED_DOWN, RELAY_OFF);
  pinMode(PIN_RELAY_BUST_UP, OUTPUT);
  digitalWrite(PIN_RELAY_BUST_UP, RELAY_OFF);
  pinMode(PIN_RELAY_BUST_DOWN, OUTPUT);
  digitalWrite(PIN_RELAY_BUST_DOWN, RELAY_OFF);
  DEBUG_PRINTLN("All relay are off");

  // in case the interrupt driver crashes on setup, give a clue
  // to the user what's going on.
  DEBUG_PRINTLN("Enabling Infrared");
  irReceiver.enableIRIn(); // start the receiver
  DEBUG_PRINTLN("Enabled Infrared");

  delay(INITIALIZATION_DELAY); // check that all relays are inactive at Reset
  DEBUG_PRINTLN("End initialization");
}

void loop()
{
  if (irReceiver.decode(&irResults)) // if we have a code receveid
  {
    // we check if code received are a correct command
    switch (irResults.value)
    {
      case TC_BED_UP: // user press button for make up the bed
        relayOpen(PIN_RELAY_BED_UP);
        break;
      case TC_BED_DOWN: // user press button for make down the bed
        relayOpen(PIN_RELAY_BED_DOWN);
        break;
      case TC_BUST_UP: // user press button for make up the bed bust
        relayOpen(PIN_RELAY_BUST_UP);
        break;
      case TC_BUST_DOWN: // user press button for make down the bed bust
        relayOpen(PIN_RELAY_BUST_DOWN);
        break;
      case REPEAT: // user continue press a button
        if (relayOn != null) // if we have a relay already on it's a correct button user stay on
        {
          lastButtonTime = millis();  // update the time-out
        }
        break;
    }

    irReceiver.resume(); // receive the next value
  }

  // if a relay are on
  // and millis() reset to 0 automatically when overflow, so if less than lastButtonTime we stop for prevent bug
  // or turn off relay if time is out, user stop push button
  actualButtonTime = millis(); // actual time since arduino start
  if (relayOn != null && (actualButtonTime < lastButtonTime || (actualButtonTime - lastButtonTime) > TIMEOUT_DELAY))
  {
    relayClose();
  }

  delay(LOOP_DELAY);
}

void relayOpen(int relay)
{
  relayClose(); // if a relay are on we stop it before set another on, bed cannot going up and down at same time...

  relayOn = relay; // we save witch relay are now on
  digitalWrite(relayOn, RELAY_ON); // we set relay on
  lastButtonTime = millis(); // we keep time for check time out
  relayStatePrint("on"); //we print witch relay are on
}

void relayClose()
{
  // we check if a relay are on else nothing to do
  if (relayOn != null)
  {
    digitalWrite(relayOn, RELAY_OFF); // we set to off relay actually on
    relayStatePrint("off"); // we print witch relay are off before reset var because relayOn are used in function relayStatePrint
    relayOn = null; // no more relay are on
  }
}

void relayStatePrint(String state)
{   
  if (relayOn != null)
  {
    // we print relay state, ex: Relay bed up on
    DEBUG_PRINT("Relay ");
    switch (relayOn) // we check witch PIN are in relayOn var
    {
      case PIN_RELAY_BED_UP:
        DEBUG_PRINT("bed up");
        break;
      case PIN_RELAY_BED_DOWN:
        DEBUG_PRINT("bed down");
        break;
      case PIN_RELAY_BUST_UP:
        DEBUG_PRINT("bust up");
        break;
      case PIN_RELAY_BUST_DOWN:
        DEBUG_PRINT("bust down");
        break;
    }
    DEBUG_PRINTLN(" " + state + ".");
  }
  else
  {
    DEBUG_PRINTLN("ERROR: No active relay found (relayOn are null).");   
  }
}

AlexandreV
 
Messages: 4
Inscription: Mar 16 Mai 2017 17:05

Re: Arduino Infrarouge, relais pour télécommande de lit sans

Message non lude Laetitia » Mer 31 Mai 2017 14:50

Bonjour,

Quelques petites remarques au niveau du code :

  • Code: Tout sélectionner
    #define null -1

    Il vaut mieux éviter de redéfinir des variables connues de l'IDE (elles sont repérables grâce à la coloration syntaxique) pour minimiser les erreurs de compilation. NULL représente l'état d'un pointeur ne pointant sur aucun objet !

  • Code: Tout sélectionner
    unsigned long lastButtonTime = millis();

    La fonction millis() tourne en continu dès le lancement du sketch, mais pas depuis la compilation! La valeur initiale de lastButtonTime n'est donc pas connue, il est préférable d'écrire :

    Code: Tout sélectionner
    unsigned long lastButtonTime = 0;

  • La variable actualButtonTime n'est pas forcément nécessaire puisqu'elle prend la valeur de millis() et est comparée immédiatement...

  • Code: Tout sélectionner
    case REPEAT: // user keeps pressing a button

    De mémoire, la détection d'appui long se fait grâce à un code spécifique émis après le code correspondant à la touche pressée (voir explication du protocole NEC). Celui-ci n'étant pas défini dans votre code, il est improbable que l'appui long sur un bouton soit correctement interprété.

Une façon simple de traiter le problème de rollover est détaillée ici, en anglais. Basiquement on utilise une astuce mathématique pour contourner le retour à zéro du compteur de millis(), et on obtient un test simple, valable tout le temps :

Code: Tout sélectionner
unsigned long lastTime = 0; // initialisation à 0 pour éviter les erreurs de calcul
unsigned long interval = 1000; // temps d'attente entre deux actions régulières

void setup()
{
  /* (...) code d'initialisation */
}


void loop()
{
  /* (...) tâches à effectuer à chaque tour de loop */

  if (millis() - lastTime >= interval) // on vérifie que le temps soit écoulé
  {
    /* (...) tâches à effectuer tous les secondes */
    lastTime = millis(); // on enregistre le dernier passage dans cette boucle
  }
}
"If it's itchy, scratch it !" - "DIY or die"

RTFM (À lire avant de poster) - ANDb (Arduino Noob Database)
Avatar de l’utilisateur
Laetitia
 
Messages: 296
Inscription: Mar 7 Aoû 2012 15:07
Localisation: Toulouse


Retourner vers Kit Communication IR

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 1 invité