Un permutateur de va-et-vient wifi

Forum dédié aux bricolages d'objets connectés IOT et leurs communications avec DomoticZ :
- Remplacement de firmware des prises, modules relais ...
- Fabrication à base d'ESP8266, de NodeMCU, de Weemos et consorts ...
omiagut
Messages : 5
Inscription : 10 juin 2019, 06:37

Un permutateur de va-et-vient wifi

Message par omiagut »

Bonjour à tou(te)s,

Comme c'est mon premier sujet sur ce forum, et que je ne me suis pas frotté au BBCode depuis .... je sollicite par avance la mansuétude des modérateurs.
Permuter des navettes de va-et-vient est un sujet qui apparaît plus souvent comme question que comme réponse, je n'ai d'ailleurs pas trouvé de réponse, c'est pourquoi j'en propose une.
Nous sommes d'accord sur ce qu'est un va-et-vient, disons à la photo p01

Les permutateurs physiques existent, et se branchent sur les navettes, par exemple :

https://www.leschroniquesdegoliath.com/ ... nt-triple/

leur rôle est de croiser/décroiser les navettes.

Pour le faire on utilise une particularité des relais à 3 entrées :
-Com : commun aux 2 autres
-NC : neutre close. Si le relais n'est pas activé (neutre) le fil relié à Com et celui relié à NC sont connectés.
-NO : neutre open. Si le relais n'est pas activé (neutre) le fil relié à Com et celui relié à NO sont déconnectés.
(photos p10 et p20)

donc avec deux relais neutres, les 2 navettes originelles, c'est la photo p40

Si l'on veut que le fil rouge à gauche soit connecté au fil bleu à droite, il faut le brancher comme sur la photo p50
Admettons qu'on initialise la broche de commande à HIGH (digitalWrite(GPIO0, HIGH). Quand on la passe à LOW, le relais déconnecte le fil gauche rouge et le fil droit rouge, et dans le même temps connecte le fil gauche rouge au fil droit bleu par le fil jaune.

Pareil de l'autre côté ( p60)

Si vous le faites avec un Arduino, c'est un simple Blink. Si c'est (un peu) plus compliqué avec un esp8266, c'est que l'Esp8266-01 fonctionne en 3.3V, et la plupart des relais en 5V, je n'ai pas trouvé de relais 3.3V compact. En plus il faut ne pas faire trop grand. Chacun sa solution sans doute, je m'en suis tiré avec cette petite alim qui suffit pour alimenter l'esp et les deux relais+PCB , qui gèrent les tensions en interne. En plus les soudures des broches, de l' alim et COM, NC NO, sont très lisibles, c'est très pratique.

Fils blancs : 220V
Fil rouge : VCC des relais en 5V
Fil noir : GND des relais
Petit fil vieux rose en dessous : lien entre les deux GPIO0 pour commander les 2 relais en même temps.

Dimensions de la boite : 85x45x27 mm

Je l'ai fait un peu dans l'abstrait. Un couple que je connais avait un grave problème : la lumière commandée par les va-et-vient est loin du canapé. Qui se lève quand on s'est installé devant la télé ? Je me rends bien compte que les navettes passant la plupart du temps dans la dalle, trouver le bon endroit pour poser la boite ne doit pas être très simple, mais là, je ne suis pas concerné :)

Je n'ajoute pas les fichiers d'interface, sauf s'ils intéressent quelqu'un, chacun ses habitudes. Rappelons que ces relais sont commandés par la GPIO0. Il vaut mieux l'initialiser sur HIGH, avec un ESP8266-01., et, pour le coup, çà tombe bien.
Mon interface permet de se connecter en AP sans mot de passe. On peut saisir identifiant et mot de passe de sa box. Si l'on réinitialise, on se connecte en mode STA de la box. L'interface elle-même est en html, css et javascript. Si quelqu'un la veut, je mettrai les sources.
Pièces jointes
p100.jpg
p100.jpg (119.88 Kio) Consulté 3782 fois
p90.jpg
p90.jpg (278.22 Kio) Consulté 3782 fois
p80.jpg
p80.jpg (214.41 Kio) Consulté 3782 fois
p70.jpg
p70.jpg (228.08 Kio) Consulté 3782 fois
p60.jpg
p60.jpg (115.39 Kio) Consulté 3782 fois
p50.jpg
p50.jpg (118.64 Kio) Consulté 3782 fois
p40.jpg
p40.jpg (143.34 Kio) Consulté 3782 fois
p10.jpg
p10.jpg (154.08 Kio) Consulté 3782 fois
p20.jpg
p20.jpg (147 Kio) Consulté 3782 fois
p01.jpg
p01.jpg (209.76 Kio) Consulté 3782 fois
garycooper
Messages : 453
Inscription : 07 août 2017, 23:58

Re: Un permutateur de va-et-vient wifi

Message par garycooper »

Bonjour et bravo pour ton installation ! Je suis un peu HS mais pas complètement... J'ai les mêmes kit de relais mais je n'arrive pas à les utiliser. Les as-tu installés avec ESP Easy ou avec un autre firmware ? Peux-tu m'indiquer comment faire pour les exploiter STP ?
Merci 😉
adv
Messages : 580
Inscription : 02 févr. 2016, 13:54
Contact :

Re: Un permutateur de va-et-vient wifi

Message par adv »

Carrément j'ai vu ça ce matin et j'ai repensé à ton cas direct.

De ce que je vois il ne se sert que d'un esp (il a relié le gpio2 de l'esp sur la commande de l'autre carte relais sur laquelle il n'y a pas l'esp).

Et c'est développé avec l'ide arduino si je ne m'abuse ?
Raspberry pi 3 - Domoticz 2024.4 | Piface v.2 + Téléinfo + RFXtrx433E
sondes Oregon | motorisations Somfy Yslo Flex 2 RTS
prises chacon, wifi | Sonoff easyESP, Tasmota, Espurna | ParadoxMG5050
omiagut
Messages : 5
Inscription : 10 juin 2019, 06:37

Re: Un permutateur de va-et-vient wifi

Message par omiagut »

Bonjour garycooper (je n'aurais jamais cru dire çà un jour)
J'ai les mêmes kit de relais mais je n'arrive pas à les utiliser
J'en ai aussi que je ne sais pas utiliser. Un jour jje me suis rendu compte que certains ne fonctionnaient tout simplement pas, même neufs : j'en avais plusieurs, je mettais mon esp dans l'un : çà marchait; dans l'autre : çà ne marchait pas. Depuis je m'approvisionne uniquement chez https://www.ebay.fr/str/techcrunchfr, et si vous n'avez pas de fournisseur attitré, je vous le conseille.
D'autre part, ces relais sont commandés par la GPIO0 de l'esp, celle qu'il faut relier à la masse pour le flasher. J'ai fini par me rendre compte que si j'initialisais la GPIO0 à LOW dans le setup, l'esp se mettait en mode flash ...

Bonjeur adv
Et c'est développé avec l'ide arduino si je ne m'abuse ?
Ben oui, j'aime bien, même si c'est parfois galère à installer. Je n'ai pas mis mes sources pour trois raisons :
- c'est un simple blink, rien de compliqué, il faut créer un serveur.
- j'utilise l 'EEPROM de manière idiote, mais j'ai la flemme de changer.
- j'utilise aussi la SPIFFS pour les fichiers html. Tout le monde n'aime pas, j'ai trouvé l'installation difficile.
non, 4 :
- rien n'est plus pénible que lire le code de quelqu'un d'autre.

En fin de compte, je vais les ajouter en fichiers joints. Pour comprendre,
1 je flash le programme writeEprom qui charge des valeurs fictives d'identifiant et de mot de passe dans l'eprom de l'esp. writeEprom.ino, c_eprom.h et c_eprom.cpp doivent être dans le même dossier, appelé writeEprom (attention à la casse)

2 dans le dossier permut1IO, il doit y avoir un dossier data qui contient les 3 fichiers html. Ces 3 fichiers sont chargés en mémoire SPIFFS par la commande esp8266 scketch data upload du menu Outils.

3 le dossier permut1IO contient donc ce dossier data, et permut1io.ino, mais aussi les même c_eprom.h et c_eprom.cpp que le dossier writeEprom. Je flash ce programme.
permut1io.ino :
teste les valeurs de l'eprom.
si ce sont les valeurs fictives, il crée un ap
sinon il tente de se connectre à la box
çà marche ?
si çà ne marche pas, il crée un ap

Si l'utilisateur rentre de nouveaux identifiants, le mot de passe est testé par une procédure javascript avant d'être réécrite dans l'Eprom
Il faut ré-initialiser l'esp si l'on a changé identifiant et mot de passe.

Vous voyez, l'explication est longue et je n'avais pas envie de la faire dans le vide. Je cite toujours mes source au début. J'attire votre attention sur Circuit4You. Manoj m'a vraiment sorti de la m... quand j'ai passé un mois à essayer de résoudre des problèmes de reset intempestif. Du coup j'ai acheté son bouquin, et c'est lui qui m'a appris à relier la balise form des fichiers html avec le code C++.

Pardon d'avoir été si long, je n'ai pas eu le temps de faire plus court, et là, il faut que j'aille arroser le jardin ... :)

// --------------------------------
// c_eprom.h
// --------------------------------

//
// Section Eprom
// https://zestedesavoir.com/tutoriels/374 ... r-arduino/
//

#include <EEPROM.h>
#include <Arduino.h>

class C_Eprom {
public :
C_Eprom();

void setSsid(String s) {m_ssid = s;}
void setPass(String s) {m_pass = s;}

String ssid() {return m_ssid;}
String pass() {return m_pass;}

void writeEprom(String ssid, String pass);
void readEprom();

private :
// variables d' échange avec Eprom
int l_ssid; // longueur de la chaîne boxSSID sur Erom
int l_pw; // longueur de la chaîne boxPASS sur Eprom
String m_ssid; // ssid de la box
String m_pass; // password de la box
int nextAddr = 0;

void writeInt(int adresse, int val);
int writeString(int adresse, String str);
int readInt(int adresse);
int readStr(int adresse, String &str, int lg);
void writeEprom();
};

// -----------------------------
// c_eprom.cpp
// -----------------------------

#include "c_eprom.h"

C_Eprom::C_Eprom()
{
readEprom();
}

void C_Eprom::writeEprom(String ssid, String pass) {
m_ssid = ssid;
m_pass = pass;
writeEprom();
}

void C_Eprom::readEprom() {
l_ssid = readInt(0x00);
l_pw = readInt(0x02);
nextAddr = readStr(0x05, m_ssid, l_ssid);
nextAddr = readStr(nextAddr, m_pass, l_pw);
}

//
// private
//

void C_Eprom::writeInt(int adresse, int val)
{
//découpage de la variable val qui contient la valeur à sauvegarder en mémoire
unsigned char faible = val & 0x00FF; //récupère les 8 bits de droite (poids faible) -> 0010 1100
//calcul : 1101 0111 0010 1100 & 0000 0000 1111 1111 = 0010 1100

unsigned char fort = (val >> 8) & 0x00FF; //décale puis récupère les 8 bits de gauche (poids fort) -> 1101 0111
//calcul : 1101 0111 0010 1100 >> 8 = 0000 0000 1101 0111 puis le même & qu’avant

//puis on enregistre les deux variables obtenues en mémoire
EEPROM.write(adresse, fort) ; //on écrit les bits de poids fort en premier
EEPROM.write(adresse + 1, faible) ; //puis on écrit les bits de poids faible à la case suivante
EEPROM.commit();

Serial.print(val);
Serial.print(" -> ");
Serial.print(fort);
Serial.print(" - ");
Serial.println(faible);
}

int C_Eprom::writeString(int adresse, String str) {
int adr = adresse;
for (int i = 0; i < str.length(); ++i) {
EEPROM.write(adr + i, (unsigned char) str.charAt(i));
Serial.print((unsigned char) str.charAt(i));
Serial.print(" ");
}
EEPROM.commit();
Serial.println("");
return adresse + str.length();
}

// Lecture d' un int
int C_Eprom::readInt(int adresse)
{
int val = 0 ; //variable de type int, vide, qui va contenir le résultat de la lecture

unsigned char fort = EEPROM.read(adresse); //récupère les 8 bits de gauche (poids fort) -> 1101 0111
unsigned char faible = EEPROM.read(adresse + 1); //récupère les 8 bits de droite (poids faible) -> 0010 1100

//assemblage des deux variable précédentes
val = fort ; // val vaut alors 0000 0000 1101 0111
val = val << 8 ; // val vaut maintenant 1101 0111 0000 0000 (décalage)
val = val | faible ; // utilisation du masque
// calcul : 1101 0111 0000 0000 | 0010 1100 = 1101 0111 0010 1100

return val ; //on n’oublie pas de retourner la valeur lue !
}

int C_Eprom::readStr(int adresse, String &str, int lg) {
for (int i = 0; i < lg; ++i) {
char c = EEPROM.read(adresse + i);
str += c;
}
Serial.println("");
return adresse + lg;
}

void C_Eprom::writeEprom() {
l_ssid = m_ssid.length();
l_pw = m_pass.length();
writeInt(0x00, l_ssid);
writeInt(0x02, l_pw);
nextAddr = writeString(0x05, m_ssid);
nextAddr = writeString(nextAddr, m_pass);
EEPROM.commit();
}

/---------------------------------
writeEprom.ino
/---------------------------------

#include <EEPROM.h>

String ssid = "XXXXXXXX";
String pw = "12345678";

int l_ssid = 0;
int l_pw = 0;
int nextAddr = 0;

void writeInt(int adresse, int val)
{
//découpage de la variable val qui contient la valeur à sauvegarder en mémoire
unsigned char faible = val & 0x00FF; //récupère les 8 bits de droite (poids faible) -> 0010 1100
//calcul : 1101 0111 0010 1100 & 0000 0000 1111 1111 = 0010 1100

unsigned char fort = (val >> 8) & 0x00FF; //décale puis récupère les 8 bits de gauche (poids fort) -> 1101 0111
//calcul : 1101 0111 0010 1100 >> 8 = 0000 0000 1101 0111 puis le même & qu’avant

//puis on enregistre les deux variables obtenues en mémoire
EEPROM.write(adresse, fort) ; //on écrit les bits de poids fort en premier
EEPROM.write(adresse+1, faible) ; //puis on écrit les bits de poids faible à la case suivante
EEPROM.commit();

Serial.print(val);
Serial.print(" -> ");
Serial.print(fort);
Serial.print(" - ");
Serial.println(faible);
}

int writeString(int adresse, String str) {
int adr = adresse;
for (int i = 0; i < str.length(); ++i) {
EEPROM.write(adr+i, (unsigned char) str.charAt(i));
Serial.print((unsigned char) str.charAt(i));
Serial.print(" ");
}
EEPROM.commit();
Serial.println("");
return adresse + str.length();
}

void setup() {
Serial.begin(9600);
EEPROM.begin(512);
delay(2000);
l_ssid = ssid.length();
l_pw = pw.length();

writeInt(0x00, ssid.length());
writeInt(0x02, pw.length());
nextAddr = writeString(0x05, ssid);
nextAddr = writeString(nextAddr, pw);
}

void loop() {
// put your main code here, to run repeatedly:

}

<!--
//----------------------------------------
// index.html
//------------------------------------------
-->

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Lumière !</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<style type="text/css">
.ecran {
background-color: black;
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
}
.button {
position: absolute;
top: 0px;
bottom: 0px;
color : white;
font-size : 500%;
transition-duration : 500ms;
}
.button:hover {
font-size : 900%;
color : white;
}
.button1 {
background-color : #4CAF50;
width : 100%;
height : 80%;
left: 0px;
}
.button3 {
background-color : #4B4BBE;
width : 100%;
height : 20%;
top : 80%;
}
</style>
</head>
<body>
<div class = "ecran">
<form method="get" action="/light">
<input class="button button1" type="submit" name="button" value="Push">
</form>
<form method="get" action="/pass">
<input class="button button3" type="submit" name="button" value="Password">
</form>
</div>
</body>
</html>

<!--
//----------------------------------------
// passPage.html
//----------------------------------------
-->

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Lumière !!</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<script type="text/javascript">
/* contrôle de la saisie
valide si pass = confirm
et si la longueur du pass convient */
function checkPass(pass)
{
var vNewPass = document.getElementById("pass").value;
var lg = vNewPass.length;
if (vNewPass == pass) {
if ((lg >= 8) && (lg <= 64)) {
document.getElementById("Valider").disabled = false;
}
}
}

</script>
<style type="text/css">
.ecran {
color: white;
background-color: #1717b4;
font-size: 120;
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
}
.col1 {
position: absolute;
left: 0%;
}
.col2 {
position: absolute;
left: 33%;
}
.col3 {
position: absolute;
left: 67%;
}
.row {
position: absolute;
width: 98%;
}
.row1 {
position: absolute;
top: 0%;
}
.row2 {
position: absolute;
top: 15%;
}
.tab2 {
position: absolute;
top: 40%;
left: 66%;
}
.bouton {
background-color: #dc8526;
transition-duration : 200ms;
}
.bouton:hover {
background-color: #dcab26;
font-size: 110%;
}
.bouton1 {

}
.bouton2 {
position: relative;
left: 50%;
}
</style>
</head>
<body>
<div class="ecran">
<form method="get" action="/check">
<table>
<tr class="row row1">
<td class="col col1">SSID box</td>
<td class="col col2">Mot de passe</td>
<td class="col col3">Confirmation</td>
</tr>
<tr class="row row2">
<td> <input class="col col1" type="text" id="ssid" name="ssid"> </td>
<td> <input class="col col2" type="password" id="pass" name="pass"> </td>
<td> <input class="col col3" type="password" id="confirm" onInput="checkPass(this.value)"> </td>
</tr>
</table>
<table class="tab2">
<tr>
<td> <input class="bouton bouton1" type="submit" id="Valider" name="button" value="Valider" DISABLED> </td>
<td> <input class="bouton bouton2" type="submit" name="button" value="Annuler"> </td>
</tr>
</table>
</form>
</div>
</body>
</html>

<!--
//----------------------------------------
// staPage.html
//----------------------------------------
-->

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Lumière !</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<style type="text/css">
.ecran {
background-color: black;
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
}
.button {
position: absolute;
top: 0px;
bottom: 0px;
color : white;
font-size : 500%;
transition-duration : 500ms;
}
.button:hover {
font-size : 900%;
color : white;
}
.button1 {
background-color : #4CAF50;
width : 100%;
height : 100%;
left: 0px;
}
</style>
</head>
<body>
<div class = "ecran">
<form method="get" action="/light">
<input class="button button1" type="submit" name="button" value="Push">
</form>
</div>
</body>
</html>

//-------------------------------------------
// permut1io.ino
//-------------------------------------------
//
// https://circuits4you.com/
// https://github.com/esp8266/Arduino
// https://projetsdiy.fr/esp8266-serveur-f ... rs-spiffs/
//
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <FS.h>
#include "c_eprom.h"

#define GPIO0 0
int pushed = 1; // en accord avec la GPIO0 qui doit être HIGH au départ

// identifiants box
C_Eprom c_eprom;
String boxSsid = "";
String boxPass = "";

// ap
IPAddress local_IP(192, 168, 4, 18);
IPAddress gateway(192, 168, 4, 255);
IPAddress subnet(255, 255, 255, 0);
const char* ssid = "ap192.168.4.18_dragon";

ESP8266WebServer server(80);
String webPage;

void setup() {
Serial.begin(9600);
SPIFFS.begin();
retarder(1000); // delay

pinMode(GPIO0, OUTPUT);
digitalWrite(GPIO0, HIGH);

// charge les identifiants de la box depuis la ROM
boxSsid = c_eprom.ssid();
boxPass = c_eprom.pass();
Serial.println(boxSsid);
Serial.println(boxPass);

// se connecte en station si les identifiants de la box sont corrects,
// sinon en point d' accés
if (!toBox()) {
toAp();
}

if (MDNS.begin("dragon")) {
Serial.println("MDNS responder started");
}

server.on("/", handleRoot);
server.on("/light", handleLight);
server.on("/box", handleBox);
server.on("/check", handleCheck);

server.begin();
Serial.println("your server is working");
}

// Equivalent delay avec yield
void retarder(const int x) {
int timer = millis();
while (millis() - timer < x) {
yield();
}
}

// connexion à la box
// si réussie charge la webPage
// et renvoie true
bool toBox() {
if (boxSsid == "XXXXXXXX" || boxPass == "12345678") {
Serial.println("ssid et pass d' origine");
return false;
}

int counter = 0;
WiFi.mode(WIFI_STA);
WiFi.begin(boxSsid.c_str(), boxPass.c_str());

while (counter < 30 && WiFi.status() != WL_CONNECTED) {
Serial.print(".");
retarder(500);
counter++;
}
Serial.println("");
if (WiFi.status() == WL_CONNECTED) {
webPage = createWebPage("/staPage.html");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
return true;
}
else {
Serial.println("ssid et pass à resaisir");
return false;
}
}

// crée un point d' accés si connexion non à la box
// charge la webPage correspondant au point d' accés
boolean toAp() {
WiFi.mode(WIFI_AP);
Serial.println(WiFi.softAPConfig(local_IP, gateway, subnet) ? "Ready" : "Failed!");
WiFi.softAP(ssid);
webPage = createWebPage("/index.html");
}

// charge un fichier .html de la SPIFFS
// dans une chaîne de caractères
String createWebPage(String qHtml) {
String str = "";
File dataFile = SPIFFS.open(qHtml, "r");
for (int i = 0; i < dataFile.size(); i++)
{
str += (char)dataFile.read();
}
dataFile.close();
return str;
}

// connexion à la racine
void handleRoot() {
server.send(200, "text/html", webPage);
}

// appui sur un bouton de la form "light"
// du fichier staPage.html ou index.html
void handleLight() {
String s = server.arg("button");
if (s == "Push") {
pushed = pushed == 0 ? 1 : 0;
digitalWrite(GPIO0, pushed);
}
server.sendHeader("Location", "/");
server.send(302, "text/html", "");
}

// appui sur le bouton "Password" de la form "pass"
// du fichier index.html
void handleBox() {
String boxPage=createWebPage("/staPage.html");
server.send(302, "text/html", boxPage);
}

// appui sur le bouton "valider" de la form "check"
// du fichier passPage.html
// Le fichier passPage.html se charge de valider la saisie (javascript)
void handleCheck() {
String s = server.arg("button");
if (s == "Valider") {
String strSsid = server.arg("ssid");
String strPass = server.arg("pass");
c_eprom.writeEprom(strSsid, strPass); // Mémo dans la ROM
}
server.sendHeader("Location", "/");
server.send(302, "text/html", "");
}

void loop() {
// put your main code here, to run repeatedly:
server.handleClient();
}
Dernière modification par omiagut le 26 juin 2019, 11:00, modifié 1 fois.
garycooper
Messages : 453
Inscription : 07 août 2017, 23:58

Re: Un permutateur de va-et-vient wifi

Message par garycooper »

Merci pour le partage mais c'est trop compliqué pour moi Arduino IDE. À chaque fois que j'ai voulu flasher quelque chose avec ce soft, j'ai galéré...
omiagut
Messages : 5
Inscription : 10 juin 2019, 06:37

Re: Un permutateur de va-et-vient wifi

Message par omiagut »

moi aussi :)
Répondre