Arduino'dan bir ESP8266 wifi modülünde temel işlemler
Cuando etkileyici Piyasadaki ilk modülleri piyasaya sürdü kablosuz internet entegre ile ESP8266 y el firmware AT komutlarını kullanarak bunu nasıl ele alacağız, biz kullanıcıların ilgisini çeken şey onu derlemelere entegre etmekti. mikrodenetleyiciler ve sorunlar (eskiden) karanlığı bilmekten ibaretti ESP8266 AT komut tablosu, beslenme ihtiyaçları veya ESP8266 ürün yazılımı güncellemesi.
Daha sonra hızlı bir şekilde programlamak için alternatifler geldi. ESP8266 ve modül uygulamaları kablosuz internet başka endişelere yol açan çok farklı formatlar: hangi ESP8266 wifi modülünü seçmelisiniz farklı antenlerin menziline (harici olanlar dahil) veya bu yeni modüllerin donanımlarımıza fiziksel entegrasyonuna bağlı olarak.
Elbette tüm bu değişiklikler nedeniyle işletmenin en temel yönlerine, en temel yönetimine önem verilmemiş olabilir. ESP8266 wifi modülü. olmasına rağmen polarite.es Kullanımı hakkında bilgi bulabilirsiniz. ESP8266 ve sistemin işleyişini genel bir şekilde açıklamaya yönelik bazı uygulamalar vardır. ESP8266 wifi modülü AT komutlarını kullanma, özellikle de makalede ESP8266 wifi modülü ile Arduino'dan HTTP sorguları yapmak için kütüphane, okuyucu izlenimleri, kullanıcılara yardımcı olmak için bazı temel bilgilerin eklenmesinin faydalı olacağını göstermektedir. ESP8266 kendi uygulamalarını yürütmek.
Çalışmak için temel işlemleri tartışın ESP8266 ve genel çözümler önermek çok farklı birçok bölümün hedefidir; Makalenin içeriğini takip etmenize yardımcı olması açısından aşağıdaki dizin yol gösterici olabilir:
- ESP8266 wifi modülünü bilgisayardan seri port üzerinden kontrol edin
- Firmware'i esptool ile güncelleyin
- Siparişleri modüle gönder
- ESP8266'dan veri alın
- İçerikteki metinleri arayarak yanıtı analiz edin
- Yanıt almak için bekleme süresini sınırlayın
- Birden çok AT komutuyla tanımlanan karmaşık bir işlemi yürütün
ESP8266 wifi modülünü bilgisayardan seri port üzerinden kontrol edin
Bir tabaktan Arduino ve seninkini kullanarak IDE bir işlemin izlenmesi mümkündür ESP8266 wifi modülü, gönder ESP8266 AT komutları ve cevabı görün ancak bunu terminal tipi bir uygulamaya sahip bir bilgisayardan yapmak çok daha uygundur.
Hangi tahtaya bağlı Arduino kullanıldığında, yalnızca bir donanım seri bağlantı noktası mevcut olabilir, bu da gönderme ve alma işlemlerini biraz zorlaştırır. Bir bilgisayardan ve bazı anakartlardan seri iletişim uygulamasında iletişim hızını değiştirmek çok daha rahattır. Arduino (ve bazı durumlarda), seri iletişimin yüksek hızlarını, özellikle de en son sürümlerin varsayılan hızı olan 115200 baud'u pek desteklemez. firmware.
Üzerinde İzlemek için hangi program kullanılmalı? ESP8266 seri bağlantı noktasını kullanmaİhtiyaçlara ve tercihlere göre seçilebilecek çok şey var; son zamanlarda klasik olanı daha çok kullanıyorum ŞirinCom (yukarıdaki ekran görüntüsündeki) çünkü bazı şeyleri tekrarlamak benim için çok rahat Siparişlerde ESP8266 wifi modülü proje testlerinde.
Seri konsol olarak işlev gören programlara ilişkin bazı öneriler burada zaten verilmiştir; Örneğin, hakkında konuşurken UART seri cihazlarını bilgisayardan kontrol etmek için PuTTY. PuTTYMükemmel bir uygulama olmasının yanı sıra çoğu masaüstü işletim sisteminde mevcuttur. Ayrıca, PuTTY hem seri port hem de konsol olarak kullanılabilir İnternet protokol ailesi (TCP/IP)üzerinde faaliyet gösterenler de dahil TLS, onu yapılandırmak ve kullanımına alışmak için harcanan (az) zamanın fazlasıyla karşılığını veren yaygın bir araç haline gelir.
Seri iletişim yazılımının yanı sıra, bağlamak için ESP8266 wifi modülü limana USB Bir bilgisayar aynı zamanda bir dönüştürücü gerektirir USB seriye TTL. Yazılımda olduğu gibi, yalnızca bağlantı noktasını dönüştürmek için kullanılan çeşitli sürümler vardır. USB seri portta TTL (bir Euro'dan elde edilebilen) farklı protokolleri taklit edebilenlere (örneğin SPI o I2C).
Tıpkı seri konsol görevi gören bir program gibi, bilgisayarla iletişim kuracak donanım da USB bir mantık devresi ile (sadece ESP8266) mikro kontrollü bir uygulama geliştiricisinin çalışmalarında ortak bir araç olacaktır, mümkün olan en kısa sürede araç kutusunda bulundurmaya ve onunla çalışmaya değer. ESP8266 wifi modülü Bir tane almak için mükemmel bir fırsat.
Dönüştürücü USB a UART TTL Ayrıca, kullanan bir devrenin davranışını izlemek için de kullanılabilir. ESP8266Bunu yapmak için, izlemek istediğiniz çıkışlar, hızlı bir diyotla (RX) dönüştürücünün veri girişine (RX) seri olarak bağlanır. 1N4148örneğin) ve birbirine paralel bir direnç (örneğin 2K2). Böyle bir kurulum, donanım seri algılayıcısı gibi çalışır.
Her ne kadar yukarıdaki görüntüdeki algılayıcı kesinlikle ilkel olsa da (diğer şeylerin yanı sıra, tampon) bir montajın çalışmasını izlemek için yeterlidir Arduino y el ESP8266.
Algılayıcıyı önceki şemadan kaldırarak, nasıl bağlanacağını gösteren şema ESP8266 wifi modülü bir tabağa Arduino. 3V3 ile beslemenin yanı sıra entegrenin reset pini ve aktivasyon pininin de yüksek seviyeye (enable) bağlanması gerekmektedir. Elbette birinin RX pininin diğerinin TX pinine bağlanması gerekiyor.
Önceki diyagramı basitleştirmek için bir plaka temsil edilmiştir. Arduino 3V3 ile çalıştırılır ve seri porttaki voltajın da 3V3 olduğu varsayılır. Eğer bir mikrodenetleyici zarar vermemek için seri portta farklı bir sinyal seviyesi (tipik olarak 5 V) gerekli olacaktır. ESP8266, kullanın seviye dönüştürücü aşağıdaki diyagramlarda olduğu gibi. Bu devre sıklıkla birçok ticari kullanıma hazır modül uygulamasında bulunur.
ESP8266 ürün yazılımını güncelleyin
W ESP8266 AT komutları, sonlandırılması, modülün varsayılan hızı... sürümüne bağlıdır ESP8266 ürün yazılımı. Tüm modüllerde aynı sürüme sahip olduğunuzdan ve mümkünse en son sürüm olduğundan emin olmanız en iyisidir.
Ne yazık ki, çoğu ESP8266 wifi modülü modelleri Yalnızca 4Mbit'e sahip oldukları için en son sürüm onlara yüklenemez. Yüklenebilecek donanım yazılımının en son (resmi) sürümü ESP8266 wifi modülleri 4 Mbit ile (çoğu), 0.9.4 sürümünü içeren 0.2'tür. ESP8266 AT komutları.
Özetle, ihtiyacınız olan ürün yazılımını güncellemek için:
-
İlgili ürün yazılımı sürümünü indirin. 4Mbit belleğe sahip bir modülün en son (resmi) sürümü, github'daki Espressif klasöründe bulunur. Içinde Espressif web sitesi Ürün yazılımının en son sürümünü indirebilirsiniz, ancak yüklü olduğu modülün yeterli belleğe sahip olduğunu doğrulamak çok önemlidir.
-
Ürün yazılımı yükleme aracının en son sürümünü indirin. Benim favorim eskort hangisinde yazılı Pythonyani her platformda çalışır. İndirilmenin yanı sıra, aşağıdakilerle de kurulabilir:
pip install esptool
(opip2
opython -m pip
…). Elbette, etkileyici Ayrıca kendi aracını da sunuyor ancak şu anda yalnızca Windows için mevcut. -
İndirilen dosyaları hazırlayın; bunları erişilebilir bir klasörde açın ve gerekirse aracı çalıştırılabilir hale getirin eskortbenim durumumda, çünkü GNU / LinuxIle,
chmod +x esptool
-
Modülü bir dönüştürücü kullanarak bilgisayara bağlayın USB UART TTL 3V3'te çalışan veya 5 V'ta çalışıyorsa bir seviye dönüştürücü kullanın. Güce ek olarak, TX'i dönüştürücünün RX'ine bağlamanız gerekecektir. USB UART TTL, RX'den TX'e, GPIO0 düşük seviyede (GND) ve belki GPIO2 yüksek seviyede (testlerimde hem düşük seviyede bağlayıp hem de bağlantısını keserek çalıştı). Modülün GPIO15 bağlantısı serbestse (ESP-12'de olduğu gibi) düşük seviyeye bağlanması gerekir. Normalde çalışma sırasında yüksek seviyede olacak olan RESET, bağlantısız bırakılabilir veya bir direnç (örneğin 10K) aracılığıyla yüksek bir seviyeye bağlanabilir, çünkü kayda başlamadan önce cihazı bağlayarak sıfırlamak gerekebilir. düşük bir seviyeye.
Modülün açılmasıyla güncelleme yapılabilecektir ancak, Bir bağlantı hatası görüntülenirse sıfırlamanız gerekecektir. RESET'i bir an için düşük seviyede bağlamak ve ardından güncelleme işlemi için yayında (bağlanmadan) bırakmak.
Modül var yarım amper tüketimi zirveleri (bazı kullanıcılara göre 600 mA'ya kadar) bu nedenle, özellikle ürün yazılımını güncellemek için bu tüketimi destekleyebilecek bir güç kaynağının kullanılması önemlidir. -
Firmware'i güncellemek için aracı çalıştırın. Benim durumumda, 3. adımda araç ve ürün yazılımı belgelerini aynı klasöre kaydettim, bu yüzden konsoldan çalıştırıyorum:
cd ~/Datos/firmwareESP8266
(aracı ve ürün yazılımını içeren klasöre geçin)./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
hızını ayarlar ESP8266 (benim durumumda 115200 baud) ve--port
bağlandığı seri bağlantı noktası (benim durumumda öykünülmüş, ilk USB). Firmware'i oluşturan farklı belgeler geride kalıyorwrite_flash
Adresin önünde, güncelleme yükünü içeren user1.bin belgesi yer alır.
ESP8266 wifi modülüne komut gönder
kontrol etmek için ESP8266 bir bilgisayardan başlamamız gerekecek uygulamayı yapılandır bunun için dönüştürücünün bağlı olduğu bağlantı noktasını seçmek yeterli olacaktır ① USB UART TTL, gibi bir şey /dev/USB0
GNU/Linux ve benzeri veya buna benzer bir şeyde COM6
Windows'ta, ② Windows'un çalışma hızını seçin. ESP8266, muhtemelen 115200 baud, ③ eşlik veya el sıkışma olmaksızın 8 veri biti artı bir durdurma biti ayarlayın ve ④ veri türüne bağlı olarak hat sonunu ayarlayın firmware, neredeyse her zaman CR+LF.
Uygulama yapılandırıldığında (veya uygun olduğunda saklanıp seçildiğinde), bağlantıyı aç ("açık cihaz" ve "açık", yukarıdaki örneklerin ekran görüntülerinde sırasıyla ŞirinCom y PuTTY) ve şu adrese sipariş göndermeye başlayabilirsiniz: ESP8266.
Şekilde görülebileceği gibi ESP8266 AT komut tablosu, etkinleştirme, devre dışı bırakma, değer ayarlama ve ona gönderme yapma biçimi oldukça öngörülebilir, ancak genel olarak hepsini hatırlamak kolay değildir ve ona başvurmak için muhtemelen elinizde olması gerekecektir.
Yolu göndermek siparişlerde al ESP8266 wifi modülü itibaren Arduino çok basit: ① ile iletişimi yapılandırın Serial.begin(115200);
(veya çeşitli donanım seri bağlantı noktalarına sahip kartlarda Seri1, Seri2…) ve ② komutları formatı kullanarak gönderin 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()
{
}
|
Yukarıdaki örnek, mesajın nasıl gönderileceğini gösterir. Siparişlerde ESP8266 wifi modülü itibaren Arduino. Bu durumda resimlendirilmiştir AT+CWJAP
Bir erişim noktasına bağlanmak için kullanılır. Bu komut, erişim noktası tanımlayıcısını argüman olarak kullanır (SSID) ve anahtarın her ikisi de tırnak içinde olduğundan bir nesne haline gelirler Srtring
ve kaçış kodunu kullanarak bunları tırnak içine alın (\"
). Siparişi tamamlamak için şunu kullanın: \r\n
hangisine karşılık gelir CR
y LF
.
Seri bağlantı noktasının her zaman ile tanımlanmadığını hatırlamak için Serial
(bazı plakalarda olabilir Serial1
, Serial2
…) kullanılan port nesnesi makroya atanarak tanımlanmıştır PUERTO_SERIE
. Kullanılan kart tipinin tespit edilmesi, seri port seçimine biraz bilgi katabilir; Daha sonra türünü nasıl öğrenebileceğinizi ele alacağız. Arduino. Tanımların geri kalanı, tekrar etmekten (ve hata yapmaktan) kaçınmak ve bunları değiştirmeyi kolaylaştırmak için sabit değerleri "adlandırmanıza" olanak tanıyan olağan tanımlardır.
Yukarıdaki örneğin bağlanması gerekiyor ESP8266 wifi modülü belirtilen erişim noktasına mı bağlandınız, ancak daha önce zaten bağlı mıydı? Bağlantı işe yaradı mı? Bunu bilmek için, söylenenleri "dinlememiz" gerekiyor. ESP8266
ESP8266 wifi modülünden veri alın
Yukarıda açıklanan veri algılayıcıyı bilgisayara bağlayarak ne olduğunu görebilirsiniz. Arduino gönderdi ESP8266 ve onun cevabı. Okumak için Arduino ve içindeki bilgiyi işleyerek tespit edilmesi gerekli olacaktır. Serial.available()
herhangi bir veri geldiyse ve geldiyse onu yükleyin Serial.read()
. Aşağıdaki örnek, gelen yanıtın nasıl okunacağını gösterir. AT+CWJAP?
, herhangi bir erişim noktasına bağlantı olup olmadığını bildirecektir.
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();
}
}
|
Bir tabakta olduğu gibi Arduino Uno (ve diğerlerinde) seri monitörün açılması programı sıfırlar, seri konsolda görmek için kullanılabilir Arduino gönderdiğiniz bilgiler ESP8266 aşağıdaki görüntünün ekran görüntüsünde gösterildiği gibi.
ESP8266 wifi modülü tarafından gönderilen yanıtı analiz edin
Ulaşan bilgiyi nasıl okuyacağımızı zaten görmüştük. Arduino gelen ESP8266. Başa çıkmanız gereken sorun, ne zaman gelmeye başlayacağını, gelmesinin ne kadar süreceğini, ne kadar süreceğini bilmiyor olmanız... ve servisten gelecek yanıtı beklemek çok verimli değil. ESP8266 izin verilmeden alınır mikrodenetleyici bu arada başka görevleri de yerine getirin.
Bu durumu yönetmenin basit bir yolu somut cevaplar bulmak için elde edilen verileri yineleyin örneğin alınan metinde aramaya devam edilip edilmeyeceğini ve metinden gelen bilgilere göre hangi eylemlerin gerçekleştirilmesi gerektiğini belirleyecek göstergeleri (bayraklar veya Boole değişkenleri) etkinleştirin. ESP8266. Yanıt geldiğinde mikrodenetleyici diğer görevlere adayabilirörneğin sensörlerden veri almak ve onu işlemek.
ESP8266'dan alınan bilgilerde metin arayın
Gelen metni aramak için ESP8266 yapabilirsiniz Alınan her mektubu aradığınız mesaja karşılık gelen mektupla karşılaştırın. Karşılaştırılacak harfi işaret eden bir sayaç (veya işaretçi) kullanmak gerekli olacaktır; Eğer gelen karakter ESP8266 mesajda incelenen ile aynı ise sayaç ilerler, farklı ise başlatılır.
Sona ulaşıldığını anlamak için aranan mesajın bir sonraki karakteri olan sıfıra başvurulur (\0
) veya mesajın uzunluğunun saklandığı sayaçla karşılaştırılarak karşılaştırmanın bitip bitmediğini ve dolayısıyla ESP8266 wifi modülü İstenilen mesajı gönderdi.
Aşağıdaki örnekte şu komut kullanılmaktadır: AT+CWLAP
bu, erişim noktalarının bir listesini döndürür ve bunların içinde "wifi polaridad.es" adı verilen bir tane aranır. Her ne kadar son karakterin sıfır olduğunu doğrulamayı seçmiş olsak da tampon Yalnızca aranan metni saklar ve uzunluğu bilinir, aynı zamanda bu kadar sayıda doğru mektubun alınıp alınmadığı da kontrol edilebilir. Birlikte LED pin 2'ye bağlanıldığında beklenen metnin bulunduğu bildiriliyor.
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
}
}
}
}
|
Önceki örneğin kodunda ayrıca bir yol da görebilirsiniz. kartın türüne bağlı olarak seri bağlantı noktasını seçin Arduino kullanılmış. Bu örnekte proje için üç tür panonuz olduğu varsayılmaktadır: bir Arduino Unobir arduino mega 2560 ve bir Arduino Leonardo. Eğer bir Arduino Uno kullanılacak Serial
ve aksi halde Serial1
.
Bir plaka ile çalışıyorsanız Arduino Leonardo Programı durdurmak ve konsolun (ilgili seri portun) çalışmasını beklemek için aynı yöntemi kullanabilirsiniz. Serial
) gecerli.
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
|
ESP8266 yanıtında çeşitli metinleri arayın
Önceki örnekteki kod, gönderici tarafından gönderilen bilgilerde metin aramak için kullanılır. ESP8266 ancak yanıt, operasyona bağlı olarak farklı bilgiler içerebilir. Bir sonraki örnekte basit bir durumla başlamak için, MCU ESP8266 es OK
İşlem doğru yapıldığında ve ERROR
Aksi takdirde siparişte olduğu gibi AT+CWJAP?
olup olmadığını doğrulamaya yarayan ESP8266 wifi modülü zaten bir erişim noktasına bağlı.
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
}
}
}
}
}
|
Birkaç olası mesajla eşleşme arayan aynı yöntemin bu yeni uygulaması, mesajdan alınan yanıta bağlı olarak farklı eylemler arasında seçim yapmanıza olanak tanır. ESP8266açmanız yeterli LED karşılık gelen.
Yanıt almak için gereken süreyi sınırlayın
Şu ana kadar ilgili bir konuya değinilmemiştir: Bir işlemin başarısız olduğunu düşünmeden önce maksimum bekleme süresi (zaman aşımı). Herhangi bir nedenle bağlantınız varsa ESP8266 wifi modülü, erişim noktasına sahip modül, İnternet'e sahip erişim noktası veya örneğin varsayımsal bir sunucu mevcut değilse, program süresiz olarak bekleyen bir noktada bloke edilebilir, dolayısıyla bu gibi durumlara bir yanıt verilmesi gerekecektir. Maksimum bekleme süresi uygulamanın tamamı için yapılandırılabilir; bu durumda genellikle daha "cömert" olur veya her işlem için ayrı bekleme süreleri programlanabilir.
(En azından) belirli bir zaman aralığının geçtiğini kontrol etmek için Hesabın başlatıldığı andaki "zaman" genellikle mevcut "zaman"dan çıkarılarak aradaki farkın istenilen limitten büyük olduğu doğrulanır.. Bu "zaman"ın gerçek zamanlı olması gerekmez; genellikle olayın başlangıcından bu yana geçen aralığa karşılık gelir. MCU zamanı saymaya başlayın; Bu, programı etkilemez çünkü ilginç olan mutlak zaman değil, geçen zamandır.
Genellikle belirli bir aralığın geçip geçmediğini kontrol etmek için şu türden bir ifade kullanılır:
1
|
(unsigned long)(millis()–milisegundos_al_empezar)>intervalo_de_tiempo
|
değişken milisegundos_al_empezar
değerini içerir millis()
Uygulamanın zamanlandığı belirli bir an olduğundan, adının "kronometre" kelimesine gönderme yapması alışılmadık bir durum değildir. Değişken intervalo_de_tiempo
önceki ifadeyi doğru yapan maksimum milisaniye sayısını içerir; yani zaman aşımını temsil eder; Genellikle bir sabittir (veya bir makrodur) ve önceki durumda olduğu gibi, adında sıklıkla "TIMEOUT" sözcüğü görünür. Çok kısa aralıklarla çalışıyorsanız kullanabilirsiniz. micros()
yerine millis()
(milisaniye yerine mikrosaniye) olmasına rağmen çok daha az yaygındır ve çok daha az kesindir.
1
|
(unsigned long)(millis()–cronometro)>TIMEOUT
|
Uzun bir tamsayı Arduino (unsigned long
) 4 bayt (32 bit) kaplar, dolayısıyla temsil edebileceği en büyük değer 4294967295'tir (2 üssü 32 eksi bir, çünkü sıfırdan başlar). tabakta Arduino Sürekli çalışırken milisaniye sayacı yaklaşık her 50 günde bir sıfırlanır (sıfıra döner). İmzasız veri türleriyle çıkarma yaparken aynı davranış yeniden üretilir (sayacın ters çevrilmesi), böylece zaman aşımını süresiz olarak kontrol etmek mümkün olur.
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;
}
}
}
|
Yukarıdaki kod bir gösterir zaman aşımı sınırlamasının çok temel uygulaması kendisinden önceki örneğe göre işaretlenmiş satırları içerir. Zaman aşımı doğrulaması, gelen veri işlendikten sonra yapıldığından ESP8266 wifi modülüalımı zorunlu bekleme süresinden daha uzun sürse bile işlemin başarılı olduğu kabul edilebilir.
Birden çok AT komutuyla tanımlanan karmaşık bir işlemi yürütün
Yararlanan uygulamanın amacına ilişkin örnek bir referansa sahip olmak ESP8266 wifi modülü, varsayalım ki bilgileri bir web hizmeti aracılığıyla erişilen bir veritabanında depolamak sıcaklığı takip etmek için. Aşağıdaki kod, her belirli zaman aralığında analog girişe bağlı bir sensörü okur, ortalama değeri hesaplar ve daha uzun bir zaman aralığının ardından bunu web sunucusuna (tarz) gönderir. IOT) aracılığıyla dilekçe HTTP (GÖNDERİN, ALIN…).
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”);
}
}
|
Bu sıcaklık kaydı örneğinde, her beş dakikada bir web sunucusuna erişilmektedir. Kullanılabilirlik özellikle yüksek olmasa da, teklifin işe yaraması beklenmelidir; ancak daha yüksek bir kayıt sıklığı gerekliyse, diğer kaynakların da uygulanması gerekecektir; örneğin; veri arabelleği gönderilmeyi bekliyor, sunucunun katılabileceği durumlarda birkaç tane göndermek ve bunları mevcut olmadığında saklamak için. Verilerin kaydedilmesi gereken sıklık daha da yüksek olsaydı, diğer protokol türlerinin alternatif olarak önerilmesi gerekecekti. HTTP hatta değiştirin TCP tarafından UDP Verilerin çoğunu, bazılarını kaybetme pahasına bile gereken hızda gönderebilmek.
Sıcaklığın gönderilmesi için gerçekleştirilecek görevi oluşturan işlemler şunlardır:
- Wifi modülünü sıfırlayın
- Geçerli erişim noktasıyla bağlantıyı kesin (varsayılan bir bağlantının mevcut olması durumunda)
- Ayarları yapın. Örneğin, bağlantı modunun (basit) ve Wi-Fi iletişimindeki (istasyon) rolün yapılandırılması gerektiği varsayılmaktadır.
- Erişim noktasına bağlanın
- Bağlantının doğru olduğunu doğrulayın (aslında burası giriş noktasıdır) Bağlantı yoksa işlemi baştan başlatın
- Sunucuya bağlan
- Talebi gönder HTTP saklanacak verilerle
İşlem sırasının tam olarak bu şekilde olması gerekmez (her ne kadar işlem böyle olsa da) ve her adım birkaç tane gerektirebilir. ESP8266 AT komutlarıÖrneğin, yukarıda listelenen konfigürasyonun iki taneye ihtiyacı olacaktır: AT+CIPMUX=0
y AT+CWMODE=1
.
ESP8266'daki işlemleri temsil eden bir veri yapısı
Önceki örneklerde, çok basit bir şekilde de olsa, soruna genel bir çözüm zaten önerilmiştir: olası yanıtları ve her durumda yapılması gereken eylemleri saklayan bir veri yapısı kullanın; Bir eylem gönderin, yanıt bekleyin ve yanıtın ne anlama geldiğine göre ilerleyin. Her karmaşık işlem birkaç tane gerektireceğinden ESP8266 AT komutlarıveri yapısı, her durumda kullanıcının yanıtına bağlı olarak gerçekleştirilmesi gereken bir işlemi sonraki veya önceki diğer işlemlerle ilişkilendirmelidir. ESP8266.
Önceki örneklerde, kullanıcının yanıtı içerisinde bir mesaj aranıyordu. ESP8266 başarı ya da hata olarak yorumlandı. Alınan tüm metnin alımına (ve analizine) ek olarak, Genel bir minimum seviyeye sahip olmak için mesajın tamamlanmasına da dikkat edilmesi tavsiye edilir. veya başka bir deyişle, kullanılabilirliğin ESP8266 wifi modülü yeni siparişler almak için. Bu sayede örneğin "wifi mevcut" diyebileceğimiz bir duruma geçiş, erişim noktasının adının alınması ve metnin alınması şeklinde olabilir. ERROR
veya metin OK
şu anlama gelir ESP8266 yanıtı tamamladınız ve şimdi bir sonrakini gönderebilirsiniz ESP8266'ya AT komutu.
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;
|
Yukarıdaki kod bir vektör (operacion
) görevin tamamını oluşturan ardışık işlemlerin metnini saklamak için. İki boyutlu bir dizi kullanılır (mensaje
) analiz edilen üç yanıtla. Yukarıda açıklandığı gibi doğru ya da yanlış yanıtı temsil eden mesajın yanı sıra, yanıtın sonunu temsil eden mesajları da aramak gerekir. Tüm işlemlerin aynı sayıda olası cevabı olmayacaktır; Daha az yanıt olduğunda, analizinde mümkün olan en az sayıda döngüyü tüketen boş bir mesaj kullanılabilir (bu durumda bile bu en uygun yol değildir). Mantıksal olarak, aranan minimum yanıt sayısının (örnekte üç), hepsi mümkün olmasa bile tüm işletim olasılıklarını içermesi gerekli olacaktır.
Olası cevaplardan bahsederken, bu örneğin bir bilgisayardan keyfi formatta veri almak için pek kullanışlı olmadığı zaten görülüyor. ESP8266 wifi modülü, ancak olay şu ki, kullanım bağlamında mikrodenetleyiciler bu alışılmadık bir durum; En yaygın olanı bağladıkları sensörler tarafından toplanan verileri göndermek ve/veya kontrol ettiği aktüatörlerle ne yapılacağına dair bilgi almaktır. Çok iyi tahmin edilebilecek çok değerli bilgiler.
Önceki veri yapısında, analiz edilen olası yanıtları ifade etmek için yapıldığı gibi, her durumda yapılması gereken işlemi belirlemek için de iki boyutlu bir matris kullanılır (siguiente_operacion
). Özellikle üç tür mesaja yanıt vermeyi seçtik: ① isteğe bağlı bir metin (LITERAL
) Wi-Fi erişim noktası ve sunucuyla bağlantı olup olmadığını doğrulamak için, ② işlemdeki hataları tespit etmek için bir metin (FALLO
) ve ③ işlemin başarıyla tamamlandığını belirten bir metin (ACIERTO
).
Son olarak, vazgeçmeden önce maksimum bekleme süresini ayarlamak için iki vektör daha var (timeout
) ve belirtin (configuracion
) işlem yanıt beklemeden sona ererse (ESPERAR_RESPUESTA
) ve iletişimin sonunu belirten mesajlar. Belleğin nasıl kaydedilebileceğine dair bir örneği gösteren bu son vektör, farklı durumları belirtmek için konfigürasyon baytının bitleriyle çalışır.
İlk ESP8266 AT komutları Veri yapısından her zaman bir yanıt beklenir; bu, başarı veya hata mesajı olabilir. Bir hata oluştuğunda modül yeniden başlatılır ve tekrar başlar ve mesaj işlemin doğru olduğunu gösteriyorsa bir sonraki işleme geçilir.
Sunucuya bağlandığınızda düzen değişir. Bu durumda, ① iletilecek veri paketinin uzunluğunun gönderilmesi ve ② talebin oluşturulması gereklidir. HTTP sabit bir metin artı sunucuda saklanmak üzere gönderilen değer (sıcaklık). Bu verilerin hazırlanması her gönderide gerçekleştirilir ve ikiye (uzunluğu bildirin) veya üçe (talebi gönderin) bölmek gerekir. HTTP) Için: ESP8266 AT siparişi. Operasyonun bölündüğü parçaların yalnızca sonuncusu yanıt bekleyecektir.
Bu durumda sorunsuz çalışacaktır (modülün meşgul olduğu uyarısı verilebilir), ancak veri uzunluğu daha büyük olduğunda veri bloklarını daha küçük parçalara bölmek ve hatta bir bekleme uygulamak bile gerekli olabilir. Modüle veriyi doldurmadan göndermesi için zaman vermek amacıyla sıcaklık okuması yapılır. tampon.
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();
|
Yukarıdaki örnek kod, daha önce açıklanmış olan diğer makrolarla birlikte, bir yanıtın beklenip beklenmeyeceğinin belirleneceği farklı durumların nasıl tanımlandığını ve uygunsa yanıtın bittiğini hangi mesajın gösterdiğini gösterir.
Kodun farklı noktalarında olduğu gibi bir işlem gönderilecektir (ortalama sıcaklığın gönderilme zamanı geldiğinde, bir işlemin bekleme süresi aşıldığında, mevcut işlem başarıyla tamamlandığında...) ancak bunun nasıl yapılacağı bellidir. küresel olarak kurulmuş, bir makro olarak tanımlanmıştır ENVIAR_OPERACION
Gönderimle ilgili adımları gruplandıran.
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();
|
Örnekteki ana programın kodu aşağıdadır. En harici görev, ortalamayı hesaplamak için sıcaklığın örneklenmesinden sorumlu olan görevdir ve bu, her belirli zaman diliminde, ESP8266 wifi modülü. Her işlem gönderildikten sonra, bir sonraki işlemin hangisi olduğunu veya bilgi gönderme görevinin tamamlanıp tamamlanmadığını belirlemek için yanıt analiz edilir.
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
}
}
}
|
Mantıksal olarak, önceki kod üzerinde çeşitli optimizasyon eylemleri gerçekleştirilebilir ancak bu, optimizasyonun nasıl yapıldığını anlamak için bir örnek olduğundan ESP8266 Genel olarak, yalnızca bazı yönlere odaklanmaya değer; bunlardan ilki veri yapısıdır. Görünüşe göre mantıklı olan şu ki bir programlama dili veri yapısı kullanın (struct
) işlenen bilgiyi temsil etmek için: ESP8266 AT komutları ve analiz edilen mesajlar.
Bir yapı kullanın (struct
Örnek diziler yerine (bunlara dayalı olarak) verileri depolamak önemsizdir ve daha zarif kodla sonuçlansa da sonuçta herhangi bir gelişme anlamına gelmez. Kullanımının ortaya çıkardığı gerçek alternatif struct
aşağıda açıklandığı gibi uygulamaktır: “iç” verileri içeren yapılardaki değişken uzunluklar onlar tarafından anılanlar. Bu şekilde, örneğin bir operasyonun analiz edilecek sabit sayıda yanıta sahip olması gerekli olmayacaktır.
Bu yaklaşım, çözümü uygulamanın en iyi yolu olduğunu öne sürer ancak dezavantajı bunun gerekli olmasıdır. dinamik bellek ayırmayı kullanın; bu riskli bir uygulamadır. mikrodenetleyici bu, çalışma zamanında ne kadar belleğin kullanılacağının dikkatli bir şekilde ölçülmesini gerektirir, derleyicinin bizi bu konuda uyarması pek mümkün olmayacağından ve programın yürütülmesi için ölümcül sonuçlara yol açacak şekilde belleği (veya yığını) tüketme olasılığı vardır.
Kodu optimize etme doğrultusunda şunu hatırlamak ilginçtir ki, büyük miktarda metin kullanan bu tür bir programda, hafıza alanından tasarruf edebilir SRAM metin dizelerinin program belleğinde saklanması (flaş) makro ile F()
. Aşağıdaki ekran görüntülerinde normal metin kullanımı ve makro kullanımıyla farklı program ve dinamik bellek dağıtımını görebilirsiniz. F()
.
Kurumdan gelen bilgilere göre gerçekleştirilen eylemlerle ilgili olarak ESP8266 wifi modülüMesajı koddan kontrol edip, alınana göre birini veya diğerini yapmaya alternatif olarak bu veri yapısında saklanabilir. durum göstergeleri yerine her görevi gerçekleştiren işlevlere yönelik işaretçiler (bayraklar), örneğin ana döngü içinde uygulamanın yönetmekten sorumlu olduğu belirli bir durum hakkında uyarıda bulunur.
Aşağıda, isteklere ait verilerin depolanacağı yapıların bir örneği verilmiştir. ESP8266 (veri türü operacion_esp8266
) ve yanıtları (veri türü) 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;
|
İşlemi temsil eden yapı olarak (sisteme gönderilen veriler) ESP8266 wifi modülü) yanıtların tanımlandığı yapıyı ve yanıtların yapısını operasyonların yapısına ifade eder, önce ikisini de beyan etmek gerekir, yeni veri türünü tanımlayarak ve ardından içeriğini tanımlayarak.
Önceki örnekte, onu içeren programın bir kullanmayı seçtiği dikkate alınmaktadır. durum göstergesisöz konusu değer tarafından belirtilen bir veya diğer işlemleri gerçekleştirmekten sorumlu olan koddan erişilebilen bir değişkene karşılık gelmesi gerekir. Cevabında ise ESP8266 Belirli bir metin analiz edildiğinde durum, karşılık gelen yanıtın yapısını gösteren değeri alır.
Daha önce de belirtildiği gibi, bir durum göstergesinin yerine geçecek veya onu tamamlayacak başka bir alternatif şu olabilir: bir fonksiyonu referans yapısında saklamak (bir işaretçi), yanıtta belirli bir metinle karşılaşıldığında çağrılacak ESP8266 wifi modülü.
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;
|
Önceki örnekte, gelen yanıtı işlemek için kullanılan veri yapısına eklenmiştir. ESP8266 wifi modülü türünde bir veri döndüren (varsayılan) bir işlevin işaretçisi float
(bir analog okumanın ağırlıklı değeri olabilir) ve argüman olarak iki bayt sağlanır (iki unsigned char
bu, analog girişin okunduğu pin ve varsayımsal bir entegrenin ENABLE'ını etkinleştiren pin olabilir).
için geliştiriliyor MCUDaha büyük sistemler için geliştirme tarzında meydana gelenin aksine, bir montajı kontrol eden uygulamanın (global) davranışını tanımlarken global değişkenlerin kullanılması çok nadir değildir, dolayısıyla bu tür tanımların bulunması özellikle nadir olmayacaktır. parametresiz ve değer döndürmeyen işlevler olarak void (*accion)();
Verileri bu şekilde temsil etme yöntemiyle çalışıyorsanız, struct
değişken uzunluktaki verilerden, belleği dinamik olarak tahsis etmek gerekli olacaktır. malloc()
(o new()
, eğer nesneler kullanılıyorsa), parametre olarak ayrılan bellek miktarını kullanacak ve ayrılan bellek alanının başlangıcına bir işaretçi döndürecektir. İle sizeof()
Depolanan türün kullanılan öğe sayısıyla çarpılmasıyla ihtiyaç duyulan bellek miktarını elde edebilirsiniz. Aşağıdaki ekran görüntülerinde kullanılarak ve kullanılmadan bir örnek görülebilir. malloc()
; İlk durumda programın kullandığı belleğe dikkat edin, bu işlevi içeren kütüphaneyi yüklemeniz gerekir.
Üzerindeki işlemler ise ESP8266 wifi modülü Programın yürütülmesi boyunca değişiklik göstereceğinden, kullanılmayan hafızanın boşaltılması gerekli olacaktır. free()
(o delete()
, nesne olması durumunda). Her ne kadar derleyiciden bunu beklemek makul olsa da (GCC) programı bellek bölümlemesini önleyecek şekilde optimize edecekse de performans kesinlikle statik olarak ayrılmış bellekle çalışmak kadar optimum olmayacaktır.
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
}
}
}
|
Bu örnekte (her iki uygulamada da) pek bir anlam ifade etmese de, işlemi diğer durumlara uygulayabilmek için genelleştirmek amacıyla şunu belirtmek gerekir: veri göndermek her zaman aynı protokolü tekrarlar: gönderilecek bayt sayısını bildirin, (>) göstergesini bekleyin ve verileri gönderin.
Bu örnekte yalnızca bir kez kullanıldığından (isteğin tamamı tek bir pakette yapılır), pek kullanışlı görünmese de genel olarak aynı işlemde birden fazla gönderim gerçekleştirmek gerekli olabilir, bunlara zorunlu durumlar da dahildir. belleğin taşmasını önlemek için parçalanması gereken önemli miktarda veri iletilecektir. ESP8266.
Bu davranışı uygulamak için bağlantının son iki öğesi kullanılabilir, böylece her veri gönderildiğinde veriler karşılık gelen değerlerle doldurulur: ilk durumda gönderilen bayt sayısı ve ikinci durumda ( talebin bir kısmı iletilecektir.
Aktarılması gereken farklı öğelerin atamasını ve gönderilmesini tekrarlamak için bir vektörde saklanabilir. Bu yeni vektör, şimdiye kadarki gibi son operasyonu değil, karmaşık operasyonun sonunu belirleyecek vektör olacak.
1 yorum