Põhitoimingud Arduino ESP8266 wifi-mooduliga
Millal Espressif tõi turule esimesed moodulid wifi integreeritud ESP8266 ja püsivara millega seda AT-käskude abil käsitleda, huvitasime meid, kasutajaid, selle integreerimist kooslustesse mikrokontrollerid ja probleemid taandusid (endise) pimeduse tundmisele ESP8266 AT käsutabel, toitumisvajadused või ESP8266 püsivara värskendus.
Seejärel saabusid programmeerimiseks kiiresti alternatiivid ESP8266 ja moodulite teostused wifi väga erinevatest vormingutest, mis tekitasid muid probleeme: millist ESP8266 wifi-moodulit valida olenevalt erinevate antennide (ka väliste) levialast või nende uute moodulite füüsilisest integreerimisest meie sõlmedesse.
Kindlasti ei pruugi kõigi nende muudatuste tõttu rõhku pandud kõige elementaarsematele aspektidele, kõige elementaarsemale juhtimisele. ESP8266 wifi moodul. Kuigi polaarsus.es Teavet selle kasutamise kohta leiate ESP8266 ja on mõned rakendused, mille eesmärk on üldisel viisil selgitada rakenduse toimimist ESP8266 wifi moodul kasutades AT-käske, eriti artiklis teek, et teha Arduinost HTTP-päringuid ESP8266 wifi-mooduliga, näitavad lugejate muljed, et kasulik oleks lisada põhiteavet, et aidata kasutajaid ESP8266 oma teostusi ellu viima.
Arutage põhitoiminguid seadmega töötamiseks ESP8266 ja üldiste lahenduste väljapakkumine on mitme väga erineva osa eesmärk; Artikli sisu jälgimiseks võib abiks olla järgmine register:
- Juhtige ESP8266 wifi moodulit arvutist läbi jadapordi
- Värskendage püsivara esptooliga
- Saada tellimused moodulisse
- Saate andmeid ESP8266-lt
- Analüüsige vastust, otsides sisust tekste
- Piirake vastuse saamise ooteaega
- Käivitage mitme AT-käsuga määratletud keerukas toiming
Juhtige ESP8266 wifi moodulit arvutist läbi jadapordi
Taldrikult Arduino ja kasutades oma IDE on võimalik jälgida a tööd ESP8266 wifi moodul, saatke ESP8266 AT käsud ja vaata vastust aga palju mugavam on seda teha terminali tüüpi rakendusega arvutist.
Olenevalt millisest plaadist Arduino kasutatud, võib saadaval olla ainult üks riistvaraline jadaport, mis lisab saatmisele ja vastuvõtmisele veidi ebamugavusi. Sidekiiruse muutmine on arvuti ja mõne emaplaadi jadasiderakenduses palju mugavam. Arduino (ja mõnel juhul) ei toeta hästi jadaside suuremat kiirust, eriti 115200 XNUMX boodi, mis on seadme uusimate versioonide vaikekiirus. püsivara.
Umbes Millist programmi kasutada jälgimiseks ESP8266 kasutades jadaporti, on palju valida vastavalt vajadustele ja eelistustele; viimasel ajal kasutan rohkem klassikat CuteCom (see, mis on ülaloleval ekraanipildil), sest mul on väga mugav teatud asju korrata ESP8266 wifi moodul AT tellimused projekti testimisel.
Mõned soovitused on siin juba antud programmide kohta, mis toimivad jadakonsoolina; Näiteks kui rääkida PuTTY UART-jadaseadmete juhtimiseks arvutist. PuTTYLisaks suurepärasele rakendusele on see saadaval enamiku töölaua operatsioonisüsteemide jaoks. Lisaks nagu PuTTY saab kasutada konsoolina nii jadapordi kui ka Interneti-protokolli perekond (TCP/IP), sealhulgas need, mis töötavad TLS, muutub tavaliseks tööriistaks, mis maksab enam kui tagasi selle seadistamisele ja kasutamisega harjumisele kulunud (väikese) aja.
Lisaks jadakommunikatsiooni tarkvarale ühendada ESP8266 wifi moodul sadamasse USB Arvuti vajab ka konverterit USB seeriasse TTL. Nagu tarkvara puhul, on ka mitmeid versioone, millest neid kasutatakse ainult pordi teisendamiseks USB jadapordis TTL (mida saab ühest eurost) nendeni, mis suudavad emuleerida erinevaid protokolle (nt SPI o I2C).
Just nagu programm, mis toimib jadakonsoolina, riistvara arvutiga suhtlemiseks USB loogikaahelaga (mitte ainult ESP8266) saab olema tavaline tööriist mikrokontrollitud rakenduste arendaja töös, see tasub esimesel võimalusel tööriistakastis olla ja sellega tööd teha ESP8266 wifi moodul See on suurepärane võimalus seda hankida.
Muundur USB a UART TTL Seda saab kasutada ka vooluahela käitumise jälgimiseks, mis kasutab ESP8266, selleks ühendatakse jälgitavad väljundid jadamisi muunduri andmesisendiga (RX) kiirdioodiga ( 1N4148nt) ja takisti (näiteks 2K2) paralleelselt. Selline seadistus töötab nagu riistvaraline jadanuusutaja.
Kuigi ülaloleval pildil olev nuusutaja on kindlasti algeline (muuhulgas pole tal puhver) on piisav, et jälgida koostu tööd Arduino ja ESP8266.
Nuusutaja eemaldamine eelmisest skeemist, skeem, mis näitab, kuidas ühendada a ESP8266 wifi moodul taldrikule Arduino. Lisaks 3V3 toitmisele peavad integreeritud lähtestamise tihvt ja aktiveerimisviik olema ühendatud kõrge tasemega (lubatud). Loomulikult peab ühe RX-i viik ühenduma teise TX-ga.
Eelmise diagrammi lihtsustamiseks on kujutatud plaat Arduino toiteallikaks on 3V3 ja mille puhul eeldatakse, et jadapordi pinge on samuti 3V3. Kui kasutate a mikrokontroller jadapordi signaalitase (tavaliselt 5 V) on vajalik, et mitte kahjustada ESP8266, kasuta taseme muundur nagu allolevatel diagrammidel. Seda vooluringi leidub sageli paljudes kaubanduslikes valmismoodulite rakendustes.
Värskendage ESP8266 püsivara
The ESP8266 AT käsud, selle lõpetamine, mooduli vaikekiirus... sõltuvad versioonist ESP8266 püsivara. Parim on veenduda, et teil on kõigis moodulites sama versioon ja võimaluse korral uusim versioon.
Kahjuks enamik ESP8266 wifi mooduli mudelid Neil on ainult 4 Mbit, nii et uusimat versiooni ei saa neile installida. Püsivara uusim (ametlik) versioon, millele saab installida ESP8266 wifi moodulid 4 Mbit (enamik) on 0.9.4, mis sisaldab versiooni 0.2 ESP8266 AT käsud.
Kokkuvõttes vajate püsivara värskendamiseks järgmist.
-
Laadige alla vastav püsivara versioon. uusim (ametlik) versioon 4 Mbit mäluga moodulile, mis on leitud githubi kaustast Espressif. Aastal Espressifi veebisait Saate alla laadida püsivara uusima versiooni, kuid on väga oluline kontrollida, kas moodulil, millele see on installitud, on piisavalt mälu.
-
Laadige alla püsivara installitööriista uusim versioon. Minu lemmik on esptool mis on sisse kirjutatud Python, nii et see töötab igal platvormil. Lisaks allalaadimisele saab seda ka installida
pip install esptool
(opip2
opython -m pip
…). Muidugi, Espressif See pakub ka oma tööriista, kuid on praegu saadaval ainult Windowsi jaoks. -
Valmistage ette allalaaditud failid; pakkige need lahti juurdepääsetavasse kausta ja vajadusel muutke tööriist käivitatavaks esptool, minu puhul alates GNU / Linux, Mis
chmod +x esptool
-
Ühendage moodul konverteri abil arvutiga USB UART TTL mis töötab 3V3 juures või kasutage nivoomuundurit, kui see töötab 5 V juures. Lisaks võimsusele peate ühendama muunduri TX ja RX USB UART TTL, RX kuni TX, GPIO0 madalal tasemel (GND) ja võib-olla GPIO2 kõrgel tasemel (minu testides on see töötanud nii madalal tasemel ühendamisel kui ka lahtiühendamisel). Kui moodulil on GPIO15 ühendus vaba (nagu ESP-12 puhul), tuleb see ühendada madala tasemega. RESET-i, mis on töö ajal tavaliselt kõrgel tasemel, võib jätta ühendamata või ühendada kõrgele tasemele takisti abil (näiteks 10K), kuna enne salvestamise alustamist võib olla vajalik seade selle ühendamise teel lähtestada. madalale tasemele.
Mooduli sisselülitamisel on see värskendamiseks saadaval, kuid Kui kuvatakse ühenduse tõrge, tuleb see lähtestada ühendades RESET-i hetkeks madalal tasemel ja seejärel jättes selle värskendusprotsessi jaoks eetrisse (ilma ühendamata).
Moodulil on poole amprise tarbimise tipud (mõne kasutaja arvates kuni 600 mA), seega on oluline kasutada seda tarbimist toetavat toiteallikat, eriti püsivara värskendamiseks. -
Käivitage tööriist püsivara värskendamiseks. Minu puhul olen salvestanud tööriista ja püsivara dokumendid sammus 3 samasse kausta, nii et käivitan konsoolist:
cd ~/Datos/firmwareESP8266
(muutke tööriista ja püsivara sisaldavasse kausta)./esptool.py --baud 115200 --port /dev/ttyUSB0 write_flash \
0x00000 ./boot_v1.1.bin \
0x01000 ./user1.bin \
0x7C000 ./esp_init_data_default.bin \
0x7E000 ./blank.bin
--baud
määrab kiiruse ESP8266 (minu puhul 115200 baudi) ja--port
jadaport, millega see ühendub (minu puhul emuleeritud esimene USB). Püsivara moodustavad erinevad dokumendid jäävad mahawrite_flash
millele eelneb aadress koos värskenduse kasulikku koormust sisaldava dokumendiga user1.bin.
Saada käsklused ESP8266 wifi-moodulile
Et kontrollida ESP8266 arvutist, millest peame alustama konfigureerige rakendus mille jaoks piisab, kui ① valida port, millega muundur on ühendatud USB UART TTL, Midagi sellist /dev/USB0
GNU/Linuxis jms või midagi sarnast COM6
Windowsis ② valige kiirus, millega ESP8266, tõenäoliselt 115200 8 boodi, ③ määrake XNUMX andmebitti pluss üks stoppbitt ilma paarsuse või käepigistuseta ja ④ määrake rea lõpp, olenevalt püsivara, peaaegu alati CR+LF.
Kui rakendus on konfigureeritud (või, kui see on asjakohane, salvestatud ja valitud), siis see on avage ühendus (ülaltoodud näidete ekraanipiltidel vastavalt "ava seade" ja "avatud" koos CuteCom y PuTTY) ja võite hakata tellimusi saatma aadressile ESP8266.
Nagu võib näha ESP8266 AT käsutabel, on aktiveerimise, deaktiveerimise, väärtuse määramise ja sellele viitamise vorming üsna etteaimatav, kuid üldiselt ei ole neid kõiki lihtne meeles pidada ja tõenäoliselt peab see viitamiseks käepärast olema.
Viis enviar AT käsud al ESP8266 wifi moodul pärit Arduino on väga lihtne: ① konfigureerige suhtlust Serial.begin(115200);
(või Serial1, Serial2… mitme riistvaralise jadapordiga plaatidel) ja ② saadavad käsud vormingus Serial.print(orden+"\r\n");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#define PUERTO_SERIE Serial // Objeto serie que corresponde a puerto serie hardware al que está conectado el módulo wifi ESP8266
#define VELOCIDAD_ESP8266 115200 // Velocidad, en baudios, a la que está configurado el ESP8266
#define IDENTIFICADOR_WIFI “polaridad.es” // SSID (Service Set Identifier)
#define CLAVE_WIFI “54lLij1RiTn3MEd3v41C” // Clave del punto de acceso wifi al que se conecta el ESP8266
void setup()
{
PUERTO_SERIE.begin(VELOCIDAD_ESP8266);
PUERTO_SERIE.print
(
“AT+CWJAP=\””+
String(IDENTIFICADOR_WIFI)+
“\”,\””+
String(CLAVE_WIFI)+
“\”\r\n”
);
}
void loop()
{
}
|
Ülaltoodud näide näitab, kuidas saata ESP8266 wifi moodul AT tellimused pärit Arduino. Sel juhul on see illustreeritud AT+CWJAP
, mida kasutatakse pääsupunktiga ühenduse loomiseks. See käsk kasutab argumentidena pääsupunkti identifikaatorit (SSID) ja võti, mõlemad jutumärkides, nii et neist saab objekt Srtring
ja lisage need jutumärkidesse, kasutades paokoodi (\"
). Tellimuse täitmiseks kasutage \r\n
mis vastab CR
y LF
.
Pidage meeles, et jadaporti ei tuvastata alati Serial
(teatud plaatidel võib see olla Serial1
, Serial2
…) kasutatav pordiobjekt on määratletud, määrates selle makrole PUERTO_SERIE
. Kasutatava plaadi tüübi tuvastamine võib anda jadapordi valikule pisut intelligentsust; Hiljem räägime sellest, kuidas saate selle tüübi teada saada Arduino. Ülejäänud definitsioonid on tavalised, mis võimaldavad teil konstantseid väärtusi "nimetada", et vältida nende kordamist (ja vigade tegemist) ja hõlbustada nende muutmist.
Ülaltoodud näide peaks ühendama ESP8266 wifi moodul märgitud pääsupunktiga, kuid kas see oli juba varem ühendatud? Kas ühendus on toiminud? Selle teadmiseks peame "kuulama", mida ESP8266
Saate andmeid ESP8266 wifi-moodulist
Ühendades ülaltoodud andmete nuusutaja arvutiga, näete, mida Arduino on saatnud aadressile ESP8266 ja tema vastus. Et lugeda Arduino ja töödelda selles sisalduvat teavet, mida on vaja tuvastada Serial.available()
kui andmeid on saabunud ja kui jah, laadige need sisse Serial.read()
. Järgmine näide näitab, kuidas vastust lugeda AT+CWJAP?
, mis annab teada, kas pääsupunktiga on ühendus olemas.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#define PUERTO_ESP8266 Serial // Objeto serie que corresponde a puerto serie hardware al que está conectado el módulo wifi ESP8266
#define VELOCIDAD_ESP8266 115200 // Velocidad, en baudios, a la que está configurado el ESP8266
char letra_recibida;
void setup()
{
PUERTO_ESP8266.begin(VELOCIDAD_ESP8266);
PUERTO_ESP8266.print(“AT+CWJAP?\r\n”);
}
void loop()
{
while(PUERTO_ESP8266.available())
{
letra_recibida=PUERTO_ESP8266.read();
}
}
|
Nagu taldrikul Arduino uno (ja teistes) jadamonitori avamine lähtestab programmi, seda saab kasutada jadakonsoolis Arduino teave, millele saadate ESP8266 nagu alloleva pildi ekraanipilt näitab.
Analüüsige ESP8266 wifi-mooduli saadetud vastust
Oleme juba näinud, kuidas lugeda infot, mis jõuab Arduino alates ESP8266. Probleem, millega peate tegelema, on see, et te ei tea, millal see saabuma hakkab, kui kaua jõuab, kui kaua see on ... ja pole eriti tõhus oodata vastust ESP8266 võetakse vastu ilma laskmata mikrokontroller täitke vahepeal muid ülesandeid.
Lihtne viis selle olukorra lahendamiseks on kordama saadud andmeid, otsides konkreetseid vastuseid mille abil aktiveeritakse näiteks indikaatorid (lipud või Boole'i muutujad), mis määravad, kas vastuvõetud tekstis otsingut jätkata ja milliseid toiminguid tuleks teha, lähtudes sellest saabunud teabest. ESP8266. Kuigi vastus saabub mikrokontroller saab pühenduda muudele ülesannetele, näiteks anduritelt andmete vastuvõtmine ja nende töötlemine.
Otsige ESP8266-lt saadud teabest teksti
Teksti otsimiseks, mis pärineb ESP8266 saate võrrelge iga saadud kirja kirjaga, mis vastab otsitavale sõnumile. Tuleb kasutada loendurit (või osutit), mis osutab võrreldavale tähele; Kui tegelane, mis saabub ESP8266 on sama mis sõnumis uuritav, liigub loendur edasi, kui see erineb, siis lähtestatakse.
Et teada saada, et lõpp on käes, uuritakse otsitava kirja järgmist tähemärki, mis on null (\0
) või salvestatakse sõnumi pikkus, et loenduriga võrdlemisel saaks teada, kas võrdlus on lõppenud ja seega ESP8266 wifi moodul saatis soovitud sõnumi.
Järgmine näide kasutab käsku AT+CWLAP
mis tagastab pääsupunktide loendi ja nende seest otsitakse ühte nimega "wifi polaridad.es". Kuigi oleme otsustanud kontrollida, et viimane märk on null, nagu puhver See salvestab ainult otsitud teksti ja selle pikkus on teada, saaks ka kontrollida, kas nii palju õigeid tähti on laekunud. Koos LED ühendatud viiguga 2 teatatakse, et oodatud tekst on leitud.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
#if defined(ARDUINO_AVR_LEONARDO)||defined(ARDUINO_AVR_MEGA2560) /* ¿Es una placa Arduino Mega 2560 o Arduino Leonardo? */
#define SERIE Serial1 /* Si es una placa Arduino Mega 2560 o Arduino Leonardo usar Serial1 */
#else /* En este proyecto solamente uso Placas Leonardo, Mega 2560 y Uno, así que tiene que ser un Arduino Uno si llega hasta aquí */
#define SERIE Serial /* Si es una placa Arduino Uno usar Serial */
#endif
#define VELOCIDAD 115200 // Velocidad (en baudios) al que está configurado el módulo wifi ESP8266 (Cuidado con la placa utilizada, no todas o siempre son capaces de trabajar a una velocidad tan alta)
#define ORDEN “AT+CWLAP\r\n” // Buscar los puntos de acceso wifi disponibles. (Dependiendo de la versión del firmware) Las órdenes terminan en CR+LF
#define MENSAJE_BUSCADO “wifi polaridad.es” // Ver si está disponible el punto de acceso llamado “wifi polaridad.es”
#define LONGITUD_MENSAJE 18 // Se necesita guardar, al menos, 17 letras y el terminador \0
#define PIN_LED_ENCONTRADO 2 // Pin al que se conecta el LED que informa de que se ha encontrado el texto (el punto de acceso buscado está disponible)
#include <string.h> // strncpy
boolean esperando=true;
char buffer_mensaje;
char mensaje[LONGITUD_MENSAJE];
byte posicion_mensaje=0;
void setup()
{
pinMode(PIN_LED_ENCONTRADO,OUTPUT);
digitalWrite(PIN_LED_ENCONTRADO,LOW); // Apagar el LED (por ahora no se ha encontrado el mensaje)
strncpy(mensaje,MENSAJE_BUSCADO,LONGITUD_MENSAJE); // sizeof(mensaje)
SERIE.begin(VELOCIDAD); // Configurar el puerto serie de Arduino a la velocidad del ESP8266
SERIE.print(ORDEN); // Enviar la orden (consultar los puntos de acceso disponibles) al módulo wifi ESP8266
}
void loop()
{
if(esperando) // Buscará infinitamente hasta que llegue el texto esperado (y si no existe el punto de acceso nunca llegará ¡Es un ejemplo!)
{
while(SERIE.available()) // Si ha llegado algún dato por el puerto serie…
{
buffer_mensaje=SERIE.read(); // …almacenarlo en el buffer
if(buffer_mensaje==mensaje[posicion_mensaje]) // Si el dato que ha llegado es igual al que correspondería del mensaje buscado…
{
posicion_mensaje++; // Pasar a la siguiente letra del mensaje
if(mensaje[posicion_mensaje]==0) // ¿Ha terminado de analizarse todo el mensaje? (la última letra de la cadena de texto es \0)
{
esperando=false; // Si se ha terminado de analizar con éxito todo el mensaje ya no se está esperando
digitalWrite(PIN_LED_ENCONTRADO,HIGH); // Encender el LED para indicar que se ha encontrado el texto buscado
}
}
else // Si la letra que ha llegado por el puerto serie no corresponde con la buscada del mensaje…
{
posicion_mensaje=0; // …empezar desde la primera letra del texto buscado
}
}
}
}
|
Eelmise näite koodis näete ka võimalust vali jadaport sõltuvalt plaadi tüübist Arduino kasutatud. See näide eeldab, et teil on projekti jaoks kolme tüüpi tahvleid: üks Arduino uno, Üks Arduino Mega 2560 ja arduino leonardo. Kui töötate koos a Arduino uno seda kasutatakse Serial
ja muidu Serial1
.
Kui töötate taldrikuga arduino leonardo Saate kasutada sama meetodit programmi peatamiseks ja konsooli ootamiseks (jadaport, mis on seotud Serial
) on olemas.
1
2
3
4
5
6
7
8
9
10
11
|
#ifdef ARDUINO_AVR_LEONARDO
#define SERIE Serial1
#define ESPERA_CONSOLA while(!Serial){} /* Esperar a la consola */
#else
#define ESPERA_CONSOLA /* Si no es un Arduino Leonardo no hace falta esperar a la consola */
#ifdef ARDUINO_AVR_MEGA2560
#define SERIE Serial1
#else // En este proyecto solamente uso Placas Leonardo, Mega 2560 y Uno, así que tiene que ser un Arduino Uno si llega hasta aquí
#define SERIE Serial
#endif
#endif
|
Otsige ESP8266 vastusest erinevaid tekste
Eelmise näite koodi kasutatakse teksti otsimiseks saadetud teabest ESP8266 kuid vastus võib sõltuvalt toimingust sisaldada erinevat teavet. Oletame, et järgmises näites alustades lihtsa juhtumiga, et tekst, mille saatis MCU ESP8266 es OK
kui operatsioon on õigesti tehtud ja ERROR
Muidu nagu tellimusega AT+CWJAP?
, mille eesmärk on kontrollida, kas ESP8266 wifi moodul olete juba pääsupunktiga ühendatud.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
#if defined(ARDUINO_AVR_LEONARDO)||defined(ARDUINO_AVR_MEGA2560) /* ¿Es una placa Arduino Mega 2560 o Arduino Leonardo? */
#define SERIE Serial1 /* Si es una placa Arduino Mega 2560 o Arduino Leonardo usar Serial1 */
#else /* En este proyecto solamente uso Placas Leonardo, Mega 2560 y Uno, así que tiene que ser un Arduino Uno si llega hasta aquí */
#define SERIE Serial /* Si es una placa Arduino Uno usar Serial */
#endif
#define VELOCIDAD 115200 // Velocidad (en baudios) al que está configurado el módulo wifi ESP8266 (Cuidado con la placa utilizada, no todas o siempre son capaces de trabajar a una velocidad tan alta)
#define ORDEN “AT+CWJAP?\r\n” // Verificar que está conectado a un punto de acceso
#define CANTIDAD_MENSAJES 2 // Se distingue entre dos mensajes: acierto y error que se identificarán con true y false
#define MENSAJE_ACIERTO “OK”
#define MENSAJE_ERROR “ERROR”
#define LONGITUD_MENSAJE 6 // Se necesita guardar, al menos, 5 letras y el terminador \0 (Un pequeño desperdicio al hacer una matriz en la que todos los elementos ocupan como el mayor. Es admisible porque son muy pocos elementos y así no se complica este ejemplo inicial)
#define PIN_LED_ACIERTO 2 // Pin al que se conecta el LED que informa del acierto
#define PIN_LED_ERROR 3 // Pin al que se conecta el LED que informa del error
#include <string.h> // strncpy
boolean esperando=true; // Todavía no se ha encontrado el final del mensaje
char buffer_mensaje; // Para almacenar la última letra cargada desde el ESP8266
byte led_estado[CANTIDAD_MENSAJES]; // Un LED (pin) para cada estado
char mensaje[CANTIDAD_MENSAJES][LONGITUD_MENSAJE]; // Mensajes de acierto y error
byte posicion_mensaje[CANTIDAD_MENSAJES]; // Un contador de posición para cada mensaje
void setup()
{
led_estado[true]=PIN_LED_ACIERTO;
led_estado[false]=PIN_LED_ERROR;
for(byte numero_mensaje=0;numero_mensaje<CANTIDAD_MENSAJES;numero_mensaje++)
{
pinMode(led_estado[numero_mensaje],OUTPUT); // Establecer el pin del LED
digitalWrite(led_estado[numero_mensaje],LOW); // Apagar el LED
posicion_mensaje[numero_mensaje]=0; // Inicializar a cero el número de letra a analizar de cada mensaje
}
strncpy(mensaje[true],MENSAJE_ACIERTO,LONGITUD_MENSAJE); // Preparar el mensaje de acierto
strncpy(mensaje[false],MENSAJE_ERROR,LONGITUD_MENSAJE); // Preparar el mensaje de error
SERIE.begin(VELOCIDAD); // Configurar el puerto serie de Arduino a la velocidad del ESP8266
SERIE.print(ORDEN); // Enviar la orden (verificar si existe conexión a un punto de acceso) al módulo wifi ESP8266
}
void loop()
{
if(esperando) // Buscará infinitamente hasta que llegue el texto esperado (y si no existe el punto de acceso nunca llegará ¡Es un ejemplo!)
{
while(SERIE.available()) // Si ha llegado algún dato por el puerto serie…
{
buffer_mensaje=SERIE.read(); // …almacenarlo en el buffer
for(byte numero_mensaje=0;numero_mensaje<CANTIDAD_MENSAJES;numero_mensaje++)
{
if(buffer_mensaje==mensaje[numero_mensaje][posicion_mensaje[numero_mensaje]]) // Si el dato que ha llegado es igual al que correspondería del mensaje buscado…
{
posicion_mensaje[numero_mensaje]++; // Pasar a la siguiente letra del mensaje
if(mensaje[numero_mensaje][posicion_mensaje[numero_mensaje]]==0) // ¿Ha terminado de analizarse todo el mensaje actual? (la última letra de la cadena de texto es \0)
{
esperando=false; // Si se ha encontrado algún mensaje y ya no se está esperando
digitalWrite(led_estado[numero_mensaje],HIGH); // Encender el LED correspondiente al mensaje encontrado
}
}
else // Si la letra que ha llegado por el puerto serie no corresponde con la buscada del mensaje…
{
posicion_mensaje[numero_mensaje]=0; // …empezar desde la primera letra del texto buscado
}
}
}
}
}
|
See sama meetodi uus rakendus, mis otsib vastet mitme võimaliku sõnumiga, võimaldab teil valida erinevate toimingute vahel olenevalt ESP8266, lihtsalt lülitage sisse LED vastav.
Piirake vastuse saamiseks kuluvat aega
Siiani ei ole viidatud asjakohasele probleemile: maksimaalne ooteaeg (ajalõpp), enne kui loetakse toimingu ebaõnnestunuks. Kui mingil põhjusel seostub ESP8266 wifi moodul, pääsupunktiga moodul, Internetiga pöörduspunkt või näiteks hüpoteetiline server pole saadaval, programm võib olla blokeeritud ühes punktis, mis ootab määramata ajaks, mistõttu tuleb sellistele asjaoludele reageerida. Maksimaalset ooteaega saab seadistada kogu rakenduse jaoks, tavaliselt on see sel juhul "helde" või saab iga toimingu jaoks programmeerida individuaalsed ooteajad.
Kontrollimaks, et (vähemalt) teatud ajavahemik on möödas Tavaliselt lahutatakse praegusest "ajast" konto käivitamise hetke "aeg" ja kontrollitakse, et vahe on suurem kui soovitud piir. See "aeg" ei pea olema reaalajas, tavaliselt vastab see intervallile, mis on möödunud ajast MCU hakata aega lugema; See ei mõjuta programmi, sest huvitav on kulunud aeg, mitte absoluutne aeg.
Tavaliselt kasutatakse selleks, et kontrollida, kas teatud intervall on möödas, järgmist tüüpi avaldist:
1
|
(unsigned long)(millis()–milisegundos_al_empezar)>intervalo_de_tiempo
|
Muutuv milisegundos_al_empezar
sisaldab väärtust millis()
teatud täitmise hetk, millest alates see ajastatud, seega pole ebatavaline, et selle nimi viitab sõnale "kronomeeter". Muutuja intervalo_de_tiempo
sisaldab maksimaalset millisekundite arvu, mis muudab eelmise avaldise tõeseks, see tähendab, et see tähistab ajalõpu; Tavaliselt on tegemist konstandiga (või makroga) ja nagu ka eelmisel juhul, esineb selle nimes sageli sõna "TIMEOUT". Kui töötate väga lühikeste intervallidega, võite kasutada micros()
asemel millis()
(millisekundite asemel mikrosekundid), kuigi see on palju vähem levinud ja palju vähem täpne.
1
|
(unsigned long)(millis()–cronometro)>TIMEOUT
|
Pikk täisarv sisse Arduino (unsigned long
) võtab enda alla 4 baiti (32 bitti), seega on suurim väärtus, mida see esindada saab, 4294967295 (2 astmeni 32 miinus üks, sest see algab nullist). taldrikul Arduino Pidevalt töötades lähtestub millisekundite loendur (naaseb nulli) ligikaudu iga 50 päeva järel. Märgistamata andmetüüpidega lahutamisel reprodutseeritakse sama käitumine (loenduri pööramine), nii et ajalõpu on võimalik piiramatult juhtida.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
#if defined(ARDUINO_AVR_LEONARDO)||defined(ARDUINO_AVR_MEGA2560) /* ¿Es una placa Arduino Mega 2560 o Arduino Leonardo? */
#define SERIE Serial1 /* Si es una placa Arduino Mega 2560 o Arduino Leonardo usar Serial1 */
#else /* En este proyecto solamente uso Placas Leonardo, Mega 2560 y Uno, así que tiene que ser un Arduino Uno si llega hasta aquí */
#define SERIE Serial /* Si es una placa Arduino Uno usar Serial */
#endif
#define VELOCIDAD 115200 // Velocidad (en baudios) al que está configurado el módulo wifi ESP8266 (Cuidado con la placa utilizada, no todas o siempre son capaces de trabajar a una velocidad tan alta)
#define ORDEN “AT+CWJAP?\r\n” // Verificar que está conectado a un punto de acceso
#define CANTIDAD_MENSAJES 2 // Se distingue entre dos mensajes: acierto y error que se identificarán con true y false
#define MENSAJE_ACIERTO “OK”
#define MENSAJE_ERROR “ERROR”
#define LONGITUD_MENSAJE 6 // Se necesita guardar, al menos, 5 letras y el terminador \0 (Un pequeño desperdicio al hacer una matriz en la que todos los elementos ocupan como el mayor. Es admisible porque son muy pocos elementos y así no se complica este ejemplo inicial)
#define PIN_LED_ACIERTO 2 // Pin al que se conecta el LED que informa del acierto
#define PIN_LED_ERROR 3 // Pin al que se conecta el LED que informa del error
#define TIMEOUT 5000 // Espera 5 segundos la respuesta del ESP8266 (y su análisis) antes de desistir
#include <string.h> // strncpy
boolean esperando=true; // Todavía no se ha encontrado el final del mensaje
boolean encontrado=false; // Salvo que se encuentre el punto de acceso se considera que la operación ha fracasado
char buffer_mensaje; // Para almacenar la última letra cargada desde el ESP8266
byte led_estado[CANTIDAD_MENSAJES]; // Un LED (pin) para cada estado
char mensaje[CANTIDAD_MENSAJES][LONGITUD_MENSAJE]; // Mensajes de acierto y error
byte posicion_mensaje[CANTIDAD_MENSAJES]; // Un contador de posición para cada mensaje
unsigned long cronometro;
void setup()
{
led_estado[true]=PIN_LED_ACIERTO;
led_estado[false]=PIN_LED_ERROR;
for(byte numero_mensaje=0;numero_mensaje<CANTIDAD_MENSAJES;numero_mensaje++)
{
pinMode(led_estado[numero_mensaje],OUTPUT); // Establecer el pin del LED
digitalWrite(led_estado[numero_mensaje],LOW); // Apagar el LED
posicion_mensaje[numero_mensaje]=0; // Inicializar a cero el número de letra a analizar de cada mensaje
}
strncpy(mensaje[true],MENSAJE_ACIERTO,LONGITUD_MENSAJE); // Preparar el mensaje de acierto
strncpy(mensaje[false],MENSAJE_ERROR,LONGITUD_MENSAJE); // Preparar el mensaje de error
SERIE.begin(VELOCIDAD); // Configurar el puerto serie de Arduino a la velocidad del ESP8266
SERIE.print(ORDEN); // Enviar la orden (verificar si existe conexión a un punto de acceso) al módulo wifi ESP8266
cronometro=millis();
}
void loop()
{
if(esperando) // Buscará infinitamente hasta que llegue el texto esperado (y si no existe el punto de acceso nunca llegará ¡Es un ejemplo!)
{
while(SERIE.available()) // Si ha llegado algún dato por el puerto serie…
{
buffer_mensaje=SERIE.read(); // …almacenarlo en el buffer
for(byte numero_mensaje=0;numero_mensaje<CANTIDAD_MENSAJES;numero_mensaje++)
{
if(buffer_mensaje==mensaje[numero_mensaje][posicion_mensaje[numero_mensaje]]) // Si el dato que ha llegado es igual al que correspondería del mensaje buscado…
{
posicion_mensaje[numero_mensaje]++; // Pasar a la siguiente letra del mensaje
if(mensaje[numero_mensaje][posicion_mensaje[numero_mensaje]]==0) // ¿Ha terminado de analizarse todo el mensaje actual? (la última letra de la cadena de texto es \0)
{
encontrado=numero_mensaje; // (numero_mensaje!=0) Hay conexión con el punto de acceso
esperando=false; // Si se ha encontrado algún mensaje y ya no se está esperando
digitalWrite(led_estado[numero_mensaje],HIGH); // Encender el LED correspondiente al mensaje encontrado
}
}
else // Si la letra que ha llegado por el puerto serie no corresponde con la buscada del mensaje…
{
posicion_mensaje[numero_mensaje]=0; // …empezar desde la primera letra del texto buscado
}
}
}
if((unsigned long)(millis()–cronometro)>TIMEOUT&&!encontrado) // Se ha superado el tiempo de espera y no hay conexión (se ha verificado que no hay o no ha llegado respuesta)
{
digitalWrite(PIN_LED_ERROR,HIGH); // Si ha superado el tiempo de espera encender el LED de error
esperando=false;
}
}
}
|
Ülaltoodud kood näitab a ajalõpu piirangu väga elementaarne rakendamine sisaldab sellele eelnevale näitele vastavaid jooni. Kuna ajalõpu kontrollimine toimub pärast kohast saabunud andmete töötlemist ESP8266 wifi moodul, võib operatsiooni lugeda õnnestunuks ka siis, kui vastuvõtt võtab kauem aega kui kehtestatud ooteaeg.
Käivitage mitme AT-käsuga määratletud keerukas toiming
Et saada näidet kasutava rakenduse eesmärgi kohta ESP8266 wifi moodul, oletame, et on salvestada teavet veebiteenuse kaudu juurdepääsetavasse andmebaasi temperatuuri jälgimiseks. Järgnev kood loeb iga teatud ajaintervalli tagant analoogsisendiga ühendatud anduri, arvutab keskmise väärtuse ja saadab pikema aja möödudes selle veebiserverisse (stiil IoT) läbi a petitsiooni HTTP (POSTITA, HANGI…).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#define PIN_TEMPERATURA A0 // Pin analógico al que se conecta la salida del sensor de temperatura LM35
#define INTERVALO_LECTURA_TEMPERATURA 30000 // Leer la temperatura cada 30 segundos (30*1000)
#define INTERVALO_GRABACION_TEMPERATURA 300000 // Grabar la media de la temperatura cada 5 minutos (5*60*1000)
unsigned long muestras=0; // Número de veces que se ha medido la temperatura (para calcular la media)
float temperatura; // de -55.0 °C a +150 °C | de -550 mV a +1500 mV | de 0 V a 2.050 V | analogRead*5.0/1023.0*100-55.0 -> analogRead/2.46-55.0
float media_temperaturas=0.0;
unsigned long cronometro_lectura_temperatura;
unsigned long cronometro_grabacion_temperatura;
void setup()
{
Serial.begin(9600);
cronometro_lectura_temperatura=millis();
cronometro_grabacion_temperatura=millis();
}
void loop()
{
if((unsigned long)(millis()–cronometro_lectura_temperatura)>INTERVALO_LECTURA_TEMPERATURA)
{
cronometro_lectura_temperatura=millis();
temperatura=analogRead(PIN_TEMPERATURA)/2.46–55.0;
muestras++;
media_temperaturas=(float)temperatura/(float)muestras+media_temperaturas*(float)(muestras–1)/(float)(muestras);
}
if((unsigned long)(millis()–cronometro_grabacion_temperatura)>INTERVALO_GRABACION_TEMPERATURA)
{
cronometro_grabacion_temperatura=millis();
// Aquí iría la parte del código que graba la temperatura. Para verificar el funcionamiento, en este ejemplo simplemente se muestra en la consola
Serial.println(“\nTemperatura media “+String(temperatura,DEC)+” °C (“+String((float)millis()/1000.0,DEC)+” s)\n”);
}
}
|
Selles temperatuurisalvestuse näites pöördutakse veebiserveri poole iga viie minuti järel. Kuigi kättesaadavus ei ole eriti kõrge, on ootuspärane, et ettepanek toimiks, kuid suurema salvestussageduse vajaduse korral tuleks rakendada muid ressursse, näiteks andmepuhver ootab saatmist, et saata mitu, kui server saab osaleda, ja salvestada need selleks ajaks, kui see pole saadaval. Kui andmete salvestamise sagedus oleks veelgi suurem, tuleks alternatiivina pakkuda muud tüüpi protokolle. HTTP või isegi asendada TCP poolt UDP et oleks võimalik saata enamik andmeid vajaliku kiirusega isegi osade kaotamise hinnaga.
Toimingud, mis moodustavad temperatuuri saatmise ülesande, oleksid järgmised:
- Lähtestage wifi-moodul
- Katkesta ühendus praeguse pääsupunktiga (juhul, kui vaikeühendus on olemas)
- Määra seaded. Näite puhul eeldatakse, et ühendusrežiim (lihtne) ja roll Wi-Fi sides (jaam) peavad olema konfigureeritud.
- Ühendage pääsupunktiga
- Veenduge, et ühendus on õige (tegelikult on see sisenemispunkt) Kui ühendust pole, alustage protsessi algusest
- Ühendage serveriga
- Saada taotlus HTTP koos salvestatavate andmetega
Toimingute järjekord ei pea olema täpselt selline (kuigi toiming on) ja iga samm võib nõuda mitut ESP8266 AT käsudNäiteks ülaltoodud konfiguratsiooni jaoks on vaja kahte: AT+CIPMUX=0
y AT+CWMODE=1
.
Andmestruktuur ESP8266 toimingute esitamiseks
Eelmistes näidetes, kuigi väga lihtsal viisil, on probleemile juba pakutud üldine lahendus: kasutada andmestruktuuri, mis salvestab võimalikud vastused ja toimingud, mida igal konkreetsel juhul teha tuleb; saatke toiming, oodake vastust ja jätkake vastavalt sellele, mida vastus tähendab. Kuna iga keeruline toiming nõuab mitut ESP8266 AT käsud, peab andmestruktuur siduma toimingu teiste, järgnevate või eelmiste toimingutega, mis tuleb igal juhul läbi viia sõltuvalt ESP8266.
Eelmistes näidetes otsiti sõnumit vastusest ESP8266 ja seda tõlgendati edu või veana. Lisaks kogu saadud teksti vastuvõtmisele (ja analüüsile) Üldise miinimumi saavutamiseks on soovitatav jälgida ka sõnumi valmimist või, teisisõnu, kättesaadavus ESP8266 wifi moodul uute tellimuste saamiseks. Sel viisil võib muutumine olekusse, mida võiksime nimetada näiteks "wifi saadaval", olla pöörduspunkti nime vastuvõtmine ja teksti vastuvõtmine ERROR
või teksti OK
tähendaks, et ESP8266 olete vastuse lõpetanud ja saate nüüd saata järgmise AT käsk ESP8266-le.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
// inicializar_operaciones.h
// 0 Reiniciar el módulo wifi ESP8266
operacion[REINICIAR_ESP8266]=“AT+RST”;
mensaje[REINICIAR_ESP8266][FALLO]=mensaje_fallo;
mensaje[REINICIAR_ESP8266][ACIERTO]=“ready\r\n”;
mensaje[REINICIAR_ESP8266][LITERAL]=mensaje_vacio;
siguiente_operacion[REINICIAR_ESP8266][FALLO]=REINICIAR_ESP8266;
siguiente_operacion[REINICIAR_ESP8266][ACIERTO]=DESCONECTAR_WIFI;
siguiente_operacion[REINICIAR_ESP8266][LITERAL]=DESCONECTAR_WIFI;
configuracion[REINICIAR_ESP8266]=ESPERAR_RESPUESTA|ACIERTO_TERMINA|FALLO_TERMINA;
timeout[REINICIAR_ESP8266]=10000;
// 1 Desconectar del punto de acceso por defecto (si fuera el caso)
operacion[DESCONECTAR_WIFI]=“AT+CWQAP”;
mensaje[DESCONECTAR_WIFI][FALLO]=mensaje_fallo;
mensaje[DESCONECTAR_WIFI][ACIERTO]=mensaje_acierto;
mensaje[DESCONECTAR_WIFI][LITERAL]=mensaje_vacio;
siguiente_operacion[DESCONECTAR_WIFI][FALLO]=REINICIAR_ESP8266;
siguiente_operacion[DESCONECTAR_WIFI][ACIERTO]=MODO_ESTACION;
siguiente_operacion[DESCONECTAR_WIFI][LITERAL]=MODO_ESTACION;
configuracion[DESCONECTAR_WIFI]=ESPERAR_RESPUESTA|ACIERTO_TERMINA|FALLO_TERMINA;
timeout[DESCONECTAR_WIFI]=2500;
// 2 Establecer el modo de estación (no punto de acceso)
operacion[MODO_ESTACION]=“AT+CWMODE=1”;
mensaje[MODO_ESTACION][FALLO]=mensaje_fallo;
mensaje[MODO_ESTACION][ACIERTO]=mensaje_acierto;
mensaje[MODO_ESTACION][LITERAL]=mensaje_vacio;
siguiente_operacion[MODO_ESTACION][FALLO]=REINICIAR_ESP8266;
siguiente_operacion[MODO_ESTACION][ACIERTO]=MODO_SIMPLE;
siguiente_operacion[MODO_ESTACION][LITERAL]=MODO_SIMPLE;
configuracion[MODO_ESTACION]=ESPERAR_RESPUESTA|ACIERTO_TERMINA|FALLO_TERMINA;
timeout[MODO_ESTACION]=2500;
// 3 Establecer el modo de conexión simple
operacion[MODO_SIMPLE]=“AT+CIPMUX=0”;
mensaje[MODO_SIMPLE][FALLO]=mensaje_fallo;
mensaje[MODO_SIMPLE][ACIERTO]=mensaje_acierto;
mensaje[MODO_SIMPLE][LITERAL]=mensaje_vacio;
siguiente_operacion[MODO_SIMPLE][FALLO]=REINICIAR_ESP8266;
siguiente_operacion[MODO_SIMPLE][ACIERTO]=CONECTAR_WIFI;
siguiente_operacion[MODO_SIMPLE][LITERAL]=CONECTAR_WIFI;
configuracion[MODO_SIMPLE]=ESPERAR_RESPUESTA|ACIERTO_TERMINA|FALLO_TERMINA;
timeout[MODO_SIMPLE]=2500;
// 4 Conectar al punto de acceso
operacion[CONECTAR_WIFI]=“AT+CWJAP=\”polaridad.es\”,\”54lLij1RiTn3MEd3v41C\””;
mensaje[CONECTAR_WIFI][FALLO]=mensaje_fallo;
mensaje[CONECTAR_WIFI][ACIERTO]=mensaje_acierto;
mensaje[CONECTAR_WIFI][LITERAL]=mensaje_vacio;
siguiente_operacion[CONECTAR_WIFI][FALLO]=REINICIAR_ESP8266;
siguiente_operacion[CONECTAR_WIFI][ACIERTO]=VERIFICAR_CONEXION;
siguiente_operacion[CONECTAR_WIFI][LITERAL]=VERIFICAR_CONEXION;
configuracion[CONECTAR_WIFI]=ESPERAR_RESPUESTA|ACIERTO_TERMINA|FALLO_TERMINA;
timeout[CONECTAR_WIFI]=20000;
// 5 Verificar si hay conexión
operacion[VERIFICAR_CONEXION]=“AT+CIPSTATUS”;
mensaje[VERIFICAR_CONEXION][FALLO]=mensaje_fallo;
mensaje[VERIFICAR_CONEXION][ACIERTO]=mensaje_acierto;
mensaje[VERIFICAR_CONEXION][LITERAL]=“STATUS:5”;
siguiente_operacion[VERIFICAR_CONEXION][FALLO]=REINICIAR_ESP8266;
siguiente_operacion[VERIFICAR_CONEXION][ACIERTO]=REINICIAR_ESP8266;
siguiente_operacion[VERIFICAR_CONEXION][LITERAL]=CONECTAR_SERVIDOR;
configuracion[VERIFICAR_CONEXION]=ESPERAR_RESPUESTA|ACIERTO_TERMINA|FALLO_TERMINA;
timeout[VERIFICAR_CONEXION]=5000;
// 6 Conectar al servidor
operacion[CONECTAR_SERVIDOR]=“AT+CIPSTART=\”TCP\”,\”servidoriot.com\”,80″;
mensaje[CONECTAR_SERVIDOR][FALLO]=mensaje_fallo;
mensaje[CONECTAR_SERVIDOR][ACIERTO]=mensaje_acierto;
mensaje[CONECTAR_SERVIDOR][LITERAL]=“CONNECT”;
siguiente_operacion[CONECTAR_SERVIDOR][FALLO]=REINICIAR_ESP8266;
siguiente_operacion[CONECTAR_SERVIDOR][ACIERTO]=INFORMAR_CANTIDAD;
siguiente_operacion[CONECTAR_SERVIDOR][LITERAL]=INFORMAR_CANTIDAD;
configuracion[CONECTAR_SERVIDOR]=ESPERAR_RESPUESTA|ACIERTO_TERMINA|FALLO_TERMINA;
timeout[CONECTAR_SERVIDOR]=15000;
// 7 Avisar de la cantidad de datos que se envían
operacion[INFORMAR_CANTIDAD]=“AT+CIPSEND=”;
mensaje[INFORMAR_CANTIDAD][FALLO]=mensaje_vacio;
mensaje[INFORMAR_CANTIDAD][ACIERTO]=mensaje_acierto;
mensaje[INFORMAR_CANTIDAD][LITERAL]=mensaje_vacio;
siguiente_operacion[INFORMAR_CANTIDAD][FALLO]=REINICIAR_ESP8266;
siguiente_operacion[INFORMAR_CANTIDAD][ACIERTO]=ENVIAR_CANTIDAD;
siguiente_operacion[INFORMAR_CANTIDAD][LITERAL]=ENVIAR_CANTIDAD;
configuracion[INFORMAR_CANTIDAD]=NO_ESPERAR_RESPUESTA;
timeout[INFORMAR_CANTIDAD]=1000;
// 8 Enviar cantidad
//operacion[ENVIAR_CANTIDAD]=”123″; // Definido para cada envío
mensaje[ENVIAR_CANTIDAD][FALLO]=sin_enlace;
mensaje[ENVIAR_CANTIDAD][ACIERTO]=“>”;
mensaje[ENVIAR_CANTIDAD][LITERAL]=mensaje_vacio;
siguiente_operacion[ENVIAR_CANTIDAD][FALLO]=REINICIAR_ESP8266;
siguiente_operacion[ENVIAR_CANTIDAD][ACIERTO]=ENVIAR_PREFIJO_PETICION;
siguiente_operacion[ENVIAR_CANTIDAD][LITERAL]=ENVIAR_PREFIJO_PETICION;
configuracion[ENVIAR_CANTIDAD]=ESPERAR_RESPUESTA|ACIERTO_TERMINA|FALLO_TERMINA;
timeout[ENVIAR_CANTIDAD]=5000;
// 9 Enviar el prefijo de la petición
operacion[ENVIAR_PREFIJO_PETICION]=“GET /frigo03/almacenar_temperatura.php?temperatura=”;
mensaje[ENVIAR_PREFIJO_PETICION][FALLO]=mensaje_vacio;
mensaje[ENVIAR_PREFIJO_PETICION][ACIERTO]=mensaje_vacio;
mensaje[ENVIAR_PREFIJO_PETICION][LITERAL]=mensaje_vacio;
siguiente_operacion[ENVIAR_PREFIJO_PETICION][FALLO]=REINICIAR_ESP8266;
siguiente_operacion[ENVIAR_PREFIJO_PETICION][ACIERTO]=ENVIAR_DATOS;
siguiente_operacion[ENVIAR_PREFIJO_PETICION][LITERAL]=ENVIAR_DATOS;
configuracion[ENVIAR_PREFIJO_PETICION]=NO_ESPERAR_RESPUESTA;
timeout[ENVIAR_PREFIJO_PETICION]=10000;
// 10 Enviar la temperatura
//operacion[ENVIAR_DATOS]=”+000.00″; // Definido para cada envío
mensaje[ENVIAR_DATOS][FALLO]=mensaje_vacio;
mensaje[ENVIAR_DATOS][ACIERTO]=mensaje_vacio;
mensaje[ENVIAR_DATOS][LITERAL]=mensaje_vacio;
siguiente_operacion[ENVIAR_DATOS][FALLO]=REINICIAR_ESP8266;
siguiente_operacion[ENVIAR_DATOS][ACIERTO]=ENVIAR_SUFIJO_PETICION;
siguiente_operacion[ENVIAR_DATOS][LITERAL]=ENVIAR_SUFIJO_PETICION;
configuracion[ENVIAR_DATOS]=NO_ESPERAR_RESPUESTA;
timeout[ENVIAR_DATOS]=5000;
// 11 Enviar el sufijo de la petición
operacion[ENVIAR_SUFIJO_PETICION]=” HTTP/1.1\r\nHost: www.servidoriot.com\r\nUser-Agent: ESP8266\r\nConnection: close\r\n\r\n”;
mensaje[ENVIAR_SUFIJO_PETICION][FALLO]=sin_enlace;
mensaje[ENVIAR_SUFIJO_PETICION][ACIERTO]=“CLOSED\r\n\r\nOK\r\n”;
mensaje[ENVIAR_SUFIJO_PETICION][LITERAL]=mensaje_vacio; // “SEND OK”
siguiente_operacion[ENVIAR_SUFIJO_PETICION][FALLO]=REINICIAR_ESP8266;
siguiente_operacion[ENVIAR_SUFIJO_PETICION][ACIERTO]=VERIFICAR_CONEXION;
siguiente_operacion[ENVIAR_SUFIJO_PETICION][LITERAL]=VERIFICAR_CONEXION;
configuracion[ENVIAR_SUFIJO_PETICION]=ESPERAR_RESPUESTA|ACIERTO_TERMINA|FALLO_TERMINA;
timeout[ENVIAR_SUFIJO_PETICION]=20000;
|
Ülaltoodud kood kasutab vektorit (operacion
), et salvestada kogu ülesande moodustavate järjestikuste toimingute tekst. Kasutatakse kahemõõtmelist massiivi (mensaje
) koos kolme analüüsitava vastusega. Nagu eespool selgitatud, tuleb lisaks õiget või valet vastust tähistavale sõnumile otsida ka vastuse lõppu tähistavad teated. Kõik toimingud ei sisalda sama arvu võimalikke vastuseid; Kui vastuseid on vähem, saab kasutada tühja sõnumit, mis kulutab analüüsimisel võimalikult väikese arvu tsükleid (isegi pole see kõige optimaalsem viis). Loogiliselt on vajalik, et minimaalne otsitavate vastuste arv (näites kolm) hõlmaks kõiki toimimisvõimalusi, isegi kui need pole kõik võimalikud.
Võimalikest vastustest rääkides on juba praegu näha, et suvalise vorminguga andmete vastuvõtmisel ei ole sellest näitest kuigi palju kasu. ESP8266 wifi moodul, kuid asi on selles, et koos kasutamise kontekstis mikrokontrollerid see pole tavaline; Kõige tavalisem on saata nende ühendatud andurite kogutud andmeid ja/või saada teavet selle kohta, mida selle juhitavate täiturmehhanismidega teha. Väga väärtuslik teave, mida saab väga hästi ennustada.
Eelmises andmestruktuuris, nii nagu seda tehakse võimalike analüüsitavate vastuste väljendamiseks, kasutatakse ka kahemõõtmelist maatriksit, et määrata igal juhul sooritatav toiming (siguiente_operacion
). Täpsemalt oleme otsustanud vastata kolme tüüpi sõnumitele: ① suvaline tekst (LITERAL
) kontrollimaks, kas Wi-Fi pääsupunkti ja serveriga on ühendus olemas, ② tekst protsessi vigade tuvastamiseks (FALLO
) ja ③ tekst, mis näitab, et toiming on edukalt lõpule viidud (ACIERTO
).
Lõpuks on veel kaks vektorit, et määrata maksimaalne ooteaeg enne loobumist (timeout
) ja täpsustage (configuracion
) kui toiming lõpeb vastust ootamata (ESPERAR_RESPUESTA
) ja sõnumid, mis näitavad suhtluse lõppu. See viimane vektor, illustreerimaks näidet, kuidas mälu saab salvestada, töötab konfiguratsioonibaidi bittidega, et näidata erinevaid olekuid.
Esimene ESP8266 AT käsud andmestruktuurist ootavad alati vastust, milleks võib olla edu- või veateade. Vea ilmnemisel moodul taaskäivitatakse ja see käivitub uuesti ning kui teade näitab, et toiming on õige, liigub see järgmise juurde.
Kui olete serveriga ühenduse loonud, muutub muster. Sel juhul on vaja ① saata edastatava andmepaketi pikkus ja ② koostada päring HTTP fikseeritud tekstiga pluss (temperatuuri) väärtus, mis saadetakse serverisse salvestamiseks. Nende andmete ettevalmistamine toimub iga saadetise puhul ja see tuleb jagada kaheks (teatada pikkus) või kolmeks (saada päring HTTPJärgi) ESP8266 AT tellimus. Ainult viimane osadest, milleks operatsioon on jagatud, ootab vastust.
Sel juhul töötab see probleemideta (võib-olla hoiatab, et moodul on hõivatud), kuid kui andmete pikkus on suurem, tuleb andmeplokid jagada väiksemateks tükkideks ja võib tekkida vajadus isegi oodata, kuna tehakse temperatuuri näiduga, et anda moodulile aega andmete saatmiseks ilma neid täitmata puhver.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#if defined(ARDUINO_AVR_LEONARDO)||defined(ARDUINO_AVR_MEGA2560) /* ¿Es una placa Arduino Mega 2560 o Arduino Leonardo? */
#define SERIE Serial1 /* Si es una placa Arduino Mega 2560 o Arduino Leonardo usar Serial1 */
#else /* En este proyecto solamente uso Placas Leonardo, Mega 2560 y Uno, así que tiene que ser un Arduino Uno si llega hasta aquí */
#define SERIE Serial /* Si es una placa Arduino Uno usar Serial */
#endif
#define VELOCIDAD 115200 // Velocidad (en baudios) al que está configurado el módulo wifi ESP8266 (Cuidado con la placa utilizada, no todas o siempre son capaces de trabajar a una velocidad tan alta)
#define REINICIAR_ESP8266 0 // Índice del vector de operaciones que representa la orden de reinicio del módulo wifi ESP8266
#define DESCONECTAR_WIFI 1
#define MODO_ESTACION 2
#define MODO_SIMPLE 3
#define CONECTAR_WIFI 4
#define VERIFICAR_CONEXION 5
#define CONECTAR_SERVIDOR 6
#define INFORMAR_CANTIDAD 7
#define ENVIAR_CANTIDAD 8
#define ENVIAR_PREFIJO_PETICION 9
#define ENVIAR_DATOS 10
#define ENVIAR_SUFIJO_PETICION 11
#define CANTIDAD_OPERACIONES 12 // Cantidad de operaciones que forma el cuerpo de la aplicación
#define FALLO 0 // Índice del vector de respuestas que representa el mensaje de error
#define FALLO_TERMINA 0B00000001 // 1<<FALLO
#define ACIERTO 1
#define ACIERTO_TERMINA 0B00000010 // 1<<ACIERTO
#define LITERAL 2
#define LITERAL_TERMINA 0B00000100 // 1<<LITERAL
#define CANTIDAD_RESPUESTAS 3 // Cantidad de posibles respuestas que se buscan en el texto recibido desde el ESP8266
#define ESPERAR_RESPUESTA 0B00001000 // 1<<CANTIDAD_RESPUESTAS
#define NO_ESPERAR_RESPUESTA 0B00000000
#define ENVIAR_OPERACION esperando_respuesta=true;SERIE.print(operacion[operacion_actual]);if(configuracion[operacion_actual]&ESPERAR_RESPUESTA){SERIE.print(“\r\n”);}for(unsigned char numero_respuesta=0;numero_respuesta<CANTIDAD_RESPUESTAS;numero_respuesta++){numero_caracter[numero_respuesta]=0;}cronometro_esp8266=millis();
|
Koos teiste juba varem selgitatud makrodega näitab ülaltoodud näitekood, kuidas on määratletud erinevad olekud, mille abil saab määrata, kas vastust oodata, ja kui võimalik, milline teade näitab, et see on lõppenud.
Kuna koodi erinevates punktides saadetakse toiming (kui on aeg saata keskmine temperatuur, kui toimingu ooteaeg on ületatud, kui praegune toiming on edukalt lõpetatud...), aga kuidas seda teha globaalselt loodud, on see määratletud makrona ENVIAR_OPERACION
mis rühmitab saatmisega seotud etapid.
1
2
3
4
5
6
7
8
9
10
11
12
|
// La macro ENVIAR_OPERACION corresponde con las operaciones:
esperando_respuesta=true;
SERIE.print(operacion[operacion_actual]);
if(configuracion[operacion_actual]&ESPERAR_RESPUESTA)
{
SERIE.print(“\r\n”);
}
for(unsigned char numero_respuesta=0;numero_respuesta<CANTIDAD_RESPUESTAS;numero_respuesta++)
{
numero_caracter[numero_respuesta]=0;
}
cronometro_esp8266=millis();
|
Järgnevalt on toodud näite põhiprogrammi kood. Kõige välisem ülesanne on see, kes vastutab temperatuuri proovide võtmise eest, et arvutada keskmine ja iga teatud aja tagant saadetakse see serverisse, kasutades ESP8266 wifi moodul. Kui iga toiming on saadetud, analüüsitakse vastust, et teha kindlaks, milline on järgmine või kas teabe saatmise ülesanne on lõpetatud.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
#include “ESP8266_operacion_compleja_varias_ordenes_AT.h”
#define PIN_TEMPERATURA A0 // Pin analógico al que se conecta la salida del sensor de temperatura LM35
#define INTERVALO_LECTURA_TEMPERATURA 30000 // Leer la temperatura cada 30 segundos (30*1000)
#define INTERVALO_GRABACION_TEMPERATURA 300000 // Grabar la media de la temperatura cada 5 minutos (5*60*1000)
unsigned long muestras=0; // Número de veces que se ha medido la temperatura (para calcular la media)
float temperatura; // de -55.0 °C a +150 °C | de 0 V a 2.050 V | de -550 mV a +1500 mV | analogRead*5.0/1023.0*100-55.0 analogRead/2.46-55.0
float media_temperaturas=0.0;
unsigned long cronometro_lectura_temperatura;
unsigned long cronometro_grabacion_temperatura;
char *mensaje_fallo=“ERROR\r\n”;
char *mensaje_acierto=“OK\r\n”;
char *sin_enlace=“link is not\r\n”;
char *mensaje_vacio=“\f”;
char *operacion[CANTIDAD_OPERACIONES]; // Matriz de punteros a constantes de caracteres con las operaciones que se envían al ESP8266 (no solo órdenes AT, aunque seguro que algunas son órdenes AT)
char *mensaje[CANTIDAD_OPERACIONES][CANTIDAD_RESPUESTAS]; // Mensajes de respuesta
unsigned char siguiente_operacion[CANTIDAD_OPERACIONES][CANTIDAD_RESPUESTAS];
unsigned char configuracion[CANTIDAD_OPERACIONES];
unsigned int timeout[CANTIDAD_OPERACIONES];
unsigned char numero_caracter[CANTIDAD_RESPUESTAS];
unsigned int longitud_peticion;
char texto_longitud_peticion[4]; // 3 caracteres para almacenar la longitud de la petición en formato texto
char valor_enviado[9]; // signo + 4 enteros + punto + 2 decimales + \0 = 9
unsigned long cronometro_esp8266;
unsigned char operacion_actual; // Número de operación que se está procesando
unsigned char proxima_operacion; // Siguiente operación que se procesará cuando termine la actual
char lectura_serie;
boolean grabando_datos=false;
boolean esperando_respuesta;
void setup()
{
#include “inicializar_operaciones.h”
longitud_peticion=strlen(operacion[ENVIAR_PREFIJO_PETICION])+strlen(operacion[ENVIAR_SUFIJO_PETICION]);
SERIE.begin(VELOCIDAD); // Configurar el puerto serie de Arduino a la velocidad del ESP8266
//delay(8000); // En fase de pruebas se puede introducir un tiempo de espera para conectar una consola/sniffer
cronometro_lectura_temperatura=millis();
cronometro_grabacion_temperatura=millis();
}
void loop()
{
if((unsigned long)(millis()–cronometro_lectura_temperatura)>INTERVALO_LECTURA_TEMPERATURA)
{
cronometro_lectura_temperatura=millis();
temperatura=analogRead(PIN_TEMPERATURA)/2.46–55.0;
muestras++;
media_temperaturas=(float)temperatura/(float)muestras+media_temperaturas*(float)(muestras–1)/(float)(muestras);
}
if(grabando_datos)
{
if((unsigned long)(millis()–cronometro_esp8266)>timeout[operacion_actual]) // Si se ha superado el tiempo de espera máximo
{
operacion_actual=siguiente_operacion[operacion_actual][FALLO]; // Pasar a la operación correspondiente al error
ENVIAR_OPERACION
}
else // Si no se ha superado el tiempo de espera máximo
{
if(configuracion[operacion_actual]&ESPERAR_RESPUESTA) // Si la siguiente operación depende de la respuesta a la actual desde el ESP8266 hay que leer la información que llegue desde el puerto serie
{
while(SERIE.available())
{
lectura_serie=SERIE.read();
for(unsigned char numero_respuesta=0;numero_respuesta<CANTIDAD_RESPUESTAS;numero_respuesta++) // Comparar la letra cargada desde el puerto serie con la correspondiente de los mensajes disponibles
{
if(lectura_serie==mensaje[operacion_actual][numero_respuesta][numero_caracter[numero_respuesta]]) // Si el dato que ha llegado es igual al que correspondería del mensaje buscado…
{
numero_caracter[numero_respuesta]++; // Como el carácter coincide, se puede comparar con el siguiente lo próximo que llegue por el puerto serie
if(mensaje[operacion_actual][numero_respuesta][numero_caracter[numero_respuesta]]==0) // Si el carácter que toca es \0 es que se ha terminado de analizar el mensaje
{
if(esperando_respuesta) // Todavía no se ha encontrado un mensaje que determine la siguiente operación
{
proxima_operacion=siguiente_operacion[operacion_actual][numero_respuesta]; // La próxima operación que habrá que procesar será la que indique el mensaje encontrado para la operación actual
esperando_respuesta=false; // Ya se ha encontrado un mensaje que determina la siguiente operación
}
if(configuracion[operacion_actual]&(1<<numero_respuesta)) // Si el mensaje encontrado es uno de los que terminan la operación…
{
if(operacion_actual+1==CANTIDAD_OPERACIONES) // Se ha completado la última operación de la tarea compleja
{
grabando_datos=false; // Se ha terminado la tarea compleja (grabar datos en el servidor)
}
else // No es la última operación de la tarea compleja, hay que seguir realizando otras operaciones
{
operacion_actual=proxima_operacion; // Ejecutar la siguiente operación
ENVIAR_OPERACION
}
}
}
}
else // Si la letra recibida no es igual que la correspondiente del mensaje
{
numero_caracter[numero_respuesta]=0; // Empezar a comparar desde la primera letra del mensaje
}
}
}
}
else // Si no hay que esperar datos desde el puerto serie
{
operacion_actual=siguiente_operacion[operacion_actual][ACIERTO];
ENVIAR_OPERACION
}
}
}
else
{
if((unsigned long)(millis()–cronometro_grabacion_temperatura)>INTERVALO_GRABACION_TEMPERATURA)
{
cronometro_grabacion_temperatura=millis();
dtostrf(media_temperaturas,4,2,valor_enviado); // snprintf(valor_enviado,9,”%+3.2f”,media_temperaturas); // printf y derivadas no funcionan en AVR
snprintf(texto_longitud_peticion,4,“%d”,longitud_peticion+strlen(valor_enviado));
grabando_datos=true;
operacion_actual=VERIFICAR_CONEXION;
operacion[ENVIAR_DATOS]=valor_enviado;
operacion[ENVIAR_CANTIDAD]=texto_longitud_peticion;
ENVIAR_OPERACION
}
}
}
|
Loogiliselt saab eelmisel koodil läbi viia mitmeid optimeerimistoiminguid, kuid kuna see on näide, et mõista, kuidas ESP8266 Üldisemalt tasub keskenduda vaid mõnele aspektile, millest esimene on andmestruktuur. Tundub, et asi on loogiline kasutage programmeerimiskeele andmestruktuuri (struct
), et esindada töödeldavat teavet: ESP8266 AT käsud ja analüüsitavad sõnumid.
Kasutage struktuuri (struct
) andmete salvestamine näidismassiivide asemel (nende põhjal) on triviaalne ja kuigi see võib anda elegantsema koodi, ei tähenda see tulemuse paranemist. Tõeline alternatiiv, mida pakub kasutamine struct
on rakendada, nagu allpool selgitatud, muutuva pikkusega struktuurides, mis sisaldavad "sisemisi" andmeid millele nad viitavad. Nii ei oleks näiteks vaja, et toimingul oleks analüüsimiseks kindel arv vastuseid.
See lähenemisviis viitab sellele, et see on parim viis lahenduse rakendamiseks, kuid puuduseks on see, et see oleks vajalik kasutada dünaamilist mälujaotust, riskantne praktika koos a mikrokontroller mis nõuab käitusajal kasutatava mälu hoolikat mõõtmist, kuna kompilaator vaevalt suudab meid selle eest hoiatada ja on teatud võimalus mälu (või pinu) ammendada, millel on programmi täitmisele saatuslikud tagajärjed.
Koodi optimeerimise reas on huvitav meeles pidada, et seda tüüpi programmis, mis kasutab suurt hulka teksti, võib säästa mäluruumi SRAM tekstistringide salvestamine programmi mällu (välklamp) koos makroga F()
. Järgmistel ekraanipiltidel näete erinevaid programme ja dünaamilist mälujaotust tavalise tekstikasutuse ja makro kasutamisega F()
.
Seoses toimingutega, mida tehakse vastavalt teabele, mis saabub ESP8266 wifi moodul, alternatiivina koodist sõnumi kontrollimisele ja ühe või teise sooritamisele vastavalt sellele, mis vastu võetakse, saab sellesse andmestruktuuri salvestada olekuindikaatorite asemel osutavad funktsioonidele, mis täidavad iga ülesannet (lipud), mis hoiatavad teatud oleku eest, et rakendus vastutab näiteks põhiahelas haldamise eest.
Järgmine on näide päringute andmete salvestamiseks struktuuridest ESP8266 (andmetüüp operacion_esp8266
) ja nende vastused (andmetüüp respuesta_esp8266
).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
typedef struct estructura_operacion_esp8266 operacion_esp8266; // Se define el tipo de datos operacion_esp8266 que corresponde con la estructura (struct) llamada estructura_operacion_esp8266 que se define más adelante
typedef struct estructura_respuesta_esp8266 respuesta_esp8266; // Se define el tipo de datos respuesta_esp8266 que corresponde con la estructura (struct) llamada struct estructura_respuesta_esp8266 que se define más adelante
struct estructura_operacion_esp8266
{
char *peticion; // Datos que se envían al ESP8266 para iniciar una operación (como una orden AT, pero también algo como la petición a un servidor…)
unsigned char cantidad_respuestas; // Número de posibles respuestas del ESP8266 que se van a analizar, que puede ser variable en cada petición (no solo OK y ERROR)
unsigned char timeout; // Tiempo (segundos) que se espera la respuesta del ESP8266 antes de desistir
respuesta_esp8266 *respuesta; // Respuestas (estructura) que se esperan de esta operación
};
struct estructura_respuesta_esp8266
{
char *mensaje; // Mensaje que se espera recibir desde el ESP8266
unsigned char posicion_mensaje; // Posición (letra) que se está comparando con la recibida desde el ESP8266
//boolean estado; // El estado se representa por un valor booleano (por ejemplo ¿se ha encontrado ya esta respuesta? para no seguir buscándola)
//unsigned char *estado; // El estado se representa con un texto (de longitud variable)
unsigned char estado; // El estado se establece con 8 banderas, una por bit
operacion_esp8266 *operacion; // Puntero a operación que se ejecutará si se encuentra esta respuesta en el mensaje devuelto por el ESP8266
};
operacion_esp8266 comprobar_conexion;
respuesta_esp8266 respuesta_OK;
respuesta_esp8266 respuesta_ERROR;
|
Toimingut esindava struktuurina (andmed, mis saadetakse ESP8266 wifi moodul) viitab struktuurile, millega vastused on määratletud, ja vastuste struktuurile operatsioonide struktuurile, esmalt on vaja deklareerida mõlemad, määratledes uue andmetüübi ja seejärel määratledes selle sisu.
Eelmises näites arvatakse, et seda sisaldav programm on valinud a oleku indikaator, mis peab vastama koodist ligipääsetavale muutujale, mis vastutab ühe või muu nimetatud väärtusega näidatud toimingu tegemise eest. Kui vastuseks ESP8266 Teatud teksti analüüsimisel võtab olek väärtuse, mis näitab vastava vastuse struktuuri.
Nagu varem öeldud, oleks veel üks alternatiiv, kas staatuse indikaator asendada või täiendada salvestada funktsiooni võrdlusstruktuuri (osuti), mida kutsutakse välja vastuses teatud tekstiga kohtumisel ESP8266 wifi moodul.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
typedef struct estructura_operacion_esp8266 operacion_esp8266; // Se define el tipo de datos operacion_esp8266 que corresponde con la estructura (struct) llamada estructura_operacion_esp8266 que se define más adelante
typedef struct estructura_respuesta_esp8266 respuesta_esp8266; // Se define el tipo de datos respuesta_esp8266 que corresponde con la estructura (struct) llamada struct estructura_respuesta_esp8266 que se define más adelante
struct estructura_operacion_esp8266
{
char *peticion; // Datos que se envían al ESP8266 para iniciar una operación (como una orden AT, pero también algo como la petición a un servidor…)
unsigned char cantidad_respuestas; // Número de posibles respuestas del ESP8266 que se van a analizar, que puede ser variable en cada petición (no solo OK y ERROR)
unsigned char timeout; // Tiempo (segundos) que se espera la respuesta del ESP8266 antes de desistir
respuesta_esp8266 *respuesta; // Respuestas (estructura) que se esperan de esta operación
};
struct estructura_respuesta_esp8266
{
char *mensaje; // Mensaje que se espera recibir desde el ESP8266
unsigned char posicion_mensaje; // Posición (letra) que se está comparando con la recibida desde el ESP8266
//boolean estado; // El estado se representa por un valor booleano (por ejemplo ¿se ha encontrado ya esta respuesta? para no seguir buscándola)
//unsigned char *estado; // El estado se representa con un texto (de longitud variable)
unsigned char estado; // El estado se establece con 8 banderas, una por bit
float (*accion)(unsigned char,unsigned char); // Puntero a la función que se llama si se encuentra la respuesta
operacion_esp8266 *operacion; // Puntero a operación que se ejecutará si se encuentra esta respuesta en el mensaje devuelto por el ESP8266
};
operacion_esp8266 comprobar_conexion;
respuesta_esp8266 respuesta_OK;
respuesta_esp8266 respuesta_ERROR;
|
Eelmises näites on see lisatud andmestruktuuri, mida kasutatakse vastuse töötlemiseks ESP8266 wifi moodul osuti (oletatavale) funktsioonile, mis tagastab tüüpi andmeid float
(võib olla analoognäidu kaalutud väärtus) ja millele antakse argumentidena kaks baiti (kaks unsigned char
mis võib olla viik, millelt analoogsisendit loetakse, ja see, mis aktiveerib hüpoteetilise integraadi ENABLE).
Arenduses jaoks MCU, vastupidiselt suuremate süsteemide arendusstiilile, pole globaalsete muutujate kasutamine komplekti juhtiva rakenduse (globaalse) käitumise määratlemisel nii haruldane, nii et seda tüüpi definitsioonide leidmine pole eriti haruldane. funktsioonidena ilma parameetriteta ja mis ei tagasta väärtusi, midagi taolist void (*accion)();
Kui töötate sellise andmete esitamise viisiga, kasutage struct
muutuva pikkusega andmete puhul on vaja mälu dünaamiliselt eraldada malloc()
(o new()
, kui kasutatakse objekte), mis kasutab parameetrina eraldatud mälumahtu ja tagastab kursori reserveeritud mäluala algusesse. Koos sizeof()
Salvestatud tüübi järgi, korrutatuna kasutatud elementide arvuga, saate vajaliku mälumahu. Näide selle kasutamisega ja ilma selleta on näha allolevatel ekraanipiltidel. malloc()
; Esimesel juhul olge programmi kasutatava mäluga ettevaatlik, peate laadima seda funktsiooni sisaldava raamatukogu.
Kui toimingud ESP8266 wifi moodul varieerub kogu programmi täitmise ajal, tuleb vabastada mälu, mida ei kasutata free()
(o delete()
, kui tegemist on objektidega). Kuigi on mõistlik eeldada, et koostaja (GCC) optimeerib programmi, et vältida mälu jaotamist, kindlasti ei ole jõudlus nii optimaalne kui staatiliselt eraldatud mäluga töötamine.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
error_operacion.mensaje=“ERROR\r\n”;
error_operacion.termina_operacion=true;
error_operacion.operacion=&reiniciar_esp8266;
error_enlace.mensaje=“link is not\r\n”;
error_enlace.termina_operacion=true;
error_enlace.operacion=&reiniciar_esp8266;
reiniciar_esp8266_correcto.mensaje=“ready\r\n”;
reiniciar_esp8266_correcto.termina_operacion=true;
reiniciar_esp8266_correcto.operacion=&desconectar_wifi;
desconectar_wifi_correcto.mensaje=mensaje_acierto;
desconectar_wifi_correcto.termina_operacion=true;
desconectar_wifi_correcto.operacion=&establecer_modo_estacion;
establecer_modo_estacion_correcto.mensaje=mensaje_acierto;
establecer_modo_estacion_correcto.termina_operacion=true;
establecer_modo_estacion_correcto.operacion=&establecer_modo_simple;
establecer_modo_simple_correcto.mensaje=mensaje_acierto;
establecer_modo_simple_correcto.termina_operacion=true;
establecer_modo_simple_correcto.operacion=&conectar_wifi;
conectar_wifi_correcto.mensaje=mensaje_acierto;
conectar_wifi_correcto.termina_operacion=true;
conectar_wifi_correcto.operacion=&verificar_conexion;
verificar_conexion_correcto.mensaje=“STATUS:5”;
verificar_conexion_correcto.termina_operacion=false;
verificar_conexion_correcto.operacion=&conectar_servidor;
verificar_conexion_terminado.mensaje=mensaje_acierto;
verificar_conexion_terminado.termina_operacion=true;
verificar_conexion_terminado.operacion=&reiniciar_esp8266;
conectar_servidor_correcto.mensaje=“CONNECT”;
conectar_servidor_correcto.termina_operacion=false;
conectar_servidor_correcto.operacion=&informar_cantidad;
conectar_servidor_terminado.mensaje=mensaje_acierto;
conectar_servidor_terminado.termina_operacion=true;
conectar_servidor_terminado.operacion=&reiniciar_esp8266;
informar_cantidad_correcto.mensaje=mensaje_acierto;
informar_cantidad_correcto.termina_operacion=true;
informar_cantidad_correcto.operacion=&enviar_cantidad;
enviar_cantidad_correcto.mensaje=“>”;
enviar_cantidad_correcto.termina_operacion=true;
enviar_cantidad_correcto.operacion=&enviar_prefijo;
enviar_prefijo_correcto.operacion=&enviar_datos;
enviar_datos_correcto.operacion=&enviar_sufijo;
enviar_sufijo_correcto.mensaje=“CLOSED\r\n\r\nOK\r\n”;
enviar_sufijo_correcto.termina_operacion=true;
enviar_sufijo_correcto.operacion=&verificar_conexion;
reiniciar_esp8266.peticion=“AT+RST”;
reiniciar_esp8266.timeout=15000;
reiniciar_esp8266.cantidad_respuestas=2;
reiniciar_esp8266.respuesta=malloc(sizeof(respuesta_esp8266*)*reiniciar_esp8266.cantidad_respuestas);
reiniciar_esp8266.respuesta[FALLO]=&error_operacion;
reiniciar_esp8266.respuesta[ACIERTO]=&reiniciar_esp8266_correcto;
desconectar_wifi.peticion=“AT+CWQAP”;
desconectar_wifi.timeout=2500;
desconectar_wifi.cantidad_respuestas=2;
desconectar_wifi.respuesta=malloc(sizeof(respuesta_esp8266*)*desconectar_wifi.cantidad_respuestas);
desconectar_wifi.respuesta[FALLO]=&error_operacion;
desconectar_wifi.respuesta[ACIERTO]=&desconectar_wifi_correcto;
establecer_modo_estacion.peticion=“AT+CWMODE=1”;
establecer_modo_estacion.timeout=2500;
establecer_modo_estacion.cantidad_respuestas=2;
establecer_modo_estacion.respuesta=malloc(sizeof(respuesta_esp8266*)*establecer_modo_estacion.cantidad_respuestas);
establecer_modo_estacion.respuesta[FALLO]=&error_operacion;
establecer_modo_estacion.respuesta[ACIERTO]=&establecer_modo_estacion_correcto;
establecer_modo_simple.peticion=“AT+CIPMUX=0”;
establecer_modo_simple.timeout=2500;
establecer_modo_simple.cantidad_respuestas=2;
establecer_modo_simple.respuesta=malloc(sizeof(respuesta_esp8266*)*establecer_modo_simple.cantidad_respuestas);
establecer_modo_simple.respuesta[FALLO]=&error_operacion;
establecer_modo_simple.respuesta[ACIERTO]=&establecer_modo_simple_correcto;
conectar_wifi.peticion=“AT+CWJAP=\”polaridad.es\”,\”54lLij1RiTn3MEd3v41C\””;;
conectar_wifi.timeout=20000;
conectar_wifi.cantidad_respuestas=2;
conectar_wifi.respuesta=malloc(sizeof(respuesta_esp8266*)*conectar_wifi.cantidad_respuestas);
conectar_wifi.respuesta[FALLO]=&error_operacion;
conectar_wifi.respuesta[ACIERTO]=&conectar_wifi_correcto;
verificar_conexion.peticion=“AT+CIPSTATUS”;
verificar_conexion.timeout=5000;
verificar_conexion.cantidad_respuestas=3;
verificar_conexion.respuesta=malloc(sizeof(respuesta_esp8266*)*verificar_conexion.cantidad_respuestas);
verificar_conexion.respuesta[FALLO]=&error_operacion;
verificar_conexion.respuesta[ACIERTO]=&verificar_conexion_correcto;
verificar_conexion.respuesta[OTRO_MENSAJE]=&verificar_conexion_terminado;
conectar_servidor.peticion=“AT+CIPSTART=\”TCP\”,\”servidoriot.com\”,80″;
conectar_servidor.timeout=15000;
conectar_servidor.cantidad_respuestas=3;
conectar_servidor.respuesta=malloc(sizeof(respuesta_esp8266*)*conectar_servidor.cantidad_respuestas);
conectar_servidor.respuesta[FALLO]=&error_operacion;
conectar_servidor.respuesta[ACIERTO]=&conectar_servidor_correcto;
conectar_servidor.respuesta[OTRO_MENSAJE]=&conectar_servidor_terminado; // OK, no significa que haya conexión pero sí termina la operación
informar_cantidad.peticion=“AT+CIPSEND=”;
informar_cantidad.timeout=1000;
informar_cantidad.cantidad_respuestas=1;
informar_cantidad.respuesta=malloc(sizeof(respuesta_esp8266*)*informar_cantidad.cantidad_respuestas);
informar_cantidad.respuesta[0]=&informar_cantidad_correcto;
//enviar_cantidad.peticion=””; // Se asigna cuando se conoce el valor que se va a enviar y se puede calcular la longitud que ocupa (número de caracteres)
enviar_cantidad.timeout=5000;
enviar_cantidad.cantidad_respuestas=2;
enviar_cantidad.respuesta=malloc(sizeof(respuesta_esp8266*)*enviar_cantidad.cantidad_respuestas);
enviar_cantidad.respuesta[FALLO]=&error_enlace;
enviar_cantidad.respuesta[ACIERTO]=&enviar_cantidad_correcto;
enviar_prefijo.peticion=“GET /frigo03/almacenar_temperatura.php?temperatura=”;
enviar_prefijo.timeout=10000;
enviar_prefijo.cantidad_respuestas=1;
enviar_prefijo.respuesta=malloc(sizeof(respuesta_esp8266*)*enviar_prefijo.cantidad_respuestas);
enviar_prefijo.respuesta[0]=&enviar_prefijo_correcto;
//enviar_datos.peticion=””; // Se asigna en cuando se conoce el valor que se va a enviar
enviar_datos.timeout=5000;
enviar_datos.cantidad_respuestas=1;
enviar_datos.respuesta=malloc(sizeof(respuesta_esp8266*)*enviar_datos.cantidad_respuestas);
enviar_datos.respuesta[0]=&enviar_datos_correcto;
enviar_sufijo.peticion=” HTTP/1.1\r\nHost: www.servidoriot.com\r\nUser-Agent: ESP8266\r\nConnection: close\r\n\r\n”;
enviar_sufijo.timeout=20000;
enviar_sufijo.cantidad_respuestas=2;
enviar_sufijo.respuesta=malloc(sizeof(respuesta_esp8266*)*enviar_sufijo.cantidad_respuestas);
enviar_sufijo.respuesta[FALLO]=&error_enlace;
enviar_sufijo.respuesta[ACIERTO]=&enviar_sufijo_correcto;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
#if defined(ARDUINO_AVR_LEONARDO)||defined(ARDUINO_AVR_MEGA2560) /* ¿Es una placa Arduino Mega 2560 o Arduino Leonardo? */
#define SERIE Serial1 /* Si es una placa Arduino Mega 2560 o Arduino Leonardo usar Serial1 */
#else /* En este proyecto solamente uso Placas Leonardo, Mega 2560 y Uno, así que tiene que ser un Arduino Uno si llega hasta aquí */
#define SERIE Serial /* Si es una placa Arduino Uno usar Serial */
#endif
#define VELOCIDAD 115200 // Velocidad (en baudios) al que está configurado el módulo wifi ESP8266 (Cuidado con la placa utilizada, no todas o siempre son capaces de trabajar a una velocidad tan alta)
#define FALLO 0 // Índice del vector de respuestas que representa el mensaje de error
#define FALLO_TERMINA 0B00000001 // 1<<FALLO
#define ACIERTO 1
#define ACIERTO_TERMINA 0B00000010 // 1<<ACIERTO
#define OTRO_MENSAJE 2
#define OTRO_MENSAJE_TERMINA 0B00000100 // 1<<OTRO_MENSAJE
#define CANTIDAD_RESPUESTAS 3 // Cantidad de posibles respuestas que se buscan en el texto recibido desde el ESP8266
#define ESPERAR_RESPUESTA 0B00001000 // 1<<CANTIDAD_RESPUESTAS
#define NO_ESPERAR_RESPUESTA 0B00000000
#define ENVIAR_OPERACION esperando_respuesta=true;SERIE.print((*operacion_actual).peticion);if((*operacion_actual).cantidad_respuestas>1){SERIE.print(“\r\n”);for(unsigned char numero_respuesta=0;numero_respuesta<(*operacion_actual).cantidad_respuestas;numero_respuesta++){numero_caracter[numero_respuesta]=0;}}cronometro_esp8266=millis();
#define PIN_TEMPERATURA A0 // Pin analógico al que se conecta la salida del sensor de temperatura LM35
#define INTERVALO_LECTURA_TEMPERATURA 30000 // Leer la temperatura cada 30 segundos (30*1000)
#define INTERVALO_GRABACION_TEMPERATURA 300000 // Grabar la media de la temperatura cada 5 minutos (5*60*1000)
unsigned long muestras=0; // Número de veces que se ha medido la temperatura (para calcular la media)
float temperatura; // de -55.0 °C a +150 °C | de 0 V a 2.050 V | de -550 mV a +1500 mV | analogRead*5.0/1023.0*100-55.0 analogRead/2.46-55.0
float media_temperaturas=0.0;
unsigned long cronometro_lectura_temperatura;
unsigned long cronometro_grabacion_temperatura;
char *mensaje_acierto=“OK\r\n”;
typedef struct estructura_operacion_esp8266 operacion_esp8266; // Se define el tipo de datos operacion_esp8266 que corresponde con la estructura (struct) llamada estructura_operacion_esp8266 que se define más adelante
typedef struct estructura_respuesta_esp8266 respuesta_esp8266; // Se define el tipo de datos respuesta_esp8266 que corresponde con la estructura (struct) llamada struct estructura_respuesta_esp8266 que se define más adelante
struct estructura_operacion_esp8266
{
char *peticion; // Datos que se envían al ESP8266 para iniciar una operación (como una orden AT, pero también algo como la petición a un servidor…)
unsigned int timeout; // Tiempo (segundos) que se espera la respuesta del ESP8266 antes de desistir
bool espera_respuesta; // Si no espera respuesta en cuanto se termine de enviar la orden se puede pasar a la siguiente
unsigned char cantidad_respuestas; // Número de posibles respuestas del ESP8266 que se van a analizar, que puede ser variable en cada petición (no solo OK y ERROR)
respuesta_esp8266 **respuesta; // Respuestas (estructura) que se esperan de esta operación
};
struct estructura_respuesta_esp8266
{
char *mensaje; // Mensaje que se espera recibir desde el ESP8266
bool termina_operacion; // Cuando se termina de leer el mensaje ha terminado la operación
operacion_esp8266 *operacion; // Puntero a operación que se ejecutará si se encuentra esta respuesta en el mensaje devuelto por el ESP8266
};
operacion_esp8266 *operacion_actual; // Operación sobre el ESP8266 que se está ejecutando actualmente
operacion_esp8266 *proxima_operacion; // Siguiente operación que se procesará cuando termine la actual
unsigned int longitud_peticion; // Número de caracteres que ocupa la petición HTTP
char texto_longitud_peticion[4]; // 3 caracteres para almacenar la longitud de la petición en formato texto
char valor_enviado[9]; // signo + 4 enteros + punto + 2 decimales + \0 = 9
unsigned long cronometro_esp8266; // Cronómetro para controlar el tiempo máximo de respuesta del ESP8266 antes de desistir
char lectura_serie; // buffer con el carácter leído desde el ESP8266
boolean grabando_datos=false; // Verdadero cuando han terminado todas las operaciones necesarias para grabar los datos
boolean esperando_respuesta; // Verdadero si aún no se ha encontrado una de los mensajes que indica que ha terminado la respuesta
unsigned char numero_caracter[CANTIDAD_RESPUESTAS]; // Número de orden de la letra del mensaje-respuesta que se está almacenando (una matriz de, como máximo, el mayor número de respuestas posible)
operacion_esp8266 reiniciar_esp8266; // Reiniciar el módulo wifi ESP8266
operacion_esp8266 desconectar_wifi; // Desconectar del punto de acceso por defecto (si fuera el caso)
operacion_esp8266 establecer_modo_estacion; // Establecer el modo de estación (no punto de acceso)
operacion_esp8266 establecer_modo_simple; // Establecer el modo de conexión simple
operacion_esp8266 conectar_wifi; // Conectar al punto de acceso
operacion_esp8266 verificar_conexion; // Verificar si hay conexión
operacion_esp8266 conectar_servidor; // Conectar al servidor
operacion_esp8266 informar_cantidad; // Avisar de la cantidad de datos que se envían
operacion_esp8266 enviar_cantidad; // Enviar cantidad
operacion_esp8266 enviar_prefijo; // Enviar el prefijo de la petición
operacion_esp8266 enviar_datos; // Enviar la temperatura
operacion_esp8266 enviar_sufijo; // Enviar el sufijo de la petición
respuesta_esp8266 error_operacion; // Todas las respuestas “ERROR” reinician el módulo wifi ESP8266
respuesta_esp8266 error_enlace; // Las respuestas “link is not” también reinician el módulo wifi ESP8266
respuesta_esp8266 reiniciar_esp8266_correcto;
respuesta_esp8266 desconectar_wifi_correcto;
respuesta_esp8266 establecer_modo_estacion_correcto;
respuesta_esp8266 establecer_modo_simple_correcto;
respuesta_esp8266 conectar_wifi_correcto;
respuesta_esp8266 verificar_conexion_correcto;
respuesta_esp8266 verificar_conexion_terminado;
respuesta_esp8266 conectar_servidor_correcto;
respuesta_esp8266 conectar_servidor_terminado;
respuesta_esp8266 informar_cantidad_correcto;
respuesta_esp8266 enviar_cantidad_correcto;
respuesta_esp8266 enviar_prefijo_correcto;
respuesta_esp8266 enviar_datos_correcto;
respuesta_esp8266 enviar_sufijo_correcto;
void setup()
{
#include “inicializar_operaciones.h”
longitud_peticion=strlen(enviar_prefijo.peticion)+strlen(enviar_sufijo.peticion);
SERIE.begin(VELOCIDAD); // Configurar el puerto serie de Arduino a la velocidad del ESP8266
//delay(8000); // En fase de pruebas se puede introducir un tiempo de espera para conectar una consola/sniffer
cronometro_lectura_temperatura=millis();
cronometro_grabacion_temperatura=millis();
}
void loop()
{
if((unsigned long)(millis()–cronometro_lectura_temperatura)>INTERVALO_LECTURA_TEMPERATURA)
{
cronometro_lectura_temperatura=millis();
temperatura=analogRead(PIN_TEMPERATURA)/2.46–55.0;
muestras++;
media_temperaturas=(float)temperatura/(float)muestras+media_temperaturas*(float)(muestras–1)/(float)(muestras);
}
if(grabando_datos)
{
if((unsigned long)(millis()–cronometro_esp8266)>(unsigned long)(*operacion_actual).timeout) // Si se ha superado el tiempo de espera máximo
{
operacion_actual=(*(*operacion_actual).respuesta[FALLO]).operacion; // Pasar a la operación correspondiente al error
ENVIAR_OPERACION
}
else // Si no se ha superado el tiempo de espera máximo
{
if((*operacion_actual).cantidad_respuestas>1) // Si la siguiente operación depende de la respuesta a la actual desde el ESP8266 hay que leer la información que llegue desde el puerto serie
{
while(SERIE.available())
{
lectura_serie=SERIE.read();
for(unsigned char numero_respuesta=0;numero_respuesta<(*operacion_actual).cantidad_respuestas;numero_respuesta++) // Comparar la letra cargada desde el puerto serie con la correspondiente de los mensajes disponibles
{
if(lectura_serie==(*(*operacion_actual).respuesta[numero_respuesta]).mensaje[numero_caracter[numero_respuesta]]) // Si el dato que ha llegado es igual al que correspondería del mensaje buscado…
{
numero_caracter[numero_respuesta]++; // Como el carácter coincide, se puede comparar con el siguiente lo próximo que llegue por el puerto serie
if((*(*operacion_actual).respuesta[numero_respuesta]).mensaje[numero_caracter[numero_respuesta]]==0) // Si el carácter que toca es \0 es que se ha terminado de analizar el mensaje
{
if(esperando_respuesta) // Todavía no se ha encontrado un mensaje que determine la siguiente operación
{
proxima_operacion=(*(*operacion_actual).respuesta[numero_respuesta]).operacion; // La próxima operación que habrá que procesar será la que indique el mensaje encontrado para la operación actual
esperando_respuesta=false; // Ya se ha encontrado un mensaje que determina la siguiente operación
}
if((*(*operacion_actual).respuesta[numero_respuesta]).termina_operacion) // Si el mensaje encontrado es uno de los que terminan la operación…
{
if(operacion_actual==&enviar_sufijo) // Se ha completado la última operación de la tarea compleja
{
grabando_datos=false; // Se ha terminado la tarea compleja (grabar datos en el servidor)
}
else // No es la última operación de la tarea compleja, hay que seguir realizando otras operaciones
{
operacion_actual=proxima_operacion; // Ejecutar la siguiente operación
ENVIAR_OPERACION
}
}
}
}
else // Si la letra recibida no es igual que la correspondiente del mensaje
{
numero_caracter[numero_respuesta]=0; // Empezar a comparar desde la primera letra del mensaje
}
}
}
}
else // Si no hay que esperar datos desde el puerto serie
{
operacion_actual=(*(*operacion_actual).respuesta[0]).operacion;
ENVIAR_OPERACION
}
}
}
else
{
if((unsigned long)(millis()–cronometro_grabacion_temperatura)>INTERVALO_GRABACION_TEMPERATURA)
{
cronometro_grabacion_temperatura=millis();
dtostrf(media_temperaturas,4,2,valor_enviado); // snprintf(valor_enviado,9,”%+3.2f”,media_temperaturas); // printf y derivadas no funcionan en AVR
snprintf(texto_longitud_peticion,4,“%d”,longitud_peticion+strlen(valor_enviado));
grabando_datos=true;
operacion_actual=&verificar_conexion;
enviar_datos.peticion=valor_enviado;
enviar_cantidad.peticion=texto_longitud_peticion;
ENVIAR_OPERACION
}
}
}
|
Kuigi selles näites (mõlemas teostuses) pole sellel erilist mõtet, tuleb operatsiooni üldistamiseks, et seda ka muudel juhtudel rakendada, märkida, et andmete saatmine kordab alati sama protokolli: teatage saadetavate baitide arv, oodake indikaatorit (>) ja saatke andmed.
Kuna selles näites kasutatakse seda ainult üks kord (kogu päring tehakse ühes paketis), ei tundu see kuigi kasulik, kuid üldiselt võib olla vaja teha sama toiminguga mitu saatmist, sealhulgas juhtudel, kui need peavad olema edastada märkimisväärses koguses andmeid, mis peavad olema killustatud, et vältida mälu ületäitumist ESP8266.
Selle käitumise rakendamiseks saab kasutada ühenduse kahte viimast elementi nii, et iga kord, kui andmed saadetakse, täidetakse andmed vastavate väärtustega: esimesel juhul saadetud baitide arv ja teisel juhul ( osa) taotlusest. edastada.
Määramise ja saatmise kordamiseks saab erinevaid edastatavaid elemente salvestada vektorisse. See uus vektor määrab keerulise toimingu lõpu ja mitte viimase toimingu nagu seni.
1 kommentaar