Paramètres de connection Wifi sur carte sd

Bonjour,

Après avoir fait plusieurs wordclocks (arduino nano +ds3231) et je viens d'en faire une autre qui est connectée (en utilisant un wemos d1 mini).

Je voudrais améliorer ce prototype en permettant un changement facile de routeur wifi, sans avoir besoin de revenir dans le code ni d'utilser l' IDE Arduino pour cela.

J'ai donc ajouté un "shield" wemos sd card qui fonctionne sans problème mais je n'arrive pas à convertir les paramètres de connection lus sur la carte sd en paramètres utilisables par

WiFi.begin (ssid, password);

En sachant que lorsque les paramètres sont initialisées à partir du code cela prend cette forme:

char *ssid      = "xxxxxx";               // Set you WiFi SSID
char *password  = "yyyyyyyyyyy";

J'ai lu beaucoup de questions identiques à la mienne sur différents forums anglo-saxons mais malheureusement pas de réponse ou pas de réponse qui fonctionne.

Voici comment je récupère les paramètres lus sur la carte sd et comment j'essaie de les utiliser ensuite:

  // if the file is available, write to it:
  if (myFile) {
    while (myFile.available()) {
      //Serial.write(myFile.read());
      wifiSSID = myFile.readStringUntil('\n');  // copie la chaine jusqu'au retour chariot
      wifiPass = myFile.readStringUntil('\n');
	  Serveur = myFile.readStringUntil('\n');
    }
    myFile.close();
char  wifiSSIDChar[ wifiSSID.length()+1]; // tableau de char de la taille du String ssid+1 (caractère de fin de ligne) 
 wifiSSID.toCharArray( wifiSSIDChar, wifiSSID.length()+1);  // récupère le param dans le tableau de char  
  Serial.print("nom wifi ");
  Serial.println(wifiSSID); // affiche le tableau de char

char  wifiPassChar[ wifiPass.length()+1]; // tableau de char de la taille du String ssid+1 (caractère de fin de ligne) 
 wifiPass.toCharArray( wifiPassChar, wifiPass.length()+1);  // récupère le param dans le tableau de char  
  Serial.print("nom pass ");
  Serial.println(wifiPass); // affiche le tableau de char

  ssid = wifiSSID;
 password = wifiPass;

Lorsque je compile ce code j'obtient l'erreur suivante : "cannot convert 'String' to 'char' in assignment".

Merci de votre aide

Je crois que la classe String ARDUINO ne possède pas d'opérateur direct d'affectation pour un char *.
Il y a une méthode c_str()

Attention, cette méthode retourne l'adresse d'un buffer qui peut devenir invalide si la String est détruite, par exemple si l'objet String est local, sur la pile donc.

Donc soit tu recopies dans une chaîne, soit l'objet String doit être global ou statique.

j'ai fait ceci

//char  wifiSSIDChar[ wifiSSID.length()+1]; // tableau de char de la taille du String ssid+1 (caractère de fin de ligne) 
// wifiSSID.toCharArray( wifiSSIDChar, wifiSSID.length()+1);  // récupère le param dans le tableau de char  
 // Serial.print("nom wifi ");
  //Serial.println(wifiSSID); // affiche le tableau de char

//char  wifiPassChar[ wifiPass.length()+1]; // tableau de char de la taille du String ssid+1 (caractère de fin de ligne) 
 //wifiPass.toCharArray( wifiPassChar, wifiPass.length()+1);  // récupère le param dans le tableau de char  
 // Serial.print("nom pass ");
 // Serial.println(wifiPass); // affiche le tableau de char
// ssid = wifiSSID;
 //password = wifiPass;
 
 ssid = wifiSSID.c_str();
  password=wifiPass.cstr();

mais à la compilation j'ai l'erreur suivante :

invalid conversion from 'const char*' to 'char' [-fpermissive]

J'ai fait une version light de mon code (avec seulement ce qui concerne le wifi et la carte sd)

#include <NTPtimeESP.h>
#include <SPI.h> // liaison avec le shield sd card
#include <SD.h> // gestion sd card

#define DEBUG_ON
NTPtime NTPch("pool.ntp.org");   // Choose server pool as required : time.google.com , fr.pool.ntp.org , ch.pool.ntp.org, pool.ntp.org
strDateTime dateTime;

//char *ssid      = "xxxxxx";               // Set you WiFi SSID
//char *password  = "yyyyyyyyyyy"; 
      
#define PIN           12    //   GPIO12 correspond à la pin D6 DU WEMOS mini D1  . Envoi les datas vers le ruban de leds
#define NUMPIXELS     144     // 144 leds en série



const int chipSelect = D4; // D4 (GPIO2) pin wemos utilisé pour la carte sd
String wifiSSID, wifiPass,Serveur;
char ssid, password ;
   
void setup()
{ 
  Serial.begin(9600); // Open serial communications and wait for port to open:
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  
  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");

  // open the file. note that only one file can be open at a time,so you have to close this one before opening another.
  File myFile = SD.open("wifi.txt");

  // if the file is available, write to it:
  if (myFile) {
    while (myFile.available()) {
      //Serial.write(myFile.read());
      wifiSSID = myFile.readStringUntil('\n');  // copie la chaine jusqu'au retour chariot
      wifiPass = myFile.readStringUntil('\n');
	  Serveur = myFile.readStringUntil('\n');
    }
    myFile.close();
	
	Serial.print("WiFi SSID: ");
      Serial.println(wifiSSID);
      Serial.print("WiFi Pass: ");
      Serial.println(wifiPass); 
	  Serial.print("Serveur NTP: ");
      Serial.println(Serveur); 
	  
//char  wifiSSIDChar[ wifiSSID.length()+1]; // tableau de char de la taille du String ssid+1 (caractère de fin de ligne) 
// wifiSSID.toCharArray( wifiSSIDChar, wifiSSID.length()+1);  // récupère le param dans le tableau de char  
 // Serial.print("nom wifi ");
  //Serial.println(wifiSSID); // affiche le tableau de char

//char  wifiPassChar[ wifiPass.length()+1]; // tableau de char de la taille du String ssid+1 (caractère de fin de ligne) 
 //wifiPass.toCharArray( wifiPassChar, wifiPass.length()+1);  // récupère le param dans le tableau de char  
 // Serial.print("nom pass ");
 // Serial.println(wifiPass); // affiche le tableau de char
// ssid = wifiSSID;
 //password = wifiPass;
 
 ssid = wifiSSID.c_str();
  password=wifiPass.cstr(); 
  
 
  Serial.println(wifiSSID, wifiPass); // affiche le tableau de char  
  Serial.println(ssid,password);
}	

  Serial.println();
  Serial.println("Boot effectué");
  Serial.println("Connection Wi-Fi en cours ");

  WiFi.mode(WIFI_STA);
  WiFi.begin (ssid, password); 
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("WiFi connectée");

} // fin du Setup


void loop()
{
 
} // fin du void loop
char ssid, password ;   // pas bon

// si les objets String sont déclarés en local (dans la fonction loop par exemple)

char ssid[30];             // adapter la longueur
char password[50];     // idem

strcpy(ssid, wifiSSID.c_str());
strcpy(password, wifiPass.c_str());
// ou mieux :
strncpy(ssid, wifiSSID.c_str(), 30);
strncpy(password, wifiPass.c_str(), 50);

// ou : si les objets String sont déclarés statiques ou globaux (en dehors des fonctions)

char *ssid;
char *password;

ssid = wifiSSID.c_str();
password=wifiPass.cstr();

Bonsoir, utilise wifimanager pour changer de wifi sans toucher au code

Bonsoir hbachetti , je te remercie de tes réponses mais malheureusement je ne vois pas encore le bout du tunnel :

En déclarant char ssid et char password en global j'ai à nouveau l'erreur "invalid conversion from 'const char' to 'char' [-fpermissive]"

et en les déclarant en local dans setup l'erreur est la suivante: "incompatible types in assignment of 'const char*' to 'char [30]' "

Est ce que tout cela ne viendrait pas de la librairie SerialESP8266wifi.h qui elle-même est appelée par NTPtime for ESP8266.

Bonsoir CelticLord
j'ai essayé de télécharger les premiers fichiers examples de Wifimanager mais à chaque fois j'ai une erreur : Erreur de compilation pour la carte WeMos D1(Retired)

ma carte est une wemos V3.0.0 certes retired chez wemos mais qui jusque là faisait le job. Après je ne sais pas si ça vient de la carte ou pas.
Demain j'essayerais directement dans mon code pour avoir le coeur net.
Merci.

En déclarant char ssid et char password en global j'ai à nouveau l'erreur "invalid conversion from 'const char' to 'char' [-fpermissive]"
et en les déclarant en local dans setup l'erreur est la suivante: "incompatible types in assignment of 'const char*' to 'char [30]' "

Poste ton code ...

Voici mon code :

#include <NTPtimeESP.h>
#include <SPI.h> // liaison avec le shield sd card
#include <SD.h> // gestion sd card

#define DEBUG_ON
NTPtime NTPch("pool.ntp.org");   // Choose server pool as required : time.google.com , fr.pool.ntp.org , ch.pool.ntp.org, pool.ntp.org
strDateTime dateTime;


#define PIN           12    //   GPIO12 correspond à la pin D6 DU WEMOS mini D1  . Envoi les datas vers le ruban de leds
#define NUMPIXELS     144     // 144 leds en série

const int chipSelect = D4; // D4 (GPIO2) pin wemos utilisé pour la carte sd
String wifiSSID, wifiPass,Serveur;

   
void setup()
{ 
  Serial.begin(9600); // Open serial communications and wait for port to open:
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  
  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");

  // open the file. note that only one file can be open at a time,so you have to close this one before opening another.
  File myFile = SD.open("wifi.txt");

  // if the file is available, write to it:
  if (myFile) {
    while (myFile.available()) {
      //Serial.write(myFile.read());
      wifiSSID = myFile.readStringUntil('\n');  // copie la chaine jusqu'au retour chariot
      wifiPass = myFile.readStringUntil('\n');
	  Serveur = myFile.readStringUntil('\n');
    }
    myFile.close();
	
	Serial.print("WiFi SSID: ");
      Serial.println(wifiSSID);
      Serial.print("WiFi Pass: ");
      Serial.println(wifiPass); 
	  Serial.print("Serveur NTP: ");
      Serial.println(Serveur); 
	  

 char ssid[30];             // adapter la longueur
char password[50];     // idem

strncpy(ssid, wifiSSID.c_str(), 30);
strncpy(password, wifiPass.c_str(), 50);
 
 ssid = wifiSSID.c_str();
  password=wifiPass.cstr(); 
  
 
  Serial.println(wifiSSID, wifiPass); // affiche le tableau de char  
  Serial.println(ssid,password);
}	

  Serial.println();
  Serial.println("Boot effectué");
  Serial.println("Connection Wi-Fi en cours ");

  WiFi.mode(WIFI_STA);
  WiFi.begin (ssid, password); 
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("WiFi connectée");

} // fin du Setup


void loop()
{
 
} // fin du void loop

Bonjour ,
testé Wifimanager dans mon code . J'ai toujours l'erreur de compilation qui apparemment proviendrais de Webserver :

ESP8266WebServer.h:81:8: note: candidate expects 4 arguments, 2 provided

  char ssid[30];             // adapter la longueur
  char password[50];     // idem

  strncpy(ssid, wifiSSID.c_str(), 30);
  strncpy(password, wifiPass.c_str(), 50);
 
  ssid = wifiSSID.c_str();               // pas OK
  password=wifiPass.cstr();          // pas OK

  Serial.println(wifiSSID, wifiPass); // println n'accepte pas deux arguments
  Serial.println(ssid,password);

}	                                          accolade mal placée

Tu fais les choses en double et la deuxième manière de faire n'est pas bonne.

En fait comme tes variables ssid et password sont utilisées dans le setup et nulle part ailleurs, tu pourrais écrire :

char *ssid;
char *password;

ssid = wifiSSID.c_str();
password=wifiPass.cstr();

Bonsoir,

J'ai testé la solution proposée mais j'ai l'erreur :
invalid conversion from 'const char*' to 'char*' [-fpermissive]

le code utilisé est

#include <NTPtimeESP.h>
#include <SPI.h> // liaison avec le shield sd card
#include <SD.h> // gestion sd card

#define DEBUG_ON
NTPtime NTPch("pool.ntp.org");   // Choose server pool as required : time.google.com , fr.pool.ntp.org , ch.pool.ntp.org, pool.ntp.org
strDateTime dateTime;


#define PIN           12    //   GPIO12 correspond à la pin D6 DU WEMOS mini D1  . Envoi les datas vers le ruban de leds
#define NUMPIXELS     144     // 144 leds en série

const int chipSelect = D4; // D4 (GPIO2) pin wemos utilisé pour la carte sd
String wifiSSID, wifiPass,Serveur;


   
void setup()
{ 
 char *ssid;
char *password;

  Serial.begin(9600); // Open serial communications and wait for port to open:
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  
  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");

  // open the file. note that only one file can be open at a time,so you have to close this one before opening another.
  File myFile = SD.open("wifi.txt");

  // if the file is available, write to it:
  if (myFile) {
    while (myFile.available()) {
      //Serial.write(myFile.read());
      wifiSSID = myFile.readStringUntil('\n');  // copie la chaine jusqu'au retour chariot
      wifiPass = myFile.readStringUntil('\n');
	  Serveur = myFile.readStringUntil('\n');
	 
		 
	ssid = wifiSSID.c_str();
	password=wifiPass.c_str();	 
    }
    myFile.close();
	
	
	

        }
        Serial.println("");
		
  Serial.println();
  Serial.println("Boot effectué");
  Serial.println("Connection Wi-Fi en cours ");

  WiFi.mode(WIFI_STA);
  WiFi.begin(( char)ssid), ( char)pass);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("WiFi connectée");

} // fin du Setup


void loop()
{
 
} // fin du void loop
    const char *ssid;
    const char *password;

Bonjour,

maintenant l'erreur est différente :

cast from 'const char*' to 'char' loses precision [-fpermissive]

  WiFi.begin(( char)ssid), ( char)pass); // pourquoi caster en char ???
                                          // et pass n'existe pas

  WiFi.begin(ssid, password); // ok

Comprends-tu la différence entre un char, un char[] et un char * ?

char c; // un caractère unique
char s[10]; // une chaîne de 10 caractères (normalement le dernier est un terminateur et vaut '\0')
char *p; // un pointeur sur un caractère ou une chaîne de caractères

p = s; // ok
p = &c; // ok

La méthode WIFI.begin attend deux chaînes, pas deux caractères.

Tu as vraiment besoin d'un tuto sur le sujet : http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.ChainesCaracteres

Bon j'essaye d'avancer dans ma compréhension des char mais il y a toujours quelque chose en plus : [ ] par exemple, ou en moins * par exemple pour le lien donné précédemment.
Pour l'instant je n'ai pas réussi à trouver une doc qui soit vraiment exhaustive sur le sujet.

Sinon la bonne nouvelle c'est maintenant le code compile.

La mauvaise nouvelle c'est que la connexion wifi ne se fait pas. Je pense que les arguments ssid et/ou password ne sont pas corrects car avec la connexion se fait avec le même code si on utilise les identifiants provenant du code au lieu de ceux provenant de la carte sd.

Pourtant ce je vois en sortie de Serial.print est identique.

Je vais tenter d'autres méthodes pour comparer les chaines . strcmp( ssid, ssid2) par exemple

Dans les deux cas (ssid et password) la comparaison avec strcmp () me retourne la 13 .
Si j'ai bien compris ce retour est la différence entre les valeurs ASCII à l'emplacement où les chaines deviennent différentes.
est ce que cela veut dire que l'une des deux chaines comparées se termine par /0 et l'autre par CR (13 en ascii) ?

readStringUntil('\n') doit lire jusqu'à \n inclus (je l'interprète comme ça; la doc n'est pas claire)
Si mon interprétation est valide (et j'espère qu'il n'y a pas de '\r' pour compliquer les choses), le derneir caractère lu est donc \n (et derrière, il y a \0)
la chaine c qui en est déduite devrait se terminer par \0 et non par \n
chaine[strlen[chaine) -2 ] = '\0' ; // devrait règler le problème..

Non, j'ai regardé dans le code, le '\n' n'est pas inclus.

Je fais tilt en retard :

Si tu es sous Windows, un éditeur comme notepad ajoute '\r' + '\n' à la fin de chaque ligne.

Conserve quand même le readStringUntil('\n') car le '\n' sera présent quel que soit l'éditeur.

Quand la lecture de tes paramètres SD est faite :

  // trim() sur la String
  wifiSSID = myFile.readStringUntil('\n');
  wifiSSID.trim();                     // ça enlève les blancs et je pense aussi les '\n' et '\r'
  ssid = wifiSSID.c_str();

Fais la même chose pour password.
C'est juste un soupçon.

Si c'est un soupçon, c'est bien trouvé:

:trim retire les espaces en début et en fin de chaîne; pour ce faire, il fait appel à isspace, dont le manuel dit "man isspace"

RETURNS
isspace' returns non-zero if C is a space, tab, carriage return, new line, vertical tab, or formfeed (0x09'-0x0D', 0x20').

Si les fonctions liées à l'IDE Arduino obeissent au manuel, on peut être sûr que les \n et \r éventuels seront enlevés....