Internet de les coses amb ESP32 i ESP8266

Exemples Referència Plaques   Recursos CITCEA
Projectes Programació Perifèrics   Inici

Funcions de la biblioteca WiFiNINA

La biblioteca WiFiNINA té moltes funcions i possibilitats, aquí només comentarem les que fem servir en aquest web. Podeu trobar la descripció completa a la pàgina WiFiNINA library.

Per poder fer servir aquesta biblioteca caldrà que estigui instal·lada. Podeu trobar les instruccions a Instal·lació de biblioteques.

Paràmetres generals

La funció firmwareVersion ens torna la versió actual del firmware que hi ha al xip ESP32. Es recomana actualitzar-lo si és una versió anterior a la 1.0.0.

    String versio = WiFi.firmwareVersion();
    if (versio < "1.0.0") {
        Serial.println("Convindria actualitzar el firmware");
    }

Elements de la xarxa

La funció ping ens permet saber si un dispositiu de la xarxa està accessible. Hi ha quatre possibles formes d'ús:

Funció Significat
WiFi.ping(ip) Cerca una adreça IP en format IPAddress
WiFi.ping(ip, ttl) Igual a l'anterior però especificant el nombre màxim d'enrutadors
WiFi.ping(host) Cerca una màquina a partir del seu nom (consulta prèviament al DNS)
WiFi.ping(host, ttl) Igual a l'anterior però especificant el nombre màxim d'enrutadors

Per exemple:

String nomHost = "recursos.citcea.upc.edu";
IPAddress ipPing(147, 83, 2, 75);
int resultat1, resultat2, resultat3;
    resultat1 = WiFi.ping(nomHost);
    resultat2 = WiFi.ping(ipPing);
    resultat3 = WiFi.ping(ipPing, 64);

Paràmetres de la connexió

La funció scanNetworks ens permet saber quantes xarxes Wi-Fi hi ha disponibles. En aquest exemple mirem quantes xarxes estan disponibles i obtenim els paràmetres bàsics de cada una.

    numXarxes = WiFi.scanNetworks();    // Torna -1 si no en troba cap

La funció SSID ens retorna l'identificador de la xarxa. La funció localIP ens dóna l'adreça IP. Aquesta adreça és important perquè és la que hem de posar al navegador quan ens connectem. Tenim funcions per connèixer altres paràmetres de la connexió que ha facilitat el punt d'accés, com la màscara de subxarxa (subnetMask) o la porta d'enllaç (gatewayIP).

    Serial.println(WiFi.SSID());
    Serial.println(WiFi.localIP()); 
    Serial.println(WiFi.subnetMask()); 
    Serial.println(WiFi.gatewayIP()); 

Les adreces IP i les màscares es retornen com objectes del tipus IPAddress. Per exemple, podem fer:

IPAddress ip_local;
    ip_local = WiFi.localIP();

La funció macAddress ens dóna l'adreça però li posem com a paràmetre la variable on volem que ens la guardi.

byte MAC[6];
    WiFi.macAddress(MAC);

La funció macAddress deixa l'adreça MAC en el vector que hem passat com a paràmetre però posant el byte més significatiu en la darrera posició i el menys significatiu en la primera. Podem fer servir un bucle per escriure l'adreça MAC en el format habitual.

    for (int i = 5; i >= 0; i--) {
        if (MAC[i] < 16) {
            Serial.print("0");
        }
        Serial.print(MAC[i], HEX);
        if (i > 0) {
            Serial.print(":");
        }
    }
    Serial.println();

En aquest exemple es proposa una funció que escriu l'adreça MAC.

La funció BSSID ens dóna l'adreça MAC del punt d'accés al que estem connectats. El seu funcionament és molt similar al de la funció macAddress.

byte MAC_bssid[6];
    WiFi.macAddress(MAC_bssid);

També podem obtenir l'adreça MAC d'un punt d'accés al que no estem connectats però està disponible:

byte MAC_bssid[6];
    WiFi.macAddress(puntAcces, MAC_bssid);    // puntAcces és un enter que correspon al número d'ordre de la xarxa

La funció channel ens torna el canal en el que està un punt d'accés.

    Serial.print(WiFi.channel(puntAcces));    // puntAcces és un enter que correspon al número d'ordre de la xarxa

La funció RSSI ens torna la intensitat del senyal.

    long inten = WiFi.RSSI();

També podem consultar la intensitat del senyal corresponent a un punt d'accés al que no estem connectats.

    long inten = WiFi.RSSI(puntAcces);    // puntAcces és un enter que correspon al número d'ordre de la xarxa

La funció encryptionType ens retorna el mètode de xifratge de la xarxa.

    byte xifratge = WiFi.encryptionType();

O en el cas d'uuna xarxa a la que no estem connectats:

    byte xifratge = WiFi.encryptionType(puntAcces);    // puntAcces és un enter que correspon al número d'ordre de la xarxa

Els possibles resultats estan a la taula següent:

Valor tipus Descripció tipus Mètode de xifratge
2 ENC_TYPE_TKIP WPA (TKIP)
4 ENC_TYPE_CCMP WPA2 (CCMP)
5 ENC_TYPE_WEP WEP
7 ENC_TYPE_NONE Sense xifratge
8 ENC_TYPE_AUTO Automàtic
Cap dels
anteriors
ENC_TYPE_UNKNOWN Desconegut

En aquest exemple es proposa una funció que escriu el tipus en funció del valor.

Configuració com a punt d'accés

La funció beginAP ens crea un punt d'accés amb l'identificador que indiquem. A més, podem posar-li una contrasenya (entre 8 i 63 caràcters) i indicar el canal (1 a 14, 1 si no ho posem).

const char idXarxa[] = "acces-ESP8266";    // Nom del punt d'accés 
const char contrasenya[] = "etseib00";    // Contrasenya de connexió 
    WiFi.softAP(idXarxa);    // Configura el punt d'accés (obert)
    WiFi.softAP(idXarxa, contrasenya);    // Protegit amb contrasenya
    WiFi.softAP(idXarxa, contrasenya, 2);    // En el canal 2

Aquesta funció pot retornar WL_AP_LISTENING si s'ha establert el punt d'accés i WL_CONNECT_FAILED en cas que no.

El punt d'accés es configurarà amb l'adreça 192.168.4.1 i donarà les adreces consecutives a aquesta als elements que s'hi connectin. La funció config ens permet configurar unes adreces IP diferents així mom la màscara i la porta d'enllaç. Cal fer servir valors coherents en la configuració. Els paràmetres són del tipus IPAddress que també està definit a la biblioteca.

IPAddress ip_PA(192, 168, 1, 1);
IPAddress dns(147, 83, 2, 3);
IPAddress porta(192, 168, 1, 1);   
IPAddress subxarxa(255, 255, 255, 0);
    WiFi.config(ip_PA); 
    WiFi.config(ip_PA, dns); 
    WiFi.config(ip_PA, dns, porta); 
    WiFi.config(ip_PA, dns, porta, subxarxa);

Connexió a una xarxa existent

Per connectar a una xarxa Wi-Fi existent farem servir la funció begin. Si la xarxa és oberta:

const char idXarxa[] = "xarxa-wifi";    // Nom del punt d'accés 
    status = WiFi.begin(idXarxa);

Si la xarxa és WEP haurem d'indicar l'índex de la contrasenya que farem servir i la contrasenya corresponent:

const char idXarxa[] = "xarxa-wifi";    // Nom del punt d'accés 
const char contrasenya[] = "contrasenya-wifi";    // Contrasenya de connexió
int index = 0;
    status = WiFi.begin(idXarxa, index, contrasenya);

Si la xarxa és WPA o WPA2 haurem d'indicar la contrasenya corresponent:

const char idXarxa[] = "xarxa-wifi";    // Nom del punt d'accés 
const char contrasenya[] = "contrasenya-wifi";    // Contrasenya de connexió
    status = WiFi.begin(idXarxa, contrasenya);

Un cop connectats a una xarxa, podem llegir l'hora d'internet fent servir la funció getTime que ens torna el nombre de segons transcorreguts des de l'inici del dia 1-1-1970, o un zero si no s'ha pogut obtenir. L'hora obtinguda és la de Greenwich.

Convé fer més d'un intent per si falla el primer:

#define numIntents 6
  unsigned long instant;
  int intents = 0;
  do {
    instant = WiFi.getTime();
    intents++;
  } while ((instant == 0) && (intents < numIntents));

En aquest exemple ho fem servir per posar en hora el rellotge de temps real.

Connexió, com a client, a un servidor

La funció connect s'encarrega de fer la connexió, com a client, a un servidor. Cal especificar l'adreça IP o el nom del servidor i el port. Els ports per defecte són el 80 (connexió http) i el 443 (connexió segura https). Exemples:

WiFiClient client;
    if (client.connect(server, 80)) {

WiFiSSLClient client;
    if (client.connect(server, 443)) {

Servidor Wi-Fi

Per crear un servidor Wi-Fi fem servir el constructor WiFiServer:

WiFiServer server(80);    // Creem un objecte de comunicació amb el port 80

Per posar en marxa el servidor fem servir la funció begin.

    server.begin();

La funció status ens indica l'estat de la connexió. Les respostes possibles són:

Resposta Significat
WL_CONNECTED Connexió correcta al punt d'accés especificat
WL_AP_CONNECTED Connexió correcta en mode punt d'accés
WL_AP_LISTENING Connexió correcta en mode punt d'accés i escoltant
WL_NO_SHIELD No s'ha detectat cap shield Wi-Fi
WL_NO_MODULE No s'ha detectat el mòdul Wi-Fi integrat
WL_NO_MODULE No s'ha detectat el mòdul Wi-Fi integrat
WL_IDLE_STATUS En aquest moment hi ha un canvi d'estat del Wi-Fi
Convé esperar una mica i tornar-ho a mirar
WL_NO_SSID_AVAIL No s'ha trobat el punt d'accés desitjat
WL_SCAN_COMPLETED S'ha acabat la cerca de punts d'accés
WL_CONNECT_FAILED S'ha trobat el punt d'accés però no s'ha pogut connectar
Correspon normalment a una contrasenya incorrecta
WL_CONNECTION_LOST S'ha perdut la connexió amb el punt d'accés
WL_DISCONNECTED Està desconnectat
Típicament quan el dispositiu no està en mode estació

    while (WiFi.status() != WL_CONNECTED) {   // Mira si s'ha connectat cada 0,5 s 
        delay(500);
        Serial.print(".");    // Cada 0,5 s posa un puntet
    }

La funció mode ens permet especificar el mode desitjat.

    WiFi.mode(WIFI_AP);    // El Wi-Fi funcionarà com a punt d'accés

Comunicació UDP

La comunicació UDP es fa mitjançant la classe WiFiUDP. Iniciarem una comunicació UDP amb la funció begin a la que indicarem, com a paràmetre, el port de connexió.

La comunicació UDP es fa enviant paquets d'un determinat nombre de bytes.

Per obrir un canal UDP per enviar un paquet fem servir la funció beginPacket que té dos paràmetres. El primer és el nom del servidor o la seva adreça IP i el segon és el port de connexió. La funció retorna 1 si tot ha anat bé i 0 si hi ha hagut algun problema.

La funció write prepara un paquet per enviar però no l'envia. Té dues sintaxis, en la primera només hi ha un paràmetre que és el byte a enviar i en la segona s'indica la variable que conté el paquet i la mida d'aquest. L'enviament del paquet es fa amb la funció endPacket que retorna 1 si tot ha anat bé i 0 si hi ha hagut algun problema.

La funció parsePacket ens indica si ha arribat un paquet i la mida d'aquest. Si retorna un 0 és que no ha arribat res. Per llegir el paquet fem servir la funció read que si no té paràmetres llegeix un byte i si té paràmetres llegeix tants bytes com indiqui el segon paràmetre sobre la variable que indiqui el primer.

 

 

 

 

 

 

 

 

 

 

Licencia de Creative Commons
Esta obra de Oriol Boix está licenciada bajo una licencia no importada Creative Commons Reconocimiento-NoComercial-SinObraDerivada 3.0.