BLE_HTS_Demo

This BLE_HTS_Demo program enables you to collect Temperature and Humidity data reading from sensor and transmit to collector device such as smartphone.

Below documents teach you how to install app that can connect and read data from our DELTA-DFCM-NNN40 development board. There are two versions, Android and iPhone.

/media/uploads/Marcomissyou/ios_app_for_environment_sensor_0518.pdf

/media/uploads/Marcomissyou/android_app_for_environment_sensor.pdf

Committer:
silviaChen
Date:
Tue Jul 18 09:34:06 2017 +0000
Revision:
9:2ff66a3d164a
Parent:
8:4653319ba675
update mbed-os so both NNN50 and NQ620 (as well as NQ624 module) platform are supported; Add config in mbed_app.json to fix NQ620 use internal RC issue ; remove the unused shield folder;update BLE_API;Modify SCL/SDA pin

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Marcomissyou 0:ef0f188a6fdd 1 /* mbed Microcontroller Library
Marcomissyou 0:ef0f188a6fdd 2 * Copyright (c) 2006-2013 ARM Limited
Marcomissyou 0:ef0f188a6fdd 3 *
Marcomissyou 0:ef0f188a6fdd 4 * Licensed under the Apache License, Version 2.0 (the "License");
Marcomissyou 0:ef0f188a6fdd 5 * you may not use this file except in compliance with the License.
Marcomissyou 0:ef0f188a6fdd 6 * You may obtain a copy of the License at
Marcomissyou 0:ef0f188a6fdd 7 *
Marcomissyou 0:ef0f188a6fdd 8 * http://www.apache.org/licenses/LICENSE-2.0
Marcomissyou 0:ef0f188a6fdd 9 *
Marcomissyou 0:ef0f188a6fdd 10 * Unless required by applicable law or agreed to in writing, software
Marcomissyou 0:ef0f188a6fdd 11 * distributed under the License is distributed on an "AS IS" BASIS,
Marcomissyou 0:ef0f188a6fdd 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Marcomissyou 0:ef0f188a6fdd 13 * See the License for the specific language governing permissions and
Marcomissyou 0:ef0f188a6fdd 14 * limitations under the License.
Marcomissyou 0:ef0f188a6fdd 15 */
Marcomissyou 0:ef0f188a6fdd 16
Marcomissyou 0:ef0f188a6fdd 17 #include "mbed.h"
silviaChen 9:2ff66a3d164a 18 #include "ble/services/BatteryService.h"
silviaChen 9:2ff66a3d164a 19 #include "ble/services/DeviceInformationService.h"
silviaChen 9:2ff66a3d164a 20 #include "ble/BLE.h"
Marcomissyou 0:ef0f188a6fdd 21
Marcomissyou 0:ef0f188a6fdd 22 #include "hts221.h"
Marcomissyou 0:ef0f188a6fdd 23 #include "uvis25.h"
Marcomissyou 0:ef0f188a6fdd 24
Marcomissyou 3:6a9082a10dc9 25 DigitalOut led1(LED1);
Marcomissyou 0:ef0f188a6fdd 26
Marcomissyou 0:ef0f188a6fdd 27 static const uint8_t UUID_HUMI_AND_UVI[] = {0xf5, 0x59, 0xa2, 0x49, 0xbe, 0xb1, 0x4c, 0x54, 0xa1, 0x0a, 0xc7, 0x95, 0x7e, 0x17, 0xf8, 0x67};
Marcomissyou 0:ef0f188a6fdd 28 uint8_t wrs_HumiUVI_payload[11] = {0, };
Marcomissyou 0:ef0f188a6fdd 29 uint8_t htsTempPayload[7] = {0,};
Marcomissyou 0:ef0f188a6fdd 30 /* Health Thermometer Service */
Marcomissyou 0:ef0f188a6fdd 31 /* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.heart_rate.xml */
Marcomissyou 0:ef0f188a6fdd 32 /* Temperature Measurement: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml */
Marcomissyou 0:ef0f188a6fdd 33 GattCharacteristic htsTemp ( GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR, htsTempPayload, 6, 13, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
Marcomissyou 0:ef0f188a6fdd 34 GattCharacteristic wrs_HumiUVI ( UUID_HUMI_AND_UVI, wrs_HumiUVI_payload, 1, 7, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
Marcomissyou 0:ef0f188a6fdd 35 GattCharacteristic *htsChars[] = {&htsTemp, &wrs_HumiUVI};
Marcomissyou 0:ef0f188a6fdd 36 GattService htsService ( GattService::UUID_HEALTH_THERMOMETER_SERVICE, htsChars, sizeof(htsChars) / sizeof(GattCharacteristic *));
Marcomissyou 0:ef0f188a6fdd 37
Marcomissyou 0:ef0f188a6fdd 38 float tempCelsius = 25.50;
Marcomissyou 0:ef0f188a6fdd 39 int32_t tempCelsius_ix100;
Marcomissyou 0:ef0f188a6fdd 40 int8_t exponent = -2;
Marcomissyou 0:ef0f188a6fdd 41 uint8_t UTC[7] = { 222, 7, 9, 11, 13, 42, 59 };
Marcomissyou 0:ef0f188a6fdd 42 float humi = 55;
Marcomissyou 0:ef0f188a6fdd 43 int32_t humi_ix100;
Marcomissyou 0:ef0f188a6fdd 44 uint8_t uvi = 8;
Marcomissyou 0:ef0f188a6fdd 45 uint32_t counter = 0;
Marcomissyou 0:ef0f188a6fdd 46
Marcomissyou 0:ef0f188a6fdd 47 const static char DEVICE_NAME[] = "WRS_d7";
Marcomissyou 0:ef0f188a6fdd 48 static const uint16_t uuid16_list[] = {GattService::UUID_BATTERY_SERVICE,
Marcomissyou 0:ef0f188a6fdd 49 GattService::UUID_DEVICE_INFORMATION_SERVICE};
Marcomissyou 0:ef0f188a6fdd 50 static volatile bool triggerSensorPolling = false;
Marcomissyou 0:ef0f188a6fdd 51
Marcomissyou 0:ef0f188a6fdd 52 /**************************************************************************/
Marcomissyou 0:ef0f188a6fdd 53 /*!
Marcomissyou 0:ef0f188a6fdd 54 @brief This custom class can be used to override any GattServerEvents
Marcomissyou 0:ef0f188a6fdd 55 that you are interested in handling on an application level.
Marcomissyou 0:ef0f188a6fdd 56 */
Marcomissyou 0:ef0f188a6fdd 57 /**************************************************************************/
Marcomissyou 0:ef0f188a6fdd 58 //
tsungta 7:c6c5ba871c2d 59 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
Marcomissyou 0:ef0f188a6fdd 60 {
silviaChen 9:2ff66a3d164a 61 BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising(); // restart advertising
Marcomissyou 0:ef0f188a6fdd 62 }
Marcomissyou 0:ef0f188a6fdd 63
Marcomissyou 0:ef0f188a6fdd 64 void periodicCallback(void)
Marcomissyou 0:ef0f188a6fdd 65 {
Marcomissyou 3:6a9082a10dc9 66 led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
Marcomissyou 0:ef0f188a6fdd 67
Marcomissyou 0:ef0f188a6fdd 68 /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
Marcomissyou 0:ef0f188a6fdd 69 * heavy-weight sensor polling from the main thread. */
Marcomissyou 0:ef0f188a6fdd 70 triggerSensorPolling = true;
Marcomissyou 0:ef0f188a6fdd 71 }
silviaChen 9:2ff66a3d164a 72
silviaChen 9:2ff66a3d164a 73 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
silviaChen 9:2ff66a3d164a 74 {
silviaChen 9:2ff66a3d164a 75 BLE &ble = params->ble;
silviaChen 9:2ff66a3d164a 76 ble_error_t error = params->error;
silviaChen 9:2ff66a3d164a 77
silviaChen 9:2ff66a3d164a 78 if (error != BLE_ERROR_NONE) {
silviaChen 9:2ff66a3d164a 79 return;
silviaChen 9:2ff66a3d164a 80 }
silviaChen 9:2ff66a3d164a 81
silviaChen 9:2ff66a3d164a 82 ble.gap().onDisconnection(disconnectionCallback);
silviaChen 9:2ff66a3d164a 83
silviaChen 9:2ff66a3d164a 84 /* Setup auxiliary services. */
silviaChen 9:2ff66a3d164a 85 BatteryService battery(ble);
silviaChen 9:2ff66a3d164a 86 DeviceInformationService deviceInfo(ble, "Delta", "NQ620", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
silviaChen 9:2ff66a3d164a 87
silviaChen 9:2ff66a3d164a 88 /* Setup advertising. */
silviaChen 9:2ff66a3d164a 89 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
silviaChen 9:2ff66a3d164a 90 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
silviaChen 9:2ff66a3d164a 91 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
silviaChen 9:2ff66a3d164a 92 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
silviaChen 9:2ff66a3d164a 93 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
silviaChen 9:2ff66a3d164a 94 ble.gap().setAdvertisingInterval(1000); /* 1000ms */
silviaChen 9:2ff66a3d164a 95 ble.gap().startAdvertising();
silviaChen 9:2ff66a3d164a 96
silviaChen 9:2ff66a3d164a 97 ble.addService(htsService);
silviaChen 9:2ff66a3d164a 98 }
silviaChen 9:2ff66a3d164a 99
Marcomissyou 0:ef0f188a6fdd 100 /**************************************************************************/
Marcomissyou 0:ef0f188a6fdd 101 /*!
Marcomissyou 0:ef0f188a6fdd 102 @brief Program entry point
Marcomissyou 0:ef0f188a6fdd 103 */
Marcomissyou 0:ef0f188a6fdd 104 /**************************************************************************/
Marcomissyou 0:ef0f188a6fdd 105
Marcomissyou 0:ef0f188a6fdd 106 int main(void)
Marcomissyou 0:ef0f188a6fdd 107 {
Marcomissyou 0:ef0f188a6fdd 108
tsungta 7:c6c5ba871c2d 109 hts221_init();
tsungta 7:c6c5ba871c2d 110 uvis25_init();
tsungta 7:c6c5ba871c2d 111
Marcomissyou 0:ef0f188a6fdd 112 HTS221_Calib();
Marcomissyou 0:ef0f188a6fdd 113
Marcomissyou 0:ef0f188a6fdd 114 Ticker ticker;
Marcomissyou 0:ef0f188a6fdd 115 ticker.attach(periodicCallback, 2);
Marcomissyou 0:ef0f188a6fdd 116
silviaChen 9:2ff66a3d164a 117 BLE& ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
silviaChen 9:2ff66a3d164a 118 ble.init(bleInitComplete);
silviaChen 9:2ff66a3d164a 119
silviaChen 9:2ff66a3d164a 120 //ble.init();
silviaChen 9:2ff66a3d164a 121 // ble.onDisconnection(disconnectionCallback);
Marcomissyou 0:ef0f188a6fdd 122
silviaChen 9:2ff66a3d164a 123 /* SpinWait for initialization to complete. This is necessary because the
silviaChen 9:2ff66a3d164a 124 * BLE object is used in the main loop below. */
silviaChen 9:2ff66a3d164a 125 while (ble.hasInitialized() == false) { /* spin loop */ }
Marcomissyou 0:ef0f188a6fdd 126
silviaChen 9:2ff66a3d164a 127 while (1) {
Marcomissyou 0:ef0f188a6fdd 128
tsungta 7:c6c5ba871c2d 129 if(hts221_verify_product_id())
tsungta 7:c6c5ba871c2d 130 HTS221_ReadTempHumi(&tempCelsius, &humi);
tsungta 7:c6c5ba871c2d 131 else {
tsungta 7:c6c5ba871c2d 132 //show dummy value
tsungta 7:c6c5ba871c2d 133 tempCelsius = 100;
tsungta 7:c6c5ba871c2d 134 humi = 100;
tsungta 7:c6c5ba871c2d 135 }
tsungta 7:c6c5ba871c2d 136
tsungta 7:c6c5ba871c2d 137 if(uvis25_verify_product_id())
Marcomissyou 3:6a9082a10dc9 138 uvi = UVIS25_ReadUVI();
tsungta 7:c6c5ba871c2d 139 else
Marcomissyou 3:6a9082a10dc9 140 uvi = 100; //Environment Sensor APP will show NO UV DEVICE.
tsungta 7:c6c5ba871c2d 141
Marcomissyou 0:ef0f188a6fdd 142 /* Update the Temperature measurement */
Marcomissyou 0:ef0f188a6fdd 143 /* See --> https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml */
Marcomissyou 0:ef0f188a6fdd 144 tempCelsius_ix100 = tempCelsius * 100;
Marcomissyou 0:ef0f188a6fdd 145 htsTempPayload[0] = 0x02; // flag
Marcomissyou 0:ef0f188a6fdd 146 htsTempPayload[1] = tempCelsius_ix100%0xff;
Marcomissyou 0:ef0f188a6fdd 147 htsTempPayload[2] = tempCelsius_ix100/0xff;
Marcomissyou 0:ef0f188a6fdd 148 htsTempPayload[3] = tempCelsius_ix100/0xffff;
Marcomissyou 0:ef0f188a6fdd 149 htsTempPayload[4] = exponent;
Marcomissyou 0:ef0f188a6fdd 150 for (int i = 0; i < 7; i++) htsTempPayload[i+5] = UTC[i];
Marcomissyou 0:ef0f188a6fdd 151 ble.updateCharacteristicValue(htsTemp.getValueAttribute().getHandle(), htsTempPayload, 12);
Marcomissyou 0:ef0f188a6fdd 152
Marcomissyou 0:ef0f188a6fdd 153 ble.waitForEvent();
Marcomissyou 1:a7ecbb0ccc61 154 wait(1);
Marcomissyou 0:ef0f188a6fdd 155 wrs_HumiUVI_payload[0] = 0x03; // flag
Marcomissyou 0:ef0f188a6fdd 156 memcpy(&wrs_HumiUVI_payload[1],&humi,4);
Marcomissyou 0:ef0f188a6fdd 157 wrs_HumiUVI_payload[5] = uvi;
Marcomissyou 0:ef0f188a6fdd 158
Marcomissyou 0:ef0f188a6fdd 159 ble.updateCharacteristicValue(wrs_HumiUVI.getValueAttribute().getHandle(), wrs_HumiUVI_payload, 6);
Marcomissyou 0:ef0f188a6fdd 160 ble.waitForEvent();
Marcomissyou 0:ef0f188a6fdd 161 wait(1);
Marcomissyou 0:ef0f188a6fdd 162
Marcomissyou 0:ef0f188a6fdd 163 }
Marcomissyou 0:ef0f188a6fdd 164
Marcomissyou 1:a7ecbb0ccc61 165 }