本系列希望貢獻筆者一些經驗,讓非資訊、電機、電子等 Makers 可以學到在物聯網開發中,一些程式開發的技巧、原理、法則與穩固的技術,因本系列文章主要讀者為初學者,內容程度為基礎入門程度,深入之處不足,但請高手們給筆者賜教,也請讀者關注本系列。<p>&nbsp;</p>
<p>文\曹永忠、吳佳駿、許智誠、蔡英德</p>
<p>本篇承接上篇『【物聯網系統開發】運用 ARDUINO 乙太網路擴充板建立簡單網頁伺服器』文章(曹永忠, 吳佳駿, 許智誠, &amp; 蔡英德, 2017),進而運用 ARDUINO 乙太網路擴充板建立網際網路通訊能力,並且可以運用通訊能力,建立 Telnet 用戶端程式、簡易型文字瀏覽器等工具程式的撰寫,讓創客神器 Arduino 開發板(曹永忠, 許智誠, &amp; 蔡英德, 2015c)可以成為物聯網開發,具有 TCP/IP 之擷取通訊內容能力之最方便使用的開發版。</p>
<h3>Telnet 用戶端程式</h3>
<p>首先,組立 W5100 以太網路模組是非常容易的一件事,如下圖所示,只要將 W5100 &nbsp;以太網路模組堆疊到任何 Arduino 開發板之上就可以了。</p>
<p style="text-align: center;"><img src="https://cdn1-techbang.pixfs.net/system/images/400600/original/ebf52a24bd80469daf0e60a9a2248fa5.jpeg?1498113435" alt="" /><br />圖1. 將 Arduino 開發板與 W5100 以太網路模組堆疊組立</p>
<p style="text-align: left;">之後,在將組立好的 W5100 以太網路模組,如下圖所示,只要將 USB 線差到 Arduino 開發板,再將 RJ 45的網路線一端插到 W5100 以太網路模組,另一端插到可以上網的集線器(Switch HUB)的任何一個區域網路接口(Lan Port)就可以了。</p>
<p style="text-align: center;"><img src="https://cdn2-techbang.pixfs.net/system/images/400601/original/53ee66a2d4ef5ef9dfff1d0e2d88b2af.jpeg?1498113435" alt="" /><br />圖2. 接上電源與網路線的 W5100 以太網路模組堆疊卡</p>
<p style="text-align: left;">所以我們如果將具有 TCP/IP 通訊能力的 Arduino 開發板,用於使用 Telnet 通訊能力,在物聯網的網路通訊中,就有機會可以用於更廣泛的工業通訊能力,那無異讓創客神器 Arduino 開發板(曹永忠 et al., 2015c)可以成為物聯網開發中,具有TCP/IP通訊內容能力之強大利器,所以我們先撰寫一個簡單的Telnet 用用戶端系統來驗證這個能力。我們為了讓W5100 以太網路模組堆疊卡變成一台具有 TCP/IP 通訊能力的機器(曹永忠, 許智誠, &amp; 蔡英德, 2015a, 2015b),我們將 Arduino 開發板的驅動程式安裝好之後,我們打開 Arduino 開發板的開發工具:Sketch IDE 整合開發軟體,攥寫一段程式,如下表所示之 Telnet 用戶端程式測試程式。</p>
<h3 style="text-align: left;">表1. Telnet 用戶端程式測試程式</h3>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="558">
<p class="a">Telnet 用戶端程式測試程式(TelnetClient)</p>
</td>
</tr>
<tr>
<td width="558" valign="top">
<p class="a">/*</p>
<p class="a">&nbsp; Telnet client</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp;This sketch connects to a a telnet server (http://www.google.com)</p>
<p class="a">&nbsp;using an Arduino Wiznet Ethernet shield.&nbsp; You'll need a telnet server</p>
<p class="a">&nbsp;to test this with.</p>
<p class="a">&nbsp;Processing's ChatServer example (part of the network library) works well,</p>
<p class="a">&nbsp;running on port 10002. It can be found as part of the examples</p>
<p class="a">&nbsp;in the Processing application, available at</p>
<p class="a">&nbsp;http://processing.org/</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp;Circuit:</p>
<p class="a">&nbsp;* Ethernet shield attached to pins 10, 11, 12, 13</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp;created 14 Sep 2010</p>
<p class="a">&nbsp;modified 9 Apr 2012</p>
<p class="a">&nbsp;by Tom Igoe</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp;*/</p>
<p class="a">&nbsp;</p>
<p class="a">#include &lt;SPI.h&gt;</p>
<p class="a">#include &lt;Ethernet.h&gt;</p>
<p class="a">&nbsp;</p>
<p class="a">// Enter a MAC address and IP address for your controller below.</p>
<p class="a">// The IP address will be dependent on your local network:</p>
<p class="a">byte mac[] = {</p>
<p class="a">&nbsp; 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF</p>
<p class="a">};</p>
<p class="a">IPAddress ip(192, 168, 30, 200);</p>
<p class="a">IPAddress dnServer(168, 95, 1, 1);</p>
<p class="a">// the router's gateway address:</p>
<p class="a">IPAddress gateway(192, 168, 30, 254);</p>
<p class="a">// the subnet:</p>
<p class="a">IPAddress subnet(255, 255, 255, 0);</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp;</p>
<p class="a">// Enter the IP address of the server you're connecting to:</p>
<p class="a">IPAddress server(140, 112, 172, 11);</p>
<p class="a">&nbsp;</p>
<p class="a">// Initialize the Ethernet client library</p>
<p class="a">// with the IP address and port of the server</p>
<p class="a">// that you want to connect to (port 23 is default for telnet;</p>
<p class="a">// if you're using Processing's ChatServer, use&nbsp; port 10002):</p>
<p class="a">EthernetClient client;</p>
<p class="a">&nbsp;</p>
<p class="a">void setup() {</p>
<p class="a">&nbsp; // start the Ethernet connection:</p>
<p class="a">&nbsp; Ethernet.begin(mac, ip, dnServer, gateway, subnet);</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp; // Open serial communications and wait for port to open:</p>
<p class="a">&nbsp; Serial.begin(9600);</p>
<p class="a">&nbsp; while (!Serial) {</p>
<p class="a">&nbsp;&nbsp;&nbsp; ; // wait for serial port to connect. Needed for Leonardo only</p>
<p class="a">&nbsp; }</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp; // give the Ethernet shield a second to initialize:</p>
<p class="a">&nbsp; delay(1000);</p>
<p class="a">&nbsp; Serial.println("connecting...");</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp; // if you get a connection, report back via serial:</p>
<p class="a">&nbsp; if (client.connect(server, 23)) {</p>
<p class="a">&nbsp;&nbsp;&nbsp; Serial.println("connected");</p>
<p class="a">&nbsp; }</p>
<p class="a">&nbsp; else {</p>
<p class="a">&nbsp;&nbsp;&nbsp; // if you didn't get a connection to the server:</p>
<p class="a">&nbsp;&nbsp;&nbsp; Serial.println("connection failed");</p>
<p class="a">&nbsp; }</p>
<p class="a">}</p>
<p class="a">&nbsp;</p>
<p class="a">void loop()</p>
<p class="a">{</p>
<p class="a">&nbsp; // if there are incoming bytes available</p>
<p class="a">&nbsp; // from the server, read them and print them:</p>
<p class="a">&nbsp; if (client.available()) {</p>
<p class="a">&nbsp;&nbsp;&nbsp; char c = client.read();</p>
<p class="a">&nbsp;&nbsp;&nbsp; Serial.print(c);</p>
<p class="a">&nbsp; }</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp; // as long as there are bytes in the serial queue,</p>
<p class="a">&nbsp; // read them and send them out the socket if it's open:</p>
<p class="a">&nbsp; while (Serial.available() &gt; 0) {</p>
<p class="a">&nbsp;&nbsp;&nbsp; char inChar = Serial.read();</p>
<p class="a">&nbsp;&nbsp;&nbsp; if (client.connected()) {</p>
<p class="a">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; client.print(inChar);</p>
<p class="a">&nbsp;&nbsp;&nbsp; }</p>
<p class="a">&nbsp; }</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp; // if the server's disconnected, stop the client:</p>
<p class="a">&nbsp; if (!client.connected()) {</p>
<p class="a">&nbsp;&nbsp;&nbsp; Serial.println();</p>
<p class="a">&nbsp;&nbsp;&nbsp; Serial.println("disconnecting.");</p>
<p class="a">&nbsp;&nbsp;&nbsp; client.stop();</p>
<p class="a">&nbsp;&nbsp;&nbsp; // do nothing:</p>
<p class="a">&nbsp;&nbsp;&nbsp; while (true);</p>
<p class="a">&nbsp; }</p>
<p class="a">}</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp;</p>
</td>
</tr>
</tbody>
</table>
<p>程式碼:<a href="https://github.com/brucetsao/arduino_RFProgramming">https://github.com/brucetsao/arduino_RFProgramming</a></p>
<p>如下圖所示,讀者可以看到本次實驗- Telnet 用戶端程式測試程式結果畫面。</p>
<p style="text-align: center;"><img src="https://cdn0-techbang.pixfs.net/system/images/400602/original/86d5cc7ada6bd2d3c4c03a84d70df298.jpeg?1498113436" alt="" /><br />圖3. Telnet 用戶端程式測試程式結果畫面</p>
<h3 style="text-align: left;">文字型 Browser 用戶端程式</h3>
<p>如果我們就可以讓 Arduino 開發板累加上 W5100 以太網路模組堆疊卡,讓創客神器 Arduino 開發板(曹永忠 et al., 2015c)成為具有 TCP/IP 通訊能力的 Arduino 開發板,而且在物聯網的網路通訊中,使用 TCP/IP 的通訊能力,來擷取網頁 HTML 的內容,那將會是無比強大的先進功能。所以我們將 Arduino 開發板的驅動程式安裝好之後,我們打開 Arduino 開發板的開發工具:Sketch IDE 整合開發軟體,攥寫一段程式,如下表所示之文字型 Browser 用戶端程式,來驗證這個能力。</p>
<h3>表2. 文字型 Browser 用戶端程式</h3>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="558">
<p class="a">文字型Browser用戶端程式(WebClient)</p>
</td>
</tr>
<tr>
<td width="558" valign="top">
<p class="a">/*</p>
<p class="a">&nbsp; Web client</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp;This sketch connects to a website (http://www.google.com)</p>
<p class="a">&nbsp;using an Arduino Wiznet Ethernet shield.</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp;Circuit:</p>
<p class="a">&nbsp;* Ethernet shield attached to pins 10, 11, 12, 13</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp;created 18 Dec 2009</p>
<p class="a">&nbsp;by David A. Mellis</p>
<p class="a">&nbsp;modified 9 Apr 2012</p>
<p class="a">&nbsp;by Tom Igoe, based on work by Adrian McEwen</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp;*/</p>
<p class="a">&nbsp;</p>
<p class="a">#include &lt;SPI.h&gt;</p>
<p class="a">#include &lt;Ethernet.h&gt;</p>
<p class="a">&nbsp;</p>
<p class="a">// Enter a MAC address for your controller below.</p>
<p class="a">// Newer Ethernet shields have a MAC address printed on a sticker on the shield</p>
<p class="a">byte mac[] = {</p>
<p class="a">&nbsp; 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF</p>
<p class="a">};</p>
<p class="a">IPAddress ip(192, 168, 30, 200);</p>
<p class="a">IPAddress dnServer(168, 95, 1, 1);</p>
<p class="a">// the router's gateway address:</p>
<p class="a">IPAddress gateway(192, 168, 30, 254);</p>
<p class="a">// the subnet:</p>
<p class="a">IPAddress subnet(255, 255, 255, 0);</p>
<p class="a">&nbsp;</p>
<p class="a">// if you don't want to use DNS (and reduce your sketch size)</p>
<p class="a">// use the numeric IP instead of the name for the server:</p>
<p class="a">//IPAddress server(74,125,232,128);&nbsp; // numeric IP for Google (no DNS)</p>
<p class="a">char server[] = "www.google.com";&nbsp;&nbsp;&nbsp; // name address for Google (using DNS)</p>
<p class="a">&nbsp;</p>
<p class="a">// Initialize the Ethernet client library</p>
<p class="a">// with the IP address and port of the server</p>
<p class="a">// that you want to connect to (port 80 is default for HTTP):</p>
<p class="a">EthernetClient client;</p>
<p class="a">&nbsp;</p>
<p class="a">void setup() {</p>
<p class="a">&nbsp; // Open serial communications and wait for port to open:</p>
<p class="a">&nbsp; Serial.begin(9600);</p>
<p class="a">&nbsp; while (!Serial) {</p>
<p class="a">&nbsp;&nbsp;&nbsp; ; // wait for serial port to connect. Needed for Leonardo only</p>
<p class="a">&nbsp; }</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp; // start the Ethernet connection:</p>
<p class="a">&nbsp; if (Ethernet.begin(mac) == 0) {</p>
<p class="a">&nbsp;&nbsp;&nbsp; Serial.println("Failed to configure Ethernet using DHCP");</p>
<p class="a">&nbsp;&nbsp;&nbsp; // no point in carrying on, so do nothing forevermore:</p>
<p class="a">&nbsp;&nbsp;&nbsp; // try to congifure using IP address instead of DHCP:</p>
<p class="a">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ethernet.begin(mac, ip, dnServer, gateway, subnet);</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp; }</p>
<p class="a">&nbsp; // give the Ethernet shield a second to initialize:</p>
<p class="a">&nbsp; delay(1000);</p>
<p class="a">&nbsp; Serial.println("connecting...");</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp; // if you get a connection, report back via serial:</p>
<p class="a">&nbsp; if (client.connect(server, 80)) {</p>
<p class="a">&nbsp;&nbsp;&nbsp; Serial.println("connected");</p>
<p class="a">&nbsp;&nbsp;&nbsp; // Make a HTTP request:</p>
<p class="a">&nbsp;&nbsp;&nbsp; client.println("GET /search?q=arduino HTTP/1.1");</p>
<p class="a">&nbsp;&nbsp;&nbsp; client.println("Host: www.google.com");</p>
<p class="a">&nbsp;&nbsp;&nbsp; client.println("Connection: close");</p>
<p class="a">&nbsp;&nbsp;&nbsp; client.println();</p>
<p class="a">&nbsp; }</p>
<p class="a">&nbsp; else {</p>
<p class="a">&nbsp;&nbsp;&nbsp; // kf you didn't get a connection to the server:</p>
<p class="a">&nbsp;&nbsp;&nbsp; Serial.println("connection failed");</p>
<p class="a">&nbsp; }</p>
<p class="a">}</p>
<p class="a">&nbsp;</p>
<p class="a">void loop()</p>
<p class="a">{</p>
<p class="a">&nbsp; // if there are incoming bytes available</p>
<p class="a">&nbsp; // from the server, read them and print them:</p>
<p class="a">&nbsp; if (client.available()) {</p>
<p class="a">&nbsp;&nbsp;&nbsp; char c = client.read();</p>
<p class="a">&nbsp;&nbsp;&nbsp; Serial.print(c);</p>
<p class="a">&nbsp; }</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp; // if the server's disconnected, stop the client:</p>
<p class="a">&nbsp; if (!client.connected()) {</p>
<p class="a">&nbsp;&nbsp;&nbsp; Serial.println();</p>
<p class="a">&nbsp;&nbsp;&nbsp; Serial.println("disconnecting.");</p>
<p class="a">&nbsp;&nbsp;&nbsp; client.stop();</p>
<p class="a">&nbsp;</p>
<p class="a">&nbsp;&nbsp;&nbsp; // do nothing forevermore:</p>
<p class="a">&nbsp;&nbsp;&nbsp; while (true);</p>
<p class="a">&nbsp; }</p>
<p class="a">}</p>
</td>
</tr>
</tbody>
</table>
<p>程式碼:<a href="https://github.com/brucetsao/arduino_RFProgramming">https://github.com/brucetsao/arduino_RFProgramming</a></p>
<p>如下圖所示,讀者可以看到本次實驗- 文字型 Browser 用戶端程式結果畫面。</p>
<p style="text-align: center;"><img src="https://cdn2-techbang.pixfs.net/system/images/400603/original/d2a9e3616004b834e2720936f48185c5.jpeg?1498113436" alt="" /><br />圖4. 文字型 Browser 用戶端程式結果畫面</p>
<h3 style="text-align: left;">後續</h3>
<p>本篇為『物聯網系統開發系列』系列之運用 ARDUINO 乙太網路擴充板建立用戶端工具程式,主要內容是要讓讀者使用創客神器 Arduino 開發板,透過乙太網路擴充板(Ethernet Shield)的網際網路連線之強大功能,可以讓 Arduino 開發板運用通訊能力,建立 Telnet 用戶端程式、簡易型文字瀏覽器等工具程式,如此一來,讀者可以將這個基礎理念與技術,進階運用到雲端平台的資料交換,或建立網路爬蟲的機制,進而在物聯網開發中,成為一個技術的核心能力&rsquo;,乃是筆者本篇內容想傳達的創作概念。</p>
<p>筆者本系列是針對非資訊、電機、電子等 Makers 攥寫的物聯網系統開發系列,這四、五年來在物聯網系統開發領域寫書、發表文章、辦展、授課,常遇到許多學子訓練不足,以交作業的心態來學習,並沒有把程式底子打好。</p>
<p>後續筆者還會繼續發表『物聯網系統開發系列』系列的文章,在未來我們可以創造出更優質,更具未來性的物聯網(Internet of Thing:IOT)產品開發相關技術。</p>
<p>敬請期待更多的文章。</p>
<h3>作者介紹</h3>
<p><strong>曹永忠 (Yung-Chung Tsao)</strong><strong> </strong><strong>,</strong>目前為自由作家暨專業 Maker,專研於軟體工程、軟體開發與設計、物件導向程式設計,商品攝影及人像攝影。長期投入創客運動、資訊系統設計與開發、企業應用系統開發、軟體工程、新產品開發管理、商品及人像攝影等領域,並持續發表作品及相關專業著作。</p>
<p>Email:<a href="mailto:[email protected]">[email protected]<br /></a>Line ID:dr.brucetsao</p>
<p><img src="https://cdn2-techbang.pixfs.net/system/images/400604/original/4a45fcaf21746e2ab9fc4ed7a715f499.jpeg?1498113437" alt="" /></p>
<p>作者網站:<a href="https://www.cs.pu.edu.tw/~yctsao/">https://www.cs.pu.edu.tw/~yctsao/<br /></a>臉書社群(Arduino.Taiwan):<a href="https://www.facebook.com/groups/Arduino.Taiwan/">https://www.facebook.com/groups/Arduino.Taiwan/<br /></a>Github 網站:<a href="https://github.com/brucetsao/">https://github.com/brucetsao/</a></p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="553" valign="top">
<p><strong>吳佳駿 (Chia-Chun Wu)</strong>,國立中興大學資訊科學與工程學系博士,現任教於國立金門大學工業工程與管理學系專任助理教授,目前兼任國立金門大學計算機與網路中心資訊網路組組長,主要研究為軟體工程與應用、行動裝置程式設計、物件導向程式設計、網路程式設計、動態網頁資料庫、資訊安全與管理。</p>
<p>Email: <a href="mailto:[email protected]">[email protected]</a></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="553" valign="top">
<p><strong>許智誠 (Chih-Cheng Hsu)</strong>,美國加州大學洛杉磯分校(UCLA) 資訊工程系博士,曾任職於美國 IBM 等軟體公司多年,現任教於中央大學資訊管理學系專任副教授,主要研究為軟體工程、設計流程與自動化、數位教學、雲端裝置、多層式網頁系統、系統整合。</p>
<p>Email: <a href="mailto:[email protected]">[email protected]</a></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="553" valign="top">
<p><strong>蔡英德 (Yin-Te Tsai)</strong>,國立清華大學資訊科學系博士,目前是靜宜大學資訊傳播工程學系教授、靜宜大學計算機及通訊中心主任,主要研究為演算法設計與分析、生物資訊、軟體開發、視障輔具設計與開發。</p>
<p>Email:<a href="mailto:[email protected]">[email protected]</a></p>
</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>參考文獻:</strong></p>
<p class="EndNoteBibliography">曹永忠, 吳佳駿, 許智誠, &amp; 蔡英德. (2017). 【物聯網系統開發】運用 ARDUINO 乙太網路擴充板建立簡單網頁伺服器. <em>智慧家庭.</em>&nbsp; Retrieved from <a href="http://www.techbang.com/posts/51518-internet-system-using-arduino-ethernet-add-on-board-to-build-a-simple-web-server">http://www.techbang.com/posts/51518-internet-system-using-arduino-ethernet-add-on-board-to-build-a-simple-web-server</a></p>
<p class="EndNoteBibliography">曹永忠, 許智誠, &amp; 蔡英德. (2015a). <em>Arduino</em><em>程式教學(</em><em>無線通訊篇):Arduino Programming (Wireless Communication)</em> (初版 ed.). 台湾、彰化: 渥瑪數位有限公司.</p>
<p class="EndNoteBibliography">曹永忠, 許智誠, &amp; 蔡英德. (2015b). <em>Arduino</em><em>编程教学(</em><em>无线通讯篇):Arduino Programming (Wireless Communication)</em> (初版 ed.). 台湾、彰化: 渥瑪數位有限公司.</p>
<p class="EndNoteBibliography">曹永忠, 許智誠, &amp; 蔡英德. (2015c). 創客神器ARDUINO到底是什麼呢?.&nbsp;&nbsp; Retrieved from <a href="http://makerdiwo.com/archives/1893">http://makerdiwo.com/archives/1893</a></p>
</blockquote>
<p class="EndNoteBibliography">&nbsp;</p>
<blockquote>
<p><strong><br /></strong></p>
<p><br /><br /></p>
</blockquote><a href="http://www.facebook.com/TKbang">加入T客邦Facebook粉絲團</a><img src="http://feeds.feedburner.com/~r/techbang/~4/EDNJt773kFY" height="1" width="1" alt=""/>