传感器技术的发展增强了移动设备用户的体验。传感器的种类有很多,常见的有加速计、陀螺仪、测斜仪、方向传感器等。本章将介绍如何利用传感器API获得设备旋转的角速度、线性运动的加速度、设备倾斜角度、设备方向、氛围光、地理位置以及近场通信等,开发人员可以综合使用传感器提供的数据开发出内容丰富的Windows应用商店应用

1响应运动的传感器

程序员可根据设备的运动来开发应用程序,例如通过晃动设备对屏幕截图,使用加速计捕获设备的晃动可以实现此功能。本节将介绍能测量设备角速度的陀螺仪、可用来测量设备加速运动的加速计以及可获取设备倾斜度的测斜仪,这些传感器由Windows.Devices.Sensors命名空间提供支持。

1.1陀螺仪

陀螺仪传感器能测量设备在空间坐标中围绕X轴、Y轴和Z轴的旋转角速度。陀螺仪可以用于协助GPS定位,导航软件使用陀螺仪显示偏转角速度,若GPS信号丢失,陀螺仪能够快速测出方向和角速度的改变,从而使导航软件及时修改导航路线。下面通过示例介绍陀螺仪API的使用。

新建一个Windows应用商店的空白应用程序项目,并命名为GyrometerExample,在MainPage.xaml文件的Grid元素中添加如下代码。

<Canvas>

<!--基于事件的被动获取-->

    <TextBlock  Text="基于事件的被动获取" FontSize="18" Canvas.Left="394" Canvas.Top="183"/>

    <Button Content="获取" Name="StartButton" Canvas.Left="394" Canvas.Top="212" Click="GetData_Click" Width="62"/>

    <Button Content="停止" Name="CloseButton"  Canvas.Left="470" Canvas.Top="212" Click="CloseData_Click"/>

<!--文本控件-->

    <TextBlock Text="获取陀螺仪读数"  FontSize="20" Canvas.Left="394" Canvas.Top="37"></TextBlock>

    <TextBlock Text="X" FontSize="18" Canvas.Left="394" Canvas.Top="84"/>

    <TextBlock Text="为空"  FontSize="18" Canvas.Left="470" Canvas.Top="84" Name="ScenarioOutput_X" Width="53"/>

    <TextBlock Text="Y"  FontSize="18" Canvas.Left="394" Canvas.Top="111"/>

    <TextBlock Text="为空"  FontSize="18" Canvas.Left="470" Canvas.Top="112" Name="ScenarioOutput_Y" Width="53"/>

    <TextBlock Text="Z" FontSize="18" Canvas.Left="394" Canvas.Top="139"/>

    <TextBlock Text="为空"  FontSize="18" Canvas.Left="470" Canvas.Top="139" Name="ScenarioOutput_Z" Width="53"/>

    <TextBlock Name="InfoText" Width="200" FontSize="18" Canvas.Left="394" Canvas.Top="309"/>

<!--基于计时器的主动获取-->

    <TextBlock Text="基于计时器的主动获取" FontSize="18" Canvas.Left="394" Canvas.Top="282"></TextBlock>

 <!--触发事件的按钮-->

 <Button Content="获取" Name="DispatcherButton" Click="Dispatcher_Click" Canvas.Left="394" Canvas.Top="316"></Button>

    <Button Content="停止" Name="CloseDispatcherButton" Click="CloseDispatcher_Click" Canvas.Left="470" Canvas.Top="316"></Button>

</Canvas>

在上面的代码中,放置了多个显示信息的TextBlock控件,其中有3个用于显示陀螺仪数据。然后又添加了4个按钮,并为这4个按钮定义了事件处理方法,其中有两个用于启动陀螺仪数据获取,另外两个按钮则用于停止数据获取。

前台运行效果如图12-1所示。

J8LX(4H)W53M$ZB3G6X2TAI

 

12-1 显示陀螺仪读数的界面

布局好前台界面后,接下来介绍如何从陀螺仪传感器获取读数。首先在后台定义几个全局变量并在构造方法中初始化,以便在后续代码中使用。代码如下所示:

private Gyrometer gyrometer;

//期望的时间间隔

private uint desiredReportInterval;

//定义一个计数器

private DispatcherTimer dispatcherTimer;

public MainPage()

{

    this.InitializeComponent();

    gyrometer = Gyrometer.GetDefault();

    if (gyrometer != null)

    {

      //获取报告间隔

        uint minReportInterval = gyrometer.MinimumReportInterval;

        desiredReportInterval = minReportInterval > 16 ? minReportInterval : 16;

       //设置按钮为不可交互状态

        CloseButton.IsEnabled = false;

        CloseDispatcherButton.IsEnabled = false;

//初始化一个计时器

dispatcherTimer = new DispatcherTimer();

    }

else

    {

        InfoText.Text = "未发现陀螺仪设备";

    }

}

在上面的代码中,使用Gyrometer.GetDefault方法获得陀螺仪传感器的引用对象gyrometer,如果gyrometer对象为空,在前台界面提示“未发现陀螺仪设备”。

陀螺仪传感器以一个时间间隔来报告读数,这个间隔称为当前报告间隔,此间隔以毫秒为单位,使用gyrometer对象的MinimumReportInterval属性能获得陀螺仪的最小报告间隔,然后将它与16毫秒进行比较,如果大于16毫秒,则将desiredReportInterval变量设置成设备所支持的最短间隔,否则,将它设置为16毫秒。值得注意的是当前报告间隔设置的越长,设备的改变灵敏度就会越大开发者可根据应用的需要设置报告间隔,选择合适的灵敏度数据,表12-1列出了报告间隔与改变灵敏度的关系对照。

12-1陀螺仪当前报告间隔与改变灵敏度的关系

当前报告间隔(毫秒)

改变灵敏度(度/秒)

1 ms ~ 16 ms

0.1(/)

17 ms ~ 32 ms

0.5(/)

>= 33 ms

                              1.0(/)

接下来对Name属性为“StartButton”按钮添加GetData_Click事件处理方法,单击这个按钮启动陀螺仪读数捕获。代码如下所示:

private void GetData_Click(object sender, RoutedEventArgs e)

{

    if (gyrometer != null)

    {

        //设置报告间隔

        gyrometer.ReportInterval = desiredReportInterval;

//注册方法

        gyrometer.ReadingChanged += new TypedEventHandler<Gyrometer, GyrometerReadingChangedEventArgs>(GetChangedData);

       //设置按钮的状态

        StartButton.IsEnabled = false;

        CloseButton.IsEnabled = true;

    }

    else

    {

        InfoText.Text = "陀螺仪设备不可用";

    }

}

在上面的事件处理程序中,为gyrometer对象的ReadingChanged事件添加了事件处理方法GetChangedData,当陀螺仪传感器驱动程序捕获到设备的旋转动作发生改变时,会触发ReadingChanged事件进而执行GetChangedData方法,下面来看一下GetChangedData方法的实现代码。

GetChangedData方法中,定义了获取陀螺仪数据并将数据显示到前台界面的过程,具体代码如下所示:

async private void GetChangedData(object sender, GyrometerReadingChangedEventArgs e)

{

    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>

    {

//陀螺仪数据对象

        GyrometerReading reading = e.Reading;

//获取设备X轴的角速度

        ScenarioOutput_X.Text = String.Format("{0,5:0.00}", reading.AngularVelocityX);

//获取设备Y轴的角速度

ScenarioOutput_Y.Text = String.Format("{0,5:0.00}", reading.AngularVelocityY);

//获取设备Z轴的角速度

  ScenarioOutput_Z.Text = String.Format("{0,5:0.00}", reading.AngularVelocityZ);

    });

}

在上面的方法中,首先从参数e中获得GyrometerReading类型的对象reading,根据reading对象的AngularVelocityX属性获取设备围绕X轴的角速度,将它显示在ScenarioOutput_X控件中,接着使用reading对象的AngularVelocityYAngularVelocityZ属性获取设备在Y轴、Z轴的旋转角速度,方法中调用了String.Format方法设置输出数据的格式以增加数据的可读性。为了避免UI线程的阻塞,使用调度器DispatcherRunAsync方法异步实现上述过程。

为“停止”按钮添加单击事件处理方法CloseData_Click(),当单击“停止”按钮时停止陀螺仪数据获取,CloseData_Click方法的代码如下所示:

private void CloseData_Click(object sender, RoutedEventArgs e)

{

    if (gyrometer != null)

    {

      //移除事件处理程序

        gyrometer.ReadingChanged -= new TypedEventHandler<Gyrometer, GyrometerReadingChangedEventArgs>(GetChangedData); 

       //设置“开始“按钮为可激活状态,“停止”按钮不可用   

        StartButton.IsEnabled = true;

        CloseButton.IsEnabled = false;

    }

    else

    {

        InfoText.Text = "未发现陀螺仪设备";

    }

}

在之前介绍获取传感器数据时,通过为gyrometer对象的ReadingChanged事件添加了一个GetChangedData方法来捕获陀螺仪改变时的数据,在上面的CloseData_Click事件方法中只是简单的将此事件处理方法移除掉,这样便可以停止传感器数据的捕获。

在上面的示例中,是通过在设备状态改变事件中添加事件处理方法的方式,被动的实现角速度信息的捕获。除了这种方法外,我们还可以利用计时器,通过每隔一段时间定时读取设备数据的方式,一次或者多次获得传感器数据,下面来看一下这种方法是如何实现的。

Name属性为“DispatcherButton”的按钮的单击事件添加事件处理方法Dispatcher_Click(),在该方法中为声明好的全局计时器对象dispatcherTimerTick事件添加一个事件处理方法DisplayCurrentReading,接着使用TimeSpan类定义一个时间段,用于设置计时器的时间间隔,然后调用dispatcherTimer对象的Start方法启动计时器。代码如下所示:

private void Dispatcher_Click(object sender, RoutedEventArgs e)

{

//给计时器添加处理程序

    dispatcherTimer.Tick += DisplayCurrentReading;

   //设置计时器的时间间隔为desiredReportInterval毫秒

    dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, (int)desiredReportInterval);

   //启动时器

    dispatcherTimer.Start();

    DispatcherButton.IsEnabled = false;

    CloseDispatcherButton.IsEnabled = true;

}

接下来定义Tick事件的处理方法DisplayCurrentReading,用来在每次Tick事件触发时,获取陀螺仪数据并将数据显示在前台界面,代码如下所示:

//获取传感器读数

private void DisplayCurrentReading(object sender, object args)

{

   //初始化GyrometerReading类的reading属性

    GyrometerReading reading = gyrometer.GetCurrentReading();

    if (reading != null)

    {

//获得读数

        ScenarioOutput_X.Text = String.Format("{0,5:0.00}", reading.AngularVelocityX);

        ScenarioOutput_Y.Text = String.Format("{0,5:0.00}", reading.AngularVelocityY);

        ScenarioOutput_Z.Text = String.Format("{0,5:0.00}", reading.AngularVelocityZ);

    }

}

在上面的代码中,使用gyrometer对象的GetCurrentReading方法获得代表当前传感器状态的GyrometerReading类型的对象reading,然后将获取到的数据显示到应用界面。这种方法通过dispatcherTimer对象定期触发Tick事件主动读取传感器状态的数据。下面来看一下停止主动读取传感器数据的方法。

Name属性为“CloseDispatcherButton”的按钮添加单击事件处理方法CloseDispatcher_Click,在这个方法中调用dispatcherTimer对象的Stop方法关闭计时器,这样便可以停止获取陀螺仪数据,代码如下所示:

//关闭计时器

private void CloseDispatcher_Click(object sender, RoutedEventArgs e)

{

    dispatcherTimer.Stop();

    DispatcherButton.IsEnabled = true;

    CloseDispatcherButton.IsEnabled = false;

}

启动调试,便可以看到运行界面,下面以“基于事件的被动获取”为例介绍操作过程。

单击“获取”按钮后,“获取”按钮将转变为不可用状态,界面上显示当前设备陀螺仪传感器的角速度信息。“停止”按钮变为可激活状态。

单击“停止”按钮,将停止更新角速度信息,此时“停止”按钮变为不可用,“获取”按钮变为可激活。二者相互配合像“开关”一样控制数据的显示。程序运行效果如图12-2所示

NI7NQ6CTXU[(@$Q_W3M`USV

 

12-2 获取陀螺仪读数的效果图

    上面的示例用两种方法实现了陀螺仪传感器数据的捕获,程序员根据应用的需求选择合适的方法。另外还要注意,在测试本示例时应确保测试设备支持陀螺仪传感器。

 

 

       注:本文选自自机械工业出版社3月出品的《Windows 8 应用开发权威指南》第12章 传感器

posted on 2013-04-12 13:55  冯瑞涛  阅读(696)  评论(3编辑  收藏  举报