はじめに
これは12月の18日目に書かれた、PSoC Advent Calendar 17日目の記事です。
先日のPSoCまつり2016で、スイッチサイエンスさんからおみやげにPRoC EZ-BLEのbreakout基板をいただいたので、その試食レポートです。
PSoC 4 BLE / PRoC BLEとは
PSoC 4にBluetooth 4.2のサブシステムをくっつけたものだそうです。PSoC 4 BLE / PRoC BLEは基本的な構成はほぼ同じで、違いはプログラマブルなサブシステムが入っているかどうか、くらいのようです。(微妙に名前が違うの、ややこしくないですか...)
チップ単体の他に、EZ-BLEという名前のアンテナを載せたモジュールもあります。これはモジュールで技適をとっているので、工作に大変使いやすくて◎👍。
いずれの石もPSoC Creatorでぽちぽちしながら開発できるのが良い👍👍👍です。
入手性
モジュールになっているEZ-BLE PRoC / PSoC 4が使いやすそうです。モジュール単体だとdigikey等、変換基板はスイッチサイエンス等であるようです。また、PRoC BLEの赤い評価基板 (CY8CKIT-042-BLE) がサイプレスから出ています。
モジュール単体、アキバでは買えるんでしょうか?
(あとCY8CKIT-042-BLEは無印CY8CKIT-042とは異なるもののようです)
参考資料など
BLEについてはBLEの解説書籍、解説記事があるのでそちらを参照します。PSoCのBLEコンポーネントの使い方は、サイプレス公式の100 projects in 100 daysが大変参考になりました。これはBLEコンポーネントの使い方を集めたチュートリアル集で、それぞれのプロジェクトがCY8CKIT-042-BLE評価ボードで動作するように作られています。プロジェクトごとに簡単な解説を書いたpdfが入っていて、これとソースコードのコメントを合わせて読むと大変理解がはかどりました。
あとは公式のアプリケーションノートが比較的読みやすいです。(昔と違ってサイプレスのドキュメントが読みやすい)
- 100 projects in 100 days @github: Exampleプロジェクト集。とりあえずダウンロード
- AN94020 - Getting Started with PRoC BLE: BLEの初歩とPSoC Creatorのチュートリアルから載っている。最初にぱらぱらと読むと良さそう。日本語あり
- AN96841 - Getting Started With EZ-BLE™ Module: 評価ボードのチュートリアル (あまり面白くなかった)
- AN92584 - Designing for Low Power and Estimating Battery Life for BLE Applications: どう低消費電力化するかの話がまとまっている
動かしてみる
温度計・照度計のビーコンにします。GATTサービスは実装せず、GAP BroadcasterとしてManufacturer Specific Dataに2バイトのデータを付加するような構成にしました。Advertisement packetの内容を適宜更新して発信していればよい、というものなので、Day 9のDynamic Broadcasterのプロジェクトをベースに修正を加えました。
ちょうどこの記事と同様です。
回路図
PRoC BLE breakoutの上に実装します。温度センサはLM35DZ、照度センサはS7183です。いずれもおそらく秋月で購入したものです。
こんな感じに接続しました。電源をGPIOにつないでいるのは、必要に応じて電源を切れるようにするためです。
Day 9のプロジェクトを修正する
元のプロジェクトはPSoC 4 BLE CY8C4247LQI-BL483向けに作られているので、Device Selectorからデバイスを変更します。とりあえずビルドすると通るのがすごい。LEDとスイッチはつけていないので、PSoCの回路図から削除します。これに合わせてmain.cでスイッチとLEDの処理を記述している箇所を削除しました。
照度・温度の値を測定するためにSAR ADCを使います。とりあえず配置してビルドするとこれも通るのですごい。
ADCのコンフィグ
ADC_Start();
ADC_StartConvert();
を呼ぶとfree runするのはPSoC 5LPでのSAR ADCの仕様と同様です。いくつかの差異と注意点があったので、下にまとめます。
マルチプレクサ
ADCの入力のマルチプレクサはADCと一体でコンフィグします。ADCの動作もマルチプレクサと一体になっていて、一回の変換は全チャネルまとめて扱うようです。つまり、
while(!ADC_IsEndConversion()) {}
すると全チャネルの変換が終わるまで待つ、という挙動をします。またEOC割り込みは1周期が終わったところでかかります。i番目のチャネルの出力は、
int16 result = ADC_GetResult16(i);
で取り出せるようです。
ビット幅、値域
デフォルトで12bitです。チャネルごとに {12bit, ALT} のどちらかを選ぶことができ、ALTの幅は全体で共通で、 {8bit, 10bit} のいずれか片方に設定できます。
全体で共通のVref (+側と-側) を設定し、チャネルごとにシングルエンド・差動のどちらかを選択します。acquisition timeや飽和検出もチャネルごとに選択できて面白いです。その他、ビット幅・クロック源・周波数・リファレンス電圧の組み合わせには細かい制約がいろいろあるので、データシートを見ながらコンフィグ画面をぽちぽちいじっていけるか確認します。(エラーがすぐに出るので良いですね)
シングルエンドの設定だと負側がGNDより低い電位にいってしまって、実質1bit分減る点に注意が必要です。ここでは2チャネルともシングルエンド・singed 12bitの設定で使用しました。
INJチャネル
毎周期変換する必要はないラインに使うようです。INJチャネルのクエリを発行すると、直後の変換サイクルのみでINJチャネルの変換が行われます。
ADC_EnableInjection();
を呼ぶとINJチャネルの値が更新されるようです。(本当にあっているかな?)
以上をデータシートを読みながらいい感じに設定しました。
低消費電力化
ビーコンとしてまともに機能するよう、少しだけ低消費電力化の試みをします。
CPU・BLEサブシステムのスリープ
この処理はひな形にしたプロジェクトにすでに実装されています。BLEサブシステムがbusyでない場合は次の送信までdeep sleepを試み、もし何らかの理由でbusyのときはただのsleepに入るようなコードになっていました。この処理はAN92584に解説されているものと同様です。
blessState = CyBle_GetBleSsState();
if(blessState == CYBLE_BLESS_STATE_ECO_ON || blessState == CYBLE_BLESS_STATE_DEEPSLEEP) {
CySysPmDeepSleep();
} else if(blessState != CYBLE_BLESS_STATE_EVENT_CLOSE) {
CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_ECO);
CySysClkImoStop();
CySysPmSleep();
CySysClkImoStart();
CySysClkWriteHfclkDirect(CY_SYS_CLK_HFCLK_IMO);
}
送信間隔の調整
デフォルトのプロジェクトでは100msおきに送信します。温度をそんな短い間隔で取りたい需要は今のところないので、これは1000ms間隔に修正しました。
本当はfast advertisingとslow advertisingを使い分けると良いのかもしれませんが、どのように使えばいいのかよくわからなかったのでおあづけです。
ADCの停止
ADCをfree runさせるのは電力の無駄なので、1回変換したら止めるようにします。DynamicADVPayloadUpdate関数の内部でADCを起こし、1周期分変換し、すぐにADCを寝かせる、という一連の処理を入れました。
センサへの電源供給
温度センサも照度センサも常時通電している必要はないので、ADCを起こしたときだけ電源を供給するようにします。ADCのコードと合わせてこうなりました。
illum_pwr_Write(0);
temp_pwr_Write(1);
for(i = 0; i < 10000; i++) {}
ADC_Wakeup();
ADC_StartConvert();
while(!ADC_IsEndConversion(ADC_WAIT_FOR_RESULT)) {}
ADC_StopConvert();
ADC_Sleep();
illum_pwr_Write(1);
temp_pwr_Write(0);
advPayload[13] = (ADC_GetResult16(1)-ADC_GetResult16(0)-0x40)>>1;
advPayload[14] = ADC_GetResult16(2)>>3;
やっぱりfor文delayがかっこ悪い。
その他
使っていないピンは出力モードにしておきます。
以上の設定で、平均消費電流が100uAくらいになりました。(正確に測れるテスタがない...) 最初1mA弱から下がらなくて悩んでいたのですが、基板表面のフラックスとごみを除去したら無事にリーク電流がなくなりました。めでたしめでたし。
あとはBLEのコンフィグ画面のスクショを貼っておきます。
受信部
とりあえず手元のMacで動作確認をします。CoreBluetooth FrameworkのAPIをpythonから呼べるようにラップし、OS X環境向けにpygattと互換のAPIを実装しているbleepというプロジェクトがあるのでこれを利用します。
(pygatt互換APIではGAP Advertisement Packetをひたすら受信してフィルタし続ける処理 (GAP scanner) が書けなかったので、内部で利用しているラッパクラスを直接叩きます)
正しそうな値を受信できていることは確認できましたが、どうもバグっぽくてデバイスを見つけられたり見つけられなかったりします。スクショ貼ろうと思ったらうんともすんとも言わなくなった。何が悪いかな。
まとめと感想
- PRoC EZ-BLE breakoutの試食をしました
- PSoC Createrでぽちぽち開発できるのは楽で良いですね。
- せっかくなのでブレッドボードに刺していろいろ遊べばよかったかもしれん。
- コネクタをはんだづけする際、向きに迷った → シルクがあると親切かなと思いました。
- 公式のexampleプロジェクトがよくできているので、これをベースに修正していくと楽でした。
- 低消費電力化は難しいですね。
来週受信スクリプトの話をもう少し詳しく書きます。
明日 (今日) はmihoさんのあっちむいてほいっ♪ ~ 魂吹き込み編 ~だそうです。