Green Building Team / Mbed 2 deprecated BLE_GreenYourLife_STM32

Dependencies:   BLE_API X_NUCLEO_IDB0XA1 X_NUCLEO_IKS01A1 mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /************************ STM32NUCLEO IOT Contest ******************************
00002  *
00003  *                   Green Building IoT Solution for
00004  *                Plant Life Monitoring And Maintenance
00005  *
00006  *                           Authored by
00007  *                        Dien Hoa Truong
00008  *                 Muhammad Haziq Bin Kamarul Azman
00009  *                        
00010  *                            for the
00011  *            eSAME 2016 STM32NUCLEO IoT Contest in Sophia-Antipolis
00012  *
00013  *  main.cpp | Program main
00014  *
00015  *  See LICENCE.txt for information on copyrights
00016  *
00017  ******************************************************************************/
00018 
00019 /** Includes **/
00020 #include "mbed.h"                                                               // ARM mbed               library
00021 #include "x_nucleo_iks01a1.h"                                                   // STM32NUCLEO board      library
00022 #include "ble/BLE.h"                                                            // Bluetooth LE           library
00023 #include "GreenBuildingService.h"                                               // Green Building service library
00024 
00025 
00026 
00027 /** Defines **/
00028 #define GB_SOIL_MOISTURE_MAX 70                                                 // Soil moisture threshold value
00029 
00030 
00031 
00032 /** Device declarations **/
00033 
00034 // Board-specific
00035 PwmOut pumpPWM(PC_8);                                                           // PWM motor control out pin
00036 DigitalOut led1(LED1, 1);                                                       // Debug pin instance
00037 AnalogIn moisture_sensor(PB_1);                                                 // Moisture sensor
00038 static X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(D14, D15); // Expansion board instance
00039 static HumiditySensor   *humidity_sensor = mems_expansion_board->ht_sensor;     // Expansion board humidity sensor instance
00040 static TempSensor       *temp_sensor     = mems_expansion_board->ht_sensor;     // Expansion board temperature sensor instance
00041 
00042 // BLE-specific
00043 BLE&                  ble = BLE::Instance(BLE::DEFAULT_INSTANCE);               // BLE device instance
00044 const static char     DEVICE_NAME[] = "GB-Sensor";                              // Device name
00045 static const uint16_t uuid16_list[] = {GreenBuildingService::UUID_GREEN_BUILDING_SERVICE};
00046 GreenBuildingService *gbServicePtr;                                             // Service pointer
00047 
00048 // Program-specific
00049 float getMoistureValue();
00050 float getHumidityValue();
00051 float getTemperatureValue();
00052 void errorLoop(void);
00053 void activateFastSensorPoll();
00054 void deactivateFastSensorPoll();
00055 void pumpActivateCallback(void);
00056 void pumpDeactivateCallback(void);
00057 
00058 Ticker sanityTicker;
00059 Ticker sensorPollTicker;
00060 Ticker fastSensorPollTicker;
00061 Timeout pumpWaitTimeout;
00062 uint8_t usersConnected;
00063 bool sensorPolling;
00064 bool fastSensorPolling;
00065 bool pumpActivate;
00066 bool waitOnce;
00067 bool bleActive;
00068 bool pumpActive;
00069 
00070 
00071 /** Callbacks **/
00072 
00073 // BLE-specific callback
00074 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)    // Callback for everytime the connection gets disconnected
00075 {
00076     ble.gap().startAdvertising();                                               // Restart advertising
00077     if((!pumpActive)||(!usersConnected))
00078         deactivateFastSensorPoll();
00079     bleActive = false;
00080     --usersConnected;
00081 //    printf("\r\n> BLE  : Disconnected. Advertising restarted.");
00082 }
00083 
00084 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)          // Callback for everytime the connection is established
00085 {
00086     ble.gap().stopAdvertising();                                                // Stop advertising
00087     activateFastSensorPoll();
00088     bleActive = true;
00089     ++usersConnected;
00090 //    printf("\r\n> BLE  : Connected to %x. Accept no subsequent connections.", params->peerAddr);
00091 }
00092 
00093 void onBleInitError(BLE &ble, ble_error_t error)
00094 {
00095 //    printf("\r\n> BLE  : Init error encountered. Error returned: %d", error);
00096     errorLoop();
00097 }
00098 
00099 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
00100 {
00101     BLE&        ble   = params->ble;
00102     ble_error_t error = params->error;
00103 
00104     if (error != BLE_ERROR_NONE) {                                              // Check to see init errors
00105         onBleInitError(ble, error);
00106         errorLoop();
00107     }
00108 
00109     if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {                         // If this is not default instance (double instanciation?)
00110 //        printf("\r\n> BLE  : BLE controller instance is invalid.");
00111         errorLoop();
00112     }
00113     
00114     ble.gap().onDisconnection(disconnectionCallback);                           // Register disconnection callback
00115     ble.gap().onConnection(connectionCallback);                                 // Register connection callback
00116 
00117     gbServicePtr = new GreenBuildingService(ble);                               // Init service with initial value
00118     
00119     /* Setup advertising. */
00120     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00121     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
00122     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,(uint8_t *)uuid16_list, sizeof(uuid16_list));
00123     ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00124     ble.gap().setAdvertisingInterval(1000); /* 1000ms */
00125     ble.gap().startAdvertising();
00126     
00127 //    printf("\r\n> BLE  : BLE Init done.");
00128 }
00129 
00130 // Helper functions for retrieving data from sensors
00131 float getMoistureValue()
00132 {
00133     float moisture = 0;
00134     for (int i = 1;i<=10;i++) {
00135         moisture += moisture_sensor.read();                                     // Get ten samples
00136     }
00137     moisture = moisture / 10;
00138     moisture = moisture * 3300;                                                 // Change the value to be in the 0 to 3300 range
00139     moisture = moisture / 33;                                                   // Convert to percentage
00140     return moisture;
00141 }
00142 
00143 float getHumidityValue()
00144 {
00145     float humidity = 0;
00146     humidity_sensor->GetHumidity(&humidity);
00147     return humidity;
00148 }
00149 
00150 float getTemperatureValue()
00151 {
00152     float temperature = 0;
00153     temp_sensor->GetTemperature(&temperature);
00154     return temperature;
00155 }
00156 
00157 
00158 // Miscellaneous callbacks & functions
00159 void sanityCallback(void)
00160 {
00161     led1 = !led1;                                                               // Blink LED1 to indicate system sanity
00162 }
00163 
00164 void sensorPollCallback(void)
00165 {
00166     sensorPolling = true;
00167 }
00168 
00169 void fastSensorPollCallback(void)
00170 {
00171     fastSensorPolling = true;
00172 }
00173 
00174 void pumpActivateCallback(void)
00175 {
00176     pumpActivate = true;
00177 }
00178 
00179 void pumpDeactivateCallback(void)
00180 {
00181     pumpActivate = false;
00182 }
00183 
00184 void activateFastSensorPoll(void)
00185 {
00186     fastSensorPolling = true;
00187     fastSensorPollTicker.attach(&fastSensorPollCallback, 0.9);
00188 }
00189 
00190 void deactivateFastSensorPoll(void)
00191 {
00192     fastSensorPolling = false;
00193     fastSensorPollTicker.detach();
00194 }
00195 
00196 
00197 void errorLoop(void)
00198 {
00199     sanityTicker.detach();
00200     sensorPollTicker.detach();
00201     ble.shutdown();
00202 //    printf("\r\n> ERROR : Error encountered. Infinite looping.");
00203     while(true)
00204     {
00205         led1 != led1;        
00206     }
00207 }
00208 
00209 
00210 
00211 /** Pre-main inits **/
00212 
00213 
00214 
00215 /** Main loop **/
00216 int main(void)
00217 {
00218     pumpPWM.write(1);
00219     pumpPWM.period(1.0f);
00220     
00221     printf("\r\n/**\r\n * Green Building Sensor Device: Debug Info\r\n */");
00222     
00223     sensorPolling = false;
00224     fastSensorPolling = false;
00225     pumpActivate = false;
00226     waitOnce = true;
00227     bleActive = false;
00228     pumpActive = false;
00229     
00230     sanityTicker.attach(sanityCallback, 1.1);                                   // LED sanity checker
00231     sensorPollTicker.attach(sensorPollCallback, 4.9);                           // Sensor poll ticker
00232     
00233     printf("\r\n> MAIN : Tickers initialized.");
00234  
00235     volatile GreenBuildingService::PlantEnvironmentType_t peVal;                // Plant environment var
00236     uint8_t pumpWaitTime = 3;                                                   // Pump waiting time
00237  
00238     ble.init(bleInitComplete);                                                  // Pass BLE init complete function upon init
00239     
00240 //    while(ble.hasInitialized() == false);
00241     
00242     printf("\r\n> MAIN : BLE Init procedure done.");
00243     
00244     // Infinite loop
00245     while (true) {
00246         
00247         if(sensorPolling || fastSensorPolling)
00248         {
00249             sensorPolling = false;                                              // Deassert polling bit
00250             fastSensorPolling = false;
00251             
00252             peVal.soilMoisture   = (uint8_t) getMoistureValue();                // Update all measurements
00253             peVal.airHumidity    = (uint8_t) getHumidityValue();
00254             peVal.airTemperature = (int8_t)  getTemperatureValue();
00255             
00256             if(ble.getGapState().connected)                                     // Update characteristic if connected
00257                 gbServicePtr->updatePlantEnvironment(peVal);
00258             
00259 //            printf("\r\n> MAIN : Current soil moisture    = %d", peVal.soilMoisture);
00260 //            printf("\r\n> MAIN : Current air humidity     = %d", peVal.airHumidity);
00261 //            printf("\r\n> MAIN : Current air temperature  = %d", peVal.airTemperature);
00262             printf("%d\t%d\t%d\r\n", peVal.airTemperature, peVal.airHumidity, peVal.soilMoisture);
00263             
00264             // If moisture is below 50% of max when user is present
00265             //    or if less than 30% of max
00266             if( ( ((peVal.soilMoisture < 0.5*GB_SOIL_MOISTURE_MAX) &&  ble.getGapState().connected)   ||
00267                   ((peVal.soilMoisture < 0.3*GB_SOIL_MOISTURE_MAX) && !ble.getGapState().connected) ) &&
00268                 waitOnce
00269             )
00270             {
00271                 pumpWaitTimeout.attach(&pumpActivateCallback, pumpWaitTime);    // Waiting time is hard coded but may be calculated, I think
00272                 activateFastSensorPoll();
00273                 waitOnce = false;
00274                 pumpActive = true;
00275             }
00276             else if((peVal.soilMoisture >= 0.6*GB_SOIL_MOISTURE_MAX) && pumpActivate) // Stop condition: when soil moisture is at 60% of max
00277             {
00278                 pumpPWM.write(1);
00279                 pumpWaitTimeout.detach();
00280                 pumpDeactivateCallback();
00281                 if(!bleActive)
00282                     deactivateFastSensorPoll();
00283                 waitOnce = true;
00284                 pumpActive = false;
00285             }
00286             
00287             if(pumpActivate)
00288             {
00289 //                printf("\r\n> MAIN : Activating water pump.");
00290                 pumpPWM.write(0.7);                
00291                 pumpActivate = false;
00292                 pumpWaitTimeout.attach(&pumpActivateCallback, 1);
00293             }
00294             
00295         }
00296         else
00297             ble.waitForEvent();                                                 //Low power wait for event   
00298         
00299     }
00300 }