2025年9月14日日曜日

CNC Candle

 


【CNCルーター】プリント基板を切断する~実行編

 

※なにか気になる点がありましたらコメント欄からお伝えください。また、CNCルータなど工作機械を操作する場合には、細心の注意を払って行うようお願いいたします。

目次

1.はじめに

 故あってプリント基板を切断することとなりました。今回は今年12月9日に投稿した「【CNCルーター】プリント基板を切断する~準備編」を受けて、実際に生成したGコードをもとにCNCルーターを動かして基板を切断する手順を解説していきたいと思います。

f:id:Tanuki_Bayashin:20211215185505j:plain
図1 切断した基板(バリをとるために小型のルーターを使用した)

2.Gコードについて

 CNCルーターはGコードと呼ばれる1種のプログラムで動作します。FlatCAMで生成されたコードを読み込むと、Gコードで書かれたプログラムがCandle の画面に表示されます。以下に簡単なGコードを列記します。

 G00 :平行移動(低速) G01Ⅹ0.00 で座標Ⅹ0.00(mm)まで移動させるときの命令。
     Y、ℤが指定されていないときはY、Zの値はそのままの状態を維持する。
 G01 :平行移動(高速)。X、Y、Zに移動先の値(mm)を指定する。
 F80.00:移動速度の指定(mm/分)。水平方向(XY平面内)と垂直方向(Z軸方向)の
     2種類が指定可能
 M03 S10000.0:主軸正転 スピンドルモーターの回転数(rpm:正転)を指定できる。
         (左の場合では10000回転を指定している)

 これくらい知っておけば、ある程度、困らないと思われます。詳しく知りたい方は、検索などで調べてください。(CNCルーターにより、機能がないために無効となる命令もある)

3.Candle の使い方

 CNCルーターを動かすソフトの一つに「Candle」と呼ばれるものがあります。下のリンク先からダウンロードできるようです。アンインストールしたいときはフォルダごと、削除すればよいようです。(バージョンはいくつかあるようです)

GitHub - Denvi/Candle: GRBL controller application with G-Code visualizer written in Qt.

f:id:Tanuki_Bayashin:20211215222420p:plain
図2 Candle.exe のダウンロード画面(Github)

 Candle.exe を実行すると図3のような画面が表示されます。また、Gコードのファイルを読み込むと、切削する部分が画像として表示されます。

f:id:Tanuki_Bayashin:20211215222636p:plain
図3 Candle.exeの実行画面

3.1 原点調整

 まず、座標の基準となる原点の調整について記述します。

f:id:Tanuki_Bayashin:20211215224309p:plain
図4 XY座標のリセット、ℤ座標のリセット Z probe
3.1.1 Z軸の調整

 ℤ軸(垂直方向)の原点調整にはℤprobe という便利な機能があります。3018‐PROではコントローラーにA5という接続箇所があります。ここにコードをつなげ、2本の電線をそれぞれ切削する対象と、エンドミルにつなぎます(ドリルの刃でもV 字カッターでも可能)。このとき [ Z probe ]をクリックするとℤ軸が降下してゆきます。

 するとエンドミルが対象物と接することにより2本の電線が導通状態になるので、Z軸がいったん浮き上がり、その後徐々に下に移動し、再び導通するとℤ軸が停止します(動画1 を参照)。この位置でZ軸の値をゼロにリセットすることで、原点調整が可能となります。(プローブに電気が流れることを利用しているので、加工するものが金属でない場合、表面にアルミホイルを張るなど工夫が必要です)

動画1:ℤ軸の原点調整の様子
youtu.be


 3018‐PRO以外のCNCルーターだと、コードが3本必要なものもあるそうなので、その場合はそれに適した方法にて対処してください。

 以下のリンク先のように製品化されているものもあります。筆者は図5のような治具を作り、[ Z probe ]のときに利用しています。プリント基板の切れ端を利用して作りました。厚さは約 1.6mmなので、その分空中にて高さが ‐1.6mmになるようにして、その時点でZ座標を0にリセットしています。

https://tanuki-bayashin.hatenablog.com/entry/2021/12/16/201652  参照

f:id:Tanuki_Bayashin:20211216023407j:plain
図5 Z probe のための治具
3.1.2 X Y軸の調整

 こちらはやや原始的な方法を用いています(図6)。Candle.exe では、Gコードで操作する以外に、X、Y、Z軸をそれぞれ単独で動かす機能もあります(1回のクリックで0.01mmから200mmまでの移動を調整可能)。この機能により、エンドミルの先端を、原点として指定したい辺りまで移動させ、光を当てながら影を見ることで調整しています。

 カメラで撮影した画像を利用したり、光の反射を利用するなどの方法が可能でないか、今後検討したいと思っています。

f:id:Tanuki_Bayashin:20211215214839j:plainf:id:Tanuki_Bayashin:20211215214801j:plain
図6 XY軸の調整(LEDライトを用いている)

3.2 基板の切断(Gコードを実行)

 動画2にて基板を切断している様子を示します。Gコードを読み込むと、図7のように切削する部分が線で描かれます。マウスを使うことにより、向きを3次元で変えることもできます。

 動画2
youtu.be

f:id:Tanuki_Bayashin:20211215233811p:plainf:id:Tanuki_Bayashin:20211215231559p:plain
図7 動作開始(上)と実行中(下)の画面


 切断する対象は、筆者の場合、両面テープにて固定しました。両面テープの厚さにより、削られる深さに変化が出ないように注意が必要かと思われます。
 
 プログラムを動かすには画面下の [ Send ] をクリックします。プログラム中に動作を一旦停止させるような指示があった場合、その地点で一時停止します。準備が整ったら、右上の [ Hold ](図7)をクリックすると、動作が再び開始されます。
 今回の場合、約10分で加工が終わりました。作業にどれくらい掛かるのか、目安となる時間が画面中央に表示されます。
 
 また、プログラムを途中で終了させたいときは、画面下側中央の [ Abort ] をクリックすると作業は終了となります(以降のGコードは無効となります)。

 また、今回の切削では台に当たる部分に板を用いました。木材は湿気で膨張したり収縮すると思われるので、湿気に影響されない樹脂に変えて試してみたいとも思っています。

https://www.footfoot.tokyo/post/2019/candle-pcb  参照

Candleで生基板を切削

Candleで生基板を切削してみる【CNCルーターでプリント基板製作】
前回は回路のG-codeを作ったのでCandleで切削してプリント基板を完成させます。なお穴は開けないズボラな基板になります。

CNCとPCの環境

  • CNCルーター : SainSmart Genmitsu CNC 3018-Pro
  • コントロール基板のファームウェア : GRBL 1.1f
  • PC : Windows10 64bit
  • USBシリアルドライバー : CH340

GRBLコントローラーはGRBL 1.1fに対応してるCandle_1.1.7を使います。SainSmartのキットに付属してる標準の環境です。USBシリアル通信のドライバーのCH340は最新のWin10ではUSBをつなぐだけで認識されたので標準サポートされてるようです。Candleの使い方はCandle Wikiにざっくりとしか書いてないので検索して調べました。

candleの画面

切削の前のセッティング

とりあえずInkscapeで作ったG-codeの.ncのファイルを「File」->「Open」で読み込みます。

CandleとCNCの接続

接続設定は上部メニュー「Service」->「Setting」でポートの更新マークをクリックするとCOMポートを自動で取得してくれます。COM4を選ぶとStatusがIdleになってJogでXYZ軸が動かせました。Settingはその他にたくさん項目がありますがこのままで問題なかったので触らず。

candle 1.1.7の初期設定。ポート設定

生基板を設置

素材の固定は金具は使わずにアクリル板に両面テープで固定するようにしてます。あんまりべったりつけると剥がすのが大変なので7.5cm x 10cmの生基板なら両面テープは5点ぐらいで十分。フレームと平行になるように工作マットを当てて大体テーブルの中央にくっつけました。両面テープはダイソーの「しっかり貼れてはがせる両面テープ」を使用。紙タイプのやつ。

ちなみにこの生基板は1.6mm厚で銅箔35μmのガラスエポキシ(FR-4)で、サイズが大きかったのでPカッターで何回も引っ掻いて割ったんですが硬くて大変でした。紙フェノールとか柔らかめの素材もあるのであとで試そう。このCNCでくり抜いたりするにはガラスエポキシは厳しいかもしれないし。

生基板を固定する両面テープ

XYZ軸をゼロ地点にセット

Gコードの(0,0,0)地点にスピンドルを移動します。XY軸は基板ぴったりだとプローブが使えないので生基板の左下から大体5.08mm内側にJogを操作して合わせました。Stepの値を下げると微調節できます。この5.08mm分(4マス)は予めInkscapeでずらしておいた値なのでこれで作図通りにいくはず。

プローブをV型カッターと生基板に接続

Z軸もゼロ(表面)にします。表面が金属ならプローブで自動で止めることができるので、スピンドルの刃と生基板にプローブを接続をしてControlのZ-probeをクリック。刃が表面についたらControlのZero XYとZero ZをクリックしてWork Coordinateを(0,0,0)にします。これで今の位置がゼロ地点になりました。

candleのゼロ地点の操作。Z-probe,XY Zero,Z ZeroでWork Coordinateをゼロに

Heightmapで高さを補正

Candleにはプローブを使って高さのずれを補正してくれるHeightmapがあります。プリント基板は掘る深さが0.何mmとかで少しのズレで銅箔が削れなかったりするのでheightmapは必須だなと思いました。

まずHeightmapのCreateをクリック。測る範囲がずれてたのでAutoをクリックすると自動で回路の範囲にしてくれました。Probe gridは高さを測るポイントの数で、多ければ精度は増しますが時間がかかります。7cm程度の回路だったので4x4で、Zt(移動時の高さ)は1.0でZb(Z軸の下限)は-1.0で問題なかったです。設定が終わったらProbeで計測開始。

candleのHeightmap設定

計測が終わったらEdit modeで元の画面に戻ります。Use Heightmapにチェックすると今作ったHeightmapが有効になります。スピンドルは終わったところで止まってますが切削を開始するとゼロ地点に戻るのでこのままで大丈夫でした。

candleのHeightmap完了

切削開始

準備が整ったのであとは下にあるSendを押すだけ。

candleでGコードを実行。

シンプルな回路なので2分ちょっとで削り終わりました。Z軸が-0.2mmで先端0.1mm角度20°のVカッターだとこの程度の切りくずで済むんですね。ほとんど飛び散ったりしないので掃除が楽。ハンディタイプの掃除機で吸ってから基板を剥がしました。切削中は振動で音がうるさかったフレームの下にゴムパッド的なのは付けたほうがよさそう。

candleで生基板を切削完了

一時停止はPauseで

何かあったらSendの右横にあるPauseで一時停止できます。スピンドルは回ったままなのでスピンドルも止めるならSpindleの刃のマークをクリック。もう一回押せば再開できます。刃にゴミがくっついた等で使いました。

candleで一時停止。Pauseとスピンドル停止

Resetでも止めることができますがこっちは再開はできません。UnlockでIdle状態に戻して最初からやり直すしかないようです。

candleで停止。ResetとUnlock

ズボラなプリント基板完成

うーんシンプル。こんなのでプリント基板と呼んでいいのかわかりませんが完成。明かりに透かしてみるとちゃんと削れてるかわかりますが大丈夫でした。穴は開けないで部品はそのままはんだ付けします。一応ICのところが1.27mmなのでこのぐらいなら切削できますね。 

2025年7月18日金曜日

Tunneling VLAN

 https://network.yamaha.com/setting/router_firewall/vpn/connect/l2tpv3_ipsec-rtx1200

参照


つの拠点間で同一セグメントのネットワークを構築する

 2023/7/12)

本設定例では、L2TPv3/IPsecトンネル機能を使用しています。

L2TPv3/IPsecトンネル機能の対応機種は、RTX5000(Rev.14.00.12以降)、RTX3510、RTX3500(Rev.14.00.12以降)、RTX1300、RTX1220、RTX1210、RTX1200(Rev.10.01.53以降)、RTX830、RTX810(Rev.11.01.21以降)、NVR700W、vRX(VMware ESXi版)です。

構成図 2つの拠点間で同一セグメントのネットワークを構築する

L2TPv3(Layer 2 Tunneling Protocol version 3)を利用して、複数の拠点で同一セグメントのネットワークを構築する設定例です。
L2TPv3を利用すると、遠隔地にあるヤマハ製のスイッチやアクセスポイントをひとつの拠点でまとめて管理できます。タグVLAN機能やDHCPによるIPアドレス割り当て機能、DHCP認証機能など、レイヤー2のプロトコルを利用した機能を遠隔地の機器に対して設定できます。
また、IPsecを併用して通信を暗号化することでデータの機密性や完全性を確保した、セキュリティーの高いネットワークを構築します。

技術情報:L2TPv3を用いたL2VPN

これから新規に拠点間で同一なセグメントのネットワークを構築したい場合は、本設定例をお試しください。
既存ネットワークのプライベートアドレスが重複しているが変えたくない場合は、こちらを参照ください。

光回線に接続するためには、別途ONUが必要です。
NVR700Wは、本体のONUポートに小型ONUを装着することで、光回線に接続できます。

本機能の対応機種のうち、設定例を掲載している機種は、以下のとおりです。

機種掲載内容備考
本社RTX5000 RTX3510 RTX3500 RTX1300 RTX1220 RTX1210 RTX1200 RTX830 RTX810 NVR700Wコマンド設定例 
拠点RTX1300 RTX1220 RTX1210 RTX1200 RTX830 RTX810 NVR700Wコマンド設定例 

本社 ルーター(1)の設定例

経路の設定ip route default gateway pp 1
ブリッジの設定bridge member bridge1 lan1 tunnel1
ip bridge1 address 192.168.100.1/24
プロバイダーとの接続設定pp select 1
pp always-on on
pppoe use lan2
pp auth accept pap chap
pp auth myname (ISP1に接続するID) (ISP1に接続するパスワード)
ppp lcp mru on 1454
ppp ipcp msext on
ppp ccp type none
ip pp address (本社の固定グローバルIPアドレス)
ip pp mtu 1454
ip pp secure filter in 1020 1030 1040 1041 2000
ip pp secure filter out 1010 1011 1012 1013 1014 1015 3000 dynamic 100 101 102 103 104 105 106 107
ip pp nat descriptor 1
pp enable 1
L2TPv3接続を受け入れるための設定tunnel select 1
tunnel encapsulation l2tpv3
tunnel endpoint address 192.168.100.1 (拠点の固定グローバルIPアドレス)
ipsec tunnel 101
ipsec sa policy 101 1 esp aes-cbc sha-hmac
ipsec ike keepalive use 1 on
ipsec ike keepalive log 1 on
ipsec ike local address 1 192.168.100.1
ipsec ike pre-shared-key 1 text (IPsecの事前共有鍵) # 注釈1
ipsec ike remote address 1 (拠点の固定グローバルIPアドレス)
l2tp always-on on
l2tp tunnel auth on (L2TPトンネル認証に用いるパスワード) # 注釈1
l2tp tunnel disconnect time off
l2tp keepalive use on 60 3
l2tp keepalive log on
l2tp hostname (接続相手に通知するホスト名)
l2tp syslog on
l2tp local router-id 192.168.100.1
l2tp remote router-id 192.168.100.2
l2tp remote end-id (L2TPv3のリモートエンドID) # 注釈1
tunnel enable 1
NATの設定nat descriptor type 1 masquerade
nat descriptor address outer 1 (本社の固定グローバルIPアドレス)
nat descriptor masquerade static 1 1 192.168.100.1 udp 500 # 注釈2
nat descriptor masquerade static 1 2 192.168.100.1 esp # 注釈2
IPsecのトランスポートモード設定ipsec transport 1 101 udp 1701
ipsec auto refresh on
L2TPv3の設定l2tp service on l2tpv3
フィルターの設定ip filter source-route on
ip filter directed-broadcast on
ip filter 1010 reject * * udp,tcp 135 *
ip filter 1011 reject * * udp,tcp * 135
ip filter 1012 reject * * udp,tcp netbios_ns-netbios_ssn *
ip filter 1013 reject * * udp,tcp * netbios_ns-netbios_ssn
ip filter 1014 reject * * udp,tcp 445 *
ip filter 1015 reject * * udp,tcp * 445
ip filter 1020 reject 192.168.100.0/24 *
ip filter 1030 pass * 192.168.100.0/24 icmp
ip filter 1040 pass * 192.168.100.1 udp * 500 # 注釈2
ip filter 1041 pass * 192.168.100.1 esp # 注釈2
ip filter 2000 reject * *
ip filter 3000 pass * *
ip filter dynamic 100 * * ftp
ip filter dynamic 101 * * www
ip filter dynamic 102 * * domain
ip filter dynamic 103 * * smtp
ip filter dynamic 104 * * pop3
ip filter dynamic 105 * * submission
ip filter dynamic 106 * * tcp
ip filter dynamic 107 * * udp
DHCPの設定dhcp service server
dhcp server rfc2131 compliant except remain-silent
dhcp scope 1 192.168.100.3-192.168.100.191/24
DNSの設定dns host lan1
dns server (ISP1より指定されたDNSサーバーのIPアドレス)
dns private address spoof on

拠点 ルーター(2)の設定例

経路の設定ip route default gateway pp 1
ブリッジの設定bridge member bridge1 lan1 tunnel1
ip bridge1 address 192.168.100.2/24
プロバイダーとの接続設定pp select 1
pp always-on on
pppoe use lan2
pp auth accept pap chap
pp auth myname (ISP2に接続するID) (ISP2に接続するパスワード)
ppp lcp mru on 1454
ppp ipcp msext on
ppp ccp type none
ip pp address (拠点の固定グローバルIPアドレス)
ip pp mtu 1454
ip pp secure filter in 1020 1030 1040 1041 2000
ip pp secure filter out 1010 1011 1012 1013 1014 1015 3000 dynamic 100 101 102 103 104 105 106 107
ip pp nat descriptor 1
pp enable 1
L2TPv3接続を受け入れるための設定tunnel select 1
tunnel encapsulation l2tpv3
tunnel endpoint address 192.168.100.2 (本社の固定グローバルIPアドレス)
ipsec tunnel 101
ipsec sa policy 101 1 esp aes-cbc sha-hmac
ipsec ike keepalive use 1 on
ipsec ike keepalive log 1 on
ipsec ike local address 1 192.168.100.2
ipsec ike pre-shared-key 1 text (IPsecの事前共有鍵) # 注釈1
ipsec ike remote address 1 (本社の固定グローバルIPアドレス)
l2tp always-on on
l2tp tunnel auth on (L2TPトンネル認証に用いるパスワード) # 注釈1
l2tp tunnel disconnect time off
l2tp keepalive use on 60 3
l2tp keepalive log on
l2tp hostname (接続相手に通知するホスト名)
l2tp syslog on
l2tp local router-id 192.168.100.2
l2tp remote router-id 192.168.100.1
l2tp remote end-id (L2TPv3のリモートエンドID) # 注釈1
tunnel enable 1
NATの設定nat descriptor type 1 masquerade
nat descriptor address outer 1 (拠点の固定グローバルIPアドレス)
nat descriptor masquerade static 1 1 192.168.100.2 udp 500 # 注釈2
nat descriptor masquerade static 1 2 192.168.100.2 esp # 注釈2
IPsecのトランスポートモード設定ipsec transport 1 101 udp 1701
ipsec auto refresh on
L2TPv3の設定l2tp service on l2tpv3
フィルターの設定ip filter source-route on
ip filter directed-broadcast on
ip filter 1010 reject * * udp,tcp 135 *
ip filter 1011 reject * * udp,tcp * 135
ip filter 1012 reject * * udp,tcp netbios_ns-netbios_ssn *
ip filter 1013 reject * * udp,tcp * netbios_ns-netbios_ssn
ip filter 1014 reject * * udp,tcp 445 *
ip filter 1015 reject * * udp,tcp * 445
ip filter 1020 reject 192.168.100.0/24 *
ip filter 1030 pass * 192.168.100.0/24 icmp
ip filter 1040 pass * 192.168.100.2 udp * 500 # 注釈2
ip filter 1041 pass * 192.168.100.2 esp # 注釈2
ip filter 2000 reject * *
ip filter 3000 pass * *
ip filter dynamic 100 * * ftp
ip filter dynamic 101 * * www
ip filter dynamic 102 * * domain
ip filter dynamic 103 * * smtp
ip filter dynamic 104 * * pop3
ip filter dynamic 105 * * submission
ip filter dynamic 106 * * tcp
ip filter dynamic 107 * * udp
DNSの設定dns host lan1
dns server (ISP2より指定されたDNSサーバーのIPアドレス)
dns private address spoof on

[注釈の説明]

注釈1:
IPsecの事前共有鍵、L2TPトンネル認証に用いるパスワード、接続相手のリモートエンドIDは、それぞれのルーターで同じ文字列を設定します。

注釈2:

2025年7月17日木曜日

Droid VNC

 


ealVNCのダウンロードはこちら

この動画では、RealVNCというVNCビューワを使ってAndroidを遠隔操作したのですが、「droid VNC Server」には、PCやMacのブラウザからでも同じようなことができる機能が搭載されています。

端末にdroid VNC Serverをインストールし、「StartServer」でサーバの起動、「StopServer」でサーバの停止。これだけの操作なので簡単ですね。サーバを起動すると画面したに二つのアクセス方法が表示されます。

上段はVNCビューワ用、下段がブラウザ用。ブラウザ用のURLにアクセスすると、上の動画のような操作がブラウザからでも出来ます。しかし、接続がちょくちょく途切れたりするのでストレスが溜まるかもしれません。

こういったアプリがあれば、Androidのスクリーンショットの撮影ももっと楽になりそうですし、もっと快適にサクサク動くようになればこのままYouTube動画を見ても楽しめそうです。

更新1:遠隔操作していませんでしたね(^^;PCに表示されたホーム画面上をマウスでクリックしたりすれば操作できます。



-----

Fdroid

https://f-droid.org/ja/packages/net.christianbeier.droidvnc_ng/  ここにフォーラム

RasPi キーボード

 


USB Linux Gadgetを使ってRaspberry PiをUSBキーボードと認識させてみた

こんにちは。主に課金周りのサーバーとそのバックシステムを担当しているKです。

皆さんUSB Linux Gadgetをご存知でしょうか。USB Linux GadgetはUDC(USB Device Controller)を備えたデバイスであり、USBホストに接続してシリアルポートやストレージ機能などを追加で拡張することができます。

今回はUSB Linux Gadgetを使ってRaspberry PiをUSBキーボードと認識させて遊んでみました。

準備したもの

  • MacBook
  • Raspberry Pi 4 Model B : OS Linux raspberrypi 5.15.32-v8+
  • Windows11

やってみたこと

Raspberry PiにUSB Linux Gadgetを設定してWindowsにキーボードとして認識させます。

その後、MacからRaspberry Piにキーコードを送ってHIDを通してWindowsにタイプした結果を表示させます。

かんたんな事前知識

USB機器は一見ひとつの機器でも内部的には複数の機能をもつものがあります。これを実現するためにUSBデバイスがどのような仕様のものなのかを、テーブルの形で階層的に保持しています。これをディスクリプタと呼びます。ディスクリプタにはいくつか種類があります。

    • デバイス・ディスクリプタ
      • 一番上のルートに位置するディスクリプタ、ベンダIDやプロダクトIDなどを設定します。
    • コンフィグレーション・ディスクリプタ
      • インターフェース・ディスクリプタとエンドポイント・ディスクリプタの長さや消費電力を設定します。
    • インターフェース・ディスクリプタ
      • ここでインターフェースとしての仕様を設定します。ここに今回の目的であるキーボードであることを設定します。
    • エンドポイント・ディスクリプタ
      • エンドポイントの番号や転送モード、パケットサイズなどを設定します。
    • ストリング・ディスクリプタ
      • デバイスに対する製品名などの文字情報を設定します。これらの情報は任意に設定でき、ホストに接続したときに表示されます。言語ごとに決められたサブディレクトリに構築します。

各ディスクリプタの仕様についてはこちらをご参照ください。

 

今回の機器構成

最初の準備

Raspberry PiにUSB OTGドライバとComposite USB Gadgetsを読み込ませます。

/boot/config.txtに以下を追加します。

dtoverlay=dwc2

/boot/cmdline.txtに以下を追加します。

modules-load=dwc2,libcomposite

間違って記入するとRaspberry Piが立ち上がらなくなるので注意しましょう。

手順

以下、Raspberry Piでの作業です。

デバイスの制御のためにlibcompositeを読み込み、configfsのディレクトリに移動します。

$ modprobe libcomposite
$ cd /sys/kernel/config/usb_gadget/

ガジェットのディレクトリを作成し、移動します。

$ mkdir -p g1
$ cd g1

configfsに設定を書いていきます。各ガジェットには、ベンダーIDと製品IDを登録する必要があります。ベンダーIDと製品IDは各メーカーで個別に決められていますが、今回は以下のものを使います。各ベンダの情報はUSB Information for Developersに記載されています。

デバイス・ディスクリプタの設定の設定をします。

$ echo 0x1d6b > idVendor  # USB IFが割り当てます。今回はLinux Foundationを選択
$ echo 0x0104 > idProduct # ベンダが割り当てます。今回はMultifunction Composite Gadgetを選択
$ echo 0x0100 > bcdDevice # BCD表現のデバイスのリリース番号 v1.0.0にしておきます
$ echo 0x0200 > bcdUSB    # BCD表現のUSB仕様リリース番号 USB2.0にします。

ストリング・ディスクリプタを作成します。

$ mkdir strings/0x409
$ echo "12345678"    > strings/0x409/serialnumber
$ echo "KeyboardTestCCN." > strings/0x409/manufacturer
$ echo "Generic USB Keyboard"  > strings/0x409/product

Functionsの設定をし、レポートディスクリプタを設定します。レポートディスクリプタはデバイスからホストに通知するデータフォーマットを定義するものです。こちらを参考にします。

$ mkdir -p functions/hid.usb0
$ echo 1 > functions/hid.usb0/protocol  # キーボード
$ echo 0 > functions/hid.usb0/subclass  # subclass設定しない
$ echo 8 > functions/hid.usb0/report_length
$ echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.usb0/report_desc

コンフィグレーション・ディスクリプタを設定します。

$ mkdir -p configs/c.1
$ echo 250 > configs/c.1/MaxPower

 

$ mkdir -p configs/c.1/strings/0x409
$ echo "Config 1" > configs/c.1/strings/0x409/configuration
$ ln -s functions/hid.usb0 configs/c.1

最後にガジェットを有効化します。後にデバイスにキーコードを送るために権限をつけておきます。

$ ls /sys/class/udc > UDC
$ chmod 777 /dev/hidg0

以上で設定は完了です。Raspberry Piを再起動するとすべての設定が消えてしまいますので、スクリプト化しておくかserviceに登録することをおすすめします。

Windowsでキーボードとして認識されたことを確認する

WindowsでRaspberry Piをキーボードとして認識しているか確認します。

USBデバイスをUSB Device Tree Viewerで見るとちゃんと認識されていました。設定したディスクリプタも確認できます。

Raspberry Piでキーコードを送ってみる

ちゃんとキーボードとして動作するのかやってみます。

以下のコマンドで”a”を押しっぱなしにするキーコードを送ってみます。

$ echo -ne "\0\0\x4\0\0\0\0\0" > /dev/hidg0

あらかじめWindowsでは”a”を表示させるためにエディタを開いてカーソルを置いておきました。キーコードを入力後、エディタをみるとaがずっと入力され続けている様子が見れます。

 

キーを離すキーコードを送ると入力が止まります。

$ echo -ne "\0\0\0\0\0\0\0\0" > /dev/hidg0

おまけ

Raspberry Pi 4 model Bから電源アダプターがUSB-Type Cに変更されています。最初、WindowsにUSBで接続してそのまま給電できるかと思ったのですが電圧が足りずOSが起動しませんでした。しかしWindowsとはUSB TypeCの口を利用して繋ぎたいのでどうしたものかと考えた結果、GPIOから給電させてみたらいけるのではないかとやってみましたら無事起動しました。以下のコマンドで電圧不足をみてlogがでていなかったので足りたのでしょう。

 

$ journalctl -xe | grep "Under-voltage"

まとめ