![](/media/cache/group/default_image.jpg.50x50_q85.jpg)
This is a basic program that provides the necessary BLE service to allow communications with the UPAS
Dependencies: BLE_API mbed nRF51822 CronoDot EEPROM NCP5623BMUTBG ADS1115 BME280 Calibration_one MCP40D17 SDFileSystem LSM303 SI1145 STC3100
Fork of BLE_Button by
main.cpp@17:077712e4e5e3, 2015-12-04 (annotated)
- Committer:
- jelord
- Date:
- Fri Dec 04 22:08:09 2015 +0000
- Revision:
- 17:077712e4e5e3
- Parent:
- 16:e066ab7e8fb3
- Child:
- 18:c911a8928d0b
Code now works with app to turn on and off the UPAS based on sample start and end times. Currently no data logging is being done.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jelord | 10:66549fa08986 | 1 | //CODE BY JAKE LORD |
jelord | 10:66549fa08986 | 2 | //ALL RIGHTS RESERVED BY VOLCKENS GROUP, FORT COLLINS CO |
rgrover1 | 0:28f095301cb2 | 3 | #include "mbed.h" |
rgrover1 | 5:43a3ab27f2e4 | 4 | #include "BLE.h" |
jelord | 10:66549fa08986 | 5 | #include "UPAS_Service.h" |
jelord | 11:1058647c66e8 | 6 | #include "EEPROM.h" |
jelord | 11:1058647c66e8 | 7 | #include "CronoDot.h" |
jelord | 11:1058647c66e8 | 8 | #include "NCP5623BMUTBG.h" |
jelord | 13:b43ec7e0cc1d | 9 | |
jelord | 17:077712e4e5e3 | 10 | #include "SDFileSystem.h" |
jelord | 17:077712e4e5e3 | 11 | #include "Adafruit_ADS1015.h" |
jelord | 17:077712e4e5e3 | 12 | #include "MCP40D17.h" |
jelord | 17:077712e4e5e3 | 13 | #include "BME280.h" |
jelord | 17:077712e4e5e3 | 14 | #include "Calibration.h" |
jelord | 17:077712e4e5e3 | 15 | |
jelord | 17:077712e4e5e3 | 16 | //List of files not currently in this Code |
jelord | 17:077712e4e5e3 | 17 | //#include "LSM303.h" |
jelord | 17:077712e4e5e3 | 18 | //#include "SI1145.h" |
jelord | 17:077712e4e5e3 | 19 | //#include "STC3100.h" |
jelord | 17:077712e4e5e3 | 20 | //#include "US_Menu.h" |
jelord | 17:077712e4e5e3 | 21 | |
jelord | 17:077712e4e5e3 | 22 | |
rgrover1 | 0:28f095301cb2 | 23 | |
jelord | 11:1058647c66e8 | 24 | DigitalOut blower(p29, 0); |
jelord | 11:1058647c66e8 | 25 | DigitalOut pbKill(p18, 1); |
jelord | 11:1058647c66e8 | 26 | DigitalOut GPS_EN(p4,0); |
jelord | 11:1058647c66e8 | 27 | EEPROM E2PROM(p22, p20); |
jelord | 11:1058647c66e8 | 28 | CronoDot RTC(p22, p20); |
jelord | 12:27273e6a50b3 | 29 | NCP5623BMUTBG RGB_LED(p22, p20); |
jelord | 16:e066ab7e8fb3 | 30 | |
jelord | 17:077712e4e5e3 | 31 | |
jelord | 17:077712e4e5e3 | 32 | |
jelord | 17:077712e4e5e3 | 33 | I2C i2c(p22, p20); |
jelord | 17:077712e4e5e3 | 34 | Adafruit_ADS1115 ads(&i2c); |
jelord | 17:077712e4e5e3 | 35 | Calibration calibrations(1); //Default serial/calibration if there are no values for the selected option |
jelord | 17:077712e4e5e3 | 36 | |
jelord | 17:077712e4e5e3 | 37 | |
jelord | 16:e066ab7e8fb3 | 38 | BLE ble; |
jelord | 11:1058647c66e8 | 39 | /*EEPROM ADDRESSING: |
jelord | 11:1058647c66e8 | 40 | 0:Status bit-Unused |
jelord | 11:1058647c66e8 | 41 | 1-15:Device Name |
jelord | 11:1058647c66e8 | 42 | 16-19:Flow Rate |
jelord | 11:1058647c66e8 | 43 | 20: Data Log Interval |
jelord | 11:1058647c66e8 | 44 | 21-26: Start Time: ssmmHHddMMyy |
jelord | 11:1058647c66e8 | 45 | 27-32: Stop Time: ssmmHHddMMyy |
jelord | 11:1058647c66e8 | 46 | 33: Duty Up |
jelord | 11:1058647c66e8 | 47 | 34: Duty Down |
jelord | 11:1058647c66e8 | 48 | 35-38: Home Latitude |
jelord | 11:1058647c66e8 | 49 | 39-42: Home Longitude |
jelord | 11:1058647c66e8 | 50 | 43-46: Work Latitude |
jelord | 11:1058647c66e8 | 51 | 47-50: Work Longitude |
jelord | 11:1058647c66e8 | 52 | 51: Runready: Currently useless, should be 0 |
jelord | 11:1058647c66e8 | 53 | 52-53: Device Calibration |
jelord | 11:1058647c66e8 | 54 | 54: Consider RunReady |
jelord | 11:1058647c66e8 | 55 | 55-56: Menu Options |
jelord | 11:1058647c66e8 | 56 | 57+ Nothing*/ |
rgrover1 | 0:28f095301cb2 | 57 | |
jelord | 17:077712e4e5e3 | 58 | Timeout stop; //This is the stop call back object |
jelord | 17:077712e4e5e3 | 59 | Timeout logg; //This is the logging call back object |
jelord | 17:077712e4e5e3 | 60 | |
jelord | 17:077712e4e5e3 | 61 | uint16_t serial_num = 1; // Default serial/calibration number |
jelord | 17:077712e4e5e3 | 62 | int RunReady =0; |
jelord | 17:077712e4e5e3 | 63 | |
jelord | 17:077712e4e5e3 | 64 | |
jelord | 10:66549fa08986 | 65 | const static char DEVICE_NAME[] = "UPAS"; //Will hold the actual name of the whichever UPAS is being connected to |
jelord | 10:66549fa08986 | 66 | static const uint16_t uuid16_list[] = {UPAS_Service::UPAS_SERVICE_UUID}; //Currently a custom 16-bit representation of 128-bit UUID |
rgrover1 | 0:28f095301cb2 | 67 | |
jelord | 10:66549fa08986 | 68 | UPAS_Service *upasServicePtr; |
rgrover1 | 0:28f095301cb2 | 69 | |
jelord | 12:27273e6a50b3 | 70 | |
jelord | 17:077712e4e5e3 | 71 | |
jelord | 10:66549fa08986 | 72 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)//Code called when mbed ble senses a disconnect |
rgrover1 | 0:28f095301cb2 | 73 | { |
rgrover1 | 6:18d8750f39ee | 74 | ble.gap().startAdvertising(); |
rgrover1 | 0:28f095301cb2 | 75 | } |
rgrover1 | 0:28f095301cb2 | 76 | |
rgrover1 | 0:28f095301cb2 | 77 | void periodicCallback(void) |
rgrover1 | 0:28f095301cb2 | 78 | { |
jelord | 12:27273e6a50b3 | 79 | RTC.get_time(); |
jelord | 12:27273e6a50b3 | 80 | const uint8_t refreshPassValues[6] = {RTC.seconds, RTC.minutes,RTC.hour,RTC.date,RTC.month,RTC.year}; |
jelord | 12:27273e6a50b3 | 81 | ble.updateCharacteristicValue( upasServicePtr->rtcCharacteristic.getValueHandle(),refreshPassValues,6); |
jelord | 17:077712e4e5e3 | 82 | |
jelord | 17:077712e4e5e3 | 83 | } |
jelord | 17:077712e4e5e3 | 84 | void periodicPrint(void) |
jelord | 17:077712e4e5e3 | 85 | { |
jelord | 17:077712e4e5e3 | 86 | // led1 = !led1; /* Do blinky on LED1 to indicate system aliveness. */ |
jelord | 17:077712e4e5e3 | 87 | //RGB_LED.set_led(1,1,5); |
jelord | 17:077712e4e5e3 | 88 | |
jelord | 11:1058647c66e8 | 89 | } |
jelord | 13:b43ec7e0cc1d | 90 | |
jelord | 17:077712e4e5e3 | 91 | /* |
jelord | 17:077712e4e5e3 | 92 | This function is called the BLE GATT Server every time a characterisitic is written to |
jelord | 17:077712e4e5e3 | 93 | All logic revolving around which bits to write to EEPROM, and what to see the RTC to us done here |
jelord | 17:077712e4e5e3 | 94 | */ |
jelord | 12:27273e6a50b3 | 95 | void writeCharacteristicCallback(const GattWriteCallbackParams *params) |
jelord | 10:66549fa08986 | 96 | { |
jelord | 12:27273e6a50b3 | 97 | uint8_t *writeData = const_cast<uint8_t*>(params->data); |
jelord | 10:66549fa08986 | 98 | // check to see what characteristic was written, by handle |
jelord | 12:27273e6a50b3 | 99 | if(params->handle == upasServicePtr->rtcCharacteristic.getValueHandle()) { |
jelord | 12:27273e6a50b3 | 100 | |
jelord | 12:27273e6a50b3 | 101 | //ble.updateCharacteristicValue(upasServicePtr->readChar.getValueHandle(),params->data,params->len); |
jelord | 12:27273e6a50b3 | 102 | |
jelord | 17:077712e4e5e3 | 103 | E2PROM.write(0x00015, writeData+6, 12); |
jelord | 11:1058647c66e8 | 104 | RTC.set_time(writeData[0],writeData[1],writeData[2],writeData[3],writeData[3],writeData[4],writeData[5]); |
jelord | 12:27273e6a50b3 | 105 | |
jelord | 12:27273e6a50b3 | 106 | }else if(params->handle == upasServicePtr->sampleTimeCharacteristic.getValueHandle()){ |
jelord | 12:27273e6a50b3 | 107 | |
jelord | 12:27273e6a50b3 | 108 | E2PROM.write(0x00015, writeData, 12); |
jelord | 13:b43ec7e0cc1d | 109 | |
jelord | 13:b43ec7e0cc1d | 110 | }else if(params->handle == upasServicePtr->subjectLabelCharacteristic.getValueHandle()){ |
jelord | 13:b43ec7e0cc1d | 111 | E2PROM.write(0x00001,writeData,15); |
jelord | 13:b43ec7e0cc1d | 112 | |
jelord | 15:c9c93454dd56 | 113 | }else if(params->handle == upasServicePtr->runReadyCharacteristic.getValueHandle()){ |
jelord | 17:077712e4e5e3 | 114 | uint8_t runData = writeData[0]; |
jelord | 17:077712e4e5e3 | 115 | |
jelord | 17:077712e4e5e3 | 116 | if(runData == 10){ |
jelord | 17:077712e4e5e3 | 117 | RunReady = 10; |
jelord | 17:077712e4e5e3 | 118 | RGB_LED.set_led(1,2,3); |
jelord | 17:077712e4e5e3 | 119 | }else{ |
jelord | 17:077712e4e5e3 | 120 | RunReady = 2; |
jelord | 17:077712e4e5e3 | 121 | } |
jelord | 13:b43ec7e0cc1d | 122 | |
jelord | 14:4fc1788b8ad2 | 123 | }else if(params->handle == upasServicePtr->runModeCharacteristic.getValueHandle()){ |
jelord | 13:b43ec7e0cc1d | 124 | /* Trigger demo mode*/ |
jelord | 13:b43ec7e0cc1d | 125 | RGB_LED.set_led(3,1,0); |
jelord | 14:4fc1788b8ad2 | 126 | E2PROM.write(0x00036,writeData,1); |
jelord | 10:66549fa08986 | 127 | } |
jelord | 10:66549fa08986 | 128 | } |
jelord | 10:66549fa08986 | 129 | |
rgrover1 | 0:28f095301cb2 | 130 | int main(void) |
rgrover1 | 0:28f095301cb2 | 131 | { |
rgrover1 | 0:28f095301cb2 | 132 | Ticker ticker; |
jelord | 17:077712e4e5e3 | 133 | ticker.attach(periodicPrint, 600); //currently unused. But do not want to comment out |
jelord | 11:1058647c66e8 | 134 | RGB_LED.set_led(1,1,1); |
jelord | 11:1058647c66e8 | 135 | RTC.get_time(); |
jelord | 12:27273e6a50b3 | 136 | uint8_t rtcPassValues[6] = {RTC.seconds, RTC.minutes,RTC.hour,RTC.date,RTC.month,RTC.year}; |
jelord | 12:27273e6a50b3 | 137 | uint8_t sampleTimePassValues[12] = {0,}; |
jelord | 12:27273e6a50b3 | 138 | uint8_t subjectLabelOriginal[15] = {0,}; |
jelord | 12:27273e6a50b3 | 139 | E2PROM.read(0x00015, sampleTimePassValues, 12); |
jelord | 12:27273e6a50b3 | 140 | E2PROM.read(0x00001, subjectLabelOriginal,15); |
rgrover1 | 0:28f095301cb2 | 141 | |
rgrover1 | 0:28f095301cb2 | 142 | ble.init(); |
rgrover1 | 6:18d8750f39ee | 143 | ble.gap().onDisconnection(disconnectionCallback); |
jelord | 12:27273e6a50b3 | 144 | ble.gattServer().onDataWritten(writeCharacteristicCallback); //add writeCharCallback (custom function) to whenever data is being written to device |
jelord | 12:27273e6a50b3 | 145 | UPAS_Service upasService(ble, false,rtcPassValues,sampleTimePassValues,subjectLabelOriginal); //Create a GattService that is defined in UPAS_Service.h |
jelord | 10:66549fa08986 | 146 | upasServicePtr = &upasService; //Create a pointer to the service (Allows advertisement without specifically adding the service |
rgrover1 | 0:28f095301cb2 | 147 | |
jelord | 10:66549fa08986 | 148 | /* setup advertising |
jelord | 10:66549fa08986 | 149 | Following lines do the follow: |
jelord | 10:66549fa08986 | 150 | 1:Declare the device as Bluetooth Smart(Low-Energy) |
jelord | 10:66549fa08986 | 151 | 2.Advertise the UPAS service that will send and receive the 57-bits of settable values in the UPAS EEPROM |
jelord | 10:66549fa08986 | 152 | 3.Advertise the name that will be associated with the UPAS |
jelord | 10:66549fa08986 | 153 | 4.Allow the UPAS to advertise unrestricted (this might change) */ |
jelord | 10:66549fa08986 | 154 | |
rgrover1 | 6:18d8750f39ee | 155 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); |
rgrover1 | 6:18d8750f39ee | 156 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); |
rgrover1 | 6:18d8750f39ee | 157 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
rgrover1 | 6:18d8750f39ee | 158 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
jelord | 17:077712e4e5e3 | 159 | ble.gap().setAdvertisingInterval(30); /* 160ms. */ |
rgrover1 | 6:18d8750f39ee | 160 | ble.gap().startAdvertising(); |
jelord | 10:66549fa08986 | 161 | |
jelord | 10:66549fa08986 | 162 | //Loop keeps device in infinite loop waiting for events to occur |
jelord | 13:b43ec7e0cc1d | 163 | while (1) { |
jelord | 17:077712e4e5e3 | 164 | ble.waitForEvent(); |
jelord | 17:077712e4e5e3 | 165 | if(RunReady==2 && blower ==0){ //Code used to see if one-click run should begin |
jelord | 17:077712e4e5e3 | 166 | calibrations.initialize(serial_num); |
jelord | 17:077712e4e5e3 | 167 | RGB_LED.set_led(3,0,2); |
jelord | 17:077712e4e5e3 | 168 | blower=1; |
jelord | 17:077712e4e5e3 | 169 | RunReady=0; |
jelord | 17:077712e4e5e3 | 170 | } |
jelord | 17:077712e4e5e3 | 171 | if(RunReady==2 && blower ==1){ //Code used to see if one-click run is done. |
jelord | 17:077712e4e5e3 | 172 | blower=0; |
jelord | 17:077712e4e5e3 | 173 | RunReady=0; |
jelord | 17:077712e4e5e3 | 174 | } |
jelord | 17:077712e4e5e3 | 175 | |
jelord | 17:077712e4e5e3 | 176 | if(RunReady==10){ //Check to see if app is done with configurations |
jelord | 17:077712e4e5e3 | 177 | blower = 0; |
jelord | 17:077712e4e5e3 | 178 | ble.gap().stopAdvertising(); |
jelord | 17:077712e4e5e3 | 179 | break; |
jelord | 17:077712e4e5e3 | 180 | } |
rgrover1 | 0:28f095301cb2 | 181 | } |
jelord | 17:077712e4e5e3 | 182 | uint8_t startAndEndTime[12] = {0,}; |
jelord | 17:077712e4e5e3 | 183 | E2PROM.read(0x00015, startAndEndTime, 12); //Grab start and end times from EEPROM |
jelord | 17:077712e4e5e3 | 184 | while(!RTC.compare(startAndEndTime[0], startAndEndTime[1], startAndEndTime[2], startAndEndTime[3], startAndEndTime[4], startAndEndTime[5])) { // this while waits for the start time by looping until the start time |
jelord | 17:077712e4e5e3 | 185 | wait(0.5); |
jelord | 17:077712e4e5e3 | 186 | RTC.get_time(); |
jelord | 17:077712e4e5e3 | 187 | |
jelord | 17:077712e4e5e3 | 188 | } |
jelord | 17:077712e4e5e3 | 189 | calibrations.initialize(serial_num); |
jelord | 17:077712e4e5e3 | 190 | blower=1; |
jelord | 17:077712e4e5e3 | 191 | |
jelord | 17:077712e4e5e3 | 192 | while(!RTC.compare(startAndEndTime[6], startAndEndTime[7], startAndEndTime[8], startAndEndTime[9], startAndEndTime[10], startAndEndTime[11])) { //Waits for end time |
jelord | 17:077712e4e5e3 | 193 | wait(0.5); |
jelord | 17:077712e4e5e3 | 194 | RTC.get_time(); |
jelord | 17:077712e4e5e3 | 195 | |
jelord | 17:077712e4e5e3 | 196 | } |
jelord | 17:077712e4e5e3 | 197 | pbKill = 0; // this is were we shut everything down |
jelord | 17:077712e4e5e3 | 198 | |
rgrover1 | 0:28f095301cb2 | 199 | } |