ラズベリーパイPico W 無線(Wi-Fi)の使い方

Pico W 無線(Wi-Fi)の使い方

ラズベリーパイ pico wに搭載された無線(Wi-Fi)の使い方を公式サイトを参考に、実際に動かし難しかった事、また解かりずらかった点など、基本的な使い方を説明します。またthonnyは最新バージョンをお勧めします。私はthonny4.0.1でPico-Wの自動実行main.pyをstopボタンで止められませんでした。

概要

今回ははこちらの公式サイトのプログラムコードに従って動かしています。
無線(Wi-Fi)の使い方が詳しく載っていますので見てみてください。

動作環境

ラズベリーパイ Pico W
Windowsパソコン WIN10 か WIN11
開発環境Thonny(最新バージョン)4.1.3

プログラム検証

Raspberry Pi Pico W のセットアップ済み、またPicozeroの MicroPython ライブラリも設定済とします。
main.pyとして自動実行されるプログラムもthonny4.1.3は、STOPボタンで停止できました。
プログラムを停止しないとファイル書き込みや、新しいプログラムの実行ができません。

Pico WをWLANに接続する

まず初めに、各種ライブラリーをインポートします。
次に自分の環境のネットワークのssid password 設定します。

import network
import socket
from time import sleep
from picozero import pico_temp_sensor, pico_led

import machine
ssid = 'NAME OF YOUR WIFI NETWORK'
password = 'YOUR SECRET PASSWORD'

次にconnect関数を定義します。
詳細は下記です。

def connect():
    #Connect to WLAN
    #network.STA_IF はルーター接続モード
    wlan = network.WLAN(network.STA_IF)
    #ネットワークがアクティブか?
    wlan.active(True)
    wlan.connect(ssid, password)
    while wlan.isconnected() == False:
        print('Waiting for connection…')
        sleep(1)
        print(wlan.ifconfig())
try:
    connect()
except KeyboardInterrupt:
    machine.reset()

下記のプログラムを実行して検証すると

import network
import socket
from time import sleep
from picozero import pico_temp_sensor, pico_led
import machine
ssid = 'NAME OF YOUR WIFI NETWORK'
password = 'YOUR SECRET PASSWORD'
def connect():
    #Connect to WLAN
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(ssid, password)
    while wlan.isconnected() == False:
        print('Waiting for connection...')
        sleep(1)
    print(wlan.ifconfig())
try:
    connect()
except KeyboardInterrupt:
    machine.reset()

下記の情報がプリントされれば接続成功ですが、内容は自身のネットワークより異なりります。

MPY: soft reboot
Waiting for connection…
Waiting for connection…
Waiting for connection…
(‘192.168.1.18’, ‘255.255.255.0’, ‘192.168.1.1’, ‘192.168.1.1’)


ifconfig()には IPアドレス、サブネットマスク、デフォルトゲートウェイ など合計4個が格納されているのが解ります。
またプログラムに間違えがなく、接続できない場合一度ピコWのUSB外し再接続して実行すると接続できます。
よく起こりますので注意してください。

上の接続関数は接続を試すもので、どこに接続されてるかわかるように実際はipアドレスプリントして返します。
ip = wlan.ifconfig()[0]
#configの1番目[0] ipアドレスだけとる
print(f’Connected on {ip}’)  
#ipアドレスプリント
return ip           
#ipアドレス

次にサーバーとブラウザーを接続するsocketを定義します。

def open_socket(ip):
    # Open a socket
    address = (ip, 80) 
  #ネットワークipアドレスと通常ブラウザーはポート80指定
    connection = socket.socket()
    connection.bind(address)
    connection.listen(1)
    return connection      
  # 1が返ってくれば正常接続です

ここまででピコサーバーとほかのパソコンの接続設定完了です

ウエブページ作成

ウエブページを作成します。
ピコWサーバはApacheなどと違います、他にも方法があるようですが、ここではf文字列(f”””……”””)で出力するみたいです。
そうすることで{}の中のデータを簡単に入れ変えることができます。

def webpage(temperature, state):
    #Template HTML
    html = f"""
            <!DOCTYPE html>
            <html>
            <form action="./lighton">
            <input type="submit" value="Light on" />
            </form>
            <form action="./lightoff">
            <input type="submit" value="Light off" />
            </form>
            <p>LED is {state}</p>
            <p>Temperature is {temperature}</p>
            </body>
            </html>
            """
  return str(html)

赤文字の部分がHTML部分で、関数def webpage(temperature, state)の引数、temperature, stateの2個は{}の中の変数に置き換えてHtmlファイルを生成して返します。

ブラウザーからの情報を収集してLED制御

はじめ私は下のプログラムの部分をよく理解できませんでした。
ウエブサーバを起動して、リクエストは何かプリントしてみました。

def serve(connection):
    #Start a web server
    state = 'OFF'
    pico_led.off()
    temperature = 0
    while True:
        client = connection.accept()[0]
        request = client.recv(1024)
        request = str(request)
        print(request)
        client.close()

この様なことでした。
ブラウザーからピコサーバーに接続要求するとrequestには下記のような情報の文字列が入ってくるのが解ります。
b’GET / HTTP/1.1\r\nHost: 192.168.1.18\r\nConne:……. 192.168.1.18/からのリクエスト
b’GET /favicon.ico HTTP/1.1\r\nHost: 192.168.1.18\r\n
b’GET /lighton? HTTP/1.1\r\nHost: 192.168.1.18\…… 192.168.1.18/lighton?からリクエスト
b’GET /favicon.ico HTTP/1.1\r\nHost: 192.168.1.18\r…
b’GET /lightoff? HTTP/1.1\r\nHost: 192.168.1.18\r…. 192.168.1.18/lightoff?からリクエスト
b’GET /favicon.ico HTTP/1.1\r\nHost: 192.168.1.18\r….
つまりrequestのブランク区切りの文字列をlistにして 2番目の情報で判断すればLEDをオンオフできます。
サーバーを動かすときはprint(request)は必要ありません。

それで、これがrequestで判定してLEDをON、OFFするプログラムです。

def serve(connection):
    #Start a web server
    state = 'OFF'
    pico_led.off()
    temperature = 0
    while True:
        client = connection.accept()[0]
        request = client.recv(1024)
        request = str(request)
        try:
            request = request.split()[1] 
      #split()関数で文字列をlistにして[1]2番目とる
        except IndexError:
            pass
        if request == '/lighton?':
            pico_led.on()
            state = 'ON'
        elif request =='/lightoff?':
            pico_led.off()
            state = 'OFF'
        temperature = pico_temp_sensor.temp
        html = webpage(temperature, state)
        client.send(html)
        client.close()

完成したプログラム

おまけに時刻、ジャバスクリプトも入れてみました、動きました。
now = time.localtime()はパソコンに接続したピコWでソニーから動かすと正しく日、時刻など表示されますが、main.pyで自動で動かすと、はじめ2022 1 1 0 0になります。
次はmain.pyで動かした場合も正しく時刻、また他のGPIOに接続したセンサーの値も表示したいと思います。

import network
import socket
from time import sleep
from picozero import pico_temp_sensor, pico_led
import machine
import time
# Wi-Fi ルーターのSSIDとパスワード
# 自分の環境に書き換えてください。
ssid = '???????'
password = '????????'
def connect():
    #Connect to WLAN
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(ssid, password)
    while wlan.isconnected() == False:
        print('Waiting for connection...')
        sleep(1)
    ip = wlan.ifconfig()[0]
    print(f'Connected on {ip}')
    return ip
def webpage(temperature, state,nen,ma,da,ta,mi):
    #Template HTML
    html = f"""
            <!DOCTYPE html>
            <html>
            <form action="./lighton">
            <input type="submit" value="Light on" />
            </form>
            <form action="./lightoff">
            <input type="submit" value="Light off" />
            </form>
            <p>LED is {state}</p>
            <p>Temperature is {temperature}</p>
            <p>date is {nen} {ma} {da} {ta} {mi}</p>
            <script>
                var date001 = new Date();
                document.writeln(date001);
            </script>
            </body>
            </html>
            """
    return str(html)
def serve(connection):
    #Start a web server
    state = 'OFF'
    pico_led.off()
    temperature = 0
    while True:
        client = connection.accept()[0]
        request = client.recv(1024)
        request = str(request)
        print(request)
        try:
            request = request.split()[ 1]
        except IndexError:
            pass
        if request == '/lighton?':
            pico_led.on()
            state = 'ON'
        elif request =='/lightoff?':
            pico_led.off()
            state = 'OFF'
        temperature = pico_temp_sensor.temp
        now = time.localtime()
        html = webpage(temperature, state,now[0],now[1],now[2],now[3],now[4])
        client.send(html)
        client.close()
def open_socket(ip):
    # Open a socket
    address = (ip, 80)
    connection = socket.socket()
    connection.bind(address)
    connection.listen(1)
    return connection
try:
    ip = connect()
    connection = open_socket(ip)
    serve(connection)
except KeyboardInterrupt:
    machine.reset()

実際に接続したときのブラウザーの画面です。
実際は英語表示ですが、下はブラウザーが日本語に変換した画面で、ピコサーバーはHTMLファイルの中に日本語を入れられないようです
間違え入れられます。
HTMLに <html lang=”ja”> <meta charset=”UTF-8″> を追記すればできます。
正しく動いています、これを基に工夫すれば色々面白いことができそうです。

タイトルとURLをコピーしました