Mai 012014
 

Arduino

Commande de prises électriques, éclairages…

par transmission 2.4GHz

Protocole de transmission

 

A l’issue de tous ces choix de base et quel que soit le mode de fonctionnement retenu, il est nécessaire de définir la façon dont les informations circulent.

Prérequis :

  • différencier les différents modules avec des plages d’adresses suffisamment étendues (prise, éclairage, capteur de température, thermostat, alarme…).
  • permettre d’identifier le type de commande (programmation, commande directe, demande de statut…),
  • en cas de programmation pour les A/M des prises, permettre plusieurs programmations quotidiennes et/ou hebdomadaires,
  • en cas de programmation pour les éclairages, permettre de commander soit des niveaux directs, soit des plages – temps de variation,
  • … et j’en ai surement oublié,
  • tenir compte du fait que les modules 2.4GHz (nRf24l01) ne permettent de transférer que 32 octets, il faut donc être économe dans l’utilisation de ces octets ou utiliser d’autres astuces. NB : cette valeur de 1 à 32 octets, c’est le Mirf.payload que l’on initialise dans le programme.

J’avais donc opté pour le découpage suivant :

  • Octet 1 (numéroté 0 dans la programmation) : 1ère partie de l’adresse du module ; permet surtout de différencier les types d’interfaces ; de 1 à 255 (on évite d’utiliser la valeur 0) ;
  • Octet 2 : 2ème partie de l’adresse du module ; permet d’identifier le module dans son type ; de 1 à 255 (on évite d’utiliser la valeur 0) ;
  • Octet 3 : type de commande (programmation, commande directe, lecture du statut du module, reset des plages horaires des modules, remise à l’heure, si nécessaire, des horloges des modules… entre l’utilisation des bits à l’unité et les combinaisons possibles, il reste beaucoup de fonctions imaginables) ;
  • Octet 4 : état de la commande directe (0 ou 1 pour une prise, de 0 à 255 pour une lampe) ;
  • Octet 5 : utilisé pour la commande de lampe, sur commande directe, de 1 à 255 pour une variation sur le nombre de secondes indiquées ;

Sur cette première base, il s’avère que 5 octets sont utilisés, il en restait donc 27 de disponibles.

NB : en s’inspirant d’une structure telle que celle du X10 (16 codes maison x 16 codes modules), on aura pu se limiter à un byte d’adresse, soit « seulement » 256 modules ; cela m’a paru trop limitatif et je suis donc resté sur 2 octets pour l’adresse.

Tableau récap pour les 5 premiers octets :

Octet[0]

Byte 7

Byte 6

Byte 5

Byte 4

Byte 3

Byte 2

Byte 1

Byte 0

Utilisation

0

0

0

0

0

0

0

0

Inutilisé

x

x

x

x

x

x

x

x

Adresse première partie

 

Octet[1]

Byte 7

Byte 6

Byte 5

Byte 4

Byte 3

Byte 2

Byte 1

Byte 0

Utilisation

0

0

0

0

0

0

0

0

Inutilisé

x

x

x

x

x

x

x

x

Adresse deuxième partie

Si par exemple, on décide que les prises sont à l’adresse haute 1, le premier module prise portera l’adresse basse 1 et donc l’adresse globale 11 en hexa (soit 00000001 00000001 en binaire).

Si les éclairages sont à l’adresse haute 2, le premier module éclairage sera à l’adresse globale 21…

Octet[2]

Byte 7

Byte 6

Byte 5

Byte 4

Byte 3

Byte 2

Byte 1

Byte 0

Action

0

0

0

0

0

0

0

0

Aucune

0

0

0

0

0

0

0

1

Programmation

0

0

0

0

0

0

1

0

Commande directe

0

0

0

0

0

1

0

0

Lecture statut

x

x

x

x

x

0

0

0

Option à venir

1

0

0

0

0

0

0

0

Remise à l’heure des RTC des modules

1

1

1

1

1

1

1

1

Remise à zéro (notamment les plages horaires programmées pour les modules prises)

 

Octet[3]

Byte 7

Byte 6

Byte 5

Byte 4

Byte 3

Byte 2

Byte 1

Byte 0

Action

0

0

0

0

0

0

0

0

Commande A/M

(prise)

0

0

0

0

0

0

0

1

x

x

x

x

x

x

x

x

Niveau d’éclairement

(lampe)

A noter que la commande de volet – écran, peut se faire sans problème avec une fonction A/M sous réserve d’avoir un relais mécanique en sortie.

Octet[4]

Byte 7

Byte 6

Byte 5

Byte 4

Byte 3

Byte 2

Byte 1

Byte 0

Action

x

x

x

x

x

x

x

x

Temps de variation lumineuse en secondes

(entre valeur actuelle et valeur demandée dans l’octet[3])

Si ma prise est à l’adresse basse 1 et que je veux lui envoyer un ordre direct de marche, je vais émettre 01h, 01h, 02h, 01h, 00h.

Pour les prises, j’étais parti sur 2 ou 3 programmation quotidiennes possibles mais je me suis rendu compte que je bloquais la possibilité d’avoir des programmations différentes, par exemple, pour la semaine et le WE.

J’étais donc reparti sur le fait de prévoir le maximum de possibilités en utilisant les 27 octets restants ; néanmoins, il me fallait un octet pour définir le ou les jour(s) de la semaine et 4 octets (compactables en 3 avec du concaténage) pour définir une heure de début (marche) et une heure de fin (arrêt).

J’avais donc redéfini le mode de programmation des heures, découpés de la façon suivante :

  • le premier octet contient un numéro de jour ou une combinaison : 1 octet = 8 bits, 1 semaine = 7 jours, ce qui permet toutes les combinaisons possibles, y compris des commandes répétitives, la valeur 0 permet au module de comprendre qu’il ne gère pas les octets suivants,
  • le second octet contient la valeur de l’heure pour l’allumage,
  • le troisième octet contient la valeur des minutes pour l’allumage,
  • le quatrième octet contient la valeur de l’heure pour l’extinction,
  • le cinquième octet contient la valeur des minutes pour l’extinction.

Et là, je vous entends me dire : reste 27 octets, 5 octets par commande, cela ne fait plus que 5 programmations possibles, c’est pas assez… Et je suis d’accord !

Donc, il faut non pas envoyer toutes les plages horaires lors d’une transmission mais envoyer les plages horaires à raison de 1 par transmission et les mémoriser dans le module ; il faut donc faire attention dans ce cas de ne pas « exploser » la capacité mémoire du module et de savoir mémoriser les données ; dans ce but, on va utiliser la partie EEPROM du module Arduino NANO qui fait 512 octets (pour la version ATmega168) et 1ko (pour la version ATmega368) ; du coup, on se retrouve avec la possibilité de programmer 512 / 5 = 102 pages horaires.

Dans la mesure où il sera intéressant de pouvoir récupérer ces info (avec le mode « lecture du statut ») et de les afficher, il faudra être raisonnable. De mon point de vue, 4 à 5 programmations différentes par semaine doit représenter la majorité des besoins.

Tableau récap pour les octets correspondants aux jours et heures:

Octet[5]

Byte 7

Byte 6

Byte 5

Byte 4

Byte 3

Byte 2

Byte 1

Byte 0

Jour

0

0

0

0

0

0

0

0

Inutilisé

0

0

0

0

0

0

1

0

Lundi

0

0

0

0

0

1

0

0

Mardi

0

0

0

0

1

0

0

0

Mercredi

1

0

0

0

0

0

0

0

Dimanche

1

1

0

0

0

0

0

0

Samedi + dimanche

1

1

1

1

1

1

1

0

Semaine complète

0

0

1

1

1

1

1

0

Du lundi au vendredi

 

Octet[6]

Byte 7

Byte 6

Byte 5

Byte 4

Byte 3

Byte 2

Byte 1

Byte 0

Heure de début

0

0

0

0

0

0

0

0

00hxx

0

0

0

0

0

0

0

1

01hxx

0

0

0

0

0

0

1

0

02hxx

0

0

0

0

0

1

0

0

04hxx

0

0

0

0

0

0

1

0

0

1

0

18hxx

0

0

0

..

0

0

0

1

0

1

1

1

23hxx

 

Octet[7]

Byte 7

Byte 6

Byte 5

Byte 4

Byte 3

Byte 2

Byte 1

Byte 0

Minutes de début

0

0

0

0

0

0

0

0

xxh00

0

0

0

0

0

0

0

1

xxh01

0

0

0

0

0

0

1

0

xxh02

0

0

0

0

0

1

0

0

xxh04

0

0

0

0

1

0

1

0

1

0

xxh42

0

0

0

..

0

0

1

1

1

0

1

1

xxh59

Idem pour octet[8] pour l’heure de fin et pour octet[9] pour les minutes de fin.

Au total, par transmission, on n’enverrait donc que 10 octets (Mirf.payload = 10).

Comme les modules récepteurs sont intelligents et stockent les informations, on n’envoie ces informations que lorsque l’on veut modifier la programmation, c’est-à-dire pas souvent.

Gestion du statut : cette fonction permet de récupérer l’état d’un module prise ou d’un module lampe, de lire la programmation horaire pour un module prise, de récupérer une valeur, par exemple pour un module thermomètre…

Adressage des modules : dans un premier temps, je vais préparer mes modules avec les adresses programmées en dur ; ultérieurement, j’aimerais faire en sorte qu’un module soit en phase d’auto-apprentissage pendant, par exemple 30 secondes après sa mise sous tension (et sous réserve qu’il n’ait pas déjà une adresse, auquel cas, il faut d’abord passer par une commande de remise à zéro).

 

Ce n’est donc pas terminé car je voudrais encore améliorer plusieurs points :

1) permettre d’utiliser un module Arduino pour commander plusieurs prises différentes; cela signifie qu’un module prise ne répond pas qu’à une seule adresse mais à plusieurs;

2) rendre possible le fait de reseter les modules;

3) reprogrammer un module (après l’avoir reseter ou à la première utilisation); il faut donc gérer le fait que l’adresse est « vide » pour être alors en mode programmation puis ne plus le faire quand l’adresse est enregistrée.

Suite : voir article sur les premiers essais

Sorry, the comment form is closed at this time.