前回は「MicroPython」を使用したブラウザからの遠隔操作、データ監視の方法を紹介しましたが、今回は「CircuitPython」を使用した方法を詳しく紹介します。
動作確認用のブラウザページ(html、JavaScript、CSS)は今回も「ChatGPT」にお任せして、「CircuitPython」を使用したWi-Fi無線通信について理解し、自由に使いこなせるようになりましょう。
遠隔操作の方法として「サーバー」機能を利用していますが、ここで紹介する「サーバー」機能を使いこなせば「ChatGPT」のようなチャットボットを作ることもできるようになります。
これについても、作り方を以下のリンクで詳しく紹介しています。
「MicroPython」や「C言語(Arduinoコマンド)」を使用した、Wi-Fi通信、遠隔操作&表示の方法も、以下のリンクで詳しく紹介しています。
「Raspberry Pi PicoW」の基本仕様、開発環境については以下のリンクで詳しく紹介しています。
1.ラズパイPico Wとは
2.開発環境について
・CircuitPythonとは
・Thonnyとは
・adafruit_httpserverライブラリの新旧の違いについて
3.MicroPythonとの違い
・USBメモリのように認識される
・環境変数設定ファイル「setting.toml」について(Ver.8以降)
4.「基本編」Wi-Fi接続、遠隔操作&表示
・動作紹介
・サンプルプログラム(コピペ)
・プログラムの詳細
5.「応用編」Wi-Fi接続、遠隔操作&表示(データ自動更新)
・動作紹介
・サンプルプログラム(コピペ)
・プログラムの詳細
6.本体に別ファイルで保存したWebページを読み込む方法
・Thonnyを使用したファイルの保存、実行方法
・Pythonサンプルプログラム(コピペ)
・HTMLサンプルプログラム(コピペ)
7.動作確認用のWebページの作成はChatGPTにおまかせ
8.まとめ
1.ラズパイPico Wとは
「Raspberry Pi PicoW」とは、イギリスを拠点とする慈善団体によって若者のプログラミング学習を目的に開発されたもので、他の「Raspberry Piシリーズ」とは異なり、OSの機能はありませんが、電源投入ですぐに使用でき、スイッチやLEDランプ、モーター、各種センサー、通信機器を接続して、それらを制御するプログラムを簡単に作成して動作確認できるため、組み込み(制御)系プログラミングの学習に最適です。
「Pico W」にはWi-Fi機能があり、Wi-Fi通信を利用したインターネット経由のデータ収集や遠隔操作等のアイデアを簡単に試すことができます。
端子配列は下画像のようになります(公式サイトより抜粋)
2.開発環境について
・CircuitPythonとは
「CircuitPython」とはマイコンボード(マイクロコントローラ)上での動作に最適化された「Python3」と互換性のある「MicroPython」から派生した、教育および初心者向けのオープンソースのプログラミング言語です。
「CircuitPython」の公式サイトは以下のリンクになります。
・Thonnyとは
「Thonny」とは「ラズベリーパイ」の上位機種にも標準でインストールされている「Python」のプログラム作成、デバッグ、実行を行うことがでる統合開発環境(IDE)です。
簡単なデバッグ機能やエラー情報の確認ができるため、学習におけるストレスを最小限に抑えることができ「Python」プログラマーにとって非常に役立つ開発環境と言えます。
エディタとしての機能は物足りないですが、手軽に導入できて特に初心者の方がお試しするには最適のツールと思います。
「CircuitPython」を使用した開発環境「Thonny」の使用方法は以下のリンクで詳しく紹介しています。
・adafruit_httpserverライブラリの新旧の違いについて
最新のライブラリは以下の「Adafruit」社のサイトから「PicoW」にインストールした「CircuitPython」のバージョン(7.x か 8.x)に合わせてダウンロードして下さい。
最新のライブラリの使い方は、以下の「GitHub」で紹介されています。
「Adafruit社」のライブラリのダウンロードから保存方法は以下のリンクで詳しく紹介しています。
「adafruit_httpserver」ライブラリの変更内容は以下になります。
# importの設定方法変更 ----------------------------------------------------------------------
# <変更後ライブラリ(サンプルプログラム)の場合>
from adafruit_httpserver import Server, Request, Response
# ファイルも返す場合は以下のようにする
from adafruit_httpserver import Server, Request, Response, FileResponse
# <変更前ライブラリの場合
from adafruit_httpserver.mime_type import MIMEType # MIMEタイプ(Webサーバーが送信するファイルの種類)を扱えるようにする
from adafruit_httpserver.request import HTTPRequest # Webブラウザからのリクエストに関する情報を取得するために使用
from adafruit_httpserver.response import HTTPResponse # Webブラウザに対して送信するレスポンスを設定するために使用
from adafruit_httpserver.server import HTTPServer # HTTPリクエストを受信し、適切なHTTPレスポンスを返信すために使用
# サーバーの起動方法変更 ----------------------------------------------------------------------
# <変更後ライブラリ(サンプルプログラム)の場合>
pool = socketpool.SocketPool(wifi.radio) # Wi-Fi接続上でソケットを管理するためのオブジェクトを作成
server = Server(pool, "/static", debug=True) # サーバー起動時にPicoWのルートディレクトリからデータを提供できるようにする
# <変更前ライブラリの場合>
pool = socketpool.SocketPool(wifi.radio) # Wi-Fi接続上でソケットを管理するためのオブジェクトを作成
server = HTTPServer(pool, "/static") # サーバー起動時にPicoWのルートディレクトリからデータを提供できるようにする
# サーバーリクエストに対するレスポンスを「HTML」で送信する方法 ----------------------------------------------------
# <変更後ライブラリ(サンプルプログラム)の場合>
# ルート(IPアドレス:ポート)アクセス時に実行される関数
@server.route("/")
def base(request: Request):
html = webpage() # WebページのHTMLコードを取得
return Response(request, html, content_type="text/html")
# <変更前ライブラリの場合>
# ルート(IPアドレス:ポート)アクセス時に実行される関数
@server.route("/")
def base(request: HTTPRequest): # HTTPリクエストに応答する関数を定義
html = webpage() # WebページのHTMLコードを取得
with HTTPResponse(request, content_type=MIMEType.TYPE_HTML) as response: # レスポンスを返すためのHTTPオブジェクトを作成
response.send(html) # レスポンスとしてHTMLコードを送信
# サーバーリクエストに対するレスポンスを「テキスト(文字列)」で送信する方法 ----------------------------------------------------
# <変更後ライブラリ(サンプルプログラム)の場合>
# 本体LED点灯(IPアドレス:ポート/lighton)アクセス時に実行される関数
@server.route("/lighton")
def light_on(request: Request): # HTTPリクエストを処理する関数を定義
led.value = True # 本体LEDを点灯
return Response(request, "LED_ON!", content_type="text/plane")
# <変更前ライブラリの場合>
# 本体LED点灯(IPアドレス:ポート/lighton)アクセス時に実行される関数
@server.route("/lighton")
def light_on(request: HTTPRequest): # HTTPリクエストを処理する関数を定義
led.value = True # 本体LEDを点灯
with HTTPResponse(request) as response: # レスポンスを返すためのHTTPオブジェクトを作成(MIMEタイプは指定しなければplane/text)
response.send("LED_ON!") # レスポンスとして文字列「LED_ON!」を送信
# サーバーリクエストに対するレスポンスに「PicoW」本体内の「ファイル」を送信する方法 ----------------------
# <変更後ライブラリ(サンプルプログラム)の場合>
# ルート(IPアドレス:ポート)アクセス時に実行される関数
@server.route("/")
def base(request: Request): # HTTPリクエストを処理する関数を定義
return FileResponse(request, filename='index.html', root_path='/')
# <変更前ライブラリの場合>
# ルート(IPアドレス:ポート)アクセス時に実行される関数
@server.route("/")
def base(request: HTTPRequest): # HTTPリクエストを処理する関数を定義
with HTTPResponse(request, content_type=MIMEType.TYPE_HTML) as response: # レスポンスを返すためのHTTPオブジェクトを作成
response.send_file("index.html") # レスポンスとしてPicoWルートフォルダの「index.html」ファイルを読み込みHTMLデータとして返す
3.MicroPythonとの違い
「MicroPython」と「CircuitPython」は、両方とも「Python」から派生し、マイクロコントローラー用に最適化されたものです。
「Python」の基本的な文法をサポートしていますが、ライブラリに関しては共通のものは一部で、多くのライブラリは専用のものを使用する必要があります。
主な特徴はそれぞれ以下のようになります。
- MicroPython
「Python 3.4」をベースに開発され「Python」標準の関数やモジュールの多くが使えるため、「Python」を使ったことがある人には扱い易いです。
サポートしているマイクロコントローラーやライブラリは「CircuitPython」よりは少ないですが、それでも初心者の方が扱うには十分な機能があり、マイクロコントローラーを使用して「Python」学習を始めるための有益なツールと思います。 - CircuitPython
「MicroPython」から派生し「Adafruit社」によって開発されたもので「Arduino」や「Raspberry Pi」「ESP32」等多くのマイクロコントローラーをサポートしています。
「MicroPython」から派生したフレームワークで、対応しているマイクロコントローラーやライブラリが多く、より高度な機能を扱うことができます。
このため「MicroPython」で「Python」言語自体に慣れてきたら「CircuitPython」に移行することで、より高度な制御を体験することができます。
その他にも、使用方法には以下の大きな違いがあります。
・USBメモリのように認識される
「CircuitPython」の開発環境の特徴は、マイコンボードをパソコンと接続した時にUSBメモリのように認識されて、マイコンボード内のデータを操作できることです。
「PicoW」に「CircuitPython」のファームウェアを書き込んでパソコンと接続すると「CIRCUITPY」というフォルダが認識されます。これを開くと以下のようなファイルが確認できます。
ファイルの内容は以下のようになります。
- boot_out.txt:「CircuitPython」のバージョンやマイクロコントローラーの情報、MACアドレス等の情報が確認できます。
- code.py:このファイルに「CircuitPython」のプログラムを記入することで実行できます。
- lib:ライブラリ保存フォルダ。プログラムを実行するために必要なライブラリを保存しておきます。
- settings.toml:Ver8から導入された、環境変数設定ファイルです。Wi-Fi接続情報(SSID、パスワード)やAPIキー等を設定して、このファイルから読み込むことで、メインのプログラムから分離することができます。
・環境変数設定ファイル「setting.toml」について(Ver.8以降)
環境設定ファイル「setting.toml」は環境変数を設定しておくためのファイルで「CircuitPython」のバージョン8.0.0から導入されました。
詳細は以下リンク先の「Adafruit社」のサイトを参照してください。
「setting.toml」は「PicoW」のルートフォルダに配置されており、このファイルに変数としてWi-Fi接続情報(SSID、パスワード)等を設定しておくことで、メインのプログラムから読み込んで使用することができます。
4.「基本編」Wi-Fi接続、遠隔操作&表示
「基本編」はシンプルなWi-Fi通信による、サーバーを使用した遠隔操作とデータ表示の方法を確認します。
開発環境「Thonny」の準備がまだの方は、以下リンクを参照してインストールしてください。
・動作紹介
「Thonny」を起動して、この下の「サンプルプログラム」をコピペして実行すると下画像のように「シェル」部にIPアドレスが表示されます。
表示されたIPアドレスをクリックするか、ブラウザのアドレスバーに「IPアドレス」を入力してアクセスすると、Webページが読み込まれ、以下のように表示されます。
ブラウザ上にはボタンが2つあり、ボタンを押すとそれぞれ以下のような動作になります。
- [Light on]ボタン:「IPアドレス/lighton?」でサーバーにリクエストを送信し、サーバーがこれを受信した場合は本体LEDを点灯させ、LEDの状態変数「state」を「’ON’」にします。
- [Light off]ボタン:「IPアドレス/lightoff?」でサーバーにリクエストを送信し、サーバーがこれを受信した場合は本体LEDを消灯させ、LEDの状態変数「state」を「’OFF’」にします。
「PicoW」へのアクセスが成功して、ブラウザ上の各ボタンを操作すると「シェル」部には下画像のように通信結果が表示されていきます。
通信結果に表示されている「IPアドレス(画像では192.168.0.8)」はアクセスしてきたクライアントの「IPアドレス」です。
「”GET 〜”」にはクライアントからのリクエストアドレスが表示されます。横の数値はリクエスト時のデータ量です。
「”200 OK”」は通信成功を表します。横の数値はレスポンス時のデータ量です。
・サンプルプログラム(コピペ)
「基本編」のサンプルプログラムは以下になります。コピペで貼り付けて実行してください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでもコピーできます。
import socketpool # TCP/IP接続用のソケット管理用
import wifi # WiFi接続を管理用
import digitalio # デジタルピンの入出力を制御用
from board import * # マイクロコントローラーのボード定義から全てのピンをインポート
import microcontroller # マイクロコントローラーに関する情報(CPU温度等)を取得
from adafruit_httpserver import Server, Request, Response # HTTPサーバー用ライブラリ
led = digitalio.DigitalInOut(LED) # 本体LEDをGPIO端子に割り当て
led.direction = digitalio.Direction.OUTPUT # LED端子を出力に設定
# グローバル変数
state = "OFF!" # 本体LED状態格納用
# Wi-FiアクセスポイントのSSIDとパスワードを設定(直接指定する場合)
ssid = "自宅のネットワーク環境のSSIDを設定" # Wi-Fi接続先SSID
password = "自宅のネットワーク環境のパスワードを設定" # Wi-Fi接続先パスワード
port_num = 80 # ポート番号(標準は80)
# Wi-Fi接続を実行
wifi.radio.connect(ssid, password) # 指定したSSIDとパスワードで接続
print("Connected to", ssid) # 接続先SSID表示
# ソケットプールを作成してHTTPサーバーを起動するための準備
pool = socketpool.SocketPool(wifi.radio) # Wi-Fi接続上でソケットを管理するためのオブジェクトを作成
server = Server(pool, "/static", debug=True) # サーバー起動時にPicoWのルートディレクトリからデータを提供できるようにする
# Webページを準備
def webpage():
temperature = microcontroller.cpu.temperature # 本体温度センサの温度取得
temperature = "{:.1f}".format(temperature) # 温度の値を小数点1桁に成形
# HTMLコードを文字列として埋め込み、「f""" 〜 """」で囲むと{ }で囲った変数の値を埋め込める
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 {state}</p>
<p>Temperature is {temperature}</p>
</body>
</html>
"""
return str(html) # HTMLコードを文字列として返す
# ルート(IPアドレス:ポート)アクセス時に実行される関数(トップページ表示、ポート80なら省略可)
@server.route("/")
def base(request: Request):
html = webpage() # WebページのHTMLコードを取得
return Response(request, html, content_type="text/html")
# 本体LED点灯(IPアドレス:ポート/lighton)アクセス時に実行される関数(ポート80なら省略可)
@server.route("/lighton")
def light_on(request: Request): # HTTPリクエストに応答する関数を定義
global state # グローバル変数の使用
state = "ON!" # 文字列「ON!」を格納
led.value = True # LEDを点灯
html = webpage() # WebページのHTMLコードを取得
return Response(request, html, content_type="text/html")
# 本体LED消灯(IPアドレス:ポート/lightoff)アクセス時に実行される関数(ポート80なら省略可)
@server.route("/lightoff")
def light_off(request: Request): # HTTPリクエストに応答する関数を定義
global state # グローバル変数の使用
state = "OFF!" # 文字列「ON!」を格納
led.value = False # LEDを消灯
html = webpage() # WebページのHTMLコードを取得
return Response(request, html, content_type="text/html")
# HTTPサーバーを開始して待ち受けるIPアドレスを表示する
print(f"Listening on http://{wifi.radio.ipv4_address}:{port_num}") # f文字列を使って「IPアドレス」と「ポート番号」を埋め込んで表示
server.serve_forever(str(wifi.radio.ipv4_address), port=port_num) # HTTPサーバーを指定された「IPアドレス」と「ポート」で開始
・プログラムの詳細
Wi-Fi接続方法から、サーバー機能を利用した遠隔操作、データ表示をする方法を、サンプルプログラムから抜粋して詳しく紹介します。
Wi-Fi接続手順まではサンプルプログラムの「基本編」と「応用編」で同じで、以下のようになります。
まずは必要なライブラリをインポートします。
Wi-Fi接続に必要な「socketpool」と「wifi」ライブラリ、「PicoW」本体のLED制御と本体温度測定用の「digitalio」「board」「microcontroller」ライブラリをインポートします。
「httpサーバー」を開始するために必要な「adafruit_httpserver」ライブラリは、別途「Adafruit社」のホームページからダウンロードして「PicoW」本体の「libフォルダ」に保存しておきます。
import socketpool # TCP/IP接続用のソケット管理用
import wifi # WiFi接続を管理用
import digitalio # デジタルピンの入出力を制御用
from board import * # マイクロコントローラーのボード定義から全てのピンをインポート
import microcontroller # マイクロコントローラーに関する情報(CPU温度等)を取得
from adafruit_httpserver import Server, Request, Response # HTTPサーバー用ライブラリ
「Adafruit社」のライブラリは以下のリンクからダウンロードできます。
最新のファームウェアをインストールした場合のライブラリはバージョン「8.x」になります。
「Adafruit社」のライブラリのダウンロードから保存方法は以下のリンクで詳しく紹介しています。
次に「PicoW」本体のLEDを使用できるようにGPIO端子の設定を以下のように行います。
# 本体LED設定
led = digitalio.DigitalInOut(LED) # 本体LEDをGPIO端子に割り当て
led.direction = digitalio.Direction.OUTPUT # LED端子を出力に設定
LEDの「ON/OFF」状態を格納するためのグローバル変数を以下のように準備します。
# グローバル変数
state = "OFF!" # 本体LED状態格納用
Wi-Fi接続を行うためには以下のように設定します。
以下コードの「2,3行目」には、ご自宅のWi-Fi環境の「SSID」と「パスワード」を設定する必要があります。
# Wi-FiアクセスポイントのSSIDとパスワードを設定(直接指定する場合)
ssid = "自宅のネットワーク環境のSSIDを設定" # Wi-Fi接続先SSID
password = "自宅のネットワーク環境のパスワードを設定" # Wi-Fi接続先パスワード
port_num = 80 # ポート番号(標準は80)
# Wi-Fi接続を実行
wifi.radio.connect(ssid, password) # 指定したSSIDとパスワードで接続
print("Connected to", ssid) # 接続先SSID表示
# ソケットプールを作成してHTTPサーバーを起動するための準備
pool = socketpool.SocketPool(wifi.radio) # Wi-Fi接続上でソケットを管理するためのオブジェクトを作成
server = Server(pool, "/static", debug=True) # サーバー起動時にPicoWのルートディレクトリからデータを提供できるようにする
設定した内容でWi-Fi接続を実行し、httpサーバーを起動するための「ソケット」を開きます。
以上がWi-Fi接続を行うための手順です。
次にブラウザで表示するWebページを以下のように準備しておきます。
「HTMLコード」を文字列として変数に格納します。この時に文字列を「””” 〜 “””」のように「”””」で囲むと改行を無視して1つの文字列として扱うことができます。
さらに「f “”” 〜 “””」のように「f」をつけることで、文字列内で中括弧{ }で囲った変数の値を文字列として埋め込むことができるようになります。
ここではLEDの「ON/OFF」状態を格納する変数「state」と本体温度を格納する変数「temperature」をページ内に埋め込んでいます。
本体温度は先に取得して文字列に埋め込むようにしています。
# Webページを準備
def webpage():
temperature = microcontroller.cpu.temperature # 本体温度センサの温度取得
temperature = "{:.1f}".format(temperature) # 温度の値を小数点1桁に成形
# HTMLコードを文字列として埋め込み、「f""" 〜 """」で囲むと{ }で囲った変数の値を埋め込める
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 {state}</p>
<p>Temperature is {temperature}</p>
</body>
</html>
"""
return str(html) # HTMLコードを文字列として返す
次に指定のアドレスにリクエストがあったときに実行する関数を各アドレスごとに以下のように設定します。
# ルート(IPアドレス:ポート)アクセス時に実行される関数(トップページ表示、ポート80なら省略可)
@server.route("/")
def base(request: Request):
html = webpage() # WebページのHTMLコードを取得
return Response(request, html, content_type="text/html")
# 本体LED点灯(IPアドレス:ポート/lighton)アクセス時に実行される関数(ポート80なら省略可)
@server.route("/lighton")
def light_on(request: Request): # HTTPリクエストに応答する関数を定義
global state # グローバル変数の使用
state = "ON!" # 文字列「ON!」を格納
led.value = True # LEDを点灯
html = webpage() # WebページのHTMLコードを取得
return Response(request, html, content_type="text/html")
# 本体LED消灯(IPアドレス:ポート/lightoff)アクセス時に実行される関数(ポート80なら省略可)
@server.route("/lightoff")
def light_off(request: Request): # HTTPリクエストに応答する関数を定義
global state # グローバル変数の使用
state = "OFF!" # 文字列「ON!」を格納
led.value = False # LEDを消灯
html = webpage() # WebページのHTMLコードを取得
return Response(request, html, content_type="text/html")
最後に取得された「IPアドレス」と設定した「ポート番号」で「HTTPサーバー」を開始します。
(ポート指定は省略可。この場合はポート80となります。)
# HTTPサーバーを開始して待ち受けるIPアドレスを表示する
print(f"Listening on http://{wifi.radio.ipv4_address}:{port_num}") # f文字列を使って「IPアドレス」と「ポート番号」を埋め込んで表示
server.serve_forever(str(wifi.radio.ipv4_address), port=port_num) # HTTPサーバーを指定された「IPアドレス」と「ポート」で開始
以上で「PicoW」が「HTTPサーバー」として機能し、クライアントからのリクエストを常に待ち受ける状態になります。
リクエストがあった場合は設定した処理を実行し、所得したデータで更新された「htmlコード」をレスポンスとして返します。
5.「応用編」Wi-Fi接続、遠隔操作&表示
「基本編」ではデータの表示を更新するためにページの更新をする必要がありました。
「応用編」ではページの更新をせずにデータの更新をすることができます。
これには「JavaScript」の「FetchAPI」を使用します。
・動作紹介
動作については「基本編」と同じように、この下の「サンプルプログラム」を「Thonny」にコピペして実行すると、シェル部に「IPアドレス(下画像では192.168.0.13:80)」が表示されます。
この「IPアドレス(上画像では192.168.0.13:80)」をクリックするか、ブラウザのアドレスバーに入力すると、以下のようなページが表示されます。
・サンプルプログラム(コピペ)
「応用編」のサンプルプログラムは以下になります。コピペで貼り付けて実行してください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでもコピーできます。
import socketpool # TCP/IP接続用のソケット管理用
import wifi # WiFi接続を管理用
import digitalio # デジタルピンの入出力を制御用
from board import * # マイクロコントローラーのボード定義から全てのピンをインポート
import microcontroller # マイクロコントローラーに関する情報(CPU温度等)を取得
from adafruit_httpserver import Server, Request, Response # HTTPサーバー用ライブラリ
led = digitalio.DigitalInOut(LED) # 本体LEDをGPIO端子に割り当て
led.direction = digitalio.Direction.OUTPUT # LED端子を出力に設定
# Wi-FiアクセスポイントのSSIDとパスワードを設定(直接指定する場合)
ssid = "自宅のネットワーク環境のSSIDを設定" # Wi-Fi接続先SSID
password = "自宅のネットワーク環境のパスワードを設定" # Wi-Fi接続先パスワード
port_num = 80 # ポート番号(標準は80)
# Wi-Fi接続を実行
wifi.radio.connect(ssid, password) # 指定したSSIDとパスワードで接続
print("Connected to", ssid) # 接続先SSID表示
# ソケットプールを作成してHTTPサーバーを起動するための準備
pool = socketpool.SocketPool(wifi.radio) # Wi-Fi接続上でソケットを管理するためのオブジェクトを作成
server = Server(pool, "/static", debug=True) # サーバー起動時にPicoWのルートディレクトリからデータを提供できるようにする
# Webページを準備(HTMLコードを文字列として埋め込む)
def webpage():
html = """
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>PicoW Controller</title>
<style>
#container {display: flex;justify-content: center;align-items: center;flex-direction: column;margin-top: 50px;}
h1 {color: #666;}
.button {width: 100px;height: 50px;border-radius: 5px;margin: 10px;cursor: pointer;font-size: 20px;font-weight: bold;color: white;text-align: center;line-height: 50px;}
#on-button {background-color: green;}
#off-button {background-color: red;}
input[type="text"] {width: 200px;padding: 5px;font-size: 20px;text-align: center;margin: 20px;}
</style>
</head>
<body>
<div id="container">
<h1>PicoW Controller</h1>
<hr>
<div>
<button id="on-button" class="button">ON</button>
<button id="off-button" class="button">OFF</button>
</div>
<div><p id="led_state"> </p></div>
<input type="text" placeholder="Temperature" />
</div>
<script>
const onButton = document.getElementById("on-button");
const offButton = document.getElementById("off-button");
const ledState = document.getElementById("led_state");
const textBox = document.querySelector("input[type='text']");
onButton.addEventListener("click", async () => {
const response = await fetch("/lighton");
const text = await response.text();
ledState.textContent = text;
console.log(text);
});
offButton.addEventListener("click", async () => {
const response = await fetch("/lightoff");
const text = await response.text();
ledState.textContent = text;
console.log(text);
});
setInterval(async () => {
const response = await fetch("/get_data");
const text = await response.text();
textBox.value = "本体温度:" + text;
}, 1000);
</script>
</body>
</html>
"""
return str(html)
# ルート(IPアドレス:ポート)アクセス時に実行される関数(トップページ表示、ポート80は省略可)
@server.route("/")
def base(request: Request): # HTTPリクエストを処理する関数を定義
html = webpage() # Webページのデータ取得して文字列で格納
return Response(request, html, content_type="text/html") # レスポンスとして「HTML」を返す
# 本体LED点灯(IPアドレス:ポート/lighton)アクセス時に実行される関数(ポート80なら省略可)
@server.route("/lighton")
def light_on(request: Request):
led.value = True # 本体LEDを点灯
return Response(request, "LED_ON!", content_type="text/plane") # レスポンスとして「テキスト」を返す
# 本体LED消灯(IPアドレス:ポート/lightoff)アクセス時に実行される関数(ポート80なら省略可)
@server.route("/lightoff")
def light_off(request: Request):
led.value = False # 本体LEDを消灯
return Response(request, "LED_OFF!", content_type="text/plane")
# 本体温度取得(IPアドレス:ポート/get_data)アクセス時に実行される関数(ポート80なら省略可)
@server.route("/get_data")
def get_data(request: Request):
temp = microcontroller.cpu.temperature # 本体温度センサの温度取得
temp = "{:.1f}".format(temp) # 温度の値を小数点1桁に成形
return Response(request, temp, content_type="text/plane")
# HTTPサーバーを開始して待ち受けるIPアドレスを表示する
print(f"Listening on http://{wifi.radio.ipv4_address}:{port_num}") # f文字列を使って「IPアドレス」と「ポート番号」を埋め込んで表示
server.serve_forever(str(wifi.radio.ipv4_address), port=port_num) # HTTPサーバーを指定された「IPアドレス」と「ポート」で開始
・プログラムの詳細
プログラムの詳細については「ライブラリ」のインポートと「Wi-Fi接続」までは「基本編」と同じです。「Webページの準備」からは以下のように異なります。
Webページは「基本編」と同様に文字列として変数に格納しますが、文字列の中に変数を埋め込む必要はないので「f “”” 〜 “””」ではなく「f」なしの「””” 〜 “””」を使用します。
# Webページを準備(HTMLコードを文字列として埋め込む)
def webpage():
html = """
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>PicoW Controller</title>
<style>
"""
中略(CSS)
"""
</style>
</head>
<body>
"""
中略(HTML)
"""
<script>
"""
中略(JavaScript)
"""
</script>
</body>
</html>
"""
return str(html)
次に以下のように「HTTPサーバー」の設定を行います。
まず、ルート(IPアドレス:ポート)に対してリクエストがあった時に「htmlコード」をレスポンスとして返します。
# ルート(IPアドレス:ポート)アクセス時に実行される関数(トップページ表示、ポート80は省略可)
@server.route("/")
def base(request: Request): # HTTPリクエストを処理する関数を定義
html = webpage() # Webページのデータ取得して文字列で格納
return Response(request, html, content_type="text/html") # レスポンスとして「HTML」を返す
その他のリクエストに対しては、リクエストアドレスごとに以下のように実行する処理を設定し、それぞれの動作に応じた「テキスト(文字列)」をレスポンスとして返します。
# 本体LED点灯(IPアドレス:ポート/lighton)アクセス時に実行される関数(ポート80なら省略可)
@server.route("/lighton")
def light_on(request: Request): # HTTPリクエストを処理する関数を定義
led.value = True # 本体LEDを点灯
return Response(request, "LED_ON!", content_type="text/plane") # レスポンスとして「テキスト」を返す
# 本体LED消灯(IPアドレス:ポート/lightoff)アクセス時に実行される関数(ポート80なら省略可)
@server.route("/lightoff")
def light_off(request: Request):
led.value = False # 本体LEDを消灯
return Response(request, "LED_OFF!", content_type="text/plane")
# 本体温度取得(IPアドレス:ポート/get_data)アクセス時に実行される関数(ポート80なら省略可)
@server.route("/get_data")
def get_data(request: Request):
temp = microcontroller.cpu.temperature # 本体温度センサの温度取得
temp = "{:.1f}".format(temp) # 温度の値を小数点1桁に成形
return Response(request, temp, content_type="text/plane")
最後は「基本編」と同様に以下のように「HTTPサーバー」を開始します。
# HTTPサーバーを開始して待ち受けるIPアドレスを表示する
print(f"Listening on http://{wifi.radio.ipv4_address}:{port_num}") # f文字列を使って「IPアドレス」と「ポート番号」を埋め込んで表示
server.serve_forever(str(wifi.radio.ipv4_address), port=port_num) # HTTPサーバーを「IPアドレス」と設定した「ポート」で開始
以上で「PicoW」が「HTTPサーバー」として機能し、クライアントからのリクエストを常に待ち受ける状態になります。
リクエストがあった場合は設定した処理を実行し、設定したデータをレスポンスとして返します。
クライアント側が受信したレスポンスは「JavaScript」で処理され、Webページを書き換えることで表示を更新します。
6.本体に別ファイルで保存したWebページを読み込む方法
サンプルプログラムの「応用編」のようにWebページの「HTMLコード」が長くなる場合は、別ファイルとして保存しておいた方がプログラムが見やすく、編集もしやすくなるので、この方法も紹介します。
・Thonnyを使用したファイルの保存、実行方法
開発環境「Thonny」を使用した方法を以下のように順を追って紹介していきます。
まずは「CircuitPython」のファームウェアを書き込んだ「PicoW」をパソコンと接続して「Thonny」を起動すると上画像のように[untitled]タブが表示されます。
[untitled]タブのところに、この下で紹介している「Pythonサンプルプログラム」をコピペで貼り付けて、上画像のように[保存]ボタンをクリックします。
上画像のように保存先を確認するウインドウが表示されるので[Raspberry Pi Pico]の方をクリックします。
上画像のように「PicoW」内のルートディレクトリの内容が表示されるので、この中から[code.py]を選択して[OK]ボタンをクリックして上書き保存します。
次に上画像のように「新規ファイル」ボタンをクリックします。
新規で[untitled]タブでファイルが作成されるのでここに、この下で紹介している「HTMLサンプルプログラム」をコピペで貼り付けます。
上画像のようにHTMLコードを貼り付けたら[保存]ボタンをクリックします。
保存先は[Raspberry Pi Pico]の方を選択します。
上画像のように「PicoW」内のルートディレクトリの内容が表示されたら、「ファイル名:」の欄に「index.html」と入力して[OK]ボタンをクリックして保存します。
次に、今回はWi-Fi接続のための「SSID」と「パスワード」も外部設定ファイル「setting.toml」から読み込んでいますので、この方法も紹介します。
上画像のように[ファイルを開く]ボタンをクリックします。
[Raspberry Pi Pico]を選択して「PicoW」内のルートディレクトリの内容を表示させます。
上画像のように表示されたら、環境変数設定ファイル「setting.toml」を選択して[OK]ボタンを押します。
上画像のように「setting.toml」ファイルが開かれますが、初期状態は何も記入されていません。
ここにプログラムに読み込みたい値を変数として設定していきます。
今回はWi-Fi接続のための「SSID」と「パスワード」を以下のように設定しているため、以下のコードをコピペして貼り付けてください。
# setting.tomlにWi-Fi接続「SSID」と「パスワード」を設定
CIRCUITPY_WIFI_SSID="自宅のネットワーク環境のSSIDを設定"
CIRCUITPY_WIFI_PASSWORD="自宅のネットワーク環境のパスワードを設定"
上画像のようにコピペして貼り付けたら、黄色の下線部2箇所をご自宅のWi-Fi通信環境に合わせて書き換えてから「保存」ボタンをクリックします。
これで全ての設定が完了しました。
上画像のように[code.py]タブをクリックして、[現在のスクリプトを実行]ボタンをクリックします。
上画像のようなエラーが表示される場合はライブラリが不足しています。
以下のリンクを参考に「Adafruit社」の「adafruit_httpserver」ライブラリを「PicoW」本体の「libフォルダ」保存してください。
ライブラリの保存方法は以下のリンクで詳しく紹介しています。
エラーが発生せずに実行されると上画像のように[シェル]部にIPアドレスでリンクが表示されるのでこれをクリックします。
ブラウザが起動し上画像のような画面が表示されます。
「ON/OFF」ボタンを押すと「PicoW」の本体LEDが「点灯/消灯」し、その下にLEDのON/OFF状態が表示されます。
一番下には「PicoW」本体の温度が1秒ごとに更新されて表示されます。
以上がWebページのデータを外部ファイルから読み出す方法です。
・Pythonサンプルプログラム(コピペ)
Webページを別ファイルから読み出すための「Python」プログラムは以下のようになります。
サンプルプログラムは以下になります。コピペで貼り付けて実行してください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでもコピーできます。
import os # ファイル操作など、OSレベルの機能を提供するために使用
import socketpool # TCP/IP接続用のソケット管理用
import wifi # WiFi接続を管理用
import digitalio # デジタルピンの入出力を制御用
from board import * # マイクロコントローラーのボード定義から全てのピンをインポート
import microcontroller # マイクロコントローラーに関する情報(CPU温度等)を取得
from adafruit_httpserver import Server, Request, Response, FileResponse # HTTPサーバー用ライブラリ
led = digitalio.DigitalInOut(LED) # 本体LEDをGPIO端子に割り当て
led.direction = digitalio.Direction.OUTPUT # LED端子を出力に設定
# グローバル変数
state = "OFF!" # 本体LED状態格納用
# Wi-FiアクセスポイントのSSIDとパスワードを取得(setting.tomlから取得する場合)
ssid = os.getenv("CIRCUITPY_WIFI_SSID") # Wi-Fi接続先SSID
password = os.getenv("CIRCUITPY_WIFI_PASSWORD") # Wi-Fi接続先パスワード
port_num = 80 # ポート番号(標準は80)
# Wi-Fi接続を実行
wifi.radio.connect(ssid, password) # 指定したSSIDとパスワードで接続
print("Connected to", ssid) # 接続先SSID表示
# ソケットプールを作成してHTTPサーバーを起動するための準備
pool = socketpool.SocketPool(wifi.radio) # Wi-Fi接続上でソケットを管理するためのオブジェクトを作成
server = Server(pool, "/static", debug=True) # サーバー起動時にPicoWのルートディレクトリからデータを提供できるようにする
# ルート(IPアドレス:ポート)アクセス時に実行される関数(トップページ表示、ポート80は省略可)
@server.route("/")
def base(request: Request): # HTTPリクエストを処理する関数を定義
return FileResponse(request, filename='index.html', root_path='/') # レスポンスとして「index.html」ファイルを返す
# 本体LED点灯(IPアドレス:ポート/lighton)アクセス時に実行される関数(ポート80なら省略可)
@server.route("/lighton")
def light_on(request: Request):
led.value = True # 本体LEDを点灯
return Response(request, "LED_ON!", content_type="text/plane") # レスポンスとして「テキスト(文字列)」を返す
# 本体LED消灯(IPアドレス:ポート/lightoff)アクセス時に実行される関数(ポート80なら省略可)
@server.route("/lightoff")
def light_on(request: Request):
led.value = False # 本体LEDを消灯
return Response(request, "LED_OFF!", content_type="text/plane")
# 本体温度取得(IPアドレス:ポート/get_data)アクセス時に実行される関数(ポート80なら省略可)
@server.route("/get_data")
def get_data(request: Request):
temp = microcontroller.cpu.temperature # 本体温度センサの温度取得
temp = "{:.1f}".format(temp) # 温度の値を小数点1桁に成形
return Response(request, temp, content_type="text/plane")
# HTTPサーバーを開始して待ち受けるIPアドレスを表示する
print(f"Listening on http://{wifi.radio.ipv4_address}:{port_num}") # f文字列を使って「IPアドレス」と「ポート番号」を埋め込んで表示
server.serve_forever(str(wifi.radio.ipv4_address), port=port_num) # HTTPサーバーを指定された「IPアドレス」と「ポート」で開始
・HTMLサンプルプログラム(コピペ)
「Python」から読み出すWebページのプログラムは以下のようになります。
ファイル名は「index.html」として「PicoW」本体のルートディレクトリに保存してください。
サンプルプログラムは以下になります。コピペで貼り付けて実行してください。
※下コード(黒枠)内の右上角にある小さなアイコンのクリックでもコピーできます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PicoW Controller</title>
<style>
#container {display: flex;justify-content: center;align-items: center;flex-direction: column;margin-top: 50px;}
h1 {color: #666;}
.button {width: 100px;height: 50px;border-radius: 5px;margin: 10px;cursor: pointer;font-size: 20px;font-weight: bold;color: white;text-align: center;line-height: 50px;}
#on-button {background-color: green;}
#off-button {background-color: red;}
input[type="text"] {width: 200px;padding: 5px;font-size: 20px;text-align: center;margin: 20px;}
</style>
</head>
<body>
<div id="container">
<h1>PicoW Controller</h1>
<hr>
<div>
<button id="on-button" class="button">ON</button>
<button id="off-button" class="button">OFF</button>
</div>
<div><p id="led_state"> </p></div>
<input type="text" placeholder="Temperature" />
</div>
<script>
const onButton = document.getElementById("on-button");
const offButton = document.getElementById("off-button");
const ledState = document.getElementById("led_state");
const textBox = document.querySelector("input[type='text']");
onButton.addEventListener("click", async () => {
const response = await fetch("/lighton");
const text = await response.text();
ledState.textContent = text;
console.log(text);
});
offButton.addEventListener("click", async () => {
const response = await fetch("/lightoff");
const text = await response.text();
ledState.textContent = text;
console.log(text);
});
setInterval(async () => {
const response = await fetch("/get_data");
const text = await response.text();
textBox.value = "本体温度:" + text;
}, 1000);
</script>
</body>
</html>
7.動作確認用のWebページの作成はChatGPTにおまかせ
以下は「MicroPython」の時にもやった「JavaScript」を使用したWebページを「ChatGPT」に書いてもらったものです。
質問の仕方によっては1回で目的の動作をするコードを書いてくれます。
今回使用した「応用編」のサンプルプログラムのWebページは以下の質問でほぼ同じものを書いてくれるので試してみましょう。
「ChatGPT」への質問は以下のように行いました。
「ChatGPT」の回答は以下のようになりました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>LEDコントロールパネル</title>
<style>
body {
text-align: center; /* このCSSだけ後から追加 */
}
button {
display: inline-block;
padding: 10px 20px;
font-size: 16px;
border-radius: 5px;
cursor: pointer;
}
button.on {
background-color: green;
color: white;
}
button.off {
background-color: red;
color: white;
}
p#led-state {
margin-top: 20px;
font-size: 18px;
}
</style>
</head>
<body>
<div style="display:flex; justify-content:center;">
<button id="on-button" class="on">ON</button>
<button id="off-button" class="off">OFF</button>
</div>
<p id="led-state"></p>
<div style="margin-top:20px; display:flex; justify-content:center;">
<label for="temperature-box">温度表示:</label>
<input type="text" id="temperature-box">
</div>
<script>
const onButton = document.querySelector('#on-button');
const offButton = document.querySelector('#off-button');
const ledStatePara = document.querySelector('#led-state');
const tempBox = document.querySelector('#temperature-box');
onButton.addEventListener('click', () => {
fetch('/lighton')
.then(response => response.text())
.then(data => {
ledStatePara.textContent = data;
console.log(data);
});
});
offButton.addEventListener('click', () => {
fetch('/lightoff')
.then(response => response.text())
.then(data => {
ledStatePara.textContent = data;
console.log(data);
});
});
setInterval(() => {
fetch('/get_data')
.then(response => response.text())
.then(data => {
tempBox.value = data;
});
}, 1000);
</script>
</body>
</html>
以上のような回答になりました。
このコードを「応用編」のサンプルプログラムの「webpage()関数」の中の「html = ”'” 〜 “””」の中で指定した文字列と置き換えるか、別ファイルとして読み込む場合はそのまま「index.html」として保存して実行すると、以下のようなWebページが表示されます。
残念ながら「LED_ON!」の表示だけ左端に表示されたため、上コードの中の「 7〜9行目」の「CSS」だけ後から追加しています。
修正したものを実行すると下画像のようになり、思い通りのWebページになり問題なく動作しました。
ChatGPTを使用したプログラミングについては、以下のリンクで紹介しています。
8.まとめ
「CircuitPython」でWi-Fi通信のサーバー機能を使用した、ブラウザからの遠隔操作、データ監視の方法を詳しく紹介しました。
「MicroPython」よりもWi-Fi接続からサーバー設定までの流れがわかりやすく、レスポンスに対しての動作もデコレーターで関数ごとにまとめられるため、見やすくてプログラムの作成も編集もやりやすいのではと思います。
今回「MicroPython」に続けて「CircuitPython」で実装しましたが、ここでやった方法で比較すると「CircuitPython」の方が使いやすいと感じました。
「CircuitPython」の特徴である、内部データをUSBメモリのようにフォルダで開いて操作できるため、Webページ用の「HTMLファイル」を単独で作成し保存、編集ができるためプログラミング効率が良いと思います。
「JavaScript」や「CSS」がより複雑になる場合は、これらも別ファイルとして分離させるとさらに効率は上がると思います。
動作確認用のブラウザページ(html、JavaScript、CSS)は「ChatGPT」にお任せしてしまえば、ある程度のものは書いてくれるため、動作確認しながら、質問の仕方を身につけて、Webページ作成のスキルも身につけていきましょう。
コメント
お邪魔いたします
(6)まで、試しました。
circuitpythonでの実行は初めてです。
他のページでMicroPythonでの例題はあったので、
試しては、いましたが・・・その後
私の環境ではMicroPythonではライブラリのinstallが
出来ない問題があり、後は全てcircuitpythonでの
試行になりました。
それにしても、Wifiに接続出来ると、こんな事も
出来るのですね。双方向・・
インタラクティブ(わっ かっこいい)な事も
出来る、面白いですね。
先の、htmlに付いては、まだ課題が、大きすぎて
時間がかかりそうです、
一冊、参考書は手元に有るのですが、
開いた時は、なかなか難しく読み進められませんでした :)
積ん読状態になってます :)
ありがとうございます
またまたこんばんわ^^
(6)まで進めば、ほぼ制覇してますね!ペースが早い!
htmlについては(7)でも紹介してますが「ChatGPT」に丸投げでいいかと思います。
ある程度の基礎や仕組みの理解はしておいた方がいいですが、聞き方さえわかればほぼ書いてくれるのであとはコピペです。
私も参考書は苦手で、買って満足した参考書がいっぱいw
難しいことは「ChatGPT」のお任せしましょう♪
お答え ありがとうございます。
「ChatGPT」は、私には まだ、まだ先のことであります。
でも
「GoogleのBard」 「Bard」 鳥かと思ったら鳥とは
綴りか違いました :)
『吟遊詩人』ですって!すごい、ネームングです。
少しセンスを感じます。
情報のリテラシー、選択眼がますます、大事に成ってきましたね
しかし、良く出来ています。
聴き方がありますが、割と、まともに返してくれます。
検索ボックスのキーワードの
入れ方が変わって来ましたよ。
すごい、世の中になりましたね。
AIがプログラミングしてくれるなんて!
もう、願ったり!叶ったり! ですが・・・
[ Selenium ]で何とか
JCBA傘下の局に、簡単にアクセス出来ないかと
(全国コミュニュティFM放送局連盟?)
探ぐって観ましたが、
ラズパイのChromiumは遅すぎて
フォーカスが合わないみたいか?上手く活きませんでした。
局の再生ボタンが「深くて」ストレートに到達
出来ないいんです。
北海道~九州の局まで数局聴くのですが
ちょっとアクセスが面倒なんです。
昔は、ミュージックバードから
ラズパイで簡単に直に聴けたのですが
ラジコと同じで、『途中でお金を抜く組織』?が
介在するようになって、面倒です。 :)
PC上では、出来るかも知れませんが。
ラズパイで挫折のままです。 :)
今はPicoの時間が多くなっています。
ありがとう ございまっす。
こんばんわ^^
htmlなら「Bard」でもそれなりに書いてくれると思いますよ。
「selenium」は私は使ったことありませんが、人が使ってるのを見た時はhtmlの要素(div、p、input、btton等)や
id、classがわかれば目的の場所を指定できるイメージでした。
chromeなら[その他ツール]→[デベロッパーツール]を表示して「要素」から目的の要素(button?)をコピペで「Bard」に貼り付けて
「この要素をseleniumでクリックする方法は?」のように聞けば書いてくれるのではないでしょうか?(想像ですが・・・)
picoでできるかどうかは謎ですw
しかし、いろんな使い方がありますね〜私はC言語が好きなんですけど、今はpythonですかね
私も時間ができたらやってみますね♪
お邪魔します :)
基本的過ぎて、恐縮ですが・・・・
I have a Question
私には、ちょっと、ややこしい。
scriptの枕ことばで
from import
こんな記述が良くアリマスネ。
これは
モジュールの中にある関数、変数を
ダイレクトに使えるようにしている。
注意点として、from importで関数を直接読み込んだ場合
モジュール内の他の関数は使えなくなります。
関数・変数を「指定」して使って居る為という。
ところが・・
この<関数・変数名>の箇所に
例えば
from random import *
の様に [ * ]を使って居る場合も有ります・・・
この場合は、
randomモジュール内の<関数・変数>は
指定しない、
つまり適宜このモジュールの
<関数・変数は>使えるものは、何でも使いますよ』ということ
でしょうか。?
丁度、ババ抜きのオールマイティ・カードの様に。
お教え下さい。
この辺の理解が遅れていて
エラーを、毎度、頂戴いたしております。:)
ありがとうございます
こんばんわ^^
pythonはあまり使い込んでませんので私の理解の範囲になりますが
CircuitPythonのboardモジュールを例にして動作確認してみるとわかりやすいのではないでしょうか?
基本的に以下2つは同じ動作が実現できます。
import board
from board import *
「*」はおっしゃる通りババ抜きのオールマイティカードのようなもので「ワイルドカード」と呼ばれ、「全て」という意味で使われます。
このため「from board import *」は「boardモジュール」の全てをインポートするということで「import board」と同じ意味を持ちます。
明確な違いは以下です。
「import board」の場合 : その後のコード作成の中で使用するもの全てに「board.〜」と書く必要がある。
「from board import *」の場合 : 「board.」を省略できる。
注意が必要なのは「*」を使用しない場合です。
例えば「from board import GP0」とした場合、GP0の端子は「board.」を省略して使用できますが、その他の端子は指定できなくなります。
もしGP1と書いた場合、内部的には「board.board.GP1」となるため「そんなものはない」と怒られます^^;。
GP1も使いたい場合は「from board import GP0 GP1」と書けば使えます。
「from 〜 import 〜」を使う場合はコードが省略できるので、可読性や作業性をあげたい時に使うと良いと思います。
また、コード内で使用する端子を先に明確にしておきたい場合や、限定してその端子しか使わせないようにしたい場合にも使用できると思います。
しかし、「from 〜 import 〜」と書いたことで、他の変数名や関数名と被ったりすると、これまたエラーになるため、
めんどくさくても「import」として、全部書くのが確実かもしれません。
この辺りはコードの規模を踏まえて、作業性や可読性を考慮しての判断となるので、状況によるかと思います。
・・・という私の理解ですが、ご参考までに^^
早速ですが訂正(汗)
私も動作確認してみたら以下の部分は間違いですね^^;
誤:「もしGP1と書いた場合、内部的には「board.board.GP1」となるため〜」
正:「もしGP1とかいても、boardモジュールの中のGP0しかインポートされていないため〜」
「from board import GP0 GP1」もカンマが抜けてますね(汗)
「from board import GP0, GP1」が正しいです。
失礼しました。
* の件
ありがとうございます。
私の質問の書き方も変でした・・・
from import
こう書いたつもりが、間違っていました、
申訳ありません、
でも、お聴きしたポイントは
ちゃんとお解り頂いたので、疑問が解けました:)
で、*は、オールマイティ・カードと同じ意味になる
これで、大分わかりました、
このアスタリスク付きの記述が時々有るので
たぶん、ソウかなとおもっていました、
こんな時間まで何を?ですが。。。。
4BでSSD起動起動が出来る記事を見たので
それを、試していたのですが、
私のところでは、usbメモリからも
ssdからも起動出来ませんでした、
ラズパイは、全てヘッドレス運用で
SSH接続です、どうも、ssh認証まで開きましたが
pwが通らず、結局、元のsdカードに戻しました。
ssdやusbメモリに直接Pi-OSを書き込んでいたので
時間がかかりました、初回起動時も時間がかかるので
かなり、同じ様な作業を繰り返していましたが、
成功はしませんでした。
また、Seleniumでは、chromeドライバを変に弄ってい
仕舞ったらしくブラウザのchromeがおかしくなり
吊られて、Microsoft Edge まで挙動がおかしくなり
かなり焦りましたが、PCの再起動で戻りました。
「Bard」も答えてくれましたが、こちらも上手く活きませんでした。
前に、1ヶ月間くらい、あれこれ試したんですが
大分、前で内容を忘れています。
ページの作りが複雑になっているらしく、
ポイントに当てられない!
Seleniumを使うと、
scriptでマウスやkeyboardからのアクションが代用出来る
と言うので、それなら
私がWebラジオを聴く時と同じで
シェルスクリプト・ファイルのファイル名入力で
選局出来る(局によっては、1文字+エンターで選局・再生する)
事と同じ様に成るはずと思い、やって観たかったのです。
この時、HTMLの参考書を買ったのですが
『痒いところに届かない』内容で、アマゾンからでしたが
書店で「品定め」後、購入すべきでした。
田舎で大きな書店は無いのです・・
情報はネットからのみです。
Sejeniumからの利用は
ダメでやりようがなかったので、これまでと思いすっかり忘れました。
そうで無くとも、忘れるのは一番得意です。:)
それや、これやで 今夜は 遅くなりました。
ありごとうございました。
あれ!
<>を使うと、消えますね!!
おはようございます^^
<>を使うと消えるのは、htmlタグとして認識されるからと思います。
夜遅くまで熱心ですね〜ラズパイ4BがSSDで起動できたらいいですね。
それで動作が早くなるなら、もう一度ラズパイ4Bやてみようかなとも思いますが・・・
1日中ほぼ設定作業で、何やってたんだろ〜な日々がつらすぎて、すっかり遠ざかってしまいました^^;
Webラジオの件は私に全く知識がなく、お力になれそうにないです(汗)
そういう世界もあるんだなと電子工作の奥深さを知りました。
先日の「XIAO RP2040」のOLED表示についてですが、届いたので動作確認してみました。
こちらではピン番号さえ合わせれば動くようです。
せっかく買ったので次の投稿は「XIAO RP2040」の紹介を予定してます。
OLEDを接続しておかないとエラーは出るようなので、その辺も踏まえて記事作成中です。
また見てください♪
お邪魔いたします
それは、楽しみです!!
===
私は「メモ帳」に[ Mery ]というアプリを使って居ます。
こちらのページにお邪魔するときも
この[ Mery ]に記述し読み返してから、
「コピーし」こちらのページに「貼り付け」ます。
それで、この前のお尋ねで、
from import
と記述した箇所が、このコメント・ページでは
『from import 』
になってました、という意味で、
<>を使うと消えると 申しあげました。
from モジュール名 import 関数・変数名
とすれば、
モジュール名 関数・変数名は 消えなかったかも知れませんが
このコメント・ページに<>を含んで
記述しそそれを貼り付けると< >の中の文字が消えていた」という
事でした。
判り難くて 面倒で、済みません。
あ、やっぱり 消えますね。
Mery の 問題かも知れません
面白いですね!
このページもhtmlでできてるので半角< >はタグとして認識されるため<br>と書けば
改行されたり
<strong>で囲むと強調されたりします。</strong>
ブラウザで確認しないと見た目は分かりませんけどね^^;
な~るほど!
そうなんですね!
では、私は迂闊に<や>は使わない方が、まごつかなく済みそうです:)
失礼いたしました。
ありがとうございます。
PCでSeleniumを使って、Googleの検索ページまでは
開ける様になりました。
一歩前進でです、:)
もっとも、ここまでの手法は、ネットで良く
紹介されています。
実行ファイル.pyを書き、任意の場所に保存し
PowerShellを開いてプロンプトに続いて
python 実行fileのアドレス\実行file.py
でOK。
これは、私がWebラジオを聴くときと全く同じ手法でした。
どうやるのかと思っていたら、解ってしまうと
『な~~んだ!そうだったのか!』でした:)
同じ、Python ですもの!
しかし、Windowsの中で特別の手続きもせずにPythonが動くのが、
なんだが不思議です :)
PythonにもPATHを通してあるからなのでしょうか?
たしか、以前も「Googleの検索ページを開く」まででは
出来ましたが、
JCBAの方は、
まだ、まだ、肝心の的をクリックさせられない。
Bard が自信満々にくれるscriptは、私の聴き方が悪いのか
試すと、全くダメです。
まあ、1行1行ネットで教えてもらいながらです。
ラズパイではヘッドレス運用なので tera turm を使い
コンソールも当然 tera turm の黒い画面に入力します、
動作が遅いと言う事は、全く無いのですが
PCではPowerShellに打ち込んでいますが、これがまた、
プロンプロが出るまでに時間がかかります。
ショートカットでPowerShellは直ぐに「開きはします」が
入力出来る状態には15~20秒位待たされます。
何をやっても時間がかかるので、20秒やそこら
どうってこと無いのですが・・・ でも「遅い」!
検索したら、PowerShellを速く開く方法があると言うので
早速、そのファイルをPowerShellで実行して見ましたが
変化は無かったです。:)
PCは、Windows11 Home 23H2
(インサイダーβ版) PowerSellは最新Ver.です
なお、実行ファイル.pyを置いたディレクトリにPATHを
通しましたが。。そのつもりなのですが・・・
通らない!
環境変数のPATHの項目に、私が追加したディレクトリ・アドレスは
表示されています。:)
パスが通っていなくとも
実行時に 絶対パスで記述すれば、実行されるので
タイピングの練習(コピペになりますが)と思って
打ち込めば良いのですが・・
失礼しました
seleniumに関しては知識が無いのでお力になれそうにありません^^;
やってみようかと思いましたがchromeDriverのインストール等、環境づくりがいるようなので
また時間ができた時に・・・
PowerShellの動きが遅いのは何でしょうね?それは経験したことがありません。
pythonの実行は実行フォルダに「cd /path」で移動してから行うので
特にパスを通して実行したこともないです。
エディタはVSCodeを使用しているので、基本的に開発環境はエディタにお任せです。
VSCodeは何でもできる万能エディタなのでPowerShellもいりません。
「Mery」と併用でも良いので導入を検討してみてはいかがでしょう?