J’ai entièrement refait mon projet GarageDoor avec d’une part un nouveau hardware sans TinkerIt et d’autre part, un nouveau programme en langage C++/Objet avec de l’Ajax et du Javascript.

Sommaire

Nouveau hardware

Au départ mon boîtier de porte de Garage était composé d’un Arduino Leonardo et d’un shield TinkerIt. Le problème est qu’il n’y a pas d’inverseur « fin de course » dans la gamme TinkerIt. J’ai donc utilisé leur capteurs à effet Hall. Le problème de ces capteurs magnétiques est que les valeurs fluctuent parfois sans raisons apparentes ce qui rendait mon programme inutilement complexe.

Circuit sans TinkerIt

J’ai alors décidé que maintenant que je savais brancher directement des interrupteurs et des LED sur un Arduino, plus rien ne m’empêchait de me passer de ces shield et modules TinkerIt. Car même s’ils sont vraiment géniaux pour réaliser un prototype fonctionnel avec peu de connaissances en électronique, ils sont relativement chers à l’achat comparés à leur homologues génériques et on se retrouve limité à ces modules alors qu’il existe une multitude de composants sur le marché. J’ai donc réalisé le câblage suivant :

Shéma de câblage
Schéma de câblage

Calcul des résistances

Les valeurs de résistances pour les interrupteurs sont choisies en fonction de la longueur du câble. Celui-ci fait parfois plusieurs mètres pour relier le boîtier avec un capteur de fin de course. Plus le câble est long, plus il est préférable de laisser passer un courant important stabilisant ainsi le signal. Pour ce faire, j’ai utilisé cet excellent article qui explique bien l’intérêt de résistance pull-up et pull-down, le choix des valeurs et pourquoi il ne faut pas utiliser un inverseur pour câbler directement les états LOW et HIGH.

Le problème de surconsommation des relais

Au départ, j’ai utilisé cette carte relais que j’ai alimentée directement avec la sortie 5V de l’Arduino :

Carte 2 relais
Carte 2 relais

J’ai alors remarqué que l’Arduino rebootait régulièrement lors de certaines combinaisons d’états des relais. Il y avait 2 causes possibles à cela. La première est une consommation de courant trop importante des relais pour l’alimentation 5V de l’Arduino qui manque parfois de puissance. La 2ème est le parasitage que peut provoquer l’alimentation des bobines des relais avec l’alimentation de l’Arduino.

Ce qui m’étonnait car avec la présence d’opto-coupleurs, je croyais mon circuit parfaitement isolé. Mais c’était une erreur de débutant ! En effet, tant qu’il n’y a qu’une seule source d’alimentation, il ne peut y avoir d’isolation efficace avec les composants en présence sur cette carte. Pour mieux comprendre, voici le circuit de câblage de cette carte relais :

Circuit interne de la carte relai
Circuit interne de la carte relais

Le cavalier en bleu sur la photo précédente relie le point VCC (l’alimentation provenant de l’Arduino) avec le point JD-VCC (l’alimentation des bobines des relais). En résumé, le cavalier court-circuite l’opto-coupleur ! C’est pourquoi, j’ai retiré ce cavalier et amené du 5V provenant d’un régulateur séparé que voici :

Circuit de régulation LM7805 (12V -> 5V)
Circuit de régulation LM7805 (12V -> 5V)

Finalement, j’ai un ensemble très stable et peu coûteux. Une unique alimentation 230V-AC vers 12V-DC récupérée dans ma réserve de déchets électroniques alimente donc 3 choses :

  • L’Arduino
  • La barrière photo-électrique (alimentée uniquement lorsque la porte est ouverte)
  • Le régulateur 12V-5V LM7805 qui alimente donc les relais

Photos

Pour finir avec la partie hardware, voici quelques photos du montage électronique :

Nouveau software

Depuis quelques projets, j’ai abandonné l’IDE Arduino (l’ancien sketch est dispo ici) pour l’IDE Eclipse et son Add-on bien plus adapté à un développement en C++. Mon code source est disponible sur mon GitHub.

Liste des améliorations

Les nouveautés logicielles par rapport à l’ancienne version sont les suivantes :

  • Les pages HTML/Javascript sont maintenant stockées sur la carte SD du shield Ethernet plutôt que dans le microprogramme. C’est plus facile à maintenir car plus lisible (pas de guillemets ni de variables concaténées) et cela libère de la place pour le programme.
  • La page web affichant l’état de la porte se met à jour automatiquement en arrière plan grâce au Javascript et à l’Ajax. Il y a certes du polling mais la réponse ne contient qu’un entier plutôt que la page web complète.
  • Les identifiants d’authentification de la page web ainsi que le token d’accès au compte Twitter sont maintenant stockés dans un fichier properties lui-même écrit sur la carte SD du shield Ethernet.
  • La version précédente n’était constituée que d’un seul fichier source… Dorénavant, la maintenance générale et la lisibilité du code ont été grandement améliorées par l’utilisation de paradigmes Objet:
    • Le IOManager.cpp gère l’ensemble des objets modélisant les entrée/sorties. Ces objets sont implémentés de façon asynchrone et ne bloquent jamais l’exécution de la boucle principale :
      • Entrées :
        • Button.cpp
        • PropertyFile.cpp
      • Sorties :
        • LED.cpp
        • Relay.cpp
        • DoorTwitter.cpp
    • Le DoorStateManager.cpp gère les 7 états possibles de la porte en fonction des entrées. Chaque état gère les sorties :
      • UnknownState.cpp
      • OpenedState.cpp
      • OpeningState.cpp
      • OpeningTimeoutState.cpp
      • ClosedState.cpp
      • ClosingState.cpp
      • ClosingTimeoutState.cpp
    • Le WebManager.cpp gère l’écoute et les réponses aux requêtes HTTP et Ajax. Pour l’implémentation de cette classe, je me suis inspiré de ce lien et de celui-ci.

D’autre part, les librairies SD, Webduino et Twitter étant un peu grosses, il a fallu que je passe d’un Arduino Leonardo à un Arduino Mega pour disposer de plus de mémoire. Mes tentatives pour alléger les librairies n’ayant pas suffi.

Vidéo

Une vidéo valant plus que de longs discours :

Enregistrer

C++ Ajax et Javascript pour mon portier Arduino
Étiqueté avec :                                        

16 avis sur « C++ Ajax et Javascript pour mon portier Arduino »

  • Ping :Sésame, ouvre toi ! Mon portier est un Arduino | Bidouilles Factory

  • 24 septembre 2014 à 8 h 54 min
    Permalien

    Merci pour ces explications. Aurais-tu un schéma au format Fritzing (de la première photo avec l’arduino) à partager ?

    Répondre
      • 24 septembre 2014 à 23 h 01 min
        Permalien

        Du coup, j’ai quelques questions matérielles… 🙂
        Aurais-tu les informations de prix / sites où tu as trouvé le capteur photoélectrique et les switchs à levier (capteur de fin de course) ?
        Aurais-tu également des photos sur la position des switchs par rapport à ta porte ?
        Quelle longueur de câble as-tu mis entre les switchs et le boitier ?

        D’après ton schéma, le relais 2 actionne un émetteur infrarouge. C’est un émetteur maison ou présent avec ta porte de garage ? Même question pour le récepteur ? T’aurais des photos du câblage du relais 2 sur ton boitier relais de ta porte ?

        Merci d’avance

        Répondre
        • 25 septembre 2014 à 17 h 52 min
          Permalien

          Pour la barrière photo électrique (composée d’un émetteur et d’un récepteur infrarouge), je l’ai trouvée sur eBay. Voici une photo du récepteur (l’émetteur a la même forme) :

          Il suffit de chercher sur eBay avec les mots clés « Beam 20M Photoelectric Infrared Detector » en mode « Monde entier ». On trouve les 1ers prix en dessous de 5€. Voici un exemple.
          Pour les capteurs fin de course, tu peux en trouver 10 ici pour 3,40€ avec frais de port gratuit.
          En outre, tu trouvera d’autres photos et explications en visitant mon billet concernant la première version du projet.
          N’hésite pas si tu as d’autres questions.

          Répondre
  • 25 septembre 2015 à 19 h 58 min
    Permalien

    Bonjour,
    Je voulais savoir si c’est difficile de creer une page web (garage.lan dans l’exemple) ? C’est du java script je n’en ai jamais fait !

    Répondre
    • 28 septembre 2015 à 14 h 14 min
      Permalien

      Salut Carbonaro,
      Tu trouvera le code html/javascript de la page garage.lan ici sur Github.
      N’hésite pas à la réutiliser et à l’adapter à ton besoin.
      Le web n’est vraiment pas ma spécialité donc j’ai fait au plus simple pour avoir une page qui se refresh en ajax. C’est à dire sans se rafraichir entièrement.
      Tu trouvera sûrement plein d’aide à ce sujet sur le web.
      Bon courage !

      Répondre
      • 9 octobre 2015 à 17 h 54 min
        Permalien

        Merci beaucoup pour ta réponse (je n’ai pas eu la notif d’où cette réponse tardive !)
        J’ai une autre question ! Peut tu accéder à ta page en dehors de ton réseau ? (en vacances par exemple)

        Répondre
        • 9 octobre 2015 à 18 h 46 min
          Permalien

          J’utilise simplement un accès VPN si j’ai besoin d’un accès à distance.

          Répondre
  • 9 mars 2016 à 18 h 18 min
    Permalien

    Bonsoir, J’ai encore beaucoup de lacunes, Ce sera donc un futur projet.Merci Beaucoup.fb

    Répondre
  • 29 septembre 2016 à 17 h 54 min
    Permalien

    Salut,
    J’ai 2 portes de garages qu’on oublie un peu trop souvent, car non visible et que je souhaite donc contrôler et éventuellement actionner à distance. Après m’être longuement instruit sur le net (solution sans fil, Rasberry, Arduino, domotique…), j’ai décider de commander un kit de débutant contenant une Arduino Mega; persuadé que je serais au minimum capable d’allumer des LED dans mon séjour en fonction de l’état ouvert et fermé.
    Ton projet est exactement ce que je souhaite réaliser au final.
    Alors, je te dis BRAVO !
    Je manque un peu de connaissance pour mettre en place l’interface WEB, mais maintenant grâce à toi je sais que c’est possible…
    Donc merci pour ce tuto. Je suis tombé dessus en faisant des recherches pour les longueur de câble.

    Répondre
  • 28 janvier 2017 à 18 h 45 min
    Permalien

    Bonjour,

    Avez vous le schema electrique complet, car j’ai du mal a visualiser sur les photos.

    Merci par avance, et très beau projet.

    Répondre
  • 8 février 2017 à 22 h 15 min
    Permalien

    Bonjour,

    J’essai de fabriquer un moteur de portail complet, mais je n’ai jamais fait de gros projet comme celui ci.

    Je ne cherche pas a le perfectionner comme le votre.

    voici mon objectif :

    Depuis une impulsion (bouton ou télécommande) je souhaite pouvoir :

    1 Démarrer le moteur –> 2 stopper le moteur –> 3 démarrer le moteur a sens inverse –> Stopper le moteur –> retour au point de départ…

    un capteur de fin de course

    des cellules infrarouge pour détecter qu’aucun véhicule ne soit garé sur le passage du portail.

    Avoir un voyant extérieur qui clignote lorsque le moteur est en action

    Avoir 3 voyants a l’intérieur pour visualisé l’état de fonctionnement (ouverture, fermeture, ou bloquer entre les 2…)

    Lorsque je regarde ton projet c’est presque le même mais en ultra perfectionné.

    Je souhaiterais savoir si vous pouviez m’aider a faire le mien? car je n’arrive pas a faire clignoter par exemple un voyant pendant le fonctionnement sans perturber la détections des impulsions par exemple.

    actuellement j’ai un arduino uno, et un shield L293D pour la gestion du moteur, ou un double relais.

    Si vous pouviez m’aider, je pense que ça doit vous paraître très simple, mais ce n’est malheureusement pas mon cas ^^.

    Merci par avance pour le temps que vous aller peut être me consacrer…

    voici mon programme :

    // — Déclaration des constantes —
    const int APPUI=0; // constante état du BP – appui sur niveau bas
    const int PAS_APPUI=1; // constante état du BP – relâché sur niveau haut

    // — Déclarations des broches —
    const int BP=2; //declaration constante de broche
    const int SENS_AV=4; //declaration constante de broche
    const int SENS_AR=5; //declaration constante de broche
    const int PinBouton = 0; // Bouton poussoir connecte a la broche A0
    const boolean BoutonUp = true;
    const boolean BoutonDown = false;
    boolean EtatBouton = BoutonDown;
    const byte AUCUN_Evenement = 0;
    const byte Evenement_BoutonUp = 1;
    const byte Evenement_BoutonDown = 2;

    // — Déclaration des variables globales —
    int ETAT_BP=0; // variable témoin de l’état du BP
    int compt=0; // variable pour comptage du nombre d’appui

    // — Déclaration des variables booleenes —
    boolean LireBouton()
    {
    boolean resultat = BoutonDown;
    if (analogRead(PinBouton) > 512) {
    resultat = BoutonUp;
    }
    return resultat;
    }

    byte LireEvenement()
    {
    byte Evenement;
    boolean NouvelEtat = LireBouton();
    if (NouvelEtat == EtatBouton)
    Evenement = AUCUN_Evenement;
    if (NouvelEtat == BoutonUp && EtatBouton == BoutonDown)
    Evenement = Evenement_BoutonUp;
    if (NouvelEtat == BoutonDown && EtatBouton == BoutonUp)
    Evenement = Evenement_BoutonDown;
    EtatBouton = NouvelEtat;
    return Evenement;
    }

    boolean etat_led;

    //**************** FONCTION SETUP d’initialisation ****************
    // La fonction ~setup()~ est exécutée en premier et 1 seule fois, au démarrage du programme

    void setup() { // debut de la fonction setup()

    Serial.begin(115200); // initialise connexion série à 115200 bauds
    // IMPORTANT : régler le terminal côté PC avec la même valeur de transmission

    // ——- Définition des broches en sortie ——-

    pinMode(SENS_AV, OUTPUT); //met la broche en sortie
    pinMode(SENS_AR, OUTPUT); //met la broche en sortie

    // ——- Définition des broches en entrée ——-

    pinMode(BP, INPUT); //met la broche en entree

    // ——- Activation du rappel au + interne des broches en entrée si nécessaire ——-

    digitalWrite(BP, HIGH) ; // activation du pullup de la broche en entrée

    // —- Initialisation de broches utilisées en sorties —

    // moteur à l’arrêt au démarrage
    digitalWrite(SENS_AR, HIGH) ;
    digitalWrite(SENS_AV, HIGH) ;

    }

    // fin de la fonction setup()
    // ********************************************************************************

    //*************** FONCTION LOOP *************
    // la fonction loop() s’exécute sans fin en boucle aussi longtemps que l’Arduino est sous tension

    void loop(){

    //—- gestion des appuis sur BP et Fin de Course —

    byte Evenement = LireEvenement();

    if (Evenement == Evenement_BoutonUp){ Serial.println(« BoutonUp ! »);
    digitalWrite(SENS_AR, HIGH) ; // controle sens AR
    digitalWrite(SENS_AV, HIGH) ; // controle sens AV
    compt=0;
    if (Evenement == Evenement_BoutonDown) Serial.println(« BoutonDown ! »);
    }

    if (digitalRead(BP)==APPUI) { // test état du BP
    compt=compt+1; // incrémente la variable compt

    if (compt==4) compt=0; // RAZ variable compt de 4=>0

    if (compt==0){
    // moteur à l’arrêt
    digitalWrite(SENS_AR, HIGH) ; // controle sens AR
    digitalWrite(SENS_AV, HIGH) ; // controle sens AV
    Serial.println(« STP »);
    }

    if (compt==1){
    // moteur en marche avant
    digitalWrite(SENS_AR, HIGH) ; // controle sens AR
    digitalWrite(SENS_AV, LOW) ; // controle sens AV
    Serial.println(« AV »);

    }

    if (compt==2){
    // moteur à l’arrêt
    digitalWrite(SENS_AR, HIGH) ; // controle sens AR
    digitalWrite(SENS_AV, HIGH) ; // controle sens AV
    moteur1.run(BACKWARD);
    moteur1.setSpeed(100);
    Serial.println(« STP »);
    }

    if (compt==3){
    // moteur en marche arrière
    digitalWrite(SENS_AR, LOW) ; // sens AR en marche
    digitalWrite(SENS_AV, HIGH) ; // sens AV à l’arrêt
    moteur1.run(BACKWARD);
    moteur1.setSpeed(100);
    Serial.println(« AR »);
    }

    delay(300); // pause anti-rebond entre 2 appuis

    }
    }

    // — Fin programme —

    Répondre
    • 9 février 2017 à 9 h 40 min
      Permalien

      Bonjour,

      Je n’ai hélas pas beaucoup de temps à vous consacrer. Néanmoins, en ce qui concerne le fait de faire clignoter une LED sans bloquer l’exécution du processus (lecture des input, mise à jour des autres output), il vous faut la faire clignoter de manière asynchrone, donc sans utiliser la fonction « delay ».
      Le site Arduino.cc fournit un excellent exemple dans cet article.

      Bon courage et à bientôt !

      Répondre

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.