Go Down

Topic: problema a far digerire i parametri wifi alla scheda esp8266 (Read 1 time) previous topic - next topic

FabrizioVC65

Ciao a tutti/e
Sto cercando di gestire la configurazione della esp8266 tramite un file txt su scheda SD
Nessun prb per la lettura dei file su SD, ma quando passo le stringhe come parametri di configurazione WIFI non si connette più alla rete.

Se uso questo codice funziona tutto:
Code: [Select]

  char* ssid = "nomerete";
  char* password = "password_rete";
  char* deviceName = "nome_device";

  IPAddress staticIP(192, 168, 1, 100); //ESP static ip
  IPAddress gateway(192, 168, 1, 1);   //IP Address of your WiFi Router (Gateway)
  IPAddress subnet(255, 255, 255, 0);  //Subnet mask
  IPAddress dns(8, 8, 8, 8);  //DNS

  Serial.println("Avvio configurazione del WiFi...");
  WiFi.hostname(deviceName);
  WiFi.config(staticIP, subnet, gateway, dns);
  WiFi.begin(ssid, password);
  
  // Wait for connection
  Serial.print("Wait for wifi connection");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());



se uso il mio codice non si connette alla rete, presumo sia un prb di conversione delle stringhe SSID e PASSWORD:
Code: [Select]

  if (!SD.begin(chipSelect)) {
    Serial.println("SD initialization failed!");
    return;
  }
  cfgFile = SD.open("cfgwifi.txt");
  if (cfgFile) {
    Serial.println("cfgwifi.txt:");
    int conta = 0;
        
    while (cfgFile.available()) {
      
      txtBuffer = "";
      txtBuffer = cfgFile.readStringUntil('n');
      if(txtBuffer == "")
      {
        Serial.println("break");
        break;
      }
      
      conta ++;
      switch (conta) {
        case 1:
          ssid = txtBuffer;
          Serial.print("ssid: ");
          Serial.println(ssid);
          break;
        case 2:
          password = txtBuffer;
          Serial.print("password: ");
          Serial.println(password);
          break;
        case 3:
          deviceName = txtBuffer;
          Serial.print("deviceName: ");
          Serial.println(deviceName);
          break;
        case 4:
          gateway.fromString(txtBuffer);
          Serial.print("gateway: ");
          Serial.println(gateway);
          break;
        case 5:
          subnet.fromString(txtBuffer);
          Serial.print("subnet: ");
          Serial.println(subnet);
          break;
        case 6:
          dns.fromString(txtBuffer);
          Serial.print("dns: ");
          Serial.println(dns);
          break;
        case 7:
          staticIP.fromString(txtBuffer);
          Serial.print("staticIP: ");
          Serial.println(staticIP);
          break;
        default:
          break;
      }
    }
    // close the file:
    cfgFile.close();
  } else {
    Serial.println("errore apertura cfgwifi.txt");
  }

  Serial.println("Avvio configurazione del WiFi...");
  WiFi.hostname(deviceName);
  WiFi.config(staticIP, subnet, gateway, dns);
  WiFi.begin(ssid, password);
  
  // Wait for connection
  Serial.print("Wait for wifi connection");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());


sul monitor seriale si ferma a :
"Wait for wifi connection ..............." (continuando a scriver puntini in attesa di una connessione valida)

Cosa sto sbagliando?

Grazie in anticipo

Federico66

Ciao a tutti/e
Sto cercando di gestire la configurazione della esp8266 tramite un file txt su scheda SD
Nessun prb per la lettura dei file su SD, ma quando passo le stringhe come parametri di configurazione WIFI non si connette più alla rete.
ma sul monitor seriale, leggi correttamente i dati letti?

Perchè se l'intenzione è leggere fino a fine riga, qui c'è un errore

Code: [Select]

txtBuffer = cfgFile.readStringUntil('n');


dovrebbe essere '\n' e non 'n', che poi in ogni caso dipende da come hai salvato il file, potrebbe essere \r\n, e allora devi gestirlo in maniera diversa;

se uso il mio codice non si connette alla rete, presumo sia un prb di conversione delle stringhe SSID e PASSWORD
forse mi sbaglio (mancano le definizion), ma se usi readStringUntil, immagino, txtBuffer sia definita String , e ssid sia definita char*, come riesci a fare questo senza che il compilatore dia errore?

Code: [Select]

ssid = txtBuffer;


Dai un'occhiata qui, ma, a prescindere dall'errore, prova a non usare l'oggetto String, usa solo le stringhe C

Federico
"La logica vi porterà da A a B. L'immaginazione vi porterà dappertutto." A. Einstein

Salvorhardin

Sempre una scintilla

Dal Dinamico Duo

FabrizioVC65

Alla fine ho risolto così:
Code: [Select]
String txtBuffer;
const byte cs = 4;
char ssid[20];
char pass[20];
char deviceName[20];
byte i;
File dataFile;

IPAddress staticIP;
IPAddress gateway;
IPAddress subnet;
IPAddress dns;

void setup(void){
  pinMode(led, OUTPUT);
  digitalWrite(led, 0);
  Serial.begin(115200);
 
  if (!SD.begin(chipSelect)) {
    Serial.println("SD initialization failed!");
    return;
  }else{
    //recupero la pssword
    dataFile = SD.open("password.txt");
    while (dataFile.available()) pass[i++] = dataFile.read();
    pass[i] = '\0'; // mark end
    dataFile.close();
    i=0;
    //recupero il nome  SSID
    dataFile = SD.open("SSID.txt");
    while (dataFile.available()) ssid[i++] = dataFile.read();
    ssid[i] = '\0'; // mark end
    dataFile.close();
    i=0;
    //recupero il DeviceName
    dataFile = SD.open("deviceName.txt");
    while (dataFile.available()) deviceName[i++] = dataFile.read();
    deviceName[i] = '\0'; // mark end
    dataFile.close();
    i=0;
    //recupero indirizzi IP
    dataFile = SD.open("cfgwifi.txt");
    if (dataFile) {
      Serial.println("  leggo cfgwifi.txt:");
      int conta = 0;
      while (dataFile.available()) {
       
        txtBuffer = "";
        txtBuffer = dataFile.readStringUntil('\n');
        Serial.println(txtBuffer);
        if(txtBuffer == "")
        {
          Serial.println("break");
          break;
        }
        conta ++;
        switch (conta) {
          case 1:
            gateway.fromString(txtBuffer);
            Serial.print("read gateway: ");
            Serial.println(gateway);
            break;
          case 2:
            subnet.fromString(txtBuffer);
            Serial.print("read subnet: ");
            Serial.println(subnet);
            break;
          case 3:
            dns.fromString(txtBuffer);
            Serial.print("read dns: ");
            Serial.println(dns);
            break;
          case 4:
            staticIP.fromString(txtBuffer);
            Serial.print("read staticIP: ");
            Serial.println(staticIP);
            break;
          default:
            break;
        }
      }
    // chiudo il file:
    dataFile.close();
   } else {
    Serial.println("errore apertura cfgwifi.txt");
   } 
  }
 
 
  Serial.println();
  Serial.println("Avvio configurazione del WiFi...");
  WiFi.hostname(deviceName);
  WiFi.config(staticIP, subnet, gateway, dns);
  WiFi.begin(ssid, pass);

  // Wait for connection
  Serial.print("Wait for wifi connection");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

 
}


Ho optato per la soluzione di diversi file txt per password e SSID e un solo file per gli IPAddress.
Mi chiedevo... per snellire il codice non sarebbe possibile, secondo voi, riunire Password e SSID in un singolo file? Penso di si ... ma come li devo leggere se scritti su diverse righe?

Federico66

Ho optato per la soluzione di diversi file txt per password e SSID e un solo file per gli IPAddress.
Pur di non utilizzare la funzione la funzione toCharArray :(

che si usa cosi
Code: [Select]

//converte (trasferisce) 19 car. dalla stringa txtBuffer nell'array pass
txtBuffer.toCharArray(pass, 20);



Mi chiedevo... per snellire il codice non sarebbe possibile, secondo voi, riunire Password e SSID in un singolo file? Penso di si ... ma come li devo leggere se scritti su diverse righe?
in realtà tutti i dati che ti servono li puoi mettere in un solo file, compresi gli ip.

Code: [Select]

const byte max_chars = 21;
char buffer[max_chars]; 
byte line_idx = 0;
byte char_idx = 0;

char pass[max_chars];
char ssid[max_chars];
 
while (file.available() > 0) {
  char rc = file.read();
  if (rc == '\n') {
    buffer[char_idx] = '\0';
    switch (line_idx) {
      case 0: //prima linea
        strcpy(ssid, buffer);
        break;
      case 1: //seconda linea
        strcpy(pass, buffer);
        break;
        //... e cosi via
    }
    line_idx++;
    char_idx = 0;
  } else if (rc == '\r') {

  } else {
    buffer[char_idx] = rc;
    char_idx++;
    if (char_idx >= max_chars)
      char_idx = max_chars - 1;
    }
}


Scritto al volo, potrebbero esserci errori, ma spero ti spinga a studiare e provare.

Federico


"La logica vi porterà da A a B. L'immaginazione vi porterà dappertutto." A. Einstein

FabrizioVC65

Grazie per le idee,
purtroppo c'è ancora qualcosa che non va.
In realtà l'esempio di Federico66 funziona ma solo per Pass e SSID che sono variabili char
Gli indirizzi IP nelle dichiarazioni sono "IPAddress" (se non sbaglio char*)
Quindi devo distinguere i 2 gruppi di variabili con 2 contenitori diversi.

Ad ogni modo la strada che avevo scelto funziona al 90%, la cosa che mi sfugge è che nell'importare la stringa  degli indirizzi IP mi succede questo:

Code: [Select]
gateway.fromString(txtBuffer);

Serial.println(txtBuffer); >> 192.168.1.1

Serial.println(gateway); >> 192.168.1.0


Da dove c.... arriva quello 0 finale? :(

Federico66

In realtà l'esempio di Federico66 funziona ma solo per Pass e SSID che sono variabili char
Sei sicuro?

Gli indirizzi IP nelle dichiarazioni sono "IPAddress" (se non sbaglio char*)
E quindi?

Federico
"La logica vi porterà da A a B. L'immaginazione vi porterà dappertutto." A. Einstein

FabrizioVC65

Sei sicuro?

E quindi?

Federico

questo è il tuo codice:

Code: [Select]
const byte max_chars = 21;
char buffer[max_chars];
byte line_idx = 0;
byte char_idx = 0;
char pass[max_chars];
char ssid[max_chars];
char deviceName[max_chars];

File file;
//IPAddress
char staticIP[max_chars];
char gateway[max_chars];
char subnet[max_chars];
char dns[max_chars];

void setup(void){

    file = SD.open("cfg/cfgfile.txt");
    while (file.available() > 0) {
    char rc = file.read();
    if (rc == '\n') {
      buffer[char_idx] = '\0';
      switch (line_idx) {
        case 0:
          strcpy(ssid, buffer);
          break;
        case 1:
          strcpy(pass, buffer);
          break;
        case 2:
          strcpy(deviceName, buffer);
          break;
        case 3:
          strcpy(gateway, buffer);
          break;
        case 4:
          strcpy(subnet, buffer);
          break;
        case 5:
          strcpy(dns, buffer);
          break;
        case 6:
          strcpy(staticIP, buffer);
          break;
      }
      line_idx++;
      char_idx = 0;
    } else if (rc == '\r') {
 
    } else {
      buffer[char_idx] = rc;
      char_idx++;
      if (char_idx >= max_chars)
        char_idx = max_chars - 1;
      }
    }


  WiFi.hostname(deviceName);
  WiFi.begin(ssid, pass); 
  WiFi.config(staticIP, subnet, gateway, dns);



questa è la risposta dell'IDE:

error: conversion from 'char [21]' to 'IPAddress' is ambiguous

   WiFi.config(staticIP, subnet, gateway, dns);


Federico66

questo è il tuo codice:
...
questa è la risposta dell'IDE:
error: conversion from 'char [21]' to 'IPAddress' is ambiguous
   WiFi.config(staticIP, subnet, gateway, dns);

E'  normale, hai solo duplicato quello che ho scritto e che è valido per user e password, per gestire anche i dati di tipo IPAddress, senza effettivamente capire quello che scrivevi  ::)

Il mio precedente "Sei sicuro?" non era una domanda, era solo per spronarti a capire l'errore.
Magari cercarlo in rete, ti avrebbe aiutato a capire e quindi a risolvere :(
Questo è l'unico modo per imparare.

Comunque, queste le definizioni delle funzioni usate
Code: [Select]

//char * strcpy (char * destination, const char * source);
//bool IPAddress::fromString(const char *address);
//begin(char* ssid, char *passphrase, //..
//bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, ...


In uno dei tuoi post avevi fatto correttamente la conversione da un String a IPAddress utilizzando fromString che è di bocca buona e implicitamente converte String in char*, ma non puoi convertire implicitamente da char[] o char* a IPAddress , però,in questo caso, non è fondamentale.

Quindi
Code: [Select]

IPAddress gateway;

//...

case 3:
  gateway.fromString(buffer);
  break;

//...



Nota:
buffer, pass e ssid sono dichiarate come char array, e quando le passi a quelle funzioni, vengono implicitamente convertite in puntatori (char*). Ora, per chiarezza, io solitamente esplicito le conversioni, cosi quando rileggo non ho dubbi su quello che sto facendo, cioè ad esempio, strcpy((char*)ssid, (char*)buffer);


Per finire, ti ripeto, non ho modo di testare quello ti scrivo (non possiedo ESP8266), e non mi reputo "esperto".
Però quando copio, cerco di capire bene quello che scrivo, cerco di farlo mio studiando e modificando per vedere cosa accade.
Se hai dubbi sul C (funzioni, dati, etc), ti consiglio questo sito cplusplus, tutto il reference è corredato di semplici esempi per spiegare l'argomento.


Federico

"La logica vi porterà da A a B. L'immaginazione vi porterà dappertutto." A. Einstein

FabrizioVC65

Ti ringrazio per le spiegazioni, adesso le provo...
Chiedo scusa per la mia ignoranza sul C, fortunatamente per me questo è solo uno dei miei diversi hobby.
Avessi più tempo potrei dedicarmi a studiare il C, che è da tempo che svicolo.
L'hobby principale non è programmare (non più...) ora mi dedico al homebrew.
Programmo da più di 30 anni ho iniziato con il Basic su macchine 286, conosco il VB.Net, l'Html, l'ASP e l'SQL. Ho creato e venduto software gestionali in VB, VB.Net e VB for Applications (Access e Autocad)
Ho iniziato ad assaggiare il C# ma poi ho lasciato per dedicarmi ad altro.
3 lavori e 2 hobby mi sembravano sufficienti per riempire il mio tempo  ;) 

Il mio attuale progettino è, creare un misuratore di densità WiFi (per la fermentazione della birra)
L'hardware non mi ha dato prb, le pagine html e la gestione dei dati da memorizzare, che devo fare, non mi preoccupano.
Come si deduce, la programmazione della esp8266 non è il mio forte... :smiley-lol:

Cmq ancora grazie per le imbeccate

FabrizioVC65

Funziona alla perfezione, l'unica nota e che per leggere correttamente l'ultima riga degli indirizzi IP devo lasciare una riga vuota nel file txt alla fine.
Va benissimo così!!
Grazie ancora della disponibilità!

Federico66

Programmo da più di 30 anni ho iniziato con il Basic su macchine 286, conosco il VB.Net, l'Html, l'ASP e l'SQL. Ho creato e venduto software gestionali in VB, VB.Net e VB for Applications.
Io faccio ancora tutto questo, aggiungi C#, Asp.net WebForm e MVC e tutto quello che ne consegue :)

Non devi scusarti, anche io Arduino e C solo per hobby da una decina di mesi, mi piace la programmazione a basso livello e mi pento per non averla affrontata prima, quindi cerco di studiare. Purtroppo con l'elettronica faccio un po' fatica, ma se non si cerca di strafare, con Arduino & company riesce abbastanza facile; e poi qui c'è sempre qualcuno in grado di darti una mano.

Funziona alla perfezione, l'unica nota e che per leggere correttamente l'ultima riga degli indirizzi IP devo lasciare una riga vuota nel file txt alla fine.
Non vorrei dire una castronata, ma potrebbe essere un problema di codifica del file.
Se scopro qualcosa, ti scrivo

Federico
"La logica vi porterà da A a B. L'immaginazione vi porterà dappertutto." A. Einstein

Federico66

Va benissimo così!!
Adesso che funziona, posso dirti che però, personalmente non mi piace la logica del dato su file legato al numero di riga, preferisco sempre avere qualcosa del tipo NAME:VALUE, in quanto più leggibile e meno incasinato se decidi di aggiungere altri parametri :)

Direi che per adesso procedi pure cosi, ma se decidi di affrontare questo discorso, fatti vivo.


Federico
"La logica vi porterà da A a B. L'immaginazione vi porterà dappertutto." A. Einstein

zoomx

Dai un'occhiata qui
http://www.ispindel.de/
misura la densità in base all'inclinazione misurata con un accelerometro.
Però se vuoi imparare, fai da te e prendi da li solo lo spunto o le ispirazioni.

In quel progetto usano la libreria WiFimanager per gestire la configurazione del WiFi
Oppure usa la flash dell'ESP8266 e SPIFFS invece di una SD.

FabrizioVC65

Dai un'occhiata qui
http://www.ispindel.de/
misura la densità in base all'inclinazione misurata con un accelerometro.
Però se vuoi imparare, fai da te e prendi da li solo lo spunto o le ispirazioni.

In quel progetto usano la libreria WiFimanager per gestire la configurazione del WiFi
Oppure usa la flash dell'ESP8266 e SPIFFS invece di una SD.
Assolutamente Si... mi baso su quello come idea ma ritengo che i dati online su un server gratuito siano limitanti e soggetti a cambiamenti da gestire in futuro.
La mia idea è di avere un DB locale scaricabile da SD e consultabile da pagine web in locale. Questo mi permette di implementare nuove funzioni in futuro o di elaborare i dati raccolti su altre piattaforme.

Per quanto riguarda la scheda uso una LOLIN D1 mini Pro (EPS8262) che è un'evoluzione della D1 mini con l'alimentatore per la batteria al Litio incorporato. L' SPIFFS ho provato a farlo funzionare ma pur avendo configurato tutto come da help, non riesco a caricare i file dall' IDE, ma non me ne preoccupo tanto era già previsto l'uso della SD che mi espande il tutto a  x GB invece che a i solo 16MB (in realtà 14) della scheda.
In questo modo posso delegare tutte le funzioni critiche al HTML che mi è più familiare.

Go Up