BLE HTM (Thermometer) by nrf51822 internal temperature sensor. I confirmed with "mbed HRM1017" and "BLE Nano kit".
Dependencies: BLE_API mbed-src nRF51822
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 }
Generated on Thu Jul 14 2022 06:43:25 by 1.7.2