BLE Lightning sensor for Nordic NRF51822 based module
Dependencies: AS3935 AS3935_ext BLE_API mbed nRF51822 nrf51_rtc
main.cpp@2:e1e638cbf972, 2015-08-30 (annotated)
- Committer:
- takafuminaka
- Date:
- Sun Aug 30 06:27:27 2015 +0000
- Revision:
- 2:e1e638cbf972
- Parent:
- 1:a4119049dd99
- Child:
- 3:2ea547dab8a8
Intermediate
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
takafuminaka | 0:371bcac81ea2 | 1 | /* |
takafuminaka | 0:371bcac81ea2 | 2 | |
takafuminaka | 0:371bcac81ea2 | 3 | */ |
takafuminaka | 0:371bcac81ea2 | 4 | |
takafuminaka | 0:371bcac81ea2 | 5 | #include "mbed.h" |
takafuminaka | 1:a4119049dd99 | 6 | #include "BLE.h" |
takafuminaka | 0:371bcac81ea2 | 7 | #include "nrf51_rtc.h" |
takafuminaka | 0:371bcac81ea2 | 8 | #include "AS3935_ext.h" |
takafuminaka | 0:371bcac81ea2 | 9 | |
takafuminaka | 1:a4119049dd99 | 10 | #include "nrf_soc.h" // for internal Thermo sensoer |
takafuminaka | 1:a4119049dd99 | 11 | |
takafuminaka | 1:a4119049dd99 | 12 | #define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console; |
takafuminaka | 1:a4119049dd99 | 13 | * it will have an impact on code-size and power consumption. */ |
takafuminaka | 1:a4119049dd99 | 14 | |
takafuminaka | 1:a4119049dd99 | 15 | #if NEED_CONSOLE_OUTPUT |
takafuminaka | 1:a4119049dd99 | 16 | Serial pc(USBTX, USBRX); |
takafuminaka | 1:a4119049dd99 | 17 | #define DEBUG(...) { pc.printf(__VA_ARGS__); } |
takafuminaka | 1:a4119049dd99 | 18 | #else |
takafuminaka | 1:a4119049dd99 | 19 | #define DEBUG(...) /* nothing */ |
takafuminaka | 1:a4119049dd99 | 20 | #endif /* #if NEED_CONSOLE_OUTPUT */ |
takafuminaka | 1:a4119049dd99 | 21 | |
takafuminaka | 1:a4119049dd99 | 22 | // Prepare BLE device |
takafuminaka | 1:a4119049dd99 | 23 | BLEDevice ble; |
takafuminaka | 1:a4119049dd99 | 24 | const static char DEVICE_NAME[] = "BLE-LITNING-S"; |
takafuminaka | 1:a4119049dd99 | 25 | |
takafuminaka | 1:a4119049dd99 | 26 | /* Health Thermometer Service */ |
takafuminaka | 1:a4119049dd99 | 27 | /* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.health_thermometer.xml */ |
takafuminaka | 1:a4119049dd99 | 28 | /* HTM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature_measurement.xml */ |
takafuminaka | 1:a4119049dd99 | 29 | uint8_t thermTempPayload[5] = { 0, 0, 0, 0, 0 }; |
takafuminaka | 1:a4119049dd99 | 30 | |
takafuminaka | 1:a4119049dd99 | 31 | GattCharacteristic tempChar (GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR, |
takafuminaka | 1:a4119049dd99 | 32 | thermTempPayload, sizeof(thermTempPayload), sizeof(thermTempPayload), |
takafuminaka | 1:a4119049dd99 | 33 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE); |
takafuminaka | 1:a4119049dd99 | 34 | GattCharacteristic *htmChars[] = {&tempChar, }; |
takafuminaka | 1:a4119049dd99 | 35 | GattService htmService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, htmChars, |
takafuminaka | 1:a4119049dd99 | 36 | sizeof(htmChars) / sizeof(GattCharacteristic *)); |
takafuminaka | 1:a4119049dd99 | 37 | |
takafuminaka | 1:a4119049dd99 | 38 | /* Original Thermometer Service */ |
takafuminaka | 1:a4119049dd99 | 39 | /* with nRF51822 internal thermal sensor */ |
takafuminaka | 1:a4119049dd99 | 40 | uint8_t internalTempPayload[5] = { 0, 0, 0, 0, 0 }; |
takafuminaka | 1:a4119049dd99 | 41 | |
takafuminaka | 1:a4119049dd99 | 42 | GattCharacteristic internalTempChar (GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR + 0x2000, |
takafuminaka | 1:a4119049dd99 | 43 | internalTempPayload, sizeof(internalTempPayload), sizeof(internalTempPayload), |
takafuminaka | 1:a4119049dd99 | 44 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE); |
takafuminaka | 1:a4119049dd99 | 45 | GattCharacteristic *itmChars[] = {&internalTempChar, }; |
takafuminaka | 1:a4119049dd99 | 46 | GattService itmService(GattService::UUID_HEALTH_THERMOMETER_SERVICE + 0x2000, itmChars, |
takafuminaka | 1:a4119049dd99 | 47 | sizeof(itmChars) / sizeof(GattCharacteristic *)); |
takafuminaka | 1:a4119049dd99 | 48 | |
takafuminaka | 1:a4119049dd99 | 49 | /* Battery Level Service */ |
takafuminaka | 1:a4119049dd99 | 50 | uint8_t batt = 98; /* Battery level */ |
takafuminaka | 1:a4119049dd99 | 51 | uint8_t read_batt = 0; /* Variable to hold battery level reads */ |
takafuminaka | 1:a4119049dd99 | 52 | static uint8_t bpm2[1] = {batt}; |
takafuminaka | 1:a4119049dd99 | 53 | GattCharacteristic battLevel ( GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, bpm2, sizeof(bpm2), sizeof(bpm2), |
takafuminaka | 1:a4119049dd99 | 54 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | |
takafuminaka | 1:a4119049dd99 | 55 | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); |
takafuminaka | 1:a4119049dd99 | 56 | GattCharacteristic *battChars[] = {&battLevel, }; |
takafuminaka | 1:a4119049dd99 | 57 | GattService battService(GattService::UUID_BATTERY_SERVICE, battChars, sizeof(battChars) / sizeof(GattCharacteristic *)); |
takafuminaka | 1:a4119049dd99 | 58 | |
takafuminaka | 1:a4119049dd99 | 59 | static const uint16_t uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE, GattService::UUID_BATTERY_SERVICE, GattService::UUID_HEALTH_THERMOMETER_SERVICE + 0x2000 }; |
takafuminaka | 1:a4119049dd99 | 60 | |
takafuminaka | 1:a4119049dd99 | 61 | static volatile bool triggerSensorPolling = false; /* set to high periodically to indicate to the main thread that |
takafuminaka | 1:a4119049dd99 | 62 | * polling is necessary. */ |
takafuminaka | 1:a4119049dd99 | 63 | static Gap::ConnectionParams_t connectionParams; |
takafuminaka | 1:a4119049dd99 | 64 | |
takafuminaka | 1:a4119049dd99 | 65 | uint32_t quick_ieee11073_from_float(float temperature); |
takafuminaka | 1:a4119049dd99 | 66 | |
takafuminaka | 1:a4119049dd99 | 67 | void Update_Values(); |
takafuminaka | 1:a4119049dd99 | 68 | |
takafuminaka | 1:a4119049dd99 | 69 | |
takafuminaka | 1:a4119049dd99 | 70 | // Prepare LED device |
takafuminaka | 1:a4119049dd99 | 71 | DigitalOut led1(LED1); |
takafuminaka | 1:a4119049dd99 | 72 | DigitalOut led2(LED2); |
takafuminaka | 1:a4119049dd99 | 73 | |
takafuminaka | 0:371bcac81ea2 | 74 | AS3935_ext Lightning(I2C_SDA0,I2C_SCL0,0x00,P0_23); |
takafuminaka | 0:371bcac81ea2 | 75 | InterruptIn IntLightning(P0_23); //IRQ AS3935 |
takafuminaka | 0:371bcac81ea2 | 76 | |
takafuminaka | 0:371bcac81ea2 | 77 | // used for the example only, not required for rtc use |
takafuminaka | 0:371bcac81ea2 | 78 | DigitalIn button1(BUTTON1); // used to trigger the time report |
takafuminaka | 0:371bcac81ea2 | 79 | InterruptIn button1Press(BUTTON1); |
takafuminaka | 0:371bcac81ea2 | 80 | |
takafuminaka | 0:371bcac81ea2 | 81 | |
takafuminaka | 0:371bcac81ea2 | 82 | time_t example_time() { |
takafuminaka | 0:371bcac81ea2 | 83 | // set an intial time |
takafuminaka | 0:371bcac81ea2 | 84 | // ...not really necessary for this example, but it beats setting it to 0 or some non-obvious large integer (# of seconds since 1/1/1970) |
takafuminaka | 0:371bcac81ea2 | 85 | time_t rawtime=0; |
takafuminaka | 0:371bcac81ea2 | 86 | |
takafuminaka | 0:371bcac81ea2 | 87 | struct tm * init_timeinfo; |
takafuminaka | 0:371bcac81ea2 | 88 | |
takafuminaka | 0:371bcac81ea2 | 89 | // initialize time |
takafuminaka | 0:371bcac81ea2 | 90 | init_timeinfo = localtime(&rawtime); // note: must initialize the struct with this before trying to set components |
takafuminaka | 0:371bcac81ea2 | 91 | // ...else code goes into the weeds!! |
takafuminaka | 0:371bcac81ea2 | 92 | init_timeinfo->tm_sec = 0; |
takafuminaka | 0:371bcac81ea2 | 93 | init_timeinfo->tm_min = 0; |
takafuminaka | 0:371bcac81ea2 | 94 | init_timeinfo->tm_hour = 0; |
takafuminaka | 0:371bcac81ea2 | 95 | init_timeinfo->tm_mon = 0; |
takafuminaka | 0:371bcac81ea2 | 96 | init_timeinfo->tm_mday = 1; |
takafuminaka | 2:e1e638cbf972 | 97 | init_timeinfo->tm_year = 70; |
takafuminaka | 0:371bcac81ea2 | 98 | |
takafuminaka | 0:371bcac81ea2 | 99 | char date[24]; |
takafuminaka | 0:371bcac81ea2 | 100 | strftime(date,sizeof(date),"%H:%M:%S on %m/%d/%G",init_timeinfo); |
takafuminaka | 1:a4119049dd99 | 101 | DEBUG("Initial time set is %s.\r\n",date); |
takafuminaka | 0:371bcac81ea2 | 102 | |
takafuminaka | 0:371bcac81ea2 | 103 | // compute the proper value for time in time_t type |
takafuminaka | 0:371bcac81ea2 | 104 | rawtime = mktime(init_timeinfo); |
takafuminaka | 0:371bcac81ea2 | 105 | return rawtime; |
takafuminaka | 0:371bcac81ea2 | 106 | } |
takafuminaka | 1:a4119049dd99 | 107 | |
takafuminaka | 0:371bcac81ea2 | 108 | void print_time() { |
takafuminaka | 0:371bcac81ea2 | 109 | // called when a button is pushed, this prints the current time to the USB-connected console |
takafuminaka | 0:371bcac81ea2 | 110 | |
takafuminaka | 0:371bcac81ea2 | 111 | time_t rawtime=rtc.time(); |
takafuminaka | 0:371bcac81ea2 | 112 | |
takafuminaka | 0:371bcac81ea2 | 113 | // massage the time into a human-friendly format for printing |
takafuminaka | 0:371bcac81ea2 | 114 | struct tm * timeinfo; |
takafuminaka | 0:371bcac81ea2 | 115 | timeinfo = localtime(&rawtime); |
takafuminaka | 0:371bcac81ea2 | 116 | char date[24]; |
takafuminaka | 0:371bcac81ea2 | 117 | strftime(date,sizeof(date),"%H:%M:%S on %m/%d/%G",timeinfo); |
takafuminaka | 1:a4119049dd99 | 118 | DEBUG("The current time is %s.(%d)\r\n",date,rawtime); |
takafuminaka | 0:371bcac81ea2 | 119 | } |
takafuminaka | 0:371bcac81ea2 | 120 | |
takafuminaka | 1:a4119049dd99 | 121 | void periodic_update() { |
takafuminaka | 0:371bcac81ea2 | 122 | // for use as interrupt routine, to insure that RTC is updated periodically |
takafuminaka | 0:371bcac81ea2 | 123 | // ...if rtc is not read before the underlying counter rolls over (typically 512 seconds), the RTC value will be wrong |
takafuminaka | 0:371bcac81ea2 | 124 | // ...ideally this would be done as part of the nrf51_rtc method, but I couldn't get it to behave (see nrf51_rtc.cpp for details) |
takafuminaka | 0:371bcac81ea2 | 125 | rtc.time(); |
takafuminaka | 1:a4119049dd99 | 126 | Lightning.lightningDistanceKm(); |
takafuminaka | 1:a4119049dd99 | 127 | led1 = !led1; |
takafuminaka | 1:a4119049dd99 | 128 | |
takafuminaka | 1:a4119049dd99 | 129 | triggerSensorPolling = true; |
takafuminaka | 0:371bcac81ea2 | 130 | // print_time(); |
takafuminaka | 0:371bcac81ea2 | 131 | } |
takafuminaka | 0:371bcac81ea2 | 132 | |
takafuminaka | 0:371bcac81ea2 | 133 | void DetectLightning() |
takafuminaka | 0:371bcac81ea2 | 134 | { |
takafuminaka | 0:371bcac81ea2 | 135 | char OriginInt; |
takafuminaka | 0:371bcac81ea2 | 136 | time_t rawtime=rtc.time(); |
takafuminaka | 0:371bcac81ea2 | 137 | struct tm * timeinfo; |
takafuminaka | 0:371bcac81ea2 | 138 | timeinfo = localtime(&rawtime); |
takafuminaka | 0:371bcac81ea2 | 139 | char date[24]; |
takafuminaka | 0:371bcac81ea2 | 140 | int distance; |
takafuminaka | 0:371bcac81ea2 | 141 | |
takafuminaka | 0:371bcac81ea2 | 142 | strftime(date,sizeof(date),"%H:%M:%S on %m/%d/%G",timeinfo); |
takafuminaka | 0:371bcac81ea2 | 143 | |
takafuminaka | 0:371bcac81ea2 | 144 | wait_ms(2); //on attend 2ms préconisation constructeur |
takafuminaka | 0:371bcac81ea2 | 145 | OriginInt = Lightning.interruptSource(); |
takafuminaka | 0:371bcac81ea2 | 146 | distance = Lightning.lightningDistanceKm(); |
takafuminaka | 0:371bcac81ea2 | 147 | |
takafuminaka | 1:a4119049dd99 | 148 | if (OriginInt == 1) { |
takafuminaka | 1:a4119049dd99 | 149 | led2 = !led2; |
takafuminaka | 1:a4119049dd99 | 150 | DEBUG("%24s : Noise level too high. %d km\r\n",date,distance); |
takafuminaka | 0:371bcac81ea2 | 151 | } |
takafuminaka | 0:371bcac81ea2 | 152 | if (OriginInt == 4) { |
takafuminaka | 1:a4119049dd99 | 153 | led2 = !led2; |
takafuminaka | 1:a4119049dd99 | 154 | DEBUG("%24s : Disturber detected. %d km\r\n",date,distance); |
takafuminaka | 0:371bcac81ea2 | 155 | } |
takafuminaka | 0:371bcac81ea2 | 156 | if (OriginInt == 8) { |
takafuminaka | 1:a4119049dd99 | 157 | led2 = !led2; |
takafuminaka | 1:a4119049dd99 | 158 | DEBUG("%24s : Lightning interrupt %d km\r\n",date,distance); |
takafuminaka | 0:371bcac81ea2 | 159 | } |
takafuminaka | 0:371bcac81ea2 | 160 | } |
takafuminaka | 0:371bcac81ea2 | 161 | |
takafuminaka | 1:a4119049dd99 | 162 | void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) // Mod |
takafuminaka | 1:a4119049dd99 | 163 | { |
takafuminaka | 1:a4119049dd99 | 164 | DEBUG("Disconnected handle %u!\n\r", handle); |
takafuminaka | 1:a4119049dd99 | 165 | DEBUG("Restarting the advertising process\n\r"); |
takafuminaka | 1:a4119049dd99 | 166 | led2 = 0; |
takafuminaka | 1:a4119049dd99 | 167 | ble.gap().startAdvertising(); |
takafuminaka | 1:a4119049dd99 | 168 | } |
takafuminaka | 1:a4119049dd99 | 169 | |
takafuminaka | 1:a4119049dd99 | 170 | void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params) |
takafuminaka | 1:a4119049dd99 | 171 | { |
takafuminaka | 1:a4119049dd99 | 172 | DEBUG("connected. Got handle %u\r\n", params->handle); |
takafuminaka | 1:a4119049dd99 | 173 | |
takafuminaka | 1:a4119049dd99 | 174 | connectionParams.slaveLatency = 1; |
takafuminaka | 1:a4119049dd99 | 175 | led2 = 1; |
takafuminaka | 1:a4119049dd99 | 176 | if (ble.gap().updateConnectionParams(params->handle, &connectionParams) != BLE_ERROR_NONE) { |
takafuminaka | 1:a4119049dd99 | 177 | DEBUG("failed to update connection paramter\r\n"); |
takafuminaka | 1:a4119049dd99 | 178 | } |
takafuminaka | 1:a4119049dd99 | 179 | |
takafuminaka | 1:a4119049dd99 | 180 | } |
takafuminaka | 0:371bcac81ea2 | 181 | |
takafuminaka | 0:371bcac81ea2 | 182 | int main(void) |
takafuminaka | 0:371bcac81ea2 | 183 | { |
takafuminaka | 1:a4119049dd99 | 184 | led1=0; |
takafuminaka | 1:a4119049dd99 | 185 | led2=0; |
takafuminaka | 0:371bcac81ea2 | 186 | int hz=0; |
takafuminaka | 0:371bcac81ea2 | 187 | |
takafuminaka | 0:371bcac81ea2 | 188 | //initialisations |
takafuminaka | 2:e1e638cbf972 | 189 | wait(1); |
takafuminaka | 1:a4119049dd99 | 190 | DEBUG("reset\r\n"); |
takafuminaka | 0:371bcac81ea2 | 191 | Lightning.reset(); |
takafuminaka | 1:a4119049dd99 | 192 | DEBUG("setTuneCap as 5\r\n"); |
takafuminaka | 0:371bcac81ea2 | 193 | Lightning.setTuneCap(5); // Tuning Parameter |
takafuminaka | 1:a4119049dd99 | 194 | DEBUG("powerup\r\n"); |
takafuminaka | 0:371bcac81ea2 | 195 | Lightning.powerUp(); |
takafuminaka | 2:e1e638cbf972 | 196 | |
takafuminaka | 2:e1e638cbf972 | 197 | DEBUG("set Indoor Mode as 0x0d\r\n"); |
takafuminaka | 2:e1e638cbf972 | 198 | Lightning.registerWrite(AS3935_AFE_GB,0x0d); |
takafuminaka | 2:e1e638cbf972 | 199 | |
takafuminaka | 1:a4119049dd99 | 200 | DEBUG("Auto Calibration Start\r\n"); |
takafuminaka | 0:371bcac81ea2 | 201 | float minerr = 100; |
takafuminaka | 0:371bcac81ea2 | 202 | int fincap = 7; |
takafuminaka | 0:371bcac81ea2 | 203 | for(int i=0;i<16;i++) { |
takafuminaka | 0:371bcac81ea2 | 204 | Lightning.setTuneCap(i); // Tuning Parameter |
takafuminaka | 0:371bcac81ea2 | 205 | hz = Lightning.MeasureLCOFreq(); |
takafuminaka | 0:371bcac81ea2 | 206 | float err = (hz-500000.)/500000.*100.; |
takafuminaka | 1:a4119049dd99 | 207 | DEBUG("%d : hz=%10d Hz (%5.2f%%)\r\n",i,hz,err); |
takafuminaka | 0:371bcac81ea2 | 208 | if ( abs(err) < minerr ) { |
takafuminaka | 0:371bcac81ea2 | 209 | minerr = abs(err); |
takafuminaka | 0:371bcac81ea2 | 210 | fincap = i; |
takafuminaka | 0:371bcac81ea2 | 211 | } |
takafuminaka | 0:371bcac81ea2 | 212 | } |
takafuminaka | 0:371bcac81ea2 | 213 | Lightning.setTuneCap(fincap); // Tuning Parameter |
takafuminaka | 0:371bcac81ea2 | 214 | wait_ms(100); |
takafuminaka | 0:371bcac81ea2 | 215 | hz = Lightning.MeasureLCOFreq(); |
takafuminaka | 0:371bcac81ea2 | 216 | float err = (hz-500000.)/500000.*100.; |
takafuminaka | 1:a4119049dd99 | 217 | DEBUG("Final %d : hz=%10d Hz (%5.2f%%)\r\n",fincap,hz,err); |
takafuminaka | 0:371bcac81ea2 | 218 | |
takafuminaka | 1:a4119049dd99 | 219 | DEBUG("Auto Calibration finished\r\n"); |
takafuminaka | 0:371bcac81ea2 | 220 | |
takafuminaka | 0:371bcac81ea2 | 221 | // user selectable, any time < 512 seconds is OK |
takafuminaka | 0:371bcac81ea2 | 222 | #define PERIODIC_UPDATE 1 |
takafuminaka | 0:371bcac81ea2 | 223 | Ticker rtc_ticker; |
takafuminaka | 1:a4119049dd99 | 224 | rtc_ticker.attach(&periodic_update, PERIODIC_UPDATE); |
takafuminaka | 0:371bcac81ea2 | 225 | |
takafuminaka | 0:371bcac81ea2 | 226 | time_t initial_time = example_time(); |
takafuminaka | 0:371bcac81ea2 | 227 | rtc.set_time(initial_time); |
takafuminaka | 0:371bcac81ea2 | 228 | |
takafuminaka | 0:371bcac81ea2 | 229 | button1Press.fall(&print_time); // when button1 is pressed, this calls rtc.time() and prints it |
takafuminaka | 0:371bcac81ea2 | 230 | |
takafuminaka | 0:371bcac81ea2 | 231 | IntLightning.rise(&DetectLightning); |
takafuminaka | 0:371bcac81ea2 | 232 | |
takafuminaka | 1:a4119049dd99 | 233 | ble.init(); |
takafuminaka | 1:a4119049dd99 | 234 | ble.gap().onDisconnection(disconnectionCallback); |
takafuminaka | 1:a4119049dd99 | 235 | ble.gap().onConnection(onConnectionCallback); |
takafuminaka | 1:a4119049dd99 | 236 | |
takafuminaka | 1:a4119049dd99 | 237 | ble.gap().getPreferredConnectionParams(&connectionParams); |
takafuminaka | 1:a4119049dd99 | 238 | |
takafuminaka | 1:a4119049dd99 | 239 | /* setup advertising */ |
takafuminaka | 1:a4119049dd99 | 240 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); |
takafuminaka | 1:a4119049dd99 | 241 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t*)uuid16_list, sizeof(uuid16_list)); |
takafuminaka | 1:a4119049dd99 | 242 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER); |
takafuminaka | 1:a4119049dd99 | 243 | |
takafuminaka | 1:a4119049dd99 | 244 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
takafuminaka | 1:a4119049dd99 | 245 | |
takafuminaka | 1:a4119049dd99 | 246 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
takafuminaka | 1:a4119049dd99 | 247 | ble.gap().setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */ |
takafuminaka | 1:a4119049dd99 | 248 | ble.gap().startAdvertising(); |
takafuminaka | 1:a4119049dd99 | 249 | |
takafuminaka | 1:a4119049dd99 | 250 | ble.gattServer().addService(htmService); |
takafuminaka | 1:a4119049dd99 | 251 | ble.gattServer().addService(battService); |
takafuminaka | 1:a4119049dd99 | 252 | |
takafuminaka | 1:a4119049dd99 | 253 | |
takafuminaka | 0:371bcac81ea2 | 254 | while (true) { |
takafuminaka | 1:a4119049dd99 | 255 | if (triggerSensorPolling) { |
takafuminaka | 1:a4119049dd99 | 256 | triggerSensorPolling = false; |
takafuminaka | 1:a4119049dd99 | 257 | |
takafuminaka | 1:a4119049dd99 | 258 | Update_Values(); |
takafuminaka | 1:a4119049dd99 | 259 | |
takafuminaka | 1:a4119049dd99 | 260 | } else { |
takafuminaka | 1:a4119049dd99 | 261 | ble.waitForEvent(); |
takafuminaka | 1:a4119049dd99 | 262 | } |
takafuminaka | 0:371bcac81ea2 | 263 | } |
takafuminaka | 0:371bcac81ea2 | 264 | } |
takafuminaka | 1:a4119049dd99 | 265 | |
takafuminaka | 1:a4119049dd99 | 266 | void Update_Values() |
takafuminaka | 1:a4119049dd99 | 267 | { |
takafuminaka | 1:a4119049dd99 | 268 | /* Update the temperature. Note that we need to convert to an ieee11073 format float. */ |
takafuminaka | 1:a4119049dd99 | 269 | |
takafuminaka | 1:a4119049dd99 | 270 | int32_t p_temp; |
takafuminaka | 1:a4119049dd99 | 271 | sd_temp_get(&p_temp); |
takafuminaka | 1:a4119049dd99 | 272 | float temperature = float(p_temp)/4.; |
takafuminaka | 1:a4119049dd99 | 273 | temperature -= 14.; // It should be changed device by device. |
takafuminaka | 1:a4119049dd99 | 274 | |
takafuminaka | 1:a4119049dd99 | 275 | // DEBUG("temp:%f\n\r", temperature); |
takafuminaka | 1:a4119049dd99 | 276 | uint32_t temp_ieee11073 = quick_ieee11073_from_float(temperature); |
takafuminaka | 1:a4119049dd99 | 277 | memcpy(thermTempPayload+1, &temp_ieee11073, 4); |
takafuminaka | 1:a4119049dd99 | 278 | |
takafuminaka | 1:a4119049dd99 | 279 | /* Battery Service Update */ |
takafuminaka | 1:a4119049dd99 | 280 | /* Update battery level */ |
takafuminaka | 1:a4119049dd99 | 281 | //ble.getGattServer().updateValue(battLevel.handle, (uint8_t*)&batt, sizeof(batt)); |
takafuminaka | 1:a4119049dd99 | 282 | /* Decrement the battery level. */ |
takafuminaka | 1:a4119049dd99 | 283 | batt <=50 ? batt=100 : batt--;; |
takafuminaka | 1:a4119049dd99 | 284 | bpm2[0] = batt; |
takafuminaka | 1:a4119049dd99 | 285 | |
takafuminaka | 1:a4119049dd99 | 286 | if (ble.gap().getState().connected ) { |
takafuminaka | 1:a4119049dd99 | 287 | ble.gattServer().write(tempChar.getValueAttribute().getHandle(), thermTempPayload, sizeof(thermTempPayload)); |
takafuminaka | 1:a4119049dd99 | 288 | ble.gattServer().write(battLevel.getValueAttribute().getHandle(), (uint8_t *)&batt, sizeof(batt)); |
takafuminaka | 1:a4119049dd99 | 289 | } |
takafuminaka | 1:a4119049dd99 | 290 | } |
takafuminaka | 1:a4119049dd99 | 291 | |
takafuminaka | 1:a4119049dd99 | 292 | /** |
takafuminaka | 1:a4119049dd99 | 293 | * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type. |
takafuminaka | 1:a4119049dd99 | 294 | * @param temperature The temperature as a float. |
takafuminaka | 1:a4119049dd99 | 295 | * @return The temperature in 11073-20601 FLOAT-Type format. |
takafuminaka | 1:a4119049dd99 | 296 | */ |
takafuminaka | 1:a4119049dd99 | 297 | uint32_t quick_ieee11073_from_float(float temperature) |
takafuminaka | 1:a4119049dd99 | 298 | { |
takafuminaka | 1:a4119049dd99 | 299 | uint8_t exponent = 0xFE; //exponent is -2 |
takafuminaka | 1:a4119049dd99 | 300 | uint32_t mantissa = (uint32_t)(temperature*100); |
takafuminaka | 1:a4119049dd99 | 301 | |
takafuminaka | 1:a4119049dd99 | 302 | return ( ((uint32_t)exponent) << 24) | mantissa; |
takafuminaka | 1:a4119049dd99 | 303 | } |