цифровая электроника
вычислительная техника
встраиваемые системы

 

Связь между двумя ESP32 через интернет

Автор: Mike(admin) от 11-04-2019, 04:55

ESP32 представляет собой мощный и в то же время простой в обращении микроконтроллер со встроенными возможностями беспроводной связи. В данном примере будет представлен простой проект, показывающий, как установить соединение между двумя устройствами на основе ESP32. Это работает как в локальной сети, так и через интернет.


Связь между двумя ESP32 через интернет

Обычно подключаемые проекты имеют веб-интерфейс или мобильный интерфейс. Если вы хотите контролировать одну вещь посредством другой, особенно с низкой задержкой и через Интернет, это довольно сложно достичь. В этом деле пригодится такой проект как этот. Это шаблон инфраструктуры Arduino, показывающий, как соединить две платы на основе ESP32 через Интернет, сводя к минимуму задержку с помощью функции автоматического восстановления в случае обрыва соединения Wi-Fi или временного отключения питания одной из подключенных плат. Эта концепция работает, если платы ESP32 находятся в одной сети Wi-Fi и если они находятся в разных сетях, даже на разных континентах.


Функциональность шаблона проекта по умолчанию – двунаправленное управление светодиодами кнопками разных плат ESP32. Вы также можете рассматривать этот шаблон как интернет-коммуникатор с азбукой Морзе. Не стесняйтесь заменять код для управления кнопками и светодиодами на любые необходимые операции ввода/вывода.


В проекте мы создаем две задачи: первая для управления подключением Wi-Fi, а вторая – для обмена данными между устройствами.


Задача Wi-Fi создается для автоматического переключения на другую сеть Wi-Fi в случае разрыва текущего соединения. В разделе конфигурации (строки 7–40 исходного кода) вы можете жестко закодировать несколько учетных данных сети 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);
         }
       }
     }
   }
 }

По сути, благодаря этим двум строкам создается сеть виртуальной локальной сети между устройствами ESP32:



Husarnet.join(husarnetJoinCode, hostNameX);
Husarnet.start();

Устройства идентифицируются по именам хостов, поэтому вам не нужно беспокоиться о поиске IP-адресов. Соединение также полностью зашифровано, безопасно и конфиденциально. Это работает не только в локальной сети, но и через Интернет, потому что подключение осуществляется через Husarnet (husarnet.com). Husarnet помогает только в установлении соединения через Интернет, а пользовательские данные не пересылаются его серверами. Благодаря этому задержка меньше.


Устройства ESP32 пингуют друг друга каждые 4 секунды. Если в течение более 6 секунд пинг не получен, цикл соединения разрывается и ожидает подключения второго устройства. Поскольку цель проекта состояла в том, чтобы сделать его простым, мы не создаем двоичные кадры, не используем буфер протокола и т. д. В зависимости от вашего приложения вы можете легко изменить это.



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("");
 }
}

Поговорим теперь о подключении аппаратной части. Подключите кнопку между контактом P22 и GND. Подключите светодиод и резистор последовательно между контактом P16 и GND. Подключите аккумулятор к вашей плате на базе ESP32. В проекте мы используем ESP32 devkit со встроенным LDO. Посмотрите на максимальный уровень входного напряжения на вашей плате на базе ESP32, чтобы избежать повреждения.


Теперь позаботимся о программном обеспечении. Подключите библиотеку acebutton, найдя ее в менеджере библиотек.


Связь между двумя ESP32 через интернетСвязь между двумя ESP32 через интернет

Затем установим поддержку ESP32-Husarnet. Откройте Настройки Aduino IDE (Preferences), добавьте ссылку https://files.husarion.com/arduino/package_esp32_husarnet_index.json через Additional Board Manager URLs. Откройте менеджер плат (Boards manager) и найдите esp32-husarnet. Нажмите кнопку установки.


Связь между двумя ESP32 через интернет

Из списка плат выберете ESP32 Arduino (Husarnet). Откройте проект ESP32_ledstrip_webserver.ino. Измените строку 25 вашим кодом присоединения Husarnet (возьмите на https://app.husarnet.com).


Связь между двумя ESP32 через интернет

Измените строки 28 - 38, чтобы добавить свои учетные данные сети Wi-Fi. Сделайте все то же самое со второй платой, изменив только значение в строке 9 с 0 на 1. Включите оба модуля ESP32 и подождите около 15 секунд, чтобы устройства ESP32 подключились к сети Wi-Fi и установили соединение P2P (работает как в локальной сети, так и через Интернет). Вот полный код программы.



#include <WiFi.h>
#include <Husarnet.h>
#include <AceButton.h>

using namespace ace_button;

#define DEV_TYPE 0    // type "0" for 1st ESP32, and "1" for 2nd ESP32

const int BUTTON_PIN = 22;
const int LED_PIN = 16;

const char* hostName0 = "esp2esp0";
const char* hostName1 = "esp2esp1";


const char* husarnetJoinCode = "xxxxxxxxxxxxxxxxxxxxxx";

#define NUM_NETWORKS 2

const char* ssidTab[NUM_NETWORKS] = {
  "wifi-ssid-one",
  "wifi-ssid-two",
};

const char* passwordTab[NUM_NETWORKS] = {
  "wifi-pass-one",
  "wifi-pass-two",
};

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,
    "taskWifi",
    10000,
    NULL,
    1,
    NULL);

  xTaskCreate(
    taskConnection,
    "taskConnection",
    10000,
    NULL,
    1,
    NULL);
}

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()) {
      if (millis() - lastMsg > 6000) {
        Serial.println("ping timeout");
        break;
      }

      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("");
  }
}



© digitrode.ru


Теги: ESP32



   Благодарим Вас за интерес к информационному проекту digitrode.ru.
   Если Вы хотите, чтобы интересные и полезные материалы выходили чаще, и было меньше рекламы,
   Вы можее поддержать наш проект, пожертвовав любую сумму на его развитие.


Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Комментарии:

Оставить комментарий