立命館守山高校 Sci-tech部 ダイセン多機能電子コンパスをArduinoで動かす

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

ダイセン多機能電子コンパスをArduinoで動かす

Arduino
凄い。
正直舐めてました。

PICでI2C組めと言われたら気が滅入りそうですが、Arduinoなら10分で作れます。
ダイセンの多機能電子コンパスにしても、Arduinoならライブラリのおかげで下に書いただけだけのプログラムで読み込みが出来ます。
共用体みたいなマイナーなテクニック使うよりもビットシフトの方が解りやすい気がしますが気にしない。
e-Gadgetからデータを転送するプログラムをちょっと書き換えただけなので

#include <wire.h>

void setup(){
Wire.begin();//I2C通信開始
Serial.begin(9600);//シリアル通信開始
}

void loop(){
int a;
a = getDir(0);
Serial.println(a); //シリアルで転送
delay(100);
}

//------------------------------------------------------------------------------
//ダイセンの多機能電子コンパスから角度を読み込みます。
// dno:0(dir回転), 1(pitch前後), 2(roll左右)
unsigned int getDir(unsigned char dno){
typedef union { //受信データ用共用体
unsigned int W;
struct {
unsigned char L;
unsigned char H;
};
} U_UINT;
U_UINT data; // 受信データ
int adrs = 0x50>>1; //スレーブアドレス
int reg; //レジスターアドレス

reg = 0x20 + dno * 2;

//通信開始
Wire.beginTransmission(adrs);
//register
Wire.send(reg);
//通信終了
Wire.endTransmission();

Wire.requestFrom(adrs, 2);
if(Wire.available()>1){
//1バイト分のデータの読み込み
data.H = Wire.receive();
//次の1バイト分のデータを読み込み
data.L = Wire.receive();
}

return (data.W);
}



このセンサ、3軸方位と3軸加速度を使って正確に方位を出してくれるだけでなく、各々のデータも出すことが出来るのでかなり優秀で便利です。

ちなみにレジスター一覧は
http://www.daisendenshi.com/cart/images/DSR-1005/manual_DSR-1005_ver100830.pdf
の11ページに載ってます。

以下はこのソースの解説。
うちの部員とか解ってない人向けです。


ということで、部員向けに説明していきます。
ArduinoはCベースですが、関数はsetup()とloop()だけで動きます。
コンパイルする前に変換してくれるので、プロトタイプ宣言も不要です。

#include <wire.h>

void setup(){
Wire.begin();//I2C通信開始
Serial.begin(9600);//シリアル通信開始
}


これは説明要りませんよね。
どちらも初期化です。


void loop(){
int a;
a = getDir(0);
Serial.println(a); //シリアルで転送
delay(100);
}

下の関数getDir()で所得した数値をaに入れて、それをシリアルでPCに転送しています。

ここからが角度を返す関数。引数にによって3種類の軸の角度を返します。
//------------------------------------------------------------------------------
//ダイセンの多機能電子コンパスから角度を読み込みます。
// dno:0(dir回転), 1(pitch前後傾き), 2(roll左右傾)
unsigned int getDir(unsigned char dno){
typedef union { //受信データ用共用体
unsigned int W;
struct {
unsigned char L;
unsigned char H;
};
} U_UINT;
U_UINT data; // 受信データ
int adrs = 0x50>>1; //スレーブアドレス
int reg; //レジストリアドレス
typedef union { //受信データ用共用体
unsigned int W;
struct {
unsigned char L;
unsigned char H;
};
} U_UINT;
U_UINT data; // 受信データ

これが一番意味不明だと思いますが、共用体というテクニックです。
union.jpg
U_UINTというint(1bit)の型の中にchar(1bit)の型を二つ入れています。
Hが10101010 Lが00001111だとすると
Wは1010101000001111になります。

int adrs = 0x50>>1;
ビットシフトが何か解らないという人に。
http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=803
I2Cのアドレスは7bitなので、16進2桁の8bitから1bit削る必要があるのでビットシフトします。

reg = 0x20 + dno * 2;

//通信開始
Wire.beginTransmission(adrs);
//register
Wire.send(reg);
//通信終了
Wire.endTransmission();

Wire.requestFrom(adrs, 2);
if(Wire.available()>1){
//1バイト分のデータの読み込み
data.H = Wire.receive();
//次の1バイト分のデータを読み込み
data.L = Wire.receive();
}
return (data.W);
}

実際に通信を行う部分です。
まず、レジスターアドレス、つまりこの番号のデータを送ってくれ。という指令を送ります。
この指令が回転の場合は0x20 前後回転の場合は0x22 左右傾の場合は0x24となっています。

//通信開始
Wire.beginTransmission(adrs);
//register
Wire.send(reg);
//通信終了
Wire.endTransmission();

コンパスに向かって転送を始めて、レジスターアドレスを送り、通信を終了します。
Wire.requestFrom(adrs, 2);
コンパスにデータを返してくれという要求と、帰ってくるデータのバイト数を指定します。
Wire.available()>1
これはあんまり必要無いですが、一応データが帰ってきてることの確認です。
data.H = Wire.receive();
data.L = Wire.receive();

一回の通信で受信できるのは1バイトなので、2回に分けてデータを受け取ります。
return (data.W);
で、最後に戻り値として2バイトのデータを返します。


ね、簡単でしょ?


最近座ってることが多くて腰が痛い…
モーラステープにお世話になりっぱなしです。
もうちょっと運動しないと

後はモータードライバと超音波センサーです
それが終われば後はいつも通りの作業。

コメントの投稿

非公開コメント

プロフィール

立命館守山高校 Sci-tech部

Author:立命館守山高校 Sci-tech部
立命館守山高校、Sci-tech(サイテック)部のブログです。
研究の途中結果や、日記、連絡事項などを載せていきます。

主な成績
ロボカップジュニアレスキューセカンダリ2010
世界大会5位

やってること
バイオディーゼル燃料を使ったバイオカートの制作
AR(拡張現実)の研究
クルーレスソーラーボート大会への出場
ロボカップジュニアへの出場
レールガン制作
など

リンク
過去ログ
最新記事
最新コメント
アクセスカウンタ
合計閲覧者数

現在の閲覧者数
カテゴリ
検索フォーム
アクセス解析
    ブロとも申請フォーム

    この人とブロともになる

    QRコード
    QR
    上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。