Image promotionnelle du switch USB ezcoo SW24L
Attribution : ezcoo
Contexte
Outre mon Mac mini, j’utilise régulièrement mon PC de jeu. Par conséquent, j’ai besoin de partager mon clavier et mon trackpad entre les deux machines. À cet effet, je dispose d’un switch ezcoo EZ-SW24L-U3LP, qui permet de partager 4 ports USB 3.0 avec deux machines différentes.
Il s’agit d’une évolution par rapport aux switchs que j’utilisais jusqu’alors. Tous les switchs USB permettent de basculer d’une machine à l’autre par l’appui sur un bouton, typiquement situé directement sur le switch, parfois sur une télécommande filaire, et encore plus occasionnellement (comme ici), à l’aide d’une télécommande infrarouge.
Dans le cas de mon SW24L, la télécommande comprend deux boutons : un par machine. Il n’y a donc pas de cycle entre les différentes “sorties” à l’appui sur un bouton unique. Chaque canal a son propre bouton.
Le boîtier intègre un récepteur infrarouge, mais offre également un connecteur jack permettant d’y brancher un récepteur externe (fourni). Ce récepteur externe ne semble pas contenir d’électronique, en sus du récepteur infrarouge.
Objectif
Ce switch s’est montré, jusque-là, très pratique pour mon cas d’usage. Mais je souhaite aller un peu plus loin, et j’aimerais pouvoir le piloter via le Wifi.
Je veux imaginer une solution qui ne soit ni invasive, ni destructive : je ne veux pas supprimer la possibilité de le piloter par la télécommande fournie, je veux lui ajouter le pilotage par le Wifi.
Cas d’usage
- Palier à un défaut, temporaire ou permanent, de la télécommande ou du système de réception infrarouge
- Intégration à HomeAssistant : sélection automatique de source en fonction de différents critères, intégration à ma dashboard
Principe de fonctionnement
Un ESP8266 est intercalé entre le récepteur infrarouge externe et le switch, de manière à ne pas interférer avec : que l’ESP8266 soit fonctionnel ou non ne doit pas empêcher les signaux infrarouges de transiter vers le switch.
Schéma de principe d’intégration de l’ESP8266 entre le récepteur IR externe et le switch.
Attribution : Richard Dern
En revanche, lorsque l’ESP8266 sera fonctionnel, il devra être capable d’analyser les signaux infrarouges (afin de pouvoir répliquer le protocole utilisé par la télécommande), et émettre les mêmes signaux vers le switch via le même câblage.
Ainsi, il pourrait être réutilisé, même si je dois changer le switch ou le récepteur : je devrais peut-être simplement mettre à jour les séquences IR.
Pilotage d’un switch USB par le wifi
Cette mise en œuvre devrait nous permettre d’esquiver certains problèmes liés au manque de documentation, et faciliter la migration vers d’autres appareils.
Ici, on communique via un câble jack commun, mais en pratique, on peut imaginer d’autres choses, comme remplacer la télécommande fournie avec un bandeau de LEDs d’entrée de gamme, du moment que l’on dispose d’un point d’entrée pratique (comme ici, le jack).
Documentation technique
ezcoo ne fourni aucune documentation technique sur son site public. En revanche, le support technique a été très coopératif, et a pu me fournir la liste des séquences IR (quoiqu’incomplète), valable pour l’ensemble de ses produits pilotés par infrarouge (que je ne redistribuerai pas : si ça vous intéresse, envoyez un message à leur support technique !).
Je refuse les techniques intrusives ou destructives. Je m’interdis donc d’ouvrir le switch ou le récepteur externe (de toute façon noyé dans l’epoxy) pour éviter de les endommager. Néanmoins, il existe quelques solutions pour obtenir les informations dont j’ai besoin.
Montage préliminaire et obtention des informations manquantes
On va simplement réaliser une rallonge jack avec borniers, afin de pouvoir facilement utiliser un multimètre sur les différents fils composant le câble. À cet effet, je me suis procuré ces câbles mâles et ces câbles femelles.
On va commencer par identifier chaque partie du connecteur jack et à quel bornier il correspond, dans le but d’éliminer tout doute pouvant subsister à ce stade. En effet, il n’est pas rare que les conventions changent d’un constructeur à l’autre, et on veut éviter d’inverser la polarité du câble, ce qui risquerait d’endommager le récepteur, le switch, ou l’ESP8266.
On va utiliser un multimètre doté d’un testeur de continuité, placer une sonde sur l’un des contacts du connecteur jack et l’autre sonde sur l’une des bornes, jusqu’à ce que la continuité soit déterminée.
Bien que très primitive, cette étape m’a tout de même permis de mettre en évidence un défaut dans l’un de mes câbles, dont l’un des fils était déconnecté.
Au final, on doit identifier les contacts suivants, et s’assurer qu’ils sont bien reliés aux bornes correspondantes du bornier :
Connecteur jack (plug) et ses contacts
Attribution : Par Benedikt.Seidl — Travail personnel, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=4173292
À ce stade, il est important de se souvenir de la correspondance entre le marquage sur le bornier et le contact sur le connecteur.
N’oublions pas que le jack est initialement un connecteur audio, et que sa versatilité a conduit à son usage dans d’autres domaines.
Ainsi, les marquages L et R (pour Left et Right) perdent leur sens dans le cas d’usage présent, et on ne peut pas être certains que la masse du connecteur du récepteur IR externe sera effectivement sur le contact le plus proche du câble.
Notre rallonge (en haut). Le câble avec connecteur mâle (en bas) nous servira à tester la continuité borne à borne.
Attribution : Richard Dern
Une fois la rallonge “assemblée”, on relie le connecteur mâle au connecteur femelle (à droite sur la photo ci-dessus), et on s’assure de la continuité entre chaque borne des borniers.
Placement des sondes du multimètre en mode continuité. Ici, on teste que la borne L d’un bornier correspond à la même borne à l’autre extrémité de la rallonge.
Attribution : Richard Dern
De cette façon, on n’a pas encore besoin d’identifier à quoi correspond exactement chaque contact (masse, ligne d’alimentation et ligne de données) du récepteur IR externe : on peut utiliser notre rallonge entre ce récepteur et le switch, et disposer d’un bornier sur lequel faire nos mesures, sans avoir besoin de détruire quoique ce soit.
On retire alors le câble mâle de la rallonge et on y met le récepteur IR, puis la rallonge vers le switch.
On peut alors déterminer le fil où se trouve la masse : on place une sonde du multimètre (toujours en testeur de continuité) sur une zone que l’on sait reliée à la masse (par exemple, sur le métal de la face extérieure de l’un des ports USB du switch), et l’autre sonde sur l’une des trois bornes du bornier. En ce qui me concerne, je tombe bien sur la borne marquée comme étant la masse.
Pour trouver la ligne d’alimentation, on passe le multimètre en mode voltmètre, on place une sonde sur la masse et on teste les deux autres bornes, à la recherche d’une tension stable (le switch doit alors être alimenté).
Pour ma part, je trouve du 5V sur la borne marquée L… Mais aussi sur celle marquée R !
Il y a plusieurs conséquences à cette “découverte”, mais la première est que la tension de la ligne de données est maintenue à VCC (5V) au repos par une résistance pull-up. La ligne de données est donc dite “active basse”, parce que les impulsions sont à 0V quand une trame est reçue.
Selon le multimètre employé, il peut être difficile de détecter une chute de tension lors d’un appui sur un bouton de la télécommande.
Dans ce cas, il y a des bidouilles à faire, mais le plus propre reste d’utiliser un oscilloscope.
C’est ce que j’ai fait, et j’ai donc pu déterminer que la ligne d’alimentation se trouve sur la borne L (qui reste à 5V), et la ligne de données sur la borne R (qui affiche un signal à peu près carré sur l’oscilloscope lorsqu’un bouton est pressé).
Pour récapituler, dans mon cas :
- Borne “masse” => masse réelle
- Borne
L=> alimentation 5V - Borne
R=> ligne de données, 5V, pull-up
Mise en œuvre
Je vais exploiter un ESP8266, et plus précisément un Wemos D1-Mini, qui sera logé dans un petit boîtier placé à côté du switch.
Ce boîtier sera doté d’un connecteur jack 3.5mm femelle, pouvant accueillir le récepteur infrarouge externe. Un autre connecteur jack permettra de relier le boîtier au switch, via le connecteur jack femelle du switch. Ainsi, mon boîtier s’intercale parfaitement entre le récepteur infrarouge externe (dont il pourra lire l’état) et le switch (auquel il pourra relayer les commandes).
Même si le récepteur infrarouge externe est alimenté en 5V, on ne peut pas admettre que le switch est capable de délivrer par ce biais la puissance requise par l’ESP8266. Par conséquent, ce boîtier sera alimenté indépendamment du switch, même si les masses sont mises en commun.
Principe d’interconnetion : notre contrôleur va lire et écrire sur le même canal que le récepteur IR.
Attribution : Richard Dern
Lecture du signal IR
On veut que l’ESP8266 soit capable de lire le signal IR, de sorte à pouvoir apprendre les séquences. Si, en pratique, on va hard-coder ces séquences dans un premier temps, il sera utile de lire ce qui est reçu depuis le récepteur IR pour s’assurer que les séquences hard-codées sont les bonnes, et plus tard, pour pouvoir apprendre de nouvelles séquences (par exemple, en cas de changement de matériel).
Or, le récepteur IR envoie du 5V sur la ligne de données, tandis que les GPIO de l’ESP8266 attendent du 3.3V.
Émission d’un signal
Pour rappel, je ne cherche pas à émettre un signal via l’infrarouge. Je ne cherche donc pas à remplacer la télécommande par mon ESP8266. Je veux utiliser l’ESP8266 pour émettre un signal via le câble jack. On peut donc voir l’ESP8266 comme une télécommande filaire, qui doit donc reproduire les séquences que la véritable télécommande enverrait au récepteur, ou en tout cas, les séquences que le récepteur enverrait au switch.
Encore une fois, les GPIO de l’ESP8266 fonctionnent en 3.3V, tandis que le switch attend un signal en 5V avec pull-up.
Logic Level Shifters
En principe, je devrais pouvoir facilement employer des Logic Level Shifters. Il s’agit de petits circuits imprimés où, d’un côté, on se connecte en 3.3V, et de l’autre en 5V, et le LLS se débrouille pour fournir une communication bidirectionnelle.
En pratique :
- Je n’en ai pas sous la main, mais j’ai des résistors et des transistors,
- apparemment, certains utilisateurs se plaignent de latences, ce qui semble être problématique dans mon contexte,
- où serait le fun si tout le travail était pré-mâché…
Circuit de lecture
Le circuit de lecture sera donc basé sur un transistor (un 2N2222A, Q1) : une résistance de 100kΩ (R1) relie le bus de données à la base du transistor, l’émetteur est directement relié à la masse et le collecteur au GPIO2 (D4) de l’ESP8266.
Une résistance de 10kΩ (R2) est placée en pull-up entre la sortie 3.3V de l’ESP8266 et le collecteur du transistor.
Ce montage a pour but de traduire les signaux 5V en signaux 3.3V, de sorte à protéger l’ESP8266, sans dénaturer le signal (ou le moins possible).
Dans ce montage :
R1minimise le courant de base et donc la charge sur la ligne de données, ce qui devrait permettre de continuer à utiliser le récepteur IR externe en parallèle de l’ESP8266 ; une valeur de 100kΩ est un bon compromis : une valeur plus élevée pourrait empêcher le transistor de commuter, alors qu’une valeur plus basse pourrait empêcher le bon fonctionnement du récepteur IR externe.R2permet de fixer l’état “haut” à 3.3V du point de vue de l’ESP8266. Une valeur de 10kΩ est un compromis : une valeur plus élevée permettrait de réduire la consommation, mais au prix d’un ralentissement des signaux, etR1devrait être ajustée en conséquence, faute de quoi le courant circulant dans le transistor en amont ne serait plus suffisant pour qu’il commute.
Notons que ce montage inverse la logique fournie par la ligne de données. Rappelez-vous, on a déterminé qu’elle fonctionne en active-low, c’est-à-dire qu’elle est constamment à 5V, mais chute à 0V pendant les communications. On devra donc, côté logiciel cette fois, inverser à nouveau cette logique.
Circuit d’émission
Le circuit d’émission repose aussi sur un 2N2222A, dont la base est reliée au GPIO13 de l’ESP8266 (D7) par une résistance de 10kΩ (R4).
L’émetteur du transistor est relié à la masse et le collecteur au bus de données.
J’ai constaté qu’en l’absence du récepteur IR externe, le bus de données n’est plus en 5V : on déduit qu’il existe une pull-up dans le circuit d’origine.
Il suffit de remettre une résistance de ce type dans notre montage (10kΩ, R3) pour retrouver une ligne de données à 5V.
Schéma complet
Schéma électronique complet du montage
Attribution : Richard Dern
En haut à gauche, on trouve le connecteur jack femelle, sur lequel on pourra brancher le récepteur IR fourni avec le switch. En dessous, c’est le connecteur mâle qui sera branché au switch. Les trois lignes (alimentation, données et masse) sont reliées, de sorte à pouvoir utiliser le récepteur externe même si l’ESP8266 est inopérant.
R3 sert de pull-up à la ligne de données lorsque l’émetteur externe n’est pas connecté.
Une valeur de 10kΩ est là encore une affaire de compromis : c’est une valeur suffisante pour limiter le courant sur le canal de données, sans perturber le récepteur externe (qui active sa propre pull-up).
Le reste du schéma est finalement assez simple, et pourrait se résumer aux deux transistors.
R1 et R4 visent avant tout à protéger l’ESP8266.
Seule R2 joue un rôle fondamental en assurant le comportement active-low attendu par DATA_BUS, mais du côté de l’ESP.
On la met donc en pull-up entre le collecteur de Q1 et le 3.3V.
Le montage final sur une plaque de prototypage.
Attribution : Richard Dern
Firmware
Comme indiqué précédemment, le but de ce montage est de me permettre de contrôler mon switch USB via le wifi, grâce à Home Assistant. Je me tourne donc vers ESPHome pour “développer” le firmware de mon ESP8266.
# [...]
# La configuration de base se fait automatiquement par ESPHome.
# Seules les lignes ci-dessous sont spécifiques au projet.
remote_receiver:
id: ir_rx
pin:
number: GPIO2
# Parce que notre montage à base de 2N2222A inverse la logique, on doit
# aussi inverser la logique du pin
inverted: True
mode:
input: true
# Veillons à bien désactiver la pull-up interne
pullup: false
# On veut afficher les séquences IR reçues à des fins de debuggage
dump: all
remote_transmitter:
pin:
number: GPIO13
# Ici par contre, on n'inverse pas la logique
inverted: false
mode:
output: true
pullup: false
# On travaille directement sur le fil conducteur, sans passer par un émetteur
# infrarouge, donc on veut toute l'amplitude du signal.
carrier_duty_percent: 100%
button:
- platform: template
name: Mac mini
on_press:
- remote_transmitter.transmit_pronto:
data: "0000 006D 0022 0000 015C 00AD 0017 0015 0017 0015 0017 0015 0017 0015 0017 0015 0017 0015 0017 0015 0017 0040 0017 0040 0017 0040 0017 0040 0017 0040 0017 0040 0017 0040 0017 0040 0017 0015 0017 0015 0017 0015 0017 0040 0017 0015 0017 0015 0017 0015 0017 0015 0017 0015 0017 0040 0017 0040 0017 0015 0017 0040 0017 0040 0017 0040 0017 0040 0017 0041 0017 0180"
- platform: template
name: PC de jeu
on_press:
- remote_transmitter.transmit_pronto:
data: "0000 006D 0022 0000 015C 00AD 0016 0016 0016 0016 0016 0016 0016 0015 0017 0016 0016 0015 0016 0016 0016 0041 0016 0041 0016 0041 0016 0040 0017 0041 0016 0041 0016 0041 0018 0040 0016 0016 0016 0041 0016 0016 0016 0016 0016 0041 0016 0015 001A 0012 0017 0015 0016 0015 0017 0015 0016 0041 0016 0041 0017 0014 0017 0041 0016 0041 0016 0041 0016 0041 0016 0180"
Si l’on fait temporairement abstraction des codes spécifiés en dur, le principe pour les obtenir est assez simple : on compile, on flashe le firmware, et on affiche les logs. Une fois que l’on est connecté à l’ESP8266, on peut appuyer brièvement sur un bouton de la télécommande, ce qui doit provoquer deux choses :
- le changement de canal sur le switch
- l’affichage dans les log de la réception d’une commande via l’infrarouge
Les logs devraient donc ressembler à quelque chose comme ça :
[14:21:34.326][D][remote.beo4:086]: Beo4: n_sym=68
[14:21:34.378][I][remote.pronto:231]: Received Pronto: data=
[14:21:34.379][I][remote.pronto:233]: 0000 006D 0022 0000 015C 00AD 0017 0015 0017 0015 0017 0015 0017 0015 0017 0015 0017 0015 0017 0015 0017 0040 0017 0040 0017 0040 0017 0040 0017 0040 0017 0040 0017 0040 0017 0040 0017 0015 0017 0015 0017 0015 0017 0040 0017 0015
[14:21:34.379][I][remote.pronto:233]: 0017 0015 0017 0015 0017 0015 0017 0015 0017 0040 0017 0040 0017 0015 0017 0040 0017 0040 0017 0040 0017 0040 0017 0041 0017 0180
[14:21:34.379][I][remote.pronto:231]: Received Pronto: data=
[14:21:34.379][I][remote.pronto:233]: 0000 006D 0002 0000 015D 0057 0017 0180
La séquence principale correspondant au bouton appuyé s’affiche aux lignes 3 et 4.
La dernière ligne correspond à une séquence de répétition qui n’a pas d’importance dans notre montage.
Cette séquence de 68 hexadécimaux (n_sym) représente les données brutes que l’on utilisera dans remote_transmitter.transmit_pronto.
Notons que la librairie de décodage identifie notre séquence comme une commande de Beo4. Parfois, elle est identifiée comme une commande NEC. On ne peut pas se fier à cette identification ici : on doit donc travailler avec les données brutes.
Une fois qu’on a renseigné les séquences correspondantes dans nos button, ces derniers devraient être fonctionnels dans l’interface de Home Assistant, et utilisables dans diverses automatisations.
Conclusion
Ce projet m’a fait peur, à plein de niveaux. Je ne savais pas où j’allais : j’avais seulement l’intuition de faire “la bonne chose à faire” (à savoir, exploiter ce lien IR externe pour piloter le switch). J’avais peur de cramer l’ESP8266 ou le switch, de ne pas réussir à émettre un signal approprié, de mettre trop de composants (ou pas assez), etc.
Le fait de ne rien trouver sur Internet était également intimidant. On trouve beaucoup de choses pour piloter des émetteurs/récepteurs infrarouges, mais le matériel employé est déjà prévu pour un usage avec un microcontrôleur, donc pour être branché directement sur les GPIO. Je n’ai rien trouvé sur du matériel fonctionnant avec des tensions différentes, sans protocole clairement défini. D’ailleurs, je n’ai même pas utilisé le document qui m’a été délivré par ezcoo : la possibilité de lire les données brutes via ESPHome l’a rendu inutile.
Il y a six composants électroniques simples dans ce projet, dont la plupart auraient pu être remplacés par des Logic Level Shifters pré-fabriqués. Ça aurait pris une petite après-midi à n’importe quel amateur éclairé. Il m’a pris presque une semaine (mais pas à temps plein…).
J’aurais pu suivre d’autres pistes : démonter le boitier, trouver le circuit sur lequel me mettre pour communiquer directement via un bus série ; j’aurais peut-être même découvert des headers sur lesquels brancher mes GPIO sans plus de cérémonie. Ce que je voulais, c’était une démarche :
- récolter des informations
- concevoir un schéma
- tester (avec une breadboard)
La mise en œuvre concrète est quasiment facultative. Elle constitue un aboutissement, la fin du voyage, et donc la partie la moins intéressante du projet. Ce n’est pas la mise en œuvre qui permet d’apprendre, ce sont les étapes qui la précèdent.
Le boitier intégré, sous le switch. Il y a plus propre (si j’avais une imprimante 3D par exemple), mais ça fonctionne parfaitement bien !
Attribution : Richard Dern
Limites et améliorations futures
Il y a un inconvénient particulier à mon montage : il m’est impossible de savoir, via le wifi, quelle est la source actuellement sélectionnée. Je peux juste le deviner en mémorisant le dernier bouton appuyé dans l’interface de Home Assistant (ou en regardant la LED active sur le switch…), mais ça ne fonctionnera pas si je change de source par infrarouge. Personnellement, je m’en fiche complètement, mais je suis certain que pour d’autres, ça pourrait être problématique.
Intégration réelle
Dans tous les cas, j’ai ajouté avec succès la possibilité de piloter mon switch USB via le wifi. Ça fera l’objet d’un article dans les jours qui viennent, mais sachez que je me suis mis à l’écosystème Hue de Philips, notamment par l’achat d’une HDMI Sync Box 8K. Je la pense avant tout comme un switch HDMI Wifi.
Puisque je peux piloter indépendamment ou conjointement l’USB et le HDMI via le wifi, je dispose de ce que l’on pourrait appeler une matrice KVM USB/HDMI sans-fil, contrôlable avec des protocoles standards via Home Assistant (ou Apple Home), qui offre en plus la possibilité de synchroniser mon éclairage avec ce qui est affiché à l’écran, pour un peu moins de 400 euros.
Et vous, il fait quoi votre KVM ? 😁
Intégration dans mes contrôles Home Assistant : les deux boutons de contrôle correspondent aux entrées du switch. Le bouton Démarrer le PC de jeu fonctionne par Wake-on-LAN, et le reste concerne ma Sync Box. Tout pour piloter ma matrice KVM USB/HDMI par le wifi !
Attribution : Richard Dern