Le nec plus ultra

Bon cette fois-ci on va vraiment mettre de la valeur à MYsensors. On a une platine pour capter la température et l'humidité pour pas trop cher et vraiment pas compliquée à mettre en oeuvre, alors passons à la vitesse supérieur, on va en mettre partout, c'est a dire dans toute les pièces où il y a un radiateur. Cool le décors est planté, cette profusion de capteurs représente chez moi environ 6 zones-pièces. C'est pas un peu "too much" ! Ben pas vraiment, dans une zone nuit par exemple, entre la chambre des parent et celle des enfants on va pouvoir varier la température et surtout les plages horaires, pareil pour la ou les salle de bains etc ... C'est du confort mais surtout des économies. Puisque l'on va avoir la possibilité d'orchestrer et d'affiner tous cela.
Bien sur des thermostats tout fait avec autant de zones et une finesse comme cela, ça coûte un bras et puis pas vraiment modulable/adaptable/intelligent. Du coup on va utiliser le combo magique jeedom mysensors. Oh dam ! il n'y a pas de "Build" qui me permette de faire cela ... le plus proche c'est la commande de relais.
Plus le choix il va falloir vraiment mettre les mains dans le cambouis cette fois-ci.

Le principe

J’étais partis dans un premier temps sur une idée de petits modules individuel qui se glisseraient dans les boites murale de chaque radiateurs, mais l'alimentation et les transmissions m'ont vite fais revenir à la réalité. Une seule carte qui va piloter les radiateurs avec leurs fils pilotes sera bien plus facile à gérer et plus efficient. Piloter les radiateurs avec le fil pilote 4 ordres est simple et facile à réaliser avec des diodes et bien suffisant puisque en fait 2 ordres sont utiles, CONFORT et ARRET. Les autres mode seront implémentés dans la programmation de la carte mais ils seront "émulés" par le thermostat de jeedom. Pour les signaux de commandes des radiateurs voici un tableau,

  • pas de signal et en mode piloté le radiateur chauffe.
  • si que les alternances positive alors ARRET.
  • si que les négative alors HORS GEL. ( peut etre utile lors de longue absences ).
  • si tout le signal mode eco.

Bon simple ! un signal alternatif et deux diodes nous voilà avec la possibilité de faire notre commande ou du moins nos 4 ordres

cmd_pilote

Pour résumer, il faut donc 2 commandes avec 1 diodes, ce qui va donner 4 ordres par radiateurs. Pour mon installation cela représente 12 commandes à sortir d'un Arduino minipro, c'est donc pas possible. Sur un Uno ça passe mais c'est juste et pas forcement évolutif donc le choix est fait ce sera un Mega et il pourra commander 9 radiateurs et donc 18 sorties. Petit challenge, mon installation est en Triphasé, ce qui veut dire que j'ai 3 phases pour piloter mes radiateur qui sont bien sur en 230V. Je vais donc éclater mes commandes en 3x3 modules puisque mes radiateurs sont répartis sur les 3 phases. Pour quelqu'un qui est en mono, cela ne change rien il suffit d'alimenter les cartes filles de commandes avec la même phase.
Coté carte de commande, j'ai également implanté un retour visuel sur l'état de commande des 9 radiateurs avec au début un afficheur LCD mais cela c'est avéré peut pratique alors je suis revenus à quelque chose de plus simple et plus facile a lire, une barre de leds multicolore, je vous passe les détails mais si je vous dit rouge, vert, bleu et éteins vous avez surement fait le lien avec les modes des radiateurs.
Petit changement, afin de découvrit de nouveaux outils et parce-que fritzing est vraiment bien, mais pas très malléable quand on veut un peu faire ce que l'on veut je suis partit sur KiCad. Alors oui bien sur c'est un peu plus difficile à appréhender mais tellement plus Pro :-) .

Schema

sch_pilotemega

Pour les explications :

  • Un arduino mega avec des labels plutôt que des fils !
  • Un module NRF2401 et son alim 3.3V depuis le Mega
  • les trois zones de pré-commandes, c'est à dire un étage avec transistors pour pouvoir commander les opto-triac MOC sans faire tomber l'alimentation de l'arduino. ( rendu compte après une âpre bataille avec des fonctionnements erratiques de la carte toutes ces leds consomment trop !!! )
  • Enfin la "carte fille" avec les MOC et l'arrivée 230V et commande des fils pilotes.

La carte

Je suis aller chercher quelques notions que j'ai apprises en des temps certains, je m'excuse au près des compétents. Si il y a des erreurs ou incohérences vous vous devez de me faire un retour.
pcb_pilotemega

C'est un mix entre encombrement, facilité de réalisation, et surtout comme j'ai pu la plupart du temps.

Donner vie aux composants

Aller encore un nouvel outil, cette fois ci c'est IDE d'Arduino. Il faudra bien sûr faire tout le préalable de mettre les lib mysensors et leds , mettre la carte en mega etc ... let's go

// Rev 5
//11/02/2024

// Enable debug prints to serial monitor
//#define MY_DEBUG

// Enable and select radio type attached
#define MY_RADIO_RF24
//#define MY_RADIO_RFM69
// Specific Pin radio for arduino Mega
#define MY_RF24_CE_PIN 49
#define MY_RF24_CS_PIN 53

//Force node ID
#define MY_NODE_ID 1

// Enable repeater functionality for this node
//#define MY_REPEATER_FEATURE  // for my configuration, it is too close to the base so useless

// MySensors
#include <MySensors.h>
// For Led status support
#include <FastLED.h>

// define LED 
// How many leds in your strip?
#define NUM_LEDS 9
// For led define DATA_PIN.
#define DATA_PIN 34
// Define the array of leds
CRGB leds[NUM_LEDS];

// Radiator Moc configuration
#define NUMBER_OF_MOC 18 // Total number of attached MOC -- be careful that even numbers since 2 MOC for one radiator
#define MOC_ON 1  // GPIO value to write to turn on attached moc
#define MOC_OFF 0 // GPIO value to write to turn off attached moc

// Def Moc pin for 18/9 MOC/RADIATOR
const int PinMoc[18] = {22, 24, 26, 28, 30, 32, 23, 25, 27, 29, 31, 33, 37, 39, 41, 43, 45, 47};

// variables for radiator
char Radiator_value[9]={'O','O','O','O','O','O','O','O','O'};

// Pilote Structure
// define MOC status from mode_code
typedef struct {
  char mode_code;
  int code_p;
  int code_n;
} modeFilPilote;

modeFilPilote modesFilPilote[4] = {
  {'O', 0, 1}, // Mode Off
  {'G', 1, 0}, // Mode hors gel
  {'E', 1, 1}, // Mode eco
  {'C', 0, 0}  // Mode confort
};

void before()
{
  for (int MOC = 0; MOC < NUMBER_OF_MOC; MOC++) {
    // Then set MOC pins in output mode
    pinMode(PinMoc[MOC], OUTPUT);
  }

  int sensor = 0;
  //find sensor status
  for (int MOC = 0; MOC < NUMBER_OF_MOC; MOC++ )
  {
     // Force radiator mode to OFF
     digitalWrite(PinMoc[MOC], LOW);
     digitalWrite(PinMoc[MOC + 1], HIGH);
     // X value cause led for first init to Yellow color
     // just for seen it's first start
     Radiator_value[sensor] = 'X';
     //index sensor + 1 but MOC +1+1  
     sensor++;
     MOC++;
  }

}

void presentation()
{
  sendSketchInfo("Fil pilote", "1.0");
  // Register all sensors to gw (they will be created as child devices) 
  // start at id 0 to 9 for 9 sensors
  for (int sensor = 0; sensor < NUMBER_OF_MOC / 2; sensor++) {
    // Register all sensors to gw (they will be created as child devices 2xmoc by radiator)
    present(sensor, S_CUSTOM);
    wait(50);
  }

}

void setup() {
  //Start init led support
  LEDS.addLeds<WS2812B,DATA_PIN,GRB>(leds,NUM_LEDS);
  LEDS.setBrightness(1);
  for (int i = 0; i < NUM_LEDS; i++) { 
        leds[i] = CRGB::Orange;
        FastLED.show();
        delay(100);
        leds[i] = CRGB::Black;
        FastLED.show();
        delay(50);
  }
}

void loop() {

// Led status 
  for (int i = 0; i < NUMBER_OF_MOC / 2; i++) { 
    switch (Radiator_value[i]) {
      case 'O':
        {
        leds[i] = CRGB::Black;
        FastLED.show();
        }
        break;
      case 'G':
        {
        leds[i] = CRGB::Blue;
        FastLED.show();
        }
        break;
      case 'E':
        {
        leds[i] = CRGB::Green;
        FastLED.show();
        }
        break;
      case 'C':
        {
        leds[i] = CRGB::Red;
        FastLED.show();
        }
        break;
    default: 
      leds[i] = CRGB::Yellow;
      FastLED.show();
    break;
    }
  }
}

void receive(const MyMessage &message) {
  #ifdef MY_DEBUG  
  Serial.println("=============== Receive Start =======================");
  if (message.isAck()) {
     Serial.println(">>>>> ACK <<<<<");
     Serial.println("This is an ack from gateway");
     Serial.println("<<<<<< ACK >>>>>>");
  }
  #endif  

  #ifdef MY_DEBUG
  // Write some debug info
  Serial.print("Incoming change for sensor:");
  Serial.println(message.sensor);
  Serial.print("New status: ");
  Serial.println(message.getBool());
  Serial.print("New string: ");
  Serial.println(message.getString());
  Serial.print("Message type: ");
  Serial.println(message.type);
  #endif

  if (message.type == V_HVAC_FLOW_STATE) {

    // get index of moc from radiator index ( mysensor => 1 sensor = 2 MOC )
    // sensor 0(*2) => MOC 0,1 | sensor 1(*2) => MOC 2,3  | sensor (2*2) -> MOC 4,5 etc ...
    unsigned char index = message.sensor * 2;
    // test for 4 mode radiator (i)
    for (int i = 0; i < 4; i++) {
      if (message.getString()[0] == modesFilPilote[i].mode_code) {
        digitalWrite(PinMoc[index], modesFilPilote[i].code_p);
        digitalWrite(PinMoc[index + 1], modesFilPilote[i].code_n);
        // set news value of Radiator_value
        Radiator_value[message.sensor] = message.getString()[0];
        #ifdef MY_DEBUG
        Serial.print("Radiateur");
        Serial.print(message.sensor);
        Serial.print("=");
        Serial.println(message.getString());
        #endif
        return;
      }
    }
  }
}

The explication !!!

Comme déjà dit, si vous avez une meilleure idée ou vous trouvé une erreur vous vous devez de me faire un retour !

Le début , comme a chaque fois c'est la mise en place, les inclusions et les premières définitions (radio, ledstrip). Là ou cela concerne vraiment la carte c'est au niveau de Moc configuration

On va definir le nombre de MOC donc si on a 6, 12 ou 18 MOC, c'est a dire proportionnel au nombre de carte de commande 1,2,ou 3.
On défini des états ON ou OFF La liste des pins affectées aux MOC Enfin l'état par défaut à Off

Viens ensuite la définition d'un ARRAY, qui va faire une liaison entre un état voulu est la programmation du couple de MOC pour l'avoir, petit rappel de notre tableau plus haut :

  • {'O', 0, 1}, // Mode Off c'est a dire alternance positive.
  • {'G', 1, 0}, // Mode hors gel c'est a dire alternance négative.
  • {'E', 1, 1}, // Mode eco c'est à dire le signal complet.
  • {'C', 0, 0} // Mode confort pas de signal.

Pour la structure c'est simple c'est un code_char pour le mode, une valeur pour code_p(ositif) et code_n(égatif).

void before()

Cela va définir et mettre en place de façon automatique et paramétré au travers des variables définies plus haut toute les définitions de notre carte et de ces sorties.
Cela met aussi les leds et le statu des radiateurs dans un état 'X', donc jaune pour la led. Ce qui indique qu'il n'y a pas encore eu de syncro entre jeedom et la carte de contrôle.
Je rappelle que c'est jeedom qui commande la carte et pas le contraire, donc il faut patienter jusqu’à la première connexion de jeedom pour que l'état soit réel.

void presentation()

Essentiel à Mysensors, on présente le nom et tous les "capteurs" avec la boucle for.

void setup()

On initialise le strip de led, on affiche une lumière orange, ce qui permet de tester les leds au démarrage de la carte.

void loop()

Cela commence par fixer la couleur de la led en fonction de l'état du radiateur, oui je sais c'est de la magie faire de la lumière noire !
Et c'est tout pour la boucle.

C'était facile, trop facile peut être mais c'était sans compter sur l'interception de mysensors qui est void_receive.

void receive()

Pas mal de messages de debug, puisque c'est cette partie qui à était la plus dure à finaliser.
On va lire le message de jeedom/Mysensors qui contient l'index du sensor que l'on multiplie par 2 pour faire le lien avec les pins des MOC. Avec cette multiplication on recupère l'index du premier MOC pour le bon sensor.
sensor 0(2) => MOC 0,1 | sensor 1(2) => MOC 2,3 | sensor (22) -> MOC 4,5 etc ...*
On récupère l'état de notre radiateur qui correspond a une des lettres O,H,E et C .
Maintenant on peut définir quel MOC allumer ou éteindre en liens avec l'index et donc les pins et les valeurs voulues suivant la définition de la structure modesFilPilote.
On fini par écrire l'état du radiateur dans "Radiator_value" pour changer l'état de la led lors du retour dans la loop.

Facile non ?

Donner intelligence avec Jeedom

aller encore un petit effort, maintenant il y a un peu de bricolage sous jeedom. Je n'ai pas réussi à ce que le module remplisse automatiquement l'onglet "Commandes", il faut donc remplir à la main. Pour chaque radiateurs il faut donc créer une ligne info et 4 action, vous l'avez compris, la ligne info va stocker l'état demandé et c'est cette valeur qui est envoyé à la carte. Les lignes actions permettent de définir les 4 valeurs O,H,E et C et de les assigner.

Nom Type Jeedom ID Capteur Type Capteur Valeur Type Donnée Unité Paramètres
Nom info et autre de 0 à 8 23 - Custom 21 - Mode de chauffage
NOM-OFF et Aucune action et défaut le même que ligne info 1 - Paramétrage O 21 - Mode de chauffage
NOM-HG et Aucune action et défaut le même que ligne info 1 - Paramétrage G 21 - Mode de chauffage
NOM-ECO et Aucune action et défaut le même que ligne info 1 - Paramétrage E 21 - Mode de chauffage
NOM-CONF et Aucune action et défaut le même que ligne info 1 - Paramétrage C 21 - Mode de chauffage

Voilà il faut reproduire ces lignes autant de fois que vous avez de cartes filles donc 3,6 ou 9 fois.

Voici le panneau de contrôle un peu tuner que j'ai chez moi.
mega_pilote
Couplé avec le plugin thermo du market jeedom
mega_thermo

ENJOY !

Fichiers

Fichier KiCad Projet => Pilote_Mega_LedStatus_final.kicad_pro
Fichier KiCad Schema => Pilote_Mega_LedStatus_final.kicad_sch
Fichier KiCad Lib => Pilote_Mega_LedStatus_final.kicad_sym
Fichier KiCad pcb => Pilote_Mega_LedStatus_final.kicad_pcb
Fichier KiCad conf => Pilote_Mega_LedStatus_final.kicad_prl

Fichier Arduino ino => Fil_Pilote_Megax9_LedStatus.ino

Previous Post