【物聯網系統開發】運用 ARDUINO 乙太網路擴充板建立簡單網頁伺服器

【物聯網系統開發】運用 ARDUINO 乙太網路擴充板建立簡單網頁伺服器

本篇為『物聯網系統開發系列』之運用 ARDUINO 乙太網路擴充板建立簡單網頁伺服器,筆者建立這個新專欄,主要是未來物聯網時代推瀾下,希望能夠透過文章,來推廣筆者在物聯網開發的實務經驗與技術分享

文\曹永忠、吳佳駿、許智誠、蔡英德

(曹永忠, 吳佳駿, 許智誠, & 蔡英德, 2017a, 2017b, 2017c; 曹永忠, 許智誠, & 蔡英德, 2015a, 2015b, 2015c, 2015d, 2015e),所以第二篇文章就要介紹 Arduino 開發板累加上乙太網路擴充板(Ethernet Shield),讓創客神器Arduino開發板可以連上網際網路(曹永忠, 許智誠, & 蔡英德, 2015f),可以成為物聯網開發中最簡單使用的開發版。

本系列希望貢獻筆者一些經驗,讓非資訊、電機、電子等 Makers 可以學到在物聯網開發中,一些程式開發的技巧、原理、法則與穩固的技術,因本系列文章主要讀者為初學者,內容程度為基礎入門程度,深入之處不足,但請高手們給筆者賜教,也請讀者關注本系列。

Arduino Ethernet Shield 簡介

W5100 主要特色是把 TCP/IP Protocols (TCP, UDP, ICMP, IPv4 ARP, IGMP, PPPoE, Ethernet) 做在硬體電路上,減輕了單晶片(MCU)的負擔 (也就是 Arduino 開發板的負擔)(曹永忠 et al., 2015b, 2015c)。Arduino 程式只要使用 Ethernet Library1 便可以輕易完成連至網際網路的動作,不過 W5100 也不是沒有缺點,因為它有一個限制,就是最多只允許同時4 個 socket 連線。

1.可到 Arduino.cc 的官網:http://www.arduino.cc/en/reference/ethernet,下載函式庫與相關範例。

Arduino Ethernet Shield 使用加長型的 Pin header (如圖 1.(a) & 圖 1.(b)),可以直接插到 Arduino 控制板上 (如圖 1.(c) & 圖 1.(d) & 圖 1.(e)),而且原封不動地保留了 Arduino 控制板的 Pin Layout,讓使用者可以在它上面疊其它的擴充板(如圖 1.(c) & 圖 1.(d) & 圖 1.(e))。比較新的 Ethernet Shield 增加了 micro-SD card 插槽(如圖 1.(a)),可以用來儲存檔案,你可以用 Arduino 內建的 SD library 來存取板子上的 SD cardEthernet Shield 相容於 UNO 和 Mega 2560 控制板。

【物聯網系統開發】運用 ARDUINO 乙太網路擴充板建立簡單網頁伺服器
▲圖1 Ethernet Shield (W5100)

Arduino 開發板跟 W5100 以及 SD card 之間的通訊都是透過 SPI bus (通過 ICSP header)。以 UNO開發板 而言,SPI bus 腳位位於 pins 11, 12 和 13,而 Mega 2560開發板 則是 pins 50, 51 和 52。UNO 和 Mega 2560 都一樣,pin 10 是用來選擇 W5100,而 pin 4 則是用來選擇 SD card。這邊提到的這幾支腳位都不能拿來當 GPIO 使用,請讀者勿必避開這兩個 GPIO 腳位。

另外,在 Arduino Mega 2560 開發板上,pin 53 是 hardware SS pin,這支腳位也必須保持為 OUTPUT,不然 SPI bus 就不能動作。在使用的時候要注意一件事,因為 W5100 和 SD card 共享 SPI bus,所以在同一個時間只能使用其中一個設備。如果你程式裏會用到 W5100 和 SD card 兩種設備,那在使用對應的 library 時就要特別留意,要避免搶 SPI bus 資源的情形。假如你確定不會用到其中一個設備的話,你可以在程式裏明白地指示 Arduino開發板,方法是: 如果不會用到 SD card,那就把 pin 4 設置成 OUTPUT 並把狀態改為 high,如果不會用到 W5100,那麼便把 pin 10 設置成 OUTPUT 並把狀態改為 high。

如圖 2所示,Ethernet Shield 狀態指示燈 (LEDs)功能列舉如下:

  • PWR: 表示 Arduino 控制板和 Ethernet Shield 已經上電
    LINK: 網路指示燈,當燈號閃爍時代表正在傳送或接收資料
    FULLD: 代表網路連線是全雙工
    100M: 表示網路是 100 MB/s (相對於 10 Mb/s)
    RX: 接收資料時閃爍
    TX: 傳送資料時閃爍
    COLL: 閃爍時代表網路上發生封包碰撞的情形 (network collisions are detected)
    資料來源:http://www.arduino.cc/en/Main/ArduinoEthernetShield

【物聯網系統開發】運用 ARDUINO 乙太網路擴充板建立簡單網頁伺服器

▲圖2 W5100指示燈

簡單 Web Server

首先,組立 W5100 以太網路模組是非常容易的一件事,如下圖所示,只要將 W5100 以太網路模組堆疊到任何 Arduino 開發板之上就可以了。

【物聯網系統開發】運用 ARDUINO 乙太網路擴充板建立簡單網頁伺服器
▲圖3 將 Arduino 開發板與 W5100 以太網路模組堆疊組立

之後,在將組立好的 W5100 以太網路模組,如下圖所示,只要將USB線差到 Arduino 開發板,再將 RJ 45的網路線一端插到 W5100 以太網路模組,另一端插到可以上網的集線器(Switch HUB)的任何一個區域網路接口(Lan Port)就可以了。

【物聯網系統開發】運用 ARDUINO 乙太網路擴充板建立簡單網頁伺服器
▲圖4 接上電源與網路線的 W5100 以太網路模組堆疊卡

我們遵照前幾章所述,將 Arduino 開發板的驅動程式安裝好之後,我們打開 Arduino 開發板的開發工具:Sketch IDE 整合開發軟體,攥寫一段程式,如下表所示之 WebServer 測試程式,我們就可以讓 W5100 以太網路模組堆疊卡變成一台簡易的網頁伺服器運作了。

W5100 以太網路模組(WebServer)

/*

  Web Server

 

 A simple web server that shows the value of the analog input pins.

 using an Arduino Wiznet Ethernet shield.

 

 Circuit:

 * Ethernet shield attached to pins 10, 11, 12, 13

 * Analog inputs attached to pins A0 through A5 (optional)

 

 created 18 Dec 2009

 by David A. Mellis

 modified 9 Apr 2012

 by Tom Igoe

 

 */

 

#include <SPI.h>

#include <Ethernet.h>

 

// Enter a MAC address and IP address for your controller below.

// The IP address will be dependent on your local network:

byte mac[] = {

  0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF

};

IPAddress ip(192, 168, 30, 200);

IPAddress dnServer(168, 95, 1, 1);

// the router's gateway address:

IPAddress gateway(192, 168, 30, 254);

// the subnet:

IPAddress subnet(255, 255, 255, 0);

 

// Initialize the Ethernet server library

// with the IP address and port you want to use

// (port 80 is default for HTTP):

EthernetServer server(80);

 

void setup() {

  // Open serial communications and wait for port to open:

  Serial.begin(9600);

  while (!Serial) {

    ; // wait for serial port to connect. Needed for Leonardo only

  }

 

 

  // start the Ethernet connection and the server:

  Ethernet.begin(mac, ip, dnServer, gateway, subnet);

  server.begin();

  Serial.print("server is at ");

  Serial.println(Ethernet.localIP());

}

 

 

void loop() {

  // listen for incoming clients

  EthernetClient client = server.available();

  if (client) {

    Serial.println("new client");

    // an http request ends with a blank line

    boolean currentLineIsBlank = true;

    while (client.connected()) {

      if (client.available()) {

        char c = client.read();

        Serial.write(c);

        // if you've gotten to the end of the line (received a newline

        // character) and the line is blank, the http request has ended,

        // so you can send a reply

        if (c == '\n' && currentLineIsBlank) {

          // send a standard http response header

          client.println("HTTP/1.1 200 OK");

          client.println("Content-Type: text/html");

          client.println("Connection: close");  // the connection will be closed after completion of the response

          client.println("Refresh: 5");  // refresh the page automatically every 5 sec

          client.println();

          client.println("<!DOCTYPE HTML>");

          client.println("<html>");

          // output the value of each analog input pin

          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {

            int sensorReading = analogRead(analogChannel);

            client.print("analog input ");

            client.print(analogChannel);

            client.print(" is ");

            client.print(sensorReading);

            client.println("<br />");

          }

          client.println("</html>");

          break;

        }

        if (c == '\n') {

          // you're starting a new line

          currentLineIsBlank = true;

        }

        else if (c != '\r') {

          // you've gotten a character on the current line

          currentLineIsBlank = false;

        }

      }

    }

    // give the web browser time to receive the data

    delay(1);

    // close the connection:

    client.stop();

    Serial.println("client disconnected");

  }

}

程式範例原始碼網址:https://github.com/brucetsao/arduino_RFProgramming

如下圖所示,讀者可以看到本次實驗- WebServer 測試程式結果畫面。

【物聯網系統開發】運用 ARDUINO 乙太網路擴充板建立簡單網頁伺服器

▲圖5 WebServer 測試程式結果畫面

下一頁還有更精采的教學喔 !

曹永忠
作者

曹永忠,國立中央大學資訊管理學系博士,目前在暨南大學電機工程學系兼任助理教授與自由作家,專注於軟體工程、軟體開發與設計、物件導向程式設計......並持續發表作相關專業著作。

使用 Facebook 留言
發表回應
謹慎發言,尊重彼此。按此展開留言規則