Contrôler ses volets Somfy avec un Arduino 0

Do It Yourself
Partager :

I. Objectif


Ce projet a pour objectif de pouvoir contrôler des volets roulants Somfy (et uniquement Somfy utilisant le protocole RTS) via votre PC. Cet article sera complété par un second qui détaillera comment contrôler les volets à la voix via Google Assistant ou depuis une page web.
L'étape la plus technique consiste à désouder un composant sur le transmetteur pour y souder un autre. Le reste des opérations est trivial.

 

II. Matériel requis

 

 

III. Procédure

III. 1. Déploiement du code sur l'Arduino


Tout d'abord, copiez le code ci-dessous dans un éditeur de texte :
 
#include <EEPROM.h>
#define PORT_TX 5

#define SYMBOL 640
#define HAUT 0x2
#define STOP 0x1
#define BAS 0x4
#define PROG 0x8
#define EEPROM_ADDRESS 0

#define VERSION 1

byte frame[7];
byte checksum;

struct Remote
{
  unsigned long remoteID;
  unsigned int rollingCode;
};

struct SomfyController
{
  int appVersion;
  Remote remotes[4];
};

SomfyController somfyControllers;
Remote newRemotes [4] = {
  {0x123456, 0},
  {0x123457, 0},
  {0x123458, 0},
  {0x123459, 0}
};

void BuildFrame(unsigned long remoteID, unsigned int rollingCode, byte *frame, byte button);
void SendCommand(byte *frame, byte sync);


void setup()
{
  Serial.begin(115200);
  DDRD |= 1<<PORT_TX;
  PORTD &= !(1<<PORT_TX);

  EEPROM.get(EEPROM_ADDRESS, somfyControllers);

  if (somfyControllers.appVersion < VERSION)
  {
    Serial.println("La version de l'application en mémoire n'est pas dans la bonne version ou la mémoire est vide");
    somfyControllers.appVersion = VERSION;
    memcpy(&somfyControllers.remotes, &newRemotes, sizeof(newRemotes));
    
    EEPROM.put(EEPROM_ADDRESS, somfyControllers);
  }

  for (int i = 0; i < (sizeof(somfyControllers.remotes) / sizeof(Remote)); i++)
  {
    Remote currentRemote = somfyControllers.remotes[i];
    Serial.print("Commande ["); Serial.print(i); Serial.println("]");
    Serial.print("\tID de la commande : "); Serial.println(currentRemote.remoteID, HEX);
    Serial.print("\tCompteur actuel : "); Serial.println(currentRemote.rollingCode);
  }
}

void loop()
{
  if (Serial.available())
  {
    String data = "";
    
    while (Serial.available())
    {
      char c = Serial.read();
      data += String(c);
      delay(10);
    }

    char serie = data[0];

    for (int i = 1; i < data.length(); i++)
    {
      char cRemotePosition = data[i];
      
      int remotePosition = cRemotePosition - '0';
      Serial.print("Commande "); Serial.println(remotePosition);

      Remote remote = somfyControllers.remotes[remotePosition];
      unsigned long remoteID = remote.remoteID;
      unsigned int rollingCode = remote.rollingCode;
      
      Serial.println("");
      if (serie == 'm')
      {
        Serial.println("Monte");
        BuildFrame(remoteID, rollingCode, frame, HAUT);
      }
      else if (serie == 's')
      {
        Serial.println("Stop");
        BuildFrame(remoteID, rollingCode, frame, STOP);
      }
      else if (serie == 'd')
      {
        Serial.println("Descend");
        BuildFrame(remoteID, rollingCode, frame, BAS);
      }
      else if (serie == 'p')
      {
        Serial.println("Prog");
        BuildFrame(remoteID, rollingCode, frame, PROG);
      }
      else
      {
        Serial.println("Code custom");
        BuildFrame(remoteID, rollingCode, frame, serie);
      }
  
      Serial.println("");
      SendCommand(frame, 2);
      for (int i = 0; i < 2; i++)
      {
        SendCommand(frame, 7);
      }
  
      //Incrémente le compteur et le sauvegarde en mémoire
      somfyControllers.remotes[remotePosition].rollingCode++;
      EEPROM.put(EEPROM_ADDRESS, somfyControllers);
    }
  }
}


void BuildFrame(unsigned long remoteID, unsigned int rollingCode, byte *frame, byte button)
{
  frame[0] = 0xA7;
  frame[1] = button << 4;
  frame[2] = rollingCode >> 8;
  frame[3] = rollingCode;
  frame[4] = remoteID >> 16;
  frame[5] = remoteID >>  8;
  frame[6] = remoteID;

  Serial.print("Frame         : ");
  for (byte i = 0; i < 7; i++)
  {
    if (frame[i] >> 4 == 0)
    {
      Serial.print("0");
    }
    Serial.print(frame[i], HEX); Serial.print(" ");
  }

  checksum = 0;
  for (byte i = 0; i < 7; i++)
  {
    checksum = checksum ^ frame[i] ^ (frame[i] >> 4);
  }
  checksum &= 0b1111;

  frame[1] |= checksum;


  Serial.println(""); Serial.print("Avec checksum : ");
  for (byte i = 0; i < 7; i++)
  {
    if (frame[i] >> 4 == 0)
    {
      Serial.print("0");
    }
    Serial.print(frame[i], HEX); Serial.print(" ");
  }

  for (byte i = 1; i < 7; i++)
  {
    frame[i] ^= frame[i-1];
  }

  Serial.println(""); Serial.print("Obfuscation    : ");
  for (byte i = 0; i < 7; i++)
  {
    if (frame[i] >> 4 == 0)
    {
      Serial.print("0");
    }
    Serial.print(frame[i], HEX); Serial.print(" ");
  }
  Serial.println("");
  Serial.print("Compteur  : "); Serial.println(rollingCode);
}

void SendCommand(byte *frame, byte sync)
{
  if (sync == 2)
  {
    PORTD |= 1<<PORT_TX;
    delayMicroseconds(9415);
    PORTD &= !(1<<PORT_TX);
    delayMicroseconds(89565);
  }

  for (int i = 0; i < sync; i++)
  {
    PORTD |= 1<<PORT_TX;
    delayMicroseconds(4*SYMBOL);
    PORTD &= !(1<<PORT_TX);
    delayMicroseconds(4*SYMBOL);
  }

  PORTD |= 1<<PORT_TX;
  delayMicroseconds(4550);
  PORTD &= !(1<<PORT_TX);
  delayMicroseconds(SYMBOL);
  
  for (byte i = 0; i < 56; i++)
  {
    if (((frame[i/8] >> (7 - (i%8))) & 1) == 1)
    {
      PORTD &= !(1<<PORT_TX);
      delayMicroseconds(SYMBOL);
      PORTD ^= 1<<PORT_TX;
      delayMicroseconds(SYMBOL);
    }
    else
    {
      PORTD |= (1<<PORT_TX);
      delayMicroseconds(SYMBOL);
      PORTD ^= 1<<PORT_TX;
      delayMicroseconds(SYMBOL);
    }
  }
  
  PORTD &= !(1<<PORT_TX);
  delayMicroseconds(30415);
}

Le code est prévu pour contrôler 4 télécommandes différentes. Si ce nombre est différent, il faut adapter le code en conséquence (lignes 29 à 34).

Il faut ensuite modifier la variable "newRemotes" en y indiquant les différents numéros de commandes souhaitées. Il s'agit de nouvelles télécommandes donc les numéros peuvent être n'importe lesquels (au format hexadécimal et inférieur à 0xFFFFFF).

Sur votre PC, lancez un éditeur Arduino, puis envoyez le code que vous venez de modifier sur votre Arduino (sous réserve bien sûr que vous ayez connecté l'Arduino au PC via le cable).
 

III. 2. Branchements de l'Arduino


Grâce au fer à souder, désoudez le résonateur sur le transmetteur et remplacez-le par celui en 433.42 MHz.
  1. Repérez le résonateur sur votre transmetteur (le composant rond gris marqué R433 sur la photo ci-dessous) :
  2. De l'autre côté, identifiez les 3 pattes à désouder (entourées en rouge) :
  3. A l'aide d'une pompe à désouder, retirez l'étain sur ces 3 pattes :
  4. Retirez le résonateur qui va ensuite pouvoir être remplacé par le nouveau en 433.42 MHz :
  5. Soudez le nouveau à l'aide du fer à souder et d'étain :
  6. Si vous avez acheté une antenne, vous pouvez souder celle-ci sur le coin inférieur gauche comme montré sur la photo :

Ensuite, réalisez les branchements comme suit :



Et voilà ! La partie la plus complexe est maintenant terminée. Vous allez maintenant pouvoir associer les télécommandes virtuelles de votre Arduino à vos volets.
 

III. 3. Association des télécommandes Arduino aux volets roulants

 
  1. Sur une télécommande déjà associée à un volet roulant, appuyez 3 secondes sur le bouton "Prog" à l'arrière. Le volet va descendre et monter.
  2. Depuis votre moniteur série sur le PC, envoyez la commande "p0" à l'Arduino. Cela va associer votre première télécommande Arduino au volet roulant. Le volet va descendre et monter.
  3. Répéter les opérations 1 et 2 pour chaque télécommande en remplaçant "p0", par "p1", puis "p2" et enfin "p3".

Note : Si vous souhaitez désassocier une télécommande Arduino d'un volet roulant, utilisez la télécommande d'origine en appuyant 3 secondes sur le bouton "Prog" à l'arrière. Envoyez ensuite la commande "p#" depuis le moniteur série (# étant le numéro de la commande Arduino à désassocier).
Source : https://www.somfy.fr/file.cfm/Supprimer_une_t%C3%A9l%C3%A9commande_VR.pdf?contentID=300929

 

IV. Fonctionnement des télécommandes Arduino


Une fois les télécommandes associées, vous pouvez controler vos volets roulants Somfy grâce aux commandes suivantes depuis le moniteur série :
  • m# : monter le volet n° #
  • d# : descendre le volet n° #
  • s# : arrêter le volet n° #

 

V. Sources

 

Commentaires 0