Allumer des prises électriques Chacon 54795 à distance avec un raspberry pi 2

Courte procédure permettant l’allumage ou l’arrêt de prise électrique CHACON 54795 à l’aide d’un RaspBerry Pi 2 et d’un émetteur 433Mhz. Le projet finale vous permettra via une commande bash sur le raspberry d’allumer ou éteindre une prise électrique via l’émetteur radio 433Mhz.

Pour débuter il vous faudra posséder la liste de matériel suivante :

Les prises éléctrique Chacon DIO fonctionnent avec le principe suivant :

– Lors de l’allumage, durant 5 secondes la led rouge clignote cela indique qu’elle est en phase d’écoute pour recevoir une requête d’association, si elle ne reçoit rien elle conserve la précédente
– L’objectif sera donc d’envoyer une requête durant ces 5 secondes avec le Raspberry afin qu’elle réponde par la suite

Je pars du principe que vous avez une installation fonctionnelle de Raspbian Stretch. Pour la procédure j’étais en version de kernel 4.9.41-v7+. L’ensemble de la procédure s’effectuera via ssh, un accès WEB est indispensable.

Depuis RASPBIAN PIXEL après l’installation de l’ISO sur votre carte SD SSH est désactivé par défaut.
Pour activer SSH montez la carte SD, la partition « /boot » doit être accessible en écriture. Puis il vous faut créer un fichier vide nomé « ssh » à la racine. Lors du démarrage Raspbian va détecter le fichier et activer le SSH-server avec comme identifiants par défaut : pi/raspberry

Câblage émetteur radio et connectiques

Câblage Récépteur radio et connectique (Inutile dans ce billet, posté pour information)

Connection et authentification SSH vers le raspberry

ssh pi@192.168.1.10

Mises à jours

sudo apt-get update && sudo apt-get upgrade

Installation des outils de bases, gcc ; g++ et make sont des compilateurs, git permet d’importer un dépôt depuis github.com

sudo apt-get install gcc g++ make git

Clone de WiringPi depuis le dépôt, wiringPi (doc) est une bibliothèque d’accès GPIO basée sur un code écrit en C

git clone git://git.drogon.net/wiringPi

Déplacement dans le dossier du projet et build

cd wiringPi && ./build

On teste la bonne reconnaissance, cela lit toutes les broches normalement accessibles et imprime un tableau de leurs numéros

gpio readall

Créer un dossier destiné à recevoir le code à compiler, puis ajoutez-y le fichier « chacon_send.cpp »
Téléchargez le Code C du programme de idleman d’envoi de commandes depuis l’émetteur radio branché sur la pin 11 du Raspberry.(Voir schéma ci-dessus)
OU
Création du fichier via nano puis copiez collez le code ci-dessous.

sudo nano chacon_send.cpp

Code à copier/coller

#include <wiringPi.h>
#include <iostream>
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <stdlib.h>
#include <sched.h>
#include <sstream>
#include <unistd.h>
/*
Par Idleman (idleman@idleman.fr - http://blog.idleman.fr)
Licence : CC by sa
Toutes question sur le blog ou par mail, possibilité de m'envoyer des bières via le blog
*/

using namespace std;


int pin;
bool bit2[26]={};              // 26 bit Identifiant emetteur
bool bit2Interruptor[4]={};
int interruptor;
int sender;
string onoff;

void log(string a){
    //Décommenter pour avoir les logs

    //cout << a << endl;
}




void scheduler_realtime() {

struct sched_param p;
p.__sched_priority = sched_get_priority_max(SCHED_RR);
if( sched_setscheduler( 0, SCHED_RR, &p ) == -1 ) {
perror("Failed to switch to realtime scheduler.");
}
}

void scheduler_standard() {

struct sched_param p;
p.__sched_priority = 0;
if( sched_setscheduler( 0, SCHED_OTHER, &p ) == -1 ) {
perror("Failed to switch to normal scheduler.");
}
}



//Envois d'une pulsation (passage de l'etat haut a l'etat bas)
//1 = 310µs haut puis 1340µs bas
//0 = 310µs haut puis 310µs bas
void sendBit(bool b) {
 if (b) {
   digitalWrite(pin, HIGH);
   delayMicroseconds(310);   //275 orinally, but tweaked.
   digitalWrite(pin, LOW);
   delayMicroseconds(1340);  //1225 orinally, but tweaked.
 }
 else {
   digitalWrite(pin, HIGH);
   delayMicroseconds(310);   //275 orinally, but tweaked.
   digitalWrite(pin, LOW);
   delayMicroseconds(310);   //275 orinally, but tweaked.
 }
}

//Calcul le nombre 2^chiffre indiqué, fonction utilisé par itob pour la conversion decimal/binaire
unsigned long power2(int power){
unsigned long integer=1;
for (int i=0; i<power; i++){
  integer*=2;
}
return integer;
}

//Convertis un nombre en binaire, nécessite le nombre, et le nombre de bits souhaité en sortie (ici 26)
// Stocke le résultat dans le tableau global "bit2"
void itob(unsigned long integer, int length)
{
    for (int i=0; i<length; i++){
      if ((integer / power2(length-1-i))==1){
        integer-=power2(length-1-i);
        bit2[i]=1;
      }
      else bit2[i]=0;
    }
}

void itobInterruptor(unsigned long integer, int length)
{
    for (int i=0; i<length; i++){
      if ((integer / power2(length-1-i))==1){
        integer-=power2(length-1-i);
        bit2Interruptor[i]=1;
      }
      else bit2Interruptor[i]=0;
    }
}




//Envoie d'une paire de pulsation radio qui definissent 1 bit réel : 0 =01 et 1 =10
//c'est le codage de manchester qui necessite ce petit bouzin, ceci permet entre autres de dissocier les données des parasites
void sendPair(bool b) {
 if(b)
 {
   sendBit(true);
   sendBit(false);
 }
 else
 {
   sendBit(false);
   sendBit(true);
 }
}


//Fonction d'envois du signal
//recoit en parametre un booleen définissant l'arret ou la marche du matos (true = on, false = off)
void transmit(int blnOn)
{
 int i;

 // Sequence de verrou anoncant le départ du signal au recepeteur
 digitalWrite(pin, HIGH);
 delayMicroseconds(275);     // un bit de bruit avant de commencer pour remettre les delais du recepteur a 0
 digitalWrite(pin, LOW);
 delayMicroseconds(9900);     // premier verrou de 9900µs
 digitalWrite(pin, HIGH);   // high again
 delayMicroseconds(275);      // attente de 275µs entre les deux verrous
 digitalWrite(pin, LOW);    // second verrou de 2675µs
 delayMicroseconds(2675);
 digitalWrite(pin, HIGH);  // On reviens en état haut pour bien couper les verrous des données

 // Envoie du code emetteur (272946 = 1000010101000110010  en binaire)
 for(i=0; i<26;i++)
 {
   sendPair(bit2[i]);
 }

 // Envoie du bit définissant si c'est une commande de groupe ou non (26em bit)
 sendPair(false);

 // Envoie du bit définissant si c'est allumé ou eteint 27em bit)
 sendPair(blnOn);

 // Envoie des 4 derniers bits, qui représentent le code interrupteur, ici 0 (encode sur 4 bit donc 0000)
 // nb: sur  les télécommandes officielle chacon, les interrupteurs sont logiquement nommés de 0 à x
 // interrupteur 1 = 0 (donc 0000) , interrupteur 2 = 1 (1000) , interrupteur 3 = 2 (0100) etc...
  for(i=0; i<4;i++)
 {
 if(bit2Interruptor[i]==0){
    sendPair(false);
 }else{
    sendPair(true);
 }
}
 
 digitalWrite(pin, HIGH);   // coupure données, verrou
 delayMicroseconds(275);      // attendre 275µs
 digitalWrite(pin, LOW);    // verrou 2 de 2675µs pour signaler la fermeture du signal

}




int main (int argc, char** argv)
{

    if (setuid(0))
    {

        perror("setuid");
        return 1;

    }


    scheduler_realtime();

    log("Demarrage du programme");
    pin = atoi(argv[1]);
    sender = atoi(argv[2]);
    interruptor = atoi(argv[3]);
    onoff = argv[4];
    //Si on ne trouve pas la librairie wiringPI, on arrête l'execution
    if(wiringPiSetup() == -1)
    {
        log("Librairie Wiring PI introuvable, veuillez lier cette librairie...");
        return -1;

    }
    pinMode(pin, OUTPUT);
    log("Pin GPIO configure en sortie");

    itob(sender,26);            // convertion du code de l'emetteur (ici 8217034) en code binaire
    itobInterruptor(interruptor,4);
   
   
    if(onoff=="on"){
     log("envois du signal ON");
     for(int i=0;i<5;i++){
         transmit(true);            // envoyer ON
         delay(10);                 // attendre 10 ms (sinon le socket nous ignore)
     }

    } else{
     log("envois du signal OFF");
     for(int i=0;i<5;i++){
         transmit(false);           // envoyer OFF
         delay(10);                // attendre 10 ms (sinon le socket nous ignore)
     }
    }

     log("fin du programme");    // execution terminée.


    scheduler_standard();
}

On lance la compilation

sudo g++ -o chacon_send chacon_send.cpp -lwiringPi

Le code compilé fournit un binaire « chacon_send », utilisez les syntaxes ci-dessous pour vous associer aux prises et les manager

chacon_send <wiringPI pin> <controler_code> <outlet_code> <on|off>
#Prise 1
./chacon_send 0 12325261 1 on
#Prise 2
./chacon_send 0 12325262 2 on
#Prise 3
./chacon_send 0 12325263 3 on
  • wiringPi pin : numéro wiringPi sur lequel on a branché la broche « DATA » de l’émetteur radio 433mhz. Il est sur le pin physique 11 qui correspond sur wiringPi au pin 0.
  • controler_code : numéro identification de l’émetteur d’une longueur de 26 bits. Arbitraire, il doit juste respecter la syntaxe des 26 bits
  • outlet_code : ID de la prise. Elle prendra ce code comme identifiant et le gardera jusqu’à qu’une nouvelle association l’écrase
  • on|off : ON ou OFF pour allumer ou éteindre la prise éléctrique

Je partage les sources qui m’ont beaucoup aidé dans la réalisation de cela, avec l’article de idleman à l’origine de la manipulation notamment sur le code à compiler ainsi que l’article de arno0x0x qui m’a permis de compléter ma recherche avec sa version modifiée.

Une réflexion sur « Allumer des prises électriques Chacon 54795 à distance avec un raspberry pi 2 »

Laisser un commentaire