Cボタン電池で動く装置をPICで作っていて、いろいろ苦労したし、誰も書いてないようなので備忘録。
なお、対象プロセッサーはPIC12F629です。16F系はあちこちに書いてあるけど、8pinPICをボタン電池で駆動し、マイクロアンペア単位の議論をする例は少ないようです。(ミリアンペアだと思ってませんでした?)
動作させる必要がないならSLEEPにすればいいのですが、ここではずーっと省電力で稼働させる時のノウハウです。
電池
ボタン電池がもつ容量は、たとえばCR2025だと165mAh。一時間に165mA通電して終了。
ちなみに単4電池は900mAhくらい。
これらの電源で装置をドライブするために、最初に考えたのは「LEDって電気食うんじゃね?」でした。
しかしPICなどで3V電源でLEDを1Kオームの抵抗で点灯すると1.4mAくらい流れます。
確かに大きいのですが、点灯間隔を伸ばすよりももっと大事なことはクロックを落とすことでした。
低クロックが省電力であるわけ
ハードウェア上の理由はMicroChip Technologyのドキュメント見てね。(日本語)
しかしながら稼働させる時には、クリスタルのほぼ下限であろう32.768KHzを使うと待ちなしでプログラムをループさせて上限が1KHzくらいです。(計算すれば、この時はわずか4命令しか余裕がない)
消費電力以前に私が考えている機能を搭載できません。
もっとゆっくりな動作でいいアプリケーションであれば、これも使いようがあるでしょう。
(ちなみにメインのルーチンを少しでも軽くするために、LEDの点滅はタイマー割り込みにしました。プリスケーラーの値もクロックで大幅にかわりますね。)
3.579545MHzを使うと0.4mAくらい。これじゃ、15日くらいしか持たない。
ところが、この3Mhzから32KHzの間のクリスタルって店頭にないんですよねー。
そこでデータシートを改めて読んだ。ここらへんのようだ。
やはり内部クロックを使ったから消費電力が小さくなるわけじゃないどころか、多い。
32KHzでは3Vで最大で28マイクロA。しかし、1MHzでは3Vで最大450マイクロA。だいたい実測とあってる。
ということは、LP,XTモードってどう選べばいいのだろうか?このモードが消費電力の鍵のようだ。
マイクロチップのフォーラムで発見した。
ゲインが高いと電流を多く消費する。目安としてLPなら200kHzまで。XTなら4MHzまで。HSなら20MHzまでだという記載を発見した。
つまりLPモードで動かすべく、200KHz以下で安いクリスタルを探せばよい。
といってもマルツで見ると153.6KHzにいきなり落ちる。
あまり出ないクリスタルは高い。
ChipOneなんか見ると一個400円とか腰抜かしそうになったよ。
マルツで頼んだ。
ちなみにこれくらいのクリスタルだと適するコンデンサーは15PFくらいのようだ。
コンパイラー最適化の考察
昨年(2016)からXCコンパイラはサブスクリプションライセンスが出来た。
これは本当にありがたいことで、1ヶ月およそ3000円でPro仕様が使える。
以前は20万円くらいの買い取りだったので、必要な時だけ使えばよくなった。
じゃぁ、フリー版とPro版で最適化はどれくらい違うのだろうか?
ちょっと古いけど調べた人がいる。ここ
Picのプログラミングで食べている人のようだ。
ずいぶんFree版はアホなのだが、忘れちゃいけないことがある。
みんなが大好きな__delay_とかは正確であること。
つまりCPUもメモリーも余裕があるならばFree版でもいいってこと。
これって聞いたことがあるセリフだ。
そうそう、
CPUもメモリーも余裕があるならC言語でいい
あーコンパイラー使うってメンテナンスややりたいことに集中するためで最適なコードうんぬん言うならばアセンブラーで全部書くしかないようね、ってことだよなぁ。
ということは、できればPro版使ったほうがいいだろうけど余裕のあるハードウェア設計にしたほうがいい、今回の件でいうならばLPモードで動けるだけのリソース確保したあと足りなければ、さらにいろいろ考えるってことだな。
—
一応、PRO版サブスクリプションライセンスを買って最適化を確認してみた。
全体的には早くなるが、肝心なところは同じようだ。
XC8 PRO版サブスクリプションライセンスの導入の最後の最後がどこにも書かれていなかったので書いておく。
最後にZIPファイルがダウンロードされるはず。
それをUNZIPして、WINかMACかLinuxかに応じて、シェルスクリプトをコマンドラインで実行する。
そうするとライセンスを管理するフォルダーにライセンスについてのファイルが作成されて、ライセンスがアクティベートされた状態になる。
—
話しを戻して。
しばしばIT業界で「なんでディスクが10GB余計に必要なんですか?」とか「メモリーが200K増えた」とかでそれ調べるために自分の時間と関係各社を巻き込むヤツがいるけど、その人件費でディスクもメモリーも買えるじゃないか、ということは考えることができないようだ。(上司が聞くからは言い訳にならない。その上司はメインフレーム時代のメモリーが金より高かった時代の残骸であるか、興味本位で聞いているに決まってる。じゃなきゃ、プロダクションシステム内のメモリーすべて把握しているんだろうな?)
そうはなりたくないね。
余談:Cプログラム中のアセンブラ
ちなみに、プログラムについてですがメンテナンス性を重視するならC言語がいいけれども、ちょっとアセンブラーでクリティカルなところは書きたいという場合、XC8では以下のとおり。(マニュアルを見たがXC16と書き方が違うようだ。)
#include <xc.h> unsigned int loopcounter; void main(void) { TRISIO = 0x00; while(1){ #asm movlw 255 movwf _loopcounter cloop: decfsz _loopcounter,f goto cloop #endasm GP0 ^= 1; } }
#asm, #endasmで囲う。アセンブラー側でのレジスターの退避はいらない。
Cの変数の参照をしたい場合、アセンブラーの中では_(アンダースコア)をつければよい。
(実はなんとか32KHzで動かないかと、ループをアセンブラーで書いてみたりした。)
これでどれくらいの消費電力になるのだろうか?
2/12追記:約47マイクロアンペアとなった。
Timer1の謎
PIC12F629などの8ビットPICにはタイマーがふたつある。
Timer0はいかにも昔からあります風で、TImer1は後から追加しました感が満載のタイマーだ。
しかし、このTImer1がおかしい。LPモードのクリスタルを接続している場合、そのクロックを取れない。
FOSC/4という命令と同じ速度しか取れない。
どっかの神様が作ってくれたダイアグラムによれば、T1CONレジスターにT1OSCENを0にし、TMR1CSを1にし、TMR1ONをオンにすれば基本的にTimer1の割り込みがかかるはず。
ところがT1OSCENを0にすると、TImer0まで動作しなくなる。なんとも不思議。
結局、T1OSCENを1にして、TMR1CSを0(つまり、FOSC/4)でしかカウンターとして使えなかった。
わからん。(追記しましたが、当然です)
Timer1を使うために出てくるレジスターは4つもある。どんな解説を読むにしろ、データシートの以下の表を見ながら理解するのがいいと思う。(ちなみに、白いところが関係するところね。)
結局、まよいながら限界を見極めたかったので全部アセンブラーで書いてしまった。
コンパイラーよりははるかに早いだろう。
が、結果を確認しているとC言語で十分なことを再確認したに過ぎないように感じる。
ただ、やれることはやったという満足感はあるけれど。
追記:Timer1のなぞと、さらなる省電力にできる方法がわかりました。PIC12F629 Timer1の研究をぜひ御覧ください。