Introduction

Dans cet article on va contrôler une prise électrique pilotable par radio-fréquence (RF) à l’aide d’une Raspberry Pi. Une lampe sera reliée à cette prise électrique et pourra ainsi être allumée ou éteinte grace à la Raspberry. N’étant moi même pas expert dans le domaine de l’électronique, cet article s’adresse plutôt à des personnes ayant quelques notions d’électronique, mais sans plus.

Comme vous vous en doutez, quelques prérequis sont nécessaires :

Ce tutoriel se veut un peu généraliste, donc si vous n’avez pas exactement le même matériel, pas de panique ! Vous aurez à adapter un peu mais tout devrait fonctionner à l’identique (ou presque).

 

Contrôler la prise électrique

Commencez par rechercher avec votre moteur de recherche favoris la “carte” des GPIOs de votre Raspberry, voici celle de la RPi3 :

Intercepter la commande RF

Afin d’être en mesure de contrôler notre prise électrique, il serait pas mal de savoir à quoi ressemble le signal à émettre ! Pour cela on va utiliser un récepteur RF, appuyer sur le bouton de la télécommande fournie avec la prise électrique, et voir ce qui passe.

Voici le récepteur en question :

Pour une raison qui m’échappe, il y a deux pin de data, nous n’utiliserons dans cet article que la première (celle de gauche sur la photo, lorsque la récepteur est de face).

  • Reliez la 1ère pin au 5V de votre Raspberry (Pin#2 pour la RPi3)
  • Reliez la 4ème pin au GND de votre Raspberry (Pin#6 pour la RPi3)
  • Reliez la 2ème pin à une des GPIO (nous choisirons la Pin#13 pour la RPi3)

Rien d’illogique jusqu’à présent 😛

Allumez votre Rasberry, ouvrez un terminal et installez wiringPi ainsi que le paquet build-essential qui nous permettra de compiler :

sudo apt install wiringpi build-essential

 

Nous allons maintenant télécharger et installer un utilitaire nommé RFSniffer qui va nous permettre de récupérer la trame envoyée par notre télécommande.

Commencez par cloner le repo github :

git clone --recursive git://github.com/ninjablocks/433Utils.git

Allez ensuite dans le répertoire qui nous intéresse :

cd 433Utils/RPi_utils

Si vous utilisez une autre PIN que la 13 pour votre récepteur, vous devez modifier le code source RFSniffer.cpp afin de modifier la valeur de PIN (première ligne dans le main). Il faut en revanche être vigilant car les numéros des PINs fournis plus haut ne sont pas les mêmes que ceux de WiringPi. Pour avez la correspondance des 2 sur ce site dans le 1er tableau. Comme vous pouvez le voir, la PIN 13 correspond à la PIN 2 de WiringPi. C’est d’ailleurs cette valeur (2) qui est utilisée par défaut dans le programme RFSniffer, c’est pour cela que j’ai utilisé la PIN 13, pour ne pas avoir à modifier le code source.

Nous allons faire une légère modification du code de RFSniffer.cpp afin d’avoir plus d’informations que celles affichées de base.

Repérez la ligne de code suivante  :

printf("Received %i\n", mySwitch.getReceivedValue() );

Et juste en dessous, rajoutez ces deux lignes :

printf("Pulse %i\n", mySwitch.getReceivedDelay() );
printf("Protocol %i\n\n", mySwitch.getReceivedProtocol() );

Compilez maintenant les programmes à l’aide de la commande suivante :

make

Lancez maintenant le programme RFSniffer :

./RFSniffer

Et appuyez sur les boutons de votre télécommande. A chaque appui, si la télécommande est suffisamment proche et que tout est bien configuré, vous devriez voir les valeurs reçues défiler comme ceci :

Notez bien les valeurs et à quel bouton elles correspondent ! Dans mon cas, je n’ai utilisé que 2 des 6 boutons de la télécommande, j’ai noté les valeurs suivantes :

Bouton ON  = 4478259

Bouton OFF = 4478268

Pulse = 175  (Il se peut que cette valeur varie très légèrement, mais cela ne semble pas affecter le bon fonctionnement de la communication)

Protocole = 1

Nous n’avons maintenant plus besoin de notre récepteur, direction la poubelle 😀 Enfin… Gardez le au cas où…

Émettre la commande RF

Nous allons maintenant utiliser l’émetteur afin que notre RPi soit en mesure d’envoyer les mêmes trames interceptées précédemment. Nous allons réaliser cela à l’aide du programme codesend, issue du même repo github. Celui-ci devrait déjà être compilé et prêt à l’emploi grace au make fait juste avant. Nous allons en revanche faire en sorte que ce programme soit accessible partout sur notre machine afin que ce soit plus pratique pour nos futurs tests. Exécutez donc la commande suivante :

sudo cp codesend /usr/bin/

Voici à quoi ressemble l’émetteur que j’utilise :

Le programme codesend utilise la PIN 0 de WiringPi, ce qui correspond à la broche #11. Branchez donc la broche data de l’émetteur sur la PIN #11 (voir schéma au dessus).

Nous allons maintenant utiliser le programme codesend afin d’envoyer l’instruction d’allumage (notée précédemment) à la prise électrique. Le programme codesend s’utilise comme suit :

codesend [valeur] [protocole] [pulse]

Dans mon cas, j’effectue donc un :

codesend 4478259 1 175

Et pouf ! La prise s’allume 🙂

On test maintenant de l’éteindre :

codesend 4478268 1 175

Et elle s’éteint correctement !

Nous sommes maintenant en mesure de contrôler la prise électrique à l’aide de notre RPi, nous allons maintenant faire en sorte d’utiliser la voix.

Contrôle vocal

Afin de contrôler vocalement la Raspberry Pi, nous allons utiliser un formidable outil appelé SnowBoy. Il s’agit d’un outil de détection de mots utilisant un réseau neuronale très performant. Le gros avantage de SnowBoy, c’est que le réseau neuronale peut-être entraîné par la communauté afin d’être de plus en plus performant et de s’adapter à n’importe quelle voix. Un second avantage est que celui-ci est entièrement déconnecté ! Cela garantie donc un certain respect de la vie privée, contrairement aux Google Home et Echo de Amazon qui communiquent en permanence avec leurs serveurs et peuvent donc être utilisés à des fins “malicieuses”…

Si vous comprenez l’anglais, voici une petite vidéo explicative de SnowBoy :

Branchez maintenant votre micro sur la Raspberry ! Je vous recommande de créer un dossier “VoiceControl” quelque part sur votre RPi afin d’organiser un minimum les fichiers 🙂

Il se peut que vous ayez à redémarrer votre RPi si le micro n’est pas détecté. Il est recommandé de brancher des enceintes à la RPi afin d’avoir une sorte d’interaction entre nous et la machine.

Téléchargement des modèles

Dans le cadre de cet article, nous allons devoir reconnaître 2 phrases :

“Allume la lumière” : https://snowboy.kitt.ai/hotword/736

“Éteins la lumière” : https://snowboy.kitt.ai/hotword/8756

Vous avez tout intérêt à reprendre les mêmes fichiers que moi car ils sont déjà un peu entraînés. N’oubliez pas que plus la communauté va entraîner le réseau neuronale, plus celui-ci sera performant. Mettez les 2 fichiers téléchargés dans votre dossier “VoiceControl”.

Installation de la librairie

On va maintenant s’attarder sur l’installation de la librairie que SnowBoy nous fournit (vous avez un guide complet sur la doc officielle si vous comprenez l’anglais : http://docs.kitt.ai/snowboy/#quick-start). Sinon suivez le guide 😉

Installez quelques dépendances :

sudo apt-get install python-pip python3-pip python-pyaudio python3-pyaudio sox

Afin de faire reconnaître pyaudio à python, utilisez la commande suivante si vous utilisez python 2.7 :

sudo pip install pyaudio

Et comme ca si vous utilisez python 3 :

sudo pip3 install pyaudio

Les deux version de python devraient être installées par défaut sur Raspbian, vous avez donc juste à choisir quelle version de python vous préférez utiliser.

Rendez-vous sur ce lien afin de télécharger la librairie de SnowBoy. Prenez la version pour les Rasp et mettez le dans votre dossier “VoiceControl”.

Extrayez l’archive téléchargée :

tar jxf rpi-arm-raspbian-8.0-1.1.1.tar.bz2

Puis essayez de lancer la démo afin de vérifier que votre micro et l’installation des dépendances fonctionnent bien :

python demo.py resources/snowboy.umdl

Si lorsque vous dites “SnowBoy” dans votre micro, une ligne de detection s’écrit dans le terminal, c’est que tout est correctement configuré ! Sinon quelque chose cloche dans votre installation… Assurez-vous que les librairies sont bien installées, et que le micro est bien configuré.

 

Fin

Vous êtes désormais en possession d’un programme vous permettant d’allumer ou d’éteindre votre prise électrique et d’un programme de détection de votre voix. Il ne reste plus qu’à combiner les deux pour contrôler la lampe reliée à la prise.

Je vous propose un script simple vous permettant d’allier les deux. Bien qu’il ne soit pas très compliqué, je l’ai commenté au maximum pour que vous puissiez comprendre :

#!/usr/bin/python
# -*- coding: utf-8 -*-
import snowboydecoder
import sys
import signal
import os

interrupted = False   # Variable permettant de gérer l'extinction du programme proprement (multithreading)
model_dir = "models/" # Chemin relatif vers le dossier qui contient tous les modèles

# Capture le CTRL+C dans le terminal afin de stopper le programme proprement (multithreading)
def signal_handler(signal, frame):
    print("Au revoir !")
    global interrupted
    interrupted = True


# Permet de gérer l'extinction du programme proprement (multithreading)
def interrupt_callback():
    global interrupted
    return interrupted


#Bonus pour faire dire quelque chose à votre Raspberry (sudo apt install pico2wave)
#def say(msg):
#    os.system("pico2wave -l fr-FR -w /tmp/out.wav \"" + msg + "\"")
#    os.system("aplay /tmp/out.wav && rm /tmp/out.wav")


#Fonction permettant d'allumer la prise électrique grace au programme codesend
def turn_on_light():
    global triggered
    if triggered:
        os.system("codesend 4478259 1 175") # Code de la télécommande retenu plus tot.
        #say("Et voila")


#Fonction permettant d'éteindre la prise électrique grace au programme codesend
def turn_off_light():
    global triggered
    if triggered:
        os.system("codesend 4478268 1 175") # Code de la télécommande retenu plus tot.
        #say("Bonne nuit!")


# Capture Ctrl+C
signal.signal(signal.SIGINT, signal_handler)
print('Listening... Press Ctrl+C to exit')


# Fichiers téléchargés sur le site permettant la reconnaissance vocale d'un mot ou expression
detect_files = [model_dir + "AllumeLaLumiere.pmdl",
                model_dir + "EteinsLaLumiere.pmdl"]


# Fonctions correspondantes appelées. Doit être dans le même ordre que le tableau "detect_files".
callbacks = [turn_on_light,
             turn_off_light]

# SnowBoy
detector = snowboydecoder.HotwordDetector(detect_files, sensitivity=[0.5]*len(detect_files))
detector.start(detected_callback=callbacks,
               interrupt_check=interrupt_callback,
               sleep_time=0.03)


detector.terminate()

 

Si vous avez des questions concernant ce script, ou des questions plus générales, des critiques, ou des suggestions à faire concernant cet article : laissez donc un commentaire 😉