ESP8266 jako Access Point

arduino master slave

Komunikacja miedzy dwoma lub więcej Arduino przy większych projektach staje się nieoceniona, gdyż bez kładzenia kabli na potrzeby RS485 można osiągnąć to samo, tyle że szybciej i prościej… trzeba tylko rozgryźć jak to zrobić. Mi się udało.

W przypadku gdy na przykład za pomocą ekranu dotykowego będącego w domu chcę:

  • sterować podlewaniem ogrodowym,
  • zwijać i rozwijać markizę,
  • otwierac i zamykąć bramą garażową,
  • włączać oświetlenie w ogrodzie,
  • pobierać temperaturę ze strychu,
  • itp itd…

Nie mam do tych odbiorników pociągniętych kabli. Rozwiązaniem staje się wykorzystanie ESP8266 jako Access Point, czyli stworzenie własnej sieci WIFI, do której będę dołączał urządzenia peryferyjne będące fizycznie przy konkretnym odbiorniku. Każde takie urządzenie może posiadać swoje przekaźniki sterujące konkretnym urządzeniem, których stan zależy od otrzymanego polecenia z modułu głównego (ekranu dotykowego będącego w domu).

Każde urządzenie peryferyjne – nazwijmy je SLAVE – posiada swój adres IP w sieci z urządzenia MASTER. Tak więc urządzenie MASTER wysyła do urządzenia SLAVE po konkretnym adresie IP polecenie, niech to będzie JSON, w którym zawarte są polecenia, jak SLAVE ma się zachować.

Jedyne, co trzeba zapewnić, to zasilanie Arduino np 5V oraz zasięg tworzonej sieci, co wydaje się dość efektywne. Sygnał łapie nawet 15-20m od urządzenia MASTER.

Działający, przykładowy kod dla urządzenia MASTER:

    #include "WiFiEsp.h"
    #define TIMEOUT 1000
    
    //esp
    char ssid[] = "tworzona-sieci-wifi";
    char pass[] = "panzpogodna";
    int status = WL_IDLE_STATUS;
    WiFiEspServer server(80);
    IPAddress myAddrFinal;
    char myIpString[16];
    long lastDebounceTime = 0;
    boolean doOnce = true;
    String data = "";
    
    void setup() {
    
      Serial.begin(115200);
      initWifi();
    
    }
    
    void loop() {
    
      //listen to incoming requests
      http();
    
      //send single request do device in tworzona-sieci-wifi network @ 192.168.111.100
      if (doOnce) {
        delay(1000);
        String jsonToSend = "{\"command\":\"start\"}" + String("^");
        String partnerIp = "192.168.111.100";
        sendRequest(partnerIp, jsonToSend);
        doOnce = false;
      }
    }
    
    void http() {
    
      WiFiEspClient client2 = server.available();  // listen for incoming clients
    
      if (client2) {
        int allowReadAllTheTime = 0;
        data = "";
    
        while (client2.connected()) {
    
          while (client2.available()) {
            char c = client2.read();
    
            if (char(c) == '?' || allowReadAllTheTime == 1) { //valid query
    
              allowReadAllTheTime = 1;
    
              if (char(c) != '^') {
                data += c;
              } else {
                data = data + "^";
                //Serial.println("data");
                //Serial.println(data);
                //Serial.println("END data");
              }
    
              int index = data.indexOf('?');
              int index2 = data.lastIndexOf('^');
    
              if (index > -1 && index2 > -1) { //valid query with all marks
    
                data = (data.substring(index + 3, index2));
                Serial.println(data);
    
                client2.flush();
                client2.stop();
    
              }
            }
          }
        }
      }
    }
    
    void sendRequest(String partnerIp, String jsonToSend) {
    
      char ipCharBuffer[partnerIp.length() + 1];
      partnerIp.toCharArray(ipCharBuffer, partnerIp.length() + 1);
      delay(100);
    
      WiFiEspClient client;
      if (client.connect(ipCharBuffer, 80)) {
        String url = "GET ?" + jsonToSend + " HTTP/1.1\r\n";
        url += "Host: " + String(ipCharBuffer) + "\r\n";
        url += "Connection: close\r\n\r\n";
        //Serial.println(url);
        client.print(url);
        client.flush();
        client.stop();
      }
    }
    
    void initWifi() {
    
      Serial1.begin(115200);
      Serial1.setTimeout(TIMEOUT);
      WiFi.init(&Serial1);
    
      if (WiFi.status() == WL_NO_SHIELD) {
        while (true); // don't continue
      }
    
      // ustaw IP swojego urządzenia
      IPAddress localIp(192, 168, 111, 111);
      WiFi.configAP(localIp);
    
      // start access point
      status = WiFi.beginAP(ssid, 10, pass, ENC_TYPE_WPA2_PSK);
    
      Serial.println("Access point started");
      printWifiStatus();
    
      server.begin();
      Serial.println("Server started");
    
    }
    
    
    void printWifiStatus() {
    
      IPAddress ip = WiFi.localIP();
      Serial.print("IP Address: ");
      Serial.println(ip);
    
    }

Działający, przykładowy kod dla urządzenia SLAVE:

    #include "WiFiEsp.h"
    #define TIMEOUT 1000
    
    //esp
    WiFiEspServer server(80);
    byte status = WL_IDLE_STATUS;
    WiFiEspClient client;
    IPAddress myAddrFinal;
    char myIpString[16];
    byte unsuccesfullConnectionIndex = 0;
    byte buffer[10];
    String data;
    String senderIp;
    
    
    void setup() {
    
      Serial.begin(115200);
      //esp
      initWifi();
      connectToWifi("tworzona-sieci-wifi", "panzpogodna");
    
    }
    
    void loop() {
    
      http();
    
    }
    
    
    void http() {
    
      WiFiEspClient client = server.available();  // listen for incoming clients
    
      if (client) {
    
        int allowReadAllTheTime = 0;
        data = "";
    
        while (client.connected()) {
    
          while (client.available()) {
            char c = client.read();
    
            if (char(c) == '?' || allowReadAllTheTime == 1) { //valid query
    
              allowReadAllTheTime = 1;
    
              if (char(c) != '^') {
                data += c;
              } else {
                data = data + "^";
                // Serial.println("data");
                // Serial.println(data);
                // Serial.println("END data");
              }
    
              int index = data.indexOf('?');
              int index2 = data.lastIndexOf('^');
    
              if (index > -1 && index2 > -1) { //valid query with all marks
    
                data = (data.substring(index + 3, index2));
                senderIp = String(client.remoteIP()[0]) + "." + String(client.remoteIP()[1]) + "." + String(client.remoteIP()[2]) + "." + String(client.remoteIP()[3]);
    
                Serial.println("received data");
                Serial.println(data);
                Serial.println("sender - lets send confirmation");
                Serial.println(senderIp);
    
                client.flush();
                client.stop();
    
                sendResponse (senderIp);
    
              }
            }
          }
        }
      }
    }
    
    void sendResponse (String to) {
    
      char deviceIPBuffer[24];
      to.toCharArray(deviceIPBuffer, to.length() + 1);
      String response = "";
    
      myAddrFinal  = WiFi.localIP();
      sprintf(myIpString, "%d.%d.%d.%d", myAddrFinal[0], myAddrFinal[1], myAddrFinal[2], myAddrFinal[3]);
    
      String json = "{\"confirmation\":\"received\"}";
    
      response = json + "^"; //confirmation
    
      Serial.println("response to sender:");
      Serial.println(response);
    
      WiFiEspClient client;
      client.flush();
      if (client.connect(deviceIPBuffer, 80)) {
        String url = "GET ?" + response + " HTTP/1.1\r\n";
        url += "Host: " + String(deviceIPBuffer) + "\r\n";
        url += "Connection: close\r\n\r\n";
        client.print(url);
        client.flush();
        client.stop();
      }
    
    }
    
    void initWifi() {
      Serial1.begin(115200);
      Serial1.setTimeout(TIMEOUT);
      WiFi.init(&Serial1);
      WiFi.config(IPAddress(192, 168, 111, 100));
    }
    
    void connectToWifi(String wifi, String pass) {
    
      char wifichar[24];
      wifi.toCharArray(wifichar, wifi.length() + 1);
      char passchar[24];
      pass.toCharArray(passchar, pass.length() + 1);
    
      if (WiFi.status() == WL_NO_SHIELD) {
        while (true);
      }
    
      status = 0;
      while (status != WL_CONNECTED) {
        status = WiFi.begin(wifichar, passchar);
        if (status == 2) {
          break;
        }
      }
    
      if (status == 2) {//no such network
        if (unsuccesfullConnectionIndex < 2) {
          unsuccesfullConnectionIndex++;
          connectToWifi(wifi, pass);
        } else {
          unsuccesfullConnectionIndex = 0;
          Serial.println("połaczenie nieudane");
        }
      } else {
        unsuccesfullConnectionIndex = 0;
        printWifiStatus();
        server.begin();
    
      }
    }
    
    
    void printWifiStatus() {
      myAddrFinal = WiFi.localIP();
      sprintf(myIpString, "%d.%d.%d.%d", myAddrFinal[0], myAddrFinal[1], myAddrFinal[2], myAddrFinal[3]);
      Serial.println(myIpString);
    
    }

W stworzonym przykładzie wykorzystuję bibliotekę WiFiEsp.h zarówno do tworzenia AP oraz do podłączania się do sieci przez urządzenie SLAVE. Ważnym do podkreślenia jest fakt, że po wysłaniu przez MASTER requestu oczekuje on na zwrotkę z potwierdzeniem otrzymania polecenia. Czyli wysyłam polecenie do SLAVE, a ten po otrzymaniu danych wysyła do MASTER potwierdzenie otrzymania nowego polecenia w którym również można zawrzeć nowy stan danego przekaźnika, który można wyświetlić na ekranie LCD w domu.


Opublikowano: 5 lipca, 2020 przez Pan z Pogodna

Leave a Reply