【Raspberry Pi Pico W】無線通信(Wi-Fi)のお試しサンプルコード集
0.はじめに
細かい説明などは他の記事を参考にしていただけると幸いです。
(私はネットワーク系の知識が乏しいので、うまく説明できないので…)
そのため、とりあえず動かしてみた系のサンプルコードを記載しておきます
micropython : v1.20
1.1 AccessPointとして使う(APモード)
変数SSIDとPASSWORDは任意の文字列を指定可能
※テスト用のため、ソースコードに直書きしてます(あまりよくない)
import network
import gc
# DEFINE
SSID:str = 'PICO_PICO_HAMMER' # 任意のアクセスポイント名を指定可能
PASSWORD:str = 'qwertyuiop' # 任意のパスワードを指定可能
gc.collect() # garbage collection(ゴミ掃除)
# アクセスポイントを作成し、access_pointを返す
access_point = network.WLAN(network.AP_IF) # AP:Access Pointとして使う
access_point.config(essid=SSID, password=PASSWORD) # APの設定を反映する
access_point.ifconfig(('192.168.4.3', '255.255.255.0', '192.168.4.1', '192.168.4.2')) # 各種IPアドレスを指定する(固定)
access_point.active(True) # アクセスポイントとして検知されるようになる
# 接続が成功した場合、(IPアドレス、ネットマスク、ゲートウェイ、DNS)を表示
print("Please connection access_point by other device...")
print("IP Address:{}\nNet Mask:{}\nGateway:{}\nDNS:{}".format(*access_point.ifconfig()))
while True:
pass # 特に処理はしない
実行結果
1.2 AccessPointとして使い、遠隔でLEDのON/OFFを制御する(APモード)
import usocket as socket
import network
import gc
# DEFINE
SSID:str = 'PICO_PICO_HAMMER' # 任意のアクセスポイント名を指定可能
PASSWORD:str = 'qwertyuiop' # 任意のパスワードを指定可能
def make_access_point(wifi_ssid:str, wifi_password:str):
"""アクセスポイントを作成し、access_pointを返す関数"""
access_point = network.WLAN(network.AP_IF) # AP:Access Pointとして使う
access_point.config(essid=wifi_ssid, password=wifi_password) # APの設定を反映する
access_point.ifconfig(('192.168.4.3', '255.255.255.0', '192.168.4.1', '192.168.4.2')) # 各種IPアドレスを指定する(固定)
access_point.active(True) # アクセスポイントとして検知されるようになる
# 接続が成功した場合、(IPアドレス、ネットマスク、ゲートウェイ、DNS)を表示
print("Please connection access_point by other device...")
print("IP Address:{}\nNet Mask:{}\nGateway:{}\nDNS:{}".format(*access_point.ifconfig()))
return access_point
class MyHomepageServer():
def __init__(self):
# socketの構成、設定
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # socketオブジェクトを作成
self.socket.bind(('', 80)) # bind
self.socket.listen(5) # listen
def _make_html_text(self, show_message:str):
""" レスポンスとして返すテキスト(html形式)を返す関数 """
html = ('''<html>
<head>
<meta charset="utf-8">
<title>Raspberry Pi pico server</title>
</head>
<body>
<h1>Message : {}</h1>
<a href="/led/on">Turn On LED</a></br>
<a href="/led/off">Turn Off LED</a>
</body>
</html>'''.format(show_message))
return html
def receive_waiting(self):
"""
受信(accept)
str型に変換し、テキストによって処理を分岐
1. b'GET /led/on'の指示が記載されている -> LEDを点灯し、messageに「LED is ON!」を埋め込み、htmlを送信(send)
2. b'GET /led/off\r\n'の指示が記載されている -> LEDを消灯し、messageに「LED is Off」を埋め込み、htmlを送信(send)
3. b'GET /favicon.ico HTTP/1.1\r\n'の指示が記載されている -> LEDを消灯し、messageに「GET favicon.ico」を埋め込み、htmlを送信(send)
3. 上記(1,2,3)以外 -> messageに「Please click any hyperlinks.」の文字列を埋め込み、htmlを送信(send)
たまに'GET /favicon.ico HTTP/1.1\r\n'の指示がacceptされるが、
"""
tmp_connection, addr = self.socket.accept() # 指示待ち状態に(指示あるまでココで一時停止状態となる)
print(f'Got a connection from {addr}') # アクセスして来た相手のAddressを表示
received_text = tmp_connection.recv(1024) # 受け取った内容を変数に格納(binary)
print(f'=== Content ===\n{received_text}') # 受け取った内容を表示(GET等)
if b"GET /led/on" in received_text:
led.value(1) # 出力をHIGHにする(LEDが点灯)
send_text = self._make_html_text("LED is ON!")
elif b"GET /led/off" in received_text:
led.value(0) # 出力をlowにする(LEDが消灯)
send_text = self._make_html_text("LED is Off")
elif b"GET /favicon.ico" in received_text:
send_text = self._make_html_text("GET favicon.ico")
else:
send_text = self._make_html_text("Please click any hyperlinks.")
tmp_connection.send(send_text) # 応答(response)を、接続相手に返す
tmp_connection.close() # connectionを閉じる
return None
# ココからmain文
gc.collect() # garbage collection(ゴミ掃除)
led = machine.Pin("LED", machine.Pin.OUT) # LED点灯用のPINを設定
ap = make_access_point(SSID, PASSWORD) # 関数にまとめてある
server = MyHomepageServer() # クラスを定義
while True:
server.receive_waiting() # こちらも関数にまとめてある
実行結果
PCやスマホで192.168.4.3にアクセスし、URLをクリックすると、picoのLEDを点灯/消灯 できる。
※たまに192.168.4.1になってしまうがなぜなのかは不明…(要調査)
おそらく初回は192.168.4.3になっていて、2回目(Thonnyの実行ボタンを押下して実行)は192.168.4.1になるっぽいです…
2. 既存のAccessPointに接続する(STAモード?)
先ほどの1.1で作成したアクセスポイントに接続してみる
import time
import network
import socket
from machine import Pin
import gc
led = Pin("LED", machine.Pin.OUT)
# DEFINE
SSID:str = 'PICO_PICO_HAMMER' # 任意のアクセスポイント名を指定可能
PASSWORD:str = 'qwertyuiop' # 任意のパスワードを指定可能
def connect_wifi():
wlan = network.WLAN(network.STA_IF) # STAモードで定義
wlan.active(True)
wlan.connect(SSID, PASSWORD) # 既存のアクセスポイントへ接続する
wlan.ifconfig(('192.168.4.13', '255.255.255.0', '192.168.4.2', '192.168.4.1')) # 192.168.4.1にIPアドレスを固定
# Wait for connect or fail
max_wait = 10
while max_wait > 0:
if wlan.status() < 0 or wlan.status() >= 3:
break
max_wait -= 1
print('waiting for connection...')
time.sleep(1)
# Handle connection error
if wlan.status() != 3:
raise RuntimeError('network connection failed')
else:
print('Connected')
status = wlan.ifconfig()
print( 'ip = ' + status[0] )
return wlan
class MyHomepageServer2():
def __init__(self):
# socketの構成、設定
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # socketオブジェクトを作成
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] # 公式推奨のやり方
self.socket.bind(addr) # bind
self.socket.listen(2) # listen
print('listening on', addr)
def _make_html_text(self, show_message:str):
""" レスポンスとして返すテキスト(html形式)を返す関数 """
html = ('''<html>
<head>
<meta charset="utf-8">
<title>Raspberry Pi pico server</title>
</head>
<body>
<h1>Message : {}</h1>
<a href="/led/on">Turn On LED</a></br>
<a href="/led/off">Turn Off LED</a>
</body>
</html>'''.format(show_message))
return html
def receive_waiting(self):
"""
受信(accept)
str型に変換し、テキストによって処理を分岐
1. b'GET /led/on'の指示が記載されている -> LEDを点灯し、messageに「LED is ON!」を埋め込み、htmlを送信(send)
2. b'GET /led/off\r\n'の指示が記載されている -> LEDを消灯し、messageに「LED is Off」を埋め込み、htmlを送信(send)
3. b'GET /favicon.ico HTTP/1.1\r\n'の指示が記載されている -> LEDを消灯し、messageに「GET favicon.ico」を埋め込み、htmlを送信(send)
3. 上記(1,2,3)以外 -> messageに「Please click any hyperlinks.」の文字列を埋め込み、htmlを送信(send)
たまに'GET /favicon.ico HTTP/1.1\r\n'の指示がacceptされるが、
"""
tmp_connection, addr = self.socket.accept() # 指示待ち状態に(指示あるまでココで一時停止状態となる)
print(f'Got a connection from {addr}') # アクセスして来た相手のAddressを表示
received_text = tmp_connection.recv(1024) # 受け取った内容を変数に格納(binary)
print(f'=== Content ===\n{received_text}') # 受け取った内容を表示(GET等)
if b"GET /led/on" in received_text:
led.value(1) # 出力をHIGHにする(LEDが点灯)
send_text = self._make_html_text("LED is ON!")
elif b"GET /led/off" in received_text:
led.value(0) # 出力をlowにする(LEDが消灯)
send_text = self._make_html_text("LED is Off")
elif b"GET /favicon.ico" in received_text:
send_text = self._make_html_text("GET favicon.ico")
else:
send_text = self._make_html_text("Please click any hyperlinks.")
tmp_connection.send(send_text) # 応答(response)を、接続相手に返す
tmp_connection.close() # connectionを閉じる
return None
gc.collect() # garbage collection(ゴミ掃除)
wlan = connect_wifi() # Wi-Fiに接続する
server = MyHomepageServer2() # クラスを定義
while True:
server.receive_waiting() # こちらも関数にまとめてある
実行結果
3. picoからpicoへ指示を出す(urequests)
先ほどまではPCブラウザなどでURLにアクセスすることで制御していたが、micropythonのurequestでURLにアクセスすることで、picoから制御することが可能
import utime as time
import network
from machine import Pin
import urequests as requests
# DEFINE
SSID:str = 'PICO_PICO_HAMMER' # 任意のアクセスポイント名を指定可能
PASSWORD:str = 'qwertyuiop' # 任意のパスワードを指定可能
URL_LED_ON:str = "http://192.168.4.13/led/on"
URL_LED_OFF:str = "http://192.168.4.13/led/off"
def l_chika(led, n=3):
for _ in range(n):
led.on()
time.sleep(0.1)
led.off()
time.sleep(0.1)
return None
def send_message_led_on():
""" """
try:
response = requests.get(URL_LED_ON) # requestを送る(LED点灯の指示)
print(response.status_code) # 基本200
print(response.text) # 受信内容を表示
except:
""" おそらくurllib3が想定しているHTMLフォーマットでないため、エラーが発生する(指示は通っている)
urllib3.exceptions.ProtocolError:
('Connection aborted.', BadStatusLine('<html><body><h1>Message : LED is Off</h1><a href="/on">Turn On LED</a></br>\n'))
"""
pass
return None
def send_message_led_off():
""" """
try:
requests.get(URL_LED_OFF) # requestを送る(LED消灯の指示)
print(response.status_code) # 基本200
print(response.text) # 受信内容を表示
except:
pass
return None
def connect_wifi():
wlan = network.WLAN(network.STA_IF) # STAモードで定義
wlan.active(True)
wlan.connect(SSID, PASSWORD) # 既存のアクセスポイントへ接続する
# wlan.ifconfig(('192.168.4.23', '255.255.255.0', '192.168.4.2', '192.168.4.1')) # 192.168.4.39にIPアドレスを固定
# Wait for connect or fail
max_wait = 10
while max_wait > 0:
if wlan.status() < 0 or wlan.status() >= 3:
break
max_wait -= 1
print('waiting for connection...')
time.sleep(1)
# Handle connection error
if wlan.status() != 3:
raise RuntimeError('network connection failed')
else:
print('Connected')
status = wlan.ifconfig()
print( 'ip = ' + status[0] )
return wlan
led = Pin("LED", machine.Pin.OUT)
l_chika(led, n=3) # LEDを3回点滅させる
wlan = connect_wifi() # Wi-Fiに接続する
while True:
time.sleep(0.1) # 0.1秒スリープする
if rp2.bootsel_button() == 1: # bootselボタンが押下状態の場合
send_message_led_on() # requestを送る(LED点灯の指示)
l_chika(led, n=2) # LEDを2回点滅させる
time.sleep(1) # 1秒スリープする
send_message_led_off() # requestを送る(LED消灯の指示)
l_chika(led, n=1) # LEDを1回点滅させる
実行結果
最後に
Raspberry Pi pico Wだけで外部インターネットと隔離されたローカルネットワークが作れるため、意外なところで使える…かもしれないなぁ、と感じた