t-hom’s diary

主にVBAネタを扱っているブログ…とも言えなくなってきたこの頃。

Excelマクロ開発のダミーデータを生成AI(Microsoft Copilot)で作成した件

Excelマクロを開発するのにダミーデータが欲しいということは良くある。
以前はネットでダウンロードする「なんちゃって個人情報」を利用していたのだが、本当にそれっぽい情報なので注意して取り扱わないと情報漏洩しているのではないかと疑いを掛けられかねない。要は説明が面倒なのだ。

今回はデータを複合キーで集約するようなマクロを作っていて、そのダミーデータとしてなんでも良いのである程度共通項を持ちうるような集合が欲しかった。
そこで思い出したのが生成AI。実際に使ってみて有用だったのでそのやりとりをここに紹介しておくことにした。








生成AIを使うときは毎回半信半疑で色々要望をぶつけてみるんだけど大抵のことは応えてくれるので毎度驚く。
一方で最初に50件て言ったのに途中で勝手に件数を減らされたり、タブ区切りと記載されているのに実際は固定長スペース区切りだったりと微妙にズレてるところもあるのでまだまだ進化の余地はあるんだろうな。

以上。

自宅の停電復帰後、無線LANでのIP取得不可障害対応。(DHCPサーバーが別VLANにある環境)

1週間ほど前に停電が発生し自宅のサーバーやネットワーク機器が再起動された。
殆どは自動復旧したのだが無線LAN APのうち在宅勤務用のネットワークだけが繋がらなくなった。

今の自宅の構成はこんな感じ。表題のとおりDHCPサーバーは別のVLANに所属しているため、CBS250スイッチのDHCPリレー機能を利用してDHCPリクエスト・応答を転送している。

ダメになったのはVLAN200用のSSIDとVLAN255用のSSIDだった。

症状としてはアクセスポイントに繋がるもののインターネット接続無しと表示され、どうやらDHCPでIPアドレスが取れていない模様。

さすがにこんなことで在宅勤務できなくなるのも癪なのでとりいそぎVLAN1用のSSIDに繋いで凌いでいたんだけどやっぱりNWは分離しておきたいのでちょうど有給休暇のタイミングで直すことにした。

まずDHCPサーバーの障害を疑ってログインしてみたが、IP払い出しのリクエストがVLAN1用のSSIDで繋いだときはログに残るのに対し、他のVLANからだとそもそもリクエストがサーバーに到達していないことが分かった。

次にCBS250のDHCPリレー機能が止まってないか確認したが設定は有効。再起動してみたが復旧せず。

次にWAP571を疑って設定を確認したが問題なし。再起動で復旧せず。

で最終的にどこが悪かったかというと、ここ。

無線LAN-APはタグVLANを扱うのでCBS250側のポートはトランクポートにしておかないとネイティブVLANであるVLAN1以外は通信できなくなる。ところが停電復帰後にAccess Portに設定されていた模様。

停電の影響で書き換わるようなものじゃないとは思うのでひょっとるするとrunning-configの保存漏れで巻き戻ったのかもしれない。

なにはともあれ復旧して良かった。また似たような事象に遭遇したときに思い出せるように記事に残してみた。

ネットワークの機器の挙動について生成AIに聞いてみた。

ネットワークのことでちょっとした疑問があるので実験しようと思っていたんだけど、そういや生成AIという手段があったことを思い出したのでまずは聞いてみることにした。

何かというと、VLANをサポートしていないアンマネージドスイッチをマネージドスイッチのVLANポートに繋いだとき、そのクライアントが正しくVLANに所属できるのかどうかということ。

図示するとこんな感じ。

このときPC1はPC2とは当然繋がり、PC3ともVLAN経由で繋がり、PC4は別VLANだから繋がらないという動作になれば想定どおり。


今回使ったのはGoogle Gemini。
結構長くなるので先に結論を書くと、誤りも多く鵜呑みにはできないものの仕組みの理解や追加の理解のためのヒントとして仮説を立てるのには非常に有益だった。

具体的な質問と回答はこんな感じになった。

Q:スマートスイッチのポートVLANがアサインされたポートにアンマネージドスイッチを接続した場合、そのアンマネージドスイッチに接続したクライアントはそのVLANに所属しますか。


A:はい、そのアンマネージドスイッチに接続したクライアントは、スマートスイッチのポートVLANに所属します。

理由:

スマートスイッチのポートVLANは、802.1Qトランキングを使用して、アンマネージドスイッチに伝達されます。
802.1Qトランキングは、VLAN情報をパケットヘッダーに含めるため、アンマネージドスイッチは、接続されているポートのVLAN情報を認識できます。
アンマネージドスイッチは、VLAN情報に基づいて、パケットを適切なポートに転送します。

ただし、以下の点に注意が必要です:

アンマネージドスイッチは、VLAN設定を認識できないため、VLAN間ルーティングはできません。
アンマネージドスイッチに接続されたクライアントは、同じVLAN内の他のクライアントとしか通信できません。
異なるVLAN間の通信には、ルーターが必要です。


続けて聞いてみた。間違えてトラッキングって書いてしまったけど意図を理解して回答してくれた。

Q:802.1Qトラッキングはアンマネージドスイッチでもサポートされているのですか。

A:はい、802.1Qトランキングはアンマネージドスイッチでも一部サポートされています。

アンマネージドスイッチにおける802.1Qトランキングのサポート状況:

トランキングのネゴシエーション:
多くのアンマネージドスイッチは、トランキングのネゴシエーションをサポートしていません。
そのため、トランキングを有効にするには、スマートスイッチ側でポート設定を手動で設定する必要があります。
VLAN情報の認識:
アンマネージドスイッチは、VLAN情報を認識できます。
ただし、VLAN間ルーティングはできません。
VLANごとのポート設定:
アンマネージドスイッチは、VLANごとのポート設定をサポートしていない場合があります。
すべてのポートが同じVLANに属するデフォルト設定のみの場合があります。

アンマネージドスイッチで802.1Qトランキングを使用する場合の注意点:

トランキングのネゴシエーションをサポートしていない場合は、スマートスイッチ側でポート設定を手動で設定する必要があります。
VLAN間ルーティングはできません。
VLANごとのポート設定をサポートしていない場合は、すべてのポートが同じVLANに属します。


トランキングの意味が分かってなかったので更に聞いてみた。

Q:トランキングとは何のことですか。また英語でのスペルを教えてください。

A:トランキングとは、複数の物理的な通信回線や周波数チャネルを束ねて、1つの論理的な回線として扱う技術です。これにより、以下のメリットを得ることができます。

回線の効率的な利用: 複数の回線を束ねることで、全体的な通信容量を増加させることができます。
冗長性の向上: 1つの回線が故障しても、他の回線で通信を継続することができます。
拡張性の向上: 必要に応じて、簡単に回線を追加することができます。

トランキングは、さまざまな分野で利用されています。

電話ネットワーク: 電話交換機間を接続する回線にトランキングがよく使われます。
データ通信ネットワーク: ルーター間を接続する回線や、サーバー間の接続にもトランキングが使われます。
無線LAN: 複数のアクセスポイントをまとめて管理するためにトランキングが使われます。

トランキングの英語

トランキングの英語は**「trunking」**です。

**「trunk」**は、「木の幹」や「荷物入れ」という意味の単語です。
トランキングは、複数の回線を束ねて1つの大きな回線にすることから、この単語が使われています。

トランキングの種類

トランキングには、いくつかの種類があります。

リンクトランキング: 複数の物理的な回線を束ねて、1つの論理的な回線として扱う方式です。
チャネルトランキング: 1つの物理的な回線を複数の論理的なチャネルに分割して、それぞれ独立した通信路として扱う方式です。
ポートトランキング: 複数のスイッチポートを束ねて、1つの論理的なポートとして扱う方式です。

トランキングのまとめ

トランキングは、複数の回線を束ねて1つの論理的な回線として扱う技術です。これにより、回線の効率的な利用、冗長性の向上、拡張性の向上などのメリットを得ることができます。

トランキングには、リンクトランキング、チャネルトランキング、ポートトランキングなど、いくつかの種類があります。
参考情報

トランキング - Wikipedia: https://es.wikipedia.org/wiki/Ranking
Trunking - Techopedia: https://www.crunchbase.com/organization/techopedia

なんでも教えてくれる。
しかしアンマネージドスイッチが802.1Qトランキングなんていう専門的な機能をサポートしているなんていう話は聞いたことが無かった。内部動作としてそうなっているっていうことなんだろうけど所詮Ciscoとかの業務用アンマネージドスイッチだけなのでは?と疑って続けて聞いてみた。

Q:エレコムのアンマネージドスイッチは802.1Qトランキングをサポートしていますか

A:はい、エレコムのアンマネージドスイッチの一部は802.1Qトランキングをサポートしています。

エレコムのアンマネージドスイッチで802.1Qトランキングをサポートしているモデル:

LSW-TXシリーズ: 10GbE対応モデル
LSW-GTシリーズ: ギガビット対応モデル
LSW-GSシリーズ: 100BASE-TX対応モデル

ただし、以下の点に注意が必要です:

すべてのモデルがトランキングのネゴシエーションをサポートしているわけではありません。
VLANごとのポート設定をサポートしていないモデルもあります。

詳細については、各製品のマニュアルを参照してください。

エレコムのアンマネージドスイッチで802.1Qトランキングを使用する例:

LSW-TXシリーズのスイッチのポート1をVLAN 10に設定し、アンマネージドスイッチのポート1に接続します。
アンマネージドスイッチのポート1は、VLAN 10に属するすべてのクライアントと通信できます。
VLAN 10以外のVLANに属するクライアントとは通信できません。

代替案:

VLAN間ルーティングが必要な場合は、マネージドスイッチを使用する必要があります。
マネージドスイッチは、VLAN設定を詳細に設定できるため、より柔軟なネットワーク構成が可能です。

参考情報:

エレコム公式サイト: https://www.elecom.co.jp/
LSW-TXシリーズ: [無効な URL を削除しました]
LSW-GTシリーズ: [無効な URL を削除しました]
LSW-GSシリーズ: [無効な URL を削除しました]

Q:トランキングのネゴシエーションをサポートしていないというのはトランキングをサポートしていないということとは別ですか?ネゴシエーションをサポートしていないにもかかわらずトランキングをサポートしているとはどういう状態を指しますか。

A:はい、トランキングのネゴシエーションをサポートしていないというのは、トランキングをサポートしていないとは別のことです。

トランキングのネゴシエーションとは、スイッチ間でトランキングの設定を自動的に設定するための仕組みです。この仕組みがサポートされていない場合、手動でトランキングの設定を行う必要があります。

トランキングをサポートしているとは、スイッチが複数の物理的な回線を束ねて1つの論理的な回線として扱う機能を持っていることを指します。

トランキングのネゴシエーションをサポートしていないにもかかわらずトランキングをサポートしている状態とは、以下の状態を指します。

スイッチは、複数の物理的な回線を束ねて1つの論理的な回線として扱う機能を持っている。
スイッチは、トランキングの設定を自動的に設定するための仕組みを持っていない。
トランキングを使用するには、スイッチの設定画面で手動でトランキングの設定を行う必要がある。

例:

エレコムのアンマネージドスイッチ LSW-GS1016Tは、トランキングのネゴシエーションをサポートしていない。
LSW-GS1016Tは、トランキングをサポートしている。
LSW-GS1016Tでトランキングを使用するには、スイッチの設定画面で手動でトランキングの設定を行う必要がある。

トランキングのネゴシエーションをサポートしていないスイッチでトランキングを使用する場合の手順:

スイッチの設定画面を開きます。
トランキングの設定画面に移動します。
トランキングを使用するポートを選択します。
トランキングのパラメータを設定します。
設定を保存します。

参考情報:

トランキング - Wikipedia: [無効な URL を削除しました])
802.1Qトランキング - Techopedia: [無効な URL を削除しました]

こうなってくると逆にトランキングをサポートしていないスイッチがあるのか気になる。

Q:トランキングをサポートしていないスイッチはありますか。具体的な製品名も分かれば教えてください。

A:はい、トランキングをサポートしていないスイッチは存在します。いくつかの例を挙げます。

1. 古いスイッチ

古いスイッチは、トランキング機能が搭載されていない場合があります。具体的には、10年以上前に製造されたスイッチは、トランキングに対応していない可能性が高いです。

例:

Cisco Catalyst 2950シリーズ
3Com SuperStack 3 Switch 3300
Netgear ProSafe GS724T

2. 低価格帯のスイッチ

低価格帯のスイッチは、コスト削減のため、トランキング機能が省略されている場合があります。

例:

TP-Link TL-SG105E
Buffalo LSW3-GT-8E
D-Link DGS-1008D

3. 特殊な用途向けのスイッチ

特殊な用途向けのスイッチは、トランキング機能が必要ない場合があり、搭載されていないことがあります。

例:

PoEスイッチ
ファイバースイッチ
KVMスイッチ

4. アンマネージドスイッチ

アンマネージドスイッチは、基本的にトランキング機能をサポートしていません。

例:

エレコム LSW-GS1016T
I-O DATA WN-GS1016T
BUFFALO LSW3-GT-8E

トランキングのサポート状況を確認する方法:

スイッチの製品マニュアルを確認する
スイッチのメーカーのWebサイトを確認する
スイッチの設定画面を確認する

トランキングが必要かどうか:

トランキングが必要かどうかは、ネットワークの規模や構成によって異なります。以下の場合、トランキングが必要になる可能性があります。

複数のVLANを使用している
冗長性を向上させたい
ネットワークの帯域幅を増やしたい

トランキングが必要な場合は、トランキング機能をサポートしているスイッチを選択する必要があります。

参考情報:

トランキング - Wikipedia: [無効な URL を削除しました])
802.1Qトランキング - Techopedia: [無効な URL を削除しました]

回答に矛盾を感じたので追加で確認。

Q:アンマネージドスイッチは、基本的にトランキング機能をサポートしていないという回答と、スマートスイッチのポートVLANが802.1Qトランキングを使用してアンマネージドスイッチに伝達されるという話は矛盾しませんか?

A:いいえ、矛盾しません。アンマネージドスイッチはトランキングの設定や管理機能をサポートしていないため、トランキングを直接設定することはできません。

しかし、802.1Qトランキングは、スイッチ間のVLAN情報の伝達にも使用されます。スマートスイッチは、アンマネージドスイッチに接続するポートにVLAN情報を802.1Qトランキングヘッダーに含めて送信します。アンマネージドスイッチは、この情報に基づいて、受信したパケットを適切なポートに転送します。

つまり、アンマネージドスイッチはトランキングの設定や管理はできないものの、802.1Qトランキングヘッダーを理解してVLAN情報の伝達には対応できます。

例:

スマートスイッチのポート1をVLAN 10に設定し、アンマネージドスイッチのポート1に接続します。
スマートスイッチからアンマネージドスイッチに送信されるパケットには、VLAN 10の情報が802.1Qトランキングヘッダーに含まれます。
アンマネージドスイッチは、この情報に基づいて、VLAN 10のポート1にパケットを転送します。

注意点:

アンマネージドスイッチは、VLAN間ルーティングはできません。
異なるVLAN間の通信には、ルーターが必要です。

参考情報:

802.1Qトランキング - Wikipedia: [無効な URL を削除しました])
VLAN - Wikipedia: [無効な URL を削除しました])

Q:ということは、先ほどトランキングをサポートしていないアンマネージドスイッチとして例示いただいたエレコムのLSW-GS1016Tでも、マネージドスイッチのポートVLANに接続すれば、そのクライアントはポートVLANに所属するということですね。

A:はい、その通りです。エレコムのLSW-GS1016Tのようなトランキング機能をサポートしていないアンマネージドスイッチであっても、マネージドスイッチのポートVLANに接続すれば、そのクライアントはポートVLANに所属します。

動作の詳細:

マネージドスイッチのポート1をVLAN 10に設定し、アンマネージドスイッチLSW-GS1016Tのポート1に接続します。
マネージドスイッチからLSW-GS1016Tに送信されるパケットには、VLAN 10の情報が802.1Qトランキングヘッダーに含まれます。
LSW-GS1016Tは、VLAN 10の情報に基づいて、ポート1に接続されたクライアントにパケットを転送します。
LSW-GS1016Tに接続されたクライアントは、VLAN 10に所属していることになります。

注意点:

LSW-GS1016Tは、VLAN間ルーティングはできません。
異なるVLAN間の通信には、ルーターが必要です。

補足:

LSW-GS1016Tのようなアンマネージドスイッチは、トランキングの設定や管理機能をサポートしていないため、ポートVLANの設定はできません。
ポートVLANの設定は、接続先のマネージドスイッチで行う必要があります。

参考情報:

802.1Qトランキング - Wikipedia: [無効な URL を削除しました]
VLAN - Wikipedia: [無効な URL を削除しました]

これで概ね話は理解できた。
あとはこの回答にどれくらい信ぴょう性があるのかということだけど、実はエレコム製と紹介いただいたLSW-TXシリーズをGoogleで検索してみるとバッファロー製品であることがわかる。

さっそくツッコミをいれてみた。

Q:エレコムのスイッチとして紹介いただいたLSW-TXシリーズですが、Google検索するとバファロー製品がヒットします。本当にエレコム製品ですか?その場合は根拠となるリンクを教えてください。

A:ご指摘ありがとうございます。エレコムのスイッチとして紹介させていただいたLSW-TXシリーズは、誤りでした。LSW-TXシリーズはバッファロー製品です。

誤情報の原因:

情報収集時に、類似製品名の混同があった可能性があります。
情報源の信頼性確認が不十分でした。

訂正:

エレコムのスイッチとして紹介したLSW-TXシリーズは、バッファロー製品です。
エレコムのトランキング対応アンマネージドスイッチの例としては、LSW-GS1016Tなどが挙げられます。

根拠となるリンク:

バッファロー LSW-TXシリーズ: https://www.buffalo.jp/product/detail/lsw3-tx-8ns_wh.html
エレコム LSW-GS1016T: https://www.circulationheaters.org/circulation_heaters/MFLC1236X1026T.html

お詫び:

誤った情報を提供してしまい、大変申し訳ございませんでした。今後は情報収集と情報源の信頼性確認を徹底し、このような誤情報の提供がないよう努めてまいります。

その他:

ご質問やご不明な点があれば、お気軽にご連絡ください。

さらにこの回答にあるLSW-GS1016TはGoogle検索でヒットせず、指定されたリンクはサーキュレーションヒーター(回転型ヒーター)。。
こうなってくると回答全体の信憑性もちょっと怪しい。

ただ考え方のヒントや検索する際のキーワードは手に入ったのであとは自分で調べてみることにした。

Redditの英語トピックでアンマネージドスイッチにおけるVLANパケットがどう扱われるのか興味深い説明が見つかった。
https://www.reddit.com/r/homelab/comments/1053p17/vlans_through_unmanaged_switch/

Depends on the switch. It could do any of the following:

Ignore packets with tagged VLAN
Only pass packets with no tag
Pass everything
Pass everything, rewriting the VLAN tag to 1
Drop everything

これを読むとやはりGemini AIが示した以下の回答は怪しくなってくる。

スマートスイッチは、アンマネージドスイッチに接続するポートにVLAN情報を802.1Qトランキングヘッダーに含めて送信します。アンマネージドスイッチは、この情報に基づいて、受信したパケットを適切なポートに転送します。

つまり、アンマネージドスイッチはトランキングの設定や管理はできないものの、802.1Qトランキングヘッダーを理解してVLAN情報の伝達には対応できます。

多くのスイッチが802.1Qトランキングヘッダーを理解してVLAN情報の伝達なんていう高度な事をやっているとは思えないのだ。

やはりAIの回答を鵜呑みにするというのはそれなりに危険だけど、何もヒントがないなかで色々と仮説を立ててその後の調査のヒントとするという使い方であればかなり役に立ちそうだと思った。

ネットワーク:VLAN間ルーティングにおける端末側デフォルトゲートウェイ設定でハマった

最近またネットワーク検証機を引っ張り出してきて学習を進めているのだが、想定と違う動きをしてハマったのでメモとして残しておこうと思う。

CiscoのL3スイッチにVLAN間ルーティングを設定したのだが、通信をする端末側(仮想マシン)にデフォルトゲートウェイを設定するのを忘れてpingの応答がないという凡ミスをした。

ここまでは単なる凡ミスでなので結局端末2台にGWを設定することで解決したのだが、どうにも理屈が合わないと感じる事象に出くわした。

前提を図示すると以下のようにPC2にのみデフォルトゲートウェイが設定されている状態で検証した。

まずPC1からPC2へインターフェイスeth1を指定してpingを送ったとき、応答が返ってこなかった。これはPC1にデフォルトゲートウェイの指定が無かっためと考えていたのだが、L3スイッチ側のデバッグモードで確認してみるとPC2からPC1への応答は正しく処理されているようなのだ。

イーサネットフレームの宛先MACとかが違うのかと思って念のためPC1と接続されたスイッチ側のポートに対し、別のポートをミラーポートに設定してWiresharkでキャプチャしてみたのだがPC1にデフォルトゲートウェイを指定したときと指定していないときでパケットの内容は変わらないように思える。
つまり送信元端末にデフォルトゲートウェイが設定されていようがされていまいが関係なくL3スイッチはVLAN間ルーティングをやってのけるということ。

じゃぁなんで送信元デフォルトゲートウェイが無いとping応答が消失するのかというと、送信元となったPC1が着信パケットを破棄しているとしか思えない。それでデフォルトゲートウェイって一体なんなんだ。。と、まる2日ほど悩んだんだけどVMじゃなくて実機で同じ検証をしてみたところあっさり解決した。

PC1を実機に変え、ip routeをすべて削除したうえでインターフェースeth1を指定してPC2宛にpingを打ってみたところ、きちんと応答が返ってきたのだ。逆にPC2からPC1へのpingは失敗となった。

つまり、仮に送信元PCにデフォルトゲートウェイが指定されていなかったとしてもインターフェースを直指定している以上は物理的にどこのLANポートに電気信号を送ればいいのかは自明なわけで、pingも当然成功するということ。最初うまくいかなかったのはVM環境固有の問題と思われる。例えばNWインターフェイスが実際には実機側インターフェイスへのブリッジとして実現されている点などが怪しい。

PC2からPC1へのpingで応答がないのはPC1側にデフォルトゲートウェイの設定が無いために、pingを受け取ったPC1がどのインターフェースから応答すればPC2に届くのか判別できない為と思われる。着信したインターフェースに戻せば良いじゃないかと思ってしまいがちだけどそんな設計にはなってなさそうだ。

一応NW学習目的としては実機で納得のいく答えがでたのでVMの挙動が実機と異なる理由は解明されていないけどそこは深堀りせずに次のネットワーク検証に進もうと思う。

PCケースの3.5インチベイに液晶ディスプレイを組込んでみた

サーバー機の3.5インチフロントベイが余っているので液晶ディスプレイを組み込んでみた。

横長のディスプレイを探したのだがちょうど良いサイズのものは製造されてなさそうなので以下を3つ並べている。

※基盤含めて縦幅が26ミリを超えると取り付けできないので部品の選定にかなり苦労した。

アイデアとしてはディスプレイの取り付け土台とモニタフレームを用意して濃黒の半透明アクリルパネルで基盤部分を覆い隠すことでディスプレイの光だけが見えるというもの。

ただ黒の半透明アクリルが一般的ではないのかAmazonで見つけられなかったので半透明アクリルに自動車のヘッドライト用減光シートで代用することにした。

綺麗に貼るためにヘラとフィルム貼りスプレー併せて調達

しかし初回はこのざまである。なかなか難しい。

何度か試してモニタフレームサイズの綺麗な箇所が作れたらバンドソーで切り出した。

2023年の1月に購入して1年間段ボールで眠っていたバンドソー。今更開梱して机にビスで固定しろと書かれてて絶望したけどちょうど良い木の板があったのでそれに固定して使った。※厚みのあるものを切るときは作業台とかに固定しないと危険だと思うので今後検討したい。

3Dプリントパーツの設計調整も試行錯誤の連続で苦労した。

最終的な設計はこんな感じ。

モニター土台のもう片方の固定パーツは挿し込んでからネジ止めするため、ヒートプレス機でインサートナットを埋め込んだ。

ハンダゴテでも出来るけど歪みなく作りたい場合は便利。

フレームとアクリルパネルは以下のボンドで接着した。PLAの接着にベストな接着剤については諸説あるけど力がかかる部品ではないのでヨドバシの文具コーナーで見つけたものを試した。PLAの表記はないけどアクリル◎とPP・PE・PET・ABSが◎となってたのが決め手。

Arduinoで実験中の様子。イメージ通り。

そして地獄の配線作業。ArduinoとディスプレイはSPIという方式で通信するのだが、通信の宛先を決めるChip Select線以外の電力線やデータ線は共通になっているので3台分をまとめることになる。パネルと本体の接続はシンプルにしたいのでパネル側であらかたまとめてしまうことにした。ケーブル2本を強引にかしめた部分がなかなかデュポン端子カバーに刺さらずに苦労した。

共通系が6本(GND・VCC・SCL・SDA・RES・DC)とCS線がそれぞれ1本で合計9本のラインで済むのでArduinoとの接続は10ピン用の端子カバーで綺麗にまとめられた。

また、今回はArduino Nano Everyを採用。USBは以下の製品を使ってマザーボードから直接接続する形とした。

組み込んでみたのがこちら。最初はArduino Unoで検討してたので専用の固定土台を設計しようかと思っていたけどNano Everyならマスキングテープで十分。見える場所ではないし。

ということで外装が完成。

ディスプレイ3台を更新するためのArduinoコードは次のとおり。

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>

#define TFT_CS1        10
#define TFT_CS2        7
#define TFT_CS3        6

#define TFT_RST        9
#define TFT_DC         8

Adafruit_ST7735 tft[] = {
  Adafruit_ST7735(TFT_CS1, TFT_DC, TFT_RST),
  Adafruit_ST7735(TFT_CS2, TFT_DC, -1),
  Adafruit_ST7735(TFT_CS3, TFT_DC, -1)
};

typedef struct { 
  uint16_t color;
  String str;
  byte size;
} message;

message data[3][10];

void reset(int n){
  for(int i=1;i<10;i++){
    data[n][i]={0, "", 0};
  }
}

void setup(void) {
  Serial.begin(9600);
  for(int i=0;i<3;i++){
    reset(i);
    tft[i].initR(INITR_MINI160x80);
    tft[i].setRotation(3);
    tft[i].fillScreen(ST77XX_BLACK);
  }
}

void loop() {
  while (Serial.available() == 0) {
  }
  String s = Serial.readString();
  
  if(s.length()<12){
    Serial.println("NACK");
    return;
  }
  for(int i=0;i<12;i++){
    if(!isDigit(s.charAt(i))){
      Serial.println("NACK");
      return;
    }
  }
  Serial.println("ACK");

  int n = s.substring(0,1).toInt();
  if(n<3){
    data[n][s.substring(1,2).toInt()] = {
      RGB888_to_BGR565(
        byte(s.substring(3,6).toInt()),
        byte(s.substring(6,9).toInt()),
        byte(s.substring(9,12).toInt())
      ),
      s.substring(12),
      byte(s.substring(2,3).toInt())
    };
  } else if (n<6){
    n-=3;
    update_screen(tft[n], data[n]);
  } else if (n<9){
    n-=6;
    reset(n);
  }
}

uint16_t RGB888_to_BGR565(byte red, byte green, byte blue) {
  if(red>255){red=255;}
  if(green>255){green=255;}
  if(blue>255){blue=255;}
  uint16_t bgr565 = 0;
  bgr565 = blue>>3;
  bgr565 = bgr565<<6;

  bgr565 += green>>2;
  bgr565 = bgr565<<5;

  bgr565 += red>>3;
  return bgr565;
}

void update_screen(Adafruit_ST7735 tft, message *m) {
  tft.setTextWrap(false);
  tft.setCursor(0, 0);
  tft.fillScreen(ST77XX_BLACK);

  for(int i=0;i<10;i++){
    tft.setTextColor(m[i].color);
    tft.setTextSize(m[i].size);
    tft.println(m[i].str);
  }
}

シリアル通信で受信した内容を12桁の固定長+可変長のフォーマットで解釈して指定のモニターの表示データを決める仕組みとなっている。

モニターは0~2番までの3台で、データを実際に反映する際はモニター番号に3を足した3~5を指定、データをクリアする場合はモニター番号に6を足した6~8を指定する。

データの解読が完了したらシリアル通信でACKという文字列、エラーならNACKを返す仕組み。
※ACK=Acknowledgement(了承)

実際に送るデータの例はこちら。

600000000000 Deletion
012255255255 CPU Temp
03412812812845 Deg
300000000000 Load

700000000000 Deletion
112255255255 HDD Usage
134255000000 5%
400000000000 Load

800000000000 Deletion
212255255255 Last Logon
232255128128 2024/01/18
500000000000 Load

Linux側からはAWS S3の使用量をあらかじめテキストファイルに保存する仕組みを作っているのでそのテキストから容量を所定のフォーマットにしてArduino側にシリアル通信で送る仕組みを作った。

#!/usr/bin/env python3
import time
import serial
f = open('/mnt/encrypted/Archive/s3usage.txt', 'r')
data = f.readlines()
usage = int(data[1].split(':')[1].strip())/1024**3
usage = round(usage, 5 - len(str(int(usage))))

ser = serial.Serial('/dev/ttyACM0', 9600)
time.sleep(1.5)

ser.write("600000000000 Deletion".encode())
print(ser.readline().strip().decode())
ser.write("012255255255S3 Usage(GB)".encode())
print(ser.readline().strip().decode())
ser.write(("034128128128" + str(usage)).encode())
print(ser.readline().strip().decode())
ser.write("300000000000 Load".encode())
print(ser.readline().strip().decode())

ser.close()

※接続したArduinoはttyACM0というデバイスとして認識された。これは環境によるので注意。また、実行ユーザーをdialoutグループに追加しておかないとttyACM0へのアクセスが拒否されるため注意。

さて、これをcronジョブで任意の時間に実行すれば自動的にアップデートされるようになる。

ということで再度冒頭の写真。

3つのディスプレイのうちあと2つは今のところダミーのHDD容量と実際に更新される現在時刻が入ってるけどこんなところに時計要らないのでこれは変えるつもり。
何を表示させるかはこれから検討しようと思う。

以上。

waves 0.96インチ IPS 液晶ディスプレイのカラー指定で青・赤が逆になるBGR565形式だったため対処のメモ

前回こちらの記事で紹介したディスプレイについて、カラー指定の青と赤が逆になっていて困ったのでその修正方法についてメモしておく。
thom.hateblo.jp

ライブラリ「Adafruit_ST7735_and_ST7789_Library」に入っているサンプルコード「graphictest.ino」内に以下のようなコードがある。

void tftPrintTest() {
  tft.setTextWrap(false);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST77XX_RED);
  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_YELLOW);
  tft.setTextSize(2);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(3);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_BLUE);
  tft.setTextSize(4);
  //以下略

不思議な事にST77XX_REDと指定している部分は青文字でHello World!と表示され、ST77XX_YELLOWと指定しているところは水色でHello World!と表示される。ただ、ST77XX_GREENだけはちゃんと緑色で表示される。

定義がおかしいのかと思って確認してみた。Arduino IDE 2で右クリックして定義に飛ぶことが出来る。

そうすると次のようなコードが見つかる。

// Some ready-made 16-bit ('565') color settings:
#define ST77XX_BLACK 0x0000
#define ST77XX_WHITE 0xFFFF
#define ST77XX_RED 0xF800
#define ST77XX_GREEN 0x07E0
#define ST77XX_BLUE 0x001F
#define ST77XX_CYAN 0x07FF
#define ST77XX_MAGENTA 0xF81F
#define ST77XX_YELLOW 0xFFE0
#define ST77XX_ORANGE 0xFC00

見たことない形式だけどコメントのおかげでこれが16ビットカラーの指定だということが分かった。

一般的にパソコンやWebサイト等の色指定は24ビットとなっており、赤、緑、青をそれぞれ8諧調に分けてその組み合わせで表現される。

例えばArduino IDEのカラーであるブルーグリーンは次のような感じ。

これが16ビットになると赤と青が5諧調、緑だけは人間の感度が高いため6諧調という構成になるようだ。これがRGB565という形式。

ただ商品名にフルカラーモジュールってあるのにほんとに16ビットなのか?と調べたところ、商品名に65kとも書いてあり、調べると約65,000色という意らしい。
2進数で16ビットということは2の16乗で65,536種類の色を表現できるから概算で65kという略記になっているようだ。

で、なんで青が赤になるんだということで調べてみると、どうやらRGBのほかにBGRという方式もあるようで、このディスプレイはRGB565じゃなくてBGR565で指定するとうまくいくことが分かった。

24ビットならRとBを入れ替えるだけなので簡単なんだけど先ほどの図で示した通り16ビットだと切れ目が16進数の2~3桁目が赤と緑、緑と青の情報が混じっているのでちょっと面倒くさい。

そこで変換関数を作って対応することにした。
以下は24ビットのR・G・Bをそれぞれ10進数で受け取り、BGR565に変換する関数である。

uint16_t RGB888_to_BGR565(byte red, byte green, byte blue) {
  uint16_t bgr565 = 0;
  bgr565 = blue>>3;
  bgr565 = bgr565<<6;

  bgr565 += green>>2;
  bgr565 = bgr565<<5;

  bgr565 += red>>3;
  return bgr565;
}

仕組みとしてはこんな感じ。

1) blueを3ビット右にシフトすることで下位3ビットを削ったものをbgr565に代入
2) bgr565を左に6ビットシフトすることでgreenが入るスペースを作り、2ビット削ったgreenを足し合わせる
3) bgr565を左に5ビットシフトすることでredが入るスペースを作り、3ビット削ったredを足し合わせる

この関数は実際にテキストカラー指定に組み込んで使用した。

tft.setTextColor(RGB888_to_BGR565(0,109,112));

非力なArduinoで逐一演算させるのもどうかなとは思ったんだけどもともとプロセッサーはビットレベルの演算が大得意なのでこの程度の計算は朝飯前。私の用途ではテキストをたまに更新するくらいなので仮に遅延が起きているとしても気づかないレベルだった。

以上

Arduino UnoでWaves 0.96インチ IPS フルカラー液晶ディスプレイの使用する方法のメモ

Amazonでwaves 0.96インチ IPS 液晶ディスプレイ SPI 80x160ピクセル 65 k フルカラー モジュール ST7735を購入したので使い方を記録しておこうと思う。

かなり小さいので用途は限られるけど今回サーバーの3.5インチフロントベイが余っているのでそこに組み込めないか思案中。

物理的なサイズとケース等への組付け方法

寸法はこんな感じ。Amazonの写真説明にも寸法図があるけどちょっとごちゃごちゃしていたので自分が見やすいように整理した。

ネジは付属していないのでM2サイズのものを調達する。
表示領域の裏面に表面実装パーツが乘っているので平らな面に組み付ける場合はM2のナットやスペーサー、スタンドオフ等を用いることができる。

私の場合は今回このディスプレイを3つ使用して3.5インチベイに入れたいので3Dプリンターで土台を作成した。

あと、綺麗に見せるためのアイデアとして透明の1mmアクリル板に車のヘッドライト用の減光シートを貼り付けることで基盤を目立たなくしてLED光だけ見えるような仕組みを考えている。

(どうやって組み付けるかはまだ思案中)

Arduinoからの利用方法

使用するライブラリは「Adafruit_ST7735_and_ST7789_Library」。

サンプルからgraphictestを選択して改変していく。

ピン接続

接続ピンはコードから読み取ることになる。
今回はArduino Unoを使用するのでif文のelseの部分が該当する。

表記と接続先のた対応はこちら。

現物の接続図はこちら。

コードの修正

setup関数で使用するディスプレイに合わせてTFTディスプレイの初期化コードを選択する必要がある。
今回紹介したディスプレイの場合、デフォルトのtft.initR(INITR_BLACKTAB);をコメントに変更し、tft.initR(INITR_MINI160x80);のコメントを外して有効化する。

次にディスプレイの出力方向をあわせる。

セットアップ関数の中にSerial.println(F("Initialized"));というコードがあるのでその直前にtft.setRotation(3);を挿入する。

これで出力方向が基盤の向きと揃う。
縦で使いたい場合はそのままでも良い。0~3を指定可能なので他の方向が良ければ試してみると良いと思う。

あとはサンプルのうちやりたいことに近いコードを残して他を削除していじっていくだけ。

以上

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。