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
This branch is the main continuation of the original project. You can find it here.
Diff: main.cpp
- Revision:
- 0:7dce5e74ad91
- Child:
- 1:b30300f95d4a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sat Nov 26 13:38:23 2016 +0000 @@ -0,0 +1,224 @@ +/************************ STM32NUCLEO IOT Contest ****************************** + * + * Green Building IoT Solution for + * Plant Life Monitoring And Maintenance + * + * Authored by + * Dien Hoa Truong + * Muhammad Haziq Bin Kamarul Azman + * + * for the + * eSAME 2016 STM32NUCLEO IoT Contest in Sophia-Antipolis + * + * main.cpp | Program main + * + ******************************************************************************/ + +/** Includes **/ +#include "mbed.h" // ARM mbed library +#include "x_nucleo_iks01a1.h" // STM32NUCLEO board library +#include "ble/BLE.h" // Bluetooth LE library +#include "GreenBuildingService.h" // Green Building service library + + + +/** Defines **/ +#define GB_SOIL_MOISTURE_MAX 100 // Soil moisture threshold value + + + +/** Device declarations **/ + +// Board-specific +PwmOut pumpPWM(PB_10); // PWM motor control out pin +DigitalOut led1(LED1, 1); // Debug pin instance +AnalogIn moisture_sensor(A2); // 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 + +// 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}; +GreenBuildingService *gbServicePtr; // Service pointer + +// Program-specific +float getMoistureValue(); +float getHumidityValue(); +float getTemperatureValue(); +void errorLoop(void); + +Ticker sanityTicker; +Ticker sensorPollTicker; +bool sensorPolling; + + + +/** Callbacks **/ + +// BLE-specific callback +void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) // Callback for everytime the connection gets disconnected +{ + ble.gap().startAdvertising(); // Restart advertising +// 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 +// printf("\r\n> BLE : Connected to %x. Accept no subsequent connections.", params->peerAddr); +} + +void onBleInitError(BLE &ble, ble_error_t error) +{ +// printf("\r\n> BLE : Init error encountered. Error returned: %d", error); + errorLoop(); +} + +void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) +{ + BLE& ble = params->ble; + ble_error_t error = params->error; + + if (error != BLE_ERROR_NONE) { // Check to see init errors + onBleInitError(ble, error); + errorLoop(); + } + + if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { // If this is not default instance (double instanciation?) +// printf("\r\n> BLE : BLE controller instance is invalid."); + errorLoop(); + } + + ble.gap().onDisconnection(disconnectionCallback); // Register disconnection callback + ble.gap().onConnection(connectionCallback); // Register connection callback + + gbServicePtr = new GreenBuildingService(ble); // Init service with initial value + + /* Setup advertising. */ + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,(uint8_t *)uuid16_list, sizeof(uuid16_list)); + 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 +float getMoistureValue() +{ + float moisture = 0; + for (int i = 1;i<=10;i++) { + moisture += moisture_sensor.read(); // Get ten samples + } + moisture = moisture / 10; + moisture = moisture * 3300; // Change the value to be in the 0 to 3300 range + moisture = moisture / 33; // Convert to percentage + return moisture; +} + +float getHumidityValue() +{ + float humidity = 0; + humidity_sensor->GetHumidity(&humidity); + return humidity; +} + +float getTemperatureValue() +{ + float temperature = 0; + temp_sensor->GetTemperature(&temperature); + return temperature; +} + + +// Miscellaneous callbacks & functions +void sanityCallback(void) +{ + led1 = !led1; // Blink LED1 to indicate system sanity +} + +void sensorPollCallback(void) +{ + sensorPolling = true; +} + +void errorLoop(void) +{ + sanityTicker.detach(); + sensorPollTicker.detach(); + ble.shutdown(); + printf("\r\n> ERROR : Error encountered. Infinite looping."); + while(true) + { + led1 != led1; + } +} + + + +/** Pre-main inits **/ + + + +/** Main loop **/ +int main(void) +{ + printf("\r\n/**\r\n * Green Building Sensor Device: Debug Info\r\n */"); + + sensorPolling = false; + + sanityTicker.attach(sanityCallback, 1.1); // LED sanity checker + sensorPollTicker.attach(sensorPollCallback, 5); // Sensor poll ticker + + printf("\r\n> MAIN : Tickers initialized."); + + volatile GreenBuildingService::PlantEnvironmentType_t peVal; // Plant environment var + uint8_t pumpCount = 0; // Pump timer + + ble.init(bleInitComplete); // Pass BLE init complete function upon init + + while(ble.hasInitialized() == false); + + printf("\r\n> MAIN : BLE Init procedure done."); + + // Infinite loop + while (true) { + + if(sensorPolling) + { + sensorPolling = false; // Deassert polling bit + + peVal.soilMoisture = (uint8_t) getMoistureValue(); // Update all measurements + peVal.airHumidity = (uint8_t) getHumidityValue(); + peVal.airTemperature = (int8_t) getTemperatureValue(); + + 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("\r\n"); + + if (peVal.soilMoisture < 0.6*GB_SOIL_MOISTURE_MAX) // If moisture is below 60% of max + { + printf("\r\n> MAIN : Activating water pump."); + pumpPWM.write(1); // Activate pump + pumpCount = 0; + while((getMoistureValue()<0.75*GB_SOIL_MOISTURE_MAX)&&(pumpCount<40)) // Activate for 20s or until 75% max moisture + { + wait(0.5); + pumpCount++; + } + pumpPWM.write(0); + } + } + else + ble.waitForEvent(); // Low power wait for event + + } +}