ModoSmart / Mbed 2 deprecated WindowSensorModule

Dependencies:   BLE_API mbed nRF51822

Fork of SensorModulePIR by ModoSmart

Revision:
3:53db6c57bb61
Parent:
1:839f9cac1eca
Child:
4:de22f0d73c12
diff -r 839f9cac1eca -r 53db6c57bb61 main.cpp
--- a/main.cpp	Tue Nov 22 18:19:08 2016 +0000
+++ b/main.cpp	Thu May 04 09:58:43 2017 +0000
@@ -1,48 +1,162 @@
 #include "mbed.h"
-//#include "HDC1000.h"
+#include "defineGPIOs.h"
 #include "BLE.h"
-#include "HealthThermometerService.h"
-//#include "SetTemperatureService.h"
-//#include "SetModeService.h"
-//#include "UARTService.h"
+//#include "HealthThermometerService.h"
+#include "ble/services/HealthThermometerService.h"  // added
 #include "PresenceDetectionService.h"
-#include "TemperatureMeasureService.h"
-
+//#include "TemperatureMeasureService.h"
+#include "HumidityMeasureService.h"
 #include "ble_gatt.h"
 #include "Si7020.h"
+#include "UARTService.h"
+#include <string.h>
 
-Serial pc(p22, p23);
-//Serial pc(USBTX, USBRX); 
-//I2C i2c(PIN_SDA,PIN_SCL);
-I2C i2c(p12, p13);
+
+// OFFSET TEMPERATURE CONFIGURATIONS:
+#define STANDARD -1  // Squared radar sensor module: -1ºC
+#define ZERO 0  // no offset
+#define OFFSET STANDARD
+
+#define NEED_SERIAL_CONSOLE_OUTPUT 0
+#if NEED_SERIAL_CONSOLE_OUTPUT
+Serial pc(PIN_TX, PIN_RX);
+#define SERIAL_DEBUG(...) { printf(__VA_ARGS__); }  //Defaults to stdio without having to wirte pcUart explicitly
+#else
+#define SERIAL_DEBUG(...) /* nothing */
+#endif
+
+#define NEED_BLE_OUTPUT 0 // Set this if you need debug messages on the console;
+#if NEED_BLE_OUTPUT
+#define DEBUG(STR) { if (uart) uart->write(STR, strlen(STR)); }
+#else
+#define DEBUG(...) /* nothing */
+#endif /* #if NEED_CONSOLE_OUTPUT */
+
+I2C i2c(PIN_SDA, PIN_SCL);
 Si7020 tempsensor(&i2c);
 
-InterruptIn motion(p11);
-//InterruptIn motion(p8);
-//InterruptIn motion(p23);
+
+InterruptIn motion_pin(PIN_PRESENCE_RIGHT);
+DigitalIn pinR(PIN_PRESENCE_RIGHT, PullNone);
+//DigitalInOut pinR(PIN_PRESENCE_RIGHT); //, PullNone);
+
+DigitalOut ledB(PIN_BLED_PCB, 1);
+DigitalOut ledR(PIN_RLED_PCB, 1);
+
+/* BATTERY MEASUREMENT */
+void my_analogin_init(void)
+{
+    NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled;
+    NRF_ADC->CONFIG = (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) |
+                      (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
+                      (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) |
+                      (ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) |
+                      (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos);
+}
+
+uint16_t my_analogin_read_u16(void)
+{
+    NRF_ADC->CONFIG     &= ~ADC_CONFIG_PSEL_Msk;
+    NRF_ADC->CONFIG     |= ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos;
+    NRF_ADC->TASKS_START = 1;
+    while (((NRF_ADC->BUSY & ADC_BUSY_BUSY_Msk) >> ADC_BUSY_BUSY_Pos) == ADC_BUSY_BUSY_Busy) {};
+    return (uint16_t)NRF_ADC->RESULT; // 10 bit
+}
 
-DigitalOut led(p21, 1);
-//DigitalOut led(LED2, 0);
+float getBatteryVolt (void)
+{
+    char Vpower[10];
+
+    float Vadc = (float)my_analogin_read_u16();
+    float Vref = 1.2; // Internal Vref
+    float Vcc = 3 * 4 * Vref * Vadc / 1024.0;
+
+    sprintf (Vpower, "Vcc=%.2fV, ", Vcc);
+    DEBUG(Vpower);
+    return Vcc;
+}
+
+int getBatteryPercent ()
+{
+    char batt_mess[10];
+    float Vbat_min = 2.3; //2;
+    float Vbat_max = 3;
+    int battLevel = (int) ( ((getBatteryVolt()-Vbat_min) / (Vbat_max-Vbat_min)) *100);
+
+    sprintf (batt_mess, "Vbatt=%i, ", battLevel);
+    DEBUG(batt_mess);
+
+    // To avoid values bigger than 100%
+    if (battLevel > 100) {
+        battLevel = 100;
+    }
+
+    return battLevel;
+}
+
+/* BLE CONFIGURATION */
 
 BLE ble;
+static const char     DEVICE_NAME[]         = "SM-PIR";
+static const uint16_t uuid16_list[]         = {GattService::UUID_HEALTH_THERMOMETER_SERVICE};
+static volatile bool  triggerSensorPolling  = false;
+static char           fwversion[31]         = "CAT-1817";
+static uint8_t        batteryLevel          = 100;
+static int8_t         TxPower               = +4;
 
-const static char     DEVICE_NAME[]        = "SensorModulePIR";
-//static const uint16_t uuid16_list[]        = {GattService::UUID_HEALTH_THERMOMETER_SERVICE, SetTemperatureService::SET_TEMPERATURE_SERVICE_UUID};
-static const uint16_t uuid16_list[]        = {GattService::UUID_HEALTH_THERMOMETER_SERVICE};
+static HealthThermometerService *thermometerServicePtr;
+PresenceDetectionService *presenceService = NULL;
+HumidityMeasureService *humidityService = NULL;
+UARTService *uart;
+const static uint8_t ManufData[] = {0x01,0x02,0x03,0x04,0x05};   // Set up to 26B of advertising data to use fro the Manufacturer data.
+
+// Firmware
+GattCharacteristic  fwChars(GattCharacteristic::UUID_FIRMWARE_REVISION_STRING_CHAR, (uint8_t *)fwversion, sizeof(fwversion), sizeof(fwversion),GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
+GattCharacteristic *firmwareChars[] = {&fwChars };
+GattService         firmwareService(GattService::UUID_DEVICE_INFORMATION_SERVICE, firmwareChars, sizeof(firmwareChars) / sizeof(GattCharacteristic *));
+
+//Battery
+GattCharacteristic  batteryPercentage(GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, (uint8_t *)batteryLevel, sizeof(batteryLevel), sizeof(batteryLevel), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
+GattCharacteristic *batteryChars[] = {&batteryPercentage};
+GattService         batteryService(GattService::UUID_BATTERY_SERVICE, batteryChars, sizeof(batteryChars) / sizeof(GattCharacteristic *));
+
+//Power
+GattCharacteristic  TxPowerChar(GattCharacteristic::UUID_TX_POWER_LEVEL_CHAR, (uint8_t*)&TxPower, sizeof(TxPower), sizeof(TxPower), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
+GattCharacteristic *charTable[] = {&TxPowerChar};
+GattService         TxPowerService(GattService::UUID_TX_POWER_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
 
-static volatile bool  triggerSensorPolling = false;
-uint8_t presence_now = 0;
-uint8_t presence_before = 0;
-float currentTemperature;
+
+bool presence = false;
+bool presenceL = false;
+uint8_t presence_count = 0;
+bool ledOn = 0;
+static volatile bool  triggerPresencePolling = false;
 
-PresenceDetectionService *presenceService = NULL;
-TemperatureMeasureService *temperatureService = NULL;
+void blinkLed (bool enable, int color)
+{
+    if (enable) {
+        if (color == 1) {
+            ledB=0;
+            wait(0.2);
+            ledB=1;
+            wait(0.2);
+        }
+        if (color == 2) {
+            ledR=0;
+            wait(0.2);
+            ledR=1;
+            wait(0.2);
+        }
+    } else {
+        // do nothing if enable=0
+    }
+}
 
+/* Restart Advertising on disconnection*/
 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
 {
-    //led = !led;
-    pc.printf("Disconnected\r\n");
-    ble.gap().startAdvertising();
+    SERIAL_DEBUG("Disconnected\r\n");
+    BLE::Instance().gap().startAdvertising();
 }
 
 /**
@@ -50,36 +164,75 @@
  */
 void onBleInitError(BLE &ble, ble_error_t error)
 {
+    /* Avoid compiler warnings */
+    (void) ble;
+    (void) error;
     /* Initialization error handling should go here */
 }
 
+
 float getTemperature(void)
 {
-    /*
-    float t = hdc1000.temperature();
-    t = t/0x10000*165-40;
-    pc.printf("Temperature: %f \n", t);
+    float temp;
     
-    return t;
-    */
+    if(tempsensor.getTemperature(&temp) != 0) {
+        DEBUG("Error getting temperature");
+        temp = -1;
+    }
 
-    //float t = 26.8;
-    //return t;
+    // Debugging:
+    SERIAL_DEBUG("\nTemperature = %.2f", temp);
+    char message[50];
+    sprintf (message, "T=%.2fC\n", temp);
+    DEBUG(message);
     
-    float temp;
-    if(tempsensor.getTemperature(&temp) != 0) {
-        //pc.printf("Error getting temperature");
-        temp = -1;
-    } 
-    pc.printf("Temperature = %fC\n", temp);
-    
-    return temp;  
+    // Adding offset:
+    temp = temp + OFFSET;
+
+    return temp;
 }
 
-void onDataWrittenCallback(const GattWriteCallbackParams *params) 
+float getHumidity(void)
+{
+
+    float hum;
+    if(tempsensor.getHumidity(&hum) != 0) {
+        SERIAL_DEBUG("Error getting humidity");
+        hum = -1;
+    }
+
+    // Debugging:
+    SERIAL_DEBUG("\nHumidity = %f", hum);
+    char message[50];
+    sprintf (message, "RH=%d\n", (int)hum);
+    DEBUG(message);
+
+    return hum;
+}
+
+void onDataWrittenCallback(const GattWriteCallbackParams *params)
 {
-   pc.printf("Resetting presence\n");
-   presence_before = 0;
+    if (params->data[0] == 1) {
+        blinkLed(ledOn,1);
+        SERIAL_DEBUG("BLE. Resetting presence\n");
+        presence_count = 0;
+    }
+
+    if (params->data[0] == 2) {
+        blinkLed(1,1);
+        blinkLed(1,1);
+        SERIAL_DEBUG("BLE. All LEDs ON/OFF\n");
+        ledOn = !ledOn;
+    }
+
+    if (params->data[0] == 3) {
+        blinkLed(1,1);
+        blinkLed(1,1);
+        blinkLed(1,1);
+        SERIAL_DEBUG("BLE. Rebooting sensor\n");
+        wait(3);
+        NVIC_SystemReset(); // SW Reset
+    }
 }
 
 /**
@@ -87,9 +240,9 @@
  */
 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
 {
-    pc.printf("Init \n");
-    
-    BLE &ble = params->ble;
+    SERIAL_DEBUG("BLE. Init \n");
+
+    BLE&        ble   = params->ble;
     ble_error_t error = params->error;
 
     if (error != BLE_ERROR_NONE) {
@@ -102,106 +255,126 @@
     if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
         return;
     }
-    
+
     //ble.gap().onConnection(connectionCallback);
-    //ble.gap().onDisconnection(disconnectionCallback);
-    ble.onDisconnection(disconnectionCallback);
+    ble.gap().onDisconnection(disconnectionCallback);
 
-    ble.gap().setScanParams(500, 400);
+    // Set Transmission power:
+    ble.setTxPower(TxPower);
+
+    //ble.gap().setScanParams(500, 400);
     //ble.gap().startScan(advertisementCallback);
-      
+
     //BLE server setup
-    //ble.init();
-    //ble_server.gap().onDisconnection(disconnectionCallbackServer); check why gives error
     ble.gattServer().onDataWritten(onDataWrittenCallback);
-    
+
     //Setup primary services
-    presenceService = new PresenceDetectionService(ble, presence_before);
-    temperatureService = new TemperatureMeasureService(ble, getTemperature());
-    
-    //setup advertising
+    presenceService = new PresenceDetectionService(ble, presence_count);
+    thermometerServicePtr = new HealthThermometerService(ble, getTemperature(), HealthThermometerService::LOCATION_EAR);
+    humidityService = new HumidityMeasureService(ble, getHumidity());
+    ble.addService(batteryService);
+    ble.addService(firmwareService);
+    uart = new UARTService(ble);
+    ble.addService(TxPowerService);
+
+
+    /* setup advertising */
+
+    /* Sacrifice 3B of 31B to Advertising Flags */
     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+
+    /* Sacrifice 2B of 31B to AdvType overhead, rest goes to AdvData array you define */
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, ManufData, sizeof(ManufData));
+    ble.gap().accumulateAdvertisingPayloadTxPower(TxPower);
     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
     //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::THERMOMETER_EAR);
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER);
+    //ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,(const uint8_t *)"BLE UART", sizeof("BLE UART") - 1);
+    //ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
-    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
-    ble.gap().setAdvertisingInterval(1000);  //1000ms 
-    ble.gap().startAdvertising(); 
-}
-
-/**
-*Server functions
-*/
 
-/* Restart Advertising on disconnection*/
-//void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
-//{
-//    ble_server.gap().startAdvertising();
-//}
-
-void periodicCallbackSensor(void)
-{
-    //led1 = !led1; /* Do blinky on LED1 while we're waiting for BLE events */
-
-    /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
-     * heavy-weight sensor polling from the main thread. */
-    triggerSensorPolling = true;
-    pc.printf("Periodic sensor \n");
+    ble.setAdvertisingInterval(1000); /* 1000ms */
+    //ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
+    ble.startAdvertising();
 }
 
 void periodicCallbackPresence(void)
 {
-    pc.printf("Periodic presence \n");
-    //presence_before = 0;
+    triggerPresencePolling = true;
+    presence = 1;
 }
 
-void irq_handler(void)
+void periodicCallbackSensor (void)
 {
-    presence_now = 1;
-    presence_before = 1;
-    pc.printf("Presence detected \n");
+    triggerSensorPolling = true;
 }
 
 int main(void)
-{   
-    pc.printf("Start \n");
-    
+{
+    SERIAL_DEBUG("Start \n");
+    char pres_message[20];
+
+    blinkLed(1,1);
+
+    //Ticker ticker_presence;
+    //ticker_presence.attach(periodicCallbackPresence, 0.5);
+
+    motion_pin.fall(&periodicCallbackPresence);
+    //motion_pin.rise(&periodicCallbackPresence);
+
     Ticker ticker_sensor;
-    ticker_sensor.attach(periodicCallbackSensor, 5);
-    
-    Ticker ticker_presence;
-    ticker_presence.attach(periodicCallbackPresence, 300);
-    
-    motion.rise(&irq_handler);
-    
+    ticker_sensor.attach(periodicCallbackSensor, 60);
+
     //BLE instance setup
     BLE &bleptr = BLE::Instance();
     bleptr.init(bleInitComplete);
-    
-    //float initialDesiredTemperature = 20;
-    
+
+    /*
+     //SpinWait for initialization to complete. This is necessary because the
+     //BLE object is used in the main loop below.
+    while (ble.hasInitialized()  == false) {    }
+    */
+
     while (true) {
+
+        /* Get Presence data: */
+        if(triggerPresencePolling) {
+            triggerPresencePolling = false;
+            //presence = motion_pin.read();
+
+            if (presence) {
+                presence_count++;
+
+                // Debugging:
+                if (presence) {
+                    blinkLed(ledOn,1);
+                }
+
+                SERIAL_DEBUG("Presence counter: %i\n", presence_count);
+                sprintf (pres_message, "Pres=%i\n", presence_count);
+                DEBUG(pres_message);
+
+                presence=0;
+            }
+
+            else {
+                SERIAL_DEBUG(".");
+            }
+        }
+
+        /* Update BLE services: */
         if (triggerSensorPolling && ble.getGapState().connected) {
             triggerSensorPolling = false;
-
-            //Do blocking calls or whatever is necessary for sensor polling.
-            // error = sensor.readData();
-            // if (!error) {
-            //     thermometerService.updateTemperature(c);
-            // }
+            thermometerServicePtr->updateTemperature(getTemperature());
+            humidityService->updateHumidity(getHumidity());
+            presenceService->updatePresence(presence_count);
+            batteryLevel = getBatteryPercent();
+            ble.updateCharacteristicValue(batteryPercentage.getValueAttribute().getHandle(), &batteryLevel, sizeof(batteryLevel));
+            ble.updateCharacteristicValue(TxPowerChar.getValueAttribute().getHandle(), (uint8_t*)&TxPower, 1);
 
-            temperatureService->updateTemperature(getTemperature());
-            presenceService->updatePresence(presence_before);
-        } 
-        ble.waitForEvent();
-        
-        if(presence_now) {
-            led = 0;
-            //cnt++;
-            presence_now = 0;
-            //pc.printf("Presence detected \n", cnt);
-            wait(2);
-            led = 1;
+        } else {
+            ble.waitForEvent();
         }
     }
 }