Hello World !
Comme je l’ai expliqué dans mon précédent article, avec mon code Python maison j’arrive à reproduire le comportement du pont original avec les lampes RGBW. Toutefois le code ne supporte pas encore les lampes CCT (Correlated Color Temperature)… On va y remédier ! 🙂 Dans son projet, Henryk a procédé à un reverse engineering des lampes RGB : il a d’abord tenté de comprendre les trames échangées en radio, puis il a tenté de comprendre les ordres échangés entre le microcontrôleur du pont et le chipset radio PL1167.
J’ai donc décidé de reproduire son mode opératoire mais avec mes moyens limités.
Fabrication d’un analyseur logique
Henryk utilise un analyseur logique professionnel de chez Saleae. Le prix d’entrée est d’environ 250€ pour un modèle supportant 8 canaux. Trop cher pour le peu d’usage que je vais avoir. J’ai donc creusé ce qu’on pouvait faire avec un Arduino et un projet Hackaday a attiré mon regard : Arduino Generic Logic Analyzer.
Son concepteur m’a permis de concevoir un analyseur à partir d’une carte Arduino Mega qui m’a couté 10€. Le logiciel qui l’accompagne est également opensource. Parfait !
NB : Bien entendu, il faut charger le code source C++ idoine dans le Arduino Mega via le compilateur, sinon le Arduino est une brique 😉
Connexion à l’analyseur logique
En me basant sur la documentation du PL1167. J’ai tenté de repérer les pins CLK, MISO, MOSI et d’analyser, mais je n’avais aucun signal ressemblant à un signal SPI. Du coup je me suis basé sur des photos du logproject d’Henryk afin de voir sur quels pins il a effectué son analyse. Et voici les points de repiquage sur le microcontrôleur après recherche à tâton.
Le câblage est ainsi réalisé :
- Broche /CS (en bleu) ==> Port 22 (Channel 0)
- Broche SCK (en vert) ==> Port 23 (Channel 1)
- Broche MOSI (en marron) ==> Port 24 (Channel 2)
- Broche MISO (en jaune) ==> Port 25 (Channel 3)
- Une masse repiquée au régulateur de tension (en noir) ==> Port GND
NB : l’analyseur logique sur Arduino Mega utilise les ports 22 à 29.
Utilisation de OLS et décodage des transmissions SPI
A partir de là on peut maintenant lancer une analyse sérieuse. Pour ce faire on configure l’analyseur logique OLS en cliquant sur Capture > Begin Capture
On commence déjà par définir l’Arduino comme analyseur logique.
Capture à 1mhz (pour plus de précision vous pouvez capturer aussi à 2mhz mais cela diminue la taille du buffer par 2, dans notre cas c’est assez). Pourquoi cette valeur ? Car le code source d’Henryk montre que le chipset fonctionne à 1mhz 🙂
Et enfin, à moins de s’appeler Superman, il est impossible de déclencher la capture et de générer un ordre radio dans le délai imparti de 7ms 🙂 Donc on va configurer un trigger.
Selon la norme du bus SPI, la patte /CS passe à l’état 0 en début de transmission et repasse à 1 en fin de transmission. Très bien, on va utiliser ce trigger là :
La capture ainsi réalisée nous permet maintenant de procéder à une analyse SPI en passant par le menu Tools > SPI Analyzer, qu’on va configurer comme suit :
On défini les différents canaux comme tel, ensuite pour le mode j’y suis allé à taton, mais il s’agit au final de mode 1, en MSB.
On obtient le résultat suivant avec un ordre RGBW :
C’est cohérent avec le LogProject de Henryk ! (et son code source)
0.65326000: Write reg 7 -> 00 00 channel 0 (2402)MHz 0.65336250: Write reg 24 -> 14 7A syncword 0: 147A 0.65346500: Write reg 27 -> 25 8B syncword 3: 258B 0.65357250: Write reg 7 -> 00 00 channel 0 (2402)MHz 0.65367625: Write reg 34 -> 80 80 clear FIFO TX, FIFO write pointer: 0, clear FIFO RX, FIFO read pointer: 0
Donc, maintenant qu’on arrive à lire le SPI, on recommence, mais cette fois-ci avec un ordre CCT :
Les Syncwords d’initiation d’un ordre CCT sont différents d’une lampe RGBW. Pas étonnant que je ne recevais rien avec le code source d’Henryk quand je tentais de sniffer les lampes CCT. De part sa conception, son abstraction PL1167 ==> nRF24L01 ne peut techniquement pas écouter 2 syncwords en même temps.
Par ailleurs, si on creuse un peu, on s’aperçoit que les lampes ne causent pas sur les mêmes canaux… Les lampes RGBW envoient des ordres sur les canaux 9, 40 et 71, alors que les lampes CWW envoient des ordres sur les canaux 4, 39 et 74. Raison de plus pour que je ne puisse rien sniffer avec le code d’Henryk…
On peut également voir le « payload » envoyé en radio :
Modification de OpenMilight pour prendre en charge les lampes CCT
On peut lire la trame avec OLS, mais ce n’est pas très pratique pour faire du reverse… Tiens, et si on tentait de modifier le code de Henryk pour se faciliter la vie ?
On modifie le fichier MilightRadio.cpp :
Ligne 12, on remplace
static const uint8_t CHANNELS[] = {9, 40, 71};
par
static const uint8_t CHANNELS[] = {4, 39, 74};
Et ensuite, ligne 42, on remplace :
retval = _pl1167.setSyncword(0x147A, 0x258B);
par
retval = _pl1167.setSyncword(0x050A, 0x55AA);
Un petit make clean, puis make, et on execute :
sudo ./openmilight -l
On envoie un ordre CCT, et… miracle, il apparait à l’écran 🙂
Reste plus qu’à adapter mon code Python « Milight Multi Bridge Emulator » pour supporter ce type de lampe 😉
La suite au prochain épisode 😀
Bonjour
Je voulais savoir si aujourd’hui votre projet pour le protocole milight est au point ? Pensez vous qu’il serait possible de faire un kit à assembler pour les débutants ? Merci
Bonjour,
Le projet est abandonné…, je vous oriente plutôt vers cet excellent projet, que j’utilise au quotidien !
https://github.com/sidoh/esp8266_milight_hub
Cdlt,