الجمعة، 8 فبراير 2019

ربط ESP32 مع ESP32 والاتصال عبر الإنترنت

نموذج مشروع بسيط يوضح كيفية إنشاء اتصال بين جهازين يعملان بنظام ESP32. يعمل على حد سواء في الشبكة المحلية وعبر الإنترنت.


الأشياء المستخدمة في هذا المشروع
مكونات الأجهزة

ESP ESP32S عدد 2
بطارية    1000mAh عدد 2
بوش بتن عدد 2 
دايود ضوئي عدد 2

قصة

تتضمن المشاريع المرتبطة بشكل نموذجي نوعًا من واجهة المستخدم على الويب أو الجوّال. إذا كنت ترغب في السيطرة على شيء واحد عن طريق شيء آخر ، وبالتزامن مع زمن انتقال منخفض وعبر الإنترنت ، فمن الصعب جدًا تحقيق ذلك. هذا هو السبب في أنني خلقت هذا المشروع. إنه نموذج إطار عمل اردوينو يوضح لك كيفية توصيل لوحين يعتمدان على ESP32 عبر الإنترنت ، مما يقلل من زمن الوصول مع وظيفة الاستعادة التلقائية في حالة اتصال Wi-Fi المعطل أو الطاقة المؤقتة لأسفل في لوحة متصلة. الشيء الرائع هو أنه يعمل إذا كانت لوحات ESP32 في نفس شبكة Wi-Fi وإذا كانت في شبكات منفصلة. حتى في مختلف القارات.


يمكن أن يكون القالب الذي نعرضه هنا أساسًا لمجموعة متنوعة من الواجهات الرائعة للمشروعات المستندة إلى ESP32 ، مثل:

القفاز الذكي للتحكم في سيارة RC الخاصة بك
التحكم عن بعد للأجهزة المنزلية الذكية الخاصة بك
مفتاح Wi-Fi آمن وخاص لمنزلك (في حين أن الاتصال هو P2P ، لا يمكن لأي طرف ثالث الوصول إلى مفتاح التشفير)
زر سريع حقا على الإنترنت لأشياءك
والكثير الكثير.


الوظيفة الافتراضية للقالب هي التحكم ثنائي الاتجاه في مصابيح LED بواسطة أزرار لوحات ESP32. يمكنك أيضًا التعامل مع هذا القالب باعتباره مُعرّف مورس على الإنترنت :). لا تتردد في استبدال الرمز للتحكم في الأزرار ومصابيح LED من خلال أي عملية إدخال / إخراج تحتاج إليها.
في المشروع ، ننشئ مهمتين: الأولى لإدارة اتصال Wi-Fi والثانية للتعامل مع تبادل البيانات بين الأجهزة.

مهمة Wi-Fi
void taskWifi( void * parameter ) {
 while (1) {
   for (int i = 0; i < NUM_NETWORKS; i++) {
     Serial.print("Connecting to ");
     Serial.print(ssidTab[i]);
     WiFi.begin(ssidTab[i], passwordTab[i]);
     for (int j = 0; j < 10; j++) {
       if (WiFi.status() != WL_CONNECTED) {
         delay(500);
         Serial.print(".");
       } else {
         Serial.println("done");
         Serial.print("IP address: ");
         Serial.println(WiFi.localIP());
#if DEV_TYPE == 0
         Husarnet.join(husarnetJoinCode, hostName0);
#elif DEV_TYPE == 1
         Husarnet.join(husarnetJoinCode, hostName1);
#endif
         Husarnet.start();
         while (WiFi.status() == WL_CONNECTED) {
           delay(500);
         }
       }
     }
   }
 }
}

تتم كتابة مهمة Wi-Fi للتبديل التلقائي إلى شبكة Wi-Fi أخرى في حالة قطع اتصال حالي. في قسم التهيئة (الخطوط من 7 إلى 40 من شفرة المصدر) ، يمكنك ترميز أكثر من بطاقة اعتماد شبكة Wi-Fi - وهذا هو الحل المريح ، لأنك لست بحاجة إلى إعادة برمجة لوحاتك إذا قمت بتشغيلها في مواقع مختلفة .


بشكل أساسي ، يتم إنشاء شبكة LAN ظاهرية بين أجهزة ESP32 بفضل هذين السطرين:
Husarnet.join(husarnetJoinCode, hostNameX);
Husarnet.start();
يتم تحديد الأجهزة بواسطة أسماء المضيف الخاصة بهم ، لذلك لا داعي للقلق ، حول العثور على عناوين IP. الاتصال هو أيضا مشفر بالكامل وآمن ، وخاصة. وهو لا يعمل فقط في الشبكة المحلية (LAN) ، ولكن أيضًا عبر الإنترنت ، لأن الاتصال يعمل بواسطة Husarnet. تساعد Husarnet فقط في إنشاء اتصال عبر الإنترنت ولا يتم إعادة توجيه بيانات المستخدم بواسطة خوادمها. وبفضل هذا الكمون أقل.


مهمة الاتصال
void taskConnection( void * parameter ) {
uint8_t oldState = btn.getLastButtonState();
while (1) {
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
#if DEV_TYPE == 0
server.begin();
Serial.println("Waiting for client");
do {
delay(500);
client = server.available();
client.setTimeout(3);
} while (client < 1);
#elif DEV_TYPE == 1
Serial.printf("Connecting to %s\r\n", hostName0);
while (client.connect(hostName0, port) == 0) {
delay(500);
}
#endif
Serial.printf("Client connected: %d\r\n", (int)client.connected());
unsigned long lastMsg = millis();
auto lastPing = 0;
while (client.connected()) {
//ping RX
if (millis() - lastMsg > 6000) {
Serial.println("ping timeout");
break;
}
//ping TX
auto now = millis();
if (now > lastPing + 4000) {
client.print('p');
lastPing = now;
}
if (oldState != btn.getLastButtonState()) {
oldState = btn.getLastButtonState();
if (oldState == 0) {
client.print('a');
} else {
client.print('b');
}
}
if (client.available()) {
char c = client.read();
if (c == 'p') {
lastMsg = millis();
}
if (c == 'a') {
digitalWrite(LED_PIN, HIGH);
}
if (c == 'b') {
digitalWrite(LED_PIN, LOW);
}
Serial.printf("read: %c\r\n", c);
}
}
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}

تتدرب أجهزة ESP32 بعضها بعضًا كل 4s. إذا لم يتم تلقي ping لأكثر من 6 ساعات ، فإن حلقة الاتصال معطلة وتنتظر أن يكون الجهاز الثاني متصلاً بالإنترنت. نظرًا لأن الهدف من المشروع هو الحفاظ على بساطة ، فإننا لا نصنع إطارات ثنائية ، ونستخدم مخازن البروتوكول إلخ. اعتمادا على التطبيق الخاص بك يمكنك بسهولة تعديل ذلك.

تجميع
ربط زر الضغط بين دبوس P22 و GND
ربط الصمام الثنائي الصمام الثنائي والمقاوم في سلسلة بين دبوس P16 و GND

قم بتوصيل البطارية بلوحة ESP32. في المشروع نستخدم ESP32 devkit مع LDO المدمج في. ألقِ نظرة على الحد الأقصى لمستوى الجهد الكهربي للإدخال في حالة اللوحة المستندة إلى ESP32 لتجنب التلف.

قم بإعداد برنامج ثابت
افتح Arduino IDE واتبع الخطوات التالية:
1. Install AceButton library:
  • open Tools -> Manage Libraries...
  • ابحث عن acebutton library and click Install button
  • 2. قم بتثبيت دعم ESP32-Husarnet:

  • فتح ملف -> تفضيلات
  • في حقل إضافة عناوين URL الخاصة بمدير مجلس الإدارة الإضافي:
  • https://files.husarion.com/arduino/package_esp32_husarnet_index.json 
    
    • افتح Tools -> Board: ... -> Boards Manager ...
    • ابحث عن esp32-husarnet
    • اضغط على Install 


    3. حدد لوحة Dev ESP32:

    أدوات مفتوحة -> المجلس
    حدد وحدة ESP32 Dev ضمن قسم ESP32 Arduino (Husarnet)
    4. برمجة لوحات ESP32 الخاصة بك:

    افتح مشروع ESP32_ledstrip_webserver.ino

    قم بتعديل السطر 25 مع كود رابط Husarnet الخاص بك (احصل على https://app.husarnet.com)
    تعديل الخطوط 28 - 38 لإضافة بيانات اعتماد شبكة Wi-Fi الخاصة بك

    تحميل المشروع إلى لوحة ESP32 الخاصة بك. كرر الخطوات السابقة مع (السطر 9):

      #define DEV_TYPE 0    // type "0" for 1st ESP32, and "1" for 2nd ESP32
      قم بتشغيل كل من وحدات ESP32 وانتظر لمدة 15 ثانية للسماح لأجهزة ESP32 بالاتصال بشبكة Wi-Fi وإنشاء اتصال P2P (يعمل في كل من شبكة LAN وعبر الإنترنت).
      و هذا كل شيء! اتمنى ان ينال اعجابك.
      #include <WiFi.h>
      #include <Husarnet.h>
      #include <AceButton.h>
      
      using namespace ace_button;
      
      /* =============== config section start =============== */
      
      #define DEV_TYPE 0    // type "0" for 1st ESP32, and "1" for 2nd ESP32
      
      const int BUTTON_PIN = 22;
      const int LED_PIN = 16;
      
      // Husarnet credentials
      const char* hostName0 = "esp2esp0";  //this will be the name of the 1st ESP32 device at https://app.husarnet.com
      const char* hostName1 = "esp2esp1";  //this will be the name of the 2nd ESP32 device at https://app.husarnet.com
      
      /* to get your join code go to https://app.husarnet.com
         -> select network
         -> click "Add element"
         -> select "join code" tab
      
         Keep it secret!
      */
      const char* husarnetJoinCode = "xxxxxxxxxxxxxxxxxxxxxx";
      
      // WiFi credentials
      #define NUM_NETWORKS 2  //number of Wi-Fi network credentials saved
      
      const char* ssidTab[NUM_NETWORKS] = {
        "wifi-ssid-one",
        "wifi-ssid-two",
      };
      
      const char* passwordTab[NUM_NETWORKS] = {
        "wifi-pass-one",
        "wifi-pass-two",
      };
      
      /* =============== config section end =============== */
      
      AceButton btn(BUTTON_PIN);
      
      HusarnetClient client;
      
      uint16_t port = 8001;
      
      #if DEV_TYPE == 0
      HusarnetServer server(port);
      #endif
      
      void handleEvent(AceButton*, uint8_t, uint8_t);
      void taskWifi( void * parameter );
      void taskConnection( void * parameter );
      
      void setup() {
        Serial.begin(115200);
      
        pinMode(BUTTON_PIN, INPUT_PULLUP);
        btn.setEventHandler(handleEvent);
      
        pinMode(LED_PIN, OUTPUT);
        digitalWrite(LED_PIN, HIGH);
      
        xTaskCreate(
          taskWifi,          /* Task function. */
          "taskWifi",        /* String with name of task. */
          10000,            /* Stack size in bytes. */
          NULL,             /* Parameter passed as input of the task */
          1,                /* Priority of the task. */
          NULL);            /* Task handle. */
      
        xTaskCreate(
          taskConnection,          /* Task function. */
          "taskConnection",        /* String with name of task. */
          10000,            /* Stack size in bytes. */
          NULL,             /* Parameter passed as input of the task */
          1,                /* Priority of the task. */
          NULL);            /* Task handle. */
      }
      
      void loop() {
        while (1) {
          btn.check();
          delay(1);
        }
      }
      
      void handleEvent(AceButton* button, uint8_t eventType,
                       uint8_t buttonState) {
        switch (eventType) {
          case AceButton::kEventPressed:
            Serial.println("pressed");
            break;
          case AceButton::kEventReleased:
            Serial.println("released");
            break;
        }
      }
      
      void taskWifi( void * parameter ) {
        while (1) {
          for (int i = 0; i < NUM_NETWORKS; i++) {
            Serial.print("Connecting to ");
            Serial.print(ssidTab[i]);
            WiFi.begin(ssidTab[i], passwordTab[i]);
            for (int j = 0; j < 10; j++) {
              if (WiFi.status() != WL_CONNECTED) {
                delay(500);
                Serial.print(".");
              } else {
                Serial.println("done");
                Serial.print("IP address: ");
                Serial.println(WiFi.localIP());
      #if DEV_TYPE == 0
                Husarnet.join(husarnetJoinCode, hostName0);
      #elif DEV_TYPE == 1
                Husarnet.join(husarnetJoinCode, hostName1);
      #endif
                Husarnet.start();
                while (WiFi.status() == WL_CONNECTED) {
                  delay(500);
                }
              }
            }
          }
        }
      }
      
      void taskConnection( void * parameter ) {
        uint8_t oldState = btn.getLastButtonState();
      
        while (1) {
          while (WiFi.status() != WL_CONNECTED) {
            delay(500);
          }
      
      #if DEV_TYPE == 0
      
          server.begin();
          Serial.println("Waiting for client");
      
          do {
            delay(500);
            client = server.available();
            client.setTimeout(3);
          } while (client < 1);
      
      #elif DEV_TYPE == 1
      
          Serial.printf("Connecting to %s\r\n", hostName0);
          while (client.connect(hostName0, port) == 0) {
            delay(500);
          }
      
      #endif
      
          Serial.printf("Client connected: %d\r\n", (int)client.connected());
      
          unsigned long lastMsg = millis();
          auto lastPing = 0;
      
          while (client.connected()) {
            //ping RX
            if (millis() - lastMsg > 6000) {
              Serial.println("ping timeout");
              break;
            }
      
            //ping TX
            auto now = millis();
            if (now > lastPing + 4000) {
              client.print('p');
              lastPing = now;
            }
      
            if (oldState != btn.getLastButtonState()) {
              oldState = btn.getLastButtonState();
              if (oldState == 0) {
                client.print('a');
              } else {
                client.print('b');
              }
            }
      
            if (client.available()) {
              char c = client.read();
      
              if (c == 'p') {
                lastMsg = millis();
              }
              if (c == 'a') {
                digitalWrite(LED_PIN, HIGH);
              }
              if (c == 'b') {
                digitalWrite(LED_PIN, LOW);
              }
      
              Serial.printf("read: %c\r\n", c);
            }
          }
          client.stop();
          Serial.println("Client disconnected.");
          Serial.println("");
        }
      }
      
      
      ESP32 إلى ESP32 مثال على الاتصال باستخدام إطار اردوينوهنـــــــــــــــا وهنا اقرأ المزيد 
      
      






      ليست هناك تعليقات:

      إرسال تعليق