ラズパイPicoと有線LAN

2026年3月19日 記

はじめに

ラズパイPicoにはWiFiを搭載したPico Wというものがあります(2もあります)。 ただ電波が弱いとかアンテナが小さいとかあって、 ちょっとしたことで「通信エラー」になってしてしまうことがありました。 そこで・・・というわけでもないのですが、 インターネットで検索してみたら「UART - Ethernet」変換基板というものを見つけました。

変換基板には大きく2種類あって、 Pico本体に直接接続できるものと、価格を抑えた小さな基板タイプのものがありました。 手持ちのお金の都合で価格を抑えた小さな基板タイプのものを購入してトライしてみました。

有線LANにしたことで結果的には以前よりも安定するようになりました。 もしPico WのWiFiで通信が不安定になるようであれば有線LANにしてしまうのもひとつの方法として 「あり」だと思います。

今回はPico側(UART-Ethernet変換基板側)を UDPサーバーに設定して通信させてみた結果を残しておくことにします。

もし「ちょっとやってみよう!」と思われた方は、 インターネットで Pico、Ethernet、有線LAN、CH9121、とかのキーワードで検索すると、 その手のものが引っかかってくると思いますので必要なものをダウンロードしてください。

必要なものは「UART-Ethernet変換基板(CH9121)の設定ソフト」と 「サンプルプログラム」および「CH9121」のマニュアルなどです。






目次

(1)制御ピン(制御信号)
(2)クライアント・サーバー
(3)その他詳細
(4)トラブルなど
(5)最後に






(1)制御ピン(制御信号)

Pico本体に接続する変換器の写真を見たらRSTIとCFG0という端子がPicoと接続できるようになっていたので、 それを参考にPico側の空いているGPIO端子に接続しました。 これらのピンの機能はは下記の通りです。

RSTI 外部リセット入力(Lowでリセット)
CFG0 UART設定モードセット入力(Lowで設定モードに入る)

起動時にCFG0をLowにしておくと設定モードに入ることができてCH9121の設定をできるようです。 また通信プロトコルもデータシートに記載されていましたが、 私は別途ダウンロードした「設定ソフト」を使って設定したのでこの辺の端子については一度も使っていません。 Picoに接続してありますが、Highレベルを出力したままにしてあります。

ちなみにこれらの端子は内部でプルアップされているようですが、念のため外部プルアップ抵抗を付けました。 それ以外はUARTのTx0,Rx0と3.3V電源とGNDを繋いだだけです。

特記事項として、最初にCH9121の「設定ソフト」を使って設定しようとしたときに上手く設定ソフトで設定することができませんでした。 仕方なく「設定専用の基板」を別に作ってUARTのTx1,Rx1およびRSTI,CFG0のピンも接続し、 それ以外のPicoの端子はすべてオープンにしてやってみたところ「設定ソフト」が変換基板を認識してくれました。

「設定ソフト」を動かすパソコンと変換基板を私はLANのクロスケーブルで直接1対1で接続したのですが、 ChatGPT(AI)の話だと今はクロスケーブルでなくても普通のストレートケーブルでも大丈夫だと言っていました。 その辺を吸収するための規格なのか仕掛けなのか良く分かりませんが(スルーしてしまいましたが)別にクロスケーブルでなくても1対1で接続できるようです。




目次へ



(2)クライアント・サーバー

今回はUDPのサンプルプログラムをダウンロードしました。

まず決める必要があるのはこのUART-Ethernet変換基板をクライアントとして動かすのか、それともサーバーとして動かすのかということです。

ここで「クライアント」とは、最初にメッセージを送信してサーバーに何らかの「問い合わせ」をする機能です。 また「サーバー」とは、クライアントから受け取ったメッセージから、それに応答するメッセージ(データ)を作成して応答データを返す(送信する)機能です。 「クライアント」はサーバーから受け取った応答(データ)を元に「何らかの処理」を続けます。

・・・ということになりますので、最初にメッセージを出すようにするのであれば「クライアント」として、 そうではなくてメッセージを受け取って何らかの応答を返すようにするのであれば「サーバー」として設定します。

ポート番号を設定する項目が2つありますので、それぞれ異なる設定をしましょう。 もし設定できるポート番号がひとつしかなければそれを設定すれば大丈夫なはずです。 設定ソフトで変換基板に上手く接続できるとデフォルトデータを読みだすことができますので、その設定値を参考にすると良いでしょう。

ここで私は変換基板を「UDPサーバー」として設定しました。 そうすると自作ソフトでは「UDPクライアント」オブジェクトを作成して、 変換基板のUDPサーバーに対して最初に問い合わせのメッセージを送信することになります。 UDPクライアントを作成するときに指定するポート番号は設定ソフトで設定した変換基板のUDPサーバーとしての「Local Port」のポート番号です。

相手側(パソコン側)の「Dest Port」のポート番号ではありませんのでご注意ください。 またIP、サブネットマスク、ゲートウェイは普通にLANを設定するのと同様で大丈夫です。

変換基板は受け取ったメッセージをUARTの信号に変換してPicoに送信します。 PicoはUARTで受け取ったメッセージを解読して応答メッセージを作成し、UARTで変換基板に応答メッセージを送信します。 変換基板は受け取ったUARTの応答メッセージをLANを通して自作ソフトに送信します。 応答を受け取った自作ソフトはその応答メッセージより、続けて「何らかの処理」を続けます。




目次へ



(3)その他詳細

まずはサーバー機能の話です。 サーバーはいずれかのクライアントからメッセージを受信すると、そのクライアントの情報を得ます。 つまりサーバーは応答を返すべき相手(IPアドレス)とポート番号をメッセージ受信時に得られますので、そこへ応答を返すことになります。 具体的にどうするかといいますと、 サーバー機能を有するオブジェクトがメッセージを受信すると、そのオブジェクトの受信メソッドを使ってクライアントからのメッセージを取得できます。 メッセージを解析&応答データを作成したら受信したサーバーオブジェクトの送信メソッドを使って応答(データ)を送信します。

これがサーバーの基本的な処理の流れです。

次にクライアント機能です。 クライアントはクライアントオブジェクトを作成し、宛先のサーバーにメッセージを送信します。 クライアントオブジェクトはどのサーバー宛に送ったかを記憶していますので、 その宛先サーバーからの応答を受信したらクライアントオブジェクトの受信メソッドを使って応答データを受信できます。

これがクライアントの基本的な処理の流れです。

逆を言えばクライアントにしてもサーバーにしても送信先または受信先が分かっていないとどこへ送信したらよいか、 どこからのデータを受信したらよいか分からないことになります。 つまりクライアントが送信する前にどこからかのメッセージを取得することはできませんし、する意味もありません。 クライアントがこれをやろうとするのが間違いで、最初にどこからかのメッセージを取得する必要があるときにはサーバーにしなければなりません。

またサーバーが最初にどこか特定のクライアントへデータを送信することはできませんし、する意味もありません。 先と同様にサーバーがこれをやろうとするのが間違いで、最初にどこかへメッセージを送信する必要があるのであればクライアントにしなければなりません。

・・・と書いてみたのですが、これはこの有線LANにしようといろいろとプログラムを弄っていたときに気づいたことです。 知っている人は「当たり前じゃん」とか思われるかと思いますが、私は今回改めてこれに気づきました。 実は最初は、「サーバーオブジェクトでデータを受信して、別に作ったクライアントオブジェクトからデータを送信すればよい」と思っていました。 しかしこれをやってみたら通信が上手く行きませんでした。 いろいろ調べていたら実はサーバーオブジェクトにも送信メソッドがあって、応答を返すことができる事実をこの時点で初めて知りました。 「なるほど!」と思い、そのサーバーオブジェクトの送信メソッドを使って応答を返し、 クライアント側はクライアントオブジェクトの受信メソッドを使って応答を受信するようにしたら上手く通信できるようになりました。

以上、この事実を改めて今回知りました。

少し補足しておきます。 今回利用したサンプルプログラムの構成がこうなっていただけ・・・と、言うこともできます。 おそらく一般的にサーバーオブジェクト、クライアントオブジェクトを作る際にはこのような構成にするのだろうと思いますが、 C言語で記述したとすれば(オブジェクトという考えはないので)、受信処理と送信処理をサーバーとクライアントの両方で別々に作ることになると思います。 そうすると送受信先のデータを送信処理と受信処理とで共有するようにするだけで、送受信処理を共通化することもできると思います。 この辺の話になると「その機能をどのような構成にして実装するのか」という話になってきて、 いろいろと違った構成が出てくるかもしれません。・・・という補足を念のため記しておきます。


いろいろと調べていたら(自作ソフト側の)受信待ちのときの「タイムアウト時間」を設定する方法を見つけました。 その通りにやってみたら上手くタイムアウト時間を設定できて、余計なスレッドを作ることなくスムーズな処理ができるようになりました。 そのタイムアウト時間の設定方法ですが、下記のコードを受信メソッドに埋め込みました。 下記コードのタイムアウト時間は5msです。 適切に変更しましょう。

struct timeval tv;
tv.tv_sec = 0;  // 0秒
tv.tv_usec = 5*1000;	// 5ms
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));






目次へ



(4)トラブルなど

有線LANで通信できるようになるまでにPicoが2つくらい壊れました。 「いつ」「壊れた」のか「壊した」のかが良くわからないので曖昧な表現で書きましたが、 設定ソフトを使って設定データを書き込むときに何かしたのかもしれません。

設定ソフトを使って変換基板の設定をする際に、なぜかTx0,Rx0だけでなくTx1,Rx1も接続しないと設定ソフトが変換基板を認識しませんでした。 ChatGPT(AI)にこの辺の話をしてみたら、「変な電流がTx1,Rx1に流れ込んでたまたま動いたのではないか?」みたいな回答をくれました。 その可能性はもちろんありそうな話でしたが、実際のところを確認するのは難しいので不明のままです。

仮に「変な電流が流れた・・・」と仮定した場合、逆を問うと「変な電流が流れなければ変換基板を認識できない・・・」という話になります。 こう考えると「設定ソフトをまだまともに動かすごとができる状態ではない」と言い換えることができます。 なので、ここでひとつの結論をだすとすれば「たまたまでも設定値を書き込めればよし!」と割り切るのか、 それとももっと深く掘り下げて原因を突き止めるのかの2択になりますが、 今回は最初の「書き込めればよし!」ということにしました。 現実として通信できないと意味ないですし、通信できて更にWiFiより安定してくれれば目的は達成しています。 しかし技術者として考えると「原因を突き止めないと・・・」という人も居ると思いますが、 変換基板にしても設定ソフトにしても「自分で作ったものではない」ので、そこまでする必要は感じません。 独自に変換基板を作る!とか、設定ソフトを作る!ということであれば原因を突き止めるメリットは「ある」かもしれませんが、 そうでなければ時間の無駄になるだけです。他にやることとか、やりたいことなどがあるのであればそっちを優先したほうが良いでしょう。 仮に「暇で何もすることがない・・・」というのであれば、興味本位で原因を突き止めてみるのも勉強になるかもしれません。




目次へ



(5)最後に

もし変換基板が壊れてまた同じ変換基板を作る(設定ソフトで設定値を書き込む)必要が出たときには、 以下のようなことをやってみようと思います。

今回は設定ソフトで設定する際に「設定値書き込み専用の基板」を作ったのですが、 設定値を書き込む際は変換基板に「電源」を供給できれば良いはずなのです。 設定自体はLAN側から行いますので。 そんなわけで、電源以外の信号線を外した状態で書き込んでみたいと思います。 これだけで設定ソフトが認識してくれればトラブルのすべてが解決しそうに思います。

いや、設定値を書き込む際にPicoが変な出力をしないようにボタンを押しながらPicoを起動し、 uf2ファイルを書き込むことができる状態にして設定値を書き込もうとしてみたことがあったのですが、 この状態だと設定ソフトが変換基板を認識しませんでした。 Picoを普通に起動しないと設定ソフトは変換基板を認識しませんでした。 Picoは普通に起動しないと3.3Vを出力しない?(変換基板の電源としてPicoの3.3Vを供給しています)ということもあるのかもしれません。

この辺のことを考えると、 単に電源を供給するだけで動く可能性、 書き込む際は電源供給をUSBの5Vにして、それ以外の配線はすべて外す必要がある可能性、 電源以外にも何らかの配線をしないと動かない可能性(信号線orプルアップorプルダウン)がありそうです。

電源供給だけで動けば問題はすぐに解決ですが、他が必要ということであれば「それ」が何かをマニュアルを読んで探る必要が出てきます。 時間が掛かりそうですね・・・とだけ、記しておきます(それをやることになる可能性がある未来の自分のために・・・)。




目次へ






メニュー