前回、micropythonでサーボモーターの制御(pca9685の制御)プログラムを作成しました↓
今回は、ブラウザからロボットを操作する為に必要な「WIFIアクセスポイント」と「WEBサーバー」をM5ctackに立てるプログラムを作成したいと思います。
過去にラズパイでブラウザからロボットを操作するプログラムを作成した事がありますが、その時は
htmi->javascript->python->pca9685
の流れで、サーボモーターを制御させていましたが、これはwebiopiのライブラリでjavascriptからpythonへの値の受け渡し(関数呼び出し)が可能であったためです。
M5stackではwebiopiは使えないので、上記のような流れは難しいですが、micropythonのライブラリを駆使する事によってなんとか可能になります。
必要なライブラリは、micropythonファームウェアに全て入っているので、importで呼び出すことができます。
それでは、前回と同じくPC上にプログラムを作成し、テストしてみます。
server.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
import network import machine import time import socket import re ESSID = 'M5stack' PASSWORD = '11223344' IP = '192.168.5.1' sv ="p" #サーボモーター制御 def servoset(): global sv if sv == "st": print("set") elif sv == "fw": print("fw") elif sv == "lt": print("lt") elif sv == "bk": print("bk") elif sv == "rt": print("rt") #html def home_page(): html = """<html lang="ja"> <head> <meta charset="utf-8"> <title>サーボテスト</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> * { margin: 0px; padding: 0px; } body { max-width: 600px; font-size: 25px; width: 100%; } main { height: 40vh; background: skyblue; } ul { display: block; height: 40vh; list-style: none; padding-top: 10px; } .bc { display: flex; } .a, .bc, .d { height: 12vh; } li { width: 100px ; height: 90% ; margin-left: auto; margin-right: auto; background: yellow; } .b { margin-left: auto; } .c { margin-right: auto; } ul li { text-align: center; } .a li, .b li, .c li, .d li { border: solid 1px; } .n li { background: yellow; } a:active { color: #ff2020; } .a li, .b li, .c li, .d li, .n li { border: solid 1px; } .n { margin-right: 3px; margin-left: 3px; } </style> </head> <body> <main> <ul> <div class="a"> <a href="/svm_aa"> <li id="forward">前進</li> </a></div> <div class="bc"> <div class="b"> <a href="/svm_bb"> <li id="left">左旋回</li> </a></div> <div class="n"> <a href="/svm_ee"> <li id="set">SET</li> </a></div> <div class="c"> <a href="/svm_cc"> <li id="right">右旋回</li> </a></div> </div> <div class="d"> <a href="/svm_dd"> <li id="backward">後退</li> </a></div> </ul> </main> </body> </html>""" return html #テキストとして値を返す #WIFI APの立ち上げ ap = network.WLAN(network.AP_IF) ap.config(essid=ESSID, authmode=3, password=PASSWORD) ap.ifconfig((IP,'255.255.255.0',IP,'8.8.8.8')) ap.active(True) print("AP OK") #WEBサーバーの立ち上げ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('', 80)) s.listen(5) #クライアント接続 while True: conn, addr = s.accept() request = str(conn.recv(1024)) m = re.search(r'svm_(\D\D\s)', request) #print(request) #ボタン操作反映 if m != None : svm = m.group(0) if svm == 'svm_aa ': sv = "fw" elif svm == 'svm_bb ': sv = "lt" elif svm == 'svm_cc ': sv = "rt" elif svm == 'svm_dd ': sv = "bk" elif svm == 'svm_ee ': sv = "st" servoset() #サーボ関数呼び出し sv ="p" response = home_page() #html text格納 conn.send(response) #クライアントへhtmlデータ送信 conn.close() #scket破棄 print("Data Received") |
コメントアウトに記載している通りになりますが、さらっと順に説明していきます。
必要なライブラリをimport後、M5stackのアクセスポイントのSSID,pass,IPを変数に格納しています。
サーボモーターの制御は、テストとして文字列を返すだけの簡単な関数を作成しました。
続くhtml pageの関数は、テキストとしてhtmlの変数に格納し、それを返します。
WIFI APの立ち上げは、ap.configでssid,暗号方式,pass,を設定し、ipconfigでサーバ側のIP,サブネットマスク,デフォルトゲートウェイ,DNS,を設定できます。ap.activeで立ち上がります。
WEBサーバーの立ち上げのプログラムについては、socket.socketの第一引数は「ipv4」第二引数は「TCP接続」を表しています。s.bindの引数は、””が全てのクライアントを受け付ける意味で、第二引数はポート番号になります。s.listunは、クライアントの同時接続可能数になります。
クライアント接続については、s.acceptで待機し、接続後、while文に入ります。
クライアントがサーバーに接続すると、s.acceptでクライアント用のソケットとIPアドレスをconn,addrに返します。requestにはクライアントからのhttp接続のheader情報が入ります。search(r’svm_(\D\D\s)’, request)でheader情報からsvm_(\D\D\s)の正規表現された文字列に該当するものを検索しています。
ボタン操作反映では、先ほど検索した文字列で上下左右、もしくは何もしない、の判定をしています。
最終的にソケットは破棄され、再度接続を行うと(今回で言えばボタンを押すと)s.acceptからの実行となります。
あとはコメント通りです。
サーボモーターが動く流れとしては、サーバー接続後、ブラウザで操作画面(html)の任意のボタンをクリックすると、URLにsvm_○○のパラメータが乗り、再度ループ処理を開始します。正規表現された文字列がボタン操作反映部のどこかの条件に当てはまるので、svの値が変更されます。サーボ関数が実効されると、svの値に応じた処理が発生、となります。
他にも細かい部分はたくさんありますが、言い出せばきりが無いので説明は割愛させていただきます。
socket通信のサーバーとクライアント間の動作が結構ややこしいので分かりづらいと思いますので、下記にドキュメントをのリンクを張っておきますので、是非ご覧ください。↓
https://docs.micropython.org/en/latest/library/usocket.html
動作確認
では、作成したプログラムを実行してみます。
スマホなどで確認すると、WIFI APに「M5stack」が現れるので、passを入力して接続します。(”WANには接続できません”のポップアップがでますが、OKを選択します)
APに接続後、M5stackで設定しているWEBサーバーのIP「192.168.5.1:80」を入力します。
操作画面のhtmlが表示されるので、任意のボタンをクリック。
URLのパラメータと、Thonny IDEのshellに、ボタンに応じた文字列が反映されていればOKです。↓
次回は、ロボットのモーションの作成に入りたいと思います。