3Dプリンタ作例/LEGO互換部品 の履歴(No.7)
更新LEGO の互換パーツを作りたい†
格安3Dプリンターとしては非常に高い精度を要求されることになるため、いろいろと工夫が必要だった。
試作品1†
上面にサポートを付けるわけにいかないので、内部にサポートを付けた。
真ん中の中空円柱が底面が小さくて浮いてしまうため1層のラフトを付けたのだけれど、 ベッドの高さ調整が悪かったのかどうか、あまりきれいにできなかった。
さらに、寸法通りにいかないところがあるので微調整が必要みたい。
四角い部分、15.80 mm の設計が、X 方向は 15.90 mm, Y 方向は 15.65 mm となっていた。 Y 方向のバックラッシュが少し大きくなってきているのかもしれない、とも思ったのだけれど、 いろいろよく測ってみると太っているのはカドの部分だけで、中央部分を測ると X 方向 15.69 mm Y 方向 15.61 mm で、そこまで大きな違いはなかった。
伝説の「リニアアドバンス」の設定で解決できるという、カドの部分でフィラメントが過剰に 押し出されてしまう影響を受けているのかもしれない。
丸く突き出た頭の部分は X 方向も Y 方向も 4.70 mm だった。 設計値は 4.90 mm なので 0.2 mm も細くなってしまっている。
四角部分の高さは 9.65 mm を指定したところ、中央で 9.7 mm カドで 9.86 mm になっていた。 ここはあまり効かないので、まあこのくらいでも。
内部の円柱外径は 6.50 mm 指定のところ 6.45 mm だった。
実際のはめ合いは上も下もかなり緩いので、要改善点として重要そうなのは、
- 頭の直径を 0.2 mm 増やす
- 内部円柱の外径を 0.1 mm 増やす
- 底面をきれいに印刷できるよう温度と距離を調節しよう
としてみよう。
試作品2†
- 頭の直径を 0.2 mm 増やす
- 内部円柱の外径を 0.1 mm 増やす
をしたところ、
頭が大きくなりすぎた。0.1 mm 減らそう。このくらいになってくると Y 軸のバックラッシュが気になるかも。 0.1 mm くらい、ソフト的な処理で対応する?
円柱外径はかなり良くなったけどまだ足りない。内径がぜんぜん足りず、中に頭が入らない。 円柱内径も増やそうか?
四角の四隅が少し下に飛び出すためかみ合わせが悪くなって困る。
このあたりは寸法で調整もできなくはないのだけれど、本来はやはりリニアアドバンスなどで対応するべきなんだよなあ。。。 ファームウェアの書き換えも含めて、もう少し本腰を入れて調べてみようかしら。
こういうのは OpenSCAD が良いみたい†
OpenSCAD でしっかりプログラムしておくと、パラメータとして与えた任意のサイズのブロックを自動的に生成できた。
また以下の工夫で十分に実用になる精度で出力できた。
- モデル
- 外寸は正規品に合わせて 8 mm の倍数から少々のクリアランス分を引いてある(width_delta)
- 1列の時と2列以上の時とを if で分けて、内部に円筒を生成するか、棒を生成するかを自動的に切り替えた
- 2列以上の時にはブリッジが長くなりすぎないように4辺から、および円筒から、サポートを伸ばした
- 縦になる四辺の周囲が膨らんでしまう現象は、これらの辺を面取りすることで防げた(wall_bevel)
- 同様に、下面の四隅のカドが膨らんでしまう現象も、このカドの部分を面取りすることで防げた(bottom_bevel)
- 上部の円柱外径や、下部の円筒台形、下部の棒の外径、箱の内寸は実測を元に設計値へ補正を加えた値を指定した
- この部分は「ズル」なのだけれど、どうしても必要だった
- スライス
- 側面の凹凸を十分に小さくするため 0.1 mm で積層
- 高さを正確に合わせるために2層のラフトを敷いてその上に生成
- インターフェースレイヤーを2層としたため実際には密に埋めた2層のレイヤー上に生成したことになる
- サポートとオブジェクトの距離は 0.15 mm
- 底面積が小さいのでこのくらい小さくしてもはがせる
- バックラッシュ補正
- 機械的にベルトの張りを調整してできるかぎりバックラッシュを小さくした
- 0.1 mm 以下のバックラッシュをソフト的に補正した
本来であれば、カドが膨らむ現象はリニアアドバンスの設定で解決すべきなのですが、 今のところはファームウェアに手を加えていないのでそのような設定ができず 小手先で対応するしかありませんでした。 一方、どうしてもこれが問題になる場合に面取りで解決できることが分かったのは収穫でした。
円筒や円柱の外径が設計値と大きくずれるのは熱膨張の影響なのか何なのか、 トライアンドエラーで補正値を求めなければならないのは嫌な感じ。 0.1 mm 程度の精度を求めようとすると仕方がないのものなのかどうか。
lego_block.scad
LANG:scad // 鏡像を複製する module sym_m(d=[1,0,0], p=[0,0,0]) { children(); translate(p) mirror(d) translate(-p) children(); } // 直交する鏡2枚分の鏡像を複製する module sym_2m() { children(); mirror([0,1,0]) children(); mirror([1,0,0]) { children(); mirror([0,1,0]) children(); } } // 回転対称で複製する module sym_c(n, axis=[0,0,1]) { for(r=[1:n]) rotate(r*axis*360/n) children(); } // 単純なレゴブロックを作る // 面積 n x m 高さ l // シートを作るには l = 1/3 にする module lego_block(n=2,m=2,l=1, width_delta=0.08, width_unit=8, wall_thick=1.55, wall_bevel = 0.4, corner_bevel = 0.8, height_unit=9.6, ceil_thick=1, prot_diameter=4.9 + 0.1, prot_height=1.7, prot_bevel = 0.15, bottom_d1 = 6.5, bottom_d2 = 4.9, bottom_d3 = 3.1 + 0.18, epsilon = 0.01, fn = 80, bottom_lp = 0.42, bottom_bevel = 0.2 ) { // n < m のときは n と m とを切り替え n > m で生成してから転置する if(n < m) { mirror([-1,1,0]) lego_block(n=m, m=n, l=l, width_delta=width_delta, width_unit=width_unit, wall_thick=wall_thick, wall_bevel = wall_bevel, height_unit=height_unit, ceil_thick=ceil_thick, prot_diameter=prot_diameter, prot_height=prot_height, prot_bevel = prot_bevel, bottom_d1 = bottom_d1, bottom_d2 = bottom_d2, epsilon = epsilon, fn = fn, bottom_lp = bottom_lp, bottom_bevel = bottom_bevel ); } else { // 以降は必ず n > m になっているはず translate([ width_unit*n/2, width_unit*m/2, 0]) { // 四角い枠 difference(){ // 外枠の直方体 translate([0, 0, -l*height_unit]/2) cube([ width_unit*n - width_delta, width_unit*m - width_delta, l*height_unit], center=true ); // 裏側の抜き translate([0, 0, -l*height_unit-ceil_thick]/2) cube([ width_unit*n - wall_thick*2, width_unit*m - wall_thick*2, l*height_unit], center=true ); // 面取り sym_2m() { // 縦の辺の面取り translate([ width_unit*n - width_delta, width_unit*m - width_delta, -l*height_unit]/2) rotate([0, 0, 45]) cube([wall_bevel,wall_bevel,l*height_unit+0.1], center=true); // 下面の角の面取り translate([ width_unit*n/2 - width_delta, width_unit*m/2 - width_delta, -l*height_unit]) rotate([0,0,1]*45) rotate(atan(2/sqrt(2))*[0, 1, 0]) cube([1,2,2]*corner_bevel, center=true); } } } // 上部に出っ張る円柱 for(i=[0:n-1]) { for(j=[0:m-1]) translate([ width_unit*(i+1/2), width_unit*(j+1/2), 0]) intersection() { // 上の円柱 cylinder( prot_height, d=prot_diameter, $fn=fn); // 面取り cylinder( prot_height, r1=prot_diameter-prot_bevel, r2=prot_diameter/2-prot_bevel, $fn=fn); } } // m >= 2 では内部に筒を持つ if(m >= 2) { // サポートが外枠からはみ出さないように制限 intersection(){ translate([ width_unit*n/2, width_unit*m/2, 0]) translate([0, 0, -l*height_unit]/2) cube([ width_unit*n - width_delta, width_unit*m - width_delta, l*height_unit], center=true ); union () { // 円筒の生成 for(i=[1:n-1]) for(j=[1:m-1]) { difference() { union() { // 下向きの円筒の外周 translate([ width_unit*i, width_unit*j, -l*height_unit]) cylinder( l*height_unit, d=bottom_d1, $fn=fn); // 円筒から伸びるサポート translate([ width_unit*i, width_unit*j, 0]) sym_c(4) translate([(bottom_d1+bottom_d2)/4,0,0]) rotate([0,45,0]) cube([bottom_lp,0.2,bottom_lp]*width_unit,center = true); } // 円筒の内側をくり抜く translate([ width_unit*i, width_unit*j, -l*height_unit]) translate([0,0,-0.1]) cylinder( l*height_unit+0.2, d=bottom_d2, $fn=fn); } } // 壁から伸びるサポート sym_m([0,1,0], [0,width_unit*m/2,0]) for(i=[1:n-1]) { translate([ width_unit*i, wall_thick, 0]) rotate([0,0,90]) rotate([0,45,0]) cube([bottom_lp,0.2,bottom_lp]*width_unit,center = true); } // 壁から伸びるサポート sym_m([1,0,0], [width_unit*n/2, 0,0]) for(j=[1:m-1]) { translate([ wall_thick, width_unit*j, 0]) rotate([0,45,0]) cube([bottom_lp,0.2,bottom_lp]*width_unit,center = true); } } } } // 1列の場合には内側に棒を持つ if(m == 1) { for(i=[1:n-1]) translate([i,1/2,0]*width_unit) translate([0,0,-height_unit*l]) { difference(){ cylinder(height_unit*l, r=bottom_d3/2, $fn=fn); rotate_extrude($fn=80) polygon([ [bottom_d3/2+epsilon-bottom_bevel,-epsilon], [bottom_d3/2+epsilon,+bottom_bevel-epsilon], [bottom_d3/2+epsilon,-epsilon] ]); } } } } } // 縦、横、高さを指定して生成する // 高さは整数値あるいは 1/3 を指定する lego_block(4,10,1/3);