วันอาทิตย์ที่ 18 ตุลาคม พ.ศ. 2558

ESP8266 : UDP ภาคต่อกับรูปแบบ Multicast

 

จากตอนที่แล้วพบว่าการเชื่อมต่อระหว่างสองบอร์ดจะไม่สะดวกนัก เนื่องจากต้องรู้หมายเลข IP และต้องทำการ upload ทุกครั้งที่ IP เปลี่ยนแปลง

สำหรับระบบสื่อสารจะคุ้นชินกับคำว่า Broadcast และ Multicast ทั้งสองเป็นการสื่อสารแบบกลุ่ม

โดย Broadcast จะเหมือนกับการกระจายเสียงของวิทยุสาธารณะ ที่จะส่งข้อมูลออกแบบกระจาย ใครที่อยู่ใน subgroup เดียวกันกับผู่ส่ง ก็จะได้รับข้อมูลพร้อมกัน

ส่วน Multicast จะจัดกลุ่มแคบลงมาโดยการส่งข้อมูลแบบ multicast จะถูกกำหนดให้ส่งในช่วง IP Address ที่ 224.0.0.1 ไปถึง 239.255.255.255 ซึ่ง device ที่อยู่ในกลุ่มเดียวกันจะต้องมี Multicast IP เดียวกัน และใช้ Port ในการรับข้อมูลตัวเดียวกัย

สำหรับตัวอย่างจะใช้ Multicast IP ที่ 239.0.0.57  และรับส่งด้วย Port หมายเลข 5555

ส่วนของการทำโปรแกรม จะเริ่มใช้งาน UDP ด้วยการระบุ เพื่อเข้าร่วมกลุ่ม ตามนี้

IPAddress ipMulti(239,0,0,57);
int portMulti = 5555;

Udp.beginMulticast(WiFi.localIP(), ipMulti, portMulti);

WiFI.localIP() คือหมายเลข IP ที่ได้รับจาก WiFi router ซึ่งจะถูกส่งไปพร้อมกับข้อมูล ผู้รับสามารถตอบกลับข้อมูลมาที่หมายเลข IP นี้ ด้วยการอ้างอิงกับ Udp.remoteIP()

สำหรับการส่งข้อมูลไปที่กลุ่ม ให้ใช้

Udp.beginPacketMulticast(ipMulti, portMulti, WiFi.localIP());

* ตัวอย่างไม่ได้ทำการ Comment ในส่วนการตอบกลับไว้ เนื่องจากจะมีการสะท้อนไปมาหลายรอบ ถ้าใครต้องการทดสอบก็นำเอา Comment ออก

เมื่อข้อมูลถูกส่งออกไป อุปกรณ์ที่เป็นสมาชิกในกลุ่ม Multicast จะได้รับข้อมูลที่ส่งออกมาพร้อมกัน สามารถทดสอบได้ถ้ามีบอร์ดมากกว่าสองบอร์ด ก็จะเห็นผลของการส่ง Multicast ได้ชัดเจนขึ้น

ส่วนการนำไปใช้งานก็ตามอัธยาศัย

จากตอนที่แล้วและตอนนี้จะต้องอาศัย WiFi router สำหรับการแจกจ่ายหมายเลข IP ให้อุปกรณ์แต่ละตัว ในส่วนของบอร์ด ESP8266 สามารถทำเป็น Access point ได้ ตอนต่อไปจะตัดการใช้งานกับ WiFi router และใช้คุณสมบัติ Access point มาทำงานแทน

#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
WiFiUDP Udp;
char packetBuffer[512];
IPAddress ipMulti(239,0,0,57);
int portMulti = 5555;

void setup() {
  Serial.begin(115200);
  WiFi.begin("SSID","PASS");
  int dotCount = 0;
  while(WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
    if(++dotCount > 30){
      dotCount = 0;
      Serial.println();
    }
  }
  Serial.print("Connect to Wifi (");
  Serial.print(WiFi.localIP());
  Serial.println(")");
  Udp.beginMulticast(WiFi.localIP(), ipMulti, portMulti);
}

String sendText = "";

void loop() {
  int noBytes = Udp.parsePacket();
  if(noBytes){
    Udp.read(packetBuffer, noBytes);
    packetBuffer[noBytes] = '\0';
    Serial.print(millis() / 1000);
    Serial.print(" : ");
    Serial.print(packetBuffer);
    Serial.print(" (from : ");
    Serial.print(Udp.remoteIP());
    Serial.print(":");
    Serial.print(Udp.remotePort());
    Serial.println(" )");

    /* Remove comment out for feedback test
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.print(WiFi.localIP());
    Udp.print(" got info.");
    Udp.endPacket();
    */
  }

  while(Serial.available()){
    char ch = Serial.read();
    if(ch != '\n'){
      sendText += ch;
    }else{
      Serial.print(" info: ");
      Serial.print(sendText);
      Udp.beginPacketMulticast(ipMulti, portMulti, WiFi.localIP());
      Udp.print(sendText);
      Serial.print(" (Send status (0:error, 1:OK): ");
      Serial.print(Udp.endPacket());
      Serial.println(")");
      sendText = "";
    }
  }
}

ESP8266 : UDP กับความง่ายในการส่งข้อมูลผ่าน network

 

Protocol หลากหลายที่ใช้กันอยู่ในโลกของ network เป็นรูปแบบที่ถูกกำหนดขึ้นโดยองค์กรใดๆ ให้เราทำตามมาตรฐาน จึงจะสามารถรับส่งข่าวสารกับคนอื่นได้ เช่น http (HyperText Transfer Protocol) TCP/IP (Transmission Control Protocol/ Internet Protocol)

ในส่วนของ UDP (User Datagram Protocol) เป็นการส่งข้อมูลแบบหลวมๆ มีรูปแบบที่ไม่เข้มงวดนัก การส่งข้อมูลเป็นการส่งที่ไม่สนใจว่าทางด้านรับจะได้รับหรือไม่ ไม่สนใจว่าข้อมูลที่ส่งไปถึงปลายทางครบถ้วนหรือไม่ ทำให้การส่งของมูลรวดเร็ว

UDP เหมาะกับการส่งข้อมูลแบบ streaming เช่น สัญญาณภาพ สัญญาณเสียง ที่ถึงแม้ว่าข้อมูลไม่ครบถ้วนก็ยังสามารถเห็นภาพ หรือได้ยินเสียง

ข้อดีอีกอย่างคือ ทำโปรแกรมเชื่อมต่อได้อย่างรวดเร็ว เปรียบกับการส่งข้อมูลด้วย RS232

เพื่อให้สามารถสื่อสารกันได้เข้าใจ อาจต้องสร้างจำเป็นต้องสร้างโปรโตคอลขึ้นเอง ตามชื่อของมัน

ตัวอย่างต่อไปจะเป็นการทดลองเขียนโปรแกรมใช้งานเบื้องต้นกับ ESP8266 ซึ่งน่าจะประยุกต์ใช้งานกับบอร์ด WiFi หรือ Ethernet แบบอื่นได้

ใช้ Arduino ESP (1.6.5) ในการทดสอบ สำหรับตัวอย่างแรกจะให้บอร์ดสองบอร์ดคุยกันผ่าน Serial monitor ของ IDE

#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
WiFiUDP Udp;
char packetBuffer[512];

void setup() {
  Serial.begin(115200);


  WiFi.begin("SSID","PASS");


  int dotCount = 0;
  while(WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
    if(++dotCount > 30){
      dotCount = 0;
      Serial.println();
    }
  }
  Serial.print("Connect to Wifi (");
  Serial.print(WiFi.localIP());
  Serial.println(")");
  Udp.begin(5555);
}

String sendText = "";

void loop() {
  int noBytes = Udp.parsePacket();
  if(noBytes){
    Udp.read(packetBuffer, noBytes);
    packetBuffer[noBytes] = '\0';
    Serial.print(millis() / 1000);
    Serial.print(" : ");
    Serial.println(packetBuffer);
  }

  while(Serial.available()){
    char ch = Serial.read();
    if(ch != '\n'){
      sendText += ch;
    }else{
      Serial.println(sendText);


      IPAddress ipDest(192,168,1,41);


      Udp.beginPacket(ipDest, 5555);
      Udp.print(sendText);
      Serial.print("Send status: "); Serial.println(Udp.endPacket());
      sendText = "";
    }
  }
}

ส้วนที่ทำตัวหนาไว้ต้องจัดการตามนี้

SSID กับ PASS เป็นของ Wifi Router ที่บอร์ดทั้งสองต่อเชื่อม

เมื่อเชื่อมต่อได้ จะได้รับ IP Address แนะนำให้เปิด Serial monitor ของ IDE เพื่อดูผลของการเชื่อมต่อ

เนื่องจากต้องทำการเชื่อมต่อบอร์ด 2 บอร์ด เมื่อรันครั้งแรก และได้ IP Address แล้ว ให้นำ IP Address ของบอร์ดอีกฝั่งมาใส่ที่ ipDest แล้วทำการ upload อีกที

ให้คงเปิด Serial monitor ไว้ พิมพ์ข้อความในช่อง แล้วกดปุ่ม Send ข้อความจะไปปรากฏที่อีกฝั่งหนึ่งทันที เมื่อรับข้อความแล้วจะนำไปใช้งาน ปิด เปิด หลอด LED หรืออะไรก็ว่าตามถนัด ด้วยการตีความข้อความที่ส่งไป

จะเห็นว่า มันไม่สะดวกนัก ถ้าจะต้องรู้ว่าอีกฝั่งมี IP Address อะไร ก่อนการเชื่อมต่อ สิ่งนี้มีการคิดไว้เรียบร้อยแล้ว และมีทางออกให้เราสามารถใช้งาน UDP ได้ง่ายขึ้น

ติดตามตอนต่อไป ในการเรียนรู้ UDP แบบ multicast และขั้นกว่าในการเชื่อมต่อบอร์ด โดยไม่ต้องมี WiFi router