Skip to content

Commit

Permalink
gain and sample period controllable through BLE
Browse files Browse the repository at this point in the history
  • Loading branch information
pseudoincorrect committed Mar 23, 2021
1 parent 5ec8588 commit eb993b7
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 115 deletions.
13 changes: 8 additions & 5 deletions Embedded_system/smart_mask/src/ble/services/ble_sms.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,27 +111,30 @@ static uint32_t add_sensor_ctrl_char(ble_sms_t * p_sms, uint8_t uuid,
/**
* @brief Function for handling the Write event
*
* @param[in] p_sms LED Button Service structure
* @param[in] p_sms Sensor Measurement Service structure
* @param[in] p_ble_evt Event received from the BLE stack
*/
static uint32_t ble_sms_event_on_write(
ble_sms_t * p_sms, ble_evt_t const * p_ble_evt)
{
ble_gatts_evt_write_t const * p_evt_write =
ble_gatts_evt_write_t const * p_evt_write =
&p_ble_evt->evt.gatts_evt.params.write;

if (p_evt_write->len != sizeof(sensor_ctrl_t))
if (p_evt_write->len != sizeof(sensor_ctrl_t)){
NRF_LOG_INFO("ble_sms_event_on_write wrong length %d", p_evt_write->len);
NRF_LOG_INFO("sizeof(sensor_ctrl_t) %d", sizeof(sensor_ctrl_t));
return NRF_ERROR_INVALID_DATA;
}

sensor_t sensor;
int16_t handle = p_evt_write->handle;

if (handle == p_sms->s1_ctrl_char.value_handle)
sensor = SENSOR_1;
else if (handle == p_sms->s2_ctrl_char.value_handle)
sensor = SENSOR_3;
else if (handle == p_sms->s3_ctrl_char.value_handle)
sensor = SENSOR_2;
else if (handle == p_sms->s3_ctrl_char.value_handle)
sensor = SENSOR_3;
else if (handle == p_sms->s4_ctrl_char.value_handle)
sensor = SENSOR_4;
else
Expand Down
2 changes: 1 addition & 1 deletion Embedded_system/smart_mask/src/sensors/sensor_handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ ret_code_t sensor_handle_get_values(
*/
bool is_sensor_ctrl_valid(sensor_ctrl_t * ctrl)
{
if (ctrl->sample_period_ms < 500 || ctrl->sample_period_ms > 2000)
if (ctrl->sample_period_ms < 200 || ctrl->sample_period_ms > 2000)
return false;
if (ctrl->gain < SAADC_CH_CONFIG_GAIN_Gain1_6 ||
ctrl->gain > SAADC_CH_CONFIG_GAIN_Gain4)
Expand Down
4 changes: 2 additions & 2 deletions Embedded_system/smart_mask/src/sensors/sensor_sampling.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
************************/

#define SAMPLES_IN_BUFFER SENSORS_COUNT
#define INITIAL_SAMPLE_RATE_MS 200
#define INITIAL_SAMPLE_RATE_MS 500

/*************************
* Static Variables
Expand Down Expand Up @@ -125,7 +125,7 @@ static ret_code_t sample_one_sensor(sensor_t sensor)
err = sensor_handle_add_value(sensor, adc_val);
APP_ERROR_CHECK(err);
nrf_gpio_pin_clear(hardware->pwr_pin);
NRF_LOG_INFO("sensor %d adc_val %d", sensor + 1, adc_val);
//NRF_LOG_INFO("sensor %d adc_val %d", sensor + 1, adc_val);

return err;
}
Expand Down
5 changes: 5 additions & 0 deletions Embedded_system/smart_mask/src/sensors/sensors.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,18 @@ typedef enum

typedef int16_t sensor_val_t;

// Pack the structure ( = not 32bit aligned)
#pragma pack(push,1)

typedef struct
{
uint32_t sample_period_ms;
uint8_t gain;
uint8_t enable;
} sensor_ctrl_t;

#pragma pack(pop)

typedef struct
{
uint32_t pwr_pin;
Expand Down
2 changes: 1 addition & 1 deletion Mobile_app/smart_mask/.flutter-plugins-dependencies
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_blue","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-2.0.1\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.0+3\\\\","dependencies":[]}],"android":[{"name":"flutter_blue","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-2.0.1\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.0+3\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.0\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.0+3\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.0.0\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.0\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_blue","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2021-03-22 13:34:03.330506","version":"2.0.2"}
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_blue","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-2.0.1\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.0+3\\\\","dependencies":[]}],"android":[{"name":"flutter_blue","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-2.0.1\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.0+3\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.0\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.0+3\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.0.0\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.0\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_blue","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2021-03-23 13:36:32.037365","version":"2.0.3"}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// contain the bluetooth state management for the app
// manage data stream (sensors, and notification)

import 'dart:math';
import 'dart:typed_data';

import 'package:flutter_blue/flutter_blue.dart';
Expand All @@ -14,7 +13,7 @@ import 'package:smart_mask/src/logic/repositories/sensor_data_repo.dart';
import 'package:smart_mask/src/logic/blocs/bluetooth/smart_mask_services_const.dart'
as smsConst;

final String sensorService = smsConst.S["sensorMeasurementService"]["UUID"];
final String sensorServiceUUID = smsConst.S["sensorMeasurementService"]["UUID"];

final Map<String, Map<String, String>> valuesChars =
smsConst.S["sensorMeasurementService"]["characteristics"]["values"];
Expand All @@ -26,7 +25,7 @@ class BluetoothBloc {
int _sampleRateValue;
SensorGain _gainValue;

// Map<Sensor, SensorControl> _sensorControls;
Map<Sensor, SensorControl> _sensorControls = Map();
Stream<BluetoothState> _bluetoothState;
SensorDataRepository _sensorDataRepository;
Stream<bool> _isConnected;
Expand All @@ -36,8 +35,11 @@ class BluetoothBloc {
_bluetoothState = FlutterBlue.instance.state;
_isConnected =
Stream.periodic(Duration(seconds: 2)).asyncMap((_) => checkConnected());
_sampleRateValue = 200;
_gainValue = SensorGain.one;

for (var i in Sensor.values) {
_sensorControls[i] =
SensorControl(initGain: SensorGain.one, initSamplePeriodMs: 200);
}
}

Future<bool> checkConnected() async {
Expand Down Expand Up @@ -70,7 +72,7 @@ class BluetoothBloc {

updateCharacteristics(List<BluetoothCharacteristic> characteristics) async {
for (var characteristic in characteristics) {
var uuid = characteristic.uuid.toString();
var uuid = characteristic.uuid.toString().toUpperCase();

dynamic uuids = [];
valuesChars.forEach((key, value) {
Expand All @@ -87,7 +89,6 @@ class BluetoothBloc {
characteristic.value.listen((x) => onReceiveValue(x, characteristic));
if (!characteristic.isNotifying) {
await characteristic.setNotifyValue(true);
print(characteristic.isNotifying);
}
}

Expand Down Expand Up @@ -122,16 +123,74 @@ class BluetoothBloc {
return sensorDatas;
}

setSampleRateValue(int newValue) {
if (!validateSensorSampleRate(newValue)) return null;
_sampleRateValue = newValue.round();
SensorControl getSensorControl(Sensor sensor) => _sensorControls[sensor];

int getSamplePeriod(Sensor sensor) {
var ctrl = getSensorControl(sensor);
return ctrl.samplePeriodMs;
}

setSamplePeriod(Sensor sensor, int newPeriodMs) {
var ctrl = getSensorControl(sensor);
ctrl.samplePeriodMs = newPeriodMs;
setSensorCtrlBle(sensor);
}

SensorGain getGain(Sensor sensor) {
var ctrl = getSensorControl(sensor);
return ctrl.gain;
}

int getSampleRateValue() => _sampleRateValue;
setGain(Sensor sensor, SensorGain newGain) async {
SensorControl ctrl = getSensorControl(sensor);
ctrl.gain = newGain;
setSensorCtrlBle(sensor);
}

setgainValue(SensorGain newValue) => _gainValue = newValue;
Future<BluetoothCharacteristic> getSensorCtrlChar(Sensor sensor) async {
List<BluetoothDevice> devices = await FlutterBlue.instance.connectedDevices;
BluetoothDevice device;
if (devices[0].name.contains("Smart")) device = devices[0];
List<BluetoothService> services = await device.services.first;
BluetoothService smsService = services
.where((s) => s.uuid.toString().toUpperCase() == sensorServiceUUID)
.first;
List<BluetoothCharacteristic> characteristics = smsService.characteristics;
BluetoothCharacteristic ctrlChar = characteristics
.where((c) =>
c.uuid.toString().toUpperCase() ==
controlChars[sensorEnumToString(sensor)]["UUID"])
.first;
return ctrlChar;
}

SensorGain getgainValue() => _gainValue;
setSensorCtrlBle(Sensor sensor) async {
var ctrl = getSensorControl(sensor);
var ctrlPacket = SensorControlPacket(ctrl);
var char = await getSensorCtrlChar(sensor);
await char.write(ctrlPacket.buffer, withoutResponse: false);
}

dispose() {}
}

class SensorControlPacket {
List<int> buffer = [];

SensorControlPacket(SensorControl sensorControl) {
// uint32_t samplePeriodMs
int byte;
byte = sensorControl.samplePeriodMs & 0x000000FF;
buffer.add(byte);
byte = (sensorControl.samplePeriodMs & 0x0000FF00) >> 8;
buffer.add(byte);
byte = (sensorControl.samplePeriodMs & 0x00FF0000) >> 16;
buffer.add(byte);
byte = (sensorControl.samplePeriodMs & 0xFF000000) >> 24;
buffer.add(byte);
// uint8_t gain
buffer.add(sensorControl.gain.index);
// uint8_t enable
buffer.add(sensorControl.enable ? 1 : 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,35 @@ const SAMPLE_PERIOD_MS = 250;

const dynamic S = {
"genericAccessService": {
"UUID": "00001800-0000-1000-8000-00805f9b34fb",
"UUID": "00001800-0000-1000-8000-00805F9B34FB",
"characteristics": {
"deviceName": {"UUID": "00002a00-0000-1000-8000-00805f9b34fb"},
"appearance": {"UUID": "00002a01-0000-1000-8000-00805f9b34fb"},
"deviceName": {"UUID": "00002A00-0000-1000-8000-00805F9B34FB"},
"appearance": {"UUID": "00002A01-0000-1000-8000-00805F9B34FB"},
"peripheralPreferredConnectionParameters": {
"UUID": "00002a04-0000-1000-8000-00805f9b34fb"
"UUID": "00002A04-0000-1000-8000-00805F9B34FB"
},
},
},
"genericAttributeService": {
"UUID": "00001801-0000-1000-8000-00805f9b34fb",
"UUID": "00001801-0000-1000-8000-00805F9B34FB",
"characteristics": {
"serviceChanged": {"UUID": "00002aa6-0000-1000-8000-00805f9b34fb"},
"serviceChanged": {"UUID": "00002AA6-0000-1000-8000-00805F9B34FB"},
},
},
"sensorMeasurementService": {
"UUID": "00001600-1212-efde-1523-785feabcd124",
"UUID": "00000000-1212-EFDE-1523-785FEABCD124",
"characteristics": {
"values": {
"sensors_1": {"UUID": "00000001-1212-efde-1523-785feabcd124"},
"sensors_2": {"UUID": "00000003-1212-efde-1523-785feabcd124"},
"sensors_3": {"UUID": "00000005-1212-efde-1523-785feabcd124"},
"sensors_4": {"UUID": "00000007-1212-efde-1523-785feabcd124"},
"sensor_1": {"UUID": "00000001-1212-EFDE-1523-785FEABCD124"},
"sensor_2": {"UUID": "00000003-1212-EFDE-1523-785FEABCD124"},
"sensor_3": {"UUID": "00000005-1212-EFDE-1523-785FEABCD124"},
"sensor_4": {"UUID": "00000007-1212-EFDE-1523-785FEABCD124"},
},
"control": {
"sensors_1": {"UUID": "00000002-1212-efde-1523-785feabcd124"},
"sensors_2": {"UUID": "00000004-1212-efde-1523-785feabcd124"},
"sensors_3": {"UUID": "00000006-1212-efde-1523-785feabcd124"},
"sensors_4": {"UUID": "00000008-1212-efde-1523-785feabcd124"},
"sensor_1": {"UUID": "00000002-1212-EFDE-1523-785FEABCD124"},
"sensor_2": {"UUID": "00000004-1212-EFDE-1523-785FEABCD124"},
"sensor_3": {"UUID": "00000006-1212-EFDE-1523-785FEABCD124"},
"sensor_4": {"UUID": "00000008-1212-EFDE-1523-785FEABCD124"},
}
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,39 @@ String sensorGainEnumToString(SensorGain sensorGain) {
return sensorGain.toString().replaceFirst("SensorGain.", "");
}

bool validateSensorSampleRate(int value) {
if (value < 100) return false;
if (value > 1000) return false;
return true;
}

class SensorControl {
SensorGain gain;
int samplePeriod;
SensorGain _gain;
int _samplePeriodMs;
bool _enable;

SensorControl({initGain, initSamplePeriodMs}) {
_gain = initGain;
_samplePeriodMs = initSamplePeriodMs;
_enable = true;
}

bool get enable => _enable;

set enable(bool state) {
if (true) _enable = state;
}

SensorControl({this.gain, this.samplePeriod});
int get samplePeriodMs => _samplePeriodMs;

set samplePeriodMs(int value) {
if (!validateSensorSamplePeriod(value)) return;
_samplePeriodMs = value;
}

SensorGain get gain => _gain;

set gain(SensorGain newGain) {
if (true) _gain = newGain;
}

bool validateSensorSamplePeriod(int value) {
if (value < 100) return false;
if (value > 1000) return false;
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,23 @@ Sensor sensorFromBLEchararcteristicUUID(String uuid) {
final Map<String, Map<String, String>> controlChars =
smsConst.S["sensorMeasurementService"]["characteristics"]["control"];

if (uuid == valuesChars["sensors_1"]["UUID"]) return Sensor.sensor_1;
if (uuid == valuesChars["sensors_2"]["UUID"]) return Sensor.sensor_2;
if (uuid == valuesChars["sensors_3"]["UUID"]) return Sensor.sensor_3;
if (uuid == valuesChars["sensors_4"]["UUID"]) return Sensor.sensor_4;
if (uuid.toUpperCase() == valuesChars["sensor_1"]["UUID"])
return Sensor.sensor_1;
if (uuid.toUpperCase() == valuesChars["sensor_2"]["UUID"])
return Sensor.sensor_2;
if (uuid.toUpperCase() == valuesChars["sensor_3"]["UUID"])
return Sensor.sensor_3;
if (uuid.toUpperCase() == valuesChars["sensor_4"]["UUID"])
return Sensor.sensor_4;

if (uuid == controlChars["sensors_1"]["UUID"]) return Sensor.sensor_1;
if (uuid == controlChars["sensors_2"]["UUID"]) return Sensor.sensor_2;
if (uuid == controlChars["sensors_3"]["UUID"]) return Sensor.sensor_3;
if (uuid == controlChars["sensors_4"]["UUID"]) return Sensor.sensor_4;
if (uuid.toUpperCase() == controlChars["sensor_1"]["UUID"])
return Sensor.sensor_1;
if (uuid.toUpperCase() == controlChars["sensor_2"]["UUID"])
return Sensor.sensor_2;
if (uuid.toUpperCase() == controlChars["sensor_3"]["UUID"])
return Sensor.sensor_3;
if (uuid.toUpperCase() == controlChars["sensor_4"]["UUID"])
return Sensor.sensor_4;

return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class FindDevicesScreen extends StatelessWidget {
builder: (c, snapshot) {
if (snapshot.data ==
BluetoothDeviceState.connected) {
return RaisedButton(
return ElevatedButton(
child: Text('OPEN'),
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
Expand Down
Loading

0 comments on commit eb993b7

Please sign in to comment.