Run a K30 CO2 sensor on a Nordic nRF52DK Board

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }