2018年 10月 24日

GitHub Pull Request Builder Plugin 使っている環境で手元ではテストが通るのに Jenkins では通らない場合

GitHub Pull Request Builder Plugin の PR ブランチビルドの挙動は以下のような状態で実行する

  • マージ可能な場合はベースブランチにマージされた状態 (origin/pr/{pr}/merge)
  • コンフリクトしている場合はPRブランチのHEAD状態 (commit hash)

表題の「手元ではテストが通るのに Jenkins では通らない場合」は表面上はコンフリクトはしないにも関わらず、ベース側に入った変更によってPRブランチ側が壊れることによって起こる。つまりコード上の意味がコンフリクトしているにも関わらず、表面的にマージされてテストされるため不可解な結果を生むことがある。

解決方法

  • ベースブランチをPRブランチにマージする(または rebase する)
    • 重要:GitHub 上でコンフリクト表示が出ているか否かは関係ない

PRのテスト結果の表示

GitHub 上に表示されるテスト結果のインジケータには上記のように2つのケースがあり、Jenkins 側のログを見ないと厳密に判断することができない。

GitHub 上での Conflict 表示でもある程度判断できるが、CI を通ったあとにベースブランチに変更が入って Conflict した場合は PR ブランチで再テストが走るまで過去の結果が表示されるため正確ではない。

備考

  • origin/pr/{pr}/merge は普通に clone すると含まれないため、Jenkins が存在しない謎のコミットをビルドしているようにみえる
2018年 10月 22日

3D プリンタフィラメントの防湿

3D プリンタフィラメントの湿度管理をはじめた。

フィラメントは割と吸湿するらしく、できる限りドライな状態を保たないと、最悪印刷できなくなることもあるようだ。そういえば、と考えてみると PETG でも白っぽくプリントされて表面の状態がかなり悪くなることがあった。吸湿が原因かわからないが、可能性はある。

フィラメントをすぐ使いきるようなヘビーユーザーでもないので、できるだけ品質を長くたもちたい。

吸水率

  • ABS: 0.1〜0.8%
  • PLA: 0.5%
  • PET: 0.3%

ref. http://www.kayo-corp.co.jp/common/pdf/pla_propertylist01.pdf https://www.jstage.jst.go.jp/article/fiber/59/10/59_10_P_324/_pdf

吸湿 (吸水) が原因で起こりうる問題

  • 糸ひき (加水分解による粘性低下)
  • 光沢不良
  • フロー不足
  • ノズルでのパチパチ音 (蒸気が逃げる音)
  • ノズル詰まり

アスベル キッチンボックス 17L 「ウィル」 NF-45 - アスベル

アスベル

5.0 / 5.0

食品保存用のアスベル キッチンボックス 17L 「ウィル」 NF-45というのを買ってみた。フィラメントを納めるにはちょうどいい。3リールほど入れることができる。蓋にパッキンがついていて、これで密閉度を高めるようになっている。パッキンはメーカーでスペアも販売している。

アスベルのこのボックスは完全密閉というわけではないみたいだが、後述するようにフィラメントを通す穴をあけるので、いずれにせよ完全ではなくなる。目的は水を漏らさないということではなく湿度を下げた状態をキープすることなので、乾燥剤が十分に延命できれば良い。

加工

防湿しつつフィラメントをそのままプリンタに供給したいので、加工する。

フィラメントを出す部分のパーツは Angled Dry Box Feeder with Source を使った。ドリルするときのガイドパーツまであって親切。これに以下の PC4-M6 ワンタッチ継手と、OD=4mm ID=2mm の PTFEチューブを使っている。

 -

5.0 / 5.0

フィラメントホルダーは Universal Filament Holder を使っている。これだと残念ながら3つのリールを入れることはできず、2つアクティブ+1つスタンバイという感じになる。

乾燥剤

エステー 備長炭ドライペット 引き出し・衣装ケース用 12シート入 - エステー

エステー

3.0 / 5.0

ひとまず塩化力ルシウムのものを1つ入れている。これは使い捨てだが元の体積以上に吸湿できる。

坂本石灰工業所 なんでも除湿シリカゲル 1kg - 坂本石灰工業所

坂本石灰工業所

3.0 / 5.0

またシリカゲルをリール近くにおいている。これはフライパンで炒れば再利用可能。

今一緒に入れている湿度計は20%未満になると湿度の表示を止めてしまうので、どのぐらいまで湿度が下げらているかよくわからないが、室内湿度が55%程度でもずっと20%未満なので割といいんじゃないでしょうか。

2018年 10月 19日

3Dプリンタのプラットフォームシートのはりかえ

Original Prusa MK3 のプラットフォーム(磁石でつけるシート型)には両面PEIフィルムが貼ってあるのだが、片方のフィルムが破れて剥れるようになってしまった。一度破れてしまうと、そこからどんどん破れが広がってしまう。

ということでこのPEIフィルムを剥して別のを貼りなおすことにした。

PEIフィルムを剥す

交換方法のマニュアルがある。シートを剥すまではいいんだけど、接着剤を剥すのがとてつもなく大変だった。リモネンはいまいち買えないので市販のシール剥し剤を使うのが良さそう。今回はアセトンとアルコールでやってみたけどかなり時間がかかったのでこれはおすすめしない。

公式の代替PEIフィルムは$8.96とそれほど高価なわけではないが、送料が$20以上と高いのと、一度貼ると剥すのがとてつもなく大変なのがわかったため、気がすすまなかった。

磁石にくっつくことからして、普通の鉄のシートっぽいので露出して放置すると錆が心配になる。

交換

3M 3Dプリンタープラットフォームシート3099AB(3枚入り) 330mmx270mm ABS/PLA対応 - スリーエム(3M)

スリーエム(3M)

5.0 / 5.0

3M の 3D プリンタ用プラットフォームシートを試してみることにした。一枚あたり1500円とあまり安いとはいえない。

貼るのは難しくない。ぴったりサイズではないので結構余りがでる。もったいないけどカットして捨てている。

貼ったあとに保護シートを剥すと、すべり止めがきいたような表面材質がでてくる。このため、保護シートを剥したあとにスキージで貼りつけなおすみたいなことはできないので注意。必ず保護シートを剥すまえに密着させる必要がある。

表面は白っぽくほぼ不透明なため、元のスチールプレートの文字や印刷範囲の表示はほぼ見えなくなる。

雑感

数回 PETG でプリントしてみたが、今のところはとてもいい感じ。ちなみに最初のレイヤーも 0.2mm でプリントしている。このシートの説明では 0.1mm でベストと書いてあるので推奨設定ではない。

食いつきはよく最初のレイヤーが失敗することはまずない。PETG は PEI フィルムだとくっつきすぎることがあったけど、このシートだとそこそこ広い設置面のオブジェクトでも剥すに苦労しなかった。

ただ表面がつるつるではないのでスキージはちょっと入れにくいように感じる。あんまり強力に貼りついた場合剥せなくなるかもしれない。

耐久性はまだわからない。プリントして剥すとシートの表面の何かが少しくっついて剥れていくようにも見える。

2018年 10月 10日

撮影用の無反射ガラスの代わり


「無反射ガラス」って名前がかっこいいんだけど「ノングレアガラス」というともうすこし実体がわかりやすい。すりガラスの目の細かいもののことで、つまり表面が細かくざらついており光を散乱させるので反射が少なくみえる (全体としての反射の量には変化がないが、散乱させるので特定方向へ反射させる量は減る)

ガラスは割れる・切れるで若干扱いにくいので、あまり使いたくはない。ということでアクリルで似たようなものはないか?と探してみると、東急ハンズで普通にノングレア・つや消し加工されたアクリル板が売っていた。カナセライトの「クリア(つや消し)」というもの。

t=2mm のものを買ったけど、270x320mm でも思ったよりもたわむので 3mm ぐらいはあったほうが良さそう。

調べてみるとカナセライトはマット以外にノングレアというおそらくもっと細かい目のタイプも作ってるようだ。アクリル板マット板、アクリル加工専門販売アクリルショップはざいや 通販をやってる切板屋さんもあった。

こういう感じ

ノングレアよりはすりガラスに近いのでほぼ透けないが、背景白だとあんまり変わらないでしょう。物撮り自体 (というか写真が……) 下手なのでもうちょい練習したさはある……

今回の写真は全部スマフォ (Huawei P20)。まじでコンデジはいらないですね……





2018年 10月 09日

KiCAD でフットプリントを作るときに外部CADを使う

KiCAD のフットプリントエディタはちょっと貧弱なので、ピン・パッドの設定をするだけのツールとして捉えたほうが良さそう。

自分は KiCAD のフットプリントエディタで作った結果、ピン配置がうまくできていなくて失敗した経験が2度や3度ではない。IC のパッケージで「四角とピンしかないじゃん」と思っても失敗するのでやめたほうが良い。LAN コネクタとかだともっと難しい。

基本的に、外形やピン位置などは外部のCADツール、ここでは Fusion 360 を使って書いて、DXF ファイルにしてインポートするようにする。

Import DXF File で位置が毎回ずれる

フットプリントエディタで Import DXF File をするとき、カーソルを動かしてしまうと、なぜか変なポイントがスナップされてしまってどうしよもうなくなる。

User Defined で 0, 0 に設定すると DXF の原点と footprint editor の原点があった状態で表示されるので、そのままクリックして位置を確定する。

Fusion360 のスケッチを書くとき、原点を外形ではなくピンの位置にしたほうが KiCAD で配置しやすい。(誤差0にしなくても、拡大して移動してだいたいあわせれば十分だけど)

DXF Import 時に線幅を設定したい

footprint editor では不可能っぽい。諦めよう

Fusion360 の補助線まで dxf に含まれてしまう

下書き用のスケッチと、エクスポート用のスケッチをわけて、エクスポート用のスケッチでプロジェクションするとよい

2018年 10月 03日

Original Prusa i3 MK2.5 のエクストルーダーを R3 にアップグレード

エクストルーダーまわりがR3になり新モデルが提供されるようになったのをうけて、これを試してみることにした。主に冷却が強化されるというものになっている。ちょうど最近冷却不足と思われるフィラメント詰まり (ほぼ密閉状態でしばらくプリントすると詰まる) が頻発したので、もしかすると改善するかもしれないという期待がある。

PETG で新しいエクストルーダーを自分でプリントしたのち、ちゃんとマニュアルがあるのでこれの通りやっただけ。https://manual.prusa3d.com/Guide/Upgrading+extruder+R2+to+R3+on+MK3-MK2.5+(self-printed+parts)/782?lang=en

2018年 10月 02日

Raspberry Pi 2 B+ と 3.2inch LCD

もともと初代 Raspberry Pi 用に買ったものだけれど、初代 Raspberry Pi をいよいよ捨てたので、ついでにいろいろ調べながら再度使ってみる。

LCD-show-180817.tar.gz の中の ./LCD32-show がやっていることは以下の通り。

しかし fbcp のインストールは失敗してた。まぁとりあえず使える。

なお、どういったコントローラが使われているかスペックに書いてないが、以下の通り。

  • タッチコントローラーは SPI ads7846
  • 液晶は SPI ili9340 240x320

fbcp は何をしている?

frame buffer をコピーするアプリケーションなのは名前から明らかだけれど、何のために?と思った。結論をいうと GPU でレンダリングした結果を SPI 接続の液晶へ表示させるためのハックのようだ。GPU を使わないなら入れなくても動かすことはできる。

dtb dts

dtb ファイル (コンパイル済みのデバイスツリーブロブ) が含まれているけど、ソースファイルがない。以下のようにするとソースにディスアセンブルできる。

dtc -I dtb -O dts -o waveshare32b-overlay.dts waveshare32b-overlay.dtb

以下のような感じのデバイスツリーとなっていた。

/dts-v1/;

/ {
        compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";

        fragment@0 {
                target = <0xdeadbeef>;

                __overlay__ {
                        status = "okay";

                        spidev@0 {
                                status = "disabled";
                        };

                        spidev@1 {
                                status = "disabled";
                        };
                };
        };

        fragment@1 {
                target = <0xdeadbeef>;

                __overlay__ {

                        waveshare32b_pins {
                                brcm,pins = <0x11 0x1b 0x16>;
                                brcm,function = <0x0 0x0 0x0>;
                                linux,phandle = <0x1>;
                                phandle = <0x1>;
                        };
                };
        };

        fragment@2 {
                target = <0xdeadbeef>;

                __overlay__ {
                        #address-cells = <0x1>;
                        #size-cells = <0x0>;

                        waveshare32b@0 {
                                compatible = "ilitek,ili9340";
                                reg = <0x0>;
                                pinctrl-names = "default";
                                pinctrl-0 = <0x1>;
                                spi-max-frequency = <0xf42400>;
                                rotate = <0x5a>;
                                fps = <0x19>;
                                bgr;
                                buswidth = <0x8>;
                                reset-gpios = <0xdeadbeef 0x1b 0x0>;
                                dc-gpios = <0xdeadbeef 0x16 0x0>;
                                debug = <0x0>;
                                linux,phandle = <0x2>;
                                phandle = <0x2>;
                        };

                        waveshare35a-ts@1 {
                                compatible = "ti,ads7846";
                                reg = <0x1>;
                        };

                        waveshare32b_ts@1 {
                                compatible = "ti,ads7846";
                                reg = <0x1>;
                                spi-max-frequency = <0x1e8480>;
                                interrupts = <0x11 0x2>;
                                interrupt-parent = <0xdeadbeef>;
                                pendown-gpio = <0xdeadbeef 0x11 0x0>;
                                ti,x-plate-ohms = [00 3c];
                                ti,pressure-max = [00 ff];
                        };
                };
        };

        __overrides__ {
                speed = <0x2 0x7370692d 0x6d61782d 0x66726571 0x75656e63 0x793a3000>;
                rotate = [00 00 00 02 72 6f 74 61 74 65 3a 30 00];
                fps = [00 00 00 02 66 70 73 3a 30 00];
                debug = <0x2 0x64656275 0x673a3000>;
        };

        __symbols__ {
                waveshare32b_pins = "/fragment@1/__overlay__/waveshare32b_pins";
                waveshare32b = "/fragment@2/__overlay__/waveshare32b@0";
        };
        __fixups__ {
                spi0 = "/fragment@0:target:0", "/fragment@2:target:0";
                gpio = "/fragment@1:target:0", "/fragment@2/__overlay__/waveshare32b@0:reset-gpios:0", "/fragment@2/__overlay__/waveshare32b@0:dc-gpios:0", "/fragment@2/__overlay__/waveshare32b_ts@1:interrupt-parent:0", "/fragment@2/__overlay__/waveshare32b_ts@1:pendown-gpio:0";
        };

        __local_fixups__ {
                fixup = "/fragment@2/__overlay__/waveshare32b@0:pinctrl-0:0", "/__overrides__:speed:0", "/__overrides__:rotate:0", "/__overrides__:fps:0", "/__overrides__:debug:0";
        };
};

Device Tree って何か?

簡単にいうとそのハードウェアのドライバの用の設定ファイル。ほぼ同じ制御方法をするハードウェアであっても、細かい制御アドレスの違い・使用バス・接続されているGPIOピンの違いが存在する。これらをいちいちカーネルにハードコードしてコンパイルするのは面倒なので、設定ファイルとして分離してある。ARM Linux だと標準的に使われている。

DTS ファイルの書きかた https://elinux.org/Device_Tree_Usage

  • compatible = "ilitek,ili9340" の部分でドライバを指定している "vendor,product" 形式。

正直読むのに苦労する。完全に理解してない。

タッチコントローラのキャリブレーション

$ DISPLAY=:0 xinput_calibrator
...
Section "InputClass"
        Identifier      "calibration"
        MatchProduct    "ADS7846 Touchscreen"
        Option  "Calibration"   "195 3780 3881 252"
        Option  "SwapAxes"      "1"
EndSection
$ sudo vi /usr/share/X11/xorg.conf.d/99-calibration.conf 
# copy calibration from above

Raspberry Pi で Chromium を起動してリモート操作

Chromium (Chrome の OSS版) を Raspberry Pi で Kiosk モード (全画面単一アプリケーションモード) で起動して、UI を作れると便利そうなのでやってみた。たとえば動画のように、3.2inch LCD 上のUIを Web 技術で完結させることができる。

Chromium を kiosk で自動起動する

raspi-config で起動モードを Desktop (autologin) に設定する。

sudo raspi-config

マウスカーソルを自動で消すやつをいれる。

$ sudo apt-get install unclutter

不正終了で残るファイルを reboot 時に消しておく。

$ crontab -e
@reboot rm -rf ~/.config/chromium/Singleton*

Raspberry Pi は Desktop の場合 LXDE が使われる。これの起動時に必要なものを自動起動するように設定する。

chromium-browser の引数は重要。とりあえずこのあたりを指定しておくと良い。

$ vi ~/.config/lxsession/LXDE-pi/autostart
#@lxpanel --profile LXDE-pi
#@pcmanfm --desktop --profile LXDE-pi
#@xscreensaver -no-splash
#@point-rpi

@xset s off
@xset -dpms
@xset s noblank
@unclutter
@chromium-browser --remote-debugging-port=9222 --no-default-browser-check --noerrdialogs --kiosk --incognito https://example.com

Chrome を remote-debugging

    • remote-debugging-port をつけているので remote debugging が有効なのだが、おそらくループバックインターフェイスしか受け付けてないのでLAN内の他のコンピュータからは直接アクセスできなかった。このため他のコンピュータから Raspberry Pi へログインするときにポートフォワードする。
ssh -L 9223:127.0.0.1:9222 pi@192.168.0.23 

これで、ログインしたコンピュータで http://localhost:9223/ するとデバッグコンソールを出せる (タブ一覧が出るので選択すれば良い)。JS が実行できるので、raspi 上で操作しなくとも特定 URL に移動したり、リロードしたりできる。もちろんエレメントインスペクタも使うことができる。

2018年 09月 30日

パワー UV LED を試す

Aliexpress で 3W 365nm のパワーUV LEDを買ってみた。ちなみに 3W と書いてあっても 3W じゃないことが多いので注意が必要。絶対最大定格 700mA Forward Voltage が 3.0〜4.0V。なので2.1W〜2.8W程度。放射束はスペック上 900mW と書いてある。

これを定電流降圧回路で600mAで光らせた。放熱器必須。アルミ基板なので熱を吸われてしまい半田がつけにくい。

蛍光させてみる

パスポート

桜のマークを視認する場合 365nm ぐらいで発光するとよくわかる。可視光が少ない紫外線でないと蛍光がわかりにくい。パスポートの場合、顔写真ページには顔写真そのものが蛍光印刷されていておもしろい。

千円札

印章はとてもわかりやすく蛍光する。裏側の印章は蛍光しない。「千円」の漢数字のところは非常にわかりにくいが蛍光している。またお札全体に帯がついていてこれも薄く蛍光している。蛍光インクは透明だがすこしテカテカしているので、実は蛍光しなくても光を反射させると普通にわかってしまう。

UVレジンの硬化時間

一瞬(0.5秒ぐらい)で流動性は完全になくなるが表面がべとつく。約3分程度で表面が完全硬化する感じ (ベトツキがなくなる)。

パワーLEDだと1灯でも照らす範囲が広いので、適当なリフレクタ ( 3Dプリントしたものにアルミ箔を貼ったもの) をつけるとなかなかフラットに照射できる。

UV計


マザーツール ポケットサイズ紫外線強度計 SP-82UV - マザーツール

マザーツール

4.0 / 5.0

UV計にも感度スペクトルがあるので、相対的な強さしかわからないが、OptSupply OSV1YL5111A (放射束が2〜4mW(@20mA)) と比べるとほぼ同じ距離で10倍程度違う。

なお太陽光の快晴時地表 UV 強度は 60W/m2 = 6,000μW/cm2 らしい。パワー UV LED 1灯でも今回測定した距離では2倍ほどの紫外線照度がある。

少し離して2灯でこんな感じ。これ以上近付けると測定器の計測限界を超えるみたい。

ちなみにこのUV計は国内ではマザーツールが扱っているがLutron のSP-82UVみたい。Lutron の校正証書みたいのがついてくる。

ref.

2018年 09月 28日

NanoPi NEO2 でやること、NanoHat OLED のメモ書き

nanopi-neo2_friendlycore-xenial_4.14.52_20180628.img.zip の場合

  • /etc/rc.local から lcd2usb_print、QtE-Demo/run.sh をコメントアウト
    • どっちもいらない
  • timedatectl set-timezone Asia/Tokyo
  • sudo apt-get -y install chrony

udev gpio rule

Nano Pi Neo 2 の提供 OS イメージだと /sys/gpio が root 保有になっており、gpio の操作に特権が必要になっている。これを Raspbian と同様に gpio group をつくり、グループに対してパーミッションを与えるようにする。

グループを追加する。

sudo groupadd gpio
sudo usermod -aG gpio pi

udev のルールを追加し、gpio に変更があった場合、所有権と権限を設定しなおすようにする。

$ sudo vim /etc/udev/rules.d/80-gpio.rules
SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chown -R root:gpio /sys/devices/platform/soc/*pinctrl/gpio*'"
SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chmod -R ug+rw /sys/devices/platform/soc/*pinctrl/gpio*'"
SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chown -R root:gpio /sys/class/gpio'"
SUBSYSTEM=="gpio", PROGRAM="/bin/sh -c '/bin/chmod -R ug+rw /sys/class/gpio'"
sudo udevadm control --reload-rules

test をやると rule の実行状態がわかる。結果が成功したかどうかとかもこれでわかる。

sudo udevadm test --action=change /sys/devices/platform/soc/1c20800.pinctrl/gpiochip1/gpio/gpio0

trigger でもルール適用できるがあまり詳細なことはわからない。

sudo udevadm trigger --verbose --subsystem-match=gpio

NanoHat OLED (ソフトウェア側)

レポジトリは https://github.com/friendlyarm/NanoHatOLED OLED 自体は I2C 経由、スイッチは GPIO に接続されている。当然だが NanoHatOLED に付属の python スクリプトを用いなくとも OLED やボタンを自力でハンドリングすることは可能 (後述)

/etc/rc.local から /usr/local/bin/oled-start が起動される。

/usr/local/bin/oled-start は /root/NanoHatOLED に cd して ./NanoHatOLED を起動してる。

./NanoHatOLED はバイナリだが、やってることはスイッチの GPIO を監視して、子プロセスに対しそれぞれ gpio0=SIGUSR1 gpio2=SIGUSR2 gpio3=SIGALRM を発生させているだけ。正直なんで C でやってるのかよくわからない。

./NanoHatOLED は /root/NanoHatOLED/BakeBit/Software/Python && python bakebit_nanohat_oled.py を起動している。

NanoHat OLED (ハードウェア側)

I2C 接続。アドレスは 0x3c (0b0111100)。128x64 OLED コントローラは SSD1306 (互換)

datasheet http://wiki.friendlyarm.com/wiki/images/a/af/096-30-SPEC_QG-2864KLBEG01_VER_C.pdf https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf

I2C のコネクタは 2.0mm ピッチ。Grove システムのやつと一緒っぽい。http://wiki.seeedstudio.com/Grove_System/ http://akizukidenshi.com/catalog/g/gC-12634/ PHコネクター? かと思ったが違う。PH コネクタはピッチは同じだが挿すことができない。

シリアルは 2.54mm ピッチ。ちゃんと調べてない。

NanoHat OLED を node.js で直接さわる

そこそこいい感じに書けた。

GPIO のボタンは Node.js の fs モジュールだけで GPIO の割込みを扱うには? | tech - 氾濫原 に書いた通りの方法で扱っている。EventEmitter の API にしてある。

OLED に対応する canvas (node-canvas) オブジェクトを保持し、更新があったかどうかを確認しつつ一定周期で再描画するような設計にした。これにより普通にブラウザでJSを書くのと同じようなモデルでコードを書くことができる。