Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-os-example-ble-BatteryLevel by
source/main.cpp@63:8ec90c81ff7d, 2018-05-02 (annotated)
- Committer:
- davidgsIoT
- Date:
- Wed May 02 12:14:43 2018 +0000
- Revision:
- 63:8ec90c81ff7d
- Parent:
- 62:e947447e0d8c
Updated Readme
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| mbed_official | 4:52bffaff7f0b | 1 | /* mbed Microcontroller Library |
| davidgsIoT | 62:e947447e0d8c | 2 | * Copyright (c) 2018 David G. Simmons |
| mbed_official | 4:52bffaff7f0b | 3 | * |
| mbed_official | 4:52bffaff7f0b | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| mbed_official | 4:52bffaff7f0b | 5 | * you may not use this file except in compliance with the License. |
| mbed_official | 4:52bffaff7f0b | 6 | * You may obtain a copy of the License at |
| mbed_official | 4:52bffaff7f0b | 7 | * |
| mbed_official | 4:52bffaff7f0b | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| mbed_official | 4:52bffaff7f0b | 9 | * |
| mbed_official | 4:52bffaff7f0b | 10 | * Unless required by applicable law or agreed to in writing, software |
| mbed_official | 4:52bffaff7f0b | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| mbed_official | 4:52bffaff7f0b | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| mbed_official | 4:52bffaff7f0b | 13 | * See the License for the specific language governing permissions and |
| mbed_official | 4:52bffaff7f0b | 14 | * limitations under the License. |
| mbed_official | 4:52bffaff7f0b | 15 | */ |
| mbed_official | 4:52bffaff7f0b | 16 | |
| mbed_official | 13:eaa1343657a8 | 17 | #include <events/mbed_events.h> |
| mbed_official | 4:52bffaff7f0b | 18 | #include <mbed.h> |
| mbed_official | 4:52bffaff7f0b | 19 | #include "ble/BLE.h" |
| mbed_official | 4:52bffaff7f0b | 20 | #include "ble/Gap.h" |
| davidgsIoT | 61:a5d14d0a94a1 | 21 | #include "k30.h" |
| davidgsIoT | 61:a5d14d0a94a1 | 22 | #include "nrf_nvic.h" |
| mbed_official | 4:52bffaff7f0b | 23 | |
| davidgsIoT | 61:a5d14d0a94a1 | 24 | DigitalOut led1(LED1); |
| davidgsIoT | 61:a5d14d0a94a1 | 25 | DigitalOut led2(LED2); |
| davidgsIoT | 61:a5d14d0a94a1 | 26 | DigitalOut led3(LED3); |
| davidgsIoT | 61:a5d14d0a94a1 | 27 | DigitalOut led4(LED4); |
| davidgsIoT | 61:a5d14d0a94a1 | 28 | //I2C i2c(p24 , p25); |
| davidgsIoT | 62:e947447e0d8c | 29 | // Standard I2C pins on the nRF52. But you can use any pins you want really. |
| davidgsIoT | 61:a5d14d0a94a1 | 30 | I2C i2c(p26, p27); |
| davidgsIoT | 61:a5d14d0a94a1 | 31 | /** If you want to debug, or see output, uncomment this **/ |
| davidgsIoT | 61:a5d14d0a94a1 | 32 | //Serial pc(USBTX, USBRX); // tx, rx |
| mbed_official | 4:52bffaff7f0b | 33 | |
| davidgsIoT | 61:a5d14d0a94a1 | 34 | /* 7-bit address of the K30 CO2 Sensor */ |
| davidgsIoT | 61:a5d14d0a94a1 | 35 | const int addr = 0xD0; |
| davidgsIoT | 61:a5d14d0a94a1 | 36 | |
| davidgsIoT | 61:a5d14d0a94a1 | 37 | /* keep track of the number of sensor failures */ |
| davidgsIoT | 61:a5d14d0a94a1 | 38 | static int failures = 0; |
| mbed_official | 4:52bffaff7f0b | 39 | |
| davidgsIoT | 61:a5d14d0a94a1 | 40 | /** Device name, and the Serice UUID **/ |
| davidgsIoT | 61:a5d14d0a94a1 | 41 | const static char DEVICE_NAME[] = "CO2Sensor"; |
| davidgsIoT | 61:a5d14d0a94a1 | 42 | static const uint16_t uuid16_list[] = {K30Service::K30_SERVICE_UUID}; |
| mbed_official | 4:52bffaff7f0b | 43 | |
| davidgsIoT | 61:a5d14d0a94a1 | 44 | /** random initial level and a Service pointer **/ |
| davidgsIoT | 61:a5d14d0a94a1 | 45 | static float co2Level = 50.0; |
| davidgsIoT | 61:a5d14d0a94a1 | 46 | static K30Service* k30ServicePtr; |
| davidgsIoT | 61:a5d14d0a94a1 | 47 | |
| davidgsIoT | 61:a5d14d0a94a1 | 48 | /** Event Queue **/ |
| mbed_official | 29:7a6aff8c9468 | 49 | static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE); |
| mbed_official | 4:52bffaff7f0b | 50 | |
| davidgsIoT | 61:a5d14d0a94a1 | 51 | /** light pattern in a circle **/ |
| davidgsIoT | 61:a5d14d0a94a1 | 52 | void lightsFwd(){ |
| davidgsIoT | 61:a5d14d0a94a1 | 53 | led1 = !led1; |
| davidgsIoT | 61:a5d14d0a94a1 | 54 | wait(.15); |
| davidgsIoT | 61:a5d14d0a94a1 | 55 | led2 = !led2; |
| davidgsIoT | 61:a5d14d0a94a1 | 56 | wait(.15); |
| davidgsIoT | 61:a5d14d0a94a1 | 57 | led4 = !led4; |
| davidgsIoT | 61:a5d14d0a94a1 | 58 | wait(.15); |
| davidgsIoT | 61:a5d14d0a94a1 | 59 | led3 = !led3; |
| davidgsIoT | 61:a5d14d0a94a1 | 60 | wait(.15); |
| davidgsIoT | 61:a5d14d0a94a1 | 61 | } |
| davidgsIoT | 61:a5d14d0a94a1 | 62 | /** reverser light pattern **/ |
| davidgsIoT | 61:a5d14d0a94a1 | 63 | void lightsRev(){ |
| davidgsIoT | 61:a5d14d0a94a1 | 64 | led1 = !led1; |
| davidgsIoT | 61:a5d14d0a94a1 | 65 | wait(.15); |
| davidgsIoT | 61:a5d14d0a94a1 | 66 | led3 = !led3; |
| davidgsIoT | 61:a5d14d0a94a1 | 67 | wait(.15); |
| davidgsIoT | 61:a5d14d0a94a1 | 68 | led4 = !led4; |
| davidgsIoT | 61:a5d14d0a94a1 | 69 | wait(.15); |
| davidgsIoT | 61:a5d14d0a94a1 | 70 | led2 = !led2; |
| davidgsIoT | 61:a5d14d0a94a1 | 71 | wait(.15); |
| davidgsIoT | 61:a5d14d0a94a1 | 72 | } |
| davidgsIoT | 61:a5d14d0a94a1 | 73 | |
| davidgsIoT | 61:a5d14d0a94a1 | 74 | /** here we read the sensor **/ |
| davidgsIoT | 61:a5d14d0a94a1 | 75 | void readSensor(){ |
| davidgsIoT | 61:a5d14d0a94a1 | 76 | |
| davidgsIoT | 61:a5d14d0a94a1 | 77 | // register values |
| davidgsIoT | 61:a5d14d0a94a1 | 78 | char cmd[4] = {0x22, 0x00, 0x08, 0x2A}; |
| davidgsIoT | 61:a5d14d0a94a1 | 79 | int ack = i2c.write(addr, cmd, 4); |
| davidgsIoT | 61:a5d14d0a94a1 | 80 | wait(0.5); |
| davidgsIoT | 61:a5d14d0a94a1 | 81 | char readBuff[4]; |
| davidgsIoT | 61:a5d14d0a94a1 | 82 | i2c.read(addr, readBuff, 4, false); |
| davidgsIoT | 61:a5d14d0a94a1 | 83 | int high = readBuff[1]; //high byte for value is 4th byte in packet in the packet |
| davidgsIoT | 61:a5d14d0a94a1 | 84 | int low = readBuff[2]; //low byte for value is 5th byte in the packet |
| davidgsIoT | 61:a5d14d0a94a1 | 85 | float CO2 = high*256 + low; //Combine high byte and low byte with this formula to get value |
| davidgsIoT | 61:a5d14d0a94a1 | 86 | char sum = readBuff[0] + readBuff[1] + readBuff[2]; //Byte addition utilizes overflow |
| davidgsIoT | 61:a5d14d0a94a1 | 87 | if (sum == readBuff[3] & ack == 0){ |
| davidgsIoT | 61:a5d14d0a94a1 | 88 | //pc.printf("CO2 value = %f\n", CO2); |
| davidgsIoT | 61:a5d14d0a94a1 | 89 | k30ServicePtr->updateK30Value(CO2); |
| davidgsIoT | 61:a5d14d0a94a1 | 90 | if(failures > 0){ |
| davidgsIoT | 61:a5d14d0a94a1 | 91 | failures--; |
| davidgsIoT | 61:a5d14d0a94a1 | 92 | } |
| davidgsIoT | 61:a5d14d0a94a1 | 93 | } else { |
| davidgsIoT | 61:a5d14d0a94a1 | 94 | //pc.printf("** Sensor Failure **\n"); |
| davidgsIoT | 61:a5d14d0a94a1 | 95 | failures++; |
| davidgsIoT | 61:a5d14d0a94a1 | 96 | CO2 = -1; |
| davidgsIoT | 61:a5d14d0a94a1 | 97 | k30ServicePtr->updateK30Value(CO2); |
| davidgsIoT | 61:a5d14d0a94a1 | 98 | if(failures > 5){ // Keep track of the number of failures. If more than 5, reboot the board. |
| davidgsIoT | 61:a5d14d0a94a1 | 99 | i2c.stop(); |
| davidgsIoT | 61:a5d14d0a94a1 | 100 | for(int x = 0; x < 10; x++){ |
| davidgsIoT | 61:a5d14d0a94a1 | 101 | lightsRev(); |
| davidgsIoT | 61:a5d14d0a94a1 | 102 | } |
| davidgsIoT | 61:a5d14d0a94a1 | 103 | NVIC_SystemReset(); |
| davidgsIoT | 61:a5d14d0a94a1 | 104 | } |
| davidgsIoT | 61:a5d14d0a94a1 | 105 | |
| davidgsIoT | 61:a5d14d0a94a1 | 106 | } |
| davidgsIoT | 61:a5d14d0a94a1 | 107 | } |
| mbed_official | 4:52bffaff7f0b | 108 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
| mbed_official | 4:52bffaff7f0b | 109 | { |
| davidgsIoT | 61:a5d14d0a94a1 | 110 | //pc.printf("Disconnected!\n"); |
| mbed_official | 4:52bffaff7f0b | 111 | BLE::Instance().gap().startAdvertising(); |
| mbed_official | 4:52bffaff7f0b | 112 | } |
| mbed_official | 4:52bffaff7f0b | 113 | |
| davidgsIoT | 61:a5d14d0a94a1 | 114 | |
| davidgsIoT | 61:a5d14d0a94a1 | 115 | |
| mbed_official | 4:52bffaff7f0b | 116 | void updateSensorValue() { |
| davidgsIoT | 61:a5d14d0a94a1 | 117 | lightsFwd(); |
| davidgsIoT | 61:a5d14d0a94a1 | 118 | readSensor(); |
| davidgsIoT | 61:a5d14d0a94a1 | 119 | wait(1.5); |
| davidgsIoT | 61:a5d14d0a94a1 | 120 | lightsFwd(); |
| davidgsIoT | 61:a5d14d0a94a1 | 121 | wait(1.5 |
| mbed_official | 4:52bffaff7f0b | 122 | |
| davidgsIoT | 61:a5d14d0a94a1 | 123 | // k30ServicePtr->updateK30Value(co2Level); |
| mbed_official | 4:52bffaff7f0b | 124 | } |
| davidgsIoT | 61:a5d14d0a94a1 | 125 | void connectionCallback(const Gap::ConnectionCallbackParams_t *params) |
| davidgsIoT | 61:a5d14d0a94a1 | 126 | { |
| davidgsIoT | 61:a5d14d0a94a1 | 127 | // pc.printf("Connected!\n"); |
| davidgsIoT | 61:a5d14d0a94a1 | 128 | BLE::Instance().gap().stopAdvertising(); |
| davidgsIoT | 61:a5d14d0a94a1 | 129 | eventQueue.call(updateSensorValue); |
| davidgsIoT | 61:a5d14d0a94a1 | 130 | } |
| mbed_official | 4:52bffaff7f0b | 131 | void blinkCallback(void) |
| mbed_official | 4:52bffaff7f0b | 132 | { |
| mbed_official | 4:52bffaff7f0b | 133 | BLE &ble = BLE::Instance(); |
| mbed_official | 4:52bffaff7f0b | 134 | if (ble.gap().getState().connected) { |
| mbed_official | 13:eaa1343657a8 | 135 | eventQueue.call(updateSensorValue); |
| davidgsIoT | 61:a5d14d0a94a1 | 136 | } else { |
| davidgsIoT | 61:a5d14d0a94a1 | 137 | lightsFwd(); |
| mbed_official | 4:52bffaff7f0b | 138 | } |
| mbed_official | 4:52bffaff7f0b | 139 | } |
| mbed_official | 4:52bffaff7f0b | 140 | |
| mbed_official | 4:52bffaff7f0b | 141 | /** |
| mbed_official | 4:52bffaff7f0b | 142 | * This function is called when the ble initialization process has failled |
| mbed_official | 4:52bffaff7f0b | 143 | */ |
| mbed_official | 4:52bffaff7f0b | 144 | void onBleInitError(BLE &ble, ble_error_t error) |
| mbed_official | 4:52bffaff7f0b | 145 | { |
| mbed_official | 4:52bffaff7f0b | 146 | /* Initialization error handling should go here */ |
| mbed_official | 4:52bffaff7f0b | 147 | } |
| mbed_official | 4:52bffaff7f0b | 148 | |
| mbed_official | 46:6b66d08f304e | 149 | void printMacAddress() |
| mbed_official | 46:6b66d08f304e | 150 | { |
| mbed_official | 46:6b66d08f304e | 151 | /* Print out device MAC address to the console*/ |
| mbed_official | 46:6b66d08f304e | 152 | Gap::AddressType_t addr_type; |
| mbed_official | 46:6b66d08f304e | 153 | Gap::Address_t address; |
| mbed_official | 46:6b66d08f304e | 154 | BLE::Instance().gap().getAddress(&addr_type, address); |
| davidgsIoT | 61:a5d14d0a94a1 | 155 | //pc.printf("DEVICE MAC ADDRESS: "); |
| mbed_official | 46:6b66d08f304e | 156 | for (int i = 5; i >= 1; i--){ |
| davidgsIoT | 61:a5d14d0a94a1 | 157 | // printf("%02x:", address[i]); |
| mbed_official | 46:6b66d08f304e | 158 | } |
| davidgsIoT | 61:a5d14d0a94a1 | 159 | //pc.printf("%02x\r\n", address[0]); |
| mbed_official | 46:6b66d08f304e | 160 | } |
| mbed_official | 46:6b66d08f304e | 161 | |
| mbed_official | 4:52bffaff7f0b | 162 | /** |
| mbed_official | 4:52bffaff7f0b | 163 | * Callback triggered when the ble initialization process has finished |
| mbed_official | 4:52bffaff7f0b | 164 | */ |
| mbed_official | 4:52bffaff7f0b | 165 | void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) |
| mbed_official | 4:52bffaff7f0b | 166 | { |
| mbed_official | 4:52bffaff7f0b | 167 | BLE& ble = params->ble; |
| mbed_official | 4:52bffaff7f0b | 168 | ble_error_t error = params->error; |
| mbed_official | 4:52bffaff7f0b | 169 | |
| mbed_official | 4:52bffaff7f0b | 170 | if (error != BLE_ERROR_NONE) { |
| mbed_official | 4:52bffaff7f0b | 171 | /* In case of error, forward the error handling to onBleInitError */ |
| mbed_official | 4:52bffaff7f0b | 172 | onBleInitError(ble, error); |
| mbed_official | 4:52bffaff7f0b | 173 | return; |
| mbed_official | 4:52bffaff7f0b | 174 | } |
| mbed_official | 4:52bffaff7f0b | 175 | |
| mbed_official | 4:52bffaff7f0b | 176 | /* Ensure that it is the default instance of BLE */ |
| mbed_official | 4:52bffaff7f0b | 177 | if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { |
| mbed_official | 4:52bffaff7f0b | 178 | return; |
| mbed_official | 4:52bffaff7f0b | 179 | } |
| mbed_official | 4:52bffaff7f0b | 180 | |
| mbed_official | 4:52bffaff7f0b | 181 | ble.gap().onDisconnection(disconnectionCallback); |
| davidgsIoT | 61:a5d14d0a94a1 | 182 | ble.gap().onConnection(connectionCallback); |
| mbed_official | 4:52bffaff7f0b | 183 | |
| mbed_official | 4:52bffaff7f0b | 184 | /* Setup primary service */ |
| davidgsIoT | 61:a5d14d0a94a1 | 185 | k30ServicePtr = new K30Service(ble, co2Level); |
| mbed_official | 4:52bffaff7f0b | 186 | |
| mbed_official | 4:52bffaff7f0b | 187 | /* Setup advertising */ |
| mbed_official | 4:52bffaff7f0b | 188 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); |
| mbed_official | 4:52bffaff7f0b | 189 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *) uuid16_list, sizeof(uuid16_list)); |
| mbed_official | 4:52bffaff7f0b | 190 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *) DEVICE_NAME, sizeof(DEVICE_NAME)); |
| mbed_official | 4:52bffaff7f0b | 191 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
| mbed_official | 4:52bffaff7f0b | 192 | ble.gap().setAdvertisingInterval(1000); /* 1000ms */ |
| mbed_official | 4:52bffaff7f0b | 193 | ble.gap().startAdvertising(); |
| mbed_official | 46:6b66d08f304e | 194 | |
| davidgsIoT | 61:a5d14d0a94a1 | 195 | //printMacAddress(); |
| mbed_official | 4:52bffaff7f0b | 196 | } |
| mbed_official | 4:52bffaff7f0b | 197 | |
| mbed_official | 4:52bffaff7f0b | 198 | void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) { |
| mbed_official | 4:52bffaff7f0b | 199 | BLE &ble = BLE::Instance(); |
| mbed_official | 13:eaa1343657a8 | 200 | eventQueue.call(Callback<void()>(&ble, &BLE::processEvents)); |
| mbed_official | 4:52bffaff7f0b | 201 | } |
| mbed_official | 4:52bffaff7f0b | 202 | |
| mbed_official | 4:52bffaff7f0b | 203 | int main() |
| mbed_official | 4:52bffaff7f0b | 204 | { |
| davidgsIoT | 61:a5d14d0a94a1 | 205 | eventQueue.call_every(1000, blinkCallback); |
| mbed_official | 4:52bffaff7f0b | 206 | BLE &ble = BLE::Instance(); |
| mbed_official | 4:52bffaff7f0b | 207 | ble.onEventsToProcess(scheduleBleEventsProcessing); |
| mbed_official | 4:52bffaff7f0b | 208 | ble.init(bleInitComplete); |
| mbed_official | 13:eaa1343657a8 | 209 | eventQueue.dispatch_forever(); |
| mbed_official | 4:52bffaff7f0b | 210 | return 0; |
| mbed_official | 4:52bffaff7f0b | 211 | } |
