Run a K30 CO2 sensor on a Nordic nRF52DK Board
Fork of mbed-os-example-ble-BatteryLevel by
main.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2018 David G. Simmons 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 <events/mbed_events.h> 00018 #include <mbed.h> 00019 #include "ble/BLE.h" 00020 #include "ble/Gap.h" 00021 #include "k30.h" 00022 #include "nrf_nvic.h" 00023 00024 DigitalOut led1(LED1); 00025 DigitalOut led2(LED2); 00026 DigitalOut led3(LED3); 00027 DigitalOut led4(LED4); 00028 //I2C i2c(p24 , p25); 00029 // Standard I2C pins on the nRF52. But you can use any pins you want really. 00030 I2C i2c(p26, p27); 00031 /** If you want to debug, or see output, uncomment this **/ 00032 //Serial pc(USBTX, USBRX); // tx, rx 00033 00034 /* 7-bit address of the K30 CO2 Sensor */ 00035 const int addr = 0xD0; 00036 00037 /* keep track of the number of sensor failures */ 00038 static int failures = 0; 00039 00040 /** Device name, and the Serice UUID **/ 00041 const static char DEVICE_NAME[] = "CO2Sensor"; 00042 static const uint16_t uuid16_list[] = {K30Service::K30_SERVICE_UUID}; 00043 00044 /** random initial level and a Service pointer **/ 00045 static float co2Level = 50.0; 00046 static K30Service* k30ServicePtr; 00047 00048 /** Event Queue **/ 00049 static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE); 00050 00051 /** light pattern in a circle **/ 00052 void lightsFwd(){ 00053 led1 = !led1; 00054 wait(.15); 00055 led2 = !led2; 00056 wait(.15); 00057 led4 = !led4; 00058 wait(.15); 00059 led3 = !led3; 00060 wait(.15); 00061 } 00062 /** reverser light pattern **/ 00063 void lightsRev(){ 00064 led1 = !led1; 00065 wait(.15); 00066 led3 = !led3; 00067 wait(.15); 00068 led4 = !led4; 00069 wait(.15); 00070 led2 = !led2; 00071 wait(.15); 00072 } 00073 00074 /** here we read the sensor **/ 00075 void readSensor(){ 00076 00077 // register values 00078 char cmd[4] = {0x22, 0x00, 0x08, 0x2A}; 00079 int ack = i2c.write(addr, cmd, 4); 00080 wait(0.5); 00081 char readBuff[4]; 00082 i2c.read(addr, readBuff, 4, false); 00083 int high = readBuff[1]; //high byte for value is 4th byte in packet in the packet 00084 int low = readBuff[2]; //low byte for value is 5th byte in the packet 00085 float CO2 = high*256 + low; //Combine high byte and low byte with this formula to get value 00086 char sum = readBuff[0] + readBuff[1] + readBuff[2]; //Byte addition utilizes overflow 00087 if (sum == readBuff[3] & ack == 0){ 00088 //pc.printf("CO2 value = %f\n", CO2); 00089 k30ServicePtr->updateK30Value(CO2); 00090 if(failures > 0){ 00091 failures--; 00092 } 00093 } else { 00094 //pc.printf("** Sensor Failure **\n"); 00095 failures++; 00096 CO2 = -1; 00097 k30ServicePtr->updateK30Value(CO2); 00098 if(failures > 5){ // Keep track of the number of failures. If more than 5, reboot the board. 00099 i2c.stop(); 00100 for(int x = 0; x < 10; x++){ 00101 lightsRev(); 00102 } 00103 NVIC_SystemReset(); 00104 } 00105 00106 } 00107 } 00108 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) 00109 { 00110 //pc.printf("Disconnected!\n"); 00111 BLE::Instance().gap().startAdvertising(); 00112 } 00113 00114 00115 00116 void updateSensorValue() { 00117 lightsFwd(); 00118 readSensor(); 00119 wait(1.5); 00120 lightsFwd(); 00121 wait(1.5 00122 00123 // k30ServicePtr->updateK30Value(co2Level); 00124 } 00125 void connectionCallback(const Gap::ConnectionCallbackParams_t *params) 00126 { 00127 // pc.printf("Connected!\n"); 00128 BLE::Instance().gap().stopAdvertising(); 00129 eventQueue.call(updateSensorValue); 00130 } 00131 void blinkCallback(void) 00132 { 00133 BLE &ble = BLE::Instance(); 00134 if (ble.gap().getState().connected) { 00135 eventQueue.call(updateSensorValue); 00136 } else { 00137 lightsFwd(); 00138 } 00139 } 00140 00141 /** 00142 * This function is called when the ble initialization process has failled 00143 */ 00144 void onBleInitError(BLE &ble, ble_error_t error) 00145 { 00146 /* Initialization error handling should go here */ 00147 } 00148 00149 void printMacAddress() 00150 { 00151 /* Print out device MAC address to the console*/ 00152 Gap::AddressType_t addr_type; 00153 Gap::Address_t address; 00154 BLE::Instance().gap().getAddress(&addr_type, address); 00155 //pc.printf("DEVICE MAC ADDRESS: "); 00156 for (int i = 5; i >= 1; i--){ 00157 // printf("%02x:", address[i]); 00158 } 00159 //pc.printf("%02x\r\n", address[0]); 00160 } 00161 00162 /** 00163 * Callback triggered when the ble initialization process has finished 00164 */ 00165 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) 00166 { 00167 BLE& ble = params->ble; 00168 ble_error_t error = params->error; 00169 00170 if (error != BLE_ERROR_NONE) { 00171 /* In case of error, forward the error handling to onBleInitError */ 00172 onBleInitError(ble, error); 00173 return; 00174 } 00175 00176 /* Ensure that it is the default instance of BLE */ 00177 if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { 00178 return; 00179 } 00180 00181 ble.gap().onDisconnection(disconnectionCallback); 00182 ble.gap().onConnection(connectionCallback); 00183 00184 /* Setup primary service */ 00185 k30ServicePtr = new K30Service(ble, co2Level); 00186 00187 /* Setup advertising */ 00188 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); 00189 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *) uuid16_list, sizeof(uuid16_list)); 00190 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *) DEVICE_NAME, sizeof(DEVICE_NAME)); 00191 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); 00192 ble.gap().setAdvertisingInterval(1000); /* 1000ms */ 00193 ble.gap().startAdvertising(); 00194 00195 //printMacAddress(); 00196 } 00197 00198 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) { 00199 BLE &ble = BLE::Instance(); 00200 eventQueue.call(Callback<void()>(&ble, &BLE::processEvents)); 00201 } 00202 00203 int main() 00204 { 00205 eventQueue.call_every(1000, blinkCallback); 00206 BLE &ble = BLE::Instance(); 00207 ble.onEventsToProcess(scheduleBleEventsProcessing); 00208 ble.init(bleInitComplete); 00209 eventQueue.dispatch_forever(); 00210 return 0; 00211 }
Generated on Thu Jul 14 2022 19:33:10 by 1.7.2