Go Down

Topic: Envoi de variables avec plusieurs ESP8266 vers un Arduino UNO W5100 (Read 587 times) previous topic - next topic

supercc

tu peux "décortiquer" ligne de la façon suivante:

Code: [Select]

char line[]="s1=23.2 s2=31.6 s3=24.1";  // pour l'exemple
float s1, s2, s3;
sscanf(line,"s1=%f s2=%f s3=%f", &s1, &s2, &s3);


La ligne scanf décode les flottants (%f) et les place dans les variables dont on précise l'adresse.

supercc

Quote
Petit précision dans un second temps, je raccorderais des relais sur les ESP pour activé des relais  mais c'est l'UNO qui décidera en fonction des données reçu par les 2 ESP.
Je vais m'absenter quelques jours alors voici une solution pour avoir, en TCP,  un client récupérant des variables sur un serveur (port 1234), et étant aussi capable de fixer les valeurs d'une variable (sur le serveur).

Dans l'exemple les variables à récupérer sont hum et temp, et la variable à récupérer et à fixer est relais (un entier).

Comme précédemment il faudra que tu renseignes l'IP du serveur et que tu adaptes la connexion filaire pour ta UNO.

Ces codes sont dans un style "à la C". Les messages sont codés/décoder à l'aide des fonctions de la famille printf/scanf (très bien documentées sur Internet). Mais rien n'empêche de véhiculer autre chose et de coder/décoder autrement (je pense à du JSON) tout en utilisant le flux TCP (cf. fonction request).

Bonne chance.

Code du serveur :

Code: [Select]

#include "ESP8266WiFi.h"

#define MAX_LEN 80 // Taille max des questions/réponses
#define DEBUG // a décommenter pour tracer les échanges TCP sur Serial.

const char* ssid = "tonSSID";
const char* password = "tonMDP";
 
WiFiServer wifiServer(1234);

float temp=23.4, hum=80.0;
int relais; // état du relais

void setup() {

  Serial.begin(19200);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) delay(100);
   
  Serial.print("Connected to WiFi. IP:");
  Serial.println(WiFi.localIP());
 
  wifiServer.begin();
}

void loop() {

// attend un client, analyse sa requête et réponds

WiFiClient client = wifiServer.available();
 
if (client) {

char message[MAX_LEN];
char response[MAX_LEN]="";
int len;

if((len=client.readBytesUntil('\n', message, MAX_LEN))) {

message[len]=0; // force la fermeture de la chaîne

// retire l'\n final s'il existe

if(message[strlen(message)-1]=='\n')
message[strlen(message)-1]=0;

#ifdef DEBUG
Serial.printf("server recv:%s\n", message);
#endif

// relais

if(!strncmp(message,"relais=",7)) {
sscanf(message, "relais=%d", &relais);
sprintf(response,"ok");
}

// dump

else if(!strcmp(message,"dump")) {

// peut être le moment de mettre à jour les valeurs des capteurs
// ...
sprintf(response,"relais=%d temp=%.1f hum=%.1f", relais, temp, hum);
}


// Other

else
Serial.printf("ERROR : %s !\n", message);
}

client.printf("%s\n", response);
    }
}



Code du client :

Code: [Select]

#include "ESP8266WiFi.h"
 
#define MAX_LEN 80 // Taille max des questions/réponses
#define DEBUG // a décommenter pour tracer les échanges TCP sur Serial.

const char* ssid = "tonSSID";
const char* password = "tonMDP";

IPAddress server(192, 168, 2, 129); // <- mettre l'IP du serveur

// Pour UNO (enfin je pense)
//EthernetClient client;
//byte server[] = { 192, 168, 2, 129 }; // <- mettre l'IP du serveur


int relais; // état du relais qu'il faut récupérer et fixer
float hum, temp;    // reflet des capteurs du serveur.

void setup()
{
  Serial.begin(19200);
 
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) delay(100);
 
  Serial.print("Connected to WiFi. IP:");
  Serial.println(WiFi.localIP());
}

// Fonction pour un échange de type question/réponse avec un serveur TCP.
// Cette fonction émet message et attend la réponse qu'elle placera dans la chaine response.
// len est la taille allouée pour la réponse (la taille de la chaîne response).

int request(IPAddress server, uint16_t port, char *message, char *response, unsigned len) {

WiFiClient client;

if (client.connect(server, 1234)) {

#ifdef DEBUG
Serial.printf("Client : send : %s\n", message);
#endif

// retire l'\n final s'il existe
if(message[strlen(message)-1]=='\n')
message[strlen(message)-1]=0;

client.printf("%s\n", message);

// attente de la réponse (voir Stream.setTimeout())
if((len=client.readBytesUntil('\n', response, MAX_LEN))) {
response[len]=0; // force la fermeture de la chaîne
// retire l'\n final s'il existe
if(response[strlen(response)-1]=='\n')
response[strlen(response)-1]=0;
#ifdef DEBUG
Serial.printf("Response for %s : %s.\n", message, response);
#endif
}
client.stop();
return 1; // true
}

return 0; // false
}

void loop() {
char message[MAX_LEN];
char response[MAX_LEN];
int len;

// Dump
sprintf(message, "dump", relais);
if(!request(server, 1234, message, response, MAX_LEN))
Serial.printf("ERROR client : no response for : %s\n", message);
else {
//Serial.printf("dump response:%s.\n", response);
if(sscanf(response,"relais=%d temp=%f hum=%f", &relais, &temp, &hum) != 3)
Serial.printf("ERROR client : bad response for dump : : %s\n", response);
else Serial.printf("relais=%d temp=%.1f hum=%.1f\n", relais, temp, hum);
}

// les variables relais, temp et hump reflètent l'état des variables du serveur.
    // En fonction de leurs valeurs on détermine la nouvelle valeur du relais

int relaisNew=0;
//if(temp>30 || hum>80) relaisNew=1;
// ou,  pour forcer un changement d'état du relais (test)
relaisNew=!relais;

if(relaisNew != relais) {
sprintf(message, "relais=%d", relaisNew);
if(!request(server, 1234, message, response, MAX_LEN))
Serial.printf("ERROR client : no response for : %s\n", message);
else if(strcmp(response, "ok"))
Serial.printf("ERROR client : bad response for %s : %s\n", message, response);
}
delay(1000);
}


EDIT : ajout du loop du client.


J4l13n

tu peux "décortiquer" ligne de la façon suivante:

Code: [Select]

char line[]="s1=23.2 s2=31.6 s3=24.1";  // pour l'exemple
float s1, s2, s3;
sscanf(line,"s1=%f s2=%f s3=%f", &s1, &s2, &s3);


La ligne scanf décode les flottants (%f) et les place dans les variables dont on précise l'adresse.
Bonjour,
J'ai vu que le sscanf ne supporte pas les float sur arduino :
https://www.locoduino.org/spip.php?article174 erreur #24


J'ai essayer en int :


Code: [Select]
int *ps1, *ps2, *ps3;
int s1, s2, s3;

void setup()
{
 Serial.begin(9600);

  ps1 = &s1;
  ps2 = &s2;
  ps3 = &s3;

  char line[] = "s1=23.2 s2=31.6 s3=24.1"; // pour l'exemple

  sscanf(line, "s1=%f s2=%f s3=%f", &s1, &s2, &s3);

  Serial.print(*ps1);
  Serial.print(*ps2);
  Serial.println(*ps3);
}

void loop() {
}


Sans succes ...

@+

while(success!=found){
   try++;
   if(fail){
        tryAgain();
}}

kamill

Bonjour,

Comme tu l'as dit %f ne fonctionne pas.
Tu peux passer par des chaines de caractères puis les convertir.
Code: [Select]
float s1, s2, s3;

void setup()
{
 Serial.begin(115200);

  char line[] = "s1=23.2 s2=31.6 s3=24.1"; // pour l'exemple

  char buf1[8],buf2[8],buf3[8];

  sscanf(line, "s1=%s s2=%s s3=%s", buf1, buf2, buf3);

  s1=atof(buf1);
  s2=atof(buf2);
  s3=atof(buf3);
 
  Serial.print(s1); Serial.print("  ");
  Serial.print(s2); Serial.print("  ");
  Serial.println(s3);
}

void loop() {
}

J4l13n

while(success!=found){
   try++;
   if(fail){
        tryAgain();
}}

J4l13n

Il existe pas mal de solutions à base de RASPBERRY PI (Domoticz, Jeedom, HomeGenie, etc.).
Ces serveurs possèdent déjà des fonctionnalités de présentation graphique des températures.

Dans ce cas, les ESP8266 sont clients (en mode veille la plupart du temps donc) et envoient des requêtes JSON au serveur.

Pour Domoticz : https://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Temperature


Bonjour hbachetti,
On peut envoyer les données en ethernet ou wifi de l'arduino vers le rpi ?

@+
while(success!=found){
   try++;
   if(fail){
        tryAgain();
}}

Go Up