Arduino से ESP8266 वाईफाई मॉड्यूल पर बुनियादी संचालन
जब एस्प्रेसिफ बाज़ार में पहला मॉड्यूल लॉन्च किया वाईफ़ाई एकीकृत के साथ ESP8266 और फर्मवेयर एटी कमांड का उपयोग करके इसे कैसे संभालना है, हम उपयोगकर्ताओं की रुचि इसे असेंबली में एकीकृत करने में थी माइक्रोकंट्रोलर्स और समस्याएं (पूर्व में) अंधेरे को जानने तक सीमित हो गईं ESP8266 एटी कमांड टेबल, भोजन की जरूरतें या ESP8266 फ़र्मवेयर अद्यतन.
फिर प्रोग्राम करने के लिए विकल्प तुरंत आ गए ESP8266 और मॉड्यूल कार्यान्वयन वाईफ़ाई बहुत भिन्न प्रारूपों के कारण अन्य चिंताएँ उत्पन्न हुईं: कौन सा ESP8266 वाईफ़ाई मॉड्यूल चुनना है विभिन्न एंटेना (बाहरी एंटेना सहित) की सीमा या हमारी असेंबली में इन नए मॉड्यूल के भौतिक एकीकरण पर निर्भर करता है।
निश्चित रूप से, इन सभी परिवर्तनों के कारण, सबसे बुनियादी पहलुओं, सबसे बुनियादी प्रबंधन पर जोर नहीं दिया गया होगा ESP8266 वाईफ़ाई मॉड्यूल। हालांकि ध्रुवीयता.ई.एस आप इसके उपयोग के बारे में जानकारी प्राप्त कर सकते हैं ESP8266 और इसके संचालन को सामान्य तरीके से समझाने के लिए कुछ एप्लिकेशन मौजूद हैं ESP8266 वाईफ़ाई मॉड्यूल एटी कमांड का उपयोग करना, विशेष रूप से लेख में ESP8266 वाईफाई मॉड्यूल के साथ Arduino से HTTP क्वेरीज़ बनाने के लिए लाइब्रेरीपाठकों के अनुभव से पता चलता है कि उपयोगकर्ताओं की मदद के लिए कुछ और बुनियादी जानकारी जोड़ना उपयोगी होगा ESP8266 अपना स्वयं का कार्यान्वयन करने के लिए।
के साथ काम करने के लिए बुनियादी संचालन पर चर्चा करें ESP8266 और सामान्य समाधान प्रस्तावित करना कई अलग-अलग हिस्सों का उद्देश्य है; लेख की सामग्री का अनुसरण करने में सहायता के लिए, निम्नलिखित सूचकांक एक मार्गदर्शक के रूप में काम कर सकता है:
- सीरियल पोर्ट के माध्यम से कंप्यूटर से ESP8266 वाईफाई मॉड्यूल को नियंत्रित करें
- फर्मवेयर को एस्प्टूल से अपडेट करें
- मॉड्यूल को आदेश भेजें
- ESP8266 से डेटा प्राप्त करें
- सामग्री में पाठ खोजकर प्रतिक्रिया का विश्लेषण करें
- प्रतिक्रिया प्राप्त करने के लिए प्रतीक्षा समय सीमित करें
- एकाधिक एटी कमांड द्वारा परिभाषित एक जटिल ऑपरेशन निष्पादित करें
सीरियल पोर्ट के माध्यम से कंप्यूटर से ESP8266 वाईफाई मॉड्यूल को नियंत्रित करें
एक प्लेट से Arduino और आपका उपयोग कर रहा हूँ आईडीई के संचालन की निगरानी करना संभव है ESP8266 वाईफ़ाई मॉड्यूल, भेजें ESP8266 एटी कमांड और उत्तर देखें लेकिन इसे टर्मिनल प्रकार के एप्लिकेशन वाले कंप्यूटर से करना अधिक सुविधाजनक है।
किस बोर्ड पर निर्भर करता है Arduino उपयोग किए जाने पर, केवल एक हार्डवेयर सीरियल पोर्ट उपलब्ध हो सकता है, जिससे भेजने और प्राप्त करने में थोड़ी असुविधा होती है। कंप्यूटर और कुछ मदरबोर्ड से सीरियल संचार एप्लिकेशन में संचार गति को बदलना अधिक आरामदायक है। Arduino (और कुछ परिस्थितियों में) धारावाहिक संचार की उच्च गति का अच्छी तरह से समर्थन नहीं करते हैं, विशेष रूप से 115200 बॉड, जो कि नवीनतम संस्करणों की डिफ़ॉल्ट गति है फर्मवेयर.
के बारे में मॉनिटर करने के लिए किस प्रोग्राम का उपयोग करें ESP8266 सीरियल पोर्ट का उपयोग करना, जरूरतों और प्राथमिकताओं के अनुसार चुनने के लिए बहुत कुछ है; हाल ही में मैं क्लासिक का अधिक उपयोग कर रहा हूं क्यूटकॉम (ऊपर स्क्रीनशॉट में वाला) क्योंकि मेरे लिए कुछ बातें दोहराना बहुत आरामदायक है ESP8266 वाईफाई मॉड्यूल एटी ऑर्डर परियोजना परीक्षण में.
सीरियल कंसोल के रूप में कार्य करने वाले प्रोग्रामों पर कुछ सिफ़ारिशें यहां पहले ही दी जा चुकी हैं; उदाहरण के लिए, जब बात हो रही हो कंप्यूटर से UART सीरियल डिवाइस को नियंत्रित करने के लिए पुट्टी. पुट्टीएक उत्कृष्ट एप्लिकेशन होने के अलावा, यह अधिकांश डेस्कटॉप ऑपरेटिंग सिस्टम के लिए उपलब्ध है। इसके अलावा, जैसे पुट्टी सीरियल पोर्ट और दोनों के साथ कंसोल के रूप में कार्य करने के लिए उपयोग किया जा सकता है इंटरनेट प्रोटोकॉल परिवार (टीसीपी/IP), जिसमें वे भी शामिल हैं जो संचालित होते हैं टीएलएस, एक सामान्य उपकरण बन जाता है जो इसे कॉन्फ़िगर करने और इसके उपयोग में उपयोग करने में खर्च किए गए (थोड़े से) समय का भुगतान करता है।
धारावाहिक संचार सॉफ्टवेयर के अलावा, कनेक्ट करने के लिए ESP8266 वाईफ़ाई मॉड्यूल बंदरगाह के लिए यु एस बी कंप्यूटर को एक कनवर्टर की भी आवश्यकता होती है यु एस बी श्रृंखला के लिए टीटीएल. जैसा कि सॉफ़्टवेयर के मामले में होता है, इसके कई संस्करण होते हैं, जिनका उपयोग केवल पोर्ट को परिवर्तित करने के लिए किया जाता है यु एस बी एक सीरियल पोर्ट पर टीटीएल (जो एक यूरो से प्राप्त किया जा सकता है) जो विभिन्न प्रोटोकॉल का अनुकरण कर सकते हैं (जैसे SPI o I2C).
एक प्रोग्राम की तरह जो एक सीरियल कंसोल के रूप में कार्य करता है, कंप्यूटर के माध्यम से संचार करने के लिए हार्डवेयर यु एस बी एक लॉजिक सर्किट के साथ (सिर्फ नहीं) ESP8266) माइक्रोकंट्रोल्ड एप्लिकेशन डेवलपर के काम में एक सामान्य उपकरण होगा, इसे जल्द से जल्द टूलबॉक्स में रखना और इसके साथ काम करना उचित है ESP8266 वाईफ़ाई मॉड्यूल इसे पाने का यह एक उत्कृष्ट अवसर है।
कनवर्टर यु एस बी a UART टीटीएल इसका उपयोग सर्किट के व्यवहार की निगरानी के लिए भी किया जा सकता है जो इसका उपयोग करता है ESP8266, ऐसा करने के लिए, जिन आउटपुट को आप मॉनिटर करना चाहते हैं वे एक तेज़ डायोड (द) के साथ कनवर्टर के डेटा इनपुट (आरएक्स) से श्रृंखला में जुड़े हुए हैं 1N4148, उदाहरण के लिए) और एक अवरोधक (उदाहरण के लिए 2K2) एक दूसरे के समानांतर हैं। ऐसा सेटअप हार्डवेयर सीरियल स्निफर की तरह काम करता है।
हालाँकि ऊपर की छवि में खोजी कुत्ता निश्चित रूप से अल्पविकसित है (अन्य बातों के अलावा ऐसा नहीं है)। बफर) एक असेंबली के संचालन की निगरानी के लिए पर्याप्त है Arduino और ESP8266.
पिछली योजना से खोजी को हटाते हुए, योजनाबद्ध तरीके से दिखाया गया है कि कैसे कनेक्ट किया जाए ESP8266 वाईफ़ाई मॉड्यूल एक प्लेट में Arduino. इसे 3V3 पर फीड करने के अलावा, रीसेट पिन और इंटीग्रेटेड के एक्टिवेशन पिन को उच्च स्तर (सक्षम) से जोड़ा जाना चाहिए। बेशक, एक का RX पिन दूसरे के TX से कनेक्ट होना चाहिए।
पिछले आरेख को सरल बनाने के लिए, एक प्लेट का प्रतिनिधित्व किया गया है Arduino 3V3 पर संचालित और जिसके लिए सीरियल पोर्ट पर वोल्टेज भी 3V3 माना जाता है। यदि आप एक का उपयोग करते हैं microcontroller सीरियल पोर्ट पर एक अलग सिग्नल स्तर (आमतौर पर 5 वी) आवश्यक होगा, ताकि नुकसान न हो ESP8266, का उपयोग करो स्तर कनवर्टर नीचे दिए गए चित्र की तरह। यह सर्किट अक्सर कई वाणिज्यिक ऑफ-द-शेल्फ मॉड्यूल कार्यान्वयन में पाया जाता है।
ESP8266 फर्मवेयर अपडेट करें
लास ESP8266 एटी कमांड, इसकी समाप्ति, मॉड्यूल की डिफ़ॉल्ट गति... के संस्करण पर निर्भर करती है ESP8266 फर्मवेयर. यह सुनिश्चित करना सबसे अच्छा है कि आपके पास सभी मॉड्यूल में एक ही संस्करण है और, यदि संभव हो तो, यह नवीनतम संस्करण है।
दुर्भाग्य से, अधिकांश ESP8266 वाईफ़ाई मॉड्यूल मॉडल उनके पास केवल 4Mbit है, इसलिए उन पर नवीनतम संस्करण स्थापित नहीं किया जा सकता है। फ़र्मवेयर का नवीनतम (आधिकारिक) संस्करण जिस पर स्थापित किया जा सकता है ESP8266 वाईफ़ाई मॉड्यूल 4 Mbit के साथ (अधिकांश) 0.9.4 है जिसमें संस्करण 0.2 शामिल है ESP8266 एटी कमांड.
संक्षेप में, आपको आवश्यक फ़र्मवेयर को अपडेट करने के लिए:
-
संबंधित फर्मवेयर संस्करण डाउनलोड करें. 4 एमबी मेमोरी वाले मॉड्यूल के लिए नवीनतम (आधिकारिक) संस्करण, जीथब पर एस्प्रेसिफ़ फ़ोल्डर में पाया गया। में एस्प्रेसिफ़ वेबसाइट आप फ़र्मवेयर का नवीनतम संस्करण डाउनलोड कर सकते हैं, लेकिन यह सत्यापित करना बहुत महत्वपूर्ण है कि जिस मॉड्यूल पर यह स्थापित है उसमें पर्याप्त मेमोरी है।
-
फ़र्मवेयर इंस्टॉलेशन टूल का नवीनतम संस्करण डाउनलोड करें। मेरी पसंदीदा है esptool जिसमें लिखा है अजगर, इसलिए यह किसी भी प्लेटफ़ॉर्म पर काम करता है। इसे डाउनलोड करने के साथ-साथ इंस्टॉल भी किया जा सकता है
pip install esptool
(opip2
opython -m pip
...). बिल्कुल, एस्प्रेसिफ यह अपना स्वयं का टूल भी प्रदान करता है लेकिन वर्तमान में केवल विंडोज़ के लिए उपलब्ध है। -
डाउनलोड की गई फ़ाइलें तैयार करें; उन्हें एक सुलभ फ़ोल्डर में अनज़िप करें और, यदि आवश्यक हो, तो उपकरण को निष्पादन योग्य बनाएं esptool, मेरे मामले में, तब से ग्नू / लिनक्सके साथ,
chmod +x esptool
-
कनवर्टर का उपयोग करके मॉड्यूल को कंप्यूटर से कनेक्ट करें यु एस बी UART टीटीएल जो 3V3 पर काम करता है या यदि यह 5 V पर काम करता है तो लेवल कनवर्टर का उपयोग करें। पावर के अलावा, आपको कनवर्टर के TX को RX से कनेक्ट करना होगा यु एस बी UART टीटीएल, RX से TX, निम्न स्तर पर GPIO0 (GND) और शायद उच्च स्तर पर GPIO2 (मेरे परीक्षणों में इसने निम्न स्तर पर इसे जोड़ने और इसे डिस्कनेक्ट करने दोनों पर काम किया है)। यदि मॉड्यूल में GPIO15 कनेक्शन मुफ़्त है (जैसा कि ESP-12 में होता है) तो इसे निम्न स्तर से कनेक्ट किया जाना चाहिए। रीसेट, जो आमतौर पर ऑपरेशन के दौरान उच्च स्तर पर होता है, को असंबद्ध छोड़ा जा सकता है या किसी अवरोधक (उदाहरण के लिए 10K) के माध्यम से उच्च स्तर पर जोड़ा जा सकता है, क्योंकि रिकॉर्डिंग शुरू करने से पहले डिवाइस को कनेक्ट करके रीसेट करना आवश्यक हो सकता है। निम्न स्तर तक.
मॉड्यूल को चालू करने से यह अद्यतन करने के लिए उपलब्ध होगा लेकिन, यदि कोई कनेक्शन त्रुटि प्रदर्शित होती है, तो उसे रीसेट करना आवश्यक होगा एक पल के लिए निम्न स्तर पर RESET को कनेक्ट करना और फिर अपडेट प्रक्रिया के लिए इसे ऑन एयर (कनेक्ट किए बिना) छोड़ देना।
मॉड्यूल है आधा एम्पीयर की खपत चरम पर (कुछ उपयोगकर्ताओं के अनुसार 600 एमए तक) इसलिए इस खपत का समर्थन करने में सक्षम बिजली आपूर्ति का उपयोग करना महत्वपूर्ण है, खासकर फर्मवेयर अपडेट करने के लिए। -
फ़र्मवेयर को अपडेट करने के लिए टूल चलाएँ. मेरे मामले में, मैंने चरण 3 में टूल और फ़र्मवेयर दस्तावेज़ों को एक ही फ़ोल्डर में सहेजा है, इसलिए मैं कंसोल से चलाता हूं:
cd ~/Datos/firmwareESP8266
(टूल और फ़र्मवेयर वाले फ़ोल्डर में बदलें)./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
की गति निर्धारित करता है ESP8266 (मेरे मामले में 115200 बॉड) और--port
यह जिस सीरियल पोर्ट से जुड़ता है (मेरे मामले में, अनुकरणीय, पहला यूएसबी)। फ़र्मवेयर बनाने वाले विभिन्न दस्तावेज़ पीछे चलते हैंwrite_flash
पते से पहले, user1.bin दस्तावेज़ में अद्यतन पेलोड शामिल है।
ESP8266 वाईफ़ाई मॉड्यूल को आदेश भेजें
को नियंत्रित करने के लिए ESP8266 हमें एक कंप्यूटर से शुरुआत करनी होगी एप्लिकेशन को कॉन्फ़िगर करें जिसके लिए ①उस पोर्ट को चुनना पर्याप्त होगा जिससे कनवर्टर जुड़ा हुआ है यु एस बी UART टीटीएल, कुछ इस तरह /dev/USB0
जीएनयू/लिनक्स और उसके समान या उसके जैसा कुछ COM6
विंडोज़ में, ② वह गति चुनें जिस पर ESP8266, शायद 115200 बॉड, ③ 8 डेटा बिट प्लस एक स्टॉप बिट सेट करें, समता या हैंडशेक के बिना, और ④ लाइन का अंत सेट करें, जो इस पर निर्भर करता है फर्मवेयर, लगभग हमेशा सीआर+एलएफ।
एक बार जब एप्लिकेशन कॉन्फ़िगर हो जाता है (या, जहां उपयुक्त हो, संग्रहीत और चयनित हो जाता है), यह है कनेक्शन खोलें ("ओपन डिवाइस" और "ओपन", क्रमशः, ऊपर दिए गए उदाहरणों के स्क्रीनशॉट में क्यूटकॉम y पुट्टी) और आप ऑर्डर भेजना शुरू कर सकते हैं ESP8266.
जैसा कि में देखा जा सकता है ESP8266 एटी कमांड टेबल, सक्रिय करने, निष्क्रिय करने, मूल्य निर्धारित करने और इसे संदर्भित करने का प्रारूप काफी अनुमानित है, लेकिन सामान्य तौर पर उन सभी को याद रखना आसान नहीं है और इसे संदर्भित करने के लिए आपको संभवतः इसे हाथ में रखने की आवश्यकता होगी।
का तरीका भेजें एटी आदेश al ESP8266 वाईफ़ाई मॉड्यूल से Arduino बहुत सरल है: ① संचार कॉन्फ़िगर करें Serial.begin(115200);
(या सीरियल1, सीरियल2... कई हार्डवेयर सीरियल पोर्ट वाले बोर्ड पर) और ② प्रारूप का उपयोग करके कमांड भेजें 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()
{
}
|
उपरोक्त उदाहरण दिखाता है कि कैसे भेजना है ESP8266 वाईफाई मॉड्यूल एटी ऑर्डर से Arduino. इस मामले में यह सचित्र है AT+CWJAP
, जिसका उपयोग किसी एक्सेस प्वाइंट से कनेक्ट करने के लिए किया जाता है। यह कमांड एक्सेस पॉइंट आइडेंटिफ़ायर को तर्क के रूप में उपयोग करता है (एसएसआईडी) और कुंजी, दोनों उद्धरण चिह्नों में हैं, इसलिए वे एक वस्तु बन जाते हैं Srtring
और उन्हें एस्केप कोड का उपयोग करके उद्धरण चिह्नों में संलग्न करें (\"
). ऑर्डर पूरा करने के लिए, उपयोग करें \r\n
जो मेल खाता है CR
y LF
.
याद रखें कि सीरियल पोर्ट की हमेशा पहचान नहीं की जाती है Serial
(कुछ प्लेटों पर यह हो सकता है Serial1
, Serial2
...) प्रयुक्त पोर्ट ऑब्जेक्ट को मैक्रो को निर्दिष्ट करके परिभाषित किया गया है PUERTO_SERIE
. उपयोग किए गए बोर्ड के प्रकार का पता लगाने से सीरियल पोर्ट चयन में थोड़ी बुद्धिमत्ता जुड़ सकती है; बाद में हम जानेंगे कि आप इसके प्रकार का पता कैसे लगा सकते हैं Arduino. बाकी परिभाषाएँ सामान्य हैं जो आपको निरंतर मूल्यों को "नाम" देने की अनुमति देती हैं ताकि उन्हें दोहराने (और गलतियाँ करने) से बचा जा सके और उन्हें बदलना आसान हो सके।
उपरोक्त उदाहरण को जोड़ने वाला माना जाता है ESP8266 वाईफ़ाई मॉड्यूल संकेतित पहुंच बिंदु तक लेकिन क्या यह पहले से ही जुड़ा हुआ था? क्या कनेक्शन काम कर गया? यह जानने के लिए हमें क्या "सुनना" होगा ESP8266
ESP8266 वाईफाई मॉड्यूल से डेटा प्राप्त करें
ऊपर बताए गए डेटा स्निफ़र को कंप्यूटर से कनेक्ट करके आप क्या देख सकते हैं Arduino को भेज दिया है ESP8266 और उसकी प्रतिक्रिया. से पढ़ने के लिए Arduino और इसमें मौजूद जानकारी को संसाधित करने के साथ इसका पता लगाना आवश्यक होगा Serial.available()
यदि कोई डेटा आ गया है और यदि हां तो उसे लोड कर लें Serial.read()
. निम्नलिखित उदाहरण दिखाता है कि प्रतिक्रिया को कैसे पढ़ा जाए AT+CWJAP?
, जो रिपोर्ट करेगा कि क्या किसी पहुंच बिंदु से कोई कनेक्शन है।
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();
}
}
|
एक प्लेट की तरह अरुडिनो उनो (और अन्य में) सीरियल मॉनिटर खोलने से प्रोग्राम रीसेट हो जाता है, इसका उपयोग सीरियल कंसोल में देखने के लिए किया जा सकता है Arduino जो जानकारी आप भेजते हैं ESP8266 जैसा कि नीचे दी गई छवि का स्क्रीनशॉट दिखाता है।
ESP8266 वाईफाई मॉड्यूल द्वारा भेजी गई प्रतिक्रिया का विश्लेषण करें
हम पहले ही देख चुके हैं कि जो जानकारी पहुंचती है उसे कैसे पढ़ा जाए Arduino से ESP8266. आपको जिस समस्या से निपटना है वह यह है कि आप नहीं जानते कि यह कब आना शुरू होगा, इसे आने में कितना समय लगेगा, इसकी लंबाई कितनी होगी... और प्रतिक्रिया की प्रतीक्षा करना बहुत प्रभावी नहीं है ESP8266 बिना बताए प्राप्त किया जाता है microcontroller इस बीच अन्य कार्य करें।
इस परिस्थिति को प्रबंधित करने का एक सरल तरीका है ठोस उत्तरों की तलाश में प्राप्त आंकड़ों को दोहराएँ जिसके साथ, उदाहरण के लिए, संकेतक (झंडे या बूलियन चर) सक्रिय करें जो यह निर्धारित करेगा कि प्राप्त पाठ में खोज जारी रखनी है या नहीं और जो जानकारी प्राप्त होती है उसके आधार पर क्या कार्रवाई की जानी चाहिए ESP8266. जबकि प्रतिक्रिया आती है microcontroller अन्य कार्यों के प्रति समर्पित हो सकते हैंउदाहरण के लिए, सेंसर से डेटा प्राप्त करना और उसे संसाधित करना।
ESP8266 से प्राप्त जानकारी में एक टेक्स्ट खोजें
से आने वाले टेक्स्ट को खोजने के लिए ESP8266 आप कर सकते हैं प्राप्त प्रत्येक पत्र की तुलना उस संदेश से करें जो उस संदेश से मेल खाता हो जिसे आप खोज रहे हैं. एक काउंटर (या एक सूचक) का उपयोग करना आवश्यक होगा जो तुलना किए जाने वाले अक्षर की ओर इशारा करता है; यदि वह पात्र जो से आता है ESP8266 संदेश में जांच की जा रही स्थिति के समान है, काउंटर आगे बढ़ता है, यदि यह भिन्न है तो इसे प्रारंभ किया जाता है।
यह जानने के लिए कि अंत आ गया है, खोजे गए संदेश के अगले अक्षर से परामर्श किया जाता है, जो शून्य होगा (\0
) या संदेश की लंबाई संग्रहीत की जाती है, इसे काउंटर के साथ तुलना करके जानें कि क्या तुलना समाप्त हो गई है और इसलिए ESP8266 वाईफ़ाई मॉड्यूल वांछित संदेश भेजा है.
निम्न उदाहरण कमांड का उपयोग करता है AT+CWLAP
जो पहुंच बिंदुओं की एक सूची लौटाएगा और उनमें से एक को "वाईफ़ाई पोलरिडाड.ईएस" कहा जाएगा। हालाँकि हमने यह सत्यापित करने के लिए चुना है कि अंतिम वर्ण शून्य है बफर इसमें केवल खोजे गए टेक्स्ट को संग्रहित किया जाता है और उसकी लंबाई ज्ञात की जाती है, इससे यह भी जांचा जा सकता है कि इतनी संख्या में सही अक्षर प्राप्त हुए हैं या नहीं। के साथ एलईडी पिन 2 से कनेक्ट होने पर यह सूचित किया जाता है कि अपेक्षित टेक्स्ट मिल गया है।
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
}
}
}
}
|
पिछले उदाहरण के कोड में आप इसका एक तरीका भी देख सकते हैं बोर्ड के प्रकार के आधार पर सीरियल पोर्ट चुनें Arduino इस्तेमाल किया गया। यह उदाहरण मानता है कि आपके पास प्रोजेक्ट के लिए तीन प्रकार के बोर्ड हैं: एक अरुडिनो उनोएक, अरडिनो मेगा 2560 और एक अरुडिनो लियोनार्डो. यदि आप एक के साथ काम करते हैं अरुडिनो उनो इसका उपयोग किया जाएगा Serial
और अन्यथा Serial1
.
अगर आप प्लेट से काम करते हैं अरुडिनो लियोनार्डो आप प्रोग्राम को रोकने और कंसोल (संबंधित सीरियल पोर्ट) की प्रतीक्षा करने के लिए उसी विधि का उपयोग कर सकते हैं Serial
) उपलब्ध है।
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 प्रतिक्रिया में विभिन्न पाठ खोजें
पिछले उदाहरण के कोड का उपयोग द्वारा भेजी गई जानकारी में टेक्स्ट को खोजने के लिए किया जाता है ESP8266 लेकिन प्रतिक्रिया में ऑपरेशन के आधार पर अलग-अलग जानकारी शामिल हो सकती है। मान लीजिए, अगले उदाहरण में एक साधारण मामले से शुरू करने के लिए, जो पाठ भेजा गया है एमसीयू ESP8266 es OK
जब ऑपरेशन सही ढंग से किया जाता है और ERROR
अन्यथा, जैसा कि आदेश के साथ है AT+CWJAP?
, जो यह सत्यापित करने का कार्य करता है कि क्या 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
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
}
}
}
}
}
|
उसी विधि का यह नया कार्यान्वयन, जो कई संभावित संदेशों के साथ मिलान की खोज करता है, आपको प्राप्त प्रतिक्रिया के आधार पर विभिन्न क्रियाओं के बीच चयन करने की अनुमति देता है। ESP8266, बस चालू करें एलईडी तदनुसार।
प्रतिक्रिया प्राप्त करने में लगने वाले समय को सीमित करें
अब तक किसी प्रासंगिक मुद्दे का कोई संदर्भ नहीं दिया गया है: द किसी ऑपरेशन को विफल मानने से पहले अधिकतम प्रतीक्षा समय (टाइमआउट)।. यदि किसी भी कारण से संबंध है ESP8266 वाईफ़ाई मॉड्यूल, एक्सेस प्वाइंट वाला मॉड्यूल, इंटरनेट वाला एक्सेस प्वाइंट या, उदाहरण के लिए, एक काल्पनिक सर्वर उपलब्ध नहीं है, प्रोग्राम को अनिश्चित काल तक प्रतीक्षा करते हुए एक बिंदु पर अवरुद्ध किया जा सकता है, इसलिए ऐसी परिस्थितियों में प्रतिक्रिया व्यक्त करनी होगी। अधिकतम प्रतीक्षा समय को संपूर्ण एप्लिकेशन के लिए कॉन्फ़िगर किया जा सकता है, आमतौर पर उस स्थिति में यह अधिक "उदार" होगा, या प्रत्येक ऑपरेशन के लिए अलग-अलग प्रतीक्षा समय को प्रोग्राम किया जा सकता है।
यह जांचने के लिए कि (कम से कम) एक निश्चित समय अंतराल बीत चुका है जिस क्षण खाता शुरू किया जाता है उसका "समय" आमतौर पर वर्तमान "समय" से घटा दिया जाता है और यह सत्यापित किया जाता है कि अंतर वांछित सीमा से अधिक है. इस "समय" का वास्तविक समय होना जरूरी नहीं है, यह आमतौर पर उस अंतराल से मेल खाता है जो तब से बीत चुका है एमसीयू समय गिनना शुरू करें; इससे कार्यक्रम पर कोई प्रभाव नहीं पड़ता क्योंकि जो दिलचस्प है वह बीता हुआ समय है न कि पूर्ण समय।
आमतौर पर, यह जांचने के लिए कि क्या एक निश्चित अंतराल बीत चुका है, प्रकार की अभिव्यक्ति का उपयोग किया जाता है:
1
|
(unsigned long)(millis()–milisegundos_al_empezar)>intervalo_de_tiempo
|
परिवर्तनशील milisegundos_al_empezar
का मान शामिल है millis()
निष्पादन में एक निश्चित क्षण का, जिससे इसे समयबद्ध किया जाता है, इसलिए यह असामान्य नहीं है कि इसका नाम "क्रोनोमीटर" शब्द को संदर्भित करता है। परिवर्तनशील intervalo_de_tiempo
इसमें मिलीसेकंड की अधिकतम संख्या शामिल है जो पिछली अभिव्यक्ति को सत्य बनाती है, अर्थात यह टाइमआउट का प्रतिनिधित्व करती है; यह आम तौर पर एक स्थिरांक (या मैक्रो) होता है और, पिछले मामले की तरह, "टाइमआउट" शब्द अक्सर इसके नाम में दिखाई देता है। यदि आप बहुत कम अंतराल के साथ काम करते हैं तो आप इसका उपयोग कर सकते हैं micros()
के बजाय millis()
(मिलीसेकंड के बजाय माइक्रोसेकंड) हालांकि यह बहुत कम आम है और बहुत कम सटीक है।
1
|
(unsigned long)(millis()–cronometro)>TIMEOUT
|
में एक लंबा पूर्णांक Arduino (unsigned long
) 4 बाइट्स (32 बिट्स) घेरता है, इसलिए इसका प्रतिनिधित्व करने वाला सबसे बड़ा मान 4294967295 है (2 की घात 32 घटा एक, क्योंकि यह शून्य से शुरू होता है)। एक थाली पर Arduino लगातार चलने के दौरान मिलीसेकंड काउंटर लगभग हर 50 दिनों में रीसेट (शून्य पर वापस) हो जाएगा। अहस्ताक्षरित डेटा प्रकारों के साथ घटाव करते समय समान व्यवहार पुन: उत्पन्न होता है (काउंटर फ़्लिप करना) इसलिए टाइमआउट को अनिश्चित काल तक नियंत्रित करना संभव है।
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;
}
}
}
|
उपरोक्त कोड दिखाता है a टाइमआउट सीमा का बहुत ही बुनियादी कार्यान्वयन इसके पहले वाले उदाहरण के संबंध में चिह्नित पंक्तियों को शामिल करना। चूंकि टाइमआउट सत्यापन से आने वाले डेटा को संसाधित करने के बाद किया जाता है ESP8266 वाईफ़ाई मॉड्यूल, ऑपरेशन को सफल माना जा सकता है भले ही रिसेप्शन में लगाए गए प्रतीक्षा समय से अधिक समय लगे।
एकाधिक एटी कमांड द्वारा परिभाषित एक जटिल ऑपरेशन निष्पादित करें
उस एप्लिकेशन के उद्देश्य का एक उदाहरण संदर्भ प्राप्त करना जो इसका फायदा उठाता है ESP8266 वाईफ़ाई मॉड्यूल, मान लीजिए कि यह है वेब सेवा के माध्यम से एक्सेस किए गए डेटाबेस में जानकारी संग्रहीत करें तापमान पर नज़र रखने के लिए. निम्नलिखित कोड प्रत्येक निश्चित समय अंतराल पर एनालॉग इनपुट से जुड़े सेंसर को पढ़ता है, औसत मूल्य की गणना करता है और लंबे समय अंतराल के बाद इसे वेब सर्वर (शैली) पर भेजता है IoT) किसी के जरिए याचिका HTTP (पोस्ट करें, प्राप्त करें...).
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”);
}
}
|
इस तापमान रिकॉर्डिंग उदाहरण में, हर पांच मिनट में एक वेब सर्वर एक्सेस किया जाता है। हालाँकि उपलब्धता विशेष रूप से अधिक नहीं है, यह उम्मीद की जानी चाहिए कि प्रस्ताव काम करेगा, लेकिन यदि उच्च रिकॉर्डिंग आवृत्ति आवश्यक थी, तो अन्य संसाधनों को लागू करना होगा, उदाहरण के लिए, डेटा बफ़र भेजे जाने की प्रतीक्षा में, कई भेजने के लिए जब सर्वर उपस्थित हो सकता है और जब यह उपलब्ध न हो तो उन्हें संग्रहीत कर सकता है। यदि जिस आवृत्ति के साथ डेटा को रिकॉर्ड करने की आवश्यकता है वह और भी अधिक है, तो अन्य प्रकार के प्रोटोकॉल को विकल्प के रूप में प्रस्तावित करना होगा HTTP या प्रतिस्थापित भी करें टीसीपी द्वारा यूडीपी कुछ खोने की कीमत पर भी अधिकांश डेटा आवश्यक गति से भेजने में सक्षम होना।
तापमान भेजने के लिए किए जाने वाले कार्य निम्नलिखित होंगे:
- वाईफ़ाई मॉड्यूल रीसेट करें
- वर्तमान पहुंच बिंदु से डिस्कनेक्ट करें (यदि कोई डिफ़ॉल्ट कनेक्शन मौजूद है)
- सेटिंग्स सेट करें. उदाहरण के लिए, यह माना जाता है कि कनेक्शन मोड (सरल) और वाई-फाई संचार (स्टेशन) में भूमिका को कॉन्फ़िगर किया जाना चाहिए।
- पहुंच बिंदु से कनेक्ट करें
- सत्यापित करें कि कनेक्शन सही है (वास्तव में, यह प्रवेश बिंदु है) यदि कोई कनेक्शन नहीं है, तो प्रक्रिया को शुरुआत से शुरू करें
- सर्वर से कनेक्ट करें
- अनुरोध भेजें HTTP संग्रहीत किए जाने वाले डेटा के साथ
संचालन का क्रम बिल्कुल इस जैसा होना जरूरी नहीं है (हालाँकि ऑपरेशन है) और प्रत्येक चरण के लिए कई की आवश्यकता हो सकती है ESP8266 एटी कमांडउदाहरण के लिए, ऊपर सूचीबद्ध कॉन्फ़िगरेशन के लिए दो की आवश्यकता होगी: AT+CIPMUX=0
y AT+CWMODE=1
.
ESP8266 पर संचालन का प्रतिनिधित्व करने के लिए एक डेटा संरचना
पिछले उदाहरणों में, हालांकि बहुत ही बुनियादी तरीके से, समस्या का एक सामान्य समाधान पहले से ही सुझाया गया है: एक डेटा संरचना का उपयोग करें जो संभावित प्रतिक्रियाओं और प्रत्येक मामले में की जाने वाली कार्रवाइयों को संग्रहीत करती है; एक कार्रवाई भेजें, प्रतिक्रिया की प्रतीक्षा करें, और प्रतिक्रिया का क्या अर्थ है उसके अनुसार आगे बढ़ें। चूँकि प्रत्येक जटिल ऑपरेशन के लिए कई की आवश्यकता होगी ESP8266 एटी कमांड, डेटा संरचना को एक ऑपरेशन को अगले या पिछले अन्य के साथ जोड़ना होगा, जिसे प्रत्येक मामले में प्रतिक्रिया के आधार पर किया जाना चाहिए ESP8266.
पिछले उदाहरणों में, प्रतिक्रिया के भीतर एक संदेश खोजा गया था ESP8266 और इसकी व्याख्या सफलता या त्रुटि के रूप में की गई। प्राप्त सभी पाठ के स्वागत (और विश्लेषण) के अलावा, सामान्य न्यूनतम रखने के लिए, संदेश को पूरा करने पर भी ध्यान देने की सलाह दी जाती है या, दूसरे शब्दों में, की उपलब्धता के लिए ESP8266 वाईफ़ाई मॉड्यूल नए ऑर्डर प्राप्त करने के लिए. इस तरह, उस स्थिति में परिवर्तन जिसे हम कॉल कर सकते हैं, उदाहरण के लिए, "वाईफ़ाई उपलब्ध", एक्सेस प्वाइंट का नाम प्राप्त करना और टेक्स्ट प्राप्त करना हो सकता है ERROR
या पाठ OK
इसका मतलब यह होगा कि ESP8266 आपने प्रतिक्रिया समाप्त कर दी है और अब आप अगला भेज सकते हैं 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
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;
|
उपरोक्त कोड एक वेक्टर का उपयोग करता है (operacion
) संपूर्ण कार्य को बनाने वाले क्रमिक परिचालनों के पाठ को संग्रहीत करने के लिए। एक द्वि-आयामी सरणी का उपयोग किया जाता है (mensaje
) तीन प्रतिक्रियाओं के साथ जिनका विश्लेषण किया गया है। जैसा कि ऊपर बताया गया है, उन संदेशों को देखना आवश्यक है जो सही या गलत प्रतिक्रिया का प्रतिनिधित्व करने वाले संदेश के अलावा प्रतिक्रिया के अंत का प्रतिनिधित्व करते हैं। सभी ऑपरेशनों में संभावित उत्तरों की संख्या समान नहीं होगी; जब कम प्रतिक्रियाएँ होती हैं, तो एक खाली संदेश का उपयोग किया जा सकता है जो इसके विश्लेषण में सबसे कम संभव संख्या में चक्रों का उपभोग करता है (फिर भी, यह सबसे इष्टतम तरीका नहीं है)। तार्किक रूप से, मांगी गई प्रतिक्रियाओं की न्यूनतम संख्या (उदाहरण में तीन) के लिए सभी परिचालन संभावनाओं को शामिल करना आवश्यक होगा, भले ही वे सभी संभव न हों।
संभावित उत्तरों के बारे में बात करते समय, यह पहले से ही देखा जा सकता है कि यह उदाहरण किसी से मनमाने प्रारूप के साथ डेटा प्राप्त करने के लिए बहुत उपयोगी नहीं है ESP8266 वाईफ़ाई मॉड्यूल, लेकिन बात यह है कि, के साथ प्रयोग के सन्दर्भ में माइक्रोकंट्रोलर्स यह सामान्य नहीं है; सबसे आम बात यह है कि उनके द्वारा कनेक्ट किए गए सेंसरों द्वारा एकत्र किए गए डेटा को भेजना और/या इसके द्वारा नियंत्रित किए जाने वाले एक्चुएटर्स के साथ क्या करना है, इसके बारे में जानकारी प्राप्त करना है। बहुत ही मूल्यवान जानकारी, जिसका पूर्वानुमान बहुत अच्छे से लगाया जा सकता है।
पिछली डेटा संरचना में, जिस तरह विश्लेषण की जाने वाली संभावित प्रतिक्रियाओं को व्यक्त करने के लिए किया जाता है, उसी तरह प्रत्येक मामले में किए जाने वाले ऑपरेशन को निर्धारित करने के लिए एक द्वि-आयामी मैट्रिक्स का भी उपयोग किया जाता है (siguiente_operacion
). विशेष रूप से, हमने तीन प्रकार के संदेशों का जवाब देना चुना है: ① एक मनमाना पाठ (LITERAL
) यह सत्यापित करने के लिए कि क्या वाई-फाई एक्सेस प्वाइंट और सर्वर से कोई कनेक्शन है, ② प्रक्रिया में त्रुटियों का पता लगाने के लिए एक टेक्स्ट (FALLO
) और ③ एक पाठ जो दर्शाता है कि ऑपरेशन सफलतापूर्वक पूरा हो गया था (ACIERTO
).
अंत में, हार मानने से पहले अधिकतम प्रतीक्षा समय निर्धारित करने के लिए दो और वेक्टर हैं (timeout
) और निर्दिष्ट करें (configuracion
) यदि ऑपरेशन प्रतिक्रिया की प्रतीक्षा किए बिना समाप्त हो जाता है (ESPERAR_RESPUESTA
) और संचार के अंत का संकेत देने वाले संदेश। यह अंतिम वेक्टर, मेमोरी को कैसे सहेजा जा सकता है इसका एक उदाहरण देने के लिए, विभिन्न स्थितियों को इंगित करने के लिए कॉन्फ़िगरेशन बाइट के बिट्स के साथ काम करता है।
सबसे पहला ESP8266 एटी कमांड डेटा संरचना हमेशा एक प्रतिक्रिया की अपेक्षा करती है, जो सफलता या त्रुटि संदेश हो सकती है। जब कोई त्रुटि होती है, तो मॉड्यूल को पुनरारंभ किया जाता है और यह फिर से शुरू होता है और यदि संदेश इंगित करता है कि ऑपरेशन सही है, तो यह अगले पर चला जाता है।
जब आप सर्वर से कनेक्ट होते हैं, तो पैटर्न बदल जाता है। इस मामले में यह आवश्यक है①संचारित किए जाने वाले डेटा पैकेट की लंबाई भेजें और②अनुरोध लिखें HTTP एक निश्चित पाठ और मूल्य (तापमान का) के साथ जो सर्वर पर संग्रहीत करने के लिए भेजा जाता है। इस डेटा की तैयारी प्रत्येक शिपमेंट में की जाती है और इसे दो (लंबाई सूचित करें) या तीन (अनुरोध भेजें) में विभाजित करना आवश्यक है HTTP) करने के लिए 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
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();
|
अन्य मैक्रोज़ के साथ, जिन्हें पहले ही समझाया जा चुका है, ऊपर दिए गए उदाहरण कोड से पता चलता है कि विभिन्न राज्यों को कैसे परिभाषित किया जाता है, जिसके साथ यह निर्दिष्ट किया जाता है कि प्रतिक्रिया के लिए इंतजार करना है या नहीं और, यदि लागू हो, तो कौन सा संदेश इंगित करता है कि यह समाप्त हो गया है।
जैसा कि कोड में विभिन्न बिंदुओं पर एक ऑपरेशन भेजा जाएगा (जब औसत तापमान भेजने का समय हो, यदि किसी ऑपरेशन का प्रतीक्षा समय पार हो गया हो, जब वर्तमान ऑपरेशन सफलतापूर्वक पूरा हो गया हो...) लेकिन यह कैसे करना है विश्व स्तर पर स्थापित, इसे एक मैक्रो परिभाषित किया गया है ENVIAR_OPERACION
जो शिपिंग में शामिल चरणों को समूहित करता है।
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();
|
उदाहरण के मुख्य प्रोग्राम का कोड निम्नलिखित है। सबसे बाहरी कार्य औसत की गणना करने के लिए तापमान का नमूना लेने का प्रभारी होता है और, प्रत्येक निश्चित अवधि में, इसे का उपयोग करके सर्वर पर भेजा जाता है 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
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
}
}
}
|
तार्किक रूप से, पिछले कोड पर कई अनुकूलन क्रियाएं की जा सकती हैं, लेकिन यह समझने के लिए एक उदाहरण है कि कैसे ESP8266 सामान्य तौर पर, यह केवल कुछ पहलुओं पर ध्यान देने योग्य है, पहला है डेटा संरचना। ऐसा लगता है कि तार्किक बात है प्रोग्रामिंग भाषा डेटा संरचना का उपयोग करें (struct
) संसाधित की जा रही जानकारी का प्रतिनिधित्व करने के लिए: द ESP8266 एटी कमांड और जिन संदेशों का विश्लेषण किया जाता है।
एक संरचना का प्रयोग करें (struct
) उदाहरण सरणियों के बजाय डेटा संग्रहीत करना (उनके आधार पर) तुच्छ है और, हालांकि इसके परिणामस्वरूप अधिक सुरुचिपूर्ण कोड हो सकता है, लेकिन इसका परिणाम में कोई सुधार नहीं होता है। के उपयोग से सामने आया सच्चा विकल्प struct
कार्यान्वयन करना है, जैसा कि नीचे बताया गया है, संरचनाओं में परिवर्तनीय लंबाई जिसमें "आंतरिक" डेटा होता है जिसका उल्लेख उनके द्वारा किया गया है। इस तरह, उदाहरण के लिए, किसी ऑपरेशन के विश्लेषण के लिए निश्चित संख्या में प्रतिक्रियाओं का होना आवश्यक नहीं होगा।
यह दृष्टिकोण बताता है कि यह समाधान लागू करने का सबसे अच्छा तरीका है लेकिन दोष यह है कि यह आवश्यक होगा गतिशील मेमोरी आवंटन का उपयोग करें, इसके साथ काम करना एक जोखिम भरा अभ्यास है microcontroller जिसके लिए सावधानीपूर्वक माप की आवश्यकता होती है कि रनटाइम पर कितनी मेमोरी का उपयोग किया जाएगा, चूंकि कंपाइलर शायद ही हमें इस बारे में चेतावनी दे पाएगा और प्रोग्राम के निष्पादन के लिए घातक परिणामों के साथ मेमोरी (या स्टैक) के समाप्त होने की एक निश्चित संभावना है।
कोड को अनुकूलित करने की पंक्ति में, यह याद रखना दिलचस्प है कि, इस प्रकार के प्रोग्राम में, जो बड़ी मात्रा में टेक्स्ट का उपयोग करता है, मेमोरी स्पेस बचा सकता है SRAM प्रोग्राम मेमोरी में टेक्स्ट स्ट्रिंग्स को स्टोर करना (फ़्लैश) मैक्रो के साथ F()
. निम्नलिखित स्क्रीनशॉट में आप टेक्स्ट के सामान्य उपयोग और मैक्रो का उपयोग करके विभिन्न प्रोग्राम और डायनामिक मेमोरी वितरण देख सकते हैं F()
.
से प्राप्त सूचना के अनुसार क्रियान्वित की जाने वाली कार्यवाही के संबंध में ESP8266 वाईफ़ाई मॉड्यूल, कोड से संदेश की जांच करने और जो प्राप्त हुआ है उसके अनुसार एक या दूसरे को निष्पादित करने के विकल्प के रूप में, इस डेटा संरचना में संग्रहीत किया जा सकता है स्थिति संकेतकों के बजाय प्रत्येक कार्य को करने वाले कार्यों के संकेतक (झंडे) जो एक निश्चित स्थिति की चेतावनी देते हैं कि एप्लिकेशन प्रबंधन के लिए जिम्मेदार है, उदाहरण के लिए, मुख्य लूप के भीतर।
अनुरोधों के डेटा को संग्रहीत करने के लिए संरचनाओं का एक उदाहरण निम्नलिखित है ESP8266 (डेटा प्रकार operacion_esp8266
) और उनकी प्रतिक्रियाएँ (डेटा प्रकार)। 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;
|
संरचना के रूप में जो ऑपरेशन का प्रतिनिधित्व करती है (डेटा जो भेजा जाता है ESP8266 वाईफ़ाई मॉड्यूल) उस संरचना को संदर्भित करता है जिसके साथ प्रतिक्रियाओं को परिभाषित किया जाता है, और संचालन की संरचना के लिए प्रतिक्रियाओं की संरचना, पहले दोनों की घोषणा करना जरूरी है, नए डेटा प्रकार को परिभाषित करके, और फिर उसकी सामग्री को परिभाषित करके।
पिछला उदाहरण मानता है कि जिस प्रोग्राम में इसे शामिल किया गया है, उसने इसका उपयोग करना चुना है संकेतक डी एस्टाडो, जो उस कोड से पहुंच योग्य एक वेरिएबल के अनुरूप होना चाहिए जो उक्त मूल्य द्वारा इंगित एक या अन्य संचालन करने के लिए जिम्मेदार है। अगर के जवाब में ESP8266 जब एक निश्चित पाठ का विश्लेषण किया जाता है, तो राज्य वह मान लेता है जो संबंधित प्रतिक्रिया की संरचना को इंगित करता है।
जैसा कि पहले कहा गया है, एक अन्य विकल्प, या तो स्थिति संकेतक को प्रतिस्थापित करना या पूरक करना होगा किसी फ़ंक्शन को संदर्भ संरचना में संग्रहीत करें (एक सूचक) जिसे प्रतिक्रिया में कुछ पाठ का सामना करने पर बुलाया जाएगा 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
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;
|
पिछले उदाहरण में, इसे डेटा संरचना में जोड़ा गया है जिसका उपयोग प्रतिक्रिया को संसाधित करने के लिए किया जाता है ESP8266 वाईफ़ाई मॉड्यूल एक (माना गया) फ़ंक्शन के लिए एक सूचक जो प्रकार का डेटा लौटाता है float
(एनालॉग रीडिंग का भारित मान हो सकता है) और जिसके लिए दो बाइट्स तर्क के रूप में प्रदान किए जाते हैं (दो)। unsigned char
जो वह पिन हो सकता है जिससे एनालॉग इनपुट पढ़ा जाता है और वह जो एक काल्पनिक एकीकृत के ENABLE को सक्रिय करता है)।
के लिए विकास में एमसीयूबड़े सिस्टम के लिए विकास शैली में जो होता है उसके विपरीत, किसी असेंबली को नियंत्रित करने वाले एप्लिकेशन के (वैश्विक) व्यवहार को परिभाषित करते समय वैश्विक चर का उपयोग करना इतना असामान्य नहीं है, इसलिए इस प्रकार की परिभाषाओं को ढूंढना विशेष रूप से दुर्लभ नहीं होगा पैरामीटर के बिना फ़ंक्शन के रूप में और जो मान वापस नहीं करता है, कुछ इस तरह void (*accion)();
यदि आप डेटा का प्रतिनिधित्व करने के इस तरीके के साथ काम करते हैं, तो इसका उपयोग करें struct
परिवर्तनीय लंबाई डेटा के साथ, मेमोरी को गतिशील रूप से आवंटित करना आवश्यक होगा malloc()
(o new()
, यदि ऑब्जेक्ट का उपयोग किया जाता है), जो एक पैरामीटर के रूप में आवंटित मेमोरी की मात्रा का उपयोग करेगा और आरक्षित मेमोरी क्षेत्र की शुरुआत में एक पॉइंटर लौटाएगा। साथ sizeof()
संग्रहीत प्रकार के आधार पर, उपयोग किए गए तत्वों की संख्या से गुणा करके, आप आवश्यक मेमोरी की मात्रा प्राप्त कर सकते हैं। इसके उपयोग के साथ और इसके बिना का एक उदाहरण नीचे स्क्रीनशॉट में देखा जा सकता है। malloc()
; पहले मामले में प्रोग्राम द्वारा उपयोग की जाने वाली मेमोरी से सावधान रहें, आपको उस लाइब्रेरी को लोड करना होगा जिसमें यह फ़ंक्शन शामिल है।
यदि संचालन पर ESP8266 वाईफ़ाई मॉड्यूल प्रोग्राम के निष्पादन के दौरान अलग-अलग होगा, उस मेमोरी को मुक्त करना आवश्यक होगा जिसका उपयोग नहीं किया गया है free()
(o delete()
, वस्तु होने की स्थिति में)। हालाँकि यह अपेक्षा करना उचित है कि संकलक (जीसीसी) मेमोरी विभाजन से बचने के लिए प्रोग्राम को अनुकूलित करेगा, निश्चित रूप से प्रदर्शन स्थिर रूप से आवंटित मेमोरी के साथ काम करने जितना इष्टतम नहीं होगा।
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
}
}
}
|
हालाँकि इस उदाहरण में (दोनों कार्यान्वयन में) इसका कोई खास मतलब नहीं है, अन्य मामलों में इसे लागू करने में सक्षम होने के लिए ऑपरेशन को सामान्य बनाने के लिए, यह ध्यान दिया जाना चाहिए कि डेटा भेजना हमेशा एक ही प्रोटोकॉल दोहराता है: भेजे जाने वाले बाइट्स की संख्या सूचित करें, संकेतक (>) की प्रतीक्षा करें और डेटा भेजें.
चूँकि इस उदाहरण में इसका उपयोग केवल एक बार किया जाता है (पूरा अनुरोध एक पैकेट में किया जाता है), यह बहुत उपयोगी नहीं लगता है, लेकिन सामान्य तौर पर, एक ही ऑपरेशन में कई बार भेजना आवश्यक हो सकता है, जिसमें ऐसे मामले भी शामिल हैं जिनमें उन्हें ऐसा करना होगा। महत्वपूर्ण मात्रा में डेटा प्रसारित किया जाना चाहिए जिसे मेमोरी को ओवरफ्लो होने से बचाने के लिए खंडित किया जाना चाहिए ESP8266.
इस व्यवहार को लागू करने के लिए, कनेक्शन के अंतिम दो तत्वों का उपयोग किया जा सकता है ताकि हर बार डेटा भेजे जाने पर, डेटा संबंधित मानों से भरा हो: पहले मामले में, भेजे गए बाइट्स की संख्या और दूसरे में, ( अनुरोध का भाग। प्रेषित किया जाना है।
असाइनमेंट को दोहराने और प्रेषित किए जाने वाले विभिन्न तत्वों को एक वेक्टर में संग्रहीत किया जा सकता है। यह नया वेक्टर वह होगा जो जटिल ऑपरेशन के अंत को निर्धारित करता है न कि अब तक के अंतिम ऑपरेशन को।
1 टिप्पणी