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

Dependencies:   BLE_API mbed-src nRF51822

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "mbed.h"
00018 #include "BLEDevice.h"
00019 #include "ble_hrs.h"
00020 #include "ble_hts.h"
00021 
00022 #include "nrf_soc.h" // for internal Thermo sensoer
00023 
00024 // nRF51822n   nrf;                               /* BLE radio driver */
00025 BLEDevice  ble;
00026 DigitalOut led1(LED1);
00027 DigitalOut led2(LED2);
00028 uint8_t cnt;
00029 
00030 #define NEED_CONSOLE_OUTPUT 0 /* Set this if you need debug messages on the console;
00031                                * it will have an impact on code-size and power consumption. */
00032 
00033 #if NEED_CONSOLE_OUTPUT
00034 Serial  pc(USBTX, USBRX);
00035 #define DEBUG(...) { pc.printf(__VA_ARGS__); }
00036 #else
00037 #define DEBUG(...) /* nothing */
00038 #endif /* #if NEED_CONSOLE_OUTPUT */
00039 
00040 const static char  DEVICE_NAME[] = "BLEnano-HTM";
00041 
00042 /* Health Thermometer Service */ 
00043 /* Service:  https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.health_thermometer.xml */
00044 /* HTM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml */
00045 uint8_t             thermTempPayload[5] = { 0, 0, 0, 0, 0 };
00046 
00047 GattCharacteristic  tempChar (GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR,
00048                                 thermTempPayload, sizeof(thermTempPayload), sizeof(thermTempPayload),
00049                                 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
00050 GattCharacteristic *htmChars[] = {&tempChar, };
00051 GattService        htmService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, htmChars, 
00052                                 sizeof(htmChars) / sizeof(GattCharacteristic *));
00053 /* Battery Level Service */
00054 uint8_t            batt = 98;     /* Battery level */
00055 uint8_t            read_batt = 0; /* Variable to hold battery level reads */
00056 static uint8_t bpm2[1] = {batt};
00057 GattCharacteristic battLevel   ( GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, bpm2, sizeof(bpm2), sizeof(bpm2),
00058                                  GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY |
00059                                  GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
00060 GattCharacteristic *battChars[] = {&battLevel, };
00061 GattService        battService(GattService::UUID_BATTERY_SERVICE, battChars, sizeof(battChars) / sizeof(GattCharacteristic *));
00062 
00063 static const uint16_t uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE, GattService::UUID_BATTERY_SERVICE, GattService::UUID_HEALTH_THERMOMETER_SERVICE + 0x1000 };
00064 
00065 static volatile bool triggerSensorPolling = false; /* set to high periodically to indicate to the main thread that
00066                                                     * polling is necessary. */
00067 static Gap::ConnectionParams_t connectionParams;
00068 
00069 uint32_t quick_ieee11073_from_float(float temperature);
00070 
00071 void Update_Values();
00072 
00073 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)    // Mod
00074 {
00075     DEBUG("Disconnected handle %u!\n\r", handle);
00076     DEBUG("Restarting the advertising process\n\r");
00077     led2 = 0;
00078     ble.startAdvertising();
00079 
00080 }
00081 
00082 void onConnectionCallback(Gap::Handle_t handle,Gap::addr_type_t peerAddrType, const Gap::address_t peerAddr, const Gap::ConnectionParams_t *params)   //Mod
00083 {
00084     DEBUG("connected. Got handle %u\r\n", handle);
00085 
00086     connectionParams.slaveLatency = 1;
00087     led2 = 1;
00088     if (ble.updateConnectionParams(handle, &connectionParams) != BLE_ERROR_NONE) {
00089         DEBUG("failed to update connection paramter\r\n");
00090     }
00091     
00092 }
00093 
00094 /**
00095  * Triggered periodically by the 'ticker' interrupt.
00096  */
00097 void periodicCallback(void)
00098 {
00099 
00100     led1 = !led1;
00101     triggerSensorPolling = true;
00102         
00103     // triggerSensorPolling = true; /* Note that the periodicCallback() executes in
00104     //                              * interrupt context, so it is safer to do
00105     //                              * heavy-weight sensor polling from the main
00106     //                              * thread.*/
00107 }
00108 
00109 int main(void)
00110 {
00111     led1 = 1;
00112     led2 = 1;
00113     wait(3);
00114 
00115     led1 = 0;
00116     led2 = 0;
00117     Ticker ticker;
00118     ticker.attach(periodicCallback, 1.0 );
00119     DEBUG("Initialising the nRF51822\n\r");
00120     ble.init();
00121     ble.onDisconnection(disconnectionCallback);
00122     ble.onConnection(onConnectionCallback);
00123 
00124     ble.getPreferredConnectionParams(&connectionParams);
00125 
00126     /* setup advertising */
00127     ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00128     ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t*)uuid16_list, sizeof(uuid16_list));
00129     ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER);
00130 
00131     ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
00132 
00133     ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00134     ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
00135     ble.startAdvertising();
00136 
00137     ble.addService(htmService);
00138     ble.addService(battService);
00139 
00140     while (true) {
00141         if (triggerSensorPolling) {
00142             triggerSensorPolling = false;
00143 
00144             Update_Values();
00145             
00146         } else {
00147             ble.waitForEvent();
00148         }
00149     }
00150 }
00151 
00152 void Update_Values()
00153 {
00154     /* Update the temperature. Note that we need to convert to an ieee11073 format float. */
00155 
00156     int32_t p_temp;
00157     sd_temp_get(&p_temp);
00158     float temperature = float(p_temp)/4.;
00159     temperature -= 16.;
00160            
00161     DEBUG("temp:%f\n\r", temperature);
00162     uint32_t temp_ieee11073 = quick_ieee11073_from_float(temperature);
00163     memcpy(thermTempPayload+1, &temp_ieee11073, 4);
00164 
00165     /* Battery Service Update */
00166     /* Update battery level */
00167     //ble.getGattServer().updateValue(battLevel.handle, (uint8_t*)&batt, sizeof(batt));
00168     /* Decrement the battery level. */
00169     batt <=50 ? batt=100 : batt--;;
00170     bpm2[0] = batt;
00171 
00172     if (ble.getGapState().connected ) {
00173         ble.updateCharacteristicValue(tempChar.getValueAttribute().getHandle(), thermTempPayload, sizeof(thermTempPayload));
00174         ble.updateCharacteristicValue(battLevel.getValueAttribute().getHandle(), (uint8_t *)&batt, sizeof(batt));
00175     }
00176 }
00177 
00178 /**
00179  * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
00180  * @param temperature The temperature as a float.
00181  * @return The temperature in 11073-20601 FLOAT-Type format.
00182  */
00183 uint32_t quick_ieee11073_from_float(float temperature)
00184 {
00185     uint8_t  exponent = 0xFE; //exponent is -2
00186     uint32_t mantissa = (uint32_t)(temperature*100);
00187     
00188     return ( ((uint32_t)exponent) << 24) | mantissa;
00189 }