Run a K30 CO2 sensor on a Nordic nRF52DK Board

Fork of mbed-os-example-ble-BatteryLevel by mbed-os-examples

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?

UserRevisionLine numberNew 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 }