L3g4200(GY50)について

お久しぶりです。大学が春休みになったので、作業を開始しました。
結構前に購入し放置していたL3g4200(GY50)はどんな感じなのかを調べてみたのでここにメモしておきます。
https://www.amazon.co.jp/HiLetgo-L3G4200D-3%E8%BB%B8%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB-%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB-%E8%A7%92%E9%80%9F%E5%BA%A6%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB/dp/B00M4986FG
ここで買いました。昔買ったんで、今は在庫がないみたいですね。

その前に、双方向レベル変換ICについて
https://www.amazon.co.jp/gp/product/B014F8ZEVM/ref=oh_aui_search_detailpage?ie=UTF8&psc=1
で購入した物で、今は在庫がないそうですね。
このICはオープン状態ではHI,GNDでLOW、5Vor3VでHI,になります。
では、双方向なので、両方を出力として、片方をHi(5V)、もう一方をLOW(0V)にするとどうなるでしょうか?
答えとしては電流が大量に流れ、ものすごい発熱します。
つまり、双方向レベル変換ICは両方を出力にする場合、Hiを5Vではなくオープンドレイン出力にする、または片方は入力固定にする必要があるという事です。

  1. オープンドレインにした場合
 片方がHi(オープン)、もう一方がLOW(GND)とすると、確実にGNDになります。Hiはただオープンになっているだけなので当然ですが。
 I2C通信では自動でこの設定(オープンドレイン出力)なので、プルアップ抵抗を入れる必要はありません。

 2.片方を入力固定にする

 これは、SPI通信です。つまり、SPIでは悩む必要はありません。

話を戻し、L3G4200について
このdatasheet(レジスタマップに詳しい)と
http://wikitronica.labc.usb.ve/images/f/fc/L3G4200D.pdf
このdatasheet(レジスタマップがわかりやすい)と
このdatasheet(ハード的に詳しい)を参考にしました。

まず、回路的な事から
  1. 基板に付属してるkb33というチップは
http://pdf1.alldatasheet.com/datasheet-pdf/view/190542/KINGBOR/KB3301.html
にあるとうり、DC-DCコンバータ。ただし、何ボルトの出力をしているかはわからない(誰か教えて)。ただし、3.3vで動いた。

 2.I2Cの場合CSは3.3V (SDOをHIにしてしまっていて詰まった)
 3.デバイスのアドレスはSD0がHIGH->0x69,LOW->0x68になる。
 4.DRはチップ的にはINT2である。DRはdataReadyの略でデータが準備できたら割り込みするよう設定することができるからだろう。
 5.SDA,SCLは電圧変換がなくてもあっても動作します。(安全は保証できない)

アドレスがわからないデバイスはI2C_SCANNERを使うことをおすすめします。
この、アドレスのスケッチを利用すれば使える。前述どうり、I2CではSDOがHI->0x69,LOW->0x68.


内部レジスタの0x0FはWHO_I_AMであり、0xd3(211<-10進数)という固定データが収まっています。このデータを読めるかで通信ができているか確認できます。
#include
int sai=0;
void setup() {
  Serial.begin(9600);
  Serial.println("Hello,we will start testing");
  Wire.begin();
}

void loop() {
  Wire.beginTransmission(0x68);
  Wire.write(0x0F);
  Wire.endTransmission();
  Wire.requestFrom(0x68,1);
  while(Wire.available()){
    sai=Wire.read();
  }
  Serial.println(sai);
  delay(10);

}

//program end
//#include と表示されてしまいますが、#includeに書き直してください

こんな感じでやると211というデータが読めるはずです。

データ読み出しをやろうと思い、データシートを読んでいると意外とわかりやすく、熟読してしまったので、まずわかったことをまとめようと思います。

STATUS_REGについて
x、y、zOR(overrun)は読み出しが遅くデータが読み出し中に書き換えられると1になります。
x、y、zDA(dataAvailable)は読み出し可能なデータが追加されると1になる。

FIFOについて
基本的なFIFO。使用するにはCTRL_REG5のFIFO_ENを1にする必要がある。x,y,zの6byteのデータを32セット保有できるようだ。5つモードがあるっぽい。 FIFO_CTRL_REGのFM[2:0]で設定するようだ

  1. BYPASS MODE(FIFOを使わない、X,Y,Z軸のデータがそれぞれ1つしか保存されていない、デフォルト)
  2. FIFO MODE
  3. Stream MODE
  4. Stream to FIFO MODE
  5. Bypass to FIFO MODE
 FIFO MODEはFIFOが埋まるとデータの上書きが行われず、記録が停止する。よってデータを読み出し、終わった後一時的にBYPASS MODEにし(FIFOをリセットするため?)、FIFO MODEに戻し記録を再開するように使うようだ。
 Stream MODEは一番古いのを捨て新しいのをFIFOに入れていく一般的なFIFO。
4,5は割り込みによってモードが変更できるようなモード

FIFO_CTRL_REGについて
WTMはwater mark(量水準)の略でFIFOがWTM[0:4]で指定した量たまるとINT2(DR)に割り込み信号を与えることができる。

FIFO_SRC_REGについて
WTMはWTMで指定した量たまっているとき1になる。EMPTY,OVRN(over run?OVER WRITTEN?)もある。

この図からわかるように、WTMは水準を超えているときはHIGH、OVRNは満タンになるとHIGHになる。EMPTYはREADでFIFOが全部読み出すとHIGHになる。全部読み出した状態でさらに読み出したデータはその前に読み出したデータと同じ値であるらしい。
FSS(太ももすりすりしたい)は現在のFIFOにたまっているデータの数を示す
個人的にWTMは便利そうだなと思いました。

CTRL_REG1について
PD(power down)は1にセットすることで、NORMAL MODEにする。Zen,Yen,XenはXenableの事で、1にすることにより軸のジャイロをつかえるようにすることができる。DR(data rate)、BWはODR(output data rate)、とローパスフィルターの設定ができる。



内部レジスタを全て読み出すと次のようになります(デフォルト)。

0F->D3 who I am
10->15    ?
11->67   ?
12->65   ?
13->0   ?
14->9   ?
15->A1   ?
16->D0   ?
17->10   ?
18->56   ?
19->CC   ?
1A->1F   ?
1B->80   ?
1C->83   ?
1D->6   ?
1E->81   ?
1F->3   ?
20->7    PD:0(起動時1に変更が必要),X,Y,Z enable:1,ODR:100Hz,
21->0
22->0 どの割り込みフラッグも立っていない
23->0 BLE(Big Little Endian  おそらくレジスタアドレス指定方法):0,250dps
24->0 FIFO_EN->0(FIFO利用不可)
25->0   Reference->0
26->0   TEMP(温度)0
27->0  X,Y,ZOR:0->読み込み中の書き込みなし、X,Y,ZAvailable:0(読み込みできるデータなし)
28->6C | X data
29->F1   |
2A->DC  | Ydata
2B->FC  |
2C->D5  | Zdata
2D->F4  |
2E->0    BypassMode ,WTM:0
2F->20   EMPTY FLAGのみ立っている
30->0
31->0
32->0
33->0
34->0
35->0
36->0
37->0
38->0

PD->1にするとデータが変動し始めます。

Z軸の角速度読み取り、H,Lのデータを合成した値を表示させてみます。

とりあえず、何らかのデータを読み取れているようです。Arduinoのプログラムは
//とりあえず動かせる程度
#include
int sai=0;
void setup() {
  delay(20);
  Serial.begin(115200);
  Serial.println("Hello,we will start testing");
  Wire.begin();
  writeReg(0x20,0x0F); //PD->HIGH
}

void loop() {
  byte ZH;
  byte ZL;
  ZH=readReg(0x2D);
  ZL=readReg(0x2C);
  /*
  if(bitRead(ZH,8)){
    //負
    ZH= ~ZH;
    ZL= ~ZL;
    Serial.write('L');
  }else{
    Serial.write('H');
  }  
  Serial.write(ZH);
  Serial.write(ZL);
  delay(10);
  

  */
  //単純に数値のみの変動を見るとき
  int ZR=ZH*16+ZL;
  Serial.println(ZR);
  
  

}

byte readReg(byte address){
  byte anser;
  Wire.beginTransmission(0x68);
  Wire.write(address);
  Wire.endTransmission();
  Wire.requestFrom(0x68,1);
  while(Wire.available()){
    anser=Wire.read();
  }
  return anser;
}

void writeReg(byte address,byte data){
  Wire.beginTransmission(0x68);
  Wire.write(address);
  Wire.write(data);
  Wire.endTransmission();
  Wire.endTransmission();
}



こんな感じです。
疑問点の一つは角速度がほぼ0の際に出る出力がどのように決定されているかです。
もう一つは、配線のせいなのかもしれませんが、勢いよく動かすと動作が停止することがあります。
The complete angular rate data for the X (Y, Z) channel is given by the concatenation
OUT_X_H & OUT_X_L (OUT_Y_H & OUT_Y_L, OUT_Z_H & OUT_Z_L) and it is
expressed as a 2’s complement number.(2の補数)

平常時はZ_H->12,11 (HEX)  、   Z_L->不定
の値を取ります。
やはり、Hが上位ビットでしょう。LSBFIRSTな気がします。
負の値はなく、真ん中あたりの値で0を示している可能性もあります。

よくわかりませんでした・・・











コメント