micro:bit 的無線電通訊功能使其成為學習物聯網和無線感測網路的理想平台。本文除了介紹 micro:bit 如何實作裝置間的訊息廣播和同步閃爍特效外,也探討其無線電通訊的底層機制,例如訊息快取管理、按鈕事件處理,以及訊息的接收與轉發。此外,文章也涵蓋瞭如何使用 ESP8266/ESP32 等 WiFi 模組擴充套件 micro:bit 的網路連線能力,包含連線 WiFi 網路、設定存取點,以及使用 urequests 模組簡化 HTTP 請求等實務操作。最後,文章也簡要介紹了 MQTT 協定及其在物聯網應用中的重要性,為讀者提供更全面的技術視野。
微位元(micro:bit)無線電廣播技術詳解與實務應用
簡介
微位元(micro:bit)裝置之間的無線電通訊為物聯網(IoT)與無線感測網路技術提供了簡易且具教育意義的實作方式。本文將探討兩個主要的程式範例:簡易訊息廣播系統與螢火蟲同步閃爍特效,並分析其技術細節、實作方法及改進方向。
簡易訊息廣播系統實作分析
系統架構與運作原理
該系統主要實作了多個micro:bit裝置之間的訊息快取管理、按鈕事件處理以及訊息的接收與轉發功能。核心程式碼如下:
message_cache = {}
cache_lifetime = 1000 * 5 # 5秒快取生命週期
position = 0
while True:
sleep(20)
now = running_time()
to_delete = []
# 快取管理機制
for key, timestamp in message_cache.items():
if now > timestamp + cache_lifetime:
to_delete.append(key)
for stale_message in to_delete:
del message_cache[stale_message]
# 按鈕事件處理
if button_a.was_pressed():
position = (position + 1) % len(messages)
display.scroll(messages[position], 50, wait=False)
if button_b.was_pressed():
radio.send('{}:{}'.format(device_name, messages[position]))
# 訊息接收與轉發
msg = radio.receive()
if msg and msg not in message_cache:
message_cache[msg] = running_time()
radio.send(msg)
sender, message = msg.split(':')
display.scroll('{} says: {}'.format(sender, message), 50, wait=False)
內容解密:
快取管理機制:透過定期清除過期訊息,避免記憶體資源耗盡。
- 使用
running_time()取得當前時間戳記。 - 比對訊息時間戳記與當前時間,判斷是否超出快取生命週期。
- 使用
按鈕事件處理邏輯:
- A按鈕用於迴圈切換預設訊息。
- B按鈕負責傳送當前選定的訊息。
訊息接收與轉發機制:
- 接收到的訊息會被快取並轉發。
- 使用
split(':')解析訊息來源與內容。
螢火蟲同步閃爍特效實作分析
技術原理與實作方法
該特效模擬了螢火蟲的生物發光同步行為,裝置之間透過無線電訊號同步閃爍。核心程式碼如下:
flash = [Image().invert()*(i/9) for i in range(9, -1, -1)]
radio.on()
while True:
if button_a.was_pressed():
radio.send('flash')
incoming = radio.receive()
if incoming == 'flash':
sleep(random.randint(50, 350))
display.show(flash, delay=100, wait=False)
if random.randint(0, 9) == 0:
sleep(500)
radio.send('flash')
內容解密:
動畫效果實作:
- 建立漸變閃爍動畫陣列
flash。 - 使用
Image().invert()實作畫面反轉效果。
- 建立漸變閃爍動畫陣列
同步機制:
- 接收到
'flash'訊號後隨機延遲顯示閃爍動畫。 - 以一定機率轉發訊號,實作訊號傳播。
- 接收到
隨機性設計:
- 使用
random.randint()引入隨機延遲,避免同步閃爍。
- 使用
系統最佳化與擴充套件方向
安全性提升:
- 增加訊息驗證機制,防止惡意幹擾。
- 實作簡單的加密傳輸。
功能擴充套件:
- 新增語音或音樂提示功能。
- 增加搖晃偵測啟動閃爍效果。
效能最佳化:
- 改善快取管理策略。
- 降低不必要的無線電廣播。
微位元(micro:bit)的無線電與網路連線能力
微位元(micro:bit)是一款強大的微控制器,具備無線電通訊能力,能夠實作多個裝置之間的無線資料傳輸。本文將探討微位元的無線電功能及其網路連線能力,並提供程式碼範例來說明如何使用這些功能。
微位元的無線電功能
微位元的無線電功能允許裝置之間進行無線通訊。預設情況下,微位元使用特定的頻率進行通訊,但開發者可以根據需要更改頻道、群組和功率等設定。
使用無線電傳送和接收訊息
微位元提供了簡單易用的API來傳送和接收訊息。開發者可以使用radio.send()和radio.receive()函式來傳送和接收字串訊息,或者使用radio.send_bytes()和radio.receive_bytes()來傳送和接收位元組訊息。
import radio
# 初始化無線電
radio.on()
while True:
# 接收無線電訊息
radio_msg = radio.receive_bytes()
if radio_msg:
# 處理接收到的訊息
print(radio_msg)
# 傳送無線電訊息
msg = b'Hello, micro:bit!'
radio.send_bytes(msg)
處理接收到的訊息
在接收訊息時,可能會遇到額外的位元組。這些額外的位元組是為了與其他平台相容而新增的,通常可以忽略。
import radio
radio.on()
while True:
radio_msg = radio.receive_bytes()
if radio_msg:
# 移除額外的位元組
if radio_msg[:3] == b'\x01\x00\x01':
radio_msg = radio_msg[3:]
# 處理接收到的訊息
print(radio_msg)
連線USB串列埠讀取訊息
開發者可以透過USB串列埠連線微位元,並讀取從微位元傳送的訊息。可以使用pySerial函式庫來實作這一點。
import serial
from serial.tools.list_ports import comports
def find_microbit():
ports = comports()
for port in ports:
if "VID:PID=0D28:0204" in port[2].upper():
return port[0]
return None
def get_serial():
port = find_microbit()
if port is None:
raise IOError('無法找到微位元。')
return serial.Serial(port, 115200, timeout=1, parity='N')
serial_conn = get_serial()
while True:
msg = serial_conn.read_all()
if msg:
print(msg)
ESP8266/32 WiFi模組
要使微位元具備網際網路連線能力,可以使用ESP8266或ESP32 WiFi模組。這些模組提供了WiFi連線功能,使得微位元可以連線到網際網路。
連線到WiFi網路
可以使用network模組來連線到WiFi網路。
import network
# 初始化WiFi站點
station = network.WLAN(network.STA_IF)
# 啟用WiFi站點
station.active(True)
# 掃描可用的WiFi網路
available_networks = station.scan()
for network in available_networks:
print(network)
設定存取點
也可以將ESP8266/32設定為WiFi存取點,讓其他裝置連線。
import network
# 初始化存取點
access_point = network.WLAN(network.AP_IF)
# 取得存取點的IP設定
print(access_point.ifconfig())
# 設定DNS伺服器
access_point.ifconfig(dns='208.67.222.222')
設定 WiFi 連線
在開始使用 MicroPython 進行網路相關操作之前,首先需要設定 WiFi 連線。這包括將裝置設定為存取點(Access Point)或連線到第三方 WiFi 網路。
設定裝置為存取點
若要將裝置設定為存取點,可以使用 config 方法,如下所示:
>>> access_point.config('essid')
'MicroPython-121ce1'
>>> access_point.config('authmode')
4
>>> access_point.config(essid='new_net_name', password='new_password')
>>> access_point.config('password')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: unknown config param
內容解密:
access_point.config('essid')用於查詢目前的網路名稱。access_point.config('authmode')傳回目前的驗證模式。access_point.config(essid='new_net_name', password='new_password')更新網路名稱和密碼。access_point.config('password')嘗試查詢密碼,但 MicroPython 不會顯示密碼,因此會出現錯誤。
MicroPython 支援以下引數來定義存取點網路的設定:
mac:MAC 位址,以位元組表示。essid:WiFi 存取點的網路名稱,以字串表示。channel:WiFi 頻道,以整數表示。hidden:布林值,表示網路是否隱藏。authmode:支援的驗證模式,如前所述。password:密碼,以字串表示。
建議在將裝置用作存取點時盡快更新網路名稱(essid)和密碼。
連線到 WiFi 網路
若要將裝置連線到可用的 WiFi 網路,請啟用站點(station)並呼叫 connect 方法:
>>> station.active(True)
>>> station.connect('Network Name', 'password123')
>>> station.ifconfig()
('192.168.178.190', '255.255.255.0', '192.168.178.1', '192.168.178.1')
內容解密:
station.active(True)啟用站點。station.connect('Network Name', 'password123')連線到指定的 WiFi 網路。station.ifconfig()傳回裝置的 IP 位址組態。
一旦連線,ifconfig 方法會告訴你裝置的 IP 位址。MicroPython 會記住站點和存取點模式的組態,因此在重啟後裝置會嘗試還原或重新連線。
管理連線
你可以輕鬆停用站點或存取點連線:
>>> access_point.active(False)
或者,你可以斷開連線:
>>> access_point.disconnect()
要檢查連線狀態,可以使用 isconnected 方法或 status 方法:
>>> station.isconnected()
True
>>> access_point.status()
STAT_GOT_IP
內容解密:
isconnected方法傳回布林值,表示連線狀態。status方法傳回連線狀態的列表。
簡單的網路連線範例
以下範例展示如何使用 socket 模組連線到伺服器並接收資料:
>>> import socket
>>> addr_info = socket.getaddrinfo("towel.blinkenlights.nl", 23)
>>> addr_info
[(2, 1, 0, '', ('94.142.241.111', 23))]
>>> server_addr = addr_info[0][-1]
>>> s = socket.socket()
>>> s.connect(server_addr)
>>> while True:
... data = s.recv(500)
... print(str(data, 'utf8'), end='')
...
內容解密:
socket.getaddrinfo方法將網域名稱轉換為 IP 位址。- 建立 socket 連線到遠端伺服器。
- 無限迴圈接收並列印從伺服器接收的資料。
使用 urequests 模組簡化 HTTP 請求
MicroPython 的 urequests 模組模擬了 requests 模組的核心功能,使得發出 HTTP 請求變得更加容易:
>>> import urequests as requests
>>> response = requests.get('http://micropython.org/')
內容解密:
- 使用 urequests 模組發出 GET 請求。
requests.get方法傳回伺服器的回應。
網路應用與MQTT協定
MicroPython在ESP8266上的網路功能非常強大,允許開發者輕鬆地與各種網路服務進行互動。由於大多數根據HTTP的程式化互動都使用JSON格式,因此使用諸如Star Wars API等服務變得非常簡單。
使用urequests進行HTTP請求
首先,我們來看看如何使用urequests模組來進行HTTP請求。以下是一個簡單的例子,展示瞭如何從Star Wars API取得資料:
>>> import urequests as requests
>>> response = requests.get('http://swapi.co/api/people/1/')
>>> dir(response)
['text', '__init__', '__qualname__', 'close', 'content', 'json', '__module__', 'encoding', 'raw', 'reason', '_cached', 'status_code']
>>> person = response.json()
>>> person['name']
'Luke Skywalker'
>>> person['homeworld']
'http://swapi.co/api/planets/1/'
>>> person['films']
['http://swapi.co/api/films/6/', 'http://swapi.co/api/films/3/', 'http://swapi.co/api/films/2/', 'http://swapi.co/api/films/1/', 'http://swapi.co/api/films/7/']
內容解密:
urequests.get()用於傳送HTTP GET請求到指定的URL。response.json()將伺服器的回應解析為Python字典。- 我們可以像存取普通字典一樣存取傳回的資料,例如
person['name']。
傳送資料到伺服器
除了取得資料外,我們還可以向伺服器傳送資料。以下是一個使用JSON placeholder服務傳送資料的例子:
>>> import urequests as requests
>>> import json
>>> data = json.dumps({'hello': 'world'})
>>> url = 'http://jsonplaceholder.typicode.com/posts'
>>> response = requests.post(url, data=data)
>>> response.json()
{'id': 101}
內容解密:
json.dumps()將Python字典轉換為JSON格式的字串。requests.post()用於傳送HTTP POST請求,將資料傳送到指定的URL。- 伺服器回應一個包含新建立資源ID的JSON物件。
建立簡單的Web伺服器
MicroPython還允許我們在ESP8266上建立一個簡單的Web伺服器。以下是一個例子,展示瞭如何建立一個傳回GPIO引腳狀態的JSON表示的Web伺服器:
import machine
import socket
import json
template = """HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: {length}
Server: MicroPython
{json}"""
pins = [machine.Pin(i, machine.Pin.IN) for i in (0, 2, 4, 5, 12, 13, 14, 15)]
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
print('listening on', addr)
while True:
cl, addr = s.accept()
print('client connected from', addr)
cl_file = cl.makefile('rwb', 0)
while True:
line = cl_file.readline()
if not line or line == b'\r\n':
break
status = {str(p): p.value() for p in pins}
data = json.dumps(status)
response = template.format(length=len(data), json=data)
cl.send(response)
cl.close()
內容解密:
- 使用
socket模組建立一個TCP通訊端,並監聽80埠上的連線請求。 - 當客戶端連線時,讀取請求頭,直到遇到空行。
- 取得GPIO引腳的狀態,將其轉換為JSON格式的字串。
- 將JSON資料插入到HTTP回應範本中,並傳送給客戶端。
MQTT協定簡介
MQTT(Message Queue Telemetry Transport)是一種輕量級的發布/訂閱(pub/sub)訊息傳輸協定。在MQTT網路中,裝置(稱為客戶端)連線到一個中央伺服器(稱為代理),並訂閱他們感興趣的主題。客戶端也可以向主題發布訊息。許多客戶端可以訂閱同一個主題,並且任何發布到該主題的訊息都將被匯總到訂閱者。
MQTT的工作原理
- 主題命名: 主題使用類別似於URL路徑的命名約定,使用“/”作為分隔符。這使得主題可以按照共同的主題進行組織,並且命名約定可以隨著時間的推移而演變。
- 發布和訂閱: 客戶端可以向特定主題發布訊息,也可以訂閱特定主題以接收發布到該主題的訊息。
- 萬用字元: 客戶端可以使用萬用字元(+和#)來訂閱符合特定模式的所有主題。