วันพุธที่ 3 กุมภาพันธ์ พ.ศ. 2559

nRF24L01 : Mesh Network

  รูปแบบการจัดโครงข่ายลักษณะ Tree Topology

  มองอย่างผิวเผินสำหรับโมดูล nRF24L01 หลายคนอาจเห็นว่าเป็นเพียงโมดูลสื่อสารไร้สายใช้เพื่อส่งข้อมูลจากจุดหนึ่งไปอีกจุดหนึ่งเท่านั้น

  จริงๆแล้วตัวโมดูลเองมีความสามารถในการเชื่อมโยงกันเป็นกลุ่มได้ โดยสูงสุดอยู่ที่ 6 โมดูลในแต่ละกลุ่ม โดยแต่ละโมดูลจะมีหมายเลขประจำตัวเป็น 00 ถึง 05

  ดูเหมือนจำนวนโมดูลจะเป็นข้อจำกัดของการใช้งาน แต่จริงแล้วได้มีการเขียนไลบรารี่เพื่อขยายจำนวนโมดูลให้เพิ่มขึ้นได้ เป็นลักษณะรูปแบบกิ่งของต้นไม้ (Tree Topology)

  การแตกกิ่งจะเริ่มจากโมดูลแรก (โมดูล 00) จะมีกิ่งที่เชื่อมโยงได้คือ 01, 02, 03, 04 และ 05 จากนั้นในแต่ละกิ่งก็จะสามารถแตกกิ่งออกไปได้อีก 5 กิ่ง ตัวอย่างกิ่งที่ 04 ก็จะมีกิ่งที่แตกออกได้เป็น 014, 024, 034, 044, 054 และกิ่งที่ 05 ก็จะได้กิ่ง 015, 025, 035, 045, 055

  สำหรับการส่งข้อมูล กิ่งย่อยจะสามารถรับส่งข้อมูลได้เฉพาะกับกิ่งหลัก (parent) และกิ่งย่อยอื่นที่แตกออกจากตัวเอง (child) จะรับส่งข้อมูลข้ามกิ่งหลักไม่ได้ การจะรับส่งข้อมูลไปยังกิ่งย่อยอื่น จะอาศัยการฝากข้อมูลส่งไปที่กิ่งหลัก กิ่งหลักจะส่งไปที่กิ่งหลักถัดไปและกิ่งย่อยอื่น กิ่งแกนจะส่งข้อมูลผ่านไปยังกิ่งหลักของกิ่งย่อยที่เราต้องการส่งข้อมูล สมมุติว่ากิ่งย่อย 014 ต้องการส่งข้อมูลให้กิ่งย่อย 035 การส่งข้อมูลจะเป็นดังนี้

  014 -> 04 -> 00 -> 05 -> 035

  โดยที่ข้อมูลที่ส่งไปจะมีส่วนหัว (Header) ที่บอกว่ากิ่งไหนเป็นตัวส่ง และต้องการส่งให้กิ่งไหน ทำให้เมื่อกิ่งย่อยได้รับข้อมูลแล้วต้องการส่งข้อมูลกลับก็จะทราบว่าจะส่งกลับไปให้กิ่งไหน เส้นทางจะเป็นดังนี้

035 -> 05 -> 00 -> 04 -> 014

  ลักษณะการขยายกิ่งโมดูล (คลิ๊กทีรูปเพื่อขยายขนาด)

  Topology


  จำนวนกิ่งทั้งหมดที่สามารถสร้างได้จากโครงช่าย 6 ชั้น  1 + 5 + 25 + 125 + 625 + 3,125 = 3,906 กิ่ง ซึ่งเป็นจำนวนมากทีเดียวในทางทฤษฎี แต่ในทางปฏิบัติแล้วข้อจำกัดอาจเกิดจากสิ่งอื่นๆ ทำให้จำนวนที่ใช้งานจริงอาจน้อยกว่า


นำไปใช้งาน

  Mesh network มีประโยชน์ในการขยายโครงข่ายที่ต้องการลูกข่ายจำนวนมาก โดยที่ตัวลูกข่ายเองสามารถทำตัวเป็นแม่ข่ายได้ในขณะเดียวกัน ดูได้จากการวางโครงข่ายข้างต้น ข้อมูลจะวิ่งไปกลับผ่านแต่ละกิ่งไปยังฐาน (์Node 00) และยังสามารถส่งข้อมูลไปยังลูกข่ายตัวอื่นๆได้ด้วย
  การนำไปใช้งานโดยส่วนใหญ่ใช้เพื่ออ่านข้อมูลของเซนเซอร์ เพื่อนำค่ามาแสดงหรือประมวลผลที่ส่วนกลาง โดยผ่านคำสั่งไปที่โหนดฐาน จากนั้นคำสั่งจะถูกกระจายไปจนถึงปลายทาง และลูกข่ายปลายทางจึงทำการส่งข้อมูลกลับไปยังโหนดฐาน ไม่เพียงแต่จะตอบสนองต่อคำสั่ง แต่ละโหนดลูกยังสามารถส่งข้อมูลไปที่โหนดฐานตามคาบเวลาที่กำหนด ลักษณะการส่งข้อมูลตามคาบเวลา อาจก่อให้เกิดการชนกันของข้อมูลได้กับโครงข่ายที่มีสมาชิกมากๆ ซึ่งอาจแก้ไขด้วยการจัดคาบเวลาในการส่งข้อมูลแบบซุ่ม
  ข้อดีของการสร้างโครงข่ายลักษณะนี้คือ การที่แต่ละโหนดไม่จำเป็นต้องมีกำลังส่งสูง การเชื่อมโยงจะอาศัยการส่งกันเป็นทอดๆไป


Arduino ไลบรารี่ 


 

วันอาทิตย์ที่ 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 = "";
    }
  }
}