[资料分享] 【零知ESP8266教程】进阶篇1 WIFI MESH 组网 示例

roc2   2019-12-7 14:04 楼主

前言:
基础篇章中,我们对零知ESP8266的本身的运用大部分局限在基础开发板上的应用,但是,其本身是一个WiFi模块,所以了解和运用它的WiFi功能属于我们的中阶储备。

之后篇章中,我们会穿插基础入门篇,因为各种模块的更新速度和硬件的支持库都在不断的修改适配和调整,相对的我们也会适应现实的要求更新和完善。请大家继续支持零知实验室!

1、引述:
MESH组网技术在IOT领域具有非常大的作用,应用非常广泛,主流的无线技术从最开始的Zigbee,到蓝牙,到这里的WIFI都实现了MESH组网技术。在这里使用零知开源平台演示wifi 组网的使用。
2、准备
①硬件
我们本次只要使用零知-ESP8266;
②软件
软件使用零知开发工具,自带示例:

33.png

3、方法步骤
(1)先在零知开发工具中打开HelloMesh示例,或者复制下面的代码到零知开发工具中:

/**********************************************************
*    文件: x.ino      by 零知实验室([url]www.lingzhilab.com[/url])
*    -^^- 零知开源,让电子制作变得更简单! -^^-
*    时间: 2019/05/28 12:22
*    说明: 
************************************************************/
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMesh.h>
#include <TypeConversionFunctions.h>
#include <assert.h>
  
const char exampleMeshName[] PROGMEM = "MeshNode_";
const char exampleWiFiPassword[] PROGMEM = "123456789";//ChangeThisWiFiPassword_TODO
  
unsigned int requestNumber = 0;
unsigned int responseNumber = 0;
  
String manageRequest(const String &request, ESP8266WiFiMesh &meshInstance);
transmission_status_t manageResponse(const String &response, ESP8266WiFiMesh &meshInstance);
void networkFilter(int numberOfNetworks, ESP8266WiFiMesh &meshInstance);
  
/* Create the mesh node object */
ESP8266WiFiMesh meshNode = ESP8266WiFiMesh(manageRequest, manageResponse, networkFilter, FPSTR(exampleWiFiPassword), FPSTR(exampleMeshName), "", true);
  
/**
   Callback for when other nodes send you a request
  
   @param request The request string received from another node in the mesh
   @param meshInstance The ESP8266WiFiMesh instance that called the function.
   @returns The string to send back to the other node
*/
String manageRequest(const String &request, ESP8266WiFiMesh &meshInstance) {
  // We do not store strings in flash (via F()) in this function.
  // The reason is that the other node will be waiting for our response,
  // so keeping the strings in RAM will give a (small) improvement in response time.
  // Of course, it is advised to adjust this approach based on RAM requirements.
  
  /* Print out received message */
  Serial.print("Request received: ");
  Serial.println(request);
  
  /* return a string to send back */
  return ("Hello world response #" + String(responseNumber++) + " from " + meshInstance.getMeshName() + meshInstance.getNodeID() + ".");
}
  
/**
   Callback for when you get a response from other nodes
  
   @param response The response string received from another node in the mesh
   @param meshInstance The ESP8266WiFiMesh instance that called the function.
   @returns The status code resulting from the response, as an int
*/
transmission_status_t manageResponse(const String &response, ESP8266WiFiMesh &meshInstance) {
  transmission_status_t statusCode = TS_TRANSMISSION_COMPLETE;
  
  /* Print out received message */
  Serial.print(F("Request sent: "));
  Serial.println(meshInstance.getMessage());
  Serial.print(F("Response received: "));
  Serial.println(response);
  
  // Our last request got a response, so time to create a new request.
  meshInstance.setMessage(String(F("Hello world request #")) + String(++requestNumber) + String(F(" from "))
                          + meshInstance.getMeshName() + meshInstance.getNodeID() + String(F(".")));
  
  // (void)meshInstance; // This is useful to remove a "unused parameter" compiler warning. Does nothing else.
  return statusCode;
}
  
/**
   Callback used to decide which networks to connect to once a WiFi scan has been completed.
  
   @param numberOfNetworks The number of networks found in the WiFi scan.
   @param meshInstance The ESP8266WiFiMesh instance that called the function.
*/
void networkFilter(int numberOfNetworks, ESP8266WiFiMesh &meshInstance) {
  for (int networkIndex = 0; networkIndex < numberOfNetworks; ++networkIndex) {
    String currentSSID = WiFi.SSID(networkIndex);
    int meshNameIndex = currentSSID.indexOf(meshInstance.getMeshName());
  
    /* Connect to any _suitable_ APs which contain meshInstance.getMeshName() */
    if (meshNameIndex >= 0) {
      uint64_t targetNodeID = stringToUint64(currentSSID.substring(meshNameIndex + meshInstance.getMeshName().length()));
  
      if (targetNodeID < stringToUint64(meshInstance.getNodeID())) {
        ESP8266WiFiMesh::connectionQueue.push_back(NetworkInfo(networkIndex));
      }
    }
  }
}
  
void setup() {
  // Prevents the flash memory from being worn out, see: [url]https://github.com/esp8266/Arduino/issues/1054[/url] .
  // This will however delay node WiFi start-up by about 700 ms. The delay is 900 ms if we otherwise would have stored the WiFi network we want to connect to.
  WiFi.persistent(false);
  
  Serial.begin(115200);
  delay(50); // Wait for Serial.
  
  //yield(); // Use this if you don't want to wait for Serial.
  
  // The WiFi.disconnect() ensures that the WiFi is working correctly. If this is not done before receiving WiFi connections,
  // those WiFi connections will take a long time to make or sometimes will not work at all.
  WiFi.disconnect();
  
  Serial.println();
  Serial.println();
  
  Serial.println(F("Note that this library can use static IP:s for the nodes to speed up connection times.\n"
                   "Use the setStaticIP method as shown in this example to enable this.\n"
                   "Ensure that nodes connecting to the same AP have distinct static IP:s.\n"
                   "Also, remember to change the default mesh network password!\n\n"));
  
  Serial.println(F("Setting up mesh node..."));
  
  /* Initialise the mesh node */
  meshNode.begin();
  meshNode.activateAP(); // Each AP requires a separate server port.
//  meshNode.setStaticIP(IPAddress(192, 168, 4, 22)); // Activate static IP mode to speed up connection times.
}
  
int32_t timeOfLastScan = -10000;
void loop() {
  if (millis() - timeOfLastScan > 3000 // Give other nodes some time to connect between data transfers.
      || (WiFi.status() != WL_CONNECTED && millis() - timeOfLastScan > 2000)) { // Scan for networks with two second intervals when not already connected.
    String request = String(F("Hello world request #")) + String(requestNumber) + String(F(" from ")) + meshNode.getMeshName() + meshNode.getNodeID() + String(F("."));
    meshNode.attemptTransmission(request, false);
    timeOfLastScan = millis();
  
    // One way to check how attemptTransmission worked out
    if (ESP8266WiFiMesh::latestTransmissionSuccessful()) {
      Serial.println(F("Transmission successful."));
    }
  
    // Another way to check how attemptTransmission worked out
    if (ESP8266WiFiMesh::latestTransmissionOutcomes.empty()) {
      Serial.println(F("No mesh AP found."));
    } else {
      for (TransmissionResult &transmissionResult : ESP8266WiFiMesh::latestTransmissionOutcomes) {
        if (transmissionResult.transmissionStatus == TS_TRANSMISSION_FAILED) {
          Serial.println(String(F("Transmission failed to mesh AP ")) + transmissionResult.SSID);
        } else if (transmissionResult.transmissionStatus == TS_CONNECTION_FAILED) {
          Serial.println(String(F("Connection failed to mesh AP ")) + transmissionResult.SSID);
        } else if (transmissionResult.transmissionStatus == TS_TRANSMISSION_COMPLETE) {
          // No need to do anything, transmission was successful.
        } else {
          Serial.println(String(F("Invalid transmission status for ")) + transmissionResult.SSID + String(F("!")));
          assert(F("Invalid transmission status returned from responseHandler!") && false);
        }
      }
    }
    Serial.println();
  } else {
    /* Accept any incoming connections */
    meshNode.acceptRequest();
  }
}

(2)验证并上传上述代码到零知-ESP8266开发板;
(3)测试:分别把上述代码上传到两个零知-ESP8266开发板,然后分别连接两个板子的串口调试窗口,然后就可以看到两个节点数据传输信息了:

34.jpg

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复