Run a K30 CO2 sensor on a Nordic nRF52DK Board

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

Revision:
61:a5d14d0a94a1
Parent:
46:6b66d08f304e
Child:
62:e947447e0d8c
--- a/source/main.cpp	Wed Apr 04 17:15:08 2018 +0100
+++ b/source/main.cpp	Tue May 01 17:45:11 2018 +0000
@@ -18,39 +18,122 @@
 #include <mbed.h>
 #include "ble/BLE.h"
 #include "ble/Gap.h"
-#include "ble/services/BatteryService.h"
+#include "k30.h"
+#include "nrf_nvic.h"
 
-DigitalOut led1(LED1, 1);
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+//I2C i2c(p24 , p25);
+I2C i2c(p26, p27);
+ /** If you want to debug, or see output, uncomment this **/
+//Serial pc(USBTX, USBRX); // tx, rx
 
-const static char     DEVICE_NAME[] = "BATTERY";
-static const uint16_t uuid16_list[] = {GattService::UUID_BATTERY_SERVICE};
+/* 7-bit address of the K30 CO2 Sensor */ 
+const int addr = 0xD0;
+
+/* keep track of the number of sensor failures */
+static int failures = 0;
 
-static uint8_t batteryLevel = 50;
-static BatteryService* batteryServicePtr;
+/** Device name, and the Serice UUID **/
+const static char     DEVICE_NAME[] = "CO2Sensor";
+static const uint16_t uuid16_list[] = {K30Service::K30_SERVICE_UUID};
 
+/** random initial level and a Service pointer **/
+static float co2Level = 50.0;
+static K30Service* k30ServicePtr;
+
+/** Event Queue **/
 static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE);
 
+/** light pattern in a circle **/
+void lightsFwd(){
+    led1 = !led1;
+    wait(.15);
+    led2 = !led2;
+    wait(.15);
+    led4 = !led4;
+    wait(.15);
+    led3 = !led3;
+    wait(.15);
+}
+/** reverser light pattern **/
+void lightsRev(){
+    led1 = !led1;
+    wait(.15);
+    led3 = !led3;
+    wait(.15);
+    led4 = !led4;
+    wait(.15);
+    led2 = !led2;
+    wait(.15);
+}
+
+/** here we read the sensor **/
+void readSensor(){
+ 
+    // register values
+    char cmd[4] =  {0x22, 0x00, 0x08, 0x2A};
+    int ack = i2c.write(addr, cmd, 4);
+    wait(0.5);
+    char readBuff[4];
+    i2c.read(addr, readBuff, 4, false);
+    int high = readBuff[1];                        //high byte for value is 4th byte in packet in the packet
+    int low = readBuff[2];                         //low byte for value is 5th byte in the packet
+    float CO2 = high*256 + low;                //Combine high byte and low byte with this formula to get value        
+    char sum = readBuff[0] + readBuff[1] + readBuff[2]; //Byte addition utilizes overflow   
+    if (sum == readBuff[3] & ack == 0){
+        //pc.printf("CO2 value = %f\n", CO2);
+        k30ServicePtr->updateK30Value(CO2);
+        if(failures > 0){
+            failures--;
+        }           
+        } else {
+            //pc.printf("** Sensor Failure **\n");
+            failures++;
+            CO2 = -1;
+            k30ServicePtr->updateK30Value(CO2);
+            if(failures > 5){ // Keep track of the number of failures. If more than 5, reboot the board. 
+                i2c.stop();
+                for(int x = 0; x < 10; x++){
+                    lightsRev();
+                }
+                NVIC_SystemReset();
+            }
+            
+        }
+}
 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
 {
+    //pc.printf("Disconnected!\n");
     BLE::Instance().gap().startAdvertising();
 }
 
+
+
 void updateSensorValue() {
-    batteryLevel++;
-    if (batteryLevel > 100) {
-        batteryLevel = 20;
-    }
+    lightsFwd();
+    readSensor();
+    wait(1.5);
+    lightsFwd();
+    wait(1.5
 
-    batteryServicePtr->updateBatteryLevel(batteryLevel);
+   // k30ServicePtr->updateK30Value(co2Level);
 }
-
+void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
+{
+    // pc.printf("Connected!\n");
+    BLE::Instance().gap().stopAdvertising();
+    eventQueue.call(updateSensorValue);
+}
 void blinkCallback(void)
 {
-    led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
-
     BLE &ble = BLE::Instance();
     if (ble.gap().getState().connected) {
         eventQueue.call(updateSensorValue);
+    } else {
+        lightsFwd();
     }
 }
 
@@ -68,11 +151,11 @@
     Gap::AddressType_t addr_type;
     Gap::Address_t address;
     BLE::Instance().gap().getAddress(&addr_type, address);
-    printf("DEVICE MAC ADDRESS: ");
+    //pc.printf("DEVICE MAC ADDRESS: ");
     for (int i = 5; i >= 1; i--){
-        printf("%02x:", address[i]);
+       // printf("%02x:", address[i]);
     }
-    printf("%02x\r\n", address[0]);
+    //pc.printf("%02x\r\n", address[0]);
 }
 
 /**
@@ -95,9 +178,10 @@
     }
 
     ble.gap().onDisconnection(disconnectionCallback);
+    ble.gap().onConnection(connectionCallback);
 
     /* Setup primary service */
-    batteryServicePtr = new BatteryService(ble, batteryLevel);
+    k30ServicePtr = new K30Service(ble, co2Level);
 
     /* Setup advertising */
     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
@@ -107,7 +191,7 @@
     ble.gap().setAdvertisingInterval(1000); /* 1000ms */
     ble.gap().startAdvertising();
 
-    printMacAddress();
+   //printMacAddress();
 }
 
 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
@@ -117,13 +201,10 @@
 
 int main()
 {
-    eventQueue.call_every(500, blinkCallback);
-
+    eventQueue.call_every(1000, blinkCallback);
     BLE &ble = BLE::Instance();
     ble.onEventsToProcess(scheduleBleEventsProcessing);
     ble.init(bleInitComplete);
-
     eventQueue.dispatch_forever();
-
     return 0;
 }