الجمعة، 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 مثال على الاتصال باستخدام إطار اردوينوهنـــــــــــــــا وهنا اقرأ المزيد 
      
      






      الاثنين، 4 فبراير 2019

      مستشعر الرطوبة- التحكم بمروحة الحمام

      المكونات والإمدادات


      اردوينو نانو ار 3
      مصدر طاقة 12 فولت
      اسلاك توصيل


      حول هذا المشروع
      تم تصميم هذا المشروع لإحساس مستوى الرطوبة في الحمام وتهويةه حتى يجف الأرض المبللة لتقليل تراكم الرطوبة في المساحة المغلقة.

      يتم تجهيز الحمامات عادة بمراوح العادم لإزالة البخار أثناء الاستحمام ، على سبيل المثال ، ويتم إيقاف تشغيلها في اللحظة التي ننجز فيها. سوف تجف الأرض من تلقاء نفسها ولكن الرطوبة تبقى في الحمام. مع مرور الوقت ، يؤدي تراكم الرطوبة إلى نمو العفن ، والذي يمكن أن يسبب مشاكل صحية شديدة 
      يمكن أن يكون ترك مروحة العادم الرئيسية خيارًا ، ولكنه مزعج إلى حد ما ويضيف إلى فاتورة الكهرباء.
      في هذا المشروع ، أستفيد من مستشعر رطوبة DHT-11 ، ومروحة غلاف كبيرة للكمبيوتر (200 مم DIA ، و 12 أمبير 300 ميلي أمبير) ، و Nano Arduino ، وموصف MOSFET للقيام بهذه المهمة. في نهاية المطاف ، 






      كود البرمجة


      #include <SimpleDHT.h>
      
      //Declaring digital pin no 2 as the dht11 data pin
      
      int pinDHT11 = 2;
      int DHTpower = 3;
      int Fan = 13;
      int LDRstate = LOW;
      SimpleDHT11 dht11;
      
      void setup() {
        pinMode(Fan, OUTPUT);
        pinMode(DHTpower, OUTPUT);
        pinMode(LDR, INPUT);
        pinMode(LDRpower, OUTPUT);
        digitalWrite(DHTpower, LOW);
        digitalWrite(LDRpower, LOW);
        digitalWrite(Fan, LOW);
        Serial.begin(9600);   
      }
      
      void loop() {
        delay(1000);
        RHcheck();                        //check Humidity Level
        delay(15000);                     //wait 15sec
        }
      
      
      void RHcheck() {                    //Check Humidity Level Function
        digitalWrite(DHTpower, HIGH);     //On Humidity Sensor
        delay(5000);
        Serial.println("============ Check Humidity ===============");
        delay(1000);
        Serial.println("DHT11 readings...");
         
        byte temperature = 0;
        byte humidity = 0;
        int err = SimpleDHTErrSuccess;
      
        //This bit will tell our Arduino what to do if there is some sort of an error at getting readings from our sensor
        if ((err = dht11.read(pinDHT11, &temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
          Serial.print("No reading , err="); Serial.println(err);delay(1000);
          return;
        }
        Serial.print("Readings: ");
        Serial.print((int)temperature); Serial.print(" C, ");
        Serial.print((int)humidity); Serial.println(" %");
        delay(500);
        if((int)humidity < 50){
          digitalWrite(DHTpower, LOW);
          delay(500);
          Serial.println("Fan OFF");
          delay(500);
          digitalWrite(Fan, LOW);
        }else{
          if ((int)humidity > 58){
            Serial.println("Humidity > 58%");
            digitalWrite(DHTpower, LOW);
            delay(500);
            Serial.println("Fan ON @ full speed");
            delay(500);
            digitalWrite(Fan, HIGH);
          }else{
            Serial.println("50% < Humidity < 58%");
            digitalWrite(DHTpower, LOW);
            delay(500);
            Serial.println("Fan ON @ low speed");
            delay(500);
            analogWrite(Fan, 200);
          }
        }
       }







      قياس درجة الحرارة والضغط والارتفاع بواسطة اردوينو



      المواد المستخدمة
      اردوينو اونو او جينون
      Adafruit BMP280
      Adafruit OLED 128x32 i2c


      مرحبًا بك ومرحبا بكم في هذا البرنامج التعليمي حيث أستخدم BMP280 لقياس درجة الحرارة والضغط والإرتفاع أيضًا ، بمساعدة لوحة Arduino UNO وشاشة OLED ، وهنا بعض من المعلمات الرئيسية BMP280 من ورقة البيانات:





      لذا بالنسبة لهذا المشروع ، سنستخدم الوحدة لقياس كل هذه الأشياء في النظامين المتري والإمبراطوري كالمعتاد ، لست متأكدًا من الوحدات ولكن يمكنك دائمًا تحويلها من خلال الشفرة ، وهنا المكونات التي سنقوم بها استعمال:






      الاختبار واستكشاف الأخطاء وإصلاحها:
             بعد توصيل الوحدة ، من الأفضل اختبار الشفرة من مثال المكتبة ، واسمها هو "BMP280test" ، إذا لم يتم اكتشاف وحدتك كما في الصورة أدناه:



      يمكنك تشغيل شفرة i²c للماسح الضوئي (ولكن قم بإلغاء توصيل أي جهاز آخر i²c مثل LCD أو OLED) ، وإذا لم يتم كسر الوحدة ، أو إذا لم يكن لديك مشكلة في اللحام ، فسترى أن الجهاز قد تم اكتشافه بواسطة الماسح الضوئي :


      الآن لاحظ هذا العنوان وانتقل إلى ملف مكتبة c ++ الخاص بك ، يتم تثبيت المكتبة عادة في 
      “Documents/Arduino/Libraries”:


      وفتحه باستخدام محرر مناسب ، فأنا أستخدم 
      Dev ++c





      ثم انتقل إلى السطر "41" و "_i2caddr" تغيير "a" باستخدام العنوان الموجود على جهاز العرض التسلسلي:



      حفظ الكل وإغلاقه ، يُقصد بالمكتبة العمل مع الوحدات التي تحتوي على 0x77 كعنوان i²c ، لكن العنوان الذي أستخدمه له 0x76.

      قم بتشغيل رمز الاختبار مرة أخرى:




      كود البرمجة

      
      #include <Adafruit_BMP280.h>
      
      Adafruit_BMP280 bmp; // I2C Interface
      
      void setup() {
        Serial.begin(9600);
        Serial.println(F("BMP280 test"));
      
        if (!bmp.begin()) {
          Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
          while (1);
        }
      
        /* Default settings from datasheet. */
        bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                        Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                        Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                        Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                        Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
      }
      
      void loop() {
          Serial.print(F("Temperature = "));
          Serial.print(bmp.readTemperature());
          Serial.println(" *C");
      
          Serial.print(F("Pressure = "));
          Serial.print(bmp.readPressure()/100); //displaying the Pressure in hPa, you can change the unit
          Serial.println(" hPa");
      
          Serial.print(F("Approx altitude = "));
          Serial.print(bmp.readAltitude(1019.66)); //The "1019.66" is the pressure(hPa) at sea level in day in your region
          Serial.println(" m");                    //If you don't know it, modify it until you get your current altitude
      
          Serial.println();
          delay(2000);
      }
      
      Adafruit SSD1306
      Adafruit GFX library
      BMP280_Adafruit_library