prototype.

Dependencies:   BLE_API_Native_IRC TMP102 beep mbed

Fork of BLE_Health_Thermometer_IRC by Yoshihiro TSUBOI

Committer:
MasanoriSakai
Date:
Mon Aug 25 13:42:31 2014 +0000
Revision:
5:01a978ee3cc1
Parent:
2:f11df1469db2
First revision from sample program.;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
donalm 0:701da26ee5cb 1 /* mbed Microcontroller Library
donalm 0:701da26ee5cb 2 * Copyright (c) 2006-2014 ARM Limited
donalm 0:701da26ee5cb 3 *
donalm 0:701da26ee5cb 4 * Licensed under the Apache License, Version 2.0 (the "License");
donalm 0:701da26ee5cb 5 * you may not use this file except in compliance with the License.
donalm 0:701da26ee5cb 6 * You may obtain a copy of the License at
donalm 0:701da26ee5cb 7 *
donalm 0:701da26ee5cb 8 * http://www.apache.org/licenses/LICENSE-2.0
donalm 0:701da26ee5cb 9 *
donalm 0:701da26ee5cb 10 * Unless required by applicable law or agreed to in writing, software
donalm 0:701da26ee5cb 11 * distributed under the License is distributed on an "AS IS" BASIS,
donalm 0:701da26ee5cb 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
donalm 0:701da26ee5cb 13 * See the License for the specific language governing permissions and
donalm 0:701da26ee5cb 14 * limitations under the License.
donalm 0:701da26ee5cb 15 */
donalm 0:701da26ee5cb 16
donalm 0:701da26ee5cb 17 #include "mbed.h"
donalm 0:701da26ee5cb 18 #include "TMP102.h"
donalm 0:701da26ee5cb 19 #include "nRF51822n.h"
MasanoriSakai 5:01a978ee3cc1 20 #include "beep.h"
donalm 0:701da26ee5cb 21
donalm 0:701da26ee5cb 22 nRF51822n nrf; /* BLE radio driver */
donalm 0:701da26ee5cb 23 TMP102 healthThemometer(p22, p20, 0x90); /* The TMP102 connected to our board */
MasanoriSakai 5:01a978ee3cc1 24 I2C i2c(p22,p20);
MasanoriSakai 5:01a978ee3cc1 25 Beep buzzer(p15);
donalm 0:701da26ee5cb 26
donalm 2:f11df1469db2 27 /* LEDs for indication: */
donalm 2:f11df1469db2 28 DigitalOut oneSecondLed(LED1); /* LED1 is toggled every second. */
donalm 2:f11df1469db2 29 DigitalOut advertisingStateLed(LED2); /* LED2 is on when we are advertising, otherwise off. */
donalm 0:701da26ee5cb 30
donalm 0:701da26ee5cb 31
MasanoriSakai 5:01a978ee3cc1 32
donalm 0:701da26ee5cb 33 /* Health Thermometer Service */
donalm 0:701da26ee5cb 34 uint8_t thermTempPayload[5] = { 0, 0, 0, 0, 0 };
donalm 0:701da26ee5cb 35 GattService thermService (GattService::UUID_HEALTH_THERMOMETER_SERVICE);
donalm 0:701da26ee5cb 36 GattCharacteristic thermTemp (GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR,
donalm 0:701da26ee5cb 37 5, 5, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
donalm 0:701da26ee5cb 38
donalm 0:701da26ee5cb 39 /* Battery Level Service */
donalm 0:701da26ee5cb 40 uint8_t batt = 100; /* Battery level */
donalm 0:701da26ee5cb 41 uint8_t read_batt = 0; /* Variable to hold battery level reads */
donalm 0:701da26ee5cb 42 GattService battService ( GattService::UUID_BATTERY_SERVICE );
donalm 0:701da26ee5cb 43 GattCharacteristic battLevel ( GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, 1, 1,
donalm 0:701da26ee5cb 44 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY |
donalm 0:701da26ee5cb 45 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
donalm 0:701da26ee5cb 46
donalm 0:701da26ee5cb 47
donalm 0:701da26ee5cb 48 /* Advertising data and parameters */
donalm 0:701da26ee5cb 49 GapAdvertisingData advData;
donalm 0:701da26ee5cb 50 GapAdvertisingData scanResponse;
donalm 0:701da26ee5cb 51 GapAdvertisingParams advParams ( GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED );
donalm 2:f11df1469db2 52
donalm 0:701da26ee5cb 53 uint16_t uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE,
donalm 0:701da26ee5cb 54 GattService::UUID_BATTERY_SERVICE};
donalm 0:701da26ee5cb 55
donalm 0:701da26ee5cb 56 uint32_t quick_ieee11073_from_float(float temperature);
donalm 0:701da26ee5cb 57 void updateServiceValues(void);
donalm 0:701da26ee5cb 58
MasanoriSakai 5:01a978ee3cc1 59 /*
MasanoriSakai 5:01a978ee3cc1 60 I2C LCD
MasanoriSakai 5:01a978ee3cc1 61 */
MasanoriSakai 5:01a978ee3cc1 62 const int AQCM0802_addr = 0x7C;
MasanoriSakai 5:01a978ee3cc1 63
MasanoriSakai 5:01a978ee3cc1 64 unsigned char mode;
MasanoriSakai 5:01a978ee3cc1 65 unsigned char contrast = 35; // 0-63
MasanoriSakai 5:01a978ee3cc1 66 unsigned char contrastFlag = false;
MasanoriSakai 5:01a978ee3cc1 67 int CGcounter;
MasanoriSakai 5:01a978ee3cc1 68 int FADEcounter;
MasanoriSakai 5:01a978ee3cc1 69
MasanoriSakai 5:01a978ee3cc1 70 void lcd_cmd(char x) {
MasanoriSakai 5:01a978ee3cc1 71 char data[2];
MasanoriSakai 5:01a978ee3cc1 72 data[0] = 0x00; // CO = 0,RS = 0
MasanoriSakai 5:01a978ee3cc1 73 data[1] = x;
MasanoriSakai 5:01a978ee3cc1 74 i2c.write(AQCM0802_addr, data, 2);
MasanoriSakai 5:01a978ee3cc1 75 }
MasanoriSakai 5:01a978ee3cc1 76
MasanoriSakai 5:01a978ee3cc1 77 void lcd_contdata(char x) {
MasanoriSakai 5:01a978ee3cc1 78 char data[2];
MasanoriSakai 5:01a978ee3cc1 79 data[0] = 0xC0; //0b11000000 CO = 1, RS = 1
MasanoriSakai 5:01a978ee3cc1 80 data[1] = x;
MasanoriSakai 5:01a978ee3cc1 81 i2c.write(AQCM0802_addr, data, 2);
MasanoriSakai 5:01a978ee3cc1 82 }
MasanoriSakai 5:01a978ee3cc1 83
MasanoriSakai 5:01a978ee3cc1 84 void lcd_lastdata(char x) {
MasanoriSakai 5:01a978ee3cc1 85 char data[2];
MasanoriSakai 5:01a978ee3cc1 86 data[0] = 0x40; //0b11000000 CO = 0, RS = 1
MasanoriSakai 5:01a978ee3cc1 87 data[1] = x;
MasanoriSakai 5:01a978ee3cc1 88 i2c.write(AQCM0802_addr, data, 2);
MasanoriSakai 5:01a978ee3cc1 89 }
MasanoriSakai 5:01a978ee3cc1 90
MasanoriSakai 5:01a978ee3cc1 91 void lcd_printStr(const char *s) {
MasanoriSakai 5:01a978ee3cc1 92 while(*s) {
MasanoriSakai 5:01a978ee3cc1 93 if(*(s + 1)) {
MasanoriSakai 5:01a978ee3cc1 94 lcd_contdata(*s);
MasanoriSakai 5:01a978ee3cc1 95 } else {
MasanoriSakai 5:01a978ee3cc1 96 lcd_lastdata(*s);
MasanoriSakai 5:01a978ee3cc1 97 }
MasanoriSakai 5:01a978ee3cc1 98 s++;
MasanoriSakai 5:01a978ee3cc1 99 }
MasanoriSakai 5:01a978ee3cc1 100 }
MasanoriSakai 5:01a978ee3cc1 101
MasanoriSakai 5:01a978ee3cc1 102 void lcd_printHex(unsigned char num) {
MasanoriSakai 5:01a978ee3cc1 103 lcd_contdata(num);
MasanoriSakai 5:01a978ee3cc1 104 }
MasanoriSakai 5:01a978ee3cc1 105
MasanoriSakai 5:01a978ee3cc1 106 void lcd_init() {
MasanoriSakai 5:01a978ee3cc1 107 wait(0.04);
MasanoriSakai 5:01a978ee3cc1 108 // LCD initialize
MasanoriSakai 5:01a978ee3cc1 109 lcd_cmd(0x38); // function set
MasanoriSakai 5:01a978ee3cc1 110 lcd_cmd(0x39); // function set
MasanoriSakai 5:01a978ee3cc1 111 lcd_cmd(0x04); // EntryModeSet
MasanoriSakai 5:01a978ee3cc1 112 lcd_cmd(0x14); // interval osc
MasanoriSakai 5:01a978ee3cc1 113 lcd_cmd(0x70 | (contrast & 0xF)); // contrast Low
MasanoriSakai 5:01a978ee3cc1 114 lcd_cmd(0x5C | ((contrast >> 4) & 0x3)); // contast High/icon/power
MasanoriSakai 5:01a978ee3cc1 115 lcd_cmd(0x6C); // follower control
MasanoriSakai 5:01a978ee3cc1 116 wait(0.2);
MasanoriSakai 5:01a978ee3cc1 117 lcd_cmd(0x38); // function set
MasanoriSakai 5:01a978ee3cc1 118 lcd_cmd(0x0C); // Display On
MasanoriSakai 5:01a978ee3cc1 119 lcd_cmd(0x01); // Clear Display
MasanoriSakai 5:01a978ee3cc1 120 wait(0.2); // need additional wait to Clear Display
MasanoriSakai 5:01a978ee3cc1 121 }
MasanoriSakai 5:01a978ee3cc1 122
MasanoriSakai 5:01a978ee3cc1 123 void lcd_setCursor(unsigned char x,unsigned char y) {
MasanoriSakai 5:01a978ee3cc1 124 lcd_cmd(0x80 | (y * 0x40 + x));
MasanoriSakai 5:01a978ee3cc1 125 }
MasanoriSakai 5:01a978ee3cc1 126
MasanoriSakai 5:01a978ee3cc1 127 void setContrast(unsigned char c) {
MasanoriSakai 5:01a978ee3cc1 128 lcd_cmd(0x39);
MasanoriSakai 5:01a978ee3cc1 129 lcd_cmd(0x70 | (c & 0x0f)); // contrast Low
MasanoriSakai 5:01a978ee3cc1 130 lcd_cmd(0x5C | ((c >> 4) & 0x03)); // contast High/icon/power
MasanoriSakai 5:01a978ee3cc1 131 lcd_cmd(0x38);
MasanoriSakai 5:01a978ee3cc1 132 }
MasanoriSakai 5:01a978ee3cc1 133
MasanoriSakai 5:01a978ee3cc1 134
donalm 0:701da26ee5cb 135 /**************************************************************************/
donalm 0:701da26ee5cb 136 /*!
donalm 0:701da26ee5cb 137 @brief This custom class can be used to override any GapEvents
donalm 0:701da26ee5cb 138 that you are interested in handling on an application level.
donalm 0:701da26ee5cb 139 */
donalm 0:701da26ee5cb 140 /**************************************************************************/
donalm 0:701da26ee5cb 141 class GapEventHandler : public GapEvents
donalm 0:701da26ee5cb 142 {
donalm 2:f11df1469db2 143 //virtual void onTimeout(void) {}
donalm 2:f11df1469db2 144
donalm 0:701da26ee5cb 145 virtual void onConnected(void)
donalm 0:701da26ee5cb 146 {
MasanoriSakai 5:01a978ee3cc1 147 advertisingStateLed = 1;
MasanoriSakai 5:01a978ee3cc1 148 buzzer.beep(440000.0,1);
MasanoriSakai 5:01a978ee3cc1 149
donalm 0:701da26ee5cb 150 }
donalm 0:701da26ee5cb 151
donalm 2:f11df1469db2 152 /* When a client device disconnects we need to start advertising again. */
donalm 0:701da26ee5cb 153 virtual void onDisconnected(void)
donalm 0:701da26ee5cb 154 {
donalm 0:701da26ee5cb 155 nrf.getGap().startAdvertising(advParams);
MasanoriSakai 5:01a978ee3cc1 156 advertisingStateLed = 0;
donalm 0:701da26ee5cb 157 }
donalm 0:701da26ee5cb 158 };
donalm 0:701da26ee5cb 159
donalm 0:701da26ee5cb 160 /**************************************************************************/
donalm 0:701da26ee5cb 161 /*!
donalm 0:701da26ee5cb 162 @brief Program entry point
donalm 0:701da26ee5cb 163 */
donalm 0:701da26ee5cb 164 /**************************************************************************/
donalm 0:701da26ee5cb 165 int main(void)
MasanoriSakai 5:01a978ee3cc1 166 {
donalm 2:f11df1469db2 167 /* Setup blinky led */
donalm 2:f11df1469db2 168 oneSecondLed=1;
donalm 0:701da26ee5cb 169
donalm 2:f11df1469db2 170 /* Setup an event handler for GAP events i.e. Client/Server connection events. */
donalm 0:701da26ee5cb 171 nrf.getGap().setEventHandler(new GapEventHandler());
donalm 2:f11df1469db2 172
donalm 0:701da26ee5cb 173 /* Initialise the nRF51822 */
donalm 0:701da26ee5cb 174 nrf.init();
donalm 0:701da26ee5cb 175
donalm 0:701da26ee5cb 176 /* Make sure we get a clean start */
donalm 0:701da26ee5cb 177 nrf.reset();
donalm 0:701da26ee5cb 178
donalm 0:701da26ee5cb 179 /* Add BLE-Only flag and complete service list to the advertising data */
donalm 0:701da26ee5cb 180 advData.addFlags(GapAdvertisingData::BREDR_NOT_SUPPORTED);
donalm 0:701da26ee5cb 181 advData.addData(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,
donalm 0:701da26ee5cb 182 (uint8_t*)uuid16_list, sizeof(uuid16_list));
donalm 0:701da26ee5cb 183 advData.addAppearance(GapAdvertisingData::GENERIC_THERMOMETER);
donalm 0:701da26ee5cb 184 nrf.getGap().setAdvertisingData(advData, scanResponse);
donalm 0:701da26ee5cb 185
donalm 0:701da26ee5cb 186 /* Health Thermometer Service */
donalm 0:701da26ee5cb 187 thermService.addCharacteristic(thermTemp);
donalm 0:701da26ee5cb 188 nrf.getGattServer().addService(thermService);
donalm 0:701da26ee5cb 189
donalm 0:701da26ee5cb 190 /* Add the Battery Level service */
donalm 0:701da26ee5cb 191 battService.addCharacteristic(battLevel);
donalm 0:701da26ee5cb 192 nrf.getGattServer().addService(battService);
donalm 0:701da26ee5cb 193
donalm 0:701da26ee5cb 194 /* Start advertising (make sure you've added all your data first) */
donalm 0:701da26ee5cb 195 nrf.getGap().startAdvertising(advParams);
MasanoriSakai 5:01a978ee3cc1 196 advertisingStateLed = 0;
MasanoriSakai 5:01a978ee3cc1 197
MasanoriSakai 5:01a978ee3cc1 198 /* i2c lcd initialize */
MasanoriSakai 5:01a978ee3cc1 199 lcd_init();
MasanoriSakai 5:01a978ee3cc1 200 lcd_setCursor(0, 0);
MasanoriSakai 5:01a978ee3cc1 201 lcd_printStr("Start ");
donalm 0:701da26ee5cb 202
donalm 0:701da26ee5cb 203 for (;;)
donalm 0:701da26ee5cb 204 {
donalm 2:f11df1469db2 205 /* Now that we're live, update the battery level & temperature characteristics */
donalm 2:f11df1469db2 206 updateServiceValues();
donalm 0:701da26ee5cb 207 wait(1);
donalm 0:701da26ee5cb 208 }
donalm 0:701da26ee5cb 209 }
donalm 0:701da26ee5cb 210
donalm 0:701da26ee5cb 211 /**************************************************************************/
donalm 0:701da26ee5cb 212 /*!
donalm 2:f11df1469db2 213 @brief Ticker callback to switch advertisingStateLed state
donalm 0:701da26ee5cb 214 */
donalm 0:701da26ee5cb 215 /**************************************************************************/
donalm 0:701da26ee5cb 216 void updateServiceValues(void)
donalm 0:701da26ee5cb 217 {
MasanoriSakai 5:01a978ee3cc1 218 char tempstring[6];
MasanoriSakai 5:01a978ee3cc1 219 AnalogIn thermister(p2);
MasanoriSakai 5:01a978ee3cc1 220 float B=4250,T0=298.15,R0=100.0,R1=10,rr1,t;
MasanoriSakai 5:01a978ee3cc1 221 int n;
MasanoriSakai 5:01a978ee3cc1 222
donalm 2:f11df1469db2 223 /* Toggle the one second LEDs */
donalm 2:f11df1469db2 224 oneSecondLed = !oneSecondLed;
donalm 0:701da26ee5cb 225
donalm 0:701da26ee5cb 226 /* Update battery level */
donalm 0:701da26ee5cb 227 nrf.getGattServer().updateValue(battLevel.handle, (uint8_t*)&batt, sizeof(batt));
donalm 2:f11df1469db2 228 /* Decrement the battery level. */
donalm 2:f11df1469db2 229 batt <=50 ? batt=100 : batt--;;
MasanoriSakai 5:01a978ee3cc1 230
MasanoriSakai 5:01a978ee3cc1 231 n = thermister.read_u16();
MasanoriSakai 5:01a978ee3cc1 232 rr1=R1*n/(1023.0-n);
MasanoriSakai 5:01a978ee3cc1 233 t=1/(log(rr1/R0)/B+(1/T0));
MasanoriSakai 5:01a978ee3cc1 234
donalm 2:f11df1469db2 235 /* Update the temperature. Note that we need to convert to an ieee11073 format float. */
MasanoriSakai 5:01a978ee3cc1 236 float temperature = healthThemometer.read();
MasanoriSakai 5:01a978ee3cc1 237 uint32_t temp_ieee11073 = quick_ieee11073_from_float(t-275.15);
donalm 0:701da26ee5cb 238 memcpy(thermTempPayload+1, &temp_ieee11073, 4);
donalm 0:701da26ee5cb 239 nrf.getGattServer().updateValue(thermTemp.handle, thermTempPayload, sizeof(thermTempPayload));
MasanoriSakai 5:01a978ee3cc1 240
MasanoriSakai 5:01a978ee3cc1 241 lcd_setCursor(0,0);
MasanoriSakai 5:01a978ee3cc1 242 lcd_printStr(" ");
MasanoriSakai 5:01a978ee3cc1 243 sprintf(tempstring,"T=%05.2f", t-275.15);
MasanoriSakai 5:01a978ee3cc1 244 lcd_setCursor(0,0);
MasanoriSakai 5:01a978ee3cc1 245 lcd_printStr(tempstring);
MasanoriSakai 5:01a978ee3cc1 246
MasanoriSakai 5:01a978ee3cc1 247 sprintf(tempstring,"S=%05.2f",temperature);
MasanoriSakai 5:01a978ee3cc1 248 lcd_setCursor(0,1);
MasanoriSakai 5:01a978ee3cc1 249 lcd_printStr(" ");
MasanoriSakai 5:01a978ee3cc1 250 lcd_setCursor(0,1);
MasanoriSakai 5:01a978ee3cc1 251 lcd_printStr(tempstring);
MasanoriSakai 5:01a978ee3cc1 252
donalm 0:701da26ee5cb 253 }
donalm 0:701da26ee5cb 254
donalm 0:701da26ee5cb 255 /**
donalm 0:701da26ee5cb 256 * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
donalm 0:701da26ee5cb 257 * @param temperature The temperature as a float.
donalm 0:701da26ee5cb 258 * @return The temperature in 11073-20601 FLOAT-Type format.
donalm 0:701da26ee5cb 259 */
donalm 0:701da26ee5cb 260 uint32_t quick_ieee11073_from_float(float temperature)
donalm 0:701da26ee5cb 261 {
donalm 0:701da26ee5cb 262 uint8_t exponent = 0xFF; //exponent is -1
donalm 0:701da26ee5cb 263 uint32_t mantissa = (uint32_t)(temperature*10);
donalm 0:701da26ee5cb 264
donalm 0:701da26ee5cb 265 return ( ((uint32_t)exponent) << 24) | mantissa;
donalm 2:f11df1469db2 266 }
donalm 2:f11df1469db2 267