Internet de les coses amb ESP32 i ESP8266

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

Canviem el color d'un NeoPixel a partir del darrer valor guardat

Google Drive incorpora un full de càlcul (spreadsheet, si ho tenim en anglès). Farem servir aquests fulls de càlcul per crear una taula on guardarem els tres colors (vermell, verd i blau) que hem d'enviar a un NeoPixel. El nostre programa enviarà al NeoPixel el darrer grup de valors guardat. Les dades les podrem escriure en el full de càlcul de moltes maneres, per exemple des d'una aplicació feta amb App Inventor (vegeu més avall en aquesta mateixa pàgina).

Ara anem a crear la taula. Piquem a Nou i triem full de càlcul. Estem considerant que tenim Google Drive en català, en cas contrari haurem de cercar la traducció corresponent a l'anglès. Se'ns obrirà la pantalla de treball amb la nova taula. Picant on diu Full de càlcul sense títol li podem posar el nom que vulguem. Aquest nom no té cap importància de cara al nostre exemple. Si féssim servir els fuls de càlcul independentment podríem posar els títols de columna a la primera filera del full però no ho farem així. Si ho féssim ens seria complicat descobrir com accedir a la taula des del microcontrolador.

Per facilitar el que necessitarem, farem una mica de "trampa". Picarem a Insereix i triarem l'opció Formulari.... Si tot va bé, tindrem un formulari nou al Google Drive i un nou full al full de càlcul creat. Si surt algun missatge d'error probablement es resoldrà recarregant les pàgines del Google Drive i del full de càlcul.

En lloc de crear columnes a la taula, el que farem serà crear preguntes al formulari. Per fer un formulari senzill, totes les preguntes les posarem del tipus resposta breu amb els paràmetres per defecte. Les preguntes que crearem seran les següents:

Ordre Pregunta
1 Vermell
2 Verd
3 Blau

Un cop creat el formulari, picarem el botó Envia i, en la finestra que s'ens obrirà, picarem el botó que es mostra a continuació.

Botó enllaç

Llavors la finestra tindrà un aspecte similar al següent:

Finestra enviar

Piquem al botó copia i se'ns copiarà l'enllaç que haurem d'enganzar en una finestra nova del navegador. En aquesta finestra podrem respondre al formulari. El que escribim no té importància, pot ser qualsevol text. Després podem tancar el formulari.

En el nostre full de càlcul hi apareixerà un full addicional que tindrà tantes columnes com preguntes té el formulari que tindràn com a títol (primera línia) la pregunta corresponent. De fet el full de càlcul tindrà una columna més, al començament, anomenada Marca de temps. Pot passar que les noves columnes triguin una estona en aparèixer.

Un cop introduït, es veuria d'aquesta manera:

Columnes de la taula

Les pàgines i els serveis de Google canvien d'aspecte amb certa freqüència. Les imatges que trobarem en aquest apartat, per tant, poden no correspondre exactament amb les reals. Aquí l'important són els passos, no l'aspecte.

De moment, el nostre full de càlcul és només accessible per a ús personal. Si hi volem accedir des de l'AppInventor ho haurem de canviar. Piquem sobre el botó Comparteix.... Se'ns obrirà una finestra en la que picarem el botó Opcions avançades. On s'indica Qui hi té accés hi deu dir Privat i ho hem de canviar per Activat: tothom que tingui l'enllaç i en el desplegable on diu Pot visualitzar haurem de triar Pot editar (en aquest cas ho podríem deixar a Pot visualitzar però llavors no podríem modificar el formulari des d'altres aplicacions). Piquem al botó Desa i tornarem a la finestra anterior on picarem el botó Fet. Ara anem a la pestanya Fitxer i piquem sobre l'opció Publica al web.... Se'ns obrirà una finestra en la que picarem el botó Publica, acceptarem la confirmació i tancarem la finestra.

Ara hem d'obtenir els enllaços necessaris per interactuar amb la taula i els identificadors que tenen les diferents columnes. Atenció: Les dades que heu de fer servir son les de la taula que hagueu creat. Els que es donen com a mostra corresponen a una taula que ja no existeix.

Primerament anirem a la nostra taula i picarem el botó Comparteix.... Allà ens sortirà un enllaç. Piquem el botó Copiar enllaç i ens guardem l'enllaç en algun lloc, per exemple un document del bloc de notes. L'enllaç obtingut serà similar a aquest:

https://docs.google.com/spreadsheets/d/1TThsoSjkeMSfwEKy4mn_4QEYH96sxv3VURqE3WHCTswDA/edit?usp=sharing

D'aquesta adreça ens interessa el codi de la taula, que és una seqüència llarga de caràcters situada entre barres. Aquí l'hem marcada en verd perquè sigui fàcil d'identificar.

Amb aquest codi crearem dues adreces que ens faran falta més endavant:

Variable Valor (en el vostre full de càlcul serà diferent)
AdreGet https://docs.google.com/spreadsheets/d/1TThsoSjkeMSfwEKy4mn_4QEYH96sxv3VURqE3WHCTswDA/export?format=csv
AdreSelect https://spreadsheet.google.com/tq?tqx=out:csv&key=1TThsoSjkeMSfwEKy4mn_4QEYH96sxv3VURqE3WHCTswDA&tq=

Ara anem a veure el programa que hem de posar al microcontrolador. Aquest programa llegirà els tres components de color cada deu segons, aproximadament.

// Aquest programa està parcialment basat en els exemples de la pàgina
// https://www.arduino.cc/en/Tutorial/LibraryExamples#wifi1010
#include <SPI.h>    // Carreguem la biblioteca SPI
#include <WiFiNINA.h>    // Carreguem la biblioteca WiFiNINA
#include <Adafruit_NeoPixel.h>    // biblioteca per als NeoPixels
#define LED 1    // pota on hem connectat el LED
const char idXarxa[] = "xarxa-wifi";    // Nom del punt d'accés 
const char contrasenya[] = "contrasenya-wifi";    // Contrasenya de connexió 
char server[] = "docs.google.com";
char pagina[] = "/spreadsheets/d/1TThsoSjkeMSfwEKy4mn_4QEYH96sxv3VURqE3WHCTswDA/export?format=csv";
unsigned long darreraConnexio = 0;
const unsigned long periodeConnexio = 10000UL;
bool pendent;
String R, G, B;    // Aquí guardarem els colors
String peticio = "";    // Aquí guardarem una línia de la petició del client
String peticioAux = "";    // i la petició anterior (també ho farem servir de reserva)
int status = WL_IDLE_STATUS;
Adafruit_NeoPixel cadena = Adafruit_NeoPixel(1, LED, NEO_GRB + NEO_KHZ800);
WiFiSSLClient client;
void setup() {    // Inicialització
    Serial.begin(9600);    // Monitor sèrie
    cadena.begin();  // Inicialitza els NeoPixels				
    cadena.show();
    while (!Serial) {
        ;    // Esperem que l'usuari obri el monitor sèrie
    }
    if (WiFi.status() == WL_NO_MODULE) {
        Serial.println("No s'ha trobat el dispositiu Wi-Fi");
        while (true);    // Bloquegem el programa
    }
    String versio = WiFi.firmwareVersion();
    if (versio < "1.0.0") {
        Serial.println("Convindria actualitzar el firmware");
    }
    while (status != WL_CONNECTED) {
        Serial.print("Connectant a la xarxa ");
        Serial.println(idXarxa);
        status = WiFi.begin(idXarxa, contrasenya);
        delay(10000);    // Ho tornarem a intentar passats 10 s
    }
    Serial.print("Connectat a "); 
    Serial.println(WiFi.SSID());
    Serial.print("Estat de la connexió: ");
    Serial.println(WiFi.status()); 
    Serial.print("Adreça IP del dispositiu: ");
    Serial.println(WiFi.localIP()); 
    Serial.print("Intensitat del senyal: ");
    Serial.print(WiFi.RSSI()); 
    Serial.println(" dBm");
    Serial.println(); 
    Serial.println("Anem a connectar al servidor");
}
void loop() {    // Programa que es repeteix indefinidament
    while (client.available()) {
        char c = client.read();    // Rebem caràcters del servidor
        if (c == '\n') {    // Mirem si és un salt de línia
            peticioAux = peticio;    // Guardem la petició anterior
            peticio = "";    // Ens preparem per a la línia següent
            pendent = true;    // Preparat per escriure-ho
        } else {
            peticio += c;    // Afegim el caràcter rebut
        }
    }
    if (pendent) {
        pendent = false;
        if (peticio == ""){    // Si està buit
            peticio = peticioAux;    // Agafem l'anterior
        }
        Serial.println();
        Serial.println(peticio);
        peticio = peticio.substring(peticio.indexOf(",") +1);
        R = peticio.substring(0, peticio.indexOf(","));
        peticio = peticio.substring(peticio.indexOf(",") +1);
        G = peticio.substring(0, peticio.indexOf(","));
        B = peticio.substring(peticio.indexOf(",") +1);
        cadena.setPixelColor(0, R.toInt(), G.toInt(), B.toInt());
        cadena.show();
    }
    if (millis() - darreraConnexio > periodeConnexio) {
        client.stop();
        if (client.connect(server, 443)) {
            Serial.println("S'ha fet la connexió al servidor");
            client.print("GET ");
            client.print(pagina);
            client.println(" HTTP/1.1");
            client.print("Host: ");
            client.println(server);
            client.println("Connection: close");
            client.println();
            // Guardem quan hem fet la connexió
            darreraConnexio = millis();
        } else {
            Serial.println("connection failed");
        }
    }
}

En aquest programa hi ha la condició que el monitor sèrie estigui obert per a que el programa comenci a funcionar. Això ens permet seguir tot el procés encara que triguem a obrir el monitor sèrie. Quan el microcontrolador hagi de funcionar de manera independent de l'ordinador caldrà eliminar les línies següents per evitar aquest bloqueig.

    while (!Serial) {
        ;    // Esperem que l'usuari obri el monitor sèrie
    }

El nostre programa de prova escriu unes quantes coses al monitor sèrie (instruccions Serial.print i Serial.println). Quan ja tinguem clar que el programa funciona, les podem eliminar quasi totes i probablement anirà una mica més ràpid.

Anem a veure un exemple senzill d'aplicació feta amb App Inventor que permet introduir els valors corresponents als tres colors i enviar-los al formulari. Abans de començar, ens caldrà obtenir alguns dels paràmetres del formulari.

En el full de càlcul, anem a la pestanya Formulari i piquem sobre l'opció Ves al formulari actiu. Se'ns obrirà el formulari que havíem creat abans. Hem d'accedir al codi HTML de la pàgina. Això pot ser lleugerament diferent segons el navegador. Piquem sobre el formulari amb el botó dret del ratolí i triem una opció que es pot dir Visualitza el codi font o Visualitza l'origen de la pàgina. Obtindrem una llista llarga de codi HTML que probablement estarà sense estructura i amb els mínims espais possibles. Aquí hi hem de cercar l'adreça que fa servir per enviar les dades del formulari. Cerquem el text form action= i ens l'hauria de trobar un sol cop. Després del signe d'igualtat hi ha d'haver una adreça entre cometes (que comença per https://). Aquesta és l'adreça que ens interessa.

Variable Valor (en el vostre full de càlcul serà diferent)
AdrePost https://docs.google.com/forms/d/e/1FAIpQLSdn0BnIxxfDTd0Nn41rwi_16Lm2RVws3b2YJQW_wl8cHIHGow/formResponse

També hem de trobar els identificadors de les columnes de la taula. Per fer-ho fàcil, cerquem el text name="entry.. L'hauria de trobar tants cops com columnes hem creat, és a dir tants com preguntes hem posat al formulari. Els codis, que són els elements que estan entre cometes, ens sortiran en el mateix ordre que les columnes. En el nostre cas eren tres columnes i, per tant, assignarem cada identificador a la columna corresponent.

Camp Identificador
camp_R entry.267410687
camp_G entry.2115647374
camp_B entry.495834116

Podríem dissenyar una pantalla amb el següent aspecte:

Disposició dels elements

Propietat Valor Comentaris
Nom Screen1 Aquest nom ja està posat a l'inici i no es pot canviar

Propietat Valor Comentaris
Nom Slider_R Aquest nom l'hem de posar en el requadre Components
Width Fill parent
MaxValue 255.0
MinValue 0.0
ThumbPosition 0.0
ColorLeft Red

Propietat Valor Comentaris
Nom Slider_G Aquest nom l'hem de posar en el requadre Components
Width Fill parent
MaxValue 255.0
MinValue 0.0
ThumbPosition 0.0
ColorLeft #66ff66ff

Propietat Valor Comentaris
Nom Slider_B Aquest nom l'hem de posar en el requadre Components
Width Fill parent
MaxValue 255.0
MinValue 0.0
ThumbPosition 0.0
ColorLeft Red

Propietat Valor Comentaris
Nom VerticalArrangement_Menu Aquest nom l'hem de posar en el requadre Components
Width Fill parent
AlignHorizontal Center

Propietat Valor Comentaris
Nom Label_Color Aquest nom l'hem de posar en el requadre Components
TextColor None

Propietat Valor Comentaris
Nom Button_Enviar Aquest nom l'hem de posar en el requadre Components
Text Enviar
FontBold Activat
TextColor Yellow
BackgroundColor Black
Shape rounded

El programa és el següent.

Programa
Programa

Cada cop que es canvia un valor es mostra el nou color al label i s'envia el nou valor quan es prem el botó. Fixem-nos que a l'hora d'enviar els valors els convertim en enters.

 

 

 

 

 

 

 

 

 

 

Llicència de Creative Commons
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.