概要
動画の中で実演しています。
準備
1. LINE Notifyのアクセストークンを取得する
以下の記事を参考にすると良いと思います。
2. 設定ファイルを準備する
config.jsonファイルにWi-Fiの接続情報とLINE Notifyのアクセストークンを書き込んでRaspberry Pi Pico W上に配置してください。
config.json
{
"ssid": "2.4GHz帯のSSID",
"password": "Wi-Fiのパスワード",
"access_token": "1で取得したLINE Notifyのアクセストークン"
}
3. ソースコードを配置する
以下のindex.htmlとmain.pyをRaspberry Pi Pico W上に配置する。
ブラウザから操作するためのWebページ。
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<title>シフトレジスタを使ってLEDを操作する</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-sm-3" style="display: flex; justify-content: center; align-items: center; margin-top: 30px;">
<form action="./red">
<button type="submit" class="btn btn-danger" style="font-size: 1.5em; padding: 10px 20px;">赤</button>
</form>
</div>
<div class="col-sm-3" style="display: flex; justify-content: center; align-items: center; margin-top: 30px;">
<form action="./green">
<button type="submit" class="btn btn-success" style="font-size: 1.5em; padding: 10px 20px;">緑</button>
</form>
</div>
<div class="col-sm-3" style="display: flex; justify-content: center; align-items: center; margin-top: 30px;">
<form action="./blue">
<button type="submit" class="btn btn-primary" style="font-size: 1.5em; padding: 10px 20px;">青</button>
</form>
</div>
<div class="col-sm-3" style="display: flex; justify-content: center; align-items: center; margin-top: 30px;">
<form action="./yellow">
<button type="submit" class="btn btn-warning" style="font-size: 1.5em; padding: 10px 20px;">黄</button>
</form>
</div>
</div>
</div>
</body>
</html>
メインとなるプログラム。
main.py
from machine import Pin, reset
import time
import socket
import network
import ujson
import urequests
sdi = machine.Pin(0, Pin.OUT)
rclk = machine.Pin(1, Pin.OUT)
srclk = machine.Pin(2,Pin.OUT)
ip = None
def get_line_config():
"""
LINE Notifyの設定情報を取得する
Returns:
access_token(str): LINE Notifyのアクセストークン
"""
with open('config.json', 'r') as f:
data = ujson.load(f)
return data['access_token']
def notify(message):
"""
LINE Notifyを利用してトークルームにメッセージを送信する。
Parameters:
message(str): 送信するメッセージの内容
Returns:
response(Response) LINE Notifyのレスポンス
"""
endpoint = 'https://notify-api.line.me/api/notify'
access_token = get_line_config()
headers = {
'Authorization': 'Bearer ' + access_token,
'Content-Type' : 'application/x-www-form-urlencoded'
}
data = f'message={message}'.encode('utf-8')
response = urequests.post(endpoint, headers=headers, data=data)
return response
def hc595_shift(dat):
"""
8ビットのデータを入力して8チャンネルを同時にON/OFFする。
"""
rclk.low()
time.sleep_ms(5)
for bit in range(7, -1, -1):
srclk.low()
time.sleep_ms(5)
value = 1 & (dat >> bit)
sdi.value(value)
time.sleep_ms(5)
srclk.high()
time.sleep_ms(5)
time.sleep_ms(5)
rclk.high()
time.sleep_ms(5)
class WiFiConnectError(Exception):
pass
def connect():
"""
Wi-Fiに接続する。
Returns:
ip (str): IPアドレス
Raises:
WiFiConnectError: Wi-Fiに接続できなかった場合
"""
# Wi-Fiの接続情報を取得する
config = {}
with open('config.json', 'r') as f:
config = ujson.load(f)
# Wi-Fiに接続する
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(config['ssid'], config['password'])
timeout = 10
while timeout > 0:
timeout -= 1
print('Waiting for connection...')
if wlan.isconnected():
ip = wlan.ifconfig()[0]
print(f'Connected: {ip}')
return ip
time.sleep(1)
raise WiFiConnectError('Wi-Fiに接続できませんでした。')
def open_socket(ip):
"""
ソケットを開く。このソケットオブジェクトを介してクライアントとの通信を行う。
Parameters:
ip: WLAN上で自分自身を表すIPアドレス
Returns:
connection(socket.socket): ソケット接続
"""
address = (ip, 80) # 80ポートでソケット通信を行う
connection = socket.socket()
connection.bind(address)
connection.listen(1) # 同時接続の最大数1
return connection
def serve(connection):
"""
WEBサーバーを起動する。
Parameters:
connection(socket.socket): ソケット接続
"""
print('Starting Web Server...')
# LINEにIPを通知する
message = f'http://{ip}'
notify(message)
while True:
# 接続があるまで待機し、クライアントのソケットオブジェクトを取得する
client = connection.accept()[0]
# クライアントからのデータを受信する(最大1024バイト)
request = client.recv(1024)
# 受信したバイナリデータを文字列にする
request = str(request)
try:
# リソースのパスを取得する
request = request.split()[1]
print(request)
except IndexError:
pass
if '/red' in request:
hc595_shift(0b00010001)
elif '/green' in request:
hc595_shift(0b00100010)
elif '/blue' in request:
hc595_shift(0b01000100)
elif '/yello' in request:
hc595_shift(0b10001000)
# HTTPレスポンスを生成する
response = 'HTTP/1.1 200 OK\r\n'
response += 'Content-Type: text/html\r\n\r\n'
with open('index.html', 'r') as f:
response += f.read()
# HTTPレスポンスを送信する
client.send(response)
# クライアントソケットを閉じる
client.close()
if __name__ == '__main__':
try:
# LEDを初期化する
hc595_shift(0b00000000)
# Wi-Fiに接続する
ip = connect()
# ソケットを開く
connection = open_socket(ip)
# Web Serverを起動する
serve(connection)
except WiFiConnectError as e:
print(f'Error: {e}')
except Exception as e:
# 再起動する
reset()
4. 電子回路を組む
電子回路は以下の記事を参考にしてください。
5. モバイルバッテリーに接続する
モバイルバッテリーに接続するとLINEにRaspberry Pi Pico WにアクセスするためのURL(IP)が通知される。
URLをクリックするとLEDを操作する画面が表示される。
ボタンを押すと各色のLEDが点灯する。