MPU-6500 6軸加速度+ジャイロセンサ



 MPU-6500は、Invensense社(現在TDKの子会社)の製品で、I2CとSPIの二つのインターフェースをもった6軸加速度・ジャイロセンサです。SPIまたはI2Cでアクセス可能です。

     T.MPU-6500のハードウエア仕様

     U.MPU-6500のSPI仕様

     V.MPU-6500のI2C仕様



T.MPU-6500のハードウエア仕様
 1)動作電圧 1.71〜3.45V

 2)加速度(Accelerometer) X、Y、Z軸。±2〜±16(g)
               16ビット出力データ・レート0.24〜40000Hz

 3)角速度(Gyroscope)  X、Y、Z軸。±250〜±2000(°/sec)
              16ビット出力データ・レート4〜8000Hz

 4)温度(Temperature) 16ビット出力データ −40℃〜85℃
              摂氏温度(℃)に変換するには以下の式で計算する。
              TEMP_degC=((TEMP_OUT-RoomTemp-Offset)/
              Temp_Sensitivity)+21degC


  U.MPU-6500のSPI仕様

   1)データの転送はMSBファーストで行われる

   2) SCLKは負極性(待機時はHigh)

   3)データはSCLKのRisingEdgeでラッチされる

   4)データはSCLKのFallingEdgeで転送される

    (以上から、SPIモードは3である)

   5)SCLKの最大周波数は1MHzである

   6)SPIデータの転送には16クロック(2Bytes)以上を要する

   7)最初のByteでSPIアドレスを送り、次に続く複数Byteでデータを送る

   8)送るアドレスByteの先頭Bitは、Read/Write bit になる
     (Readのときは1、Writeのときは0)


  ◎SPIモードで動かすための設定と、ジャイロの感度設定を以下の手順で行う

   1)PWR_MGMT_1レジスタでDEVICE_RESETする

   2)SIGNAL_PATH_RESETレジスタでGYRO、ACCEL、TEMPをリセット

   3)GYRO_CONFIGレジスタで感度を±2000dpsに設定する

 X,Y,ZそれぞれのGYRO_*OUT_HとGYRO_*OUT_Lレジスタからジャイロセンサ値を読み取る

  ◎SPIデータの読み書きのプログラムは以下のような手順で行います

  1)読み込みの手順

   NCS(チップセレクタ)をLOWにする

   アドレス8bit(アドレスの先頭ビットを1=Read,0=Write )を送る

   空データ8bit(0x00)送信と同時に受信を行う

   NCS(チップセレクタ)をHIGHにする

  2)書き込みの手順

   NCS(チップセレクタ)をLOWにする

   アドレス8bit(アドレスの先頭ビットが1=Read,0=Write )

   書き込みデータ8bit

   NCS(チップセレクタ)をHIGHにする


以上の手順はArduinoの項で述べたことと同じですが、SPIの送受信関数を自分で作成する必要があります。
                                       
MPU-6500側  
R8C/M12側
 1 VCC 今回は3.6Vを使用
 2 GND  GNDに接続
 3 SCL Serial ClockP3_4に接続
 4 SDA MISO(Master Out Slave In)P3_7に接続
 5 EDA 増設用無接続
 6 ECL 増設用無接続
 7 ADO MOSI(Master In Slave Out)P3_5に接続
 8 INT 割り込み無接続
 9 NCS Chip SelectP3_3に接続
10 FSYNC GNDに接続



結 線 図(半田面)




◎SPI 1バイト 読み書きの基本関数

 MPU-6500のプログラムを組む上で以前作成したSPI LCDで使用した送信専用の関数は使用せず、新たに以下のように送受信を同時に行うSPI制御関数を使用しています。


01:unsigned char SPI_transfer(unsigned char data)
02:{
03: unsigned char i;
04: unsigned char ipdat;// 受信入力データ
05: ipdat = 0x00;
06: ADDR = 0;     // ADOを入力ポートに設定
07://C_NCS;      // チップセレクトをLow
08: H_CLK();// Mode 3 アイドル時はHigh
09: for(i=0;i<8;i++){ // 1ビト毎にクロックと共に送受信する
10:  ipdat <<=1; // 受信データを1ビット左にシフト
11:  L_CLK();     // クロックをLにして送受信準備
12:  delay();
13:  if(ADO) ipdat |= 0x01;// ADO端子(データ入力端子)
14:  if(data & 0x80){  // MSBから送信
15:   S_SDA;
16:  }
17:  else{
18:   C_SDA;
19:  }
20:  H_CLK();  // クロックをHにして入出力処理
21:  data <<=1; // 送信データを1ビット左にシフト
22: }
23://S_NCS;// チップセレクトをHigh
24: H_CLK();// クロックを待機モード
25: return ipdat;// 受信データを戻り値として返す
26:}


 完成するまで色々トラブりました。何とか正常に動いているとは思いますが、あまりスマートなプログラムではありません。





◎プログラム構成

 プログラムは以下の3部から構成されています



1)EM_MPU6500_SPI.c ・・・メインプログラム

#include<stdio.h>
#include "sfr_r8m12a.h"
#include "ctrl.h"

01:void main(void)
02:{
03: unsigned long xd; // 受信データ格納変数
04: unsigned long dataH,dataL;// 読み込みデータ上位8ビット、下位8ビット
05: unsigned long AX,AY,AZ;
06: unsigned char addr;
07: S_NCS;
08: init();
09: set_UART0();
10://asm("FSET I");
11://u0rif = 0;// 受信割り込みフラグクリア
12: addr=0x75;
13: UART0_tx_str("MPU-6500 通信開始\n\r");
14: xd=Read(0x75); // WHO_AM_I チェック
15: UART0_tx_hex(xd,2);// 0x70 ならばOK
16: CRLF();
17: Write(0x6B,0x01);// SET PWR_MGMT_1
18: delay();
19: Write(0x1A,0x00);// SET Config
20: delay();
21: Write(0x1B,0x18);// SET GYRO_CONFIG(000 110 00):GYRO_FS_SEL=3
22: delay();
23: Write(0x68,0x07); // SIGNAL_PATH_RESET GYRO、ACCEL、TEMPをリセット
24: delay();
25: Write(0x6A,0x10); // USER_CTRL I2C_IF_DISを1にする(I2C無効)
26: delay();
27: while(1){
28:  dataH=Read(0x43);dataL=Read(0x44);// GYRO_X
29:  AX=(dataH<<8 ) | dataL;
30:  dataH=Read(0x45);dataL=Read(0x46);// GYRO_Y
31:  AY=(dataH<<8 ) | dataL;
32:  dataH=Read(0x47);dataL=Read(0x48);// GYRO_Z
33:  AZ=(dataH<<8 ) | dataL;
34:  UART0_tx_num(AX,4);UART0_tx(' ');UART0_tx_num(AY,4);UART0_tx(' ');UART0_tx_num(AZ,4);
35:  CRLF();
36:  wait_ms(1000);
37: }
38:}
39:/* I/O 初期化関数 */
40:void init(void)
41:{
42: int i;
43: prc0 = 1;// プロテクトレジスタ解除
44: hocoe = 1;// 高速オンチップオシレータ発振開始
45: for(i=0;i<50;i++);// 発振安定まで待つ
46: hscksel = 1;// 高速オンチップオシレータ選択ビットを1にする
47: scksel = 1;// システム基準クロックを高速にする
48: prc0 = 0;// プロテクトレジスタ禁止
49: pd1  = 0xdf;// ポート1データディレクションレジスタ全て出力に設定
50: p1= 0xff;
51: pd3= 0xdc;// 1101 1100 出力:P3_7,P3_6,4,3,2,1,0 入力:, P3_5
52:}



2)spi_ctrl.c ・・・SPI(Mode 3対応)、UART0の制御関数


  /* 1バイト 読み書きの基本関数 */
01:unsigned char SPI_transfer(unsigned char data)
   ・
   ・(省略)
   ・

  /* 書き込みの基本関数 MOSI(Master Out Slave In) */
01:void Write(unsigned char address,unsigned char data)
02:{
03: C_NCS; // チップセレクトをLow
04: SPI_transfer(address);
05: delay();
06: SPI_transfer(data);
07: delay();
08: S_NCS; // チップセレクトをHigh
09:}

  /* 読み込みの基本関数 MISO(Master In Slave Out */
01:unsigned char Read(unsigned char address)
02:{
03: unsigned char rdat;
04: C_NCS;// チップセレクトをLow
05: SPI_transfer(address|0x80);
06: delay();
07: rdat=SPI_transfer(0x00);
08: delay();
09: S_NCS;// チップセレクトをHigh
10: return rdat;
11:}
   ・
   ・(省略)
   ・

3)ctrl.h ・・・ヘッダーファイル

01:#define S_NCS p3_3=1 // NCS端子(チップセレクト端子) p3_3を1にする
02:#define C_NCS p3_3=0 // NCS端子(チップセレクト端子) p3_3を0にする
03:#define NCS_DDR pd3_3 // NCS端子の入出力設定レジスタ
04:
05:#define SDA p3_7
06:#define S_SDA p3_7=1 // SDA端子(データ入力端子) p3_7を1にする
07:#define C_SDA p3_7=0 // SDA端子(データ入力端子) p3_7を0にする
08:#define SDDA pd3_7 // SDA端子の入出力設定レジスタ
09:
10:#define ADO p3_5 // p3_5をADOと定義する
11:#define S_ADO p3_5=1 // ADO端子(データ出力端子) p3_5を1にする
12:#define C_ADO p3_5=0 // ADO端子(データ出力端子) p3_5を0にする
13:#define ADDR pd3_5 // ADO端子の入出力設定レジスタ
14:#define S_SCL p3_4=1 // クロック端子 p3_4を1にする
15:#define C_SCL p3_4=0 // クロック端子 p3_4を0にする
16:#define SCL_DDR pd3_4 // SCLK端子の入出力設定レジスタ
17:#define CLOCK 20000 18:void init(void);
19:void set_UART0(void);
20:int put_uart0(char r);
21:int UART0_rx(void);
22:int UART0_tx(char data); 23:void UART0_tx_str(char *str);
24:void CRLF(void);
25:int UART0_tx_hex(unsigned long value,int keta);// 16進で表示する関数
26:void UART0_tx_num(unsigned long val,int keta); // 10進数で表示する関数

27:void wait_us(unsigned long usec); // us単位のタイマ
28:void wait_ms(unsigned long msec); // ms単位のタイマ
29:void delay(void); // 6usの遅延関数
30:void H_CLK(void); // クロックをHighにする
31:void L_CLK(void); // クロックをLowにする

32:void Write(unsigned char address,unsigned char data);// 書き込みの基本関数 MOSI(Master Out Slave In)
33:unsigned char Read(unsigned char address);// 読み込みの基本関数 MISO(Master In Slave Out
34:unsigned char SPI_transfer(unsigned char data);// 読み書きの基本関数


 画面表示される加速度値が正しいのかどうかは確信がありません。プログラムがどこか間違っているのかもしれませんが、今回は、SPI制御関数を作成することが目的でしたので、詳しく検討することはしません。時間の余裕があれば、いつかは再検討してみたいと思っています。



プロジェクトファイルのダウンロード


















  V.MPU-6500のI2C仕様




メニューに戻る