# MQTT-DCC ESP32 PlatformIO Project Ce projet cible un ESP32 sous PlatformIO et permet de : - se connecter à un réseau Wi-Fi - se connecter à un broker MQTT - recevoir des commandes d'accessoires DCC au format JSON sur le topic `dcc/command` - générer un paquet DCC et le transmettre sur une alimenation à base de LM18200 via sortie GPIO - publier des retours d'état sur le topic `dcc/status` ## Fonctionnalités principales - Configuration Wi-Fi via un portail web AP si la connexion Wi-Fi échoue - Stockage des identifiants Wi-Fi dans la mémoire non volatile (NVS) - Stockage des identifiants MQTT et nom d'hôte dans la mémoire non volatile (NVS) - Séparation du code Wi-Fi et MQTT dans des modules dédiés - Génération de paquets d'accessoire DCC ## Configuration 1. Ouvrir `include/config.h`. 2. Vérifier ou modifier les paramètres MQTT : - `MQTT_SERVER` - `MQTT_PORT` - `MQTT_TOPIC_CMD` - `MQTT_TOPIC_STATUS` - `MQTT_TOPIC_RESPONSE` 3. Si nécessaire, ajuster les pins DCC : - `DCC_DIR_PIN` - `DCC_PWM_PIN` 4. Le SSID et le mot de passe Wi-Fi sont stockés dans la mémoire non volatile et sont configurables via le portail AP. > Ce projet utilise désormais la librairie `locoduino/DCCpp` pour générer un vrai signal DCC NMRA compatible avec un driver LM18200. > `DCC_DIR_PIN` est utilisé pour le signal DCC et `DCC_PWM_PIN` pour l'activation de l'interface. - Au démarrage, l'ESP tente de se connecter au Wi-Fi avec les identifiants enregistrés. - Si l'accès Wi-Fi n'est pas disponible, il démarre un point d'accès nommé `DCC_Config`. Et permet via un smartphone de définir les SSID / Key à l'aide d'un portail captif - Ouvrir le navigateur à l'adresse IP affichée dans la console série pour configurer le SSID et le mot de passe. - Après enregistrement, l'ESP redémarre et tente de se reconnecter au Wi-Fi. ## Format de commande MQTT Publier un message JSON sur le topic `dcc/command` : ```json { "id": "1234", "address": 123, "state": true } ``` - `id` : identifiant éventuel pour corrélation - `address` : adresse de l'accessoire - `state` : `true` pour activer / `false` pour désactiver ## Exemple Node-RED Dans Node-RED, utilisez un noeud `inject` puis un noeud `mqtt out` : 1. Configurez un noeud `mqtt broker` avec l'adresse de votre broker MQTT. 2. Ajoutez un noeud `inject` et définissez la charge utile (`payload`) avec le JSON ci-dessus. 3. Mettez le `topic` du noeud `mqtt out` à `dcc/command`. 4. Connectez le noeud `inject` au noeud `mqtt out`. Exemple de flux simple : ```json [{"id":"inject_dcc","type":"inject","z":"flow","name":"Commande DCC","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"dcc/command","payload":"{\"id\":\"1234\",\"address\":123,\"state\":true}","payloadType":"json","wires":[["mqtt_out"]]},{"id":"mqtt_out","type":"mqtt out","z":"flow","name":"Envoi MQTT","topic":"dcc/command","qos":"0","retain":"false","broker":"mqtt_broker"}] ``` Cela permet d’intégrer facilement le projet dans un système global basé sur Node-RED. ## Déploiement Compiler et téléverser avec PlatformIO : ```bash pio run -e esp32dev --target upload ``` ## Structure du projet - `src/main.cpp` : programme principal - `src/WifiManager.cpp` : gestion du Wi-Fi et du portail de configuration - `src/MqttManager.cpp` : gestion de la connexion MQTT - `lib/Dcc/` : génération de paquets DCC - `include/config.h` : paramètres de configuration ## Améliorations possibles - ajout d'un vrai générateur NMRA DCC avec horloge de sortie - interface web de configuration plus complète - gestion OTA - publication d'un message de statut plus riche # Annexe - Le DCC Le pilotage des accessoires en DCC classique (NMRA) et via l'écosystème DCC-EX repose sur le même principe fondamental : l'envoi de paquets de données numériques sur les rails (ou un bus dédié) à destination de décodeurs d'accessoires (aiguillages, signaux, relais). Cependant, la manière de spécifier l'Adresse et la Valeur (Commande/État) diffère légèrement selon qu'il s'agit du protocole bas niveau sur les rails ou des commandes textuelles envoyées à une centrale DCC-EX. ## Le Pilotage DCC Classique Dans le standard NMRA (S-9.2.1), les accessoires sont pilotés via des paquets d'accessoires de base (Basic Accessory Decoder Packet). ### L'Adresse Contrairement aux locomotives qui ont une adresse simple (1 à 10239), l'adressage des accessoires en DCC est historiquement découpé : - **L'Adresse de Décodeur** (Decoder Address) : Un décodeur physique d'accessoires (ex: une carte à 4 sorties) possède une adresse principale (1 à 511). - **La Sortie / Pair** (Sub-address / Output) : Chaque décodeur gère généralement 4 sorties (paires d'adresses). - **L'Adresse Unitaire** (Linear / Output Address) : Pour simplifier, les centrales et logiciels traduisent cela en une adresse linéaire continue (1, 2, 3, 4, 5, 6...). On a : ``` Adresse Linéaire = ((AdresseDécodeur - 1) * 4) + Numéro de Sortie ``` ### La Valeur (Position et État) Un paquet d'accessoire DCC ne transmet pas une vitesse (0-128) comme une locomotive, mais un bit de direction et un bit d'activation : - Direction / Position (1 bit) : - 1 = Dévie / Closed / Red / Active (ex: Aiguillage en déviation) - 0 = Droit / Thrown / Green / Inactive (ex: Aiguillage en voie directe) - Power / Enable (1 bit) : - 1 = Bobine sous tension (Commande envoyée) - 0 = Bobine coupée (Relâchement de l'impulsion pour éviter de brûler le moteur solénoïde) ## Le Pilotage avec DCC-EX DCC-EX est un système open-source pour Arduino/ESP32. Il simplifie la complexité des octets NMRA en proposant une API texte très simple via port série, Wi-Fi ou Bluetooth. Dans DCC-EX, les accessoires sont pilotés selon deux approches : **Directe** (numéro de pin ou paquet DCC) ou **Virtuelle** (Turnouts/Routes). ### Méthode 1 : Commande Directe d'Aiguillage / Accessoire DCC Pour envoyer une commande DCC d'accessoire directement sur les rails à une adresse linéaire ``` a ``` ou plus communément pour un aiguillage (Turnout) : ``` > ``` Paramètres : - **ADRESSE** : L'adresse linéaire de l'accessoire (ex: 1 à 2048). - **VALEUR / ÉTAT** : - 1 : Thrown (Dévié / Actif) - 0 : Closed (Droit / Inactif) - C : Toggle / Inverser la position actuelle. Exemple : - -> Met l'aiguillage DCC N°12 en position Déviée (Thrown). - -> Met l'aiguillage DCC N°12 en position Directe (Closed). ### Méthode 2 : Définition des "Turnouts" (Accessoires déclarés dans DCC-EX) DCC-EX permet d'associer des adresses virtuels ou des broches physiques (Servomoteurs, Relais sur Arduino) à des objets "Turnout". Dans le fichier de configuration myAutomations.cpp ou config.h, vous définissez vos accessoires : ```cpp // Aiguillage sur décodeur DCC à l'adresse 5 Turnout::createDCC(5, "Aiguillage Gare"); // Aiguillage piloté directement par un Servomoteur connecté sur la Pin 9 de l'Arduino Turnout::createSERVO(6, 9, 100, 400, 1, "Aiguillage Servo"); ``` Une fois définis, ils se pilotent via le protocole API texte : ``` > ``` - Exemple : (Mettre le Turnout 5 en Thrown). - Exemple : (Mettre le Turnout 5 en Closed).