Cet article propose de commander des appareils de voie depuis une tablette (ou un smartphone, ou un PC) et un browser. Pour ce faire, un ESP32 est utilisé en serveur web, qui, via une box et son réseau wifi va afficher le TCO qui permettra d’établir un itinéraire. Si ce premier article n’utilise qu’un ESP32, les articles suivants mentionneront la possibilité d’utiliser des ESP8266.
TCO Web interactif
TCO Web interactif avec des ESP32 et des ESP8266 (1)
.
Par :
DIFFICULTÉ :★★☆
Le schéma ci-dessous donne le principe de fonctionnement de la solution mise en œuvre.
Le projet met en œuvre un ESP32 serveur HTML B
qui permet de piloter des aiguillages ou autres accessoires de réseau C
à partir d’une tablette ou un smartphone A
. La tablette/smartphone se connecte en wifi au serveur de l’ESP32 B
qui présente une ou plusieurs pages en forme de TCO A
sur lequel des commandes tactiles agissent sur les aiguilles.
Dans l’écran du TCO A
, les appareils de voie sont repérés par une zone jaune qui indique leur état (la direction donnée). Les images des appareils de voie sont cliquables (sur un browser PC) ou touchables (sur un smartphone ou une tablette), ce qui permet de changer leur état (d’obtenir une autre direction).
Enfin, un message de changement d’état est envoyé par le serveur Web B
, qui réaffiche la nouvelle image de l’appareil de voie A
et commande électroniquement le ou les moteurs de l’appareil de voie C
.
Les différents moteurs.
Les moteurs pris en compte disposent, de préférence, des caractéristiques suivantes :
- Alimentation en courant continu ;
- Mouvement lent des aiguilles ;
- Dispositif de coupure de courant en fin de course ;
- Réalimentation des cœurs.
Les moteurs disposant d’autres caractéristiques (alimentation en courant alternatif, servomoteurs, moteurs pas-à-pas, etc.) devront faire l’objet d’adaptations particulières.
La figure suivante présente des exemples de moteurs pouvant convenir :
L’ESP32 sera hébergé sur une carte électronique permettant la commande de 8 moteurs. Le nombre d’appareils de voie pouvant être commandés par ces 8 moteurs se déduit du tableau ci-après.
Avec cette carte électronique, on pourra commander au mieux :
- soit 8 aiguillages simples (gauche, droite ou symétrique) ;
- soit 4 appareils de voie complexes (TJD ou aiguillage triple) ;
- soit entre 5 et 7 appareils de voie de toute sorte.
D’autres types de moteurs sont envisageables comme les moteurs à solénoïdes, à condition qu’ils soient dotés d’un dispositif de coupure de courant en fin de course et d’une réalimentation du cœur de l’appareil. Les moteurs Piko référence 55271 et Roco référence 61195 sont de ce type et peuvent convenir.
Les autres moteurs à solénoïdes, moyennant un supplément d’électronique (relais, redresseur, dispositif de décharge capacitive, etc.) peuvent convenir. Voir le sujet Décodeur pour aiguillage à solénoïdes sur Arduino ou bien Amplifier le signal de sortie d’un ARDUINO avec un ULN 2803. Les moteurs Peco PL10E, PL10W, PL1001, Marklin 74491 ou 74492 sont de cette catégorie.
Le microcontrôleur ESP32
Le choix s’est porté sur le microcontrôleur ESP32 NodeMCU de la société AZ-Delivery. Ce microcontrôleur présente les caractéristiques suivantes :
- Double processeur ;
- Fréquence d’horloge jusqu’à 240 MHz ;
- Mémoire : 512k de RAM, 448k d’EEPROM, 4M de Flash ;
- 38 broches (32 GIOP [1] , 5 pour l’alimentation, 1 Reset/Enable) ;
- Alimentation de 7 à 12V par le régulateur intégré – les processeurs fonctionnant sous 3,3V ;
- Capacités Wifi et Bluetooth (LE ou standard) ;
- Connection aux périphériques grâce à ADC [2], DAC [3], PWM [4], I2C [5], SPI [6], UART [7] , … ;
- Connection avec d’autres ESP par radio (2,4 MHz) avec la technologie ESP-NOW ;
- Basse consommation d’énergie et dispositif de mise en sommeil.
Le brochage de l’ESP32 NodeMCU d’AZ-Delivery est présenté dans la figure suivante. Merci de bien vouloir noter que pour un ESP32 d’un autre modèle ou d’un autre fournisseur, le brochage peut être différent. Veuillez-vous reporter à la documentation normalement fournie avec le microcontrôleur. Dans la suite du document, le nom du microcontrôleur sera abrégé en ESP32.
Plus d’explications sur le fonctionnement des différentes broches se trouve sur le site suivant (en anglais) Random Nerd Tutorials : ESP32 Pinout Reference : Which GPIO pins should you use ?.
L’ESP32 peut être programmé avec l’IDE de l’Arduino. La procédure d’installation de l’ESP32 dans l’IDE est décrite par Jean-Luc dans l’article intitulé Éclairer le réseau (2). Le site Random Nerd Tutorials : Installing ESP32 in Arduino IDE (Windows, Mac OS X, Linux) décrit également (en anglais) la procédure à mettre en œuvre.
Une présentation de l’ESP32 a également été faite dans le sujet Automatisation du pont FLEISCHMANN 6152 (HO) avec un ESP32 (1).
La conception du TCO
Comme dans le sujet Écran couleur tactile Kuman, le TCO est constitué de petites images carrées représentant une portion du réseau pour laquelle les appareils de voie doivent être commandés.
Les différentes images des éléments de construction du TCO sont, pour le moment, hébergées par le site web http://utpeca.free.fr/ dans le sous-répertoire TCO. Le tableau ci-après présente les différents éléments pouvant entrer dans la composition d’un TCO.
De même, les images des éléments correspondants à la rotation des autres éléments de voie existent :
- AigD1_E1_090.png, AigD1_E1_180.png, AigD1_E1_270.png pour l’aiguillage droit ;
- …
- Crois2_E4_090.png, Crois2_E4_180.png, Crois2_E4_270.png pour la TJD2 ;
- …
Pour les lecteurs qui souhaiteraient héberger ces vignettes dans leur propre site Web, ou bien utiliser d’autres technologies (SPIFFS [8], cartes MicroSD, ...), elles sont fournies dans le ZIP ci-après.
Construction du TCO.
Le code HTML pour représenter le TCO de la figure 6 est le suivant :
<table border='0' cellspacing='0' cellpadding='0'><tr>
<tr>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/Sign.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/VirG1_180.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/VirD1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
</tr>
<tr>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/But5.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/AigG1_E1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/Crois2_E1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/But5_180.png'></td>
</tr>
<tr>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/VirD1_180.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>
<td> <img class='img1' src='http://utpeca.free.fr/TCO/But5_180.png'></td>
</tr>
</table>
L’attribut class=’img1’
permet de définir le style (les caractéristiques) de l’affichage des éléments du TCO, comme suit :
<style>
.img1 {border: 0px; width: 64px; height=64px;}
</style>
Cette portion de code doit se trouver dans la section head
du code HTML.
Introduction de l’interactivité.
Le TCO tel qu’il est défini précédemment ne permet pas l’interactivité (c’est-à-dire de commander les appareils de voie). Pour ce faire, il faut remplacer les lignes :
…
<td> <img class='img1' src='http://utpeca.free.fr/TCO/AigG1_E1.png'></td>
…
<td> <img class='img1' src='http://utpeca.free.fr/TCO/Crois2_E1.png'></td>
…
par les lignes suivantes :
…
<td> <a href='javascript:;'
onClick="posApp1=ChangeAig(posApp1, 'Aig1', 'AigG1', '')">
<img class='img1' src='http://utpeca.free.fr/TCO/AigG1_E1.png'
name='imgAig1'></td>
…
<td> <a href='javascript:;'
onClick="posApp2=ChangeTjd(posApp2, 'Tjd2', 'Crois2', '')">
<img class='img1' src='http://utpeca.free.fr/TCO/Crois2_E1.png'
name='imgTjd2'></td>
…
De cette façon, un clic sur l’image de l’appareil de voie (ou un toucher de l’écran) déclenchera l’appel à la fonction Javascript ChangeAig
pour l’aiguillage ou ChangeTjd
pour la TJD.
Le code de la fonction ChangeAig
est le suivant :
function ChangeAig(posApp, kodApp, imgApp, angApp)
{
var posAig = posApp;
var xhr = new XMLHttpRequest();
if ( posAig == "1" )
{
posAig = "2";
document.getElementById("DESC").innerHTML =
" "+kodApp+" : voie déviée";
}
else
{
posAig = "1";
document.getElementById("DESC").innerHTML =
" "+kodApp+" : voie directe";
}
if ( angApp == '' )
{
document.images['img'+kodApp].src=imgWeb+imgApp+'_E'+posAig+'.png';
}
else
{
document.images['img'+kodApp].src=
imgWeb+imgApp+'_E'+posAig+'_'+angApp+'.png';
}
xhr.open("GET", "/update?output="+document.getElementById(kodApp).id+
":A&state="+posAig, true);
xhr.send();
return posAig;
}
Le code des fonctions ChangeTjd
, ChangeAigS
et ChangeAigT
prend en compte les différences d’état des appareils correspondants, mais reste similaire à la fonction ChangeAig
.
Le code à téléverser dans l’ESP32.
Ce programme est basé sur l’exemple fourni par Rui Santos publié sur le site RandomNerdTutorials, à l’adresse suivante https://RandomNerdTutorials.com/esp....
Il comprend, dans l’ordre :
- Les
includes
nécessaires au programme : Wifi, AsyncTCP et ESPAsyncWebServer ; - Les constantes et variables générales du programme (connexion au routeur, état des appareils, etc.) ;
- Une chaîne de caractères contenant les instructions HTML qui seront exécutées sur le serveur ESP32 ainsi que le code Javascript ;
- Un
include
définissant la table des appareils ainsi que le TCO à afficher (code HTML) – ce code est injecté dans la chaîne de caractères vue ci-dessus par la fonctionprocessor
; - Une fonction pour actionner les appareils à la demande de l’utilisateur ;
- La fonction
setup
qui permet la connexion au router, qui envoie la page HTML sur la tablette ou le PC du demandeur et qui récupère l’appareil à positionner ; - La fonction
loop
vide.
Les bibliothèques utilisées.
Il faut tout d’abord importer les bibliothèques prenant en charge un serveur web asynchrone. Ces bibliothèques sont WiFi, AsyncTCP et ESPAsyncWebServer.
// Import required libraries
#include "WiFi.h"
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
Les constantes et variables.
// Connection au routeur wifi (la box)
const char* ssid = "... le nom de votre routeur ...";
const char* password = "... votre mot de passe ...";
// communication entre le serveur et la page HTML (browser)
const char* PARAM_INPUT_1 = "output"; // Nom de l'appareil
const char* PARAM_INPUT_2 = "state"; // Etat de l'appareil
// Adresse du site où sont stockées les images
String img_Web = "http://utpeca.free.fr/TCO/";
// Gestion des 74HC595
const byte verrou = 2; // ST_CP (latch)
const byte donnee = 4; // DS (data)
const byte horloge = 0; // SH_CP (clock)
uint16_t u_Data = 0b0101010101010101; // data pour les 74hc595
const uint16_t k_Msk = 0b1100000000000000; // Masque
const uint16_t k_Dir = 0b0100000000000000; // Moteur direct
const uint16_t k_Dev = 0b1000000000000000; // Moteur dévié
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
La chaîne contenant le code HTML+Javascript.
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>TCO par UTPECA</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<style>
html {font-family: Arial; display: inline-block; text-align: left;}
h2 {font-size: 3.0rem;}
p {font-size: 15px; font-weight: bold; width: 400px; margin-left: 30px;
padding-bottom: 2px; padding-top: 2px; border: 2px solid #6B6B94}
.img1 {border: 0px; width: 64px; height=64px;}
body {max-width: 1280px; margin:0px auto; padding-bottom: 10px;
padding-top: 10px;}
</style>
</head>
<body background='http://utpeca.free.fr/TCO/Pierre.gif' >
<table border='0' width='1280' cellspacing='0' cellpadding='0'>
<tr><td><img border='0' src=’%IMAGE_WEB%Titre2.gif'</td></tr>
<tr><td><img border='0' src=’%IMAGE_WEB%Ligne.gif'</td></tr></table>
%CONSTRUIRE_TCO%
<table><tr><td><img border='0' src='%IMAGE_WEB%Ligne.gif'</td></tr></table>
<p id='DESC'> Manoeuvrez un appareil</p>
<table><tr><td><img border='0' src='%IMAGE_WEB%Ligne.gif'</td></tr></table>
<script>
var imgWeb = '%IMAGE_WEB%';
var posApp1 = '%VALEUR_APP1%';
var posApp2 = '%VALEUR_APP2%';
var posApp3 = '%VALEUR_APP3%';
var posApp4 = '%VALEUR_APP4%';
var posApp5 = '%VALEUR_APP5%';
var posApp6 = '%VALEUR_APP6%';
var posApp7 = '%VALEUR_APP7%';
var posApp8 = '%VALEUR_APP8%';
function ChangeAig(posApp, kodApp, imgApp, angApp)
{
var posAig = posApp;
var xhr = new XMLHttpRequest();
...Comme vu dans le paragraphe "Introduction de l’interactivité"
xhr.open("GET", "/update?output="+document.getElementById(kodApp).id+
":Aig&state="+posAig, true);
xhr.send(); return posAig;
}
function ChangeAigS(posApp, kodApp, imgApp, angApp)
{
...Comme vu dans le paragraphe "Introduction de l’interactivité"
return posAig;
}
function ChangeAigT(posApp, kodApp, imgApp, angApp)
{
...Comme vu dans le paragraphe "Introduction de l’interactivité"
return posAig;
}
function ChangeTjd(posApp, kodApp, imgApp, angApp)
{
...Comme vu dans le paragraphe "Introduction de l’interactivité"
return posTjd;
}
</script>
</body>
</html>
)rawliteral";
Le module de description du TCO (tables des appareils et fonction processor).
D’une manière générale, ce module de description du TCO est un fichier source chargé dans le croquis et contenant du code supplémentaire décrivant la table des appareils, ainsi que la fonction processor. Cette fonction permet d’injecter dans le code HTML la description du TCO et d’injecter dans le code Javascript les données permettant l’interactivité du TCO.
Le croquis fourni avec ce projet comprend quatre définitions de TCO. Le choix de chaque TCO se fait en modifiant le #define
qui va bien (sic) et en recompilant. Par exemple, modifier #define TCO1
par #define TCO3
pour obtenir le TCO nommé PO-Midi1 puis téléverser.
// Prise en compte du fichier source du TCO
/*********************************************************************/
#define TCO1
#ifdef TCO1
#include "Mon_TCO_No01.h"
#endif
#ifdef TCO2
#include "Mon_TCO_No02.h"
#endif
#ifdef TCO3
#include "PO-Midi1.h"
#endif
#ifdef TCO4
#include "Mon_TCO_No04.h"
#endif
Ces TCO sont donnés à titre d’exemple pour permettre au lecteur de produire son propre TCO.
Le code de la description de la table des appareils de voie est donné ci-après.
// Définition de la table des Appareils
/*********************************************************************/
// par TCO_Web (Utpeca) le 24/06/2022
typedef struct
{
char etaApp; // état de l'appareil ( de '1' à '4')
char typApp; // type de l'appareil ('A', 'J', 'T', 'S')
byte noMot1; // No du 1er moteur (de 1 à 8)
byte noMot2; // No du 2me moteur (de 1 à 8)
} appareil;
appareil t_App[NBMOT] =
{
{'1', 'A', 1, 0},
{'1', 'J', 2, 3},
{'1', ' ', 0, 0},
{'1', ' ', 0, 0},
{'1', ' ', 0, 0},
{'1', ' ', 0, 0},
{'1', ' ', 0, 0},
{'1', ' ', 0, 0}
};
Le code de la fonction processor
est comme suit :
// Remplacer %CONSTRUIRE_TCO% par la table des images dans la page web
/*********************************************************************/
String processor(const String& var)
{
if (var == "CONSTRUIRE_TCO")
{
String tco = "";
tco += "<table border='0' cellspacing='0' cellpadding='0'><tr>\n";
tco += "<tr>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/Sign.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1'
src='http://utpeca.free.fr/TCO/VirG1_180.png'> </td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/VirD1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "</tr>\n";
tco += "<tr>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/But5.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <a href='javascript:;'
onClick=\"posApp1=ChangeAig(posApp1, 'Aig1', 'AigG1', '')\">
<img class='img1' src='http://utpeca.free.fr/TCO/AigG1_E1.png'
name='imgAig1'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <a href='javascript:;'
onClick=\"posApp2=ChangeTjd(posApp2, 'Tjd2', 'Crois2', '')\">
<img class='img1' src='http://utpeca.free.fr/TCO/Crois2_E1.png'
name='imgTjd2'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/But5_180.png'></td>\n";
tco += "</tr>\n";
tco += "<tr>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/vide.png'></td>\n";
tco += "<td> <img class='img1'
src='http://utpeca.free.fr/TCO/VirD1_180.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1' src='http://utpeca.free.fr/TCO/H1.png'></td>\n";
tco += "<td> <img class='img1'
src='http://utpeca.free.fr/TCO/But5_180.png'></td>\n";
tco += "</tr>\n";
tco += "</table>\n";
return tco;
}
else if (var == "IMAGE_WEB") { return img_Web; }
else if (var == "VALEUR_APP1") { return String(t_App[0].etaApp); }
else if (var == "VALEUR_APP2") { return String(t_App[1].etaApp); }
else if (var == "VALEUR_APP3") { return String(t_App[2].etaApp); }
else if (var == "VALEUR_APP4") { return String(t_App[3].etaApp); }
else if (var == "VALEUR_APP5") { return String(t_App[4].etaApp); }
else if (var == "VALEUR_APP6") { return String(t_App[5].etaApp); }
else if (var == "VALEUR_APP7") { return String(t_App[6].etaApp); }
else if (var == "VALEUR_APP8") { return String(t_App[7].etaApp); }
else return String();
}
La fonction setup.
Les principales étapes exécutées dans la fonction sont les suivantes :
- Mise en route du moniteur série à la vitesse de 115 200 bauds ;
- Déclarations des broches utilisées pour faire fonctionner les registres à décalage 74HC595 ;
- Initialisation des appareils pour les mettre en conformité avec le TCO affiché ;
- Connexion au réseau wifi avec les paramètres SSID et Mot-de-Passe, puis envoi au moniteur du résultat de la connexion ;
- Envoi de la chaîne de caractères HTML (index_html) complétée par l’exécution de processor au browser via le wifi ;
- Attente de la réponse du browser et si celle-ci est correcte, appel de la fonction CommandeAppareil avec les paramètres véhiculés dans la réponse.
La fonction CommandeAppareil.
Les principales étapes exécutées dans la fonction sont les suivantes :
- Décodage des données renvoyées par le browser au serveur web (nom, type et état de l’appareil ;
- Appel de la fonction
AfficheAppareil
permettant l’affichage sur le moniteur série des informations relatives à l’appareil concerné (la quantité d’information dépendant de l’éventuelle directive DEBUG dans le croquis) ; - Appel de la fonction
ActionneAppareil
effectuant le calcul de la donnée à passer aux registres à décalage 74HC595 qui permettront la mise en route des moteurs adéquats ;
Mise en route du serveur Web.
Une fois le code du croquis téléversé dans l’ESP32, l’écran ci-après s’affiche sur le moniteur série du PC.
Dans la ligne de commande de votre browser, il faut entrer l’adresse IP du serveur Web sous la forme suivante : http://192.168.1.xxx. C’est celle indiquée dans la figure ci-dessus.
La carte électronique et sa mise en œuvre
Le circuit imprimé.
L’implantation des composants.
Liste des composants :
- un ESP32 à 38 broches ;
- un connecteur 12 V (J1), 8 connecteurs 3 bornes vers les moteurs d’aiguillages (M1 à M8) et un strap (fil de câblage) ;
- un réducteur de tension (buck converter) – entrée de 4,5V à 24V) – sortie réglée sur 3,3V ;
- deux 74HC595 et deux ULN2803 ;
- trois condensateurs de découplage (100 nF/35 V).
Le schéma de câblage.
Le schéma de câblage est présenté dans la figure suivante. Les condensateurs de découplage ne sont pas représentés afin d’alléger le schéma.
Le réducteur de tension.
Le réducteur de tension peut être un modèle de base. Il coûte quelques euros sur les sites chinois ou américains vendant du chinois (Amazon, AliExpress, etc.). Il n’a pas de référence précise, mais on peut le retrouver en faisant une recherche "mini-réducteur de tension".
Il faut le préparer comme indiqué dans l’image suivante. Certains fabricants le fournissent avec l’ajustable en fonction, auquel cas il faut couper la piste cuivrée avec un cutter comme indiqué dans la figure. Dans tous les cas, il faut faire un pont de soudure pour avoir 3,3V.
D’autres réducteurs de tension peuvent être utilisés comme le Mini360 ou le MP1584. Cependant, leur mise en œuvre nécessite un multimètre et une adaptation des connexions au circuit imprimé.
Les décodeurs série/parallèle et les réseaux de Darlington.
Le fonctionnement du décodeur série/parallèle 74HC595 est décrit dans le site Arduino Serial to Parallel Shifting-Out with a 74HC595. Il a été également expliqué par Christian dans la fiche pratique du Loco Revue N° 902 d’août 2022.
Le fonctionnement du réseau de Darlington ULN2803 est exposé dans le sujet Amplifier le signal de sortie d’un ARDUINO avec un ULN 2803.
Le branchement des moteurs.
- la broche de gauche (notée Mia) vers la commande de voie directe ;
- la broche centrale au +12V (commun du moteur) ;
- la broche de droite (Mib) vers la commande de voie déviée.
La commande d’un moteur se fait en mettant au niveau bas la sortie correspondante du 74HC595.
Câblage des appareils.
Les deux schémas ci-après indiquent comment câbler l’aiguillage et la TJD contrôlés par le TCO :
Conclusion
Cet article a présenté un TCO économique (pas d’électrotechnique), universel (pour réseau analogique ou DCC) et évolutif, qui pourra inciter le lecteur à construire sa propre solution.
Un deuxième article est en préparation pour présenter une évolution de ce projet : séparation des fonctions Serveur HTML / Commande des Appareils et hébergement des vignettes du TCO dans le serveur HTML plutôt que dans un site Web.
[1] GPIO (ou GIOP) : General Purpose Input/Output pins – broche d’entrée/sortie générale.
[2] ADC : analogic digital convertor – convertisseur analogique digital.
[3] DAC : digital analogic convertor– convertisseur digital analogique.
[4] PWM : pulse wide modulator – modulation de largeur d’impulsion.
[5] I2C : inter integrated circuit – bus série synchrone bidirectionnel half-duplex (origine Philips).
[6] SPI : serial peripheral interface – bus série synchrone full-duplex (origine Motorola).
[7] UART : universal asynchronous receiver/transmitter – émetteur-récepteur asynchrone universel.
[8] SPIFFS : Serial Peripheral Interface Flash File System.