<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://mydil.tala-informatique.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Nigdor</id>
	<title>mydil - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://mydil.tala-informatique.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Nigdor"/>
	<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Sp%C3%A9cial:Contributions/Nigdor"/>
	<updated>2026-04-09T01:18:53Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.39.17</generator>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=111</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=111"/>
		<updated>2018-02-22T20:24:53Z</updated>

		<summary type="html">&lt;p&gt;Nigdor : /* Documentation technique */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
=Projets=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
Trouver des amplis sur ebay.com pas cher de classe AB&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|  &lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=center|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairie C++ !&lt;br /&gt;
&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Fichier:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;/div&gt;</summary>
		<author><name>Nigdor</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=110</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=110"/>
		<updated>2018-02-22T20:23:14Z</updated>

		<summary type="html">&lt;p&gt;Nigdor : /* Flux musical */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
=Projets=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
Trouver des amplis sur ebay.com pas cher de classe AB&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|  &lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=center|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairies C++ !&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Fichier:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Flux musical =&lt;br /&gt;
La communication se fera en générant un flux entre le programme (PC) et l&#039;enceinte (ESP8266). Ce flux, pour des raisons de simplicité, se fera en TCP car ce protocole gère les retransmissions, les tampons d&#039;entrée / sortie, etc... &lt;br /&gt;
&lt;br /&gt;
A terme, une application temps réel comme la musique mériterait de passer sur de l&#039;UDP. Surtout que, si l&#039;on souhaite utiliser du [https://www.tala-informatique.fr/wiki/index.php/Esp8266_udp_server multicast], pour parler à un groupe d&#039;enceintes, on ne peut le faire qu&#039;en UDP !&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
La partie serveur prend un fichier, ici un MP3, lit un morceau du fichier et l&#039;envoi à l&#039;enceinte à travers une socket TCP. Deux paramètres sont à prendre en compte :&lt;br /&gt;
*le temps d&#039;attente entre chaque envoi;&lt;br /&gt;
*la taille d&#039;un morceau;&lt;br /&gt;
Ces paramètres nécessiteront certainement un temps d&#039;ajustement qui sera en fonction de la latence, la congestion du réseau, les capacités des puces impliquées (ici l&#039;ESP8266), etc...&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:warning-icon.png|centré|60px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Les extraits de code qui vont suivre respectent vaguement les préceptes, au combien importants, de la programmation orientée objet et sont fournis à titre indicatif  dans l&#039;unique but de démontrer la faisabilité d&#039;un tel projet ! Voici [[:Media:Iot_Speaker.zip | l&#039;archive]] qui contient le code exposé ci-dessous.&lt;br /&gt;
|}&lt;br /&gt;
=== MusicSender ===&lt;br /&gt;
Voici le contenu du fichier &#039;&#039;MusicSender.class.php&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicSender&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5045;&lt;br /&gt;
&lt;br /&gt;
    // Le temps d&#039;attente en microsecondes entre chaque paquets&lt;br /&gt;
    private static $SLEEP_INTERVAL = 2500;&lt;br /&gt;
&lt;br /&gt;
    // La taille de chacun des paquets&lt;br /&gt;
    private static $CHUNK_BUFFER = 32768;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie le MP3 à l&#039;enceinte&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $mp3File&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function play($mp3File)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_file($mp3File)) {&lt;br /&gt;
            // Ouverture du fichier en lecture binaire&lt;br /&gt;
            $file = fopen($mp3File, &#039;rb&#039;);&lt;br /&gt;
            if ($file === FALSE) {&lt;br /&gt;
                echo &amp;quot;Fail reading file &amp;quot; . $file . &amp;quot;\n&amp;quot;;&lt;br /&gt;
                return FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            // Ouverture de la socket&lt;br /&gt;
            $socket = $this-&amp;gt;openSocket();&lt;br /&gt;
            // Tant qu&#039;on est pas à la fin du fichier&lt;br /&gt;
            while (! feof($file)) {&lt;br /&gt;
                // Envoie d&#039;un &amp;quot;morceau&amp;quot; de taille CHUNK_BUFFER à l&#039;enceinte&lt;br /&gt;
                if (@socket_write($this-&amp;gt;socket, fread($file, self::$CHUNK_BUFFER), self::$CHUNK_BUFFER) === FALSE) {&lt;br /&gt;
                    // Problème de socket (fermeture, déconnexion, etc...)&lt;br /&gt;
                    return FALSE;&lt;br /&gt;
                }&lt;br /&gt;
                usleep(self::$SLEEP_INTERVAL);&lt;br /&gt;
            }&lt;br /&gt;
            // Fermeture de la socket&lt;br /&gt;
            $this-&amp;gt;closeSocket();&lt;br /&gt;
            // Fermeture du fichier&lt;br /&gt;
            fclose($file);&lt;br /&gt;
            return TRUE;&lt;br /&gt;
        }&lt;br /&gt;
        echo $file.&amp;quot; does not exists !\n&amp;quot;;&lt;br /&gt;
        return FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Lit tous les mp3 présents dans le dossier&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $dir&lt;br /&gt;
     */&lt;br /&gt;
    public function readFolder($dir)&lt;br /&gt;
    {&lt;br /&gt;
        if (is_dir($dir)) {&lt;br /&gt;
            // On récupére les fichiers sans les 2 premiers &#039;.&#039; et &#039;..&#039;&lt;br /&gt;
            $files = array_slice(scandir($dir), 2);&lt;br /&gt;
            foreach ($files as $file) {&lt;br /&gt;
                // On créé le chemin absolu&lt;br /&gt;
                $mp3File = $dir . DIRECTORY_SEPARATOR . $file;&lt;br /&gt;
                // On test l&#039;extension&lt;br /&gt;
                if (pathinfo($file)[&amp;quot;extension&amp;quot;] == &amp;quot;mp3&amp;quot;) {&lt;br /&gt;
                    $this-&amp;gt;play($mp3File);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_create_listen() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        if (socket_connect($this-&amp;gt;socket, $this-&amp;gt;ip, self::$PORT) == FALSE) {&lt;br /&gt;
            echo &amp;quot;socket_bind() a échoué : &amp;quot; . socket_strerror(socket_last_error($this-&amp;gt;socket)) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Launch.php ===&lt;br /&gt;
On créé un fichier &#039;&#039;Launch.php&#039;&#039; qui va servir à appeler la classe précédente :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicSender.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$dir = &amp;quot;!!chemin_vers_des_fichiers_mp3!!&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$sender = new MusicSender($esp_ip);&lt;br /&gt;
&lt;br /&gt;
$sender-&amp;gt;readFolder($dir);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Réception : ESP8266 ==&lt;br /&gt;
{|style=&amp;quot;width:650px&amp;quot; align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
[[Fichier:Warning manual.jpg|centré|300px]]&lt;br /&gt;
|valign=&amp;quot;top&amp;quot; align=&amp;quot;justify&amp;quot;|&lt;br /&gt;
Soyez sûr de comprendre la section sur [https://www.tala-informatique.fr/wiki/index.php/Arduino_sketch_writing| comment écrire un sketch] avant de poursuivre. Le code ci-dessous fait référence à des parties bien spécifiques, détaillées et expliquées dans la section suscitée.&lt;br /&gt;
|}&lt;br /&gt;
=== Partie WiFi ===&lt;br /&gt;
La première étape consiste à raccorder notre &#039;&#039;ESP&#039;&#039; au réseau WiFi !&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;ESP8266WiFi.h&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// WiFi Parameters //&lt;br /&gt;
const char ssid[] = &amp;quot;cfcasa&amp;quot;;&lt;br /&gt;
const char password[] = &amp;quot;***********&amp;quot;;&lt;br /&gt;
IPAddress ip(192, 168, 1, 200);&lt;br /&gt;
IPAddress gw(192, 168, 1, 254);&lt;br /&gt;
IPAddress mask(255, 255, 252, 0);&lt;br /&gt;
&lt;br /&gt;
void setup() {&lt;br /&gt;
  // on démarre le port série&lt;br /&gt;
  Serial.begin(115200);&lt;br /&gt;
  // On attend &amp;quot;un peu&amp;quot; que le buffer soit prêt&lt;br /&gt;
  delay(10);&lt;br /&gt;
  // On démarre le WiFi&lt;br /&gt;
  initWiFi();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initWiFi() {&lt;br /&gt;
  // On efface la configuration précédente&lt;br /&gt;
  WiFi.disconnect(true);&lt;br /&gt;
  Serial.printf(&amp;quot;\nConnexion a %s&amp;quot;, ssid);&lt;br /&gt;
  // Initialisation de la connection&lt;br /&gt;
  WiFi.config(ip, gw, mask, gw);&lt;br /&gt;
  WiFi.begin(ssid, password);&lt;br /&gt;
  // Test pour déterminer quand la connection est prete&lt;br /&gt;
  while (WiFi.status() != WL_CONNECTED) {&lt;br /&gt;
    delay(500);&lt;br /&gt;
    Serial.print(&amp;quot;.&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  // Affichage des informations&lt;br /&gt;
  Serial.printf(&amp;quot; connecté\nAdresse IP: %s\n&amp;quot;, WiFi.localIP().toString().c_str());&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Lecteur MP3 ===&lt;br /&gt;
Vient ensuite la partie du lecteur MP3. Dans la partie des imports, ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Parameters //&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
#define VOLUME  70 // volume level 0-100&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
uint8_t volume_level = VOLUME;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le shield MP3&lt;br /&gt;
initMP3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMP3() {&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // Démarrage du lecteur MP3&lt;br /&gt;
  player.begin();&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Récupération du stream MP3 ===&lt;br /&gt;
On va maintenant récupérer le flux envoyé depuis le serveur. Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// MP3 Server parameters //&lt;br /&gt;
const uint16_t MP3_PORT = 5045;&lt;br /&gt;
WiFiServer server(MP3_PORT);&lt;br /&gt;
const uint16_t BUFFER_SIZE = 16384;&lt;br /&gt;
//const uint16_t BUFFER_SIZE = 32768;&lt;br /&gt;
byte buffer[BUFFER_SIZE + 1];&lt;br /&gt;
uint16_t byteRead = 0;&lt;br /&gt;
bool isBufferReady = false;&lt;br /&gt;
WiFiClient client;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction &#039;&#039;setup()&#039;&#039; nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur TCP&lt;br /&gt;
initMp3Server();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void initMp3Server() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  server.begin();&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute TCP sur le port %d\n&amp;quot;, MP3_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void readMp3() {&lt;br /&gt;
  // Un client est connecté&lt;br /&gt;
  if (client) {&lt;br /&gt;
    // Si le client est toujours connecté...&lt;br /&gt;
    if (client.connected()) {&lt;br /&gt;
      // Tant que l&#039;on reçoit de la musique&lt;br /&gt;
      while (client.available() &amp;gt; 0) {&lt;br /&gt;
        // On rempli le buffer avec le contenu du paquet TCP&lt;br /&gt;
        buffer[byteRead++] = client.read();&lt;br /&gt;
        // Si le buffer est plein&lt;br /&gt;
        if (byteRead == BUFFER_SIZE) {&lt;br /&gt;
          // On previent que le buffer est plein&lt;br /&gt;
          isBufferReady = true;&lt;br /&gt;
          // On sort de la boucle&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      // Si le buffer est plein&lt;br /&gt;
      if (isBufferReady) {&lt;br /&gt;
        // On envoi tout au lecteur MP3&lt;br /&gt;
        player.playChunk(buffer, byteRead);&lt;br /&gt;
        // On RAZ le compteur de bytes&lt;br /&gt;
        byteRead = 0;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      // Si le client est déconneté&lt;br /&gt;
      client = server.available();&lt;br /&gt;
      // On prévient que le buffer est vide&lt;br /&gt;
      isBufferReady = false;&lt;br /&gt;
      // On RAZ le compteur de bytes&lt;br /&gt;
      byteRead = 0;&lt;br /&gt;
      Serial.println(F(&amp;quot;Client disconnected&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // On test la présence d&#039;un client&lt;br /&gt;
    client = server.available();&lt;br /&gt;
    if (client) {&lt;br /&gt;
      // Un client est connecté !&lt;br /&gt;
      Serial.println(F(&amp;quot;New client !&amp;quot;));&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Enfin, on ajoute le ligne suivante dans la fonction &#039;&#039;loop()&#039;&#039; :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
readMp3();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A ce stade, l&#039;ESP devrait être capable de récupérer le flux et de le jouer !&lt;br /&gt;
&lt;br /&gt;
= Envoi de commandes =&lt;br /&gt;
Envoyer de la musique c&#039;est bien, pouvoir régler le volume c&#039;est encore mieux !&lt;br /&gt;
&lt;br /&gt;
La façon la plus simple d&#039;adresser le problème c&#039;est d&#039;utiliser un autre port et, comme les messages sont petits, d&#039;utiliser UDP.&lt;br /&gt;
== Partie Serveur ==&lt;br /&gt;
Dans la même veine, voici la classe qui permet d&#039;envoyer les commandes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class MusicHandler&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // L&#039;adresse IP de l&#039;enceinte connectée&lt;br /&gt;
    private $ip;&lt;br /&gt;
&lt;br /&gt;
    // La socket utilisée pour communiquer avec l&#039;enceinte&lt;br /&gt;
    private $socket;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $PORT = 5046;&lt;br /&gt;
&lt;br /&gt;
    // Le port de l&#039;enceinte connectée&lt;br /&gt;
    private static $RETRIES = 3;&lt;br /&gt;
&lt;br /&gt;
    // Liste de commandes&lt;br /&gt;
    private static $CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $CMD_RESET = &#039;R&#039;;&lt;br /&gt;
&lt;br /&gt;
    private static $RESPONSE_NOK = &#039;N&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function __construct($ip)&lt;br /&gt;
    {&lt;br /&gt;
        $this-&amp;gt;ip = $ip;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Augmente le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeUp()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;+&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Baisse le volume d&#039;un incrément&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function volumeDown()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . &amp;quot;-&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function setVolume($volume)&lt;br /&gt;
    {&lt;br /&gt;
        if ($volume &amp;lt; 0 || $volume &amp;gt; 100) {&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME . $volume);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public function getVolume(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_VOLUME);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /**&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    public function doReset()&lt;br /&gt;
    {&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_RESET);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    public function doLocate(){&lt;br /&gt;
        return $this-&amp;gt;sendCommand(self::$CMD_LOCATE);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Envoie une commande au module&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $message&lt;br /&gt;
     */&lt;br /&gt;
    private function sendCommand($message)&lt;br /&gt;
    {&lt;br /&gt;
        $result = false;&lt;br /&gt;
        if ($this-&amp;gt;openSocket() !== FALSE) {&lt;br /&gt;
            if (socket_sendto($this-&amp;gt;socket, $message, strlen($message), 0, $this-&amp;gt;ip, self::$PORT) !== FALSE) {&lt;br /&gt;
                $result = $this-&amp;gt;readAcknoledge();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        $this-&amp;gt;closeSocket();&lt;br /&gt;
        return $result;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Attend la confirmation de la commande&lt;br /&gt;
     *&lt;br /&gt;
     * @return boolean&lt;br /&gt;
     */&lt;br /&gt;
    private function readAcknoledge()&lt;br /&gt;
    {&lt;br /&gt;
        $buf = &amp;quot;&amp;quot;;&lt;br /&gt;
        $retries = 0;&lt;br /&gt;
        while ($retries &amp;lt; self::$RETRIES) {&lt;br /&gt;
            $byteReceived = socket_recvfrom($this-&amp;gt;socket, $buf, 2048, 0, $this-&amp;gt;ip, self::$PORT);&lt;br /&gt;
            if ($byteReceived &amp;gt; 0) {&lt;br /&gt;
                return $buf != self::$RESPONSE_NOK ? $buf : FALSE;&lt;br /&gt;
            }&lt;br /&gt;
            usleep(500000);&lt;br /&gt;
            $retries ++;&lt;br /&gt;
        }&lt;br /&gt;
        return false;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Ouverture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function openSocket()&lt;br /&gt;
    {&lt;br /&gt;
        if (($this-&amp;gt;socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === FALSE) {&lt;br /&gt;
            $errorcode = socket_last_error();&lt;br /&gt;
            $errormsg = socket_strerror($errorcode);&lt;br /&gt;
            echo (&amp;quot;Couldn&#039;t create socket: [$errorcode] $errormsg \n&amp;quot;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Fermeture de la socket&lt;br /&gt;
     */&lt;br /&gt;
    private function closeSocket()&lt;br /&gt;
    {&lt;br /&gt;
        socket_close($this-&amp;gt;socket);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On créé un fichier &#039;&#039;Command.php&#039;&#039; qui va servir à appeler la classe précédente : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
include &#039;MusicHandler.class.php&#039;;&lt;br /&gt;
&lt;br /&gt;
$esp_ip = &amp;quot;192.168.1.200&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
$handler = new MusicHandler($esp_ip);&lt;br /&gt;
&lt;br /&gt;
// Exemple de commandes //&lt;br /&gt;
//$result = $handler-&amp;gt;volumeUp();&lt;br /&gt;
//$result = $handler-&amp;gt;getVolume();&lt;br /&gt;
//$result = $handler-&amp;gt;doReset();&lt;br /&gt;
//$result = $handler-&amp;gt;setVolume(70);&lt;br /&gt;
&lt;br /&gt;
$result = $handler-&amp;gt;doLocate();&lt;br /&gt;
&lt;br /&gt;
echo $result !== FALSE ? &amp;quot;ok : $result\n&amp;quot; : &amp;quot;nok\n&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Partie Cliente ==&lt;br /&gt;
Dans la partie des imports ajoutez la ligne suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;WiFiUDP.h&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Dans la partie des variables statiques ajoutez les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Command Server parameters //&lt;br /&gt;
const uint16_t CMD_PORT = 5046;&lt;br /&gt;
// L&#039;instance du serveur UDP&lt;br /&gt;
WiFiUDP udp;&lt;br /&gt;
// Liste de commandes&lt;br /&gt;
const char CMD_VOLUME = &#039;V&#039;;&lt;br /&gt;
const char CMD_LOCATE = &#039;L&#039;;&lt;br /&gt;
const char CMD_RESET = &#039;R&#039;;&lt;br /&gt;
const char RESPONSE_NOK[] = &amp;quot;N&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// Localisation parameters&lt;br /&gt;
uint8_t ledPin = LED_BUILTIN;&lt;br /&gt;
const uint16_t BLINK_FREQ = 500;&lt;br /&gt;
const uint8_t BLINK_REP = 60;&lt;br /&gt;
uint8_t repetition = 0;&lt;br /&gt;
uint32_t timer;&lt;br /&gt;
bool isLocate = false;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la fin de la fonction setup() nous allons ajouter les lignes suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// On démarre le serveur UDP&lt;br /&gt;
initCmdServer();&lt;br /&gt;
// On prépare la led de localisation&lt;br /&gt;
initLocateLed();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
A la suite, on insère les fonctions suivantes : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool readCmd() {&lt;br /&gt;
  if (udp.parsePacket() &amp;gt; 0) {&lt;br /&gt;
    uint8_t len = udp.available();&lt;br /&gt;
    char c = udp.read();&lt;br /&gt;
    if (len == 1) {&lt;br /&gt;
      if (c == CMD_RESET) {&lt;br /&gt;
        player.softReset();&lt;br /&gt;
        sendPacket(CMD_RESET);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_VOLUME) {&lt;br /&gt;
        sendPacket(volume_level);&lt;br /&gt;
        return true;&lt;br /&gt;
      } else if (c == CMD_LOCATE) {&lt;br /&gt;
        if (!isLocate) {&lt;br /&gt;
          locate(true);&lt;br /&gt;
          sendPacket(CMD_LOCATE);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    } else if (len == 2) {&lt;br /&gt;
      char value = udp.read();&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        if (value == &#039;+&#039; &amp;amp;&amp;amp; volume_level != 100) {&lt;br /&gt;
          setVolume(volume_level + 1);&lt;br /&gt;
        } else if (value == &#039;-&#039; &amp;amp;&amp;amp; volume_level != 0) {&lt;br /&gt;
          setVolume(volume_level - 1);&lt;br /&gt;
        } else {&lt;br /&gt;
          sendNack();&lt;br /&gt;
          return false;&lt;br /&gt;
        }&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    } else {&lt;br /&gt;
      if (c == CMD_VOLUME) {&lt;br /&gt;
        char value[4] = &amp;quot;0&amp;quot;;&lt;br /&gt;
        udp.read(value, 3);&lt;br /&gt;
        uint8_t vol = atoi(value);&lt;br /&gt;
        if (vol &amp;gt;= 0 &amp;amp;&amp;amp; vol &amp;lt;= 100) {&lt;br /&gt;
          setVolume(vol);&lt;br /&gt;
          return true;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    sendNack();&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
  // Check if locate needs to be done&lt;br /&gt;
  locate(false);&lt;br /&gt;
}&lt;br /&gt;
void locate(bool blink) {&lt;br /&gt;
  if (blink) {&lt;br /&gt;
    // Initialisation des variables&lt;br /&gt;
    digitalWrite(ledPin, LOW);&lt;br /&gt;
    isLocate = true;&lt;br /&gt;
    repetition = 0;&lt;br /&gt;
    timer = millis();&lt;br /&gt;
  } else if (isLocate) {&lt;br /&gt;
    // Calcule du temps&lt;br /&gt;
    uint32_t elapsed = millis() - timer;&lt;br /&gt;
    if (elapsed &amp;gt; BLINK_FREQ) {&lt;br /&gt;
      repetition++;&lt;br /&gt;
      if (repetition == BLINK_REP) {&lt;br /&gt;
        // On a atteint le nombre de clignotements&lt;br /&gt;
        isLocate = false;&lt;br /&gt;
        digitalWrite(ledPin, HIGH);&lt;br /&gt;
      } else {&lt;br /&gt;
        // On fait clignoter la led&lt;br /&gt;
        digitalWrite(ledPin, !digitalRead(ledPin));&lt;br /&gt;
        timer = millis();&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setVolume(uint8_t vol) {&lt;br /&gt;
  volume_level = vol;&lt;br /&gt;
  Serial.printf(&amp;quot;Setting volume to %d\n&amp;quot;, volume_level);&lt;br /&gt;
  player.setVolume(volume_level);&lt;br /&gt;
  sendPacket(volume_level);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendNack() {&lt;br /&gt;
  sendPacket(RESPONSE_NOK);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(const char content[]) {&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(content);&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void sendPacket(int content) {&lt;br /&gt;
  char value[4];&lt;br /&gt;
  udp.beginPacket(udp.remoteIP(), udp.remotePort());&lt;br /&gt;
  udp.write(itoa(content, value, 10));&lt;br /&gt;
  udp.endPacket();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initCmdServer() {&lt;br /&gt;
  // Démarrage du serveur TCP&lt;br /&gt;
  udp.begin(CMD_PORT);&lt;br /&gt;
  Serial.printf(&amp;quot;Ecoute UDP sur le port %d\n&amp;quot;, CMD_PORT);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void initLocateLed() {&lt;br /&gt;
  pinMode(ledPin, OUTPUT);&lt;br /&gt;
  digitalWrite(ledPin, HIGH);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
L&#039;ESP est maintenant capable de :&lt;br /&gt;
* monter / baisser le volume ;&lt;br /&gt;
* de faire un reset du lecteur MP3 (en cas de problème)&lt;br /&gt;
* de faire clignoter sa led pour être localisé facilement.&lt;/div&gt;</summary>
		<author><name>Nigdor</name></author>
	</entry>
	<entry>
		<id>https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=100</id>
		<title>Iot speaker</title>
		<link rel="alternate" type="text/html" href="https://mydil.tala-informatique.fr/index.php?title=Iot_speaker&amp;diff=100"/>
		<updated>2018-02-22T14:20:34Z</updated>

		<summary type="html">&lt;p&gt;Nigdor : /* Classe D */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
=Projets=&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;100%&amp;quot;&lt;br /&gt;
|-valign=top&lt;br /&gt;
! Objectif !! Les acteurs !! Compétences !! Matériel&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
Construire des enceintes sans-fils (sauf le courant) actives connectées capables de travailler en &amp;quot;groupe&amp;quot;&lt;br /&gt;
||&lt;br /&gt;
*[[User:Tala | Tala]]&lt;br /&gt;
*[[User:Nigdor |Nigdor]]&lt;br /&gt;
*[[User:Prandar |Prandar]]&lt;br /&gt;
||&lt;br /&gt;
*électronique&lt;br /&gt;
*C++ (microcontrôleur)&lt;br /&gt;
||&lt;br /&gt;
* microcontrôleur (esp8266)&lt;br /&gt;
* amplificateur audio (XPT8871, PAM8403, ...)&lt;br /&gt;
* décodeur MP3 (VS1053B)&lt;br /&gt;
* potentiomètre digital (X9C103S)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Choix de l&#039;amplificateur =&lt;br /&gt;
A faire:&lt;br /&gt;
*Expliquer la différence entre classe AB et D (qualité sonore vs. éco énergie)&lt;br /&gt;
*Faire un tableau récapitulatif des caractéristiques des amplis:&lt;br /&gt;
** mono / stéréo / les deux&lt;br /&gt;
** tension de fonctionnement / consommation (5v, 12v, 24v, etc...)&lt;br /&gt;
** puissance (5w, 20w, 30w, etc...)&lt;br /&gt;
** impédance de sortie (2 x 4Ω, 1 x 8Ω, etc...)&lt;br /&gt;
** réponse fréquentielle ;&lt;br /&gt;
** résistance aux courts-circuits ;&lt;br /&gt;
** bruit pop (quand pas de musique);&lt;br /&gt;
** besoin d&#039;un dissipateur ou non (effet joule à prévoir...)&lt;br /&gt;
** lien vers la documentation si besoin d&#039;info(eg. pour le [https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932])&lt;br /&gt;
** le plus important : le ressenti !&lt;br /&gt;
==Classe AB==&lt;br /&gt;
Trouver des amplis sur ebay.com pas cher de classe AB&lt;br /&gt;
==Classe D==&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! Modèle !! Image !! Phonique !! Puissance !! Impédance !! Tension !! PCC !! POP !! Dissipateur !! Documentation !! Avis&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XH-M531&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XH-M531.jpg|centré|200px]] &lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|  &lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
PAM8403&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8403.jpg|centré|100px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
3W(*2 ?)&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
5V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
Reduit mais présent&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.diodes.com/assets/Datasheets/PAM8403.pdf PAM8403]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:PAM8610.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
XPT8871&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:XPT8871.jpg|centré|120px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TDA8932&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TDA8932.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
2*15W&lt;br /&gt;
|align=center|&lt;br /&gt;
4 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
Entre 10 V et 36 V (Rechercher quel est le plus optimal)&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
&lt;br /&gt;
|align=center|&lt;br /&gt;
[https://www.nxp.com/docs/en/data-sheet/TDA8932B.pdf TDA8932]&lt;br /&gt;
|align=center|&lt;br /&gt;
|-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|align=center|&lt;br /&gt;
TPA3110&lt;br /&gt;
|align=center|&lt;br /&gt;
[[Fichier:TPA3110.jpg|centré|150px]]&lt;br /&gt;
|align=center|&lt;br /&gt;
Stéréo&lt;br /&gt;
|align=center|&lt;br /&gt;
15W/ch&lt;br /&gt;
|align=center|&lt;br /&gt;
8 Ω&lt;br /&gt;
|align=center|&lt;br /&gt;
16 V&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
NON&lt;br /&gt;
|align=center|&lt;br /&gt;
OUI&lt;br /&gt;
|align=center|&lt;br /&gt;
[http://www.ti.com/lit/ds/symlink/tpa3110d2.pdf TPA3110]&lt;br /&gt;
|align=center|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Potentiomètre digital =&lt;br /&gt;
A faire&lt;br /&gt;
&lt;br /&gt;
= Décodeur MP3 =&lt;br /&gt;
==Présentation==&lt;br /&gt;
Le décodeur MP3 choisi est le VS1053&lt;br /&gt;
&lt;br /&gt;
[[Fichier:vs1053_board.jpg|centré|200px]]&lt;br /&gt;
&lt;br /&gt;
Ce décodeur offre une interface SPI et permet de lire ainsi que d&#039;enregistrer des fichiers aux formats :&lt;br /&gt;
* lecture :&lt;br /&gt;
**MP3 ;&lt;br /&gt;
**Ogg Vorbis (libre de droit) ;&lt;br /&gt;
**PCM;&lt;br /&gt;
**WAV;&lt;br /&gt;
* enregistrement :&lt;br /&gt;
**Ogg Vorbis(libre de droit) ;&lt;br /&gt;
&lt;br /&gt;
==Documentation technique==&lt;br /&gt;
Voici la [[:Media:vs1053_doc.pdf|documentation du VS1053]], pour ceux qui voudraient écrire une librairies C++ !&lt;br /&gt;
== Schéma ==&lt;br /&gt;
Les tests ont été réalisés avec un WemOS D1 mini (ESP8266) :&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; width=&amp;quot;85%&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053 !! Connections&lt;br /&gt;
|-valign=top&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:wemos_D1_R2_mini_diagram.png|centré|470px]]&lt;br /&gt;
||&lt;br /&gt;
[[Fichier:vs1053_board_diagram.png|centré|300px]]&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ESP8266 !! VS1053&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XDCS&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XoS (Cable Select)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D3&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DREQ&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D5&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| SCK (Serial ClocK)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D6&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MISO (Master In Slave Out)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| D7&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| MOSI (Master Out Slave In)&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| RST&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| XRST&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| 5V&lt;br /&gt;
|- &lt;br /&gt;
|align=&amp;quot;center&amp;quot;| G&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| DGND&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
Vous devriez avoir quelque chose comme ça :&lt;br /&gt;
&lt;br /&gt;
[[Fichier:wemos_D1_vs1053_diagram.jpg|centré|400px]]&lt;br /&gt;
&lt;br /&gt;
== Programmation ==&lt;br /&gt;
Tout d&#039;abord un grand merci à [https://github.com/baldram/ESP_VS1053_Library &#039;&#039;baldram&#039;&#039;] pour sa [[Fichier:ESP_VS1053_Library.zip|librairie]] que nous allons utiliser !&lt;br /&gt;
&lt;br /&gt;
Le plus simple est de regarder l&#039;exemple &#039;&#039;SimpleMP3Player&#039;&#039; fourni avec la librairie :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// La fameuse librairie de baldram&lt;br /&gt;
#include &amp;lt;VS1053.h&amp;gt;&lt;br /&gt;
// Un MP3 au format binaire dans un tableau (le fichier est livré avec la librairie)&lt;br /&gt;
#include &amp;lt;helloMp3.h&amp;gt;&lt;br /&gt;
// Définition des port SPI utilisé (ici pour l&#039;ESP8266)&lt;br /&gt;
#define VS1053_CS     D1&lt;br /&gt;
#define VS1053_DCS    D0&lt;br /&gt;
#define VS1053_DREQ   D3&lt;br /&gt;
// Définition du volume&lt;br /&gt;
#define VOLUME  80 // volume level 0-100&lt;br /&gt;
// Création de l&#039;objet VS1053&lt;br /&gt;
VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);&lt;br /&gt;
&lt;br /&gt;
void setup () {&lt;br /&gt;
  // Démarrage du SPI&lt;br /&gt;
  SPI.begin();&lt;br /&gt;
  // démarrage du VS1053&lt;br /&gt;
  player.begin();&lt;br /&gt;
  // Ligne nécessaire pour certain lecteur&lt;br /&gt;
  player.switchToMp3Mode();&lt;br /&gt;
  player.setVolume(VOLUME);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void loop() {&lt;br /&gt;
  // On joue le MP3 dans le tableau&lt;br /&gt;
  player.playChunk(helloMp3, sizeof(helloMp3));&lt;br /&gt;
  // On attend 3 secondes&lt;br /&gt;
  delay(3000);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Pour que cet exemple fonctionne, il faut soit copier le contenu de &#039;&#039;HelloMp3.h&#039;&#039; dans le fichier exemple, soit copier le fichier dans le répertoire de la librairie dans votre dossier &#039;&#039;Arduino&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Une fois la compilation terminée, vous devriez entendre &#039;&#039;du bruit&#039;&#039; sortir du VS1053 !&lt;br /&gt;
&lt;br /&gt;
= Communication =&lt;br /&gt;
== Envoi : serveur en PHP ==&lt;br /&gt;
== Réception : ESP8266 ==&lt;/div&gt;</summary>
		<author><name>Nigdor</name></author>
	</entry>
</feed>