1. Introduction

Ma chambre possède deux fenêtres entièrement vitrées donnant plein sud. Ayant refait ma chambre depuis trois ans, elles sont équipées de stores électriques. Les boutons qui les commandent ne sont pas fixés aux murs et pendent lamentablement devant la fenêtre.

Il y a deux boutons par store qui permettent de les monter, de les descendre ou, s'ils sont relâchés, de les arrêter. Un court-circuit est empêché par voie mécanique, c'est-à-dire que les boutons ne peuvent pas être pressés en même temps. Un système de levier relève le bouton A avant que le bouton B soit entièrement pressé. Ainsi le boitier possède une taille non négligeable et empêche l’individu d'observer correctement à travers la fenêtre sans avoir l’œil attiré.

DSC_0514.jpg

Figure 1.1. — Aperçu d'une fenêtre

La programmation de boutons avec un micro-ordinateur est donc une bonne solution pour résoudre le problème. Les boutons peuvent être réduits et donc moins visibles sur les murs. Il faudra empêcher tout court-circuit par programmation. De plus la mise en place de ce système serait une porte ouverte à la commande par application, soit connecté en Wi-Fi soit alors par la mise en place d'un mini-serveur web.

1.1. Le Raspberry Pi

La commande des stores électriques est basée sur un Raspberry Pi, qui est un tout petit ordinateur bon marché. Le système d'exploitation Linux est utilisé car c'est un OS open source gratuit.

RaspberryPi.jpg

Figure 1.2. — Raspberry Pi

1.1.1. Connectique

Le Raspberry possède plusieurs entrées et sorties. Seuls les connecteurs utilisés lors de ce projet y sont décrits.

1.1.1.1.SD

Le port SD est utilisé comme moyen de stockage des fichiers créés par l'utilisateur mais aussi des fichiers du système d'exploitation.

1.1.1.2. USB

Par les ports USB, tout appareil disposant d'un port USB peut être branché. Le Raspberry étant un micro-ordinateur, un clavier doit être branché pour la mise à bien des programmes. J'ai installé une interface graphique de Linux (bien que cela ne soit pas nécessaire) et donc il fallait utiliser une souris pour l'utiliser.

1.1.1.3. HDMI

La sotie principale du Raspberry est le port HDMI (High-Definition Multimedia Interface) qui est le format utilisé pour les lecteurs DVD haute définition. Il existe aussi une sortie DSI (Display Serial Interface) qui est utilisé pour les écrans de smartphone ou de tablette ainsi qu'une sortie vidéo composite que l'on utilise surtout sur du vieux matériel comme par exemple des écrans à tubes cathodiques

1.1.1.4. micro-USB

Cette entré est uniquement utilisée comme alimentation. Il faut s'assurer que du 5V est délivré avec un courant d'AU MOINS 700 mA. Il est conseillé d'utiliser du 1A. Pour de projet j'ai utilisé un connecteur Apple qui délivre du 5V avec un courant de 1000 mA.

1.1.1.5. GPIO

Le port GPIO (General Purpose Input/Output) comporte 26 broches mâle en deux rangées de 13. Il y a des broches déjà dédiées au système qui ne doivent impérativement pas être branchées. Il y en a d'autres qui ont déjà une fonction attitrée. Néanmoins il reste 6 broches complétement libre d'accès. Elles seront donc utilisées pour le projet.

IMG.jpg

Figure 1.3. — Broches du port GPIO numérotées de 1 à 26.

2. Matériel et méthodes

Pour ce projet, il faut bien évidemment du matériel, à savoir, un Raspberry Pi ainsi que le matériel pour l'affichage, un clavier et une souris, un autre ordinateur, des câbles, deux boutons par store, une résistance de 10K Ohm par bouton et une platine à relais, avec les relais (deux relais par store).

2.1. Installation de l'OS

La première manipulation à effectuer est d'installer une version de Linux sur le Raspberry Pi. L'installation est différente selon l'OS de l'ordinateur que vous allez utiliser. Il sera décrit ici que l'installation faire sous Mac OS X. Elle est en effet plus simple que celle sous Windows et à peu près équivalente sous Linux. Pour installer, il faut télécharger la distribution de Linux voulue disponible sur le site www.raspberrypi.org/downloads. (La distribution Raspbian a été utilisée pour ce projet.)

Une fois l'archive téléchargée il faut la décompresser. Deux fichiers apparaissent alors, c'est le fichier "img" qui doit être implanté sur la carte SD. Pour ce faire, il faut:

1. Démarrer l'application Terminal.

2. Connecter une carte SD dans votre Mac, formatez la si ce n'est pas déjà fait.

3. Saisir la commande diskutil list pour afficher la liste des disques connectés: voilà ce qu'on obtient.

iMac:~User$   diskutil list

  /dev/disk0
  #:        TYPE          NAME             SIZE        IDENTIFIER
  0: GUID_partition_scheme*               1.0 TB        disk0
  1:                     EFI             209.7 MB       disk0s1
  2: Apple_HFS       Macintosh HD         999.3 GB      disk0s2
  3: Apple_Boot      Recovery HD          650.0 MB      disk0s3
  /dev/disk2
  #:        TYPE          NAME             SIZE        IDENTIFIER
  0: Apple_partition_scheme *            18.8 MB        disk2
  1: Apple_partition_map                  32.3 KB       disk2s1
  2: Apple_HFS       Flash Player         18.8 MB       disk2s2
  /dev/disk3
  #:        TYPE          NAME             SIZE        IDENTIFIER
  0:  FDisk_partition_scheme *             16.1 GB       disk3
  1:              Windows_FAT_32 SD       16.1 GB        disk3s1

4. Repérer la carte SD selon sa taille de stockage et retenir son chemin d'accès (dans ce cas /dev/disk3). Et utiliser la commande suivante pour démonter le disque. (X doit être remplacé par le numéro du disque)

diskutil unmountdisk /dev/diskX

5. Avec la commande cd, entrer dans le répertoire créé par l'archive et entrer cette commande pour écrire le fichier .img sur la carte SD. (NomDuFichier doit être remplacé par le nom du fichier image)

sudo dd if=NomDuFichier.img of=/dev/sdX bs=2M

6. Attendre la fin de l'écriture, puis retirer la carte de l'ordinateur. Elle peut maintenant être insérée dans le lecteur du Raspberry. Puis brancher l'alimentation micro-USB et l'ordinateur démarre tout seul.

2.2. Mise à jour des logiciels

Si ce projet est réalisé longtemps après sa première conception, il vous faudra mettre à jour les logiciels pour disposer des meilleures versions disponibles. Pour ce faire il faut utiliser l'outil apt dans la console. Il est préférable d'actualiser le cache des logiciels avec la 1ère commande. Pour mettre tous les logiciels à jour, il faut entrer la 2ème commande. Et enfin pour mettre à jour qu'un logiciel spécifique, il faut utiliser la 3ème commande en remplaçant Logiciel par le nom du logiciel à mettre à jour.

sudo apt-get update

sudo apt-get upgrade

sudo apt-get install Logiciel

2.3. Circuit et Programmation

Tout d'abord, pour pouvoir programmer et utiliser le port GPIO, il est préférable de télécharger une librairie python pour gérer le port GPIO. J'ai utilisé la librairie nommée raspberry-gpio-python qui peut être téléchargée sur le site http://sourceforge.net/projects/raspberry-gpio-python/. Il faut l'enregistrer dans le répertoire racine home.

Une fois cela fait, ouvrez le terminal et tapez cette commande pour extraire le téléchargement: Remplacez les x par la version de la librairie téléchargée. Un nouveau répertoire vient d'être créé

tar xvzf RPi.GPIO-x.x.x.tar.gz

Allez dans ce répertoire et tapez cette commande pour installer la librairie.

sudo python setup.py install

A ce moment il est possible de recevoir un message d'erreur du type: fatal error python.h. Dans ce cas, il faut juste taper cette commande puis relancer celle d'installation qui fonctionnera.

sudo apt-get install python-dev

Pour commencer un programme en python il faut créer un fichier en .py que l'on peut modifier avec le logiciel IDLE ou un autre éditeur de texte. Puis pour le lancer, il faut enregistrer le code, aller dans le répertoire où il se trouve et taper cette commande.

sudo python nomDuFichier.py

2.3.2. Boutons

CaptureBoutons.PNG

Figure 2.1. — Schématisation du montage effectué pour faire fonctionner les boutons.

J'ai utilisé une résistance de rappel de 10K Ohm qui va forcer le niveau haut pour que le Raspberry sache clairement quand les boutons sont pressés. Au repos, quand aucun bouton n'est pressé, le Raspberry va capter une tension de 3.3V aux broches 13 et 15. Mais quand un des boutons va être pressé, une tension de 0V va être captée et donc le changement d'état du bouton va être retenu.

En ce qui concerne le code, il faut d'abord importer la librairie utile, c'est à dire celle qu'on a téléchargée précédemment.

import RPi.GPIO as GPIO

On définit d'abord le système de numérotation des broches, soit les numéros connus par le processeur (BCM) soit ceux du connecteur (BOARD). Ensuite on définit les broches 13 et 15 en tant qu'entrée de donnée.

GPIO.setmode(GPIO.BOARD)
GPIO.setup(13, GPIO.IN)
GPIO.setup(15, GPIO.IN)

Maintenant nous allons créer une boucle infinie pour que le Raspberry lise continuellement les données reçues à la broche 12. C'est une boucle de type while. Comme True est tout le temps vraie, la boucle reprend tout le temps.

while True:

On assigne la valeur de la lecture de tension par la broche 13 et par la broche 15 comme suit dans deux variables différentes nommée respectivement valueUp et valueDown.

valueUp = GPIO.input(13)
valueDown = GPIO.input(15)

Pour tester le fonctionnement des boutons, on peut écrire une instruction conditionnelle qui va nous afficher un message quand un des deux boutons est pressé.

if valueUp == False:
   print("le bouton UP est enfoncé")
if valueDown == False:
   print("le bouton DOWN est enfoncé")

On peut à présent remarquer que le message continue d'apparaitre si l'on reste appuyé sur le bouton. Pour éviter ce problème, il suffit d'insérer une boucle imbriquée qui va permettre de répéter la lecture du bouton pressé jusqu'à que celui-ci soit relâché.

if valueUp == False:
   print("le bouton UP est enfoncé")
   while valueUp == False:
      valueUp = GPIO.input(13)

if valueDown == False:
   print("le bouton DOWN est enfoncé")
   while valueDown == False:
      valueDown = GPIO.input(15)

Le code se compose maintenant de ces lignes:

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)
GPIO.setup(13, GPIO.IN)
GPIO.setup(15, GPIO.IN)

while True:

  valueUp = GPIO.input(13)
  valueDown = GPIO.input(15)

  if valueUp == False:
     print("le bouton UP est enfoncé")
     while valueUp == False:
        valueUp = GPIO.input(13)

  if valueDown == False:
     print("le bouton DOWN est enfoncé")
     while valueDown == False:
        valueDown = GPIO.input(15)

Le script python peut être exécuté depuis le terminal.

2.3.1. Relais

CaptureRelais.PNG

Figure 2.2. — Schématisation d'un montage pour faire fonctionner un relais.

Figure 2.3. — Il existe des platines déjà soudées où tous les composants y figurent déjà, notamment celles compatible avec Arduino.

Les broches 16 et 18 du port GPIO sont utilisées comme sorties. Quand un courant va les parcourir, le relais qui fait office d’interrupteur va basculer et ainsi délivrer du 230V au store. Le premier relais donne du courant pour monter le store tandis que le deuxième permet la fermeture.

Pour ce qui est du code à taper en python, il vous faut les conditions des boutons vues plus haut. Quand le bouton pour monter "up" est pressé, le un courant passe par le relais et active la montée des stores. Quand le bouton pour descendre "down" est pressé le store descend. Il faut aussi initialiser les deux broches de sorties de telle façon à ce qu'elles renvoient un état bas.

Mais comme il faut impérativement éviter que les deux relais fonctionnent en même temps. Si tel est le cas un court-circuit avec du 240V est produit. Il faut rajoute que si le bouton "up" est pressé et que le store est en train de descendre, le store s’arrête. Et que si le bouton "down" est pressé et que le store est en train de monter, il s'arrête également. Cela permet aussi de contrôler la hauteur du store pour le régler à la hauteur voulue. Il faut alors ajouter deux nouvelles variables qui vont changer si le store monte ou s'il descend.

On aura donc.

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)
GPIO.setup(13, GPIO.IN)    #bouton monter
GPIO.setup(15, GPIO.IN)    #bouton descendre
GPIO.setup(16, GPIO.OUT)    #relais monter
GPIO.setup(18, GPIO.OUT)    #relais descendre
GPIO.output(16, False)
GPIO.output(18, False)

while True:

  valueUp = GPIO.input(13)        # variables qui change selon l'etat du bouton
  valueDown = GPIO.input(15)

  etatUp = False            # variables qui changent selon l'etat du store
  etatDownm = False

  if valueUp == False:          # si le bouton pour monter le store est presse 
    if etatDown == True:         # si le storte descend
      GPIO.output(18, False)        # alors le store s'arrete
      etatDown = False                      
      while valueUp == False:        #boucle qui permet d'éviter les rebond du bouton
        valueUp = GPIO.input(13)

    elif etat1D == False:           # si le storte ne descend pas
      GPIO.output(16, True)         # alors le store monte
      etatUp = True
      while valueUp == False:
        valueUp = GPIO.input(13)

  elif valueDown == False:          # si le bouton pour descendre le store est presse
    if etatUp == True:            # si le storte monte
      GPIO.output(16, False)         # alors le store s'arrete
      etatUp = False
      while valueDown == False:
        valueDown = GPIO.input(15)

    elif etatUp == False:           # si le storte ne monte pas
      GPIO.output(18, True)         # alors le store descend
      etatDown = True
      while valueDown == False:
        valueDown = GPIO.input(15)

3. Résultats

3.1. Commande de deux stores

Nous avons fini de commander un store. Si vous voulez commander un deuxième store, il vous faut réaffecter la broche 7 qui est normalement la broche d'horloge. Comme les deux stores fonctionnent séparément il ne faut pas que l'un soit dans la condition de l'autre. On affecte dès lors les broches 7 et 11 comme étant les boutons "up" et "down" du premier store, les broches 12 et 13 comme étant les boutons "up" et "down" du 2ème store, les broches 15 et 16 comme étant les relais monter et descendre du 1er store et enfin les broches 18 et 22 comme étant les relais monter descendre du 2ème store.

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)
GPIO.setup(7, GPIO.IN)      #bouton 1 montee
GPIO.setup(11, GPIO.IN)     #bouton 1 descente
GPIO.setup(12, GPIO.IN)     #bouton 2 montee
GPIO.setup(13, GPIO.IN)     #bouton 2 descente

GPIO.setup(15, GPIO.OUT)    #moteur store 1 descente
GPIO.setup(16, GPIO.OUT)    #moteur store 1 montee
GPIO.setup(18, GPIO.OUT)    #moteur store 2 descente
GPIO.setup(22, GPIO.OUT)    #moteur store 2 montee

GPIO.output(15, False)          #regle toutes les sorties à l'etat bas
GPIO.output(16, False)          #les relais sont donc tous au repos
GPIO.output(18, False)
GPIO.output(22, False)

etat1U = False          #variable etat de la montee du premier store
etat1D = False          #variable etat de la descente du premier store
etat2U = False          #variable etat de la montee du deuxieme store
etat2D = False          #variable etat de la descente du deuxieme store

while True:

   store1Up = GPIO.input(7)                    # a chaque boule, une variable est creee et sa valeur
   store1Down = GPIO.input(11)              # indique si un bouton est presse
   store2Up = GPIO.input(12)
   store2Down = GPIO.input(13)

   if store1Up == False:                      # si le bouton pour monter le store 1 est presse 
      if etat1D == True:                     # si le store 1 descend
         GPIO.output(15, False)           # alors le store 1 s'arrete
         etat1D = False                      
         while store1Up == False:            #boucle qui permet d'éviter les rebond du bouton
            store1Up = GPIO.input(7)

      elif etat1D == False:                   # si le store 1 ne descend pas
         GPIO.output(16, True)             # alors le store 1 monte
         etat1U = True
         while store1Up == False:
            store1Up = GPIO.input(7)

   elif store1Down == False:                  # si le bouton pour descendre le store 1 est presse
      if etat1U == True:                        # si le store 1 monte
         GPIO.output(16, False)              # alors le store 1 s'arrete
         etat1U = False
         while store1Down == False:
            store1Down = GPIO.input(11)

      elif etat1U == False:                    # si le store 1 ne monte pas
         GPIO.output(15, True)              # alors le store 1 descend
         etat1D = True
         while store1Down == False:
            store1Down = GPIO.input(11)

   if store2Up == False:                       # si le bouton pour monter le store 2 est presse
      if etat2D == True:                      # si le store 2 descend
         GPIO.output(18, False)             # alors le store s'arrete
         etat2D = False
         while store2Up == False:
            store2Up = GPIO.input(12)

      elif etat2D == False:                   # si le store 2 ne descend pas
         GPIO.output(22, True)             # alors le store 2 monte
         etat2U = True
         while store2Up == False:
            store2Up = GPIO.input(12)

   elif store2Down == False:                   # si le bouton pour descendre le store 2 est presse
      if etat2U == True:                        # si le store 2 monte
         GPIO.output(22, False)              # alors le store 2 s'arrete
         etat2U = False
         while store2Down == False:
            store2Down = GPIO.input(13)

      elif etat2U == False:                    # si le store 2 ne monte pas
         GPIO.output(18, True)              # alors le store 2 descend
         etat2D = True
         while store2Down == False:
            store2Down = GPIO.input(13)

Nous avons donc maintenant un code fonctionnel. Il reste une dernière étape. Faire en sorte que le programme s'exécute au démarrage du Raspberry et ne pas à avoir à brancher clavier, souris et écran pour le faire. Pour la version graphique il faut afficher les fichiers cachés en faisant Ctrl + H, puis ouvrir le fichier intitulé .bashrc, le faire défiler jusque tout en bas et rajouter à la dernière ligne la même ligne de commande que pour lancer le programme.

sudo python nomDuFichier.py

Et voilà tout est fini, il ne reste plus qu'à mettre en place.

DSC_0513.jpg

Figure 3.1. — Boutons contre le mur

4. Discussion

Le résultat obtenu est correspond exactement au but recherché, il rentre dans un budget de moins de 150CHF tout frais compris. Les finitions sont propres, le script python fonctionnel. Aucun bug ne survient, et si tel était le cas, il suffit de débrancher et rebrancher le Raspberry Pi pour le redémarrer et ainsi exécuter à nouveau le script.

La difficulté première est d'apprendre le langage python, si l'on est déjà familiarisé avec un autre langage, ce n'est pas très compliqué. La seconde difficulté est apparue pour faire fonctionner les deux stores en même temps, de définir un bon nombre de variable, de s'y retrouver dans son code. C'est pourquoi je conseille de bien commenter son script (ou n'importe quel code de plus de 30 lignes) pour une lecture plus facile et une compréhension à postériori.

Je conseille vivement d'effectuer des premiers tests avec des LEDs plutôt qu'avec le 230V pour repérer un éventuel pépin et éviter tout risque. Les circuits de LEDs sont par la suite remplacés par les relais et rien n'a besoin d'être changé.

Une amélioration du code avec des timers serait possible pour indiquer que si un bouton est pressé plus de 0.5 seconde, le store s'arrête au moment où le bouton est relâché. Cela deviendrait plus pratique pour commander des petits trajets de stores, comme par exemple l'inclinaison des lamelles. Ou aussi pour commander l'ouverture des stores tous les jours à 9 heures et leur fermeture à 22 heures. On pourrait rêver de stores complétement automatisés.

5. Conclusion

Voilà les stores fonctionnels! Amusez-vous bien avec ce nouveau gadget!

La suite de ce billet sera consacrée, à la programmation d’une application Android visant à piloter les stores depuis un smartphone depuis n'importe quelle pièce de la maison. L'information du bouton sera transmise par onde Wi-Fi au Raspberry, qui pourra alors traduire ce signal pour monter ou descend un store.

6. Références

Figure 1.2. — WIKIPEDIA, http://upload.wikimedia.org/wikipedia/commons/3/3d/RaspberryPi.jpg

Figure 1.3. — Eben UPTON et Gareth HALFACREE, Raspberry Pi: Le guide de l'utilisateur, Pearson France, 2013

Figure 2.3. — http://goto-0x00.de/wp-content/uploads/2013/03/2-Kanal-5V-Relay-Relais-Module.png