picoをリモコンで操作したい (4)

前回、pico → ラズパイの通信に成功したので
第2回のプログラムと組み合わせて、双方向通信に挑戦

ラズパイ側の送信部分は第2回のものとほぼ同じですが
ボタンを押し続けたとき、離し続けた時に通信が連続的に行われないよう
少しだけコードを追加 (38-40行、49-52行)
それ以外はほぼ、第2回と第3回のコードの組み合わせです

"""
*** コメントの大半は Github Copilot によって生成されたものです ***

ラズパイとPicoの間でUARTを使って双方向通信
ラズパイ(リモコン)側プログラム
ラズパイにつないだボタンの状態をPicoに送り、Picoからの応答を受け取って表示する
"""

import serial
import fcntl
import RPi.GPIO as GPIO
from gpiozero import Button
import time

# ===== 定数定義 =====
BAUD_RATE = 9600
UART_TIMEOUT = 1.0      # シリアル受信のタイムアウト時間(秒)
LOOP_INTERVAL = 0.01    # メインループの実行間隔(秒)
BUTTON_INPUT_PIN = 17   # ボタン入力ピン(GPIO 17 = Raspberry Pi pin 11)

# ===== ボタン状態の定義 =====
STATUS_ON = 1           # ボタンが押された状態
STATUS_OFF = 0          # ボタンが離された状態
prev_onoff_status = STATUS_OFF  # 前回のボタン状態

# ===== GPIO 初期化 =====
GPIO.setmode(GPIO.BCM)
button = Button(BUTTON_INPUT_PIN)

# ===== シリアルポート初期化 =====
lock = open('/tmp/ttyS0.lock', 'w')  # シリアルポート用ロックファイルを開く
fcntl.flock(lock, fcntl.LOCK_EX)     # 排他ロックを取得(他のプロセスからのアクセスを防止)
ser = serial.Serial('/dev/serial0', BAUD_RATE, timeout=UART_TIMEOUT)

try:
    while True:
        if button.is_pressed:
            # ボタンが押されし続けた場合に1を送り続けないようにする
            if prev_onoff_status == STATUS_OFF:
                prev_onoff_status = STATUS_ON
                ser.write(b'1')
            
                # Picoからの応答を受信
                received_data = ser.readline()
                print_data = received_data.decode('utf-8').rstrip('\n')
                print(f"pico から受信: {print_data}") 
                
        else:
            # ボタンが離され続けた場合に0を送り続けないようにする
            if prev_onoff_status == STATUS_ON:
                prev_onoff_status = STATUS_OFF
                ser.write(b'0')

        time.sleep(LOOP_INTERVAL)

finally:
    # ===== 終了処理 =====
    ser.close()
    fcntl.flock(lock, fcntl.LOCK_UN)  # ロックファイルのロックを解除
    lock.close()

pico 側のプログラムも、ほぼ第2回と第3回の組み合わせです

"""
*** コメントの大半は Github Copilot によって生成されたものです ***

ラズパイとPicoの間でUARTを使って双方向通信
pico(本体)側プログラム
ラズパイにつないだボタンの状態をPicoで受け取り、'1' を受け取った回数をラズパイに送る
"""

from machine import UART, Pin
import time

# ===== 定数定義 =====
BAUD_RATE = 9600  # シリアル通信のボーレート
UART_TIMEOUT = 1.0  # UART受信のタイムアウト時間(秒)
LOOP_INTERVAL = 0.05  # メインループの実行間隔(秒)
LED_PIN = 15  # GPIO 15 = RP-pico pin 20

# ===== LED初期化 =====
led = Pin(LED_PIN, Pin.OUT)

# ===== LED状態とカウンター =====
LED_ON = 1
LED_OFF = 0
on_count = 0  # Picoが受け取った'1'の総数

# ===== UART通信初期化 =====
uart = UART(0, baudrate=BAUD_RATE, tx=Pin(0), rx=Pin(1))

# ===== メインループ =====
while True:
    if uart.any():
        data = uart.read(1)
        
        if data == b'1': # Raspberry Pi側のボタンが押された場合
            led.value(LED_ON)
            # 現在のカウンター値をRaspberry Piに送信
            uart.write(f"count: {on_count}\n".encode('utf-8'))
            on_count += 1
            
        if data == b'0': # Raspberry Pi側のボタンが離された場合
            led.value(LED_OFF)
    
    time.sleep(LOOP_INTERVAL)

つづいてタクトスイッチのチャタリング対策で
ラズパイ側のLOOP_INTERVAL値の調整

の予定だったのですが、インターバル 10ms でチャタリングが見られませんでした
ちょっと驚き

ここまでで解った事。
ラズパイはOSが動いているので、受信がちょっと難しい

ラズパイ zero W を使ってリモコンを作る事を考えていました
リモコンから送信だけなら、それでも問題なさそうですが
pico の電池残量をリモコンに表示したいので
双方向通信が欲しい

なので、ラズパイ zero W をリモコンにする予定を変更

リモコンも pico で作る事にしました
次回は pico と pico で双方向通信に挑戦です。

コメント

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