Pulling data from Thinkpad APS sensor using C++

Recently, I have just discovered that my Thinkpad T60, along with many other Lenovo’s Thinkpad computers have this built-in accelerometer. So it pops up, I want to use the data from the sensor in my AIR application, through the use of native extensions.

So firstly, in order to write a native extension, which will pump out a DLL, I need to be able to use the sensor in a console C++ application first. It took me 2 weeks to get to the Pointers basic section in my C programming book, and about 3 days to learn to load a DLL and use its function.

As of now, I have been able to pull data from the sensor to my native application and calculate the tilt on the Y axis (which is the roll axis).  The tilt is a bit off, but it wouldn’t matter I don’t think. This has only been tested on a Thinkpad T60 Windows XP Sp3, x86.

So here is how I pulled ShockproofGetAccelerometerData from the sensor. If you have any optimizations, please suggest, but please also comment on how that works because I’m still very much new to C++.  Cheers.

/*
 * LoadSensorDLL.cpp
 *
 *  Created on: Feb 11, 2012
 *      Author: CONG NGUYEN
 *        
 */

#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <math.h>

struct AccelData
{
    int status;
    short x; //raw data
    short y; //raw data

    short xx; //avg. of 40ms
    short yy; //avg. of 40ms
    char temp; //raw value
    short x0; //used for auto-center
    short y0; //used for auto-center

};

using namespace std;

typedef void * (__stdcall *ShockproofGetAccelerometerData)(AccelData* accData);

//function prototypes
void calibrate(void);
void calibrateX();
void calibrateY();
short getAccelX();
short getAccelY();
double getRotationRadiansX();
double getRotationDegreesX();
double getRotationRadiansY();
double getRotationDegreesY();

//declare constants
const double PI = 3.141592;

//declare global variables
HINSTANCE hinstDLL;
AccelData accData = {0,0,0,0,0,0,0,0};
ShockproofGetAccelerometerData pfnGetData;
bool isSupported;

//declare global variables used for calibration and movement
short x_hor = 0;
short y_hor = 0;
short x_max = 0;
short y_max = 0;
double x_norm = 0.0;
double y_norm = 0.0;

double test = 0.0;

int main(void)
{
    int loop = 1;

    hinstDLL = LoadLibrary(L"Sensor.dll");

    if(hinstDLL == 0)
    {
        hinstDLL = LoadLibrary(L"sensor.dll");
    }

    if(hinstDLL == 0)
    {
        isSupported = false;
    }
    else
    {
        isSupported = true;
        pfnGetData = (ShockproofGetAccelerometerData) GetProcAddress((HINSTANCE) hinstDLL, "ShockproofGetAccelerometerData");
    }

    calibrate();
    calibrateX();
    calibrateY();

    cout << x_hor << ", " << y_hor << endl;
    cout << x_max << ", " << y_max << endl;

    cout << endl;
    cout << "Calibration completed.\n";
    getchar();
    cout << "TIlt 45 degrees. Press any keys to confirm.\n";
    getchar();
    cout << getRotationDegreesY();

    //end program
    getchar();
    FreeLibrary(hinstDLL);
    return 0;
}

short getAccelX()
{
    pfnGetData(&accData);
    return accData.x;
}

short getAccelY()
{
    pfnGetData(&accData);
    return accData.y;
}

void calibrate(void)
{
    cout << "Lay Thinkpad onto a flat and horizontal ground.\n";
    cout << "Press any key to continue.\n";
    if(getchar() == '\n')
    {
        x_hor = getAccelX();
        y_hor = getAccelY();
    }
}

void calibrateX()
{
    cout << "Pitch your Thinkpad a bit backwards.\n";
    cout << "Press any key, then rotate your Thinkpad back to normal position.\n";
    getchar();
    while(getAccelX() != x_hor)
    {
        if(getAccelX() > x_max)
        {
            x_max = getAccelX();
        }
    }
}

void calibrateY()
{
    cout << "Roll your Thinkpad to the right a bit.\n";
    cout << "Press any key, then rotate your Thinkpad back to normal position.\n";
    getchar();
    while(getAccelY() != y_hor)
    {
        if(getAccelY() > y_max)
        {
            y_max = getAccelY();
        }
    }
}

double getRotationRadiansX()
{
    x_norm = (double)((double)getAccelX() - (double)x_hor) / ((double)x_max - (double)x_hor);
    if(x_norm > 1)
    {
        x_norm = 1/x_norm;
    }
    return acos(x_norm);
}

double getRotationDegreesX()
{
    return getRotationRadiansX() * 180 / PI;
}

double getRotationRadiansY()
{
    y_norm = (double)((double)getAccelY() - (double)y_hor) / ((double)y_max - (double)y_hor);
    if(y_norm > 1)
    {
        y_norm = 1/y_norm;
    }
    return acos(y_norm);
}

double getRotationDegreesY()
{
    return getRotationRadiansY() * 180 / PI;
}
Advertisements

2 thoughts on “Pulling data from Thinkpad APS sensor using C++

    1. Hey Yeokm, I’m so sorry that I couldn’t reply to you sooner. WordPress didn’t notify me so I didn’t know until now. Go ahead and use the code, you probably have already. Thanks for reading!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s