운동 활동 추적 기기에서 데이터 수집하기
이 예제에서는 Bluetooth® Low Energy 통신을 사용하여 운동 활동 추적 기기에서 데이터를 수집하고 플로팅하는 방법을 보여줍니다.
하드웨어 설정
이 예제에서는 Under Armour® 심박수 모니터링 벨트와 Under Armour 스마트 러닝화를 사용합니다. 두 기기 모두 Bluetooth Low Energy 통신을 지원합니다.
기기를 검색해서 연결하기
먼저, MATLAB®에서 Bluetooth Low Energy 기기를 찾아 기기가 연결을 지원하는지 확인합니다. blelist
함수가 애드버타이징하는 인근 Bluetooth Low Energy 주변 기기를 스캔합니다.
blelist
ans=14×5 table
Index Name Address RSSI Advertisement
_____ ___________________ ______________________________________ ____ _____________
1 "" "21996E3A-8F31-496D-B332-79D03B759BC7" -65 [1×1 struct]
2 "" "12377421-4EA3-4F77-9365-EFD580C34DE9" -66 [1×1 struct]
3 "UA E39 MODULE" "8206F662-BA4A-483F-A908-516FF506BFB0" -67 [1×1 struct]
4 "" "CF65AD36-2146-4CA1-BCEA-FED47F6195CA" -76 [1×1 struct]
5 "UA Footpod 239AE2" "CF7B1A17-4104-4D7B-AE70-1837CAE9C9D0" -78 [1×1 struct]
6 "" "67A1A92A-5F1C-4AF8-857A-99F194E9A5F8" -82 [1×1 struct]
7 "" "5609D68D-0EED-41D7-BE19-F3ACAA119C7A" -84 [1×1 struct]
8 "" "5A17DF46-6F71-4DAC-AF0D-0F28E3911187" -85 [1×1 struct]
9 "" "9675A0FA-0394-468B-B908-040696E1C5BC" -88 [1×1 struct]
10 "" "61540D17-C2DD-41D4-B107-E2E7374B11F4" -88 [1×1 struct]
11 "" "C2A5CCC3-CA6C-4688-AAE9-A5BE039561F9" -92 [1×1 struct]
12 "" "AF5E1195-4088-4A4B-ADA5-0BD3C91BFE62" -93 [1×1 struct]
13 "" "83C69EFB-0FAD-4A35-B167-79C51A1F245D" -94 [1×1 struct]
14 "" "993276FD-07EC-433D-85E1-E144B289B648" -95 [1×1 struct]
MATLAB에서 기기를 찾으면 ble
를 호출하여 기기에 연결합니다. 이름이 고유하면 기기 이름을 지정하고, 또는 기기 주소를 지정합니다.
belt = ble("UA E39 MODULE")
belt = ble with properties: Name: "UA E39 MODULE" Address: "8206F662-BA4A-483F-A908-516FF506BFB0" Connected: 1 Services: [4×2 table] Characteristics: [22×5 table] Show services and characteristics
shoe = ble("UA Footpod 239AE2")
shoe = ble with properties: Name: "UA Footpod 239AE2" Address: "CF7B1A17-4104-4D7B-AE70-1837CAE9C9D0" Connected: 1 Services: [8×2 table] Characteristics: [39×5 table] Show services and characteristics
ble
객체 벨트의 Characteristics 속성에 액세스합니다. 이 기기에 "Heart Rate" 서비스가 있으며, 이 서비스에는 "Heart Rate Measurement" 특성이 포함되어 있습니다.
belt.Characteristics
ans=22×5 table
ServiceName ServiceUUID CharacteristicName CharacteristicUUID Attributes
____________________ ______________________________________ _____________________________________________________ ______________________________________ ____________
"Heart Rate" "180D" "Heart Rate Measurement" "2A37" {["Notify"]}
"Heart Rate" "180D" "Body Sensor Location" "2A38" {["Read" ]}
"Heart Rate" "180D" "Heart Rate Control Point" "2A39" {["Write" ]}
"Battery Service" "180F" "Battery Level" "2A19" {1×2 string}
"Device Information" "180A" "System ID" "2A23" {["Read" ]}
"Device Information" "180A" "Model Number String" "2A24" {["Read" ]}
"Device Information" "180A" "Serial Number String" "2A25" {["Read" ]}
"Device Information" "180A" "Firmware Revision String" "2A26" {["Read" ]}
"Device Information" "180A" "Hardware Revision String" "2A27" {["Read" ]}
"Device Information" "180A" "Software Revision String" "2A28" {["Read" ]}
"Device Information" "180A" "Manufacturer Name String" "2A29" {["Read" ]}
"Device Information" "180A" "IEEE 11073-20601 Regulatory Certification Data List" "2A2A" {["Read" ]}
"Device Information" "180A" "PnP ID" "2A50" {["Read" ]}
"Custom" "21A51000-4C86-11E2-BCFD-0800200C9A66" "Custom" "21A51011-4C86-11E2-BCFD-0800200C9A66" {1×2 string}
"Custom" "21A51000-4C86-11E2-BCFD-0800200C9A66" "Custom" "21A51021-4C86-11E2-BCFD-0800200C9A66" {1×2 string}
"Custom" "21A51000-4C86-11E2-BCFD-0800200C9A66" "Custom" "21A51022-4C86-11E2-BCFD-0800200C9A66" {["Write" ]}
⋮
ble
객체 shoe의 Characteristics 속성에 액세스합니다. 이 기기에 "Running Speed and Cadence" 서비스가 있으며, 이 서비스에는 "RSC Measurement" 특성이 포함되어 있습니다.
shoe.Characteristics
ans=39×5 table
ServiceName ServiceUUID CharacteristicName CharacteristicUUID Attributes
___________________________ ______________________________________ _____________________________________________________ ______________________________________ ____________
"Device Information" "180A" "System ID" "2A23" {["Read" ]}
"Device Information" "180A" "Model Number String" "2A24" {["Read" ]}
"Device Information" "180A" "Serial Number String" "2A25" {["Read" ]}
"Device Information" "180A" "Firmware Revision String" "2A26" {["Read" ]}
"Device Information" "180A" "Hardware Revision String" "2A27" {["Read" ]}
"Device Information" "180A" "Software Revision String" "2A28" {["Read" ]}
"Device Information" "180A" "Manufacturer Name String" "2A29" {["Read" ]}
"Device Information" "180A" "IEEE 11073-20601 Regulatory Certification Data List" "2A2A" {["Read" ]}
"Device Information" "180A" "PnP ID" "2A50" {["Read" ]}
"Battery Service" "180F" "Battery Level" "2A19" {1×2 string}
"Running Speed and Cadence" "1814" "RSC Measurement" "2A53" {["Notify"]}
"Running Speed and Cadence" "1814" "RSC Feature" "2A54" {["Read" ]}
"Running Speed and Cadence" "1814" "SC Control Point" "2A55" {1×2 string}
"Custom" "21A54000-4C86-11E2-BCFD-0800200C9A66" "Custom" "21A54001-4C86-11E2-BCFD-0800200C9A66" {1×2 string}
"Custom" "21A54000-4C86-11E2-BCFD-0800200C9A66" "Custom" "21A54002-4C86-11E2-BCFD-0800200C9A66" {1×2 string}
"Custom" "21A54000-4C86-11E2-BCFD-0800200C9A66" "Custom" "21A54003-4C86-11E2-BCFD-0800200C9A66" {1×3 string}
⋮
심박수 데이터 읽어오기
다음으로, 서비스와 특성 정보를 지정하여 "Heart Rate Measurement" 특성에 대한 객체를 만듭니다.
hr = characteristic(belt, "heart rate", "heart rate measurement")
hr = Characteristic with properties: Name: "Heart Rate Measurement" UUID: "2A37" Attributes: "Notify" Descriptors: [1x3 table] DataAvailableFcn: [] Show descriptors
그런 다음 기기에서 현재 심박수 측정값을 읽어옵니다.
data = read(hr)
data = 1×4
22 96 73 3
Bluetooth Low Energy Specifications List의 Heart Rate Service 사양에 따르면 "Heart Rate Measurement" 특성 값에는 플래그 바이트와 그 뒤에 하나 이상의 심박수 값이 포함되어 있습니다. 측정 값의 형식은 플래그 값에 따라 다릅니다. 원시 데이터를 분당 맥박 수(bpm) 단위의 심박수로 변환합니다.
flag = uint8(data(1)); % Get the first bit of the flag, which indicates the format of the heart rate value heartRateValueFormat = bitget(flag, 1); if heartRateValueFormat == 0 % Heart rate format is uint8 heartRate = data(2); else % Heart rate format is uint16 heartRate = double(typecast(uint8(data(2:3)), 'uint16')); end fprintf('Heart rate measurement: %d(bpm)\n', heartRate);
Heart rate measurement: 96(bpm)
달리기 속도와 케이던스 데이터 읽기
마찬가지로, 서비스와 특성 정보를 지정하여 "RSC Measurement" 특성에 대한 객체를 만듭니다.
rsc = characteristic(shoe, "running speed and cadence", "rsc measurement")
rsc = Characteristic with properties: Name: "RSC Measurement" UUID: "2A53" Attributes: "Notify" Descriptors: [1x3 table] DataAvailableFcn: [] Show descriptors
그런 다음 기기에서 현재 달리기 속도와 케이던스 값을 읽어옵니다.
data = read(rsc)
data = 1×10
3 0 0 0 0 0 84 57 0 0
Bluetooth Low Energy Specifications List의 Running Speed and Cadence Service 사양에 따르면 "RSC Measurement" 특성 값에는 순간 속도를 나타내는 2바이트와 순간 케이던스를 나타내는 1바이트가 포함됩니다. 원시 데이터를 분당 미터 수(m/s) 단위의 달리기 속도와 분당 걸음 수 단위의 케이던스로 변환합니다.
instantaneousSpeed = double(typecast(uint8(data(2:3)), 'uint16'))/256; instantaneousCadence = data(4); fprintf('Instantaneous speed: %.2f(m/s) and instantaneous cadence: %d(steps per minute)\n', instantaneousSpeed, instantaneousCadence);
Instantaneous speed: 0.00(m/s) and instantaneous cadence: 0(steps per minute)
심박수와 달리기 속도에 대한 상관 구하기
심박수 및 RSC 데이터를 읽어온 후 달리기 세션 동안의 실시간 데이터를 추적하여 두 측정값에 대한 상관을 구하여 피트니스 성능을 분석합니다.
운동 데이터의 상관 관계를 표시하기 위해, 먼저 데이터 점들을 루프로 추가하여 애니메이션을 만드는 두 개의 플롯을 만듭니다.
% Create a plot for running speed against heart rate axSpeed = axes('XLim', [0, 5], 'YLim', [60, 220]); xlabel(axSpeed, 'Running speed (m/s)'); ylabel(axSpeed, 'Heart rate (bpm)'); subplot(1, 2, 1, axSpeed); hSpeed = animatedline(axSpeed, 'Marker', 'o', 'MarkerFaceColor', 'green'); % Create a plot for running cadence against heart rate axCadence = axes('XLim', [0, 200], 'YLim', [60 220]); xlabel(axCadence, 'Running cadence (steps per minute)'); ylabel(axCadence, 'Heart rate (bpm)'); subplot(1, 2, 2, axCadence); hCadence = animatedline(axCadence, 'Marker', 'o', 'MarkerFaceColor', 'blue');
다음으로, 루프에서 기기 데이터를 읽어오고 사용자가 걷기에서 조깅, 달리기로 진행함에 따라 플롯을 업데이트합니다.
for loop = 1:30 % Get heart rate data data = read(hr); flag = uint8(data(1)); heartRateValueFormat = bitget(flag, 1); if heartRateValueFormat == 0 heartRate = data(2); else heartRate = double(typecast(uint8(data(2:3)), 'uint16')); end % Get running speed data data = read(rsc); instantaneousSpeed = double(typecast(uint8(data(2:3)), 'uint16'))/256; instantaneousCadence = data(4); % Update plot with new data addpoints(hSpeed, instantaneousSpeed, heartRate); addpoints(hCadence, instantaneousCadence, heartRate); drawnow; end
이 플롯은 일반적으로 달리기 속도와 케이던스 값이 높을수록 심박수가 증가한다는 것을 보여줍니다.
기기와의 연결 끊기
기기 객체를 다 사용했으면 이 객체를 지웁니다.
clear belt shoe