Raspberry Pi : un interrupteur passe-partout

23/11/2015

J’ai récemment emménagé dans mon kot (chambre d’étudiant) à Louvain-la-Neuve. Je suis habitué à vivre avec ma domotique, et c’est pourquoi j’ai monté presque l’entièreté de ma précédente installation. J’entends par là la gestion par le Raspberry Pi des différentes lampes ainsi que les rideaux. L’interface Web est déjà activée, et à ce stade il ne reste plus que l’automatisation générale de ma chambre.

Je ne suis que locataire de cette chambre, je ne pouvais donc pas me permettre de démonter l’interrupteur général (celui fiché dans le mur) pour le remplacer par un relais, chose que j’ai faite chez moi. J’ai donc dû réfléchir à une alternative, et cet article présente la solution trouvée.

Le principe en quelques mots : le Raspberry communique par port série avec un Arduino Nano. Sur cet Arduino est connecté un servomoteur capable d’appuyer physiquement sur l’interrupteur encastré. On rajoutera un bouton poussoir pour garder un interrupteur physique à côté.

Note : l’utilisation d’une Nano est un choix délibéré. En effet, un circuit basé sur un NE555 aurait largement pu réaliser cette tâche pour un coût moindre. Mais il aurait été plus difficile à mettre en place. On trouve facilement en Asie une Nano pour 2,5 euros.
Le servo et le bouton-poussoir monté sur l’Arduino
Le servo et le bouton-poussoir monté sur l’Arduino.
Le circuit est relativement simple, et son passage sur PCB est très facile. Il s’agit d’une résistance de 2,2 kΩ et d’un servo 9 g.
Passage du circuit sur PCB (recto)
Passage du circuit sur PCB (recto).
Passage du circuit sur PCB (verso)
Passage du circuit sur PCB (verso).
On s’attaque ensuite au code de l’Arduino. La communication entre les 2 plates-formes se fera donc en série à 9 600 bauds. Le Nano enverra chaque seconde l’état de l’interrupteur en binaire. Le Pi sera capable d’envoyer, également en binaire, l’état dans lequel il souhaite que soit l’interrupteur . Les conditions de déclenchement du moteur sont simples : le nouvel état envoyé doit être différent du précédent ou le bouton poussoir est activé.

Le servomoteur fait une bruit désagréable en forçant sur l’interrupteur (le système est loin d’être parfait) ; on utilisera alors judicieusement la commande detach() afin de désactiver son alimentation. De ce fait, il ne cherche plus à corriger sa position et ne fait plus de bruit. Solution efficace contre les insomnies.

Vous trouverez l’entièreté du code sur cette page.

Concernant la partie Raspberry, elle a nécessité un peu de réflexion. Je vous fais part de mes idées :

La communication en série doit être maintenue en permanence pour assurer une bonne communication entre les 2 plates-formes. Si cette connexion est interrompue, le Nano redémarre immédiatement. Une seule communication est possible. Je veux dire par là qu’il n’est pas possible de communiquer avec le Nano dans 2 scripts en parallèle.

Mon interface Web nécessite de connaître l’état de l’interrupteur (0 ou 1), mais d’autres scripts en ont aussi besoin pour x ou y raisons. Un script tourne donc dans un screen Linux en permanence et reçoit continuellement l’état envoyé par l’Arduino. Si celui-ci est différent de l’état précédent, le script stocke le nouvel état dans un fichier. Quand un de mes scripts nécessite de connaître l’état de l’interrupteur (par exemple l’interface Web), il lui suffit d’aller lire le contenu du fichier. Je n’ai rien trouvé de mieux comme solution. Je doute que celle-ci soit efficace, mais elle fonctionne.

Le contenu du script de lecture est le suivant :

import serial
ser = serial.Serial(‘/dev/ttyUSB0’, 9600)
state = 0
while 1:
        l = ser.readline()
        print(l)
        if(str(state) != str(l)):
                file = open(‘state.txt’, ‘w’)
                file.write(l)
                file.close()

Le fichier state.txt contient donc uniquement 0 ou 1 selon l’état de l’interrupteur.

Pour allumer ou éteindre l’interrupteur, on envoie juste en série 0 ou 1. Comme la communication est maintenue par le script de lecture, l’envoi se fait sans souci.

import serial
ser = serial.Serial(‘/dev/ttyUSB0’, 9600)
ser.write(‘1’) 							# ‘1’ pour allumer, ‘0’ pour eteindre

L’exécution du script pousse l’Arduino à passer dans l’état souhaité.

Vous vous demandez certainement comment on détermine "ttyUSB0" ; il suffit de lancer la commande
ls /dev/tty*
sur le Pi. Connectez ensuite l’Arduino en USB et relancez la commande. Notez la ligne qui apparaît dans le terminal.

Logiquement tout est fonctionnel, et vous pourrez voir le moteur s’activer dans un sens ou dans l’autre.

Concernant la partie physique, elle est de l’ordre de la bidouille ; je vous présente la mienne :
Partie physique du montage
Partie physique du montage.
Il s’agit d’un boîtier en carton sur lequel est directement collé le servo. Une tête maison est montée sur le servo pour mieux s’adapter à la taille de l’interrupteur. Le tout est maintenu par de la patafix afin de pouvoir être démonté facilement. Le nouvel interrupteur de ma chambre n’est autre que le tout petit bouton poussoir au-dessus du Nano !

Ce système est totalement fonctionnel et j’en suis très satisfait. Je vais certainement optimiser le code et les scripts ; je pense qu’il y a moyen de faire beaucoup mieux.
Petite mise à jour avec un caisson en balsa et en acier et surtout un interrupteur plus voyant
Petite mise à jour avec un caisson en balsa et en acier et surtout un interrupteur plus voyant .
Blog | Haut