ModoSmart / Mbed 2 deprecated WindowSensorModule

Dependencies:   BLE_API mbed nRF51822

Fork of SensorModulePIR by ModoSmart

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "defineGPIOs.h"
00003 #include "BLE.h"
00004 #include "ble/services/HealthThermometerService.h"
00005 #include "ble/services/BatteryService.h"
00006 #include "ble/services/EnvironmentalService.h"
00007 #include "HumidityMeasureService.h"
00008 #include "PresenceDetectionService.h"
00009 #include "ble_gatt.h"
00010 #include "Si7020.h"
00011 #include "UARTService.h"
00012 #include <string.h>
00013 
00014 
00015 
00016 // OFFSET TEMPERATURE CONFIGURATIONS:
00017 #define STANDARD -1  // Squared radar sensor module: -1ºC
00018 #define ZERO 0  // no offset
00019 #define OFFSET STANDARD
00020 
00021 #define NEED_SERIAL_CONSOLE_OUTPUT 0
00022 #if NEED_SERIAL_CONSOLE_OUTPUT
00023 Serial pc(PIN_TX, PIN_RX);
00024 #define SERIAL_DEBUG(...) { printf(__VA_ARGS__); }  //Defaults to stdio without having to wirte pcUart explicitly
00025 #else
00026 #define SERIAL_DEBUG(...) /* nothing */
00027 #endif
00028 
00029 #define NEED_BLE_OUTPUT 1 // Set this if you need debug messages on the console;
00030 #if NEED_BLE_OUTPUT
00031 #define DEBUG(STR) { if (uart) uart->write(STR, strlen(STR)); }
00032 #else
00033 #define DEBUG(...) /* nothing */
00034 #endif /* #if NEED_CONSOLE_OUTPUT */
00035 
00036 I2C i2c(PIN_SDA, PIN_SCL);
00037 Si7020 tempsensor(&i2c);
00038 
00039 InterruptIn     motion_pin(PIN_PRESENCE_RIGHT);
00040 DigitalIn       pinR(PIN_PRESENCE_RIGHT, PullNone);
00041 DigitalOut      ledB(PIN_BLED_PCB, 1);
00042 DigitalOut      ledR(PIN_RLED_PCB, 1);
00043 
00044 bool presenceState = false;
00045 int presenceCounter = 0;
00046 //uint8_t presenceCounterBLE = 0;
00047 bool installMode = 0;
00048 bool battNotify = 1;
00049 static volatile bool  triggerPresencePolling = false;
00050 
00051 
00052 /* BLE CONFIGURATION */
00053 
00054 BLE ble;
00055 static const char     DEVICE_NAME[]         = "WindowSensorUnit";
00056 static const uint16_t uuid16_list[]         = {GattService::UUID_HEALTH_THERMOMETER_SERVICE};
00057 static volatile bool  triggerSensorPolling  = false;
00058 static char           fwversion[31]         = "Agile-IoT";
00059 static uint8_t        batteryLevel          = 99;
00060 static int8_t         TxPower               = +4;
00061 //static uint8_t        humidity            = 99;
00062 const static uint8_t  ManufData[]           = {0x01,0x02,0x03,0x04,0x05};   // Set up to 26B of advertising data to use for the Manufacturer data.
00063 
00064 
00065 //static HealthThermometerService *thermometerServicePtr = NULL;;
00066 static BatteryService* batteryServicePtr = NULL;;
00067 //static EnvironmentalService* humidityTemperatureServicePtr = NULL;
00068 UARTService *uart;
00069 
00070 // Firmware
00071 GattCharacteristic  fwChars(GattCharacteristic::UUID_FIRMWARE_REVISION_STRING_CHAR, (uint8_t *)fwversion, sizeof(fwversion), sizeof(fwversion),GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
00072 GattCharacteristic *firmwareChars[] = {&fwChars };
00073 GattService         firmwareService(GattService::UUID_DEVICE_INFORMATION_SERVICE, firmwareChars, sizeof(firmwareChars) / sizeof(GattCharacteristic *));
00074 
00075 //Power
00076 GattCharacteristic  TxPowerChar(GattCharacteristic::UUID_TX_POWER_LEVEL_CHAR, (uint8_t*)&TxPower, sizeof(TxPower), sizeof(TxPower), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
00077 GattCharacteristic *charTable[] = {&TxPowerChar};
00078 GattService         TxPowerService(GattService::UUID_TX_POWER_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
00079 
00080 /* BATTERY MEASUREMENT */
00081 void my_analogin_init(void)
00082 {
00083     NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled;
00084     NRF_ADC->CONFIG = (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) |
00085                       (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
00086                       (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) |
00087                       (ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) |
00088                       (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos);
00089 }
00090 
00091 uint16_t my_analogin_read_u16(void)
00092 {
00093     NRF_ADC->CONFIG     &= ~ADC_CONFIG_PSEL_Msk;
00094     NRF_ADC->CONFIG     |= ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos;
00095     NRF_ADC->TASKS_START = 1;
00096     while (((NRF_ADC->BUSY & ADC_BUSY_BUSY_Msk) >> ADC_BUSY_BUSY_Pos) == ADC_BUSY_BUSY_Busy) {};
00097     return (uint16_t)NRF_ADC->RESULT; // 10 bit
00098 }
00099 
00100 float getBatteryVolt (void)
00101 {
00102     char Vpower[10];
00103 
00104     float Vadc = (float)my_analogin_read_u16();
00105     float Vref = 1.2; // Internal Vref
00106     float Vcc = 0.62 * Vref * Vadc / 1024.0;; //3 * 4 * Vref * Vadc / 1024.0;
00107 
00108     sprintf (Vpower, "Vcc=%.2fV, ", Vcc);
00109     DEBUG(Vpower);
00110     return Vcc;
00111 }
00112 
00113 int getBatteryPercent ()
00114 {
00115     char batt_mess[10];
00116     float Vbat_min = 3; //2;
00117     float Vbat_max = 3.7;
00118     int battLevel = (int) ( ((getBatteryVolt()-Vbat_min) / (Vbat_max-Vbat_min)) *100);
00119 
00120     sprintf (batt_mess, "Vbatt=%i, ", battLevel);
00121     DEBUG(batt_mess); 
00122    
00123     return battLevel;
00124 }
00125 
00126 void blinkLed (bool enable, int color)
00127 {
00128     if (enable) {
00129         if (color == 1) {
00130             ledB=0;
00131             wait(0.2);
00132             ledB=1;
00133             wait(0.2);
00134         }
00135         if (color == 2) {
00136             ledR=0;
00137             wait(0.2);
00138             ledR=1;
00139             wait(0.2);
00140         }
00141     } else {
00142         // do nothing if enable=0
00143     }
00144 }
00145 
00146 uint8_t updatePresenceCounter (int counts)
00147 {
00148     uint8_t uint8_counter;
00149 
00150     if (counts>=255) {
00151         uint8_counter = 255;
00152 
00153     } else {
00154         uint8_counter = uint8_t(counts);
00155     }
00156 
00157     return uint8_counter;
00158 }
00159 
00160 float getHumidity(void)
00161 {
00162     float hum;
00163     if(tempsensor.getHumidity(&hum) != 0) {
00164         SERIAL_DEBUG("Error getting humidity");
00165         hum = -1;
00166     }
00167 
00168     // Debugging:
00169     SERIAL_DEBUG("\nHumidity = %f", hum);
00170     char message[50];
00171     sprintf (message, "RH=%.2f %i\n", hum, (uint16_t)hum);
00172     DEBUG(message);
00173 
00174     //return uint8_t(hum);
00175     //return uint16_t(hum);
00176     return hum;
00177 }
00178 
00179 float getTemperature(void)
00180 {
00181     float temp;
00182 
00183     if(tempsensor.getTemperature(&temp) != 0) {
00184         DEBUG("Error getting temperature");
00185         temp = -1;
00186     }
00187 
00188     // Debugging:
00189     SERIAL_DEBUG("\nTemperature = %.2f", temp);
00190     char message[50];
00191     sprintf (message, "T=%.2fC\n", temp);
00192     DEBUG(message);
00193 
00194     // Adding offset:
00195     temp = temp + OFFSET;
00196 
00197     return temp;
00198 }
00199 
00200 /* Restart Advertising on disconnection*/
00201 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
00202 {
00203     SERIAL_DEBUG("Disconnected\r\n");
00204     BLE::Instance().gap().startAdvertising();
00205 }
00206 
00207 /**
00208  * This function is called when the ble initialization process has failed
00209  */
00210 void onBleInitError(BLE &ble, ble_error_t error)
00211 {
00212     /* Avoid compiler warnings */
00213     (void) ble;
00214     (void) error;
00215     /* Initialization error handling should go here */
00216 }
00217 
00218 void onDataWrittenCallback(const GattWriteCallbackParams *params)
00219 {
00220     int var = params->data[0];
00221 
00222     if (var == 1) {
00223         blinkLed(installMode,1);
00224         SERIAL_DEBUG("BLE. Resetting presence\n");
00225         presenceCounter = 0;
00226         //presenceCounterBLE = 0;
00227         triggerSensorPolling = true;       // force update of all BLE services
00228     }
00229 
00230     if (var == 2) {
00231         blinkLed(1,1);
00232         blinkLed(1,1);
00233         SERIAL_DEBUG("BLE. All LEDs ON/OFF\n");
00234         installMode = !installMode;
00235     }
00236 
00237     if (params->data[0] == 3) {
00238         blinkLed(1,1);
00239         blinkLed(1,1);
00240         blinkLed(1,1);
00241         SERIAL_DEBUG("BLE. Rebooting sensor\n");
00242         wait(3);
00243         NVIC_SystemReset(); // SW Reset
00244     }
00245 }
00246 
00247 /**
00248  * Callback triggered when the ble initialization process has finished
00249  */
00250 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
00251 {
00252     SERIAL_DEBUG("BLE. Init \n");
00253 
00254     BLE&        ble   = params->ble;
00255     ble_error_t error = params->error;
00256 
00257     if (error != BLE_ERROR_NONE) {
00258         /* In case of error, forward the error handling to onBleInitError */
00259         onBleInitError(ble, error);
00260         return;
00261     }
00262 
00263     /* Ensure that it is the default instance of BLE */
00264     if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
00265         return;
00266     }
00267 
00268     //ble.gap().onConnection(connectionCallback);
00269     ble.gap().onDisconnection(disconnectionCallback);
00270 
00271     // Set Transmission power:
00272     ble.setTxPower(TxPower);
00273 
00274     //BLE server setup
00275     ble.gattServer().onDataWritten(onDataWrittenCallback);
00276 
00277     //Setup primary services
00278     batteryServicePtr = new BatteryService(ble, batteryLevel);
00279 
00280     //humidityTemperatureServicePtr = new EnvironmentalService (ble);
00281 
00282     ble.addService(firmwareService);
00283     //ble.addService(TxPowerService);
00284 
00285     /* setup advertising */
00286 
00287     /* Sacrifice 3B of 31B to Advertising Flags */
00288     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00289     ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00290 
00291     /* Sacrifice 2B of 31B to AdvType overhead, rest goes to AdvData array you define */
00292     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
00293     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
00294     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER);
00295 
00296     ble.setAdvertisingInterval(1000); /* 1000ms */
00297     ble.startAdvertising();
00298 }
00299 
00300 void periodicCallbackPresence(void)
00301 {
00302     triggerPresencePolling = true;
00303     presenceState = true;
00304 }
00305 
00306 void periodicCallbackSensor (void)
00307 {
00308     triggerSensorPolling = true;
00309 }
00310 
00311 void updateBLEservices ()
00312 {
00313     //humidityTemperatureServicePtr->updateTemperature (getTemperature());
00314     //humidityTemperatureServicePtr->updateHumidity (getHumidity());
00315 
00316     batteryServicePtr->updateBatteryLevel(getBatteryPercent());
00317 
00318 }
00319 
00320 int main(void)
00321 {
00322     SERIAL_DEBUG("Start \n");
00323     char pres_message[20];
00324 
00325     blinkLed(1,1);
00326 
00327     motion_pin.fall(&periodicCallbackPresence);
00328 
00329     Ticker ticker_sensor;
00330     ticker_sensor.attach(periodicCallbackSensor, 3); // 5 min
00331 
00332     //BLE instance setup
00333     BLE &bleptr = BLE::Instance();
00334     bleptr.init(bleInitComplete);
00335 
00336     while (true) {
00337 
00338         /* Get Presence data: */
00339         if(triggerPresencePolling) {
00340             triggerPresencePolling = false;
00341 
00342             // if presence is detected:
00343             if (presenceState) {
00344 
00345                 presenceCounter++;
00346 
00347                 // Update all BLE services for every presence detected:
00348                 updateBLEservices();
00349 
00350                 // Debugging:
00351                 blinkLed(installMode,1);
00352                 SERIAL_DEBUG("Presence counter: %i\n", presenceCounter);
00353                 sprintf (pres_message, "Pres=%i\n", presenceCounter);
00354                 DEBUG(pres_message);
00355 
00356                 presenceState=0;
00357             }
00358 
00359             // if no presence:
00360             else {
00361                 SERIAL_DEBUG(".");
00362             }
00363         }
00364 
00365         /* Update BLE services if connected: */
00366         if (triggerSensorPolling && ble.getGapState().connected) {
00367 
00368             // Quanto consuma quando sta leggendo la temperatura?
00369             triggerSensorPolling = false;
00370 
00371             updateBLEservices();
00372 
00373             /*
00374             // Red LED blinks if low battery, at every connection
00375             if (batteryLevel <= 10) {
00376                 blinkLed(battNotify,2);
00377             }
00378             */
00379 
00380         } else {
00381             ble.waitForEvent();
00382         }
00383     }
00384 }