Raspberry Pi Picoで無線LAN(3)
2022.5.26:ソースコードを修正(例外処理をの範囲を狭めました)
はじめに
Raspberry Pi Pico × MicroPython の組み合わせで「ESP-WROOM-02」を動かします。そのものズバリのサンプルが無いか、非常に少ないみたいなので、とりあえず動いた配線やソースコードを上げておきます。
(今後進展があったら追記があると思います)
「Raspberry Pi Picoで無線LAN(1)」では、ESP-WROOM-02と通信を始めるまで、「Raspberry Pi Picoで無線LAN(2)」では、クライアントとして無線LANネットワークに接続してデータを投げる辺りを載せました。
ここでは、サーバーとして起動させて、通信を受けてたら、何かしらデータを返すなどの動作をさせる、というあたりを載せておきたいと思います。
配線・コードサンプル
Raspberry Pi Pico側のコードになりますが、ここまでくると、ほとんどATコマンドとUARTのデータ受取だけの問題になります。
ちなみに、USBでPCとつないだ状態で作業してます。
import machine, utime
#”映え”が必要だったので...
def blink(led):
for i in range(3):
LED.value(0)
utime.sleep_ms(100)
LED.value(1)
utime.sleep_ms(100)
def execCommand( serial, cmd ):
execCommand_withWait( serial, cmd, 3000 )
#コマンド送信と戻り値の表示
def execCommand_withWait( serial, cmd, mswait ):
serial.write(cmd)
utime.sleep_ms(mswait)
res = serial.read()
#print('------')
#print(res)
#print('------')
#print(res.decode('utf-8'))
stat = ''
try:
stat = res.decode('utf-8').replace('\r\n\r\n','\r\n').split('\r\n')
except Exception as ex:
stat = 'Decode Error Unknown Responce'
for w in stat:
print('-> '+w)
print('------')
def networkConnect(u):
#フラッシュメモリに保存しない設定
execCommand(u,'AT+CWMODE_CUR=1\r\n')
#クライアントモードでDHCPでIP自動割り当て有効
#execCommand(u,'AT+CWDHCP_CUR=1,1\r\n')
#サーバーなのでIP固定 IP,デフォルトGW,マスク
execCommand(u,'AT+CIPSTA_CUR="192.168.100.64","192.168.100.1","255.255.255.0"\r\n')
#アクセスポイントに接続
execCommand(u,'AT+CWJAP_CUR="SSID","Password"\r\n')
utime.sleep(4)
#IP確認
execCommand(u,'AT+CIFSR\r\n')
def createServer(u):
#マルチプルコネクション
execCommand(u,'AT+CIPMUX=1\r\n')
#サーバーモード実行 ポートは1235
execCommand(u,'AT+CIPSERVER=1,1235\r\n')
u = machine.UART(0, 115200, tx=machine.Pin(0), rx=machine.Pin(1))
print("UART START")
LED = machine.Pin(22, machine.Pin.OUT)
LED.value(1)
print("LED START")
#バージョン表示
execCommand(u,'AT+GMR\r\n')
#無線ネットワーク検出
execCommand(u,'AT+CWLAP\r\n')
#ネットワーク接続関連のコマンド
networkConnect(u)
#サーバー立ち上げ関連のコマンド
createServer(u)
#接続状況の表示
execCommand(u,'AT+CIPSTATUS\r\n')
#IP,MAC
execCommand(u,'AT+CIFSR\r\n')
while True:
if u.any() > 0: #クライアントからデータの受信
blink(LED)
print('----START')
res = u.read(1024) #読み取り
print(res) #生データ
stat = res.decode('utf-8').split('\r\n')
for w in stat:
if w.find('+IPD') >= 0 : #ConnectやCloseの時は処理しない。
blink(LED)
blink(LED)
print('--DataRecive')
rcvary = w.split(',')
ID = rcvary[1]
DATA = (rcvary[2].split(':'))[1]
print('=>'+ID)
print('=>'+DATA)
returnword ='recved='+DATA
command ='AT+CIPSEND='+ID+','+str(len(returnword+'\r\n'))+'\r\n'
print('>>'+returnword)
print('>>'+command)
execCommand_withWait(u,command, 500)
execCommand_withWait(u,returnword+'\r\n', 500)
execCommand_withWait(u,'AT+CIPCLOSE='+ID+'\r\n',500)
print('----END')
接続や送受信のテストはTeratermでやりました。
一応、サーバー的な振る舞いをするようにしたので、固定IPにしています。
クライアントからの接続数制限とか、透過モードが良さそうとか、いろいろ思案すべき点はあるのですが、つなぐ→データ送る→データが返ってきて→クローズされる、と、一通りの流れで動くところまで何とかたどり着いたので、今回は良しとします。今のところ家庭内LANですし。
あとはサーバー側の実装です。
おまけのひとこと
いわゆる、サーバーモードで待ち続けるので電気食いますね。
IoTで何かするときは、大抵クライアントモードみたいな形にして、スリープモードを駆使して長期間動かす想定なので、今回の内容はあんまりかなとは思いますが、家や職場などで十分に電源が確保できそうな場所ではいろいろできて便利かなと思います。
さらに一言
いくら探してもそれらしいコマンド無かったので、もしかしたらとは思っていましたが、やはりUARTを使ったATコマンドによる通信では、SSLは非対応のようです。うーん。
本気出してやるなら、Micro Python側で暗号化の手段を立てないとダメですかね。さすがに「本気出して」となると、平文駄々漏らし状態はヤバいですから。幸い、RaspberryPiPicoはマイコンの中ではCPU強いっぽいので何とかなるかな。
参考
((1)、(2)と同じですが載せておきます)
<追加分>
http://www.microtechnica.tv/support/manual/espwroom02jp_man.pdf
Espressifのマニュアル