送信機と受信機を作りネットワーク越しでRCカーを操作してみます。

前回はRCカーのサーボとモーターをUSBゲームパットで操作しました。今回はネットワーク経由で送信側と受信側を分けて小さなリモート操作のテストをしてみます。送信側はWindowsでもスマートフォンでも良いのですが、今回はraspberry Pi5を送信機にします。raspberry Pi5(ubuntu24.04)で以下のセットアップします。USBゲームパットの信号を送るだけですから環境は単純なものです。

第4回はさまざまな試行錯誤をしています。そのためまとまりがない記事で参考にならないでしょう。混乱する内容であり、経過としてみてください。雑記です。リモート操縦するための原理の検証が出来ました。

 

raspberry Pi5を送信機にセットアップ

sudo apt update && sudo apt upgrade
sudo apt install python3-pip python3-venv build-essential git
python3 -m venv myenv
source myenv/bin/activate
pip3 install inputs

ネットワークで送受信をするためにIPを設定します。適宜環境に合わせてください。記事当初はシンプルなネットワーク経由の信号送受信チェックの記事にする予定でしたが、さまざまな問題があり以下コードは改良したものになります。そのためコードが長く複雑になっています。未知のエラーや不要なブロックなどもあるでしょう。例えばサーボに関しては、1~-1ではなく、0.5~-0.5にするべきですが改善していません。サーボが回転し過ぎてギリギリっとなっています。Raspberry Piを使ってゲームパッドの操作信号を受け取り、UDPソケットを介して別のRaspberry Piへ送信するためのものです。

 

raspberry Piの送受信コード

send.pyとreceive.py

ワードプレスに張り付けるとインデントがどうしても削除されてしまいます。どうやらコード内の<と、離れた場所の>があるため、掲載すると一行になるという現象です。google docに貼り付けました。

 

コードの作成で考慮したこと

リアルタイム性を重視するためにUDP(User Datagram Protocol)を使用してデータを送信しています。UDPの特性として、非接続型プロトコルであるため接続確立の遅延がなく、低オーバーヘッドでデータを送受信でき、データの損失を許容しながらも即時性を確保することが可能です。

これにより遠隔操作されるRCカーへの指令を迅速かつ連続的に送ることができ、応答性を最大化しています。

送信側が信号を出しながら突然切断が発生した場合に、RCカーは走り続けてしまうことがあります。完全な仕組みではありませんが、簡易的なタイムアウトと安全モードを入れてあります。

最後の受信時刻から一定期間データが受信されない場合(タイムアウト)、デバイスを安全な状態(モーターを停止状態に)に設定します。これにより、予期せぬ動作や事故を防ぐことができます。ネットワークが切断されるとすぐに停止状態になります。ネットワークが切断には、急発進を防ぐためにBボタンを1秒以上を押すと解除されます。まだまだ改善する部分は多いでしょう。

 

VPN環境を作って5G/4Gなど無線環境で操作するための準備

次はVPN環境を作って5G/4Gなど無線環境で操作するための準備をしましょう。WireGuardで構築します。Ubuntu24.04で準備します。

sudo apt update && sudo apt upgrade
sudo apt install openssh-server
sudo ufw allow 22
sudo apt install nano

以下の記事を参考にWireGuardセットアップです。セットアップしたものをサーバーの下にぶら下げます。CHUWIのミニPCは安い割に良い感じです。サーバーとして十分に性能が良いのです。

ubuntu24.04/ubuntu22.04にWireGuardをインストール
https://riragon.com/ubuntu22-04wireguard/

VPNの簡単な図

10.0.1.1-VPNサーバー
10.0.1.201-raspberry Pi4受信側 (IP:192.168.10.201)
10.0.1.202-raspberry Pi5送信側 (IP:192.168.10.202)

とこんな感じの接続になります。

前回のコードのIPをVPNに書き換えます。そしていろいろ改良しました。ワードプレスに貼るとインデントが崩れるのでgoogle docです。

 

RCカーの配線周りの整理整頓

熱で縮小するチューブでジャンパ線(ジャンバケーブル、テストケーブル)の接続などを外れないようにします。

ヒートガンも使いました。

ピンをまとめて蓋をします。

こういった3ピンなどは作業をしていると、接続がポロポロとれます。これにチューブを通して熱します。

こんな感じに養生できました。安心感がありますね。

ラズパイ用の電源も載せられます。いったん仮設置は完了です。

 

5Gでリモート操作のテスト

RCカーに5G携帯を載せてraspberry Pi4にテザリングします。5Gネットワークから、VPNを経由してraspberry Pi5と接続されます。raspberry Pi5からUSBゲームコントローラでRCカーを制御します。

片手なので上手く操作できていませんが、5GネットワークとVPNを通して操作しても十分に操作できる品質でした。サーボが左に傾いていたり、細かい微調整は必要ですが原理的には完成です。

つまり5G/4Gの電波があるところなら、どこでもリモート操作ができるRCカーが完成しました。

 

操作側をラズパイ5からモニター付きミニPCに変更

操作しているときにいろいろな情報を見たいためラズパイ5からモニター付きミニPCに変更しました。昔購入して使っていないNetbook OneGx1 Proを使います。

Netbook OneGx1 Proレビュー

買うと絶対後悔する10インチ以下の超小型ノートパソコンNetbook OneGx1 Pro

ubuntu24.04をインストールします。特別な設定なくインストールできます。ログイン時は画面が横になりますが問題ありません。そしてサーボ動作をギリギリと限界まで動いていたので45°に制限しました。

 

RC側のラズパイ4にシャットダウンボタンを装着

モニターが無いRC側の電源オンオフが面倒なのでシャットダウンスイッチをつけてみました。どのラズパイでもGPIOピンがあれば同じでしょう。ブートディスクをSSDにすると、電源ぶち切りしてもほぼ壊れませんが、MicroSDを起動ブートにしていると、たまに壊れます。

ラズパイでリモート操縦のRCカーを作っています。RCカー側のラズパイはモニターやキーボードが付いていません。SSH接続などで操作すのですが「sudo shutdown -h now」を入力するのがめんどくさいのです。そこで物理的にシャットダウンスイッチを付けました。

たまたま?昔購入した中にKY-004ボタンモジュールがありました。

KY-004モジュールは、プッシュボタンキースイッチであり、押されると回路を閉じて、Arduino、Raspberry Pi、ESP32などのマイクロコントローラーに高信号を送信します。

KY-004モジュール仕様

タイプ: プッシュボタンキースイッチ
最大操作力: 180/230(±20gf)
耐久性: 100,000サイクル
動作電圧: 3.0V から 5.5V
温度測定範囲: -55°C から 125°C
測定精度: ±0.5°C
基板寸法: 18.5mm x 15mm

KY-004モジュールのピン配置 KY-004キースイッチモジュールのピン配置は以下の通りです。Raspberry Piでのボタンの使用においては、電源ピンに+5Vを接続する必要がないことがあります。GPIOピンの電圧変化だけでボタンの状態を検出することができます。

ピン (S): シグナル→ GPIO17に接続(11番)
ピン (中央): +5V→ 接続しない
ピン (-): GND→ Groundに接続(9番)

 

プッシュボタンを押すとシャットダウンする機能を作成

sudo apt update
sudo apt install python3-rpi.gpio

以下のプログラムを作成しました。

nano /home/riragon/switch-shutdown.py

import RPi.GPIO as GPIO
import time
import os

# GPIOの設定
button_pin = 17  # GPIOピン番号を設定(ボタンが接続されているピン)

GPIO.setmode(GPIO.BCM)  # GPIO番号でピンを指定
GPIO.setup(button_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # プルアップ抵抗を有効

def button_callback(channel):
    print("ボタンが押されました。シャットダウンします。")
    os.system("sudo shutdown -h now")  # シャットダウンコマンドを実行

# イベント検出の設定
GPIO.add_event_detect(button_pin, GPIO.FALLING, callback=button_callback, bouncetime=200)

try:
    while True:  # 無限ループで実行
        time.sleep(1)  # CPUの使用を減らすためにスリープ
finally:
    GPIO.cleanup()  # GPIO設定をクリーンアップ
chmod +x switch-shutdown.py

実行権限をつけたのでサービスに登録して、サービスの自動起動を設定します。

sudo nano /etc/systemd/system/switch-shutdown.service

[Unit]
Description=Button Shutdown Service
After=multi-user.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/riragon/switch-shutdown.py
User=root
WorkingDirectory=/home/riragon
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable switch-shutdown.service
sudo systemctl start switch-shutdown.service
sudo systemctl status switch-shutdown.service

スイッチを固定するために便利な「やわらかプラスチック」を使います。お湯に入れると透明になりくっつきます。冷えるとプラスチックになります。

こんな感じにスイッチをプラスチックに接着します。強く動かせば外せますが、それなりに固定されます。

冷えると白くなり固まります。見た目は悪いですが仮設置にはとても便利です。

 

GStreamerとUSBカメラを設置

いろいろと思考錯誤しながら操縦系は動作したので映像系をテストで実装しました。配線系を整理してラズパイ用のバッテリーをつめるようにして、テスト通信用(テザリング)のスマホの設置場所を作りUSBカメラを搭載しました。

スマホを載せてテザリングがもっとも簡単な5G化です。やわらかプラスチックで適当に固定部分を作ってゆきます。

バッテリーとスマホを搭載して完成です。

USBカメラを適当に固定しました。ランチボックスは中にいろいろ設置できるので、やわらかプラスチックも一緒につかうことで、素早い構築ができます。本当は3Dプリンターなど使うのが良いのですが、とりあえず作るということで。

USBカメラの送信は、以下コードで仮で作成しました。

gst-launch-1.0 -v rtpbin name=rtpbin \
v4l2src device=/dev/video0 ! \
image/jpeg,width=640,height=480 ! \
jpegdec ! \
videorate ! video/x-raw,framerate=30/1 ! \
videoconvert ! \
x264enc tune=zerolatency bitrate=1800 speed-preset=ultrafast key-int-max=5 ! \
rtph264pay config-interval=1 pt=96 ! \
rtpbin.send_rtp_sink_0 rtpbin.send_rtp_src_0 ! \
rtpulpfecenc pt=127 percentage=1 ! \
udpsink host=10.0.10.202 port=5000 buffer-size=65536

以上でとりあえずは動作する原理の確認ができました。配線やUSBルーターやいろいろ調整しております。

カバーもつきます。動作も完全にワイヤレスです。

操作端末もスマートフォンのテザリングです。動作も完全にワイヤレスです。

はい、送受信ともに無線(4Gと5G)環境で問題なく操舵できました。さまざまな改良を得てだいぶ実用的な操作ができるようになりました。次回から個別にそれらの紹介をしてゆきます。