×
Namespaces

Variants
Actions
(Difference between revisions)

Archived:Reducing accelerometer sensor noise on Symbian

From Nokia Developer Wiki
Jump to: navigation, search
tapla (Talk | contribs)
(New page: __NOTOC__ __NOEDITSECTION__ {|style="background:#eceff2" width="660px" border="1" cellpadding="5" cellspacing="0" |- |'''ID''' ||   |'''Creation date''' || April 18, 2008 |- |'''Pla...)
 
Forum Nokia KB (Talk | contribs)
m (Protected "Reducing accelerometer sensor noise" [edit=sysop:move=sysop])

Revision as of 10:55, 22 April 2008


ID   Creation date April 18, 2008
Platform S60 3rd Edition, MR Tested on devices Nokia N95 8GB
Category Symbian C++ Subcategory Hardware, Sensor


Keywords (APIs, classes, methods, functions): MRRSensorDataListener, TRRSensorInfo, TRRSensorEvent, MRRSensorDataListener::HandleDataEventL()

Overview

Sometimes the accelerometer sensor produces quite a lot of noise (i.e. unwanted data). This can be perceived for example by putting the device on the table while observing the produced data. The values should stay more or less stable while the device is on the table. However, this is not the case because of the noise.

This code snippet demonstrates how to reduce the noise from the accelerometer sensor. The technique used in this snippet is to create a circular buffer (a.k.a. a ring buffer) and continuously fill it with data produced by the sensor. As a result, "raw" sensor data is not used, but instead an average value of the buffer contents. This effectively smooths the values, which is perceived in practice as reduction of the noise.

Registering listeners for the sensors and displaying sensor data are not covered in this snippet. For that, you may want to see CS000888 - Listening for accelerometer sensor data events and Displaying sensor data.

Note: In order to use the code, you need to install the sensor plugin for your SDK.

This snippet can be self-signed.

MMP file

The following libraries are required:

LIBRARY  RRSensorApi.lib
LIBRARY gdi.lib

Header file: CSensorDataFilter.h

#ifndef __CSENSORDATAFILTER_H_
#define __CSENSORDATAFILTER_H_
 
#include <e32base.h> // CBase
 
// Size of the data buffer. The smaller the value, the quicker the reaction
// speed to the changes in the sensor data. However, at the same time, the
// amplitude of noise from the sensor is higher.
const TInt KDataBufferSize = 16;
 
class CSensorDataFilter : public CBase
{
public: // Constructors and destructor
/**
* Two-phased constructor.
*/

static CSensorDataFilter* NewL();
 
/**
* Destructor.
*/

~CSensorDataFilter();
 
private: // Private constructors
/**
* Two-phased constructor.
*/

void ConstructL();
 
/**
* Default constructor.
*/

CSensorDataFilter();
 
public: // New functions
/**
* Calculates the average value from the buffer contents after adding
* a new value to it.
* @param aNewValue a new value to add to the buffer
* @return the average value of the buffer contents
*/

TInt FilterSensorData(TInt aNewValue);
 
private: // Data
TInt* iRingBuffer;
TInt* iRingBufferPointer;
};
 
#endif /*__CSENSORDATAFILTER_H_*/

Source file: CSensorDataFilter.cpp

#include "CSensorDataFilter.h"
 
CSensorDataFilter* CSensorDataFilter::NewL()
{
CSensorDataFilter* self = new (ELeave) CSensorDataFilter();
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
 
CSensorDataFilter::CSensorDataFilter()
{
// No implementation required
}
 
void CSensorDataFilter::ConstructL()
{
// Allocate a ring buffer to hold the sensor data
iRingBuffer = new (ELeave) TInt[KDataBufferSize];
 
// Clear the buffer
memset(iRingBuffer, '\0', KDataBufferSize * sizeof(TInt));
 
// Set the buffer pointer to the beginning of the buffer
iRingBufferPointer = iRingBuffer;
}
 
CSensorDataFilter::~CSensorDataFilter()
{
delete iRingBuffer;
}
 
TInt CSensorDataFilter::FilterSensorData(TInt aNewValue)
{
// Add the new value to the buffer, at the current position
*iRingBufferPointer = aNewValue;
 
// Move the pointer, circulating it to the beginning if the buffer is full
iRingBufferPointer++;
if (iRingBufferPointer >= (iRingBuffer + (KDataBufferSize - 1)))
{
iRingBufferPointer = iRingBuffer;
}
 
// Calculate the average of the buffer values
TInt sum = 0;
for (TInt i = 0; i < KDataBufferSize; i++)
{
sum = sum + iRingBuffer[i];
}
return (sum / KDataBufferSize);
}

Header file: CMyControl.h

#include <RRSensorApi.h>
 
#include "CSensorDataFilter.h"
// Accelerometer sensor UID
const TInt KAccelerometerSensorUID = 0x10273024;
class CMyControl : public CCoeControl, public MRRSensorDataListener
{
// ...
 
private: // Functions from base classes
/**
* From MRRSensorDataListener.
* Callback function for receiving sensor data events.
*
* @param aSensor identifies the sensor that created the event.
* @param aEvent contains data about created event.
*/

void HandleDataEventL(TRRSensorInfo aSensor, TRRSensorEvent aEvent);
 
private: // Data
CRRSensorApi* iAccelerometerSensor;
TInt iAccSensorDataX;
TInt iAccSensorDataY;
TInt iAccSensorDataZ;
CSensorDataFilter* iSensorDataFilterX;
CSensorDataFilter* iSensorDataFilterY;
CSensorDataFilter* iSensorDataFilterZ;
}

Source file: CMyControl.cpp

#include <RRSensorApi.h>
 
#include "CSensorDataFilter.h"
void CMyControl::ConstructL(const TRect& aRect)
{
// ...
 
// Reset sensor data
iAccSensorDataX = 0;
iAccSensorDataY = 0;
iAccSensorDataZ = 0;
 
// Create sensor data filters
iSensorDataFilterX = CSensorDataFilter::NewL();
iSensorDataFilterY = CSensorDataFilter::NewL();
iSensorDataFilterZ = CSensorDataFilter::NewL();
 
// ...
}
CMyControl::~CMyControl()
{
// ...
 
// Delete sensor data filters
delete iSensorDataFilterX;
delete iSensorDataFilterY;
delete iSensorDataFilterZ;
}
/**
* Gets called whenever a data event occurs.
*/

void CMyControl::HandleDataEventL(TRRSensorInfo aSensor, TRRSensorEvent aEvent)
{
// A data event occurred. Store new values from the accelerometer sensor.
switch (aSensor.iSensorId)
{
case KAccelerometerSensorUID:
{
// Smooth sensor data with some filtering to reduce noise
iAccSensorDataX = iSensorDataFilterX->FilterSensorData(
aEvent.iSensorData1);
iAccSensorDataY = iSensorDataFilterY->FilterSensorData(
aEvent.iSensorData2);
iAccSensorDataZ = iSensorDataFilterZ->FilterSensorData(
aEvent.iSensorData3);
}
break;
default:
break;
}
}

Postconditions

Data received from accelerometer sensor is run through a filter to reduce noise.

See also

136 page views in the last 30 days.
×