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