White scenery @showyou, hatena

If you have any comments, you may also send twitter @shsub or @showyou.

OpenGL+TDS01V(3軸地磁気加速度気圧センサ)+TDControlを組み合わせて動かしてみた

動作環境

  • Vista(64bit)+VisualStudio2005Pro
  • XP(32bit)とかでも問題なく動くと思う

手順

TDS01Vのドライバを入れる

これはTDS01Vをマシンに刺してWindowsUpdateでドライバ検索すれば勝手に入ると思う

OpenGLを動かしてみる

OpenGL(GLUT)はhttp://akita-nct.jp/take/appendix/glsl/glsl_setting.html当たりを参考にしてインストールした。今回はVS2005Proを使ってるけどExpressEditionでもいけるはず。

TDControlのサンプルを使ってみる

http://futr.cocolog-nifty.com/blog/2007/09/tds01v_c_50c1_1.htmlからTDControlをダウンロードして、sample.exeでもいじってみる。

OpenGLとTDControlを組み合わせる

OpenGLで作ったサンプルに、TDControlを組み合わせて、TDControlで得た値を元にOpenGL上の物体を制御する。
ためしにこんなもの作ってみた。サンプルの切り貼り。。。

main.cpp(GL部分)

#include <GL/glut.h>
#include "tdsample.h"

TDSample tds;
GLdouble vertex[][3] = {
	{ 0.0, 0.0, 0.0 },
	{ 1.0, 0.0, 0.0 },
	{ 1.0, 1.0, 0.0 },
	{ 0.0, 1.0, 0.0 },
	{ 0.0, 0.0, 1.0 },
	{ 1.0, 0.0, 1.0 },
	{ 1.0, 1.0, 1.0 },
	{ 0.0, 1.0, 1.0 }
};

int edge[][2] = {
	{ 0, 1 },
	{ 1, 2 },
	{ 2, 3 },
	{ 3, 0 },
	{ 4, 5 },
	{ 5, 6 },
	{ 6, 7 },
	{ 7, 4 },
	{ 0, 4 },
	{ 1, 5 },
	{ 2, 6 },
	{ 3, 7 }
};

void idle(void)
{
	glutPostRedisplay();
}

void resize(int w, int h)
{
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(30, (double)w / (double)h, 1.0, 100.0);
	glMatrixMode(GL_MODELVIEW);
}

void display(void)
{
	int i;
	int r = tds.Loop();
	glClear(GL_COLOR_BUFFER_BIT);

	glLoadIdentity();
	/* 回転 */
	gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

	glRotated((double)r, 0.0, 1.0, 0.0);
	/* 図形描画 */
	glColor3d(0.0, 0.0, 0.0);
	glBegin(GL_LINES);
	for( i=0; i < 12; ++i ) {
		glVertex3dv(vertex[edge[i][0]]);
		glVertex3dv(vertex[edge[i][1]]);
	}
	glEnd();
	glFlush();
}

void init(void)
{
	tds.Init();
	glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA);
	glutCreateWindow(argv[0]);
	glutDisplayFunc(display);
	glutReshapeFunc(resize);
	glutIdleFunc(idle);
	init();
	glutMainLoop();
	return 0;
}

tdsample.cpp

#include"tdcontrol.h"
#include "tdsample.h"

static TDControl td;

int TDSample::Init(void)
{	
	// ----ここから接続処理-----------------------------------
	// COMポートを開く
	int port;
	printf("COM番号を入力してください >");
	scanf("%d",&port);
	
	if(td.OpenCom(port)){
		printf("オープン完了 %s\n",td.ComName);
	}else{
		printf("オープン失敗、終了します。\n");
		return -1;
	}
	
	// 開けたら設定
	if(td.SetCom()){
		printf("設定成功\n");
	}else{
		printf("設定失敗、終了します。\n");
		td.CloseCom();
		return -1;
	}
	// ----ここまで接続処理-----------------------------------
	
	/*printf("何か入力すると通信開始を開始します >");
	int a;
	scanf("%d",&a);*/

	// ----ここから初期化処理-----------------------------------
	// 自動初期化の場合
	if(!td.AutoStart(0,1001,0)){
		td.CloseCom();
		printf("自動初期化失敗!\n");
		return -1;
	}else{
		printf("初期化完了!\n");
		printf("CheckSystem = %d\n",td.CheckSystem);
		printf("RomVersion = %d\n",td.RomVersion);
	}
	return 0;
	// ----ここまで初期化処理-----------------------------------
}

int TDSample::Loop()
{
	// ----ここから受信処理-----------------------------------
	
	// 100回分データを受信
	//for(int i = 0;i < 100; i++){
		// 測定を開始(毎回必要)
		td.SendCommand(CMD_START);
		CheckCommand();
		// 受信(毎回必要)
		td.SendCommand(CMD_READ);
		CheckCommand();
	
		// ここでは気圧を表示
		// データはint型で生のまま保存されているので、必要に応じて割ってください(ここでは10)
		//printf("気圧 = (%3d) %10.1f",0,td.RecvData.Barometer / 10.0);
		printf("DirDeg = (%3d) %10.1f\r",0,td.RecvData.DirDeg / 10.0);
	//}
	// ----ここまで受信処理-----------------------------------
	return td.RecvData.DirDeg / 10.0;
}	

TDSample::~TDSample()
{
	// COMクローズ
	td.CloseCom();
	return;
}

//----------------------------------------------------------------------------------------------------
// 簡単なコマンド受信関数
// 
// この関数はデータが帰ってくるまで制御が戻らない上に、何らかのトラブルでデータが来なくなると無限ループが発生してしまうので、お勧めできません。
// ただ、非常に簡単に受信できるので、簡単に使いたいときは便利です。

void TDSample::CheckCommand(void)
{
	while(1){
		int ret = td.RecvCommand();
		if(ret == RECV_BAD){
			printf("BAD\n");
			break;
		}
		if(ret == RECV_GOOD){
			break;
		}
	}
}

tdsample.h

#ifndef __TDSAMPLE_H_
#define __TDSAMPLE_H_

class TDSample
{
public:
	//TDSample();
	~TDSample();
	int Init(void);
	int Loop(void);
	void CheckCommand(void);
};

#endif

tdcontrol.hは先のTDControl.lzhを解凍した中にあるものをプロジェクトにコピーした。
一箇所引っかかったのはglut.hとstdlib.hでexit関数がぶつかるみたいなので、同時には読まないようにした。

実行結果


全くもってわかりにくいとは思うのですが、TDS01Vに応じてOpenGL内の立方体が回転しています。

考察

TDS01Vはたまにとんでもない値をたたき出すので、中間値フィルタとか平滑化とかしたほうがいいでしょう。
あとこれだけだとネタとしてしょぼいのでもっと検出値でいろいろ遊びたいですね。

何はともあれ、電子関係に疎い私でも、意外と簡単に3軸地磁気加速度センサに触れたのでした。