Search code examples
c#windows-runtimewindows-phone-8.1accelerometerwin-universal-app

Accelerometr stops after a while


In my App i tried to use acceletometr and it works, but it stops after a while. I don't know why becouse I Run it async.

public void initAccelerometr()
{
    var _accelerometer = Accelerometer.GetDefault();
    if (_accelerometer != null)
    {
        // Establish the report interval
        _accelerometer.ReportInterval = 2;

        _accelerometer.ReadingChanged += new TypedEventHandler<Accelerometer, AccelerometerReadingChangedEventArgs>(accelerometrReadingChanged);
    }
    else  {   /* not supported  */   }
}

async private void accelerometrReadingChanged(object sender, AccelerometerReadingChangedEventArgs e)
{
    var dispatcher = Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher;
    await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        AccelerometerReading reading = e.Reading;
        AccelerometrZ = String.Format("{0,5:0.0000}", reading.AccelerationZ);
    });
}

Sometimes when I moving the phone it works all the time but sometimes it works only for a few seconds.


Solution

  • As I've tested there are couple of things you need to change:

    • you don't consult your report interval with the minimum value (probably). On my phone (Lumia 820) it's 10 miliseconds - and as I think it's really low (2 ms - huh - it's not a phone it's nice measuring device ;). Also MSDN says:

      The application should consult the MinimumReportInterval property prior to setting the report interval to ensure that the sensor can honor the requested report interval. Setting a value below the minimum supported interval will either trigger an exception or have undefined results.

    • second thing - I think your _accelerometer may be garbage collected - you define it as a local variable, I've moved it to MainPage class:

      Accelerometer _accelerometer;
      public void initAccelerometr()
      {
          _accelerometer = Accelerometer.GetDefault();
          if (_accelerometer != null)
          {
              Debug.WriteLine("Minimum report interval is: {0}", _accelerometer.MinimumReportInterval);
              _accelerometer.ReportInterval = _accelerometer.MinimumReportInterval;
              _accelerometer.ReadingChanged += new TypedEventHandler<Accelerometer, AccelerometerReadingChangedEventArgs>(accelerometrReadingChanged);
          }
      }
      

    With those two things above my accelerometer runs for 10 minutes and can't stop. I think also that firing Dispatcher every 10 miliseconds is not a good idea, I would save accelerometer values somewhere and use for example DispatcherTimer to show them:

    DispatcherTimer dTimer;
    public MainPage()
    {
        this.InitializeComponent();
        this.Loaded += (sender, e) =>
            {
                initAccelerometr();
                dTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(100) };
                dTimer.Tick += (sa, ea) => myText.Text = acceletometerValue;
                dTimer.Start();
            };
    }
    
    string acceletometerValue;
    private void accelerometrReadingChanged(object sender, AccelerometerReadingChangedEventArgs e)
    {
        acceletometerValue = String.Format("{0,5:0.0000}", e.Reading.AccelerationZ);
    }