BLE HTM (Thermometer) by nrf51822 internal temperature sensor. I confirmed with "mbed HRM1017" and "BLE Nano kit".

Dependencies:   BLE_API mbed-src nRF51822

I reffered "BLE_HTM_HRM1017".

It can be connected from "nRF Toolbox" as "HTM" application on BLE enabled Android or iOS devices. The value is not accurate because it measures nrf51822 tip temperature.

You will need to change offset value in the main.cpp.

It requires no sensor connection. The measured value will be change when you touch the nrf51822 tip or modue. I created it to check compatibility of "mbed HRM1017" and "BLE Nano kit".

Committer:
takafuminaka
Date:
Fri Jan 30 07:54:51 2015 +0000
Revision:
1:ed4b9dcade96
Parent:
0:1865c1b765f4
Update to recent Libraries

Who changed what in which revision?

UserRevisionLine numberNew contents of line
takafuminaka 0:1865c1b765f4 1 /* mbed Microcontroller Library
takafuminaka 0:1865c1b765f4 2 * Copyright (c) 2006-2013 ARM Limited
takafuminaka 0:1865c1b765f4 3 *
takafuminaka 0:1865c1b765f4 4 * Licensed under the Apache License, Version 2.0 (the "License");
takafuminaka 0:1865c1b765f4 5 * you may not use this file except in compliance with the License.
takafuminaka 0:1865c1b765f4 6 * You may obtain a copy of the License at
takafuminaka 0:1865c1b765f4 7 *
takafuminaka 0:1865c1b765f4 8 * http://www.apache.org/licenses/LICENSE-2.0
takafuminaka 0:1865c1b765f4 9 *
takafuminaka 0:1865c1b765f4 10 * Unless required by applicable law or agreed to in writing, software
takafuminaka 0:1865c1b765f4 11 * distributed under the License is distributed on an "AS IS" BASIS,
takafuminaka 0:1865c1b765f4 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
takafuminaka 0:1865c1b765f4 13 * See the License for the specific language governing permissions and
takafuminaka 0:1865c1b765f4 14 * limitations under the License.
takafuminaka 0:1865c1b765f4 15 */
takafuminaka 0:1865c1b765f4 16
takafuminaka 0:1865c1b765f4 17 #include "mbed.h"
takafuminaka 0:1865c1b765f4 18 #include "BLEDevice.h"
takafuminaka 0:1865c1b765f4 19 #include "ble_hrs.h"
takafuminaka 0:1865c1b765f4 20 #include "ble_hts.h"
takafuminaka 0:1865c1b765f4 21
takafuminaka 0:1865c1b765f4 22 #include "nrf_soc.h" // for internal Thermo sensoer
takafuminaka 0:1865c1b765f4 23
takafuminaka 0:1865c1b765f4 24 // nRF51822n nrf; /* BLE radio driver */
takafuminaka 0:1865c1b765f4 25 BLEDevice ble;
takafuminaka 0:1865c1b765f4 26 DigitalOut led1(LED1);
takafuminaka 0:1865c1b765f4 27 DigitalOut led2(LED2);
takafuminaka 0:1865c1b765f4 28 uint8_t cnt;
takafuminaka 0:1865c1b765f4 29
takafuminaka 0:1865c1b765f4 30 #define NEED_CONSOLE_OUTPUT 0 /* Set this if you need debug messages on the console;
takafuminaka 0:1865c1b765f4 31 * it will have an impact on code-size and power consumption. */
takafuminaka 0:1865c1b765f4 32
takafuminaka 0:1865c1b765f4 33 #if NEED_CONSOLE_OUTPUT
takafuminaka 0:1865c1b765f4 34 Serial pc(USBTX, USBRX);
takafuminaka 0:1865c1b765f4 35 #define DEBUG(...) { pc.printf(__VA_ARGS__); }
takafuminaka 0:1865c1b765f4 36 #else
takafuminaka 0:1865c1b765f4 37 #define DEBUG(...) /* nothing */
takafuminaka 0:1865c1b765f4 38 #endif /* #if NEED_CONSOLE_OUTPUT */
takafuminaka 0:1865c1b765f4 39
takafuminaka 0:1865c1b765f4 40 const static char DEVICE_NAME[] = "BLEnano-HTM";
takafuminaka 0:1865c1b765f4 41
takafuminaka 0:1865c1b765f4 42 /* Health Thermometer Service */
takafuminaka 0:1865c1b765f4 43 /* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.health_thermometer.xml */
takafuminaka 0:1865c1b765f4 44 /* HTM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml */
takafuminaka 0:1865c1b765f4 45 uint8_t thermTempPayload[5] = { 0, 0, 0, 0, 0 };
takafuminaka 0:1865c1b765f4 46
takafuminaka 0:1865c1b765f4 47 GattCharacteristic tempChar (GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR,
takafuminaka 0:1865c1b765f4 48 thermTempPayload, sizeof(thermTempPayload), sizeof(thermTempPayload),
takafuminaka 0:1865c1b765f4 49 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
takafuminaka 0:1865c1b765f4 50 GattCharacteristic *htmChars[] = {&tempChar, };
takafuminaka 0:1865c1b765f4 51 GattService htmService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, htmChars,
takafuminaka 0:1865c1b765f4 52 sizeof(htmChars) / sizeof(GattCharacteristic *));
takafuminaka 0:1865c1b765f4 53 /* Battery Level Service */
takafuminaka 0:1865c1b765f4 54 uint8_t batt = 98; /* Battery level */
takafuminaka 0:1865c1b765f4 55 uint8_t read_batt = 0; /* Variable to hold battery level reads */
takafuminaka 0:1865c1b765f4 56 static uint8_t bpm2[1] = {batt};
takafuminaka 0:1865c1b765f4 57 GattCharacteristic battLevel ( GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, bpm2, sizeof(bpm2), sizeof(bpm2),
takafuminaka 0:1865c1b765f4 58 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY |
takafuminaka 0:1865c1b765f4 59 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
takafuminaka 0:1865c1b765f4 60 GattCharacteristic *battChars[] = {&battLevel, };
takafuminaka 0:1865c1b765f4 61 GattService battService(GattService::UUID_BATTERY_SERVICE, battChars, sizeof(battChars) / sizeof(GattCharacteristic *));
takafuminaka 0:1865c1b765f4 62
takafuminaka 0:1865c1b765f4 63 static const uint16_t uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE, GattService::UUID_BATTERY_SERVICE, GattService::UUID_HEALTH_THERMOMETER_SERVICE + 0x1000 };
takafuminaka 0:1865c1b765f4 64
takafuminaka 0:1865c1b765f4 65 static volatile bool triggerSensorPolling = false; /* set to high periodically to indicate to the main thread that
takafuminaka 0:1865c1b765f4 66 * polling is necessary. */
takafuminaka 0:1865c1b765f4 67 static Gap::ConnectionParams_t connectionParams;
takafuminaka 0:1865c1b765f4 68
takafuminaka 0:1865c1b765f4 69 uint32_t quick_ieee11073_from_float(float temperature);
takafuminaka 0:1865c1b765f4 70
takafuminaka 0:1865c1b765f4 71 void Update_Values();
takafuminaka 0:1865c1b765f4 72
takafuminaka 0:1865c1b765f4 73 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) // Mod
takafuminaka 0:1865c1b765f4 74 {
takafuminaka 0:1865c1b765f4 75 DEBUG("Disconnected handle %u!\n\r", handle);
takafuminaka 0:1865c1b765f4 76 DEBUG("Restarting the advertising process\n\r");
takafuminaka 0:1865c1b765f4 77 led2 = 0;
takafuminaka 0:1865c1b765f4 78 ble.startAdvertising();
takafuminaka 0:1865c1b765f4 79
takafuminaka 0:1865c1b765f4 80 }
takafuminaka 0:1865c1b765f4 81
takafuminaka 0:1865c1b765f4 82 void onConnectionCallback(Gap::Handle_t handle,Gap::addr_type_t peerAddrType, const Gap::address_t peerAddr, const Gap::ConnectionParams_t *params) //Mod
takafuminaka 0:1865c1b765f4 83 {
takafuminaka 0:1865c1b765f4 84 DEBUG("connected. Got handle %u\r\n", handle);
takafuminaka 0:1865c1b765f4 85
takafuminaka 0:1865c1b765f4 86 connectionParams.slaveLatency = 1;
takafuminaka 0:1865c1b765f4 87 led2 = 1;
takafuminaka 0:1865c1b765f4 88 if (ble.updateConnectionParams(handle, &connectionParams) != BLE_ERROR_NONE) {
takafuminaka 0:1865c1b765f4 89 DEBUG("failed to update connection paramter\r\n");
takafuminaka 0:1865c1b765f4 90 }
takafuminaka 0:1865c1b765f4 91
takafuminaka 0:1865c1b765f4 92 }
takafuminaka 0:1865c1b765f4 93
takafuminaka 0:1865c1b765f4 94 /**
takafuminaka 0:1865c1b765f4 95 * Triggered periodically by the 'ticker' interrupt.
takafuminaka 0:1865c1b765f4 96 */
takafuminaka 0:1865c1b765f4 97 void periodicCallback(void)
takafuminaka 0:1865c1b765f4 98 {
takafuminaka 0:1865c1b765f4 99
takafuminaka 0:1865c1b765f4 100 led1 = !led1;
takafuminaka 0:1865c1b765f4 101 triggerSensorPolling = true;
takafuminaka 0:1865c1b765f4 102
takafuminaka 0:1865c1b765f4 103 // triggerSensorPolling = true; /* Note that the periodicCallback() executes in
takafuminaka 0:1865c1b765f4 104 // * interrupt context, so it is safer to do
takafuminaka 0:1865c1b765f4 105 // * heavy-weight sensor polling from the main
takafuminaka 0:1865c1b765f4 106 // * thread.*/
takafuminaka 0:1865c1b765f4 107 }
takafuminaka 0:1865c1b765f4 108
takafuminaka 0:1865c1b765f4 109 int main(void)
takafuminaka 0:1865c1b765f4 110 {
takafuminaka 0:1865c1b765f4 111 led1 = 1;
takafuminaka 0:1865c1b765f4 112 led2 = 1;
takafuminaka 0:1865c1b765f4 113 wait(3);
takafuminaka 0:1865c1b765f4 114
takafuminaka 0:1865c1b765f4 115 led1 = 0;
takafuminaka 0:1865c1b765f4 116 led2 = 0;
takafuminaka 0:1865c1b765f4 117 Ticker ticker;
takafuminaka 0:1865c1b765f4 118 ticker.attach(periodicCallback, 1.0 );
takafuminaka 0:1865c1b765f4 119 DEBUG("Initialising the nRF51822\n\r");
takafuminaka 0:1865c1b765f4 120 ble.init();
takafuminaka 0:1865c1b765f4 121 ble.onDisconnection(disconnectionCallback);
takafuminaka 0:1865c1b765f4 122 ble.onConnection(onConnectionCallback);
takafuminaka 0:1865c1b765f4 123
takafuminaka 0:1865c1b765f4 124 ble.getPreferredConnectionParams(&connectionParams);
takafuminaka 0:1865c1b765f4 125
takafuminaka 0:1865c1b765f4 126 /* setup advertising */
takafuminaka 0:1865c1b765f4 127 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
takafuminaka 0:1865c1b765f4 128 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t*)uuid16_list, sizeof(uuid16_list));
takafuminaka 0:1865c1b765f4 129 ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER);
takafuminaka 0:1865c1b765f4 130
takafuminaka 0:1865c1b765f4 131 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
takafuminaka 0:1865c1b765f4 132
takafuminaka 0:1865c1b765f4 133 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
takafuminaka 0:1865c1b765f4 134 ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
takafuminaka 0:1865c1b765f4 135 ble.startAdvertising();
takafuminaka 0:1865c1b765f4 136
takafuminaka 0:1865c1b765f4 137 ble.addService(htmService);
takafuminaka 0:1865c1b765f4 138 ble.addService(battService);
takafuminaka 0:1865c1b765f4 139
takafuminaka 0:1865c1b765f4 140 while (true) {
takafuminaka 0:1865c1b765f4 141 if (triggerSensorPolling) {
takafuminaka 0:1865c1b765f4 142 triggerSensorPolling = false;
takafuminaka 0:1865c1b765f4 143
takafuminaka 0:1865c1b765f4 144 Update_Values();
takafuminaka 0:1865c1b765f4 145
takafuminaka 0:1865c1b765f4 146 } else {
takafuminaka 0:1865c1b765f4 147 ble.waitForEvent();
takafuminaka 0:1865c1b765f4 148 }
takafuminaka 0:1865c1b765f4 149 }
takafuminaka 0:1865c1b765f4 150 }
takafuminaka 0:1865c1b765f4 151
takafuminaka 0:1865c1b765f4 152 void Update_Values()
takafuminaka 0:1865c1b765f4 153 {
takafuminaka 0:1865c1b765f4 154 /* Update the temperature. Note that we need to convert to an ieee11073 format float. */
takafuminaka 0:1865c1b765f4 155
takafuminaka 0:1865c1b765f4 156 int32_t p_temp;
takafuminaka 0:1865c1b765f4 157 sd_temp_get(&p_temp);
takafuminaka 0:1865c1b765f4 158 float temperature = float(p_temp)/4.;
takafuminaka 0:1865c1b765f4 159 temperature -= 16.;
takafuminaka 0:1865c1b765f4 160
takafuminaka 0:1865c1b765f4 161 DEBUG("temp:%f\n\r", temperature);
takafuminaka 0:1865c1b765f4 162 uint32_t temp_ieee11073 = quick_ieee11073_from_float(temperature);
takafuminaka 0:1865c1b765f4 163 memcpy(thermTempPayload+1, &temp_ieee11073, 4);
takafuminaka 0:1865c1b765f4 164
takafuminaka 0:1865c1b765f4 165 /* Battery Service Update */
takafuminaka 0:1865c1b765f4 166 /* Update battery level */
takafuminaka 0:1865c1b765f4 167 //ble.getGattServer().updateValue(battLevel.handle, (uint8_t*)&batt, sizeof(batt));
takafuminaka 0:1865c1b765f4 168 /* Decrement the battery level. */
takafuminaka 0:1865c1b765f4 169 batt <=50 ? batt=100 : batt--;;
takafuminaka 0:1865c1b765f4 170 bpm2[0] = batt;
takafuminaka 0:1865c1b765f4 171
takafuminaka 0:1865c1b765f4 172 if (ble.getGapState().connected ) {
takafuminaka 0:1865c1b765f4 173 ble.updateCharacteristicValue(tempChar.getValueAttribute().getHandle(), thermTempPayload, sizeof(thermTempPayload));
takafuminaka 0:1865c1b765f4 174 ble.updateCharacteristicValue(battLevel.getValueAttribute().getHandle(), (uint8_t *)&batt, sizeof(batt));
takafuminaka 0:1865c1b765f4 175 }
takafuminaka 0:1865c1b765f4 176 }
takafuminaka 0:1865c1b765f4 177
takafuminaka 0:1865c1b765f4 178 /**
takafuminaka 0:1865c1b765f4 179 * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
takafuminaka 0:1865c1b765f4 180 * @param temperature The temperature as a float.
takafuminaka 0:1865c1b765f4 181 * @return The temperature in 11073-20601 FLOAT-Type format.
takafuminaka 0:1865c1b765f4 182 */
takafuminaka 0:1865c1b765f4 183 uint32_t quick_ieee11073_from_float(float temperature)
takafuminaka 0:1865c1b765f4 184 {
takafuminaka 0:1865c1b765f4 185 uint8_t exponent = 0xFE; //exponent is -2
takafuminaka 0:1865c1b765f4 186 uint32_t mantissa = (uint32_t)(temperature*100);
takafuminaka 0:1865c1b765f4 187
takafuminaka 0:1865c1b765f4 188 return ( ((uint32_t)exponent) << 24) | mantissa;
takafuminaka 0:1865c1b765f4 189 }