2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RaspberryPi PicoをUSB接続の温度センサーにして定期的に温度を測定するプログラムをつくる

Last updated at Posted at 2024-10-31

あらすじ

以前作ったコードをchatGPT o1-previewに書き直してもらったらずいぶんよくなったので改めて記事を作成した。どうもinput()ではなく sys.stdin.readline()でコマンドを読み取ると良いらしい。素人にはinput関数がどうやってserialのバッファを取得してるのかが分からなかったので、こういう大して難しくなさそうなのに地味でマイナーすぎてぐぐっても解決策がみつからない類の問題をサクッと解決してくれるchatGPT様には足を向けて寝られない。あと4oよりo1-preの方が明らかに頭がいい。

RaspberryPiPico側のコード

今回は基板に内臓されている温度センサーの値を取得してるけどGPIOピンからセンサーの値を取得したりモーター等を動かしたりすることもできる。1分に1回程度動作する環境制御機器を想定しているのでレスポンスの速さは確かめていない。

main.py
import machine
import utime
import sys

def read_temperature():
    sensor_temp = machine.ADC(4)
    reading = sensor_temp.read_u16()
    voltage = reading * 3.3 / 65535
    temperature = 27 - (voltage - 0.706) / 0.001721
    return temperature

print("Waiting for commands...")

while True:
    # コマンドをブロッキングで読み取る
    command = sys.stdin.readline().strip()
    if command == "GET_TEMP":
        temp = read_temperature()
        sys.stdout.write("Temperature: {:.2f} C\n".format(temp))
    else:
        sys.stdout.write("Unknown command.\n")

PC側のコード

最初にVender IDとProduct IDでPico基板を探している。デバイスの名前や説明を編集できれば一番いいのだけれどその機能がMicroPythonに実装されてるのか分からなかった。とりあえずPico側に名を名乗らせるコマンドを追加すれば対応できると思う。

get_temp.py
import serial
import serial.tools.list_ports
import time

def find_pico_port(vid=0x2E8A, pid=0x0005):
    ports = list(serial.tools.list_ports.comports())
    for port in ports:
        if (port.vid, port.pid) == (vid, pid):
            return port.device
    return None

def main():
    pico_port = find_pico_port()
    if pico_port is None:
        print("Raspberry Pi Picoが見つかりませんでした。")
        return

    print(f"Raspberry Pi Picoが{pico_port}で見つかりました。")

    # シリアルポートを開く
    ser = serial.Serial(pico_port, baudrate=115200, timeout=1)
    time.sleep(0.1)  # デバイスの準備待ち

    # 入力バッファをクリア
    ser.reset_input_buffer()

    try:
        # 2秒ごとに温度を取得するループ
        while True:
            # コマンドを送信
            ser.write(b'GET_TEMP\n')

            # 応答を読み取る
            response = ser.readline().decode('utf-8', errors='ignore').strip()
            print(f"受信した温度データ: {response}")

            # 2秒間待機
            time.sleep(2)
    except serial.SerialException as e:
        print(f"シリアル通信でエラーが発生しました:\n {e}")
    except KeyboardInterrupt:
        pass
    finally:
        print("\n温度取得を終了します。")
        ser.close()

if __name__ == "__main__":
    main()


動作テスト

Windows機のThonnyで実行するとこんな感じ

>>> %Run MicroPython_USB_CDC_Host.py
Raspberry Pi PicoがCOM12で見つかりました。
受信した温度データ: Temperature: 17.68 C
受信した温度データ: Temperature: 17.21 C
受信した温度データ: Temperature: 16.75 C
受信した温度データ: Temperature: 17.21 C

温度取得を終了します。
>>> 

動作中にUSBケーブルを抜くとこんな感じ

>>> %Run MicroPython_USB_CDC_Host.py
Raspberry Pi PicoがCOM12で見つかりました。
受信した温度データ: Temperature: 17.68 C
受信した温度データ: Temperature: 17.21 C
受信した温度データ: Temperature: 17.21 C
シリアル通信でエラーが発生しました:
 WriteFile failed (PermissionError(13, 'デバイスがコマンドを認識できません。', None, 22))

温度取得を終了します。
>>> 

とりあえずAIに頼めばいい感じのデモコードを作ってくれる時代になってしまったので簡単な作例を公開する意義が薄くなった気はするけど以前作ったやつがあんまりにもあんまりなので今回は公開する。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?