Skip to content

Commit 1f8323e

Browse files
authored
Merge pull request #1069 from brentru/wearable-ble-temperature-sensor
Wearable BLE Temperature Monitor
2 parents 96a3d09 + 928fb05 commit 1f8323e

File tree

1 file changed

+218
-0
lines changed

1 file changed

+218
-0
lines changed
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
/*********************************************************************
2+
Learn Guide: BLE Temperature Monitoring Armband
3+
4+
Adafruit invests time and resources providing this open source code,
5+
please support Adafruit and open-source hardware by purchasing
6+
products from Adafruit!
7+
8+
MIT license, check LICENSE for more information
9+
All text above, and the splash screen below must be included in
10+
any redistribution
11+
*********************************************************************/
12+
#include <bluefruit.h>
13+
#include <Adafruit_LittleFS.h>
14+
#include <InternalFileSystem.h>
15+
#include <Wire.h>
16+
#include <Adafruit_NeoPixel.h>
17+
#include "Adafruit_MCP9808.h"
18+
19+
// Read temperature in degrees Fahrenheit
20+
#define TEMPERATURE_F
21+
// uncomment the following line if you want to read temperature in degrees Celsius
22+
//#define TEMPERATURE_C
23+
24+
// Feather NRF52840 Built-in NeoPixel
25+
#define PIN 16
26+
Adafruit_NeoPixel pixels(1, PIN, NEO_GRB + NEO_KHZ800);
27+
28+
// Maximum temperature value for armband's fever indicator
29+
// NOTE: This is in degrees Fahrenheit
30+
float fever_temp = 100.4;
31+
32+
// temperature calibration offset is +0.5 to +1.0 degree
33+
// to make axillary temperature comparible to ear or temporal.
34+
float temp_offset = 0.5;
35+
36+
// Sensor read delay, in minutes
37+
int sensor_delay = 1;
38+
39+
// Measuring your armpit temperature for a minimum of 12 minutes
40+
// is equivalent to measuring your core body temperature.
41+
int calibration_time = 12;
42+
43+
// BLE transmit buffer
44+
char temperature_buf [8];
45+
46+
// BLE Service
47+
BLEDfu bledfu; // OTA DFU service
48+
BLEDis bledis; // device information
49+
BLEUart bleuart; // uart over ble
50+
BLEBas blebas; // battery
51+
52+
// Create the MCP9808 temperature sensor object
53+
Adafruit_MCP9808 tempsensor = Adafruit_MCP9808();
54+
55+
void setup() {
56+
Serial.begin(115200);
57+
Serial.println("Wearable BlueFruit Temperature Sensor");
58+
Serial.println("-------------------------------------\n");
59+
60+
61+
if (!tempsensor.begin(0x18)) {
62+
Serial.println("Couldn't find MCP9808! Check your connections and verify the address is correct.");
63+
while (1);
64+
}
65+
Serial.println("Found MCP9808!");
66+
67+
// Sets the resolution of reading
68+
tempsensor.setResolution(3);
69+
70+
// Configure BLE
71+
// Setup the BLE LED to be enabled on CONNECT
72+
// Note: This is actually the default behaviour, but provided
73+
// here in case you want to control this LED manually via PIN 19
74+
Bluefruit.autoConnLed(true);
75+
76+
// Config the peripheral connection with maximum bandwidth
77+
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
78+
79+
Bluefruit.begin();
80+
Bluefruit.setTxPower(4); // Check bluefruit.h for supported values
81+
Bluefruit.setName("Bluefruit52");
82+
Bluefruit.Periph.setConnectCallback(connect_callback);
83+
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
84+
85+
// To be consistent OTA DFU should be added first if it exists
86+
bledfu.begin();
87+
88+
// Configure and Start Device Information Service
89+
bledis.setManufacturer("Adafruit Industries");
90+
bledis.setModel("Bluefruit Feather52");
91+
bledis.begin();
92+
93+
// Configure and Start BLE Uart Service
94+
bleuart.begin();
95+
96+
// Start BLE Battery Service
97+
blebas.begin();
98+
blebas.write(100);
99+
100+
// Set up and start advertising
101+
startAdv();
102+
103+
Serial.println("Please use Adafruit's Bluefruit LE app to connect in UART mode");
104+
105+
// initialize neopixel object
106+
pixels.begin();
107+
108+
// set all pixel colors to 'off'
109+
pixels.clear();
110+
}
111+
112+
void loop() {
113+
114+
// wakes up MCP9808 - power consumption ~200 mikro Ampere
115+
Serial.println("Wake up MCP9808");
116+
tempsensor.wake();
117+
118+
// read and print the temperature
119+
Serial.print("Temp: ");
120+
#if defined(TEMPERATURE_F)
121+
float temp = tempsensor.readTempF();
122+
// add temperature offset
123+
temp += temp_offset;
124+
Serial.print(temp);
125+
Serial.println("*F.");
126+
#elif defined(TEMPERATURE_C)
127+
float temp = tempsensor.readTempC();
128+
// add temperature offset
129+
temp += temp_offset;
130+
Serial.print(temp);
131+
Serial.println("*C.");
132+
#else
133+
#warning "Must define TEMPERATURE_C or TEMPERATURE_F!"
134+
#endif
135+
136+
// set NeoPixels to RED if fever_temp
137+
if (temp >= fever_temp) {
138+
pixels.setPixelColor(1, pixels.Color(255, 0, 0));
139+
pixels.show();
140+
}
141+
142+
// float to buffer
143+
snprintf(temperature_buf, sizeof(temperature_buf) - 1, "%0.*f", 1, temp);
144+
145+
if (calibration_time == 0) {
146+
Serial.println("Writing to UART");
147+
// write to UART
148+
bleuart.write(temperature_buf);
149+
}
150+
else {
151+
Serial.print("Calibration time:");
152+
Serial.println(calibration_time);
153+
calibration_time-=1;
154+
}
155+
156+
// shutdown MSP9808 - power consumption ~0.1 mikro Ampere
157+
Serial.println("Shutting down MCP9808");
158+
tempsensor.shutdown_wake(1);
159+
160+
// sleep for sensor_delay minutes
161+
// NOTE: NRF delay() puts mcu into a low-power sleep mode
162+
delay(1000*60*sensor_delay);
163+
}
164+
165+
void startAdv(void)
166+
{
167+
// Advertising packet
168+
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
169+
Bluefruit.Advertising.addTxPower();
170+
171+
// Include bleuart 128-bit uuid
172+
Bluefruit.Advertising.addService(bleuart);
173+
174+
// Secondary Scan Response packet (optional)
175+
// Since there is no room for 'Name' in Advertising packet
176+
Bluefruit.ScanResponse.addName();
177+
178+
/* Start Advertising
179+
* - Enable auto advertising if disconnected
180+
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
181+
* - Timeout for fast mode is 30 seconds
182+
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
183+
*
184+
* For recommended advertising interval
185+
* https://developer.apple.com/library/content/qa/qa1931/_index.html
186+
*/
187+
Bluefruit.Advertising.restartOnDisconnect(true);
188+
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
189+
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
190+
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
191+
}
192+
193+
// callback invoked when central connects
194+
void connect_callback(uint16_t conn_handle)
195+
{
196+
// Get the reference to current connection
197+
BLEConnection* connection = Bluefruit.Connection(conn_handle);
198+
199+
char central_name[32] = { 0 };
200+
connection->getPeerName(central_name, sizeof(central_name));
201+
202+
Serial.print("Connected to ");
203+
Serial.println(central_name);
204+
}
205+
206+
/**
207+
* Callback invoked when a connection is dropped
208+
* @param conn_handle connection where this event happens
209+
* @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h
210+
*/
211+
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
212+
{
213+
(void) conn_handle;
214+
(void) reason;
215+
216+
Serial.println();
217+
Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
218+
}

0 commit comments

Comments
 (0)