SketchUp Make を使っていたのは多少慣れていたから以外の理由は特になくて、最近だと無料版の Make の機能がヘボすぎて辛くなってきた。

そして Autodesk Fusion 360 が小規模開発者には無料で使えるのを知らなかった。(123 だけ無料だと思っていた) 普通にフル機能が使えるっぽいので使いはじめてみた。一言でいうと、普通に最高。

やってみた雰囲気

フォトカプラ的なもの (多少実際のモデルと異なります)

ロータリーエンコーダー風のもの

位置的にちゃんと光軸通るの?ってのを探ってる

周辺環境とがっちゃんこしたやつ

回るんやで

CAM まで内蔵されてるんやで

できたで (※これは3D CGではありません)

温度感

2D で「スケッチ」を描いてプッシュ/プルで形成していくので、SkechUp と比べてイメージの書き下し手順には大差なく、Fusion 360 のほうが高機能なのでかなりやりやすい。

上のように手にとれる立体をつくるまで、モデリングに3、4時間、切削の4時間ぐらい(ハマリも含めて)。

思いのほかモデリングが楽で「こうしたい」と思ったことはだいたいできた。スケッチを複製して別の面に移動するみたいなことはできない? っぽくて、プッシュプルで頑張ったけど、やりかたはありそう…

YouTube に公式の日本語チュートリアルがあるので、ぼーっと見とくだけで全能感が産まれる。

ワークフロー

スケッチと呼ばれる 2D 図面を起こしてから、3D モデルに変換していく。

図形は最初から完璧に配置する必要はない。図面に寸法を記入すると、自動的に図形の形が正しい形になる。

拘束という仕組みがあり、辺と辺・点と点の関係を定義すると、図形に他の変更を加えても、その関係が維持されるようになる。寸法も拘束の一種といえる。宣言的プログラミング (制約プログラミング) を GUI でできる感じ。

長方形などのプリミティブな図形は、簡単に図形が描けるだけではなく、自動的に拘束が定義される。

タイムライン

まず、これはアンドゥ機能ではない。

作業のある時点に遡って変更を行え、それに依存する他の作業すべてに影響を及ぼす。過去改変のコマンド。

CAM まわりの罠

Grbl な環境でめちゃくちゃな動きをしまくってハマりまくった。CAMotics とかでシミュレーションさせたりしてもおかしくなくて、実機で動かして初めて分かる不具合だったのでかなり難儀した (安いエンドミル数本と高いエンドミル1本をダメにした)

以下のようにすること

  • minimumCircularRadius を 1000 とかにする (ARC コマンドをやめて全て直線で出力)
  • 出力ファイルを nkf -Lu --overwrite 1.nc とかして改行コードを unix にすること (Fusion 360 は CRLF を吐くが、LF にしないとなんか謎のぶっこわれたパスを描いてしまうことがあった)

  1. トップ
  2. tech
  3. SketchUp Make を捨てて Autodesk Fusion 360 に移行した

久しぶりに歯医者。クリーニングといって、メンテナンスだけで虫歯というわけではない。半年毎になってるんだけど、用事が多くて前回からかなり時間が開いてる。

歯茎がさがっていて、噛み締めが多いからじゃないか。1日の終わりに反省すると寝てる間に歯ぎしりしやすいから反省するな、と言われる。無理やで

やっぱり飲み会とか好きじゃない。独りでアニメを見ながら「ひふみん可愛いデォユフフwww」とか言いながら酒を飲むのが最高であって、意識高い話をしながら酒を飲んでも特に何も産まれない。

これは切り替えの問題なのだ。酒を飲んでるとは難しいことを考えてはならない (MUST)。複雑なことをすると複雑な問題をひきおこす。

家で酒を飲んでアニメを見ていれば、酒臭くてうぜぇなみたいな話にはならないし、好きなように好きなような酒を飲んで好きなように酔っぱらって好きなようにインターネットがができる。辛い思いをする必要はどこにもない。


ツイッターとかフェイスブックとかを止めてるが、書きこみを止めているだけで、投稿はたまに見ていたりする。投稿を見た結果「やっぱ見ないほうがいいな」と思うが、投稿自体に制約を設けると「生きてる証明をなにかしらで示さなければ」と思う。そうすると (自分の中では) 価値のあるトピックでエントリーを書こうという気になる。この世界では、クソ短文で承認欲求を満たしてはならない。

何がいいたいかというと、「見ないことに価値がある」と思ってはじめてみたが、意外にも「見ても、反応・投稿しないことに価値がある」ということがわかったことだ。すべての情報は一度飲みこまなければ吐きだしてはならない、という制約をつけることによって、(自分の中では) より価値の高いものがアウトプットできる。


はてブもやっぱ見ちゃうことがあるけど、クソみたいな意識高い高いエントリについてる目線だけ高い高いブコメとか、おまえも同様にクソだろとしか思えない。クソがクソ叩いて喜んでる。クソがクソ叩いてるのを喜んでるクソがオレ。ブルーハーツって未だにテレビとかで曲がかかってすごいよなあ。弱いものたちが夕暮れ〜さらに弱いものを叩く〜。クソの連鎖。評価基準がクソなせいだと思う。ちゃんと作ってるか成長しているかが最重要。ウィーウィルベカームシルエッツ。


3D CAD をやってみて、やはりプログラミングを先にいろいろやっていて良かったと感じる。仕事で「プログラミングできて良かった」と思うことは極めて稀だが、趣味でいろんなことをしてみると全く「プログラミングをできて良かった」と思うことが多い。拘束とは制約プログラミングだと気付ければ難しいことが一切なくなり、便利さだけが理解できる。

「趣味」をバカにして「仕事こそが人生の意義だ」みたいなことを言うひとがいるが、全く間違いであり、そういう言い草は全く気にくわない。そういう人は単に仕事が趣味なのであって、趣味をバカにしている。趣味こそが全身全霊をささげるべき対象であって、仕事は単にそのために金を稼ぐ手段であるか、ないしは趣味で培った力の一部を社会に還元する行為である。


街には「地域ぐるみでなくそう路上喫煙」とか旗が立ってたりするが、喫煙者はすぐそばで路上喫煙をする。彼らは文字が読めないので仕方がない。対応策が間違っているのだ。喫煙者はなぜか人間として扱われているが、識字率99%以上のこの国で文字が読めないので、初等教育も受けていないことは明白であり、人間のような姿に見える他の生物である。JT とかいう独占企業があってモラルを啓蒙して「おれは悪くない」アピールをしているが、そもそも人間ではない生物にはモラルなどなく、判断能力のないそれに、中毒症状をいいことに薬物を売りつけるのが JT であって、今すぐにでも滅びなければならない。

不思議なのはそれのカタチが人間であるおかげで、人間として扱われれいて、人権が保証されているところである。人間は呼吸をしなければ生きていけず、空気の汚染は健康に直結する。それが環境を汚染して人間をいくら傷つけても、それが「薄く広い」殺人ならば罪にはならない。いくら薄く広く子供を殺して、あるいは子供以外の人間を殺してもそれは罪に問われない。どこから人権が生じるのだろうか? 人権のある生物から産まれれば人権があるのだろうか? 公共の福祉とはなんなのだろうか? 憲法に定められた「健康で文化的な最低限度の生活」における健康ってなんなのだろうか。「人民の健康が最高の法たるべし」ではないのだろうか? いったいそれにはいつ罰が与えられ、人間は健康に人生を過ごすことができるのであろうか?


(このエントリはクソよっぱらってクソのように世の中を思いながら書きました)

今まで SketchUp + SketchUCam で雑にポケット加工の機能を使って生成してたりしていたのですが、思うような G-Code になかなかならなくてダルくなったので自力で書くことにしました。

加工範囲ぎりぎりを動かすので、いつもリミットにあたらないか心配しながらやってたのですが、そのへんを考慮するようにしました。

今いちスタンダードなやりかたがわからないのですが、中央から削っていくようにしてみました。このほうがゴミが残りにくいかな?

あと面出しって英語でなんて言うかわからなくて検索できませんでした。

#!/usr/bin/env ruby -v

io = $stdout

=begin
使いかた:
 1. 面出し範囲のX軸幅・Y軸幅を測ってパラメータを変えておく
 2. 面出し範囲の左下に原点をあわせる
 3. G-code を生成して流す
=end

# 加工面のX軸の幅
x_size = 201
# 加工面のY軸の幅
y_size = 151
# 削る厚さ
cut_thikness = 0.1
# 使用するエンドミルの直径
tool_diameter = 6.0
# 削りのオーバーラップ割合
overwrap = 0.9
# 加工フィードレート
feed   = 500
# セーフレベル
z_safe = 1

###
io.puts "G94 ( mm/min feed rate. )"
io.puts "G21 ( Use mm )"
io.puts "G90 ( Absolute distance )"
io.puts "M3 S10000 (Start Spindle)"
io.puts

# 原点が面出し表面の左下にあること前提
# 念のためリミットにひっかからないことを確認するため、最初に外形を一周する
# この生成プログラムでは座標が加工原点からマイナスにいったり、
# 設定した x_size/y_size を超えることはない
# 一方で、加工原点や x_size/y_size からはエンドミル半径分はみだして切削する
# これは削り残しがないようにするためで意図的

io.puts "G0 Z%.5f" % [z_safe]
io.puts "G0 X%.5f Y%.5f" % [0, 0]
io.puts "F%.5f" % [feed]
io.puts "G1 Z%.5f" % [-cut_thikness]
io.puts "G1 X%.5f Y%.5f" % [0, y_size]
io.puts "G1 X%.5f Y%.5f" % [x_size, y_size]
io.puts "G1 X%.5f Y%.5f" % [x_size, 0]
io.puts "G1 X%.5f Y%.5f" % [0, 0]
io.puts "G0 Z%.5f" % [z_safe]

# 中央から外形に向かって削る
begin
	x_steps = ( x_size / (tool_diameter * overwrap) ).ceil
	y_steps = ( y_size / (tool_diameter * overwrap) ).ceil
	steps = [x_steps, y_steps].min

	# 切削中のrectサイズ
	x_center = x_size / 2.0
	y_center = y_size / 2.0
	x_current_size = 0
	y_current_size = 0

	# 削りはじめ、XとYで差があるので、まずはそれを埋める
	case
	when x_size > y_size
		x_current_size = (x_steps - y_steps - 1) * (tool_diameter * overwrap)
		x_offset = (x_size - x_current_size) / 2.0

		io.puts ""
		io.puts "(initial line)"
		io.puts "G0 Z%.5f" % [z_safe]
		io.puts "G0 X%.5f Y%.5f" % [x_offset, y_center]
		io.puts "G1 Z%.5f" % [-cut_thikness]
		io.puts "G1 X%.5f Y%.5f" % [x_offset + x_current_size, y_center]
	when y_size > x_size
		y_current_size = (y_steps - x_steps - 1) * (tool_diameter * overwrap)
		y_offset = (y_size - y_current_size) / 2.0

		io.puts ""
		io.puts "(initial line)"
		io.puts "G0 Z%.5f" % [z_safe]
		io.puts "G0 X%.5f Y%.5f" % [x_center, y_offset]
		io.puts "G1 Z%.5f" % [-cut_thikness]
		io.puts "G1 X%.5f Y%.5f" % [x_center, y_offset + y_current_size]
	else
		# nothing to do
	end

	# 少しずつ広げながら削る
	# 外形は最初に一度削っているが、内側の削りカスを除去するためにも再度削る
	steps.times do |step|
		x_current_size += (tool_diameter * overwrap)
		y_current_size += (tool_diameter * overwrap)
		xx = x_current_size / 2.0
		yy = y_current_size / 2.0
		io.puts ""
		io.puts "(step %d)" % step
		io.puts "G1 X%.5f Y%.5f" % [x_center + xx, y_center + yy]
		io.puts "G1 X%.5f Y%.5f" % [x_center - xx, y_center + yy]
		io.puts "G1 X%.5f Y%.5f" % [x_center - xx, y_center - yy]
		io.puts "G1 X%.5f Y%.5f" % [x_center + xx, y_center - yy]
		io.puts "G1 X%.5f Y%.5f" % [x_center + xx, y_center + yy]
	end
end

io.puts "G0 Z%.5f" % [z_safe]
io.puts "M5 (Stop Spindle)"
io.puts "M2 (Program End)"

% 演算子とか、もろもろが便利なので Ruby で書きましたが、再代入禁止の変数が欲しいですね。定数だとおおげさなので……

  1. トップ
  2. tech
  3. CNC フライスで加工台の面出しをするG-Codeを生成するRubyスクリプト

Universal Foldable Keyboard のレビュー

結局 amazon.com (US) から買ってみました。ちゃんと技適マーク付きのが来ました。日本で買うより安いです。

説明書が入ってなくて、なんかよくわからんイラストだけです。IKEA の説明書みたいなやつと言えばわかる人にはわかるでしょう。

配列自体は変態配列で、たとえ US 配列でも普通のキーボードと比べて打ちやすくはないです。右側はキー数が多いせいでピッチが狭かったり、中央付近で折れる構造のために中央付近のキーがなんか変な感じがします。

よくできてるなと思ったところは

  • 同時に2つペアリングができて、ボタン1発で切替えができる
  • OS切替ボタンがあって、Windows/Android/iOS でキーマップが変わるようになっている

あたりです。

同時に2つペアリングするやつは、それぞれに別々の BLE アドレスがふられているので、近くにある別々の機器に同時にペアリングして、ボタンで切替えながら入力先を変更できるので、Windows/Mac で開発しながら、Android もデスクに置いて切替えて入力するみたいなことができて便利そうです。

Universal Foldable Keyboard の仕様

まぁレビューするために買ったんじゃないんですよ。BLE キーボードの参考実装として買ったのです。ということで以下技術的な仕様をレビューします。

GATT 構造のダンプ

以下のようになっています。Device Information の Firmware Revision に CSR uEnergy SDK 2.4.2 と入っていたので、CSR のチップなのでしょう。Unknown Service が2つありますが、CSR の DFU まわりのためのサービスのようです。

HID Information の Base USB Specification Version に 0x213 が入っていて異常です。HID のスペックは 1.11 が最新のはずなので、(BCD で) 0x111 とかが正しいと思うのですが、2.13 という謎のバージョンになっています。

Device Information Service の PnP ID は source=USB VID=0x45e PID=2060 version=272 でした。

Connection Parameter は

  • 15ms - 15ms
  • Slave Latency 33
  • Supervision Timeout: 600

でした。

他には特に気になるところはありません。

Generic Attribute (0x1801)
- Service Changed [I] (0x2A05)
   Client Characteristic Configuration (0x2902)
Generic Access (0x1800)
- Device Name [R W] (0x2A00)
- Appearance [R] (0x2A01)
- Peripheral Preferred Connection Parameters [R] (0x2A04)
Human Interface Device (0x1812)
- Report Map [R] (0x2A4B)
   External Report Reference (0x2907)
- Report [N R] (0x2A4D)
   Client Characteristic Configuration (0x2902)
   Report Reference (0x2908)
- Report [N R] (0x2A4D)
   Client Characteristic Configuration (0x2902)
   Report Reference (0x2908)
- Report [R W WNR] (0x2A4D)
   Report Reference (0x2908)
- Report [R W] (0x2A4D)
   Report Reference (0x2908)
- HID Information [R] (0x2A4A)
- Boot Keyboard Input Report [N R] (0x2A22)
   Client Characteristic Configuration (0x2902)
- Boot Keyboard Output Report [R W WNR] (0x2A32)
- HID Control Point [WNR] (0x2A4C)
- Protocol Mode [R WNR] (0x2A4E)
Battery Service (0x180F)
- Battery Level [N R] (0x2A19)
   Client Characteristic Configuration (0x2902)
   Report Reference (0x2908)
Unknown Service (a74df799-13fd-4f82-a45a-0340180eac97)
- Unknown Characteristic [R W] (343f8f87-ec68-41a7-a97f-3141b2424e1d)
Unknown Service (00001016-d102-11e1-9b23-00025b00a5a5)
- Unknown Characteristic [R W] (00001013-d102-11e1-9b23-00025b00a5a5)
- Unknown Characteristic [W] (00001018-d102-11e1-9b23-00025b00a5a5)
- Unknown Characteristic [N R] (00001014-d102-11e1-9b23-00025b00a5a5)
   Client Characteristic Configuration (0x2902)
Device Information (0x180A)
- Firmware Revision String [R] (0x2A26)
- PnP ID [R] (0x2A50)
Scan Parameters (0x1813)
- Scan Interval Window [WNR] (0x2A4F)
- Scan Refresh [N] (0x2A31)
   Client Characteristic Configuration (0x2902)   

HID ReportMap

Report Map を読み出して、人力でパースしました。自動的にパースしてダンプしてくれるツールってないんですかね? おかげで人力で結構 HID Report Map が読めるようになってしまいました。

概要としては

  • report id = 1 が通常のキーボードのレポート
    • ただし feature report の定義もある (詳細は不明)
  • report id = 3 がメディアキーとかのレポート
    • 音量とか再生ボタンとか

report id = 2 が抜けてますが、Report Map Characteristics に External Report Reference Descriptor がついており、Battery Level Characteristics の UUID が入っていました。そして Battery Level Characteristics に Report Reference Descriptor がついており、report id = 2 / input report として定義されていました。これって HID の Report Map の中には定義しなくていいんでしょうか? HOGP とかの仕様書を読んでもどうしてもよくわからないのですが…… HID にもバッテリー情報を送る決まりはありますが、それは関係ないんでしょうか。(というか BLE のバッテリー情報に主要OSが対応してないのでどうしよもないです)

feature report の仕様はよくわかりません。MS 提供のツールで、言語設定を上書きできるので、これの操作に使われているような気がしています。

05-01 Usage Page (Generic Desktop)
09-06 Usage (Keyboard)
A1-01 Collection (Application)
	85-01 Report ID (0x01)
	05-07 Usage Page (Key Codes)
	19-E0 Usage Minimum (224)
	29-E7 Usage Maximum (231)
	15-00 Logical Minimum (0)
	25-01 Logical Maximum (1)
	75-01 Report Size (1)
	95-08 Report Count (8)
	81-02 Input (Data, Variable, Absolute); Modifier data

	95-05 Report Count (5)
	75-01 Report Size (1)
	05-08 Usage Page (Page# for LEDs)
	19-01 Usage Minimum (1)
	29-05 Usage Maximum (5)
	91-02 Output (Data, Variable, Absolute) ; LED report

	95-01 Report Count (1)
	75-03 Report Size (3)
	91-03 Output (Constant, Variable, Relative) ; padding

	95-07 Report Count (7)
	75-08 Report Size (8)
	16-00-00 Logical Minimum (0)
	26-FF-00 Logical Maximum (255)
	05-07 Usage Page (Key Codes)
	19-00 Usage Minimum (0)
	2A-91-00 Usage Maximum (145)
	81-00 Input (Data, Array, Absolute); Key arrays

	05-0C Usage Page (Consumer)
	0A-C0-02 Usage (0x02c0/704 ?)
	A1-02 Collection (Logical)
		85-01 Report ID (0x01)
		1A-C1-02 Usage Minimum (705)
		2A-C6-02 Usage Maximum (710)
		75-08 Report Size (8)
		95-06 Report Count (6)
		B1-03 Feature (Content, Variable, Relative)
	C0 End Collection
C0 End Collection

05-0C Usage Page (Consumer)
09-01 Usage (Consumer Control)
A1-01 Collection (Application)
	85-03 Report ID (0x03)
	75-10 Report Size (16)
	95-01 Report Count (1)
	15-01 Logical Minimum (1)
	26-FF-03 Logical Maximum (1023)
	19-01 Usage Minimum (1)
	2A-FF-03 Usage Maximum (1023)
	81-60 Input (No Preferred, Null state)
C0 End Collection

ドライバ

Windows に接続すると、専用のドライバが読みこまれることを確認しました。なんのためにそうなっているのかよくわかりませんが、明確に Windows の汎用 kbdhid ドライバとは違いがあります。

自作キーボードを Universal Foldable Keyboard に成り済まして検証する

だいぶあれ気ですが、PnP ID を偽称して Universal Foldable Keyboard に成り済まして消費電流を検証しました。Universal Foldable Keyboard を買ってやりたかった一番のことがこれです……

結果的に、汎用 kbdhid ドライバだと 800μA ぐらいの消費が、Universal Foldable Keyboard のドライバを読みこませることで 200μA まで減るということがわかりました。ドライバ内でなにかしら調節しているようです。チートかよ。

備考:Windows のドライバロード手順

デバイスが接続されると以下のディレクトリの .inf からデバイスドライバが検索される。BLE 接続後、しばらくプログレスバーが表示されるが、これを検索している時間分待たされるっぽい。

C:\Windows\System32\DriverStore\FileRepository

.inf の中に以下のような行がある。

%UniversalFoldableKeyboard.DeviceDesc% = UniversalFoldableKeyboard, HID\{00001812-0000-1000-8000-00805f9b34fb}_Dev_VID&02045e_PID&080c&Col01


ここのやつがデバイスとマッチするとドライバがロードされる。VID/PID は PnP ID、Col01 は HID の Report Map の中のコレクションの Report ID ?っぽいがよくわからない。Collection もうまく一致していないとロードされない。

一致するドライバがみつかると C:\Windows\INF 以下に oemNN.inf oemNN.PNF としてコピーされる。次回からはここの .inf が読まれるのですぐ接続される。

  1. トップ
  2. tech
  3. Microsoft Universal Foldable Keyboard (US版) を買ってみたら辛い事実がわかった