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体制にすることで解決は可能かと思います。