L'année 2021 démarre plutôt bien, et j'ai profité des premiers lives Twitch de l'année pour continuer la bidouille de minitels mais aussi pour tenter de convertir deux anciens téléphones à cadrans rotatifs en interphones sans-fil. Tandis que la modification des minitels suit son cours (je viens tout juste de souder le connecteur du clavier du Minitel), la conversion des vieux téléphones en interphones sans-fil se révèle plus problématique que prévu. Petit point rapide dans ce billet des soucis rencontrés, des solutions testées, et de l'avenir de ce projet.
Revenons deux minutes à l'origine de ce projet. On trainait en famille dans un vide-grenier (oui, à l'époque où c'était encore possible) et je suis tombé sur un de ces vieux téléphones à cadran rotatif, ce même type de téléphone que j'utilisais tout petit pour appeler mes grands-parents. Il faut avouer que composer le numéro à 8 chiffres -- dans cet ancien temps la numérotation n'était pas encore à 10 chiffres -- était vraiment amusant: on plaçait le doigt dans le numéro souhaité, puis on faisait tourner le cadran jusqu'en butée, et ce dernier revenait en position initiale en faisant un petit bruit de crécelle. Tout nostalgique que j'étais, j'en ai acheté deux exemplaires pour moins de 10€, avec en tête l'idée de les réhabiliter à la maison.
Dans un premier temps, on souhaitait s'en servir comme second téléphone fixe, mais il s'est avéré que la méthode de génération du numéro composé n'est plus supportée par les réseaux téléphoniques d'aujourd'hui. Le système de numérotation par impulsion de l'ancien temps ne peut donc fonctionner, et il est donc impossible de passer des appels avec ce type de téléphone. Du coup, pourquoi ne pas les transformer en interphones sans-fil ? Tant qu'à faire, autant intégrer de la modernitude dans ces vieilleries ! Et c'est d'un pratique pour appeler les enfants qui jouent dans la mezzanine pour leur demander de mettre le couvert, pardi 😇.
Tout excité à l'idée de réaliser ce projet (on était en 2020 à ce moment là), je teste dans un premier temps si les micros et les hauts-parleurs des téléphones fonctionnent, ce qui est le cas. Puis je connecte un micro à une entrée analogique d'un arduino Nano, et je code un petit programme qui échantillonne le signal en provenance du micro (amplifié avec un module lm386, histoire d'avoir un niveau de signal suffisant) et le retransmet sur le haut-parleur, lui aussi couplé à un module d'amplification similaire. Et miracle, ça fonctionne ! Bon d'accord, le son est pourri, mais ça fonctionne !
La voix humaine varie entre 40 et 1500 Hertz (d'après Musimem), et l'arduino Nano que j'utilisais, cadencé à 16 MHz, ne peut pas échantillonner plus vite que 615 384 échantillons à la seconde, ou plus simplement 615 kHz. C'est plutôt pas mal, mais la résolution sonore est limitée car le convertisseur analogique/numérique (ou ADC) ne produit des valeurs que sur 8 bits au vu de la vitesse d'échantillonnage requise. Ceci dit, le résultat n'était pas trop mal !
Le souci avec un système de communication bi-directionnelle comme un interphone, c'est qu'il faut gérer en même temps la conversion du signal audio en provenance du micro en échantillons numériques, l'envoi de ces échantillons, mais aussi la conversion des échantillons numériques reçus en signal analogique à destination du haut-parleur. Ca veut donc dire faire plein d'autres choses que de l'échantillonnage de la voix, ce qui réduit la vitesse d'échantillonnage effective.
Avec ce premier test réussi, j'ai tenté l'implémentation d'un projet existant (Long Range Arduino Based Walkie Talkie using nRF24L01 [EN]) visant à transmettre de la voix sur du 2.4 GHz, mais sans succès. Comme je m'y attendais, l'arduino voit sa vitesse d'échantillonnage réduite et la piètre résolution du convertisseur analogique/numérique n'arrange pas la qualité sonore. En cherchant un peu plus, je me rends alors compte que je ne suis pas le seul qui s'est cassé la tête sur ce type d'usage, comme le démontre le retour d'expérience de GreatScott!! sur Hacakday [EN].
Il va falloir tester autre chose.
Vu que pas mal de mes connaissances m'ont parlé en bien des systèmes produits par Espressif et notamment la plateforme ESP32, je me suis demandé s'il était possible que ces derniers fassent l'affaire. J'ai pu expérimenter le développement sur ESP32 avec mon projet de smartwatch programmable (la vénérable T-Watch 2020 v1 de Lilygo), et je dois avouer que ça m'a bien bluffé. Je décidais donc de donner sa chance à l'ESP32, et commandais un ESP32 NodeMCU sur Amazon pour prototyper tout ça.
C'est à ce moment là (donc début 2021, si vous suivez) que j'ai commencé à prototyper sur ESP32 lors de lives sur Twitch, et les premiers résultats ont été assez satisfaisants. J'ai réussi à échantillonner le son du micro et à l'envoyer sur le haut-parleur, mais la qualité était juste horrible. Ceci dit, c'était encore acceptable. C'est quand j'ai commencé à interfacer l'ESP32 à un service accessible en WiFi que les choses se sont gâtées. L'envoi du son sur le service distant fonctionnait, mais d'une part la qualité n'était pas merveilleuse du tout, mais de la donnée était perdue et il y avait un décalage énorme (entre 5 à 10 secondes) entre l'échantillonnage par l'ESP32 et la transmission via WiFi.
Alors oui, l'ESP32 ça fonctionne bien, mais il a beaucoup de mal à réaliser en même temps la conversion du signal audio en échantillons numériques et la transmission de ces derniers. Et encore, c'était sans intégrer la convesion numérique/analogique pour la restitution du son sur le haut-parleur. Bref, ça devenait mal engagé. Certes l'ESP32 NodeMCU ne coûte pas bien cher, mais il souffre de plusieurs défauts.
Le premier défaut concerne la conversion numérique/analogique (DAC): la résolution du DAC interne de l'ESP32 est de 8 bits, on ne peut donc coder que des valeurs de 0 à 256, qui constitueront autant de "paliers" dans la tension de sortie et donc une imprécision dans le signal audio restitué. Surtout que la conversion analogique/numérique (ADC) ne souffre pas de cette limitation, la résolution étant de 12 bits. La réduction de 12 bits à 8 bits altère le son de manière significative, et impacte de fait la qualité de la communication. Le second défaut concerne l'électronique du NodeMCU: l'entrée analogique est parasitée par une alimentation du circuit un peu mal fichue, et par l'absence de quelques composants permettant de filtrer l'audio entrant. C'est aussi ce qui ressort des tests qu'a effectué atomic14 dans sa vidéo youtube [EN]: le son est parasité, la qualité sonore très dégradée, et sans prendre en compte la transmission via le réseau !
Encore un fail, mais bon ça m'aura permis de bien prendre en main le dev sur ESP32.
Une des solutions possibles consiste à externaliser la conversion numérique/analogique et analogique/numérique, idéalement en employant des composants permettant d'échantillonner avec une bonne résolution (12 bits dans les deux cas), et fournissant un débit suffisant pour avoir une bonne qualité audio. On pourrait aussi envisager l'emploi d'un microphone I2S (qui fournit directement des échantillons numériques), mais je n'ai pas envie de perdre le grain du microphone du téléphone original.
La solution idéale pour le prototypage consiste à utiliser une carte adaptée, en l'occurence une esp32-lyrat-mini, compatible avec le framework esp-adf d'Espressif. Ce framework est dédié au traitement audio, et cette carte compatible intègre tout ce qu'il faut pour faire la conversion analogique/numérique et numérique/analogique via des composants externes. Elle intègre aussi des filtres adaptés, histoire d'avoir une meilleure qualité sonore. En bref, c'est vraiment une board faite pour cet usage. Comme un crétin, je ne pensais pas devoir en arriver là pour réaliser ce projet, mais je pense que je ne vais pas avoir d'autre choix. J'ai passé commande, on verra dans quelques semaines ce que ça donne 😀.