It is a simple IoT solution for plant life monitoring and maintenance, based on STM32NUCLEO boards and expansion modules. This branch is the post-eSAME development branch.

Dependencies:   BLE_API X_NUCLEO_IDB0XA1 X_NUCLEO_IKS01A1 mbed

Fork of BLE_GreenYourLife_STM32 by Green Building Team

This branch is the main continuation of the original project. You can find it here.

Revision:
5:9d68ed883e95
Parent:
3:c460d60ffda6
Child:
6:35d615722597
--- a/main.cpp	Thu Dec 01 08:28:55 2016 +0000
+++ b/main.cpp	Fri Dec 02 17:36:56 2016 +0000
@@ -6,9 +6,6 @@
  *                           Authored by
  *                        Dien Hoa Truong
  *                 Muhammad Haziq Bin Kamarul Azman
- *                        
- *                            for the
- *            eSAME 2016 STM32NUCLEO IoT Contest in Sophia-Antipolis
  *
  *  main.cpp | Program main
  *
@@ -24,46 +21,50 @@
 
 /** Defines **/
 #define GB_SOIL_MOISTURE_MAX 70                                                 // Soil moisture threshold value
+#define GB_USERS_CONNECTED_MAX 4                                                // Maximum connected users
+#define GB_PUMP_CYCLE_MAX 40                                                    // Maximum pump cycle allowed
 
 
 
 /** Device declarations **/
 
 // Board-specific
-PwmOut pumpPWM(PC_8);                                                           // PWM motor control out pin
+PwmOut     pumpPWM(PC_8);                                                       // PWM motor control out pin
 DigitalOut led1(LED1, 1);                                                       // Debug pin instance
-AnalogIn moisture_sensor(PB_1);                                                 // Moisture sensor
+AnalogIn   moisture_sensor(PB_1);                                               // Moisture sensor
 static X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(D14, D15); // Expansion board instance
-static HumiditySensor   *humidity_sensor = mems_expansion_board->ht_sensor;     // Expansion board humidity sensor instance
-static TempSensor       *temp_sensor     = mems_expansion_board->ht_sensor;     // Expansion board temperature sensor instance
+static HumiditySensor   *humidity_sensor      = mems_expansion_board->ht_sensor;      // Expansion board humidity sensor instance
+static TempSensor       *temp_sensor          = mems_expansion_board->ht_sensor;      // Expansion board temperature sensor instance
 
 // BLE-specific
 BLE&                  ble = BLE::Instance(BLE::DEFAULT_INSTANCE);               // BLE device instance
 const static char     DEVICE_NAME[] = "GB-Sensor";                              // Device name
-static const uint16_t uuid16_list[] = {GreenBuildingService::UUID_GREEN_BUILDING_SERVICE};
+static const uint16_t uuid16_list[] = {GreenBuildingService::UUID_GREEN_BUILDING_SERVICE}; // UUID service list
 GreenBuildingService *gbServicePtr;                                             // Service pointer
+//Gap::Handle_t         bleConnectionHandles[GB_USERS_CONNECTED_MAX];             // Connection handle tables
 
 // Program-specific
 float getMoistureValue();
 float getHumidityValue();
 float getTemperatureValue();
-void errorLoop(void);
-void activateFastSensorPoll();
-void deactivateFastSensorPoll();
-void pumpActivateCallback(void);
-void pumpDeactivateCallback(void);
+void  errorLoop(void);
+void  activateFastSensorPoll();
+void  deactivateFastSensorPoll();
+void  pumpActivateCallback(void);
+void  pumpDeactivateCallback(void);
 
-Ticker sanityTicker;
-Ticker sensorPollTicker;
-Ticker fastSensorPollTicker;
+Ticker  sanityTicker;
+Ticker  sensorPollTicker;
+Ticker  fastSensorPollTicker;
 Timeout pumpWaitTimeout;
+
+uint8_t pumpWaitTime = 3;                                                       // Pump waiting time
 uint8_t usersConnected;
-bool sensorPolling;
-bool fastSensorPolling;
-bool pumpActivate;
-bool waitOnce;
-bool bleActive;
-bool pumpActive;
+bool    sensorPolling;
+bool    fastSensorPolling;
+bool    bleActive;
+bool    pumpActive;
+
 
 
 /** Callbacks **/
@@ -76,21 +77,22 @@
         deactivateFastSensorPoll();
     bleActive = false;
     --usersConnected;
-//    printf("\r\n> BLE  : Disconnected. Advertising restarted.");
 }
 
 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)          // Callback for everytime the connection is established
 {
-    ble.gap().stopAdvertising();                                                // Stop advertising
-    activateFastSensorPoll();
-    bleActive = true;
-    ++usersConnected;
-//    printf("\r\n> BLE  : Connected to %x. Accept no subsequent connections.", params->peerAddr);
+    if(usersConnected>GB_USERS_CONNECTED_MAX)
+        ble.disconnect(params->handle, Gap::REMOTE_USER_TERMINATED_CONNECTION); // Disconnect automatically due to connection constraint
+    else
+    {
+        activateFastSensorPoll();
+        bleActive = true;
+        ++usersConnected;
+    }
 }
 
 void onBleInitError(BLE &ble, ble_error_t error)
 {
-//    printf("\r\n> BLE  : Init error encountered. Error returned: %d", error);
     errorLoop();
 }
 
@@ -105,7 +107,6 @@
     }
 
     if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {                         // If this is not default instance (double instanciation?)
-//        printf("\r\n> BLE  : BLE controller instance is invalid.");
         errorLoop();
     }
     
@@ -121,8 +122,6 @@
     ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
     ble.gap().setAdvertisingInterval(1000); /* 1000ms */
     ble.gap().startAdvertising();
-    
-//    printf("\r\n> BLE  : BLE Init done.");
 }
 
 // Helper functions for retrieving data from sensors
@@ -169,20 +168,10 @@
     fastSensorPolling = true;
 }
 
-void pumpActivateCallback(void)
-{
-    pumpActivate = true;
-}
-
-void pumpDeactivateCallback(void)
-{
-    pumpActivate = false;
-}
-
 void activateFastSensorPoll(void)
 {
     fastSensorPolling = true;
-    fastSensorPollTicker.attach(&fastSensorPollCallback, 0.9);
+    fastSensorPollTicker.attach(&fastSensorPollCallback, 0.9f);
 }
 
 void deactivateFastSensorPoll(void)
@@ -191,16 +180,32 @@
     fastSensorPollTicker.detach();
 }
 
+void pumpSetup(void)
+{
+    pumpPWM.write(1);
+    pumpPWM.period(2.0f);
+}
+
+void pumpActivateCallback(void)
+{
+    pumpPWM.write(0.7);
+}
+
+void pumpDeactivateCallback(void)
+{
+    pumpPWM.write(1);
+}
 
 void errorLoop(void)
 {
     sanityTicker.detach();
     sensorPollTicker.detach();
     ble.shutdown();
-//    printf("\r\n> ERROR : Error encountered. Infinite looping.");
+
     while(true)
     {
-        led1 != led1;        
+        led1 != led1;
+        printf("\n\n\n\n\n\n\n\n");
     }
 }
 
@@ -213,31 +218,22 @@
 /** Main loop **/
 int main(void)
 {
-    pumpPWM.write(1);
-    pumpPWM.period(1.0f);
+    pumpSetup();                                                                // Setup pump
     
-    printf("\r\n/**\r\n * Green Building Sensor Device: Debug Info\r\n */");
-    
-    sensorPolling = false;
+    sensorPolling     = false;
     fastSensorPolling = false;
-    pumpActivate = false;
-    waitOnce = true;
-    bleActive = false;
-    pumpActive = false;
+    bleActive         = false;
+    pumpActive        = false;
     
-    sanityTicker.attach(sanityCallback, 1.1);                                   // LED sanity checker
-    sensorPollTicker.attach(sensorPollCallback, 4.9);                           // Sensor poll ticker
-    
-    printf("\r\n> MAIN : Tickers initialized.");
+    sanityTicker.attach(sanityCallback, 1.1f);                                  // LED sanity checker
+    sensorPollTicker.attach(sensorPollCallback, 3559.9f);                       // Sensor poll ticker (1 hr too long?)
  
     volatile GreenBuildingService::PlantEnvironmentType_t peVal;                // Plant environment var
-    uint8_t pumpWaitTime = 3;                                                   // Pump waiting time
+    uint8_t pumpLimitCount = 0;                                                 // Pump limit counter
  
     ble.init(bleInitComplete);                                                  // Pass BLE init complete function upon init
     
-//    while(ble.hasInitialized() == false);
-    
-    printf("\r\n> MAIN : BLE Init procedure done.");
+//    while(ble.hasInitialized() == false);                                       // Buggy loop
     
     // Infinite loop
     while (true) {
@@ -254,42 +250,41 @@
             if(ble.getGapState().connected)                                     // Update characteristic if connected
                 gbServicePtr->updatePlantEnvironment(peVal);
             
-//            printf("\r\n> MAIN : Current soil moisture    = %d", peVal.soilMoisture);
-//            printf("\r\n> MAIN : Current air humidity     = %d", peVal.airHumidity);
-//            printf("\r\n> MAIN : Current air temperature  = %d", peVal.airTemperature);
             printf("%d\t%d\t%d\r\n", peVal.airTemperature, peVal.airHumidity, peVal.soilMoisture);
             
             // If moisture is below 50% of max when user is present
             //    or if less than 30% of max
+            //    and pump is not active
             if( ( ((peVal.soilMoisture < 0.5*GB_SOIL_MOISTURE_MAX) &&  ble.getGapState().connected)   ||
-                  ((peVal.soilMoisture < 0.3*GB_SOIL_MOISTURE_MAX) && !ble.getGapState().connected) ) &&
-                waitOnce
+                  ((peVal.soilMoisture < 0.3*GB_SOIL_MOISTURE_MAX) && !ble.getGapState().connected)   &&
+                  !pumpActive
+                )
             )
             {
-                pumpWaitTimeout.attach(&pumpActivateCallback, pumpWaitTime);    // Waiting time is hard coded but may be calculated, I think
                 activateFastSensorPoll();
-                waitOnce = false;
                 pumpActive = true;
-            }
-            else if((peVal.soilMoisture >= 0.6*GB_SOIL_MOISTURE_MAX) && pumpActivate) // Stop condition: when soil moisture is at 60% of max
-            {
-                pumpPWM.write(1);
-                pumpWaitTimeout.detach();
-                pumpDeactivateCallback();
-                if(!bleActive)
-                    deactivateFastSensorPoll();
-                waitOnce = true;
-                pumpActive = false;
+                // TODO: calculate pumpWaitTime ( pumpWaitTime = f(peVal.airHumidity, peVal.airTemperature) )
+                pumpWaitTimeout.attach(&pumpActivateCallback, pumpWaitTime);
             }
             
-            if(pumpActivate)
+            // Stop condition: when soil moisture is at 60% of max or after few pump cycles
+            if(pumpActive)
             {
-//                printf("\r\n> MAIN : Activating water pump.");
-                pumpPWM.write(0.7);                
-                pumpActivate = false;
-                pumpWaitTimeout.attach(&pumpActivateCallback, 1);
+                ++pumpLimitCount;
+                
+                if( (peVal.soilMoisture >= 0.6*GB_SOIL_MOISTURE_MAX) ||
+                    (pumpLimitCount>GB_PUMP_CYCLE_MAX)
+                )
+                {
+                    pumpWaitTimeout.detach();
+                    pumpDeactivateCallback();
+                    pumpActive = false;                                         // Something not right here...
+                    if(!bleActive)
+                        deactivateFastSensorPoll();
+                }
             }
             
+            
         }
         else
             ble.waitForEvent();                                                 //Low power wait for event