2016年 08月 26日

BLE Nano (nRF51822) のドライブ能力を外付け部品なしで拡張する

仕様に書いてあるが標準だと 0.5mA になっている。これは超高輝度LEDなら直接光るかもしれない。電源電圧がそもそも低いので青色とかはやめたほうがよさそう。

なお、設定を変えると最大3ピンまで5mAのドライブ能力に拡張することができる。これは特にピンの制約はなくて、どのピンでも可能なようだ。LEDぐらいしか駆動するものがないのなら、LED ピンのドライブ能力を拡張しておくと安心できる。

設定方法は例えば以下の通りで、

	NRF_GPIO->PIN_CNF[PIN_STATUS_LED] =
		(NRF_GPIO->PIN_CNF[PIN_STATUS_LED] & ~GPIO_PIN_CNF_DRIVE_Msk) |
		(GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos);

PIN_CNF の DRIVE を変更すれば良い。この例だとソースもシンクも5mAになる。ソースとシンクは別々に設定可能。

なお mbed 環境で DigitalOut とかしている場合 PIN_CNF レジスタは変更済みなので、必要ないところは上書きしないように注意する必要がある。

mbed + BLE Nano で FOTA (DFUService) を使うには?

nRF51 での FOTA の仕組み

DFUService というのが mbed の BLE_API だと提供されていて勘違いしたけど、これは実際のファームウェア書きこみ処理は一切行わない。これがやっていることは bootloader を起動するということだけだ。

FOTA の仕組みとしては

  1. クライアントは DFUService に対してリクエスト
  2. DFUService はアプリケーション抜けて bootloader として再起動する
  3. クライアントは再度 DFU を見つけて通信を行う
  4. bootloader はBLE経由でデータを受けとってFlashに書きこむ
  5. bootloader はアプリケーションを起動する

という感じですすむ。

mbed 環境でのやりかた

まず、コンパイル済みの bootloader が必要で、これを USB 経由で書きこむ。これで準備完了になるので、これ以降は FOTA だけで書く必要がある。USB 経由で書きこむと bootloader を上書きしてしまうので、FOTA は無効になる 。

bootloader はどれを使うか

https://github.com/RedBearLab/nRF51822-Arduino/tree/S130/bootloader

Arduino IDE 経由で書きこめる bootloader になっているが、FOTA の機能もついている。BLE Nano だとこれ使っておけば良さそう。他のも使ってみたがこれだけ動いた。

mbed からデフォルトでダウンロードされる hex は書けない

ただ、上記 bootloader.hex を書きこんでも、mbed のオンラインコンパイラでコンパイル・リンクして生成される hex ファイルでは基本的に書きこめずに失敗する。これは mbed 環境でコンパイルした場合、親切にも SoftDevice などをマージした状態で hex を作ってくれるから。しかし FOTA するのはアプリケーションの部分だけなので、余計な部分を取り除く必要がある。

これは nRF51_OTA_strip.py を使えばできる。単に引数に入力と出力を与えればアプリケーション部分だけの hex ファイルを吐いてくれる。

ここを変えれば FOTA 版が落とせるみたいです。気付かなかった。ここで FOTA 版を選択すると、DFUService は自動的に組込まれてコンパイルされます。

書きこみかた

できた hex ファイルをなんとかして Android か iPhone に転送する。Google Drive に突っ込むのがてっとり早い。

そして nRF Toolbox を使って DFU をする。このとき、Init packet がどうたらというダイアログがでるが No を選択する。

Device を選択して Upload をタップすれば DFU がはじまる。結構時間がかかる。

bootloader のソースコードは?

https://github.com/ARMmbed/nrf5x-dfu-bootloader

たぶんこれがそれっぽい。ビルドしてないので確認はしてない。

OS X で DFU できないの?

公式ツールは Android / iPhone だけなので、できない。

サードパーティで作ってる人がいる。https://github.com/jeremysf/nrfDFU が、手元だとうまく動かすことができなかった。追試が必要。

2016年 08月 25日

pcb2gcode へのプルリク

ちっちゃな変更を3つほど送った。

add error for positive --zcut by cho45 · Pull Request #46 · pcb2gcode/pcb2gcode · GitHub

なんか pcb2gcode を実行したら刺さるので、こまったなあと思ったら設定ミスがわかった。pcb2gcode 側でせめてwarningぐらい出せや、と思ってかっとなって書いたプルリク。

Milldrill diameter (--milldrill-diameter option) by cho45 · Pull Request #47 · pcb2gcode/pcb2gcode · GitHub

メモ書き:KiCAD + pcb2gcode で pcbmilling | tech - 氾濫原 のとき書いたパッチ。pcb2gcode は --milldrill オプションをつけるとエンドミルを使ってすべての穴をあけることができる。たとえばφ0.8mm 以上の穴しかないなら、φ0.8mmのエンドミルで全ての穴をあけることができる。

ただ、このとき使われるオプションが --cutter-diameter だった。このオプションは外形カット時に使われるオプションなので、外形カットとドリルのときとでエンドミル径を変えることができなかった。

このパッチで --milldrill-diameter として穴をあけるときのエンドミル径を上書きできるようになった。

Clearly specify X/Y to G2. by cho45 · Pull Request #48 · pcb2gcode/pcb2gcode · GitHub

grbl だと G2 に X/Y がない場合、たんに無視されるという挙動をして絶望した。実際に機械を動かして穴をあけてから「あれ? ちゃんと開いてないぞ?」と気付いたので、目の前には加工途中の基板があった。原点がずれるとやっかいなので後日にすることもできず、勘でパッチを書いたら動いてくれた。grbl のコードも pcb2gcode のコードも手元にクローンしていてよかった……


ここまで既にマージ済み。めんどくさいコントリビューションルールもなく、非常にレスポンスはやくレビューしてくれて、良かった。

あとこうやってプルリク送った経緯と書いておくのは良い気がするので送ったときには書いていきたい。

BLE Nano (nRF51822) でどうしても 1mA 以上電流食うぞというとき

BLE Nano をあいかわらず触っている。どうしても消費電流の削減ができず3日ぐらい悩んだので、参考までに「どうすれば効率よく消費電流を削減できそうか」をしるす。

ドキュメントを良くよむこと

nRF51822_PS v3.1.pdf と nRF51_Series_Reference_manual v3.0.pdf というのが主要なドキュメントになる。前者には nRF51822 特有のことがら全般が書かれていて、こちらに消費電力や、ピンごとの物理仕様が書いてある。後者は nRF51 シリーズのシステムのドキュメントになっており、レジスタ仕様とかが書いてある。

消費電力の観点で考えると、まず nRF51822_PS v3.1.pdf に一通り目を通して、どの回路がどのぐらいの電力消費をするかを把握しておくと良い。

当然支配的なところから解決しないとどうしよもないので、大きいところをとりあえずおさえる。具体的には

  • 16MHz HFCLK (クロックだけで約1mAぐらい食う)
  • CPU (起きているときは 4mA ぐらい食う)
  • Radio (送信出力ごとに最大電流が異なる 5.5〜16mA。かなり大きく見えるが BLE の場合送信にかける時間はかなり短いので、平均的には支配率はそれほど高くない)

スリープ中に 16MHz のクロックを切るためには

タイトルの 1mA という数字は HFCLK の消費のことを想定している。このクロックは必要ならば動くという挙動をする。CPU が動いているなら必ず動いている。

大事なのは以下の表 (nRF51822_PS v3.1.pdf から引用)

ここで HFCLK に依存しているブロックがスリープ中に一切ないようにしなければならない。nRF51_Series_Reference_manual v3.0.pdf のほうにはどのペリフェラルが HFCLK に依存しているかは書いてないので、この表はとても大事。

だいたいのブロックは必要なときだけ有効にして動かす系だけど、UART や TWI のようにだいたいオンにしてるみたいなペリフェラルもスリープ前に明示的にオフにする必要がある。というよりは必要なときだけオンにするという使いかたのほうが安全。

TWI なら

NRF_TWI0->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos;
do_something();
NRF_TWI0->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;

UART なら

NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Enabled << UART_ENABLE_ENABLE_Pos);
NRF_UART0->TASKS_STARTTX = 1;
NRF_UART0->TASKS_STARTRX = 1;
// dummy send to wakeup...
NRF_UART0->PSELTXD = 0xFFFFFFFF;
NRF_UART0->EVENTS_TXDRDY = 0;
NRF_UART0->TXD = 0;
while (NRF_UART0->EVENTS_TXDRDY != 1);
NRF_UART0->PSELTXD = tx;

do_something();

while (NRF_UART0->EVENTS_TXDRDY != 1);

uint32_t tx = NRF_UART0->PSELTXD;

NRF_UART0->TASKS_STOPTX = 1;
NRF_UART0->TASKS_STOPRX = 1;
NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Disabled << UART_ENABLE_ENABLE_Pos);

みたいな感じになる。UART はなんかバグってるのかよくわからないけど、ダミーで一回書かないとちゃんと復帰しなくてこまった。mbed のライブラリにも同様のことが書いてある。

ペリフェラル以外

書きこみインターフェイス (デバッガ) で書きこんだ直後のプログラムはデバッグモードで動いていて、この状態だと上記と同じように 16MHz とデバッガ用の回路が動くようで、消費電力がまったく減らない。

この状態から抜けてノーマルモードで起動するには

  • デバッガを切断したうえで、全ての電源供給をやめて、再度電源を入れなおす
  • デバッガ起動中でもリセットピンでリセット可能にして、デバッガを切断するとともにピンリセットをかける

あたりがある。前者は若干めんどうなので、後者の方法のほうがおすすめ。

// Enable Pin-reset on DEBUG mode
NRF_POWER->RESET = 1;

と main の冒頭あたりに書いておくと、デバッグモード中でもピンリセットがかけられる。「ピンリセットってどのピン?」と思うかもしれないが、SWDIO が nRESET と共用になっているので、書きこみ気から SWDIO/SWDCLK を抜いて GND に一瞬つなげばノーマルモードで起動するようになる。

BLE Nano 固有

BLE Nano は P0_19/D13 に LED がついてる。この LED は VDD に繋っており、負論理で光る。なので、この LED を消したいときは明示的に PullUp するか出力に設定して HIGH にする必要がある。

DigitalIn unused_p0_19(P0_19, PullUp);

備考

ちなみに英語で検索するときは nRF51 power consumption とかでググるのが良いです。

2016年 08月 24日

最近『メーデー』を見ている

メーデー!9:航空機事故の真実と真相 (吹替版) - ---

---

5.0 / 5.0

メーデー!10:航空機事故の真実と真相 (吹替版) - ---

---

5.0 / 5.0

メーデー!11:航空機事故の真実と真相 (吹替版) - ---

---

5.0 / 5.0

プライムビデオでシーズン11、10と9の一部が見れるのでずっと見てる。

航空業界は事故調査がものすごく発達しているというのを感じることができる。機械的な要因からパイロットの心理的な要因まで、とことん分析される。淡々とすすむので、見ていて疲れないが、好奇心は刺激されるので見ていてメリットしかない。

なぜ航空業界にはここまで厳しい事故調査が行われるのに、他の業界ではちゃんとしたものがないのだろうと考える。一発で大量に人が死ぬってのがインパクトがあることだから、というのがあるのだろうなと思った。自動車よりも飛行機のほうが圧倒的に安全なのにも関わらず、人間は飛行機を過剰に怖がる。


ブログラムのバグも、本来なら個人の力量に帰着せず、なぜそれをフレームワークや職場環境でカバーできなかったのかとかを深く考えるべきものであるはずだけど、基本的にプログラムのバグ1個で直接物理的に人が大量に死んだりはあまりないので、そういうところまで深く考える人が少ない。つまりプログラムで大量に人が殺せればプログラムのバグは適切に対処されるようになるだろう。人間が死なないと人間は学ばない。

 -

5.0 / 5.0

Huawei MediaPad T2 7.0 Pro を買ってみた。しばらくうちにはタブレットがなかったので、ひさびさにタブレットを手に入れた。

こんな価格だけど使用感は全く問題ない。指紋認証でロックが解除できて、思ったよりこれが便利。

PDF ドキュメント読むときに使うのがかなり快適だな〜 という感じ。Zenfone 2 と比べて2インチしか変わらないけど、ぜんぜん違う。

2016年 08月 23日

Androud N がリリースされたようですが、ZenFone 2 には Android M が一向にきません。こないんでしょうか。

2016年 08月 22日

自宅のネットワーク、ちょいちょい特定のDNSがひけなくなるけど、なんなんだろうなあ。プロバイダのキャッシュサーバーがおかしいのだろうか……

今期のアニメ

『この美術には問題がある!』と『NEW GAME』が安心してみれて無限に可愛い女の子が喋る感じなのが良い

2016年 08月 13日

メモ書き:KiCAD + pcb2gcode で pcbmilling

とりあえずメモだけ

Eagle の場合は pcb-gcode を使えばよかったが、これは Eagle の ULP で書かれているので KiCAD には使えない。pcb2gcode はガーバーファイルから直接 gcode に変換するのでどちらでも使える。

レイアウト

KiCAD 書き出し


pcb2gcode

以下のパッチのブランチで実行

https://github.com/pcb2gcode/pcb2gcode/pull/47

millproject

# Use standard mm
metric=true
metricoutput=1

# front=
back=Main-B.Cu.gbr
outline=Main-Edge.Cuts.gbr
drill=Main.drl

back-output=back.gcode
outline-output=outline.gcode
drill-output=drill.gcode

# https://github.com/chrysn-pull-requests/pcb2gcode/blob/graphical-documentation/man/options.svg
zwork=-0.1
zsafe=1
mill-feed=500
mill-speed=10000
mill-vertfeed=200
offset=0.07679491924311227
#offset=10
extra-passes=1

zdrill=0.9
zchange=20
drill-feed=100
drill-speed=10000
milldrill=true
# milldrill のときの直径 パッチが必要
milldrill-diameter=0.8

# for grbl
nog81=true

# 外形カット時のミル直径
cutter-diameter=1
zcut=-1
cut-feed=500
cut-speed=10000
cut-infeed=1
cut-side=back

optimise=true
zero-start=true
dpi=1000

offset には削るエンドミルの半径を入れる。たとえば 30° 0.1mm のVカッターを -0.1mm で掘る (zwork=-0.1) にする場合 φ0.153mm なので、offset=0.0767 にする。

パッチのメモ

各 gcode を --zero-start で別々に生成すると原点がずれる。しかも --cutter-diameter を変えると外形レイヤーの基準がかわってしまう。

milldrill の場合 drill 系のオプションは無意味で、全て cutter 系のオプションが適用される。

milldrill のときの mill の直径は cutter-diameter と共用のようで、外形カットと穴開けで別の直径のエンドミルにできない…

KiCAD の時点で外形を大きくしておくか、パッチ書くしかない。→ 書いた

結果

pcb2gcode は isolate な部分を全て削る設定にすることができない(と思う)。なので孤立した銅箔が生成されてしまう。 extra-passes=100 とかにすればできるだけ全て削れるっぽい。

offset を大きく設定すると voronoi アルゴリズムが有効になり、孤立した部分をなくせる (孤立した部分は近くの配線に吸収される)。配線というよりは銅箔面の領域分割という感じになる。PCB っぽくはないけどおもしろい。

まだこれは試してない。