Raspberry Pi Pico W を使った遠隔制御

はじめに

IoTテクノロジーの急速な発展に伴い、あらゆる分野に進出することになった通信機能付きシングルコンピュータ。

中でも、Raspberry Piは安価で入手できるシンブルコンピュータで、趣味や製品の試作機として利用されており、

また、各コンピュータサイエンス誌に定期的に特集が組まれる、今は流行りのコンピュータです。

Raspberry Pi Pico Wは、Raspberry Piの豊富な機能をそぎ落とし、小型マイコンにしたRaspberry Pi PicoにWi-Fi機能を追加した通信可能なマイコンとして注目されています。

Raspberry Pi Pico WはRaspberry Piよりもさらに安価で、1,200円(2023/11月時点)で入手可能です。

また、マイコン制御する際のソフトウェアとして、組み込み技術者が必須としていたアセンブラやC言語などではなく、最近流行りのPythonで制御できるようになっている為、組み込み制御を行う上でネックになっていた言語の壁を一気に解決する工夫が行われています。

今回は、このRaspberry Pi Pico Wを使い、ネットワーク経由で、模型の制御を行ってみようと思います。

 

仕組み

Raspberry Pi Pico WはWi-Fi機能をもっているので、Wi-Fiのアクセスポイントへ接続することができます。

また、Raspberry Pi Pico W上でWebサーバを動かすことができる為、HTTPクライアントからHTTPリクエストがあった時に、リクエストを解釈し、リクエストに応じて、マイコンのポートを制御することができます。

これを利用して、マイコンに接続されているデバイスを制御するように、ソフトウェアをPythonで構成します。
HTTPクライアントは、スマホのブラウザを使い、Wi-Fiのアクセスポイントを介してRaspberry Pi Pico Wにアクセスするようにネットワークを構築します。

必要な機材

今回のシステムでは、スマホからWi-Fi経由でRaspberry Pi Pico Wを搭載したキャタピラ付きの模型を制御するように製作します。

製作に必要な機材は以下のとおり。

No 分類 機材名 利用用途 備考
1 HTTPクライアント iPhone8 ブラウザ(Safari)

※Wi-Fiとブラウザが動けばどんな機種でも可

Wi-Fi接続可能な
HTTPクライアントとして使用。
2 Wi-Fi AP 自宅のWi-Fi AP Wi-Fiのアクセスポイント
DHCPサービスはONにしてIPアドレスを割り当てます。
3 Raspberry Pi Pico W Raspberry Pi Pico W Wi-Fi接続
WebServerとHW制御プログラムを実行。
参考価格:1200円
4 電気回路関連 Clienmero ブレッドボード 電源モジュールセット PC接続ケーブル付 電子工作 400穴 小型 Raspberry Pi Pico Wと各デバイスに接続する為の回路を作る為に使用。 参考価格:980円
uxcell ピンソケット ピンヘッダー メス ストレート 1列 ピッチ2.54mm 40ピン 5個入り Raspberry Pi Pico Wとブレッドボードに接続する為のピンをつける為に使用。 参考価格:747円
サンハヤト ジャンプワイヤキット SKS-100 単線タイプでよく使用する短めジャンプワイヤのセット品 ブレットボードで回路を作成する際のジャンプ線として使用。 参考価格:560円
KKHMF 3個 2チャンネル直流モータードライブモジュール プラスとマイナスの回転 ダブルHブリッジステッピングモータミニドライブボード 2つのモータの正転/反転を個別に制御するコントローラとして使用。モータに流す電力増幅装置としても使用。 参考価格:599円
エレコム モバイルバッテリー 軽量 小型 薄型 5000mAh 12W (2.4A) 2台同時充電 急速充電 出力2ポート(Type-C +USB-A) 入力(Type-C) 【 iPhone SE3 / 13 / 12 / iPad/Android 各種対応】 ブラック EC-C04BK Raspberry Pi Pico W及びモータに接続する電源として使用。電流が弱いとモータが駆動しないので、電流多めのものを選択。 参考価格:1799円
オーディオファン マイクロUSBケーブル フラットタイプ 充電データ転送対応 USB2.0 短い ブラック 10cm モバイルバッテリーからRaspberry Pi Pico Wに接続する為のケーブル。 参考価格:466円
サムコス 発光ダイオード 透明LEDダイオード 3mm 5mm 円型頭部 高輝度 電子部品ライト 赤/青/黄/緑/白 5色 収納ケース付 200個入 大砲を光らす為のLED。

LEDを光らす際のプルダウン抵抗については、手持ちのものを使用。

参考価格:645円
5 モーター制御関連 タミヤ 楽しい工作シリーズ ユニバーサルプレートセット モーターギアボックス固定用として使用。 参考価格:319円
タミヤ 楽しい工作シリーズ ツインモーターギアボックス モーターギアボックスとして使用。 参考価格:1076円
タミヤ 楽しい工作特別企画商品 トラック&ホイールセット ブラック/メタリックグレイ 69917 モーターギアボックスと連動して駆動するキャタピラとして使用 参考価格:1200円
6 模型 HGUC 機動戦士ガンダム RX-75 ガンタンク

※キャタピラがあれば何でも可

上記のモーター制御を組み込む模型。 参考価格:880円

※上記以外に必要な機材は、手持ちのストックで何とかしました。

 

Raspberry Pi Pico Wを搭載したキャタピラ付きの模型(完成画)

※配線、基盤は制御しているのがかわかるように敢えて外出しにしています。

主要な回路構成は以下のとおり。

ソフトウェアについて

ソフトウェアは、前述したとおり、アセンブラやC言語といった組み込み制御ではお馴染みな言語は使用せず、Pythonを使用して作成します。

具体的には、組み込みソフトで利用可能なMicroPythonを使用します。

MicroPythonについてはこちらを参照。
環境構築や組み込みでお馴染みなLチカについては、こちらにまとまっているので参照ください。

 

ここでは、この模型を動かすときに使用したPythonコードの一部を記載します。

# モーターとLEDのPIN定義
import machine

motor11 = machine.Pin(21, machine.Pin.OUT)
motor12 = machine.Pin(20, machine.Pin.OUT)
motor21 = machine.Pin(19, machine.Pin.OUT)
motor22 = machine.Pin(18, machine.Pin.OUT)
led1 = machine.Pin(7, machine.Pin.OUT, value=0)
led2 = machine.Pin(8, machine.Pin.OUT, value=0)

# モーター1の制御
# @param ctrl_val 0:停止, 1:正転, 2:反転, それ以外:対象外
def control_motor1(ctrl_val):
    if ctrl_val == 0:
        motor11.value(0)
        motor12.value(0)
    if ctrl_val == 1:
        motor11.value(1)
        motor12.value(0)
    if ctrl_val == 2:
        motor11.value(0)
        motor12.value(1)

# モーター2の制御
# @param ctrl_val 0:停止, 1:正転, 2:反転, それ以外:対象外
def control_motor2(ctrl_val):
    if ctrl_val == 0:
        motor21.value(0)
        motor22.value(0)
    if ctrl_val == 1:
        motor21.value(1)
        motor22.value(0)
    if ctrl_val == 2:
        motor21.value(0)
        motor22.value(1)

status = wlan.ifconfig()
time.sleep(0.5)
# IPアドレス取得
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
stateis = ""
print('listening on', addr)

# 起動確認用LED点灯
led.value(1)

# HTTPリクエスト受付ループ
while True:
    try:
        cl, addr = s.accept()
        print('client connected from', addr)
        request = cl.recv(1024)
        print(request)

        request = str(request)
        # Requestチェック
        motor_start = request.find('/motor/start')
        motor_back = request.find('/motor/back')
        motor_stop = request.find('/motor/stop')
        motor_left = request.find('/motor/left')
        motor_right = request.find('/motor/right')
        led_on = request.find('/led/on')
        led_off = request.find('/led/off')
        print( 'motor start = ' + str(motor_start))
        print( 'motor stop = ' + str(motor_stop))
        print( 'motor left = ' + str(motor_left))
        print( 'motor right = ' + str(motor_right))
        print( 'led on = ' + str(led_on))
        print( 'led off = ' + str(led_off))

        # start
        if motor_start == 6:
            print("motor start")
            control_motor1(2)
            control_motor2(2)
            stateis = "motor is start"
            time.sleep(0.5)
            f = open('TwinMotorControl_Sub.html','r')
            fhtml = f.read()
            f.close()

        # back
        if motor_back == 6:
            print("motor back")
            control_motor1(1)
            control_motor2(1)
            stateis = "motor is back"
            time.sleep(0.5)
            f = open('TwinMotorControl_Sub.html','r')
            fhtml = f.read()
            f.close()

        # stop
        if motor_stop == 6:
            print("motor stop")
            control_motor1(0)
            control_motor2(0)
            stateis = "motor is back"
            time.sleep(0.5)            
            f = open('TwinMotorControl_Sub.html','r')
            fhtml = f.read()
            f.close()

        # left
        if motor_left == 6:
            print("motor left")
            stateis = "motor is left"
            control_motor1(2)
            control_motor2(1)
            time.sleep(0.5)            
            f = open('TwinMotorControl_Sub.html','r')
            fhtml = f.read()
            f.close()

        # right
        if motor_right == 6:
            print("motor right")
            control_motor1(1)
            control_motor2(2)
            stateis = "motor is right"
            time.sleep(0.5)            
            f = open('TwinMotorControl_Sub.html','r')
            fhtml = f.read()
            f.close()

        # led on
        if led_on == 6:
            print("led on")
            led1.value(1)
            led2.value(1)
            stateis = "led on"
            time.sleep(0.5)            
            f = open('TwinMotorControl_Sub.html','r')
            fhtml = f.read()
            f.close()

        # led off
        if led_off == 6:
            print("led off")
            led1.value(0)
            led2.value(0)
            stateis = "led off"
            time.sleep(0.5)            
            f = open('TwinMotorControl_Sub.html','r')
            fhtml = f.read()
            f.close()

        # 操作リクエストでない場合、main画面を出す
        if motor_start != 6 and motor_stop != 6 and motor_left !=6 and motor_right != 6 and motor_back != 6 and led_on !=6 and led_off != 6:
            f = open('TwinMotorControl.html','r')
            fhtml = f.read()
            f.close()

        response = fhtml % stateis

        cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
        cl.send(response)
        cl.close()

    except OSError as e:
        cl.close()
        print('connection closed')

 

WebServerで出すコントロールUI画面

スマホのブラウザで表示するUI画面です。こちらは、HTMLがわかる方ならば簡単かと思います。

※もっと良い書き方があるかもしれません。

<HTMLコード>

<html>
    <style>
        button {
            width: 10em;
            height:3em;
            color:#ffffff;
            background-color:#0000ff;
          }
    </style>
    <head> <title>Pico W From File</title> </head>
    <body> <h1>Pico W Twin Motor Control</h1>
        <p>%s</p>
        <table>
        <tr>
            <td></td><td><button onclick="location.href='./motor/start'">Motor Foward</button></td><td></td>
        </tr>
        <tr>	
            <td><button onclick="location.href='./motor/left'">Motor Left</button></td>
<td><button onclick="location.href='./motor/stop'">Motor Stop</button></td>
<td><button onclick="location.href='./motor/right'">Motor Right</button></td>
        </tr>
        <tr>
            <td></td><td><button onclick="location.href='./motor/back'">Motor Back</button></td><td></td>
        </tr>
        <tr>
            <td><button onclick="location.href='./led/on'">LED On</button></td>
            <td></td>
            <td><button onclick="location.href='./led/off'">LED Off</button></td>
        </tr>
        </table>
    </body>
</html>

 

動作確認

各コントロールできることを確認できました。

詳細な動きについては筆者のInstagramにリールがのっているので、こちらを参照ください。

Instagramのアカウントがない方は、以下をご覧ください。

【前進】
【後進】
【右旋回】
【左旋回】
【LED点灯】

まとめ

Raspberry Pi Pico Wを使えば、Wi-Fi接続できるし、Pythonを使い簡単にハードウェア制御ができることが確認できました。

Pythonしかやったことがない人でもハード寄りの仕事ができて、Python技術者の需要が益々増えそうです。

 

やってみて思ったこと

Raspberry Pi Pico Wは安価の為、色々な場所にセンサーや駆動系の回路を接続して、情報の収取や簡単な制御に使うことができそう。

台風が接近している中、田畑の様子を見る為に外出し、命を落とす方が毎年いらっしゃいます。

田畑にセンサー付きのRaspberry Pi Pico Wを配置し、水嵩を計測してWi-Fi経由でサーバに送信し、サーバでは水嵩の上限に達しているか監視し、上限に達したら水路を閉めるようにWi-Fi経由でRaspberry Pi Pico Wに要求を出し水路を閉める、といったシステムが作れたら、社会貢献ができて便利ではないかと感じました。

 

#RaspberryPi #RaspberryPiPico #RaspberryPiPicoW #ラズベリーパイ #ラズベリーパイピコ #ラズベリーパイピコW #Iot #ガンダム #ガンタンク #組み込み #タミヤツインモーターギアボックス

\ 最新情報をチェック /