2018年9月20日木曜日

BL652 - BLEマイコンで温度センサー(ソフトウェア編)

BLEモジュールのBL652を用いて、温度を計測しスマホにBLEで送るデバイスを作りました。
BL652は、Noridic社のSDKを使わずにsmartBASICと称する BASIC言語でソフト開発が可能で、開発時間を短縮できます。

今回の温度計測は、BL652のベースであるnRF528チップの内蔵温度計を使用しています。
データシート上、計測誤差が±4度と、温度計としては実用範囲外ですが、Garmin等のサイコンの温度表示もこのレベルかと思います。

smartBASICでは、簡単に温度を計測できる関数がありました。
i=SYSINFO(2024)
これで変数iに温度(摂氏×10倍)が代入されます。



1.任意のテキスト エディタでBASICコードを書きます。
特に開発環境に指定はありません。

















// Definitions
//******************************************************************************
//#define TEMP_MANTISSA                        2711
#define TEMP_EXPONENT                        -2
#define UUID_HEALTH_THERMOMETER_SERVICE      0x1809

//#define UUID_HEALTH_THERMOMETER_SERVICE      0x1818

#define ENABLE_DEBUG_PRINTS                  1
#define BLE_DISCOVERABILITY_GENERAL          2
#define BLE_APPEARANCE                       0
#define MAX_DEVNAME_CHRS                     20
#define BLE_CHARVAL_AD_TAG                   0x16

#define ADV_SCAN_IND                         2
#define ADV_FILTERPOLICY_ANY                 0

        //Advertise interval
#define ADV_INTERVAL_MS                      250
        //Advertise timeout
#define ADV_TIMEOUT_MS                       0
        //Whitelist Policy in Adverts
#define ADV_WHITELIST_FILTER_POLICY          ADV_FILTERPOLICY_ANY

//******************************************************************************
// Global Variable Declarations
//******************************************************************************
dim rc         //Result code
dim devName$   //Device name
dim hChar      //Characteristic handle
dim hSvc       //Service handle
DIM  TEMP_MANTISSA

//Example :: BleVSpWrite.sb (See in BL652CodeSnippets.zip)
#define GPIO_TEMP_SENS           3 

DIM tx$,scRpt$,adRpt$,addr$,hndl,cnt,iToggle,adc
DIM iInterval,iTimerCount,startTick,prevTick,veloTick,iGcounter
iInterval=1
iGcounter=0
DIM tmpdata, data
DIM i 
DIM iCrankPass, iPower
//------------------------------------------------------------------------------
// For debugging
// --- rc = result code
// --- ln = line number
//------------------------------------------------------------------------------
Sub AssertRC(rc,ln)
    if rc!=0 then
        print "\nFail :";integer.h' rc;" at tag ";ln
    endif
EndSub
//------------------------------------------------------------------------------
// Register Error Handler as early as possible
//------------------------------------------------------------------------------
sub HandlerOnErr()
  if (ENABLE_DEBUG_PRINTS!=0) then
    print "\n OnErr - ";GetLastError();"\n"
  endif
endsub

//------------------------------------------------------------------------------
// This subroutine gets called first
//------------------------------------------------------------------------------
sub OnStartup()

endsub

//******************************************************************************
// Handler definitions
//******************************************************************************

//Example :: TimerRunning.sb
FUNCTION HandlerTimer0()
DIM rc,dvcNme$,nmeWrtble,apprnce,MinConnInt,MaxConnInt,ConnSupTO,sL,sTgt$,tmp$
DIM addr$ : addr$=""

DIM discovMode : discovMode=0 
DIM advAppearance : advAppearance = 1
DIM maxDevName : maxDevName = 22
DIM advRpt$ : advRpt$=""
DIM scRpt$ : scRpt$=""

    dim scnRpt$  //Empty scan report

//----------------------
nmeWrtble = 0             //Device name will not be writable by peer
apprnce = 768             //The device will appear as a Generic Thermometer
MinConnInt = 500000        //Minimum acceptable connection interval is 0.5 seconds
MaxConnInt = 1000000       //Maximum acceptable connection interval is 1 second
ConnSupTO = 4000000        //Connection supervisory timeout is 4 seconds
sL = 0                   //Slave latency--number of conn events that can be missed

PRINT "\nSystmp 2024    = ";SYSINFO(2024) 

i=SYSINFO(2024) 

//---Advertise

SPRINT #tmp$, " ";integer.h' i
tmp$=RIGHT$(tmp$, strlen(tmp$)-4)
sTgt$=tmp$
dvcNme$="temp.="+sTgt$

nmeWrtble = 0                
apprnce = 768            
MinConnInt = 500000          
MaxConnInt = 1000000         
ConnSupTO = 4000000      
sL = 0                      

rc = BleGapSvcInit(dvcNme$,nmeWrtble,apprnce,MinConnInt,MaxConnInt,ConnSupTO,sL)

IF BleAdvRptInit(advRpt$, discovMode, advAppearance, maxDevName)==0 THEN
 PRINT "\nAdvert report initialised"
endif

PRINT BleAdvRptAddUuid16(advRpt$, 0x180F,0x180A, -1, -1, -1, -1)
PRINT BleAdvRptsCommit(advRpt$, scRpt$)

//rc =BleScanStart(20000, 0)
PRINT "\n --- New DevName : "; BleGetDeviceName$()
IF BleAdvertStart(0,addr$,25,60000,0)==0 THEN   
    PRINT "\nAdverts Started\n" 
endif

ENDFUNC 1         //remain blocked in WAITEVENT
        //exit from WAITEVEN if end func ZERO0
//----------------------------MAIN C----------------------------------
ONEVENT EVTMR0 CALL HandlerTimer0

//setups------------------------------------------------------------------------------------------------
TIMERSTART(0,1000,1)  //4 NG 14 work    //start a 1000 millisecond recurring timer
PRINT "\nWaiting for Timer 0"
//Remove resistor 
PRINT GpioSetFunc(GPIO_TEMP_SENS, 1, 2)  
//Analogue in 
PRINT GpioSetFunc(GPIO_TEMP_SENS, 3, 0)

WAITEVENT

PRINT "\nExiting..."
2.オンラインコンパイラで、BL652(とfirmwareのバージョン)を指定し、上記で書いたBASICのファイルを選択し、XCompileボタンを押すと、ソースがコンパイルされ、実行ファイルがダウンロードされます。
エラーがあると、ブラウザにエラー箇所が表示されます。




Laird社推奨のUwTerminalXを使用して、上記の実行ファイルをBL652に書き込みます。
まず、COMポートの設定を行います。


続いてTerminalタブで右クリックー>LOAD+RUNー>ファイル選択
でBL652に書き込む実行ファイルを指定すると、書き込めます。
 LOADとRUN・・・懐かしい。



書き込みが完了すると、自動的に実行ファイルがRUNされます。
PRINT文の出力は、Terminalに表示されます。


“Systmp 2024=”の値が温度です。(摂氏×10倍)
“New DevName” は、BL652モジュールがBLEデバイスとしてAdvertiseしてる名前です。


↓スマホ側の表示です。
BLEデバイスをスキャンすると、以下のようにtemp.=として温度(摂氏×10倍)が16進数でデバイス名として表示され、プログラム通りにスマホに無線送信(Advertise)されていることが確認できます。



BL652のsmartBASIC開発は、 オンライン・コンパイラを利用するため、面倒なSDKの開発環境を構築する必要がありません。
一見お手軽ですが、オンラインコンパイラが閉鎖されると、BASICでは何も開発できないリスクは感じます。
ただ、最後は、Nordic社の開発環境を利用して、ソフト開発はできるので、購入したBL652がゴミになるリスクはないと思います。


2019/05/24追記

BL652を腕時計型デバイスに組み込めるか。
BL652は、以下のように小型です。
素手ではんだ付けができる限界サイズといえる小ささです。






腕時計型デバイスを作成するにあたり、
今回のようにBLEのAdvertiseによってデータを送信し、
XperiaZシリーズで受信するのであれば、
何ら問題ないとおもいます。
消費電力も小さくCR2032で賄える(2ma以下)で動作可能と記憶してます。

しかし、BL652でAdvertiseし、BL652でスキャン/受信すると
データの受信にタイムラグ(4秒程度)が生じます。
原因は調査中ですが、ややインパクトがあるので、
BL652間通信は、VSP(VirtualSerialProtocol)と称する
BLE上でUART通信する技術を用いることとなるかと思います。
この場合、マイコンのリソース/パワーの多くを無線通信にもっていかれるため、
心拍センサーとのI2C通信が安定的に行えるか、やや不安がございます。

BL652でI2Cは行ったことはございませんが、万一、安定しない場合、
I2Cの制御用にBL652を一つと、無線送信用にBL652をもう一つと、
2CPU体制にすることで解決は可能かと思います。








4 件のコメント:

  1. お世話になっております。信州MAKERSです。MFT2019ネタのご指導有難うございます。何とか申請までしました、6月4日に審査結果待ちですが、その間2019版のサイコンの構想しております。脈波センサをROHMのBH1790GLCを使って、リストバンドに仕込もうと検討してますが、小型低消費電力のCPUと無線機能を考えるとご紹介のBL652がいいのではないかと考えております。BL652をペアでBLE通信させて脈波と母艦マイコンを接続させることでいろいろできるのではないかと思いますが、BL652をリストバンド型に実装するのは可能性があるでしょうか?
    ご指導宜しくお願いいたします。

    返信削除
  2. 信州MAKERS様
    お世話になっております。
    MFT2019ネタは技術的なハードルが予想を大きく超えたと感じておりますが、次から次に打ち手を考え出されておられ、感心しておりました。
    BL652をリストバンド型に実装する可能性について、記事内容を追記・更新させていただき、回答とさせていただきたいと思います。
    更にご不明な点がございましたら、何なりとお問い合わせください。

    返信削除
  3. DgradeDIY様 迅速なご回答有難うございます。お忙しいなかわざわざ記事更新をしていただけるとのこと感謝いたします。自作サイコンを実際に使えるレベルまで開発するのは大変だと感じております。先駆者でDradeDIY様にご指導いただいて、何とか今年中には使える自作サイコンにしたいと考えております。ご指導宜しくお願いいたします。

    返信削除
    返信
    1. 信州MAKERS様

      サイコンの製作がうまくいくことをお祈りいたします。

      ↓このような自作サイコンを作られた方を発見しました。GPS付です。ご参考まで。
      https://qiita.com/hishi/items/8f77fd4655027fac7c7d

      削除