Windows Phone 7 - 了解Sensor - Accelerometer

Windows Phone 7 - 了解Sensor – Accelerometer

在了解<Windows Phone 7 - 了解Sensor – Combined Motion API>介紹的內容後,該篇針對Accelerometer加以說明,

學習如何使用原始數據資訊,進一步處理需要的功能。由於Accelerometer影響的是線性加速度,因此運作的原理

是了解Accelerometer的重要部分,以下先介紹其運作原理。

 

〉方向性的運作概念圖

image

擷取<Using the Accelerometer on Windows Phone 7>中的一圖,說明Accelerometer採用三個維度:X、Y、Z,解釋設備

在空間運行的方式。透過一個公式來說三軸目前存在的意義:「G-forces (1G = 9.81 m/s2)」,因此,Z軸=1.0時,代表

目前手機的正面正往上方,相反地,Z軸=-1時,代表手機正面正往下方;

可參考<Windows Phone 7 Game Development: A Beginner’s Guide (Accelerometer)>介紹的圖示,更容易理解三軸的定義:

 

不過對於上圖的說明,如果你跟我一樣對空間概念比較不熟悉的話,可以捉住幾個重點:

‧X軸:代表手機的兩側,手機直立時,往右下角壓:X軸是正數增加;相反地,往左下角壓:X軸是負數增加;

‧Y軸:代表手機的頂部與底部,橫著拿時(左手捉住頂部,右手捉住底部),往右下角壓:Y軸是負數增加;往左下角壓:Y軸是正數增加;

‧Z軸:代表手機的正面與背面,正面對著天空時:Z軸是負數增加;背面對著天空時:Z軸是正數增加;

 

記熟這三個要點後,舉個例子來說明:

1. 假設想要做直立手機時進行左右搖擺,觸發一個事件,該注意那一個軸的變化?

     =>答案是:X軸;因為左右搖,改變最大數值是X軸與它速度的變化;

2. 假設想要做一個手機面對自己,做出求籤的動作時,該注意那一個軸的變數?

     =>答案是:Z軸;因為求籤時需正面與背面的晃動,因此它變數量最多;

3. 假設想要做手機放在口袋,手機頂部朝向地面時,該注意那一個軸的變數?

     =>答案是:Y軸;因為手機直立時,底部向下,如同橫立時往右下角壓,所以是負數,但頂部朝地,

          也代表,往左下角壓,Y軸會變成正數,剛好觸發事件。

 

 

以上是針對運作原理的說明,往下便開始針對WP7 SDK裡針對Accelerometer加以說明。

Accelermeter

     該API主要用於測量加速力,例如:重力、移動所產生的力量。所有的Windows Phone設備至少一定有Accelerometer

它支援Silverlight與XNA做為另一種輸入的方式。它屬於一種管理型的函式庫,放置於「Microsoft.Devices.Sensors」之中。

(A) 重點屬性

屬性 說明
IsSupported 設定/取得設備是否支援Accelerometer執行時所需要的感應器。該屬性不需要實例化Accelerometer類型可直接使用。
IsDataValid 取得感應器的資料是否具有效性。
CurrentValue 取得一個實作ISensorReading的物件,該物件包含感應器所收集的當前值。該物件可能是下列類型的其中一種:
AccelerometerReading
CompassReading
GyroscopeReading
MotionReading
TimeBetweenUpdates 設定/取得CurrentValueChanged事件之間發生的首選時間(preferred time)。
State 取得目前Acceelerometer的狀態。詳細資料來自SensorState列舉,如下:
‧NotSupported
‧Ready
‧Initializing
‧NoData
‧NoPermissions
‧Disabled

上述這些屬性均是在實作應用程式時,一定會使用的,包括檢查設備是否支援Accelerometer,是否取得的資料是有效的,

進一步使用當前的值去進行處理。

 

(B) 重點事件

事件 說明
CurrentValueChanged 該事件發生當有新的數據資料被Sensor擷取到時。
發生的頻率,根據TimeBetweenUpdates屬性設定時間而定。

 

(B-1) SensorReadingEventArgs<AccelerometerReading>

           實作CurrentValueChanged事件時,SensorReadingEventArgs<T> Class該類別提供CurrentValueChanged事件主要的觸發來源,

AccelerometerReading來說,它是主要記錄目前設備在這個時間點的Accelerometer所擷取到的數據資料,往下說明其結構:

屬性 說明
Acceleration 取得設備的線性加速度(linear acceleration),以G力(gravitational)為單位。
Timestamp 取得AccelerometerReading計算的時間戳的時間,這可用於關聯整個Sensor取得數據與計算原始資料的演算法。

 

在上述了解完Accelerometer的基本結構後,往下便說明如何使用該API。

 

〉範例說明
    在說明範例時,如果沒有實體設備可以測試的話,可以參考<How to: Test Applications that Use the Accelerometer>

的介紹,透過模擬器一樣可以模擬Accelerometer的功能協助範例的測試。

 

該範例為呈現當橫著拿時(左手捉住頂部,右手捉住底部)時,監測Accelerometer在Y軸變化時,圖示自動往左或往右的簡易範例,:

(1) 加入Microsoft.Devices.Sensors與using Microsoft.Xna.Framework參考與增加MainPage.xaml中要呈現的圖示

   1: <!--ContentPanel - place additional content here-->
   2: <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
   3:     <Button Content="Start" Height="72" HorizontalAlignment="Left" Margin="20,10,0,0" Name="startButton" VerticalAlignment="Top" Width="160" Click="startButton_Click" />
   4:     <Button Content="Stop" Height="72" HorizontalAlignment="Right" Margin="0,10,20,0" Name="stopButton" VerticalAlignment="Top" Width="160" Click="stopButton_Click"/>
   5:     <TextBlock Height="30" HorizontalAlignment="Left"  Margin="20,100,0,0" Name="xTextBlock" Text="X: 1.0" VerticalAlignment="Top" Foreground="Red" FontSize="28" FontWeight="Bold"/>
   6:     <TextBlock Height="30" HorizontalAlignment="Center"  Margin="0,100,0,0" Name="yTextBlock" Text="Y: 1.0" VerticalAlignment="Top" Foreground="Green" FontSize="28" FontWeight="Bold"/>
   7:     <TextBlock Height="30" HorizontalAlignment="Right"  Margin="0,100,20,0" Name="zTextBlock" Text="Z: 1.0" VerticalAlignment="Top"  Foreground="Blue" FontSize="28" FontWeight="Bold"/>
   8:     <TextBlock Height="30" HorizontalAlignment="Center" Margin="6,571,6,0" Name="statusTextBlock" Text="TextBlock" VerticalAlignment="Top" Width="444" />
   9:     <!-- 加上要呈現的圖示範圍 -->
  10:     <!-- 設定Margin以調整圖示於中間 -->
  11:     <Canvas x:Name="cvsImg" Margin="150,250,0,0">
  12:         <Image x:Name="imgSource" Width="150" 
  13:                Height="200" Source="/Images/a.jpg">
  14:             <!-- 定義RenderTransform做為效果呈現的功能-->
  15:             <Image.RenderTransform>
  16:                 <TranslateTransform x:Name="translation" />                       
  17:             </Image.RenderTransform>
  18:         </Image>
  19:     </Canvas>           
  20: </Grid>

圖示放置於Images目錄裡,並且設定圖示呈現的樣式。

 

(2) 註冊Accelerometer,並檢查設備是否支援Accelerometer感應器

   1: public MainPage()
   2: {
   3:     InitializeComponent();
   4:     //在建構子即檢查是否支援Accelerometer感應器
   5:     Init();
   6: }
   7:  
   8: Accelerometer gAccelerometer;
   9:  
  10: /// <summary>
  11: /// 檢查該設備是否支援Accelerometer感應器;
  12: /// </summary>
  13: private void Init()
  14: {
  15:     if (!Accelerometer.IsSupported)
  16:     {
  17:         statusTextBlock.Text = "設備不支援Accelerometer感應器。";
  18:         startButton.IsEnabled = false;
  19:         stopButton.IsEnabled = false;
  20:     }
  21: }

 

(2) 註冊啟動與關閉Accelerometer感應器,並設定啟動監控CurrentValueChanged

   1: private void startButton_Click(object sender, RoutedEventArgs e)
   2: {
   3:     if (gAccelerometer == null)
   4:     {
   5:         // 實例化Accelerometer
   6:         gAccelerometer = new Accelerometer();
   7:         // 設定擷取Accelerometer的首選時間
   8:         gAccelerometer.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20);
   9:         // 註冊處理CurrentValueChanged的事件
  10:         gAccelerometer.CurrentValueChanged +=
  11:             new EventHandler<SensorReadingEventArgs<AccelerometerReading>>
  12:                     (accelerometer_CurrentValueChanged);
  13:     }
  14:  
  15:     try
  16:     {
  17:         statusTextBlock.Text = "啟動... accelerometer感應器";
  18:         // 正式啟動
  19:         gAccelerometer.Start();
  20:     }
  21:     catch (InvalidOperationException ex)
  22:     {
  23:         //啟動失敗
  24:         statusTextBlock.Text = "無法啟動... accelerometer感應器";
  25:     }
  26: }
  27:  
  28: private void stopButton_Click(object sender, RoutedEventArgs e)
  29: {
  30:     if (gAccelerometer != null)
  31:     {
  32:         // 關閉Accelerometer感應器.
  33:         gAccelerometer.Stop();
  34:         statusTextBlock.Text = "關閉... accelerometer感應器";
  35:     }
  36: }

 

(3) 處理發生CurrentValueChanged事件時,Y軸正/負值影響圖示移動的方式

   1: /// <summary>  
   2: /// 處理Accelerometer感應器取得的數據資料,使用AccelerometerReading物件;  
   3: /// </summary>   
   4: void accelerometer_CurrentValueChanged(object sender,    
   5:                          SensorReadingEventArgs<AccelerometerReading> e)   
   6: {   
   7:     // 由於Accelerometer與UI Thread屬於不同的Thread,呼叫Dispatcher來更新UI Thread的內容。   
   8:     // 將SensorReading (AccelerometerReading)送至UpdateUI方法中。   
   9:     Dispatcher.BeginInvoke(() => UpdateUI(e.SensorReading));  
  10: }  
  11:  
  12: /// <summary>  
  13: /// 實際更新畫面元件的方法。  
  14: /// </summary>  
  15: private void UpdateUI(AccelerometerReading accelerometerReading)  
  16: {      
  17:     statusTextBlock.Text = "取得資料..."; 
  18:     //將AccelerometerReading的值轉成Vertor3,三維度的內容值。  
  19:     Vector3 acceleration = accelerometerReading.Acceleration;  
  20:     
  21:     //顯示三軸變化的數據。  
  22:     xTextBlock.Text = "X: " + acceleration.X.ToString("0.00"); 
  23:     yTextBlock.Text = "Y: " + acceleration.Y.ToString("0.00");  
  24:     zTextBlock.Text = "Z: " + acceleration.Z.ToString("0.00");  
  25:     
  26:     //使用Image定義的RenderTransform來進行圖示的移動  
  27:     
  28:     if (acceleration.Y < 0) 
  29:         // Y為負,代表右下角被往下壓,要往畫面右邊,要將Y轉成正數
  30:         translation.X = Math.Abs(acceleration.Y) * 200;
  31:     else
  32:         // Y為正,代表左下角被往下壓,要往畫面左邊,要將Y轉成負數
  33:         translation.X = acceleration.Y * -200;
  34: }

 

(4) 執行結果

4-0. 執行前的樣子

image

 

4-1. 移動Y軸,讓Y軸形成為-1值,圖示由左移動至右

image

 

4-2. 移動Y軸,讓Y軸形成為1值,圖示由右移動至左

image

======

以上是介紹有關Accelerometer的使用,對於Sensor的使用在Silverlight Application使用的情境蠻多的,

可以讓整個App增加不少樂趣,也可以當作另一種的輸入方式,不妨思考一下自己的App那裡可以使用,

但也別忘記要識別該設備是否有支援該Sensor。分享給大家,希望有所幫助。

 

References:

Accelerometer for Windows Phone (重要)

Using the Accelerometer on Windows Phone 7 (重要)

Sensors for Windows Phone & Sensors Overview for Windows Phone

How to: Get Data from the Accelerometer Sensor for Windows Phone

How to: Use Reactive Extensions to Emulate and Filter Accelerometer Data for Windows Phone

How-to: 利用Web Camera模拟Windows Phone 7的重力加速度传感器

给你的Windows Phone 7模拟器加入GPS和加速度传感器模拟功能

Retrieving Accelerometer Input (Windows Phone)

Introduction to using WP7 Accelerometer

WP7 Code: Using the Accelerometer API

WP7(accelerometer)重力感应编程

Windows Phone 7 Game Development: A Beginner’s Guide (Accelerometer)

 

Dotblogs Tags: