アクセスカウンタ

<<  2016年7月のブログ記事 zoom RSS

トップへ


BLE + 温湿度・気圧センサー + 照度センサー

2016/07/30 12:24
CY8CKIT-042-BLE に 前回も使用した温湿度と気圧が測れる BME280 と
照度センサー TSL2561 を繋げて、
環境センサーを作成しました。

PSoC Creatorには、多くのサンプルプログラムがあり、
これをベースにして簡単に作成できるようです

環境センサーについても、Environmental sensingというサンプルコードがあります。

このサンプルコードを参考にして、修正していきました。

TopDesignは、こんな感じに。
画像

I2Cを追加して、BME280を追記しています。BME280のブロックは、
TopDesignに書いても書かなくても関係ないです
照度のTSL2561は実際には接続していますが、TopDesignには書いてません。

サンプルではLED三色使用していますが、後で何かに使うかもしれないので、
1個に減らしました

ピン配は、I2Cをどこでもいいみたいですが一応並べて配置。
画像
アナログピンの場合は少し制限があるみたいです。
LED、SW、Debug用UARTは下のボードとの
兼ね合いで決まってますので、変更できないでしょう

BLEのプロファイルは、
画像
のようにDescriptorを3つだけにしました。

プログラムの構成を大幅に変更しました。
画像


main関数の最初は、コールバックの設定と各種初期化です。
1:CyGlobalIntEnable;
2:
3:/* Start CYBLE component and register generic event handler */
4:CyBle_Start(BLE_Component_CallBack);
5:
6:/* Configure button interrupt */
7:Wakeup_Interrupt_StartEx(&ButtonPressInt);
8:
9:#if (DEBUG_UART_ENABLED == ENABLED)
10:UART_DEB_Start();
11:#endif /* (DEBUG_UART_ENABLED == ENABLED) */
12:
13:I2C_1_scl_SetDriveMode(I2C_1_scl_DM_RES_UP);
14:I2C_1_sda_SetDriveMode(I2C_1_sda_DM_RES_UP);
15:I2C_1_Start();
16:
17:BME280_Init();
18:TSL2561_Init();
19:DBG_PRINTF("TSL2561_ReadId()=%02x\r\n", TSL2561_ReadId());
20:
21:ESS_Init();
22:
23:/* Global Resources initialization */
24:WDT_Start();
25:BLE_InitStateLeds();

I2Cは、内部ブルアップ抵抗を使用して、部品点数削減です。
データシートには、内部抵抗じゃない方がいいよってありますが
100kbpsなら問題ないようです。

main関数のループ部分は、
1:while(1)
2:{
3: /* CyBle_ProcessEvents() allows BLE stack to process pending events */
4: CyBle_ProcessEvents();
5:
6: /* To achieve low power in the device */
7: BLE_LowPowerImplementation();
8:
9: /* Handle advertising LED blinking */
10: BLE_HandleStateLeds();
11:
12: /* */
13: BME280_Handle();
14: TSL2561_Handle();
15:
16: state = CyBle_GetState();
17: if (state == CYBLE_STATE_CONNECTED)
18: {
19: /* */
20: ESS_Handle();
21: }
22:
23: /* button */
24: if (isButtonPressed == YES)
25: {
26: isButtonPressed = NO;
27: DBG_PRINTF("Pressed button\r\n");
28: }
29:
30: /* Store bonding data to flash only when all debug information has been sent */
31: #if (DEBUG_UART_ENABLED == ENABLED)
32: if((cyBle_pendingFlashWrite != 0u) &&
33: ((UART_DEB_SpiUartGetTxBufferSize() + UART_DEB_GET_TX_FIFO_SR_VALID) == 0u))
34: #else
35: if(cyBle_pendingFlashWrite != 0u)
36: #endif /* (DEBUG_UART_ENABLED == ENABLED) */
37: {
38: uint8 apiResult = CyBle_StoreBondingData(0u);
39: DBG_PRINTF("Store bonding data, status: %x \r\n", apiResult);
40: }
41:}
CyBle_ProcessEvents関数が、BLEのイベントを処理してくれる
(たぶん、Callbackしてくれる?)関数なので、これ必須。
BLE_LowPowerImplementationは、必要ない時にLowPowerになってくれるようです
サンプルコードそのままです
あとは、なんちゃらHandle関数で、自分の好きな処理をしています。
この中では、WDTの時間を使って、周期的に処理をしています。

WDTと聞くと、ハングアップしたときにリセット入れるためのものと思いましたが、
どうやら、動作モードが何種類かあるらしく、
単なるタイマーとして使用することができるようです。
通常のタイマーとの違いは、ソースのクロックということになるでしょう。
WDTなら低周波数なので、低消費電力になると思います

BME280のソースコードは、ESP8266で作成したものをほぼ流用しています。
I2Cアクセス部分のみ異なります。
レジスタの書き込み関数は、割り込みベースの書き方で
1:static bool BME280i_WriteRegister(uint8 addr, uint8 data)
2:{
3: bool ret = false;
4: uint32 sts;
5: uint8 buff[2] = {addr, data};
6:
7: sts = I2C_1_I2CMasterWriteBuf((uint32)BME280_SLAVE_ADDR, buff, 2, I2C_1_I2C_MODE_COMPLETE_XFER);
8: if (sts != I2C_1_I2C_MSTR_NO_ERROR)
9: {
10: DBG_PRINTF("BME280:W:Write error:0x%lx\r\n", sts);
11: return ret;
12: }
13:
14: /* Waits until master completes write transfer */
15: while ((I2C_1_I2CMasterStatus() & I2C_1_I2C_MSTAT_WR_CMPLT) == 0) continue;
16:
17: /* Displays transfer status */
18: if (I2C_1_I2CMasterStatus() & I2C_1_I2C_MSTAT_ERR_XFER)
19: {
20: DBG_PRINTF("BME280:W:Status err\r\n");
21: }
22: else
23: {
24: ret = true;
25: }
26: I2C_1_I2CMasterClearStatus();
27:
28: return ret;
29:}


レジスタ読み込み関数は、ローモード(?)的な書き方で
1:static bool BME280i_ReadRegister(uint8 addr, uint8 *data, sint32 length)
2:{
3: bool ret = false;
4: uint32 sts;
5:
6: do
7: {
8: sts = I2C_1_I2CMasterSendStart(BME280_SLAVE_ADDR, I2C_1_I2C_WRITE_XFER_MODE);
9: if (sts != I2C_1_I2C_MSTR_NO_ERROR)
10: {
11: DBG_PRINTF("BME280:R:Write slave addr error:0x%lx\r\n", sts);
12: break;
13: }
14:
15: sts = I2C_1_I2CMasterWriteByte(addr);
16: if (sts != I2C_1_I2C_MSTR_NO_ERROR)
17: {
18: DBG_PRINTF("BME280:R:Error when write addr:0x%lx\r\n", sts);
19: break;
20: }
21:
22: sts = I2C_1_I2CMasterSendRestart(BME280_SLAVE_ADDR, I2C_1_I2C_READ_XFER_MODE);
23: if (sts != I2C_1_I2C_MSTR_NO_ERROR)
24: {
25: DBG_PRINTF("BME280:R:Error when write slave addr2:0x%lx\r\n", sts);
26: break;
27: }
28:
29: while(length > 0)
30: {
31: if (--length > 0)
32: {
33: *data++ = (uint8)I2C_1_I2CMasterReadByte(I2C_1_I2C_ACK_DATA);
34: }
35: else
36: {
37: *data++ = (uint8)I2C_1_I2CMasterReadByte(I2C_1_I2C_NAK_DATA);
38: }
39: }
40: ret = true;
41: } while(false);
42:
43: I2C_1_I2CMasterSendStop();
44:
45: return ret;
46:}
ローモードだと、ほとんどI2C APIの名前を変えるだけで行けます

main関数のループ呼び出す、BME280_Handle関数は、
先のWDTの時間を使用して、周期的に処理をしています。
1:void BME280_Handle(void)
2:{
3: sint32 temperature;
4: uint32 humidity;
5: uint32 pressure;
6: uint32 baro;
7:
8: if (WDT_IsTimeout(&timer))
9: {
10: BME280_ForceMeasure();
11: if (BME280_MeasureData(&temperature, &humidity, &pressure))
12: {
13: baro = pressure * 10;
14: CyBle_EsssSetCharacteristicValue(CYBLE_ESS_TEMPERATURE, 0, 2, (uint8*)&temperature);
15: CyBle_EsssSetCharacteristicValue(CYBLE_ESS_HUMIDITY , 0, 2, (uint8*)&humidity );
16: CyBle_EsssSetCharacteristicValue(CYBLE_ESS_PRESSURE , 0, 4, (uint8*)&baro );
17: DBG_PRINTF("BME280:%ld.%02ld, %lu.%02lu, %lu.%03lu\r\n",
18: temperature / 100, temperature % 100,
19: humidity / 100, humidity % 100,
20: pressure / 1000, pressure % 1000);
21: }
22: else
23: {
24: DBG_PRINTF("BME280:measure error\r\n");
25: }
26: }
27:}
設定された時間が経過したらtrueを返すWDT_IsTimeout関数を作成しました。
測定結果をBLEのCharacteristicに書き込んでいます。

TSL2561については、このICのデータシートに載っているソースコードを参考に作成。
レジストの書き込みと読み込みはBME280とほぼ同じでOK。
というか、アドレスしか違わない。あとでまとめた方がよさそう。

main関数のループ呼び出す、TSL2561_Handle関数では、
1:void TSL2561_Handle(void)
2:{
3: uint16 lux, irr;
4: if (WDT_IsTimeout(&timer))
5: {
6: lux = TSL2561_GetLux();
7: DBG_PRINTF("TSL2561:lux=%u\r\n", lux);
8: irr = (lux * 10) / 685;
9: CyBle_EsssSetCharacteristicValue(CYBLE_ESS_IRRADIANCE, 0, 2, (uint8*)&irr);
10: }
11:}
照度(lux)は、BLEでは放射照度(Irradiance)を使用するのでしょうか?
このCharactristicは0.1W/m2単位で格納する必要があるので、
luxを変換して代入しています。
lux⇔W/m2変換は、波長によって変わるようですが、まぁ、いいんでしょう
だけど、単位が荒すぎないですか?
お家では、0か1、がんばって2なんですが。。。
用途違いなのでしょうか。。。

センサー側のログ
画像
1分ごとに各データをNotificationsしています。

データ取得側は、CySmartを使用して、下のログを見るとNotificationを
受信していることが分かります。Notificationを受信すると上側の値も変化します。
画像


照度が納得いってませんが
BLEセンサーは非常に簡単に作成できました
さすが、Cypressですね
記事へブログ気持玉 / トラックバック / コメント


BLEを学ぶ

2016/07/24 09:35
BLEは簡単と言うけれど、初めてだとなかなかね

サンプルは簡単に動かせるけど、作ろうと思うとなかなかね

英語はよくわからないから、PSoC Creatorをメインにして、学習

まずは、「Central」と「Peripheral」 について、

Advertiseしている方が「Peripheral」、
AdvertiseをScanして、Connectを開始する方が「Central」

ということらしいが、なんか無線LANとは逆な感じです。

後で出てくるProfileによって、「Peripheral」だけしか
選択できなかったり、「Central」やどっちでもなれるようになるらいい。
PSoCのBLEの設定から今のところそう判断しています。
画像


次に、「Profile」について、
このBLEが何者かを決めるもの。
BLE SIGによって、ある程度登録されている。
カスタムもできるみたい。
画像

「Server」と「Client」について、
さっきの「Central」と「Peripheral」とは、まったくの無関係らしい。
データを持っている方が「Server」で、取ってくる方が「Client」。

環境センサーの例では、センサー側が「Server」ということになるが、
これはセンサーデータについてだけです。もし、このセンサーが
時間を取得する場合、時間については「Client」になる。
この辺がややこしぃが、まぁ単なる役割としての
呼び名ととらえた方がいいかと思います。

BLEは、Profileを決めて、そのProfileの役割を決めて、

@ Profileの決定
A Profieの役割の決定
B Serviceの選択
C Characteristicsの選択
D Descriptorの選択

という感じで、デバイスが特徴づけられる。
Aまでを、Bluetooth SIGで決められているものに準拠する場合
B〜Dから必須とオプションに従う必要がある。
これにより、スマホとかの標準アプリで操作できるようになる。

PSoCサンプルの環境センサーの場合、こんな感じで、階層化されています。
画像
P:Profile、R:Role、S:Server、C:Characteristics、D:Discriptionを示し、
先の番号と階層の段が対応しています。

Bluetooth SIGでの@〜Bは、ここに一覧があります。

CのCharacteristicsは、Service毎にどのようなCharacteristicsが必要かが先のページの
各Serviceに記載されています。Characteristicsの一覧はここにあります。
DのDescriptorも、先のServiceの仕様書によってどのCharactreristicsには、
どのようなDesciptorを付けられるか決められています。
Descriptorの一覧は、ここにありますが、そのリンク先の情報は十分ではない気がします

PSoC Creatorなら、この辺の組み合わせは、たぶんツールに
予め登録されている(?)と期待しています。

こんな感じにサービスを選択出来て
画像

Characteristicsも選択出来て
画像

Descriptorも選択できます
画像

正しいかどうかは確認してませんが、便利すぎて怖いです

次回は、いつもの環境センサーを作ってみたいです
記事へブログ気持玉 / トラックバック / コメント


BLEはじめました

2016/07/16 15:41
WiFiで遊んだあとは、BLEで遊ばないとね

やっぱり、電池で動かしたいしね

どのメーカーのBLEを購入しようか迷いましたが、

条件は、

@ 日本国内無線認証取得済みモジュール
A モジュールが小さい
B 開発キットが安い
C 日本語資料が多い

というとことでしょう。

有名どころのメーカーは、

Nordic、Microchip、TI、Cypress、STMicro

というとことでしょうか。

SWITCH SCIENCEから買うなら、Nordicのチップを使ったホシデンのモジュール。
秋月電子で買うなら、Microchipのモジュール。
なんか今ひとつ
TI、STMicroのモジュールは、FCCまでか?

Digi-keyで検索してみると、
Nordic、MicrochipやCypressが開発キット、小さなモジュールがあり、良さそうです。
Microchipの開発キットは他と比べると若干高い。
CypressはPSoCにBLEが入っているので、面白そう。
Nordicのドングルならパケットキャプチャできる?
日本語資料なら、NordicよりMicrochipかCypressが優位?

と、適当に比較してみて、PSoCに興味あるし、Cypressに決定

Digi-keyでユーザー登録して、さっそく発注
画像

CY8CKIT-042-BLEだけでいいのですが、
\7,500(?)以上で送料無料になるので、
ついでに、小さなモジュールのCYBLE-022001-00を購入。

これでも足らないので、使いそうな部品を適当に購入。
無駄遣い?

いいえ、飛行機乗って買いに行ったと思えば、激激激激安です

ユーザー登録に1日、発注して3日後には到着。
海外品を入手するのに、1週間もかからないという、鬼世界

中身は、こんな感じで、きっちりしています。
画像

左のマニュアル通りにドングルをPCに刺して、
(ドングルのファームウェアのアップデートが必要)
赤い基板にボタン電池をセットしたら、CapSensor(これもCypressの面白ポイント)
に従って、ドングルのLEDの明るさが変化。

もぉ、これだけでもワクワクが止まらない
記事へブログ気持玉 / トラックバック / コメント


ケース・イン

2016/07/09 12:16
暑い日も安心。

外出先からスマホでエアコンONできるようになったので、
涼しいお家が待ち構えてくれています

ちゃんとしたものに仕上げるため、ブレッドボードではなく、
半田付けして、ケースに入れてみました。

実装済み基板がこちら。
画像

すっかすかです
左側のモジュールがESP8266、右側がBME280モジュールです。
真ん中下にあるのは、電源モジュールです。
ほぼモジュール乗っけているだけです。

赤外線は、従来品より広角のIRに変更して、
トランジスタで駆動してます。写真では、ちょうど真ん中くらいに、
実装しているけど、ケーブルで見えない
ケーブルは、動作確認用のLEDとIRのケーブルです。

これをケースに入れました。
おもて面(?)動作確認用のLEDとIRのLED側が
画像
となってます。
温度測定するのと、無線モジュールが熱くなりそうなので、
空気穴を開けてみましたが、効果はどうなんでしょね

DCジャック面が
画像
となってます。
こちらも空気穴開けておきました。

このあと、ゴム足をつけて完成しました

記事へブログ気持玉 / トラックバック / コメント


<<  2016年7月のブログ記事

トップへ

迷える子羊の苦悩 2016年7月のブログ記事/BIGLOBEウェブリブログ
文字サイズ:       閉じる