ASUS Tinker Board 2S 與 MCU 的無線通訊 – Wi-Fi篇

前言

目前在嵌入式系統或MCU常見的區域型無線通訊方式,如下表大致可以區分成5大類:

通訊技術 適用距離 Bits / Sec 常見應用
NFC 數公分~數公尺 約數百K 門禁裝置
藍牙 約 <50公尺

(5.X版可達300公尺)

約數十M 辦公室自動化、居家自動化
Wi-Fi 約 < 50公尺

(透過強波可到數百公尺)

約 <數G 辦公室自動化、居家自動化、工業自動化
Zigbee 約數百公尺 約數百K 辦公室自動化、居家自動化、工業自動化
LoRa 約數公里 約數十K 工業自動化、農業自動化

WiFi在無線通訊應用中是具有高頻寬、高速、訊號涵蓋範圍廣的特性,是許多行動裝置中最常使用的通訊技術,也廣泛應用於各種網際網路的訊息傳輸應用,在物聯網的應用裡,WiFi更是扮演著非常重要的角色,透過TCP / IP協定可以實現物聯網對於各種裝置的相互通聯,本篇教學將會透過WiFi、TCP / IP、UDP三種協定服務實作教學,實現Tinker Board 2S與MCU (Linkit-7697)進行網際網路的遠端遙控應用。

Tinker Board 2S透過PCIE-M.2擴充槽安裝通訊模組,其通訊模組包含WiFi與藍牙通訊的功能,通訊模組上也提供了可以外接天線或是與強波裝置連結的端子台,這主要是為了可以強化Tinker Board 2S在進行網際網路應用的彈性,無論是當成Server或是Client都可以具有一定的傳輸效能。

Tinker Board 2S做為嵌入式系統,其安裝的作業系統Linux-Debian也充分支援各種WiFi的協定應用,透過Python程式已Socket的方式進行通訊軟體介面的建立,因此本篇教學文將會著眼在Python程式設計的相關重點說明為主。

Linkit-7697微控器本身內建有WiFi與BLE藍牙通訊的功能,在小巧的微控器晶片裡充分整合了通訊與硬體擴充電路介面的操作,是一種非常適合運用在各種物聯網應用的微控器,此外,Linkit-7697的WiFi開發資源非常完整,可以開發成Server或是Client的各種應用,因此本篇教學將會以Linkit-7697進行WiFi遠端遙控的操作。

撰寫/攝影 曾俊霖
時間 2小時 材料表 ASUS  Tinker Board 2S / 2GB-連結

MCU Linkit-7697

 

難度 中等

 

一、測試電路

本次測試電路是以Linkit-7697控制RGB三色LED模組進行測試,如下圖。

二、Linkit7697測試電路範例程式

1. MCU的WiFi UDP存取程式設計流程(簡單的輸入與輸出資料傳輸測試)

(1). 設定WiFi通訊SSID與密碼
(2). 起始化並設定UDP通訊連接埠
(3). 接收UDP資料並進行命令格式解碼
(4). 依照命令進行RGB LED的控制
(5). 透過UDP連線回傳資料回應Tinker Board 2S

2. Linkit7697測試程式片段:

[pastacode lang=”cpp” manual=”%23include%20%3CLWiFi.h%3E%0A%23include%20%3CWiFiUdp.h%3E%0A%0A%23define%20LED_G%2010%0A%23define%20LED_B%2011%0A%23define%20LED_R%2012%0A%0Aint%20status%20%3D%20WL_IDLE_STATUS%3B%0Achar%20ssid%5B%5D%20%3D%20%22CAVEDU_02%22%3B%20%2F%2F%20%20your%20network%20SSID%20(name)%0Achar%20pass%5B%5D%20%3D%20%2212345678%22%3B%20%20%20%20%2F%2F%20your%20network%20password%20(use%20for%20WPA%20%2F%20WEP)%0Aint%20keyIndex%20%3D%200%3B%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20your%20network%20key%20Index%20number%20(needed%20only%20for%20WEP)%0A%0Aunsigned%20int%20localPort%20%3D%207890%3B%20%20%20%20%20%20%2F%2F%20local%20port%20to%20listen%20on%0A%0Achar%20Reply_R_ON%5B%5D%20%3D%20%22Red%20ON%22%3B%20%20%20%20%20%20%20%2F%2F%20a%20string%20to%20send%20back%0Achar%20Reply_R_OFF%5B%5D%20%3D%20%22Red%20OFF%22%3B%20%20%20%20%20%20%20%2F%2F%20a%20string%20to%20send%20back%0Achar%20Reply_G_ON%5B%5D%20%3D%20%22Green%20ON%22%3B%20%20%20%20%20%20%20%2F%2F%20a%20string%20to%20send%20back%0Achar%20Reply_G_OFF%5B%5D%20%3D%20%22Green%20OFF%22%3B%20%20%20%20%20%20%20%2F%2F%20a%20string%20to%20send%20back%0Achar%20Reply_B_ON%5B%5D%20%3D%20%22Blue%20ON%22%3B%20%20%20%20%20%20%20%2F%2F%20a%20string%20to%20send%20back%0Achar%20Reply_B_OFF%5B%5D%20%3D%20%22Blue%20OFF%22%3B%20%20%20%20%20%20%20%2F%2F%20a%20string%20to%20send%20back%0A%0AString%20SA%5B2%5D%3B%0Aint%20A%5B2%5D%3B%0A%0AWiFiUDP%20Udp%3B%0A%0Avoid%20setup()%20%7B%0A%20%20%2F%2FInitialize%20serial%20and%20wait%20for%20port%20to%20open%3A%0A%20%20Serial.begin(9600)%3B%0A%20%20while%20(!Serial)%20%7B%0A%20%20%20%20%3B%20%2F%2F%20wait%20for%20serial%20port%20to%20connect.%20Needed%20for%20native%20USB%20port%20only%0A%20%20%7D%0A%0A%20%20%2F%2F%20attempt%20to%20connect%20to%20Wifi%20network%3A%0A%20%20while%20(status%20!%3D%20WL_CONNECTED)%20%7B%0A%20%20%20%20Serial.print(%22Attempting%20to%20connect%20to%20SSID%3A%20%22)%3B%0A%20%20%20%20Serial.println(ssid)%3B%0A%20%20%20%20%2F%2F%20Connect%20to%20WPA%2FWPA2%20network.%20Change%20this%20line%20if%20using%20open%20or%20WEP%20network%3A%0A%20%20%20%20status%20%3D%20WiFi.begin(ssid%2C%20pass)%3B%0A%20%20%7D%0A%20%20Serial.println(%22Connected%20to%20wifi%22)%3B%0A%20%20printWifiStatus()%3B%0A%0A%20%20Serial.println(%22%5CnStarting%20connection%20to%20server…%22)%3B%0A%20%20%2F%2F%20if%20you%20get%20a%20connection%2C%20report%20back%20via%20serial%3A%0A%20%20Udp.begin(localPort)%3B%0A%7D%0A%0Avoid%20loop()%20%7B%0A%0A%20%20char%20packetBuffer%5B255%5D%3B%20%2F%2Fbuffer%20to%20hold%20incoming%20packet%0A%0A%20%20%2F%2F%20if%20there’s%20data%20available%2C%20read%20a%20packet%0A%20%20int%20packetSize%20%3D%20Udp.parsePacket()%3B%0A%20%20if%20(packetSize)%20%7B%0A%20%20%20%20Serial.print(%22Received%20packet%20of%20size%20%22)%3B%0A%20%20%20%20Serial.println(packetSize)%3B%0A%20%20%20%20Serial.print(%22From%20%22)%3B%0A%20%20%20%20IPAddress%20remoteIp%20%3D%20Udp.remoteIP()%3B%0A%20%20%20%20Serial.print(remoteIp)%3B%0A%20%20%20%20Serial.print(%22%2C%20port%20%22)%3B%0A%20%20%20%20Serial.println(Udp.remotePort())%3B%0A%0A%20%20%20%20%2F%2F%20read%20the%20packet%20into%20packetBufffer%0A%20%20%20%20int%20len%20%3D%20Udp.read(packetBuffer%2C%20255)%3B%0A%20%20%20%20if%20(len%20%3E%200)%20%7B%0A%20%20%20%20%20%20packetBuffer%5Blen%5D%20%3D%200%3B%0A%20%20%20%20%7D%0A%20%20%20%20Serial.println(%22Contents%3A%22)%3B%0A%20%20%20%20Serial.println(packetBuffer)%3B%0A%0A%20%20%20%20String%20value%20%3D%20String(packetBuffer)%3B%0A%0A%20%20%20%20String_to_Int(value%2C%202)%3B%0A%0A%20%20%20%20Serial.print(SA%5B0%5D)%3B%0A%20%20%20%20Serial.print(%22%2C%22)%3B%0A%20%20%20%20Serial.println(A%5B1%5D)%3B%0A%0A%20%20%20%20if%20(SA%5B0%5D%20%3D%3D%20%22G%22)%20%7B%0A%20%20%20%20%20%20if%20(A%5B1%5D%20%3D%3D%201)%20%7B%0A%20%20%20%20%20%20%20%20digitalWrite(LED_G%2C%20HIGH)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20send%20a%20reply%2C%20to%20the%20IP%20address%20and%20port%20that%20sent%20us%20the%20packet%20we%20received%0A%20%20%20%20%20%20%20%20Udp.beginPacket(Udp.remoteIP()%2C%20localPort)%3B%0A%20%20%20%20%20%20%20%20Udp.write(Reply_G_ON)%3B%0A%20%20%20%20%20%20%20%20Udp.endPacket()%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(A%5B1%5D%20%3D%3D%200)%20%7B%0A%20%20%20%20%20%20%20%20digitalWrite(LED_G%2C%20LOW)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20send%20a%20reply%2C%20to%20the%20IP%20address%20and%20port%20that%20sent%20us%20the%20packet%20we%20received%0A%20%20%20%20%20%20%20%20Udp.beginPacket(Udp.remoteIP()%2C%20localPort)%3B%0A%20%20%20%20%20%20%20%20Udp.write(Reply_G_OFF)%3B%0A%20%20%20%20%20%20%20%20Udp.endPacket()%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20value%20%3D%20%22%22%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if%20(SA%5B0%5D%20%3D%3D%20%22B%22)%20%7B%0A%20%20%20%20%20%20if%20(A%5B1%5D%20%3D%3D%201)%20%7B%0A%20%20%20%20%20%20%20%20digitalWrite(LED_B%2C%20HIGH)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20send%20a%20reply%2C%20to%20the%20IP%20address%20and%20port%20that%20sent%20us%20the%20packet%20we%20received%0A%20%20%20%20%20%20%20%20Udp.beginPacket(Udp.remoteIP()%2C%20localPort)%3B%0A%20%20%20%20%20%20%20%20Udp.write(Reply_B_ON)%3B%0A%20%20%20%20%20%20%20%20Udp.endPacket()%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(A%5B1%5D%20%3D%3D%200)%20%7B%0A%20%20%20%20%20%20%20%20digitalWrite(LED_B%2C%20LOW)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20send%20a%20reply%2C%20to%20the%20IP%20address%20and%20port%20that%20sent%20us%20the%20packet%20we%20received%0A%20%20%20%20%20%20%20%20Udp.beginPacket(Udp.remoteIP()%2C%20localPort)%3B%0A%20%20%20%20%20%20%20%20Udp.write(Reply_B_OFF)%3B%0A%20%20%20%20%20%20%20%20Udp.endPacket()%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20value%20%3D%20%22%22%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if%20(SA%5B0%5D%20%3D%3D%20%22R%22)%20%7B%0A%20%20%20%20%20%20if%20(A%5B1%5D%20%3D%3D%201)%20%7B%0A%20%20%20%20%20%20%20%20digitalWrite(LED_R%2C%20HIGH)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20send%20a%20reply%2C%20to%20the%20IP%20address%20and%20port%20that%20sent%20us%20the%20packet%20we%20received%0A%20%20%20%20%20%20%20%20Udp.beginPacket(Udp.remoteIP()%2C%20localPort)%3B%0A%20%20%20%20%20%20%20%20Udp.write(Reply_R_ON)%3B%0A%20%20%20%20%20%20%20%20Udp.endPacket()%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(A%5B1%5D%20%3D%3D%200)%20%7B%0A%20%20%20%20%20%20%20%20digitalWrite(LED_R%2C%20LOW)%3B%0A%20%20%20%20%20%20%20%20%2F%2F%20send%20a%20reply%2C%20to%20the%20IP%20address%20and%20port%20that%20sent%20us%20the%20packet%20we%20received%0A%20%20%20%20%20%20%20%20Udp.beginPacket(Udp.remoteIP()%2C%20localPort)%3B%0A%20%20%20%20%20%20%20%20Udp.write(Reply_R_OFF)%3B%0A%20%20%20%20%20%20%20%20Udp.endPacket()%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20value%20%3D%20%22%22%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0A%0Avoid%20String_to_Int(String%20temp%2C%20int%20count)%0A%7B%0A%20%20int%20index%3B%0A%0A%20%20index%20%3D%20temp.indexOf(‘%2C’)%3B%0A%20%20SA%5B0%5D%20%3D%20temp.substring(0%2C%20index)%3B%0A%0A%20%20for%20(int%20i%20%3D%201%3B%20i%20%3C%20count%3B%20i%2B%2B)%20%7B%0A%20%20%20%20temp%20%3D%20temp.substring(index%20%2B%201%2C%20temp.length())%3B%0A%20%20%20%20index%20%3D%20temp.indexOf(‘%2C’)%3B%0A%20%20%20%20SA%5Bi%5D%20%3D%20temp.substring(0%2C%20index)%3B%0A%20%20%20%20A%5Bi%5D%20%3D%20SA%5Bi%5D.toInt()%3B%0A%20%20%7D%0A%7D%0A%0Avoid%20printWifiStatus()%20%7B%0A%20%20%2F%2F%20print%20the%20SSID%20of%20the%20network%20you’re%20attached%20to%3A%0A%20%20Serial.print(%22SSID%3A%20%22)%3B%0A%20%20Serial.println(WiFi.SSID())%3B%0A%0A%20%20%2F%2F%20print%20your%20WiFi%20shield’s%20IP%20address%3A%0A%20%20IPAddress%20ip%20%3D%20WiFi.localIP()%3B%0A%20%20Serial.print(%22IP%20Address%3A%20%22)%3B%0A%20%20Serial.println(ip)%3B%0A%0A%20%20%2F%2F%20print%20the%20received%20signal%20strength%3A%0A%20%20long%20rssi%20%3D%20WiFi.RSSI()%3B%0A%20%20Serial.print(%22signal%20strength%20(RSSI)%3A%22)%3B%0A%20%20Serial.print(rssi)%3B%0A%20%20Serial.println(%22%20dBm%22)%3B%0A%7D” message=”LinkIt 7697 wifi ” highlight=”34-46,51-72,84-86″ provider=”manual”/]

這個測試程式主要可以「接收」使用者的命令進行RGB-LED電路模組的控制,並且「發送」訊息回應使用者。

接收命令 RGB-LED動作 發送回應訊息
R,1 亮起紅色光 Red ON
R,0 熄滅紅色光 Red OFF
G,1 亮起綠色光 Green ON
G,0 熄滅綠色光 Green OFF
B,1 亮起藍色光 Blue ON
B,0 熄滅藍色光 Blue OFF

 

3. Linkit7697的操作狀態訊息輸出(透過Serial 序列資料輸出訊息)

(a) 初始狀態訊息輸出

 

(b) 接收來自Tinker Board 2S UDP資料並輸出狀態

4. Tinker Board 2S Python測試流程:

    • 起始化並設定WiFi TCP / IP
    • 設定UDP通訊模式
    • 輸入控制命令
    • 透過UDP發送控制命令至MCU
    • 等候來自MCU的回應訊息
    • 接收MCU的回應訊息
    • 顯示來自MCU的回應訊息

5. Tinker Board 2S Python測試程式:

[pastacode lang=”python” manual=”import%20socket%0Aimport%20threading%0A%0Aimport%20inspect%0Aimport%20ctypes%0A%0Aimport%20time%0Aimport%20datetime%0Aimport%20requests%0A%0Aimport%20tkinter%0Aimport%20tkinter.font%20as%20tkFont%0A%0Afrom%20PIL%20import%20Image%0Aimport%20PIL.Image%2C%20PIL.ImageTk%0A%0Aimport%20os%0Aimport%20io%0A%0Aclass%20App%3A%0A%20%20%20%20def%20__init__(self%2C%20window%2C%20window_title)%3A%0A%20%20%20%20%20%20%20%20self.window%20%3D%20window%0A%20%20%20%20%20%20%20%20self.window.title(window_title)%0A%20%20%20%20%20%20%20%20self.window.geometry(‘800×600′)%0A%20%20%20%20%20%20%20%20self.window.resizable(False%2C%20False)%0A%0A%20%20%20%20%20%20%20%20self.thread_sw%20%3D%201%0A%0A%20%20%20%20%20%20%20%20self.fontStyle%20%3D%20tkFont.Font(size%3D30)%0A%20%20%20%20%20%20%20%20self.header_label%20%3D%20tkinter.Label(window%2C%20text%3D’%E7%B6%B2%E8%B7%AF%E7%9B%A3%E6%8E%A7%E7%B3%BB%E7%B5%B1’%2Cfont%3Dself.fontStyle)%0A%20%20%20%20%20%20%20%20self.header_label.place(x%3D80%2C%20y%3D0%2C%20width%3D640)%0A%0A%20%20%20%20%20%20%20%20%23%20%E5%BB%BA%E7%AB%8B%E5%A5%97%E6%8E%A5%E5%AD%97%0A%20%20%20%20%20%20%20%20self.udp_socket%20%3D%20socket.socket(socket.AF_INET%2C%20socket.SOCK_DGRAM)%0A%20%20%20%20%20%20%20%20%23%20%E7%B9%AB%E7%B5%90%E6%9C%AC%E5%9C%B0%E8%B3%87%E8%A8%8A%0A%20%20%20%20%20%20%20%20self.udp_socket.bind((”%2C%207890))%0A%0A%20%20%20%20%20%20%20%20%23%20%E5%BB%BA%E7%AB%8B%E4%B8%80%E5%80%8B%E5%AD%90%E5%9F%B7%E8%A1%8C%E7%B7%92%E7%94%A8%E4%BE%86%E6%8E%A5%E6%94%B6%E7%B6%B2%E8%B7%AF%E8%B3%87%E6%96%99%0A%20%20%20%20%20%20%20%20self.t%20%3D%20threading.Thread(target%3Dself.recv_msg%2C%20args%3D(self.udp_socket%2C))%0A%20%20%20%20%20%20%20%20self.t.start()%0A%0A%20%20%20%20%20%20%20%20%23%20%E5%BB%BA%E7%AB%8B%E7%B6%B2%E8%B7%AF%E7%AF%80%E9%BB%9E1%E9%A1%AF%E7%A4%BA%E8%A8%8A%E6%81%AF%0A%20%20%20%20%20%20%20%20self.fontStyle%20%3D%20tkFont.Font(size%3D20)%0A%20%20%20%20%20%20%20%20self.Node_1_Label%20%3D%20tkinter.Label(window%2Ctext%3D%22%E7%B6%B2%E8%B7%AF%E7%AF%80%E9%BB%9E1%22%2Cpadx%20%3D%2020%2C%20font%3Dself.fontStyle)%0A%20%20%20%20%20%20%20%20self.Node_1_Label.place(x%3D20%2C%20y%3D150%2C%20width%3D150)%0A%0A%20%20%20%20%20%20%20%20%23%20%E7%99%BC%E9%80%81%E8%B5%B7%E5%A7%8B%E8%A8%8A%E6%81%AF%E7%B5%A6%E6%9C%AC%E6%A9%9F%E6%B8%85%E7%A9%BA%E8%A8%8A%E6%81%AF%E6%AC%84%E4%BD%8D%0A%20%20%20%20%20%20%20%20self.dest_ip%20%3D%20’127.0.0.1’%0A%20%20%20%20%20%20%20%20self.dest_port%20%3D%207890%0A%20%20%20%20%20%20%20%20self.msg%20%3D%20”%0A%20%20%20%20%20%20%20%20self.udp_socket.sendto(self.msg.encode(%22utf-8%22)%2C%20(self.dest_ip%2C%20self.dest_port))%0A%0A%20%20%20%20%20%20%20%20%23%20%E5%BB%BA%E7%AB%8B%E7%99%BC%E9%80%81%E4%BD%8D%E5%9D%80%E9%A1%AF%E7%A4%BA%E8%A8%8A%E6%81%AF%0A%20%20%20%20%20%20%20%20self.fontStyle%20%3D%20tkFont.Font(size%3D16)%0A%20%20%20%20%20%20%20%20self.Send_IP_Label%20%3D%20tkinter.Label(window%2Ctext%3D%22%E7%99%BC%E9%80%81%E4%BD%8D%E5%9D%80%22%2Cpadx%20%3D%2020%2C%20font%3Dself.fontStyle)%0A%20%20%20%20%20%20%20%20self.Send_IP_Label.place(x%3D20%2C%20y%3D520%2C%20width%3D100)%0A%0A%20%20%20%20%20%20%20%20%23%20%E5%BB%BA%E7%AB%8B%E7%99%BC%E9%80%81%E4%BD%8D%E5%9D%80%E8%BC%B8%E5%85%A5%E8%A8%8A%E6%81%AF%0A%20%20%20%20%20%20%20%20self.fontStyle%20%3D%20tkFont.Font(size%3D16)%0A%20%20%20%20%20%20%20%20self.Send_IP_input%20%3D%20tkinter.Entry(window%2Cfont%3Dself.fontStyle%2Cfg%3D’blue’)%0A%20%20%20%20%20%20%20%20self.Send_IP_input.place(x%3D125%2C%20y%3D520%2C%20width%3D200)%0A%0A%20%20%20%20%20%20%20%20%23%20%E5%BB%BA%E7%AB%8B%E4%BD%8D%E5%9D%80%E5%9F%A0%E8%99%9F%E9%A1%AF%E7%A4%BA%E8%A8%8A%E6%81%AF%0A%20%20%20%20%20%20%20%20self.fontStyle%20%3D%20tkFont.Font(size%3D16)%0A%20%20%20%20%20%20%20%20self.Port_Label%20%3D%20tkinter.Label(window%2Ctext%3D%22%E4%BD%8D%E5%9D%80%E5%9F%A0%E8%99%9F%22%2Cpadx%20%3D%2020%2C%20font%3Dself.fontStyle)%0A%20%20%20%20%20%20%20%20self.Port_Label.place(x%3D330%2C%20y%3D520%2C%20width%3D100)%0A%0A%20%20%20%20%20%20%20%20%23%20%E5%BB%BA%E7%AB%8B%E4%BD%8D%E5%9D%80%E5%9F%A0%E8%99%9F%E8%BC%B8%E5%85%A5%E8%A8%8A%E6%81%AF%0A%20%20%20%20%20%20%20%20self.fontStyle%20%3D%20tkFont.Font(size%3D16)%0A%20%20%20%20%20%20%20%20self.Port_input%20%3D%20tkinter.Entry(window%2Cfont%3Dself.fontStyle%2Cfg%3D’blue’)%0A%20%20%20%20%20%20%20%20self.Port_input.place(x%3D435%2C%20y%3D520%2C%20width%3D100)%0A%0A%20%20%20%20%20%20%20%20%23%20%E5%BB%BA%E7%AB%8B%E7%99%BC%E9%80%81%E8%B3%87%E8%A8%8A%E9%A1%AF%E7%A4%BA%E8%A8%8A%E6%81%AF%0A%20%20%20%20%20%20%20%20self.fontStyle%20%3D%20tkFont.Font(size%3D16)%0A%20%20%20%20%20%20%20%20self.Data_Label%20%3D%20tkinter.Label(window%2Ctext%3D%22%E7%99%BC%E9%80%81%E8%B3%87%E8%A8%8A%22%2Cpadx%20%3D%2020%2C%20font%3Dself.fontStyle)%0A%20%20%20%20%20%20%20%20self.Data_Label.place(x%3D20%2C%20y%3D555%2C%20width%3D100)%0A%0A%20%20%20%20%20%20%20%20%23%20%E5%BB%BA%E7%AB%8B%E7%99%BC%E9%80%81%E8%B3%87%E8%A8%8A%E8%BC%B8%E5%85%A5%E8%A8%8A%E6%81%AF%0A%20%20%20%20%20%20%20%20self.fontStyle%20%3D%20tkFont.Font(size%3D16)%0A%20%20%20%20%20%20%20%20self.Data_input%20%3D%20tkinter.Entry(window%2Cfont%3Dself.fontStyle%2Cfg%3D’blue’)%0A%20%20%20%20%20%20%20%20self.Data_input.place(x%3D125%2C%20y%3D555%2C%20width%3D400)%0A%0A%20%20%20%20%20%20%20%20%23%20%E5%BB%BA%E7%AB%8B%E7%99%BC%E9%80%81%E8%B3%87%E6%96%99%E6%8C%89%E9%88%95%0A%20%20%20%20%20%20%20%20self.fontStyle%20%3D%20tkFont.Font(size%3D20)%0A%20%20%20%20%20%20%20%20self.Send_Button%20%3D%20tkinter.Button(window%2C%20text%3D’%E7%99%BC%E9%80%81%E8%B3%87%E6%96%99’%2C%20font%3Dself.fontStyle%2C%20command%3Dself.Send_Data)%0A%20%20%20%20%20%20%20%20self.Send_Button.place(x%3D550%2C%20y%3D525%2C%20width%3D200%2C%20height%3D60)%0A%0A%20%20%20%20%20%20%20%20%23%20%E5%BB%BA%E7%AB%8B%E9%97%9C%E9%96%89%E5%A4%9A%E5%9F%B7%E8%A1%8C%E7%B7%92%E6%8C%89%E9%88%95%0A%20%20%20%20%20%20%20%20self.fontStyle%20%3D%20tkFont.Font(size%3D20)%0A%20%20%20%20%20%20%20%20self.Send_Button%20%3D%20tkinter.Button(window%2C%20text%3D’%E9%97%9C%E9%96%89%E5%9F%B7%E8%A1%8C%E7%B7%92’%2C%20font%3Dself.fontStyle%2C%20command%3Dself.Close_Thread)%0A%20%20%20%20%20%20%20%20self.Send_Button.place(x%3D550%2C%20y%3D450%2C%20width%3D200%2C%20height%3D60)%0A%0A%20%20%20%20%20%20%20%20%23%20After%20it%20is%20called%20once%2C%20the%20update%20method%20will%20be%20automatically%20called%20every%20delay%20milliseconds%0A%20%20%20%20%20%20%20%20self.delay%20%3D%201000%0A%20%20%20%20%20%20%20%20self.update()%0A%0A%20%20%20%20%20%20%20%20self.window.mainloop()%0A%0A%20%20%20%20def%20Send_Data(self)%3A%20%0A%20%20%20%20%20%20%20%20self.dest_ip%20%3D%20self.Send_IP_input.get()%0A%20%20%20%20%20%20%20%20self.dest_port%20%3D%20int(self.Port_input.get())%0A%20%20%20%20%20%20%20%20self.msg%20%3D%20self.Data_input.get()%0A%20%20%20%20%20%20%20%20self.udp_socket.sendto(self.msg.encode(%22utf-8%22)%2C%20(self.dest_ip%2C%20self.dest_port))%0A%0A%20%20%20%20def%20Close_Thread(self)%3A%20%0A%20%20%20%20%20%20%20%20self.thread_sw%20%3D%200%0A%20%20%20%20%20%20%20%20self.stop_thread(self.t)%0A%20%20%20%20%20%20%20%20self.udp_socket.shutdown(socket.SHUT_RDWR)%0A%20%20%20%20%20%20%20%20self.udp_socket.close()%0A%0A%20%20%20%20def%20update(self)%3A%0A%20%20%20%20%20%20%20%20%22%22%22%E6%8E%A5%E6%94%B6%E7%B6%B2%E8%B7%AF%E8%B3%87%E6%96%99%E4%B8%A6%E9%A1%AF%E7%A4%BA%22%22%22%0A%20%20%20%20%20%20%20%20%23%20%E9%A1%AF%E7%A4%BA%E7%B6%B2%E8%B7%AF%E7%AF%80%E9%BB%9E1%E7%9A%84%E8%B3%87%E6%96%99%0A%20%20%20%20%20%20%20%20self.fontStyle%20%3D%20tkFont.Font(size%3D20)%0A%20%20%20%20%20%20%20%20self.Node_1_value_Label%20%3D%20tkinter.Label(%0A%20%20%20%20%20%20%20%20%20%20%20%20self.window%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20text%20%3D%20str(self.recv_msg)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20padx%20%3D%2020%2C%20bg%3D%22white%22%2C%20fg%3D%22red%22%2C%20font%3Dself.fontStyle)%0A%20%20%20%20%20%20%20%20self.Node_1_value_Label.place(x%3D20%2C%20y%3D200%2C%20width%3D400)%0A%0A%20%20%20%20%20%20%20%20self.window.after(self.delay%2C%20self.update)%0A%0A%20%20%20%20def%20recv_msg(self%2Cudp_socket)%3A%0A%20%20%20%20%20%20%20%20while%20(self.thread_sw%20%3D%3D%201)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20print(‘self.thread_sw%20%3D%20’%2Cself.thread_sw)%0A%20%20%20%20%20%20%20%20%20%20%20%20print(‘thread_sw%20%3D%20’%2Cself.thread_sw)%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%201.%20%E6%8E%A5%E6%94%B6%E8%B3%87%E6%96%99%0A%20%20%20%20%20%20%20%20%20%20%20%20self.recv_msg%20%3D%20udp_socket.recvfrom(1024)%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%202.%20%E8%A7%A3%E7%A2%BC%0A%20%20%20%20%20%20%20%20%20%20%20%20self.recv_ip%20%3D%20self.recv_msg%5B1%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20self.recv_msg%20%3D%20self.recv_msg%5B0%5D.decode(%22utf-8%22)%0A%0A%20%20%20%20def%20_async_raise(self%2Ctid%2C%20exctype)%3A%0A%20%20%20%20%20%20%20%20%22%22%22raises%20the%20exception%2C%20performs%20cleanup%20if%20needed%22%22%22%0A%20%20%20%20%20%20%20%20tid%20%3D%20ctypes.c_long(tid)%0A%20%20%20%20%20%20%20%20if%20not%20inspect.isclass(exctype)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20exctype%20%3D%20type(exctype)%0A%20%20%20%20%20%20%20%20res%20%3D%20ctypes.pythonapi.PyThreadState_SetAsyncExc(tid%2C%20ctypes.py_object(exctype))%0A%20%20%20%20%20%20%20%20if%20res%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20ValueError(%22invalid%20thread%20id%22)%0A%20%20%20%20%20%20%20%20elif%20res%20!%3D%201%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20%22%22%22if%20it%20returns%20a%20number%20greater%20than%20one%2C%20you’re%20in%20trouble%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20and%20you%20should%20call%20it%20again%20with%20exc%3DNULL%20to%20revert%20the%20effect%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20ctypes.pythonapi.PyThreadState_SetAsyncExc(tid%2C%20None)%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20SystemError(%22PyThreadState_SetAsyncExc%20failed%22)%0A%0A%20%20%20%20def%20stop_thread(self%2Cthread)%3A%0A%20%20%20%20%20%20%20%20self.thread_sw%20%3D%200%0A%20%20%20%20%20%20%20%20self._async_raise(thread.ident%2C%20SystemExit)%0A%0A%20%20%20%20def%20__del__(self)%3A%0A%20%20%20%20%20%20%20%20print(‘Good%20Bye!’)%0A%0A%0A%23%20Create%20a%20window%20and%20pass%20it%20to%20the%20Application%20object%0AApp(tkinter.Tk()%2C%20%22%E7%B6%B2%E8%B7%AF%E7%9B%A3%E6%8E%A7%E7%B3%BB%E7%B5%B1%22)%0A” message=”tinker GUI app to talk with LinkIt 7697 via wifi” highlight=”33-51,99-103,123-131″ provider=”manual”/]

(a) Tinker Board 2S 程式初始狀態

(b) 設定發送IP(如:Linkit7697的IP為192.168.12.139)、設定通訊埠(如:7890)與設定欲發送命令資料(如:B,1,讓LED亮藍燈),按下「發送資料」後,網路節點1(來自Linkit7697的回應訊息)回應「Blue ON」

本篇教學文主要針對Tinker Board 2S以WiFi通訊透過UDP協定進行與MCU的通訊,透過UDP的傳輸,具有資料傳輸效率甚高的特點(因為不需要進行嚴謹的資安檢查),非常適合用來進行高速的資料傳輸,因此,將會於另一篇教學文中,介紹透過UDP協定進行多個計算機系統之間串流影像傳輸,實現遠端的影像串流傳輸,並且透過人工智慧影像辨識的整合,達成網路串流影像辨識的目的,大家就拭目以待吧!

相關文章

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *