簡介
跌倒導致致命的傷害已成為老年人不可忽視的巨大挑戰(zhàn)。在過去的幾年中,在跌倒檢測領(lǐng)域提出了不同類型的方法,可以解釋并分為三種類型:基于可穿戴設備、基于環(huán)境傳感器和基于視覺。首先,可穿戴設備通常利用嵌入式傳感器來檢測身體的運動和位置,例如加速度計、磁力計和陀螺儀 。并且基于可穿戴設備的方法成本很低,而且對于老年人來說安裝和操作并不復雜。其次,基于環(huán)境的方法總是使用壓力傳感器來檢測和跟蹤身體。該解決方案還具有成本效益且易于部署。然而,感知人體以外的物體的可能性對這種方法的檢測精度提出了顯著挑戰(zhàn)。最后但同樣重要的是,基于視覺的解決方案充分利用部署的攝像頭來監(jiān)控范圍內(nèi)的所有物體,包括人體 。與上述兩種方式相比,對人們?nèi)粘I畹母蓴_較少,但觀測空間有限,無法實現(xiàn)無處不在的監(jiān)控。
在本項目中,提出了一種基于 Arduino、Windows 10 和 Microsoft Azure 的實時跌倒檢測監(jiān)控系統(tǒng)。三維加速度計的原始數(shù)據(jù)由 Arduino 和 ADXL345 提供。Windows 10 設備利用這些信息通過有效的數(shù)據(jù)融合和跌倒檢測算法來獲取對象的方向。微軟 Azure 服務和移動/PC 應用程序也旨在實現(xiàn)無縫的數(shù)據(jù)處理、分析、存儲和獲取,只要它們可以訪問 Internet,就可以隨時隨地從任何地方訪問。系統(tǒng)架構(gòu)如圖1所示:
基于姿勢識別的跌倒檢測原理
在這個項目中,跌倒檢測算法是根據(jù)Bharadwaj Sreenivasan 的 Fall-detection-in-Android設計的。算法中有兩個模塊,姿勢識別和跌倒檢測。首先,我們從加速度計中讀取 x、y 和 z 值。然后我們計算 x、y 和 z 的 L2 范數(shù)。這由姿勢識別和跌倒檢測模塊使用。
在姿勢識別模塊中,用戶姿勢分為三種基本姿勢:坐姿、站立姿勢和行走姿勢?!皔”的值被應用一個閾值來找出方向。使用 L2 范數(shù)與重力引起的平均加速度 (9.8) 的變化率,我們將數(shù)據(jù)分類為行走或狀態(tài)之間的轉(zhuǎn)換。
跌倒檢測模塊在信號中搜索特定模式。圖 2 表示跌倒事件期間 L2 范數(shù)的典型模式:
如果連續(xù)最小值和最大值之間的差值大于 2g,則輸出判定為下降。跌倒事件的最終決定是基于姿勢識別和跌倒決策模塊的輸出。當檢測到跌倒時,姿勢識別模塊的決定會告訴我們這是否是誤報。如果狀態(tài)仍在行走,則可以丟棄跌倒事件決策。表 1 總結(jié)了最終決定:
先決條件
在這個項目中,對于Arduino設備,藍牙通信是通過HC-06實現(xiàn)的,HC-06是一個便宜的小封裝模塊。對于 Windows 10 設備,如果您使用 Surface Pro 和 Lumia 1520,則不需要藍牙模塊。但是,如果您使用 Raspberry Pi 或 MBM 作為 Windows 10 IoT 設備,則需要藍牙加密狗。
注意:如果您尚未安裝 Windows 10 和 Visual Studio 2015,則需要 2-3 小時才能完成先決條件。
需要什么
部分:
1. Arduino Uno和標準 A/B USB 電纜
2. HC-06藍牙模塊
3. ADXL345加速度計模塊
4. 公母公母跳線
5.迷你面包板
6. Lumia 1520或其他 Windows Phone 10 兼容設備
項目說明
第 1 步:將加速度計模塊 ADXL345 連接到 Arduino
ADXL345 是一款小型、薄型、低功耗、3 軸 MEMS 加速度計,具有高達 +-16 g 的高分辨率(13 位)測量。數(shù)字輸出數(shù)據(jù)采用 16 位二進制補碼格式,可通過 SPI(3 線或 4 線)或 I2C 數(shù)字接口訪問。
ADXL345 支持 SPI 和 I2C,我們將在此項目中討論 I2C。I2C 是 2 線串行連接,因此我們需要將 SDA(數(shù)據(jù))和 SCL(時鐘)線連接到 Arduino UNO 進行通信。在 Arduino UNO 上,SDA 在模擬引腳 4 上,SCL 在模擬引腳 5 上。確保 VCC 和傳感器上的 CS 引腳都連接到 3.3v。我們將 CS 連接到 3.3V 以告訴傳感器我們將使用它作為 I2C 設備,而不是 SPI 設備。
第 2 步:連接藍牙模塊
在這個項目中,我們使用 HC-06 作為藍牙模塊 - 它比 SparkFun 的 BlueSMiRF Silver 模塊便宜得多。此外,HC-05 上面有“完整”固件,許多 AT 命令,并且可以是主模塊和從模塊。另一方面,HC-06 固件只能是從設備,具有非常有限的 AT 命令。下表顯示了所有 HC-06 固件命令及其響應:
首先,將藍牙模塊插入面包板以使連接更容易。要為模塊供電,請從 Arduino 的 5V 電源軌跳線到模塊的 Vcc 引腳。并從模塊的 GND 引腳運行公公跳線到 Arduino 上的任何 GND 引腳。要建立串行通信,請將藍牙模塊的 TX 引腳的公公跳線連接到 Arduino 的 RX 引腳(數(shù)字引腳 0),并將另一個從模塊的 RX 引腳連接到 Arduino 的 TX 引腳(數(shù)字引腳 1)。
注意:當您將藍牙的 TX 和 RX 引腳連接到 Arduino 時,您將無法將草圖從 Arduino IDE 上傳到 Arduino。當您需要上傳草圖時斷開它們并在成功上傳草圖后重新連接它們。在下面的草圖中,顯示使用了 HC-05。實際上,如上所述,HC-05 和 HC-06 都可以。
藍牙和加速度計連接后,實物如下圖:
第 3 步:將藍牙模塊與 Windows 10 設備配對
藍牙模塊運行 SPP(藍牙串行協(xié)議)協(xié)議。所以任何支持 SPP 的設備都可以連接到它。在 Windows 10 設備上,這看起來像一個虛擬 COM 端口。在連接之前,請確保模塊已通電并準備好配對。模塊上的紅色 LED 指示狀態(tài):閃爍表示“準備配對”,常亮表示“配對”。
在 Windows 10 for PC 上,只需導航到設置-》設備-》藍牙,打開藍牙,然后屏幕上將顯示“HC-06”模塊。點擊以配對設備,然后輸入設備的配對碼。請記住,默認配對碼是 1234,默認串口速度是 9600 波特。然后,藍牙頁面顯示如下:
對于 Windows 10 for Mobile,導航到設置-》設備-》藍牙,然后執(zhí)行上一節(jié)中描述的相同步驟。配對設備頁面如下所示:
對于 Windows 10 IoT Core 設備,例如 Raspberry Pi 2、MBM 和 Dragon Board 410c,配對過程有很大不同。首先,對于沒有板載藍牙模塊的樹莓派 2 和 MBM,我們應該購買藍牙 USB 加密狗并插入。只需參考硬件兼容性列表并選擇經(jīng)過驗證的藍牙 USB 加密狗。
在這個項目中,我們選擇了 ORICO BTA-403 模塊。
如果您在 Dragon Board 410c 上嘗試此項目,那么您不需要藍牙加密狗,因為 Dragon Board 410c 具有板載藍牙模塊。
將 ORICO BTA-403 藍牙 USB 加密狗插入樹莓派 2 的 USB 接口,如下所示。
插入 ORICO BTA-403 藍牙 USB 加密狗后,它將在 Windows 10 IoT Core 設備的默認應用程序屏幕上顯示消息。
在這里,我們應該使用 SSH 連接到 Windows IoT Core 并運行命令行工具來配置設備。
注意:請記住應在主菜單上選擇 BR 模式。默認配對碼為 1234。
配對成功后,設備的藍牙頁面顯示如下:
第 4 步:創(chuàng)建 Azure 存儲帳戶
在這個項目中,我們將需要 Azure 存儲表來存儲來自 Windows 10 IoT Core 設備的數(shù)據(jù)。因此,我們可以按如下方式創(chuàng)建它。
(1) 在 Azure 管理門戶 中,單擊左側(cè)的“STORAGE”圖標以查看您現(xiàn)有的存儲帳戶(如果有),然后單擊“+NEW”按鈕在左下角。
(2) 在“新建”面板中,選擇“數(shù)據(jù)服務”| “存儲” | “快速創(chuàng)建”。填寫“URL、位置/關(guān)聯(lián)組和復制”字段,然后單擊“創(chuàng)建存儲帳戶”按鈕。
(3) 等待新存儲帳戶的狀態(tài)顯示為“在線”。
(4) 選擇新創(chuàng)建的Storage account,然后點擊頁面底部的MANAGE ACCESS KEYS。復制存儲帳戶名稱和訪問密鑰之一。
第 5 步:創(chuàng)建 Azure 存儲表
我們使用 Azure 存儲資源管理器來創(chuàng)建 Azure 存儲表。
?。?) 進入添加賬戶,填寫賬戶名和訪問密鑰。建立帳戶后,您可以訪問顯示 Blob 容器、隊列和表的存儲。
?。?) 選擇表并單擊新建按鈕,創(chuàng)建一個名為“Accelerometer Table”的新表,如下所示:
第 6 步:軟件
首先,現(xiàn)在我們已經(jīng)為 Arduino 連接好了所有東西,從(在本文下方提供)使用“ADXL345_HC06.ino”項目并將其加載到您 PC 上的 Arduino IDE 中。務必拔掉 HC-06 模塊的 TX/RX 跳線,然后上傳草圖。將 TX/RX 跳線重新連接到 Arduino 的數(shù)字 0 和數(shù)字 1 引腳。插上電源,應用程序?qū)⒃?Arduino Uno 上運行。
其次,從github下載“GenericBluetoothSerialUWApp”項目。使用帶有 Update 1 的 Visual Studio 2015 加載“GenericBluetoothSerialUWApp”。這個應用程序是在我們的 MVP David Jones 的Generic Serial Bluetooth with Win 10 IoT-Core RPI2的幫助下設計的。如果您希望此 UWP 應用在 PC 上運行,請選擇帶有本地設備調(diào)試的 x86 或 x64。如果您希望此 UWP 應用在 Windows 10 移動版上運行,請選擇帶有設備調(diào)試的 ARM。如果您希望此 UWP 應用在 Windows 10 IoT 設備(例如 Raspberry Pi 2)上運行,請確保將“遠程調(diào)試”點設置為您的設備。
接下來,在解決方案資源管理器中打開 MainPage.xaml.cs 并找到“dataTransferTick”。添加您在第 4 節(jié)中保存的存儲帳戶名稱和訪問密鑰。
將 HC-06 與 Windows 10 設備配對后,在 Visual Studio 中按 F5 以啟動通用 Windows 平臺應用。
雙擊“HC-06”符號,您將在應用程序的最頂部找到 Id 和 Name 顯示,如下所示。
很快,您可以看到 HC-06 上的 LED 狀態(tài)將從閃爍變?yōu)榉€(wěn)定。并且藍牙模塊的通信通道一旦建立,“Start Rev”按鈕就會被啟用。
單擊 Start Recv 以啟用數(shù)據(jù)接收。然后您將看到啟用了 Stop Recv、Process Data 和 Upload Data 按鈕。只需單擊處理數(shù)據(jù)按鈕即可運行跌倒檢測算法。您將在 Recvd TextBlock 上看到數(shù)據(jù)以及攜帶設備的人的狀態(tài)。
您仍然可以發(fā)現(xiàn)數(shù)據(jù)將顯示在 Visual Studio 的調(diào)試窗口中,如下所示:
然后,單擊“上傳”按鈕將數(shù)據(jù)上傳到 Azure。數(shù)據(jù)將每 3 秒傳輸一次。如果要更改時間間隔,可以修改“AzureButton_Click”中的代碼如下。
私人無效 AzureButton_Click(對象發(fā)送者,RoutedEventArgs e){
timerDataTransfer = ThreadPoolTimer.CreatePeriodicTimer(dataTransferTick, TimeSpan.FromMilliseconds(Convert.ToInt32( 3000 )));
}
很快,可以看到AccelerometerTable中的數(shù)據(jù)如下
第三,從github下載“FallDetectionClient”。使用帶有 Update 1 的 Visual Studio 2015 加載此項目。此應用程序是使用 Windows Universal Temple 構(gòu)建的,因此您可以在 Windows 10 PC/Mobile 以及 Windows 10 IoT Core 設備上運行它。接下來,在解決方案資源管理器中打開 StorageSensor.cs 并找到“_accountName”和“_key”。添加您在第 4 節(jié)中保存的存儲帳戶名稱和訪問密鑰。
現(xiàn)在您應該可以在 Visual Studio 中按 F5:應用程序?qū)⒉渴鸩?,您應該會在設備輸出中看到這一點。
ADXL345_HC06.ino:
#include
#include
#define Register_ID 0
#define Register_2D 0x2D
#define Register_X0 0x32
#define Register_X1 0x33
#define Register_Y0 0x34
#define Register_Y1 0x35
#define Register_Z0 0x36
#define Register_Z1 0x37
int ADXAddress = 0xA7 >> 1;?
int reading = 0;
int val = 0;
int X0, X1, X_out;
int Y0, Y1, Y_out;
int Z1, Z0, Z_out;
double Xg, Yg, Zg;
void setup()
{
? Serial.begin(9600);
? Wire.begin();?
? delay(100);
? Wire.beginTransmission(ADXAddress);
? Wire.write(Register_2D);
? Wire.write(8);
? Wire.endTransmission();
}
void loop() {
? double tempx = 0;
? char strx[5];
? double tempy = 0;
? char stry[5];
? double tempz = 0;
? char strz[5];
??
? String gy;
? Wire.beginTransmission(ADXAddress);
? Wire.write(Register_X0);
? Wire.write(Register_X1);
? Wire.endTransmission();
? Wire.requestFrom(ADXAddress, 2);
? if (Wire.available() <= 2);
? {
? ? X0 = Wire.read();
? ? X1 = Wire.read();
? ? X1 = X1 << 8;
? ? X_out = X0 + X1;
? }
? Wire.beginTransmission(ADXAddress);
? Wire.write(Register_Y0);
? Wire.write(Register_Y1);
? Wire.endTransmission();
? Wire.requestFrom(ADXAddress, 2);
? if (Wire.available() <= 2);
? {
? ? Y0 = Wire.read();
? ? Y1 = Wire.read();
? ? Y1 = Y1 << 8;
? ? Y_out = Y0 + Y1;
? }
? Wire.beginTransmission(ADXAddress);
? Wire.write(Register_Z0);
? Wire.write(Register_Z1);
? Wire.endTransmission();
? Wire.requestFrom(ADXAddress, 2);
? if (Wire.available() <= 2);
? {
? ? Z0 = Wire.read();
? ? Z1 = Wire.read();
? ? Z1 = Z1 << 8;
? ? Z_out = Z0 + Z1;
? }
? Xg = X_out / 256.00;?
? Yg = Y_out / 256.00;
? Zg = Z_out / 256.00;
?
? if(Xg>0)
? {
? ? gy = String("")+ "x=+"+Xg;
? }
? else
? {
? ? gy = String("")+ "x="+Xg;
? }
??
? if(Yg>0)
? {
? ? gy += String("")+ "y=+"+Yg;
? }
? else
? {
? ? gy += String("")+ "y="+Yg;
? }
??
? if(Zg>0)
? {
? ? gy += String("")+ "z=+"+Zg+",";
? }
? else
? {
? ? gy += String("")+ "z="+Zg+",";
? }?
??
? Serial.print(gy);
}
評論
查看更多