こんにちは。koraです。
HM-StarterKitには、タイヤの回転を測定するエンコーダと、車体の回転を測定するジャイロセンサが組み込まれています。今回は、これらを使えるようにします。
SPIの準備
エンコーダとジャイロセンサはSPI通信を使用して値を取得します。SPI(シリアル・ペリフェラル・インターフェース)は、マイコンと外部のデバイスの通信によく使われるインターフェースです。HM-StarterKit用のSPI通信用のライブラリがサンプルプログラム内にあるので、今回もそれをコピーして使います。
サンプルプログラムのStep7から、spi.hとspi.cをコピーしてmy_hm_starterkitフォルダ内に貼り付けます。そして、ファイル -> 追加 -> 既存のファイルを追加 を選んで、 先ほどコピーしたファイルをプロジェクトに取り込みます。
また、既存のファイルにいくつか変更点を加えます。
intprg.c
まず、プロトタイプ宣言を追加します。
extern void write_spdr_gyro(void); extern void spii_int_gyro(void); extern void read_spdr_gyro(void); extern void write_spdr_enc(void); extern void spii_int_enc(void); extern void read_spdr_enc(void);
次に、以下の行を、
// RSPI0 SPRI0 void Excep_RSPI0_SPRI0(void){ } // RSPI0 SPTI0 void Excep_RSPI0_SPTI0(void){ } // RSPI0 SPII0 void Excep_RSPI0_SPII0(void){ } // RSPI1 SPRI1 void Excep_RSPI1_SPRI1(void){ } // RSPI1 SPTI1 void Excep_RSPI1_SPTI1(void){ } // RSPI1 SPII1 void Excep_RSPI1_SPII1(void){ }
下のように書き換えます。
// RSPI0 SPRI0 void Excep_RSPI0_SPRI0(void){ read_spdr_enc(); } // RSPI0 SPTI0 void Excep_RSPI0_SPTI0(void){ write_spdr_enc(); } // RSPI0 SPII0 void Excep_RSPI0_SPII0(void){ spii_int_enc(); } // RSPI1 SPRI1 void Excep_RSPI1_SPRI1(void){ read_spdr_gyro(); } // RSPI1 SPTI1 void Excep_RSPI1_SPTI1(void){ write_spdr_gyro(); } // RSPI1 SPII1 void Excep_RSPI1_SPII1(void){ spii_int_gyro(); }
init.c
init.cでは、SPIの初期設定をするためspi.hをインクルードします。
#include "spi.h"
そして、init_all()関数内に、次の行を追加します。この関数は、spi.hとspi.cにすでにあるので、新しく中身を書く必要はありません。
init_spi_gyro(); init_spi_enc();
テスト
それでは、追加した機能をテストします。シリアル通信を使いますので、前回と同様にPCとTeraTermを準備しておきます。
my_hm_starterkit.c
まずは、main関数からSPI関連の関数を呼べるように、インクルードします。
#include "spi.h"
エンコーダをテストするときは、サンプルプログラムStep5のmain関数を参考に、自作プロジェクトのmain関数に反映します。
void main(void) { init_all(); unsigned long i = 0; int data = 0; for(i = 0; i < 100*1000*10; i++); while(1){ RSPI0.SPCMD0.BIT.SSLA = 0x00; preprocess_spi_enc(0x1400); data = Get_enc_data(); SCI_printf("R_Encdata_10bit,%d\n\r", ((int)(data & 0xFFFF)) & 0x2FFF ); RSPI0.SPCMD0.BIT.SSLA = 0x02; preprocess_spi_enc(0x1300); data = Get_enc_data(); SCI_printf("L_Encdata_10bit,%d\n\r", ((int)(data & 0xFFFF)) & 0x2FFF ); for(i = 0; i < 100*1000*10; i++); //画面クリアシーケンス SCI_printf("\x1b[2J"); SCI_printf("\x1b[0;0H"); } }
実行してTeraTermに表示した結果は、このようになります。
ジャイロをテストするときは、サンプルプログラムStep6のmain関数を参考にします。
void main(void) { init_all(); unsigned long i = 0; long data = 0; for(i = 0; i < 100*1000*10; i++); preprocess_spi_gyro(0x062100); data = read_gyro_data(); for(i = 0; i < 100*1000*10; i++); while(1){ SCI_printf("data_H,%d\n\r",(data & 0x00FF00) >> 8); SCI_printf("data_L,%d\n\r\n\r",(data & 0x0000FF)); SCI_printf("Ang_Velocity[deg/s],%d\n\r",((int)((2000.0*((float)data))/32767.0))); for(i = 0; i < 100*1000*10; i++); for(i = 0; i < 100*1000*100; i++); //画面クリアシーケンス SCI_printf("\x1b[2J"); SCI_printf("\x1b[0;0H"); preprocess_spi_gyro(0xB70000); data = (short)(read_gyro_data()&0x0000FFFF); } }
TeraTermに表示すると、このようになります。
ちなみに、init_spi_gyro(); はジャイロセンサ関連のマイコン側の初期設定を行っており、ジャイロセンサ本体の初期設定は、preprocess_spi_gyro(0x062100); で行っています。06がPWR_MGMT_1(パワーマネジメント)のアドレスで、21がsleep mode解除やクロック自動指定の設定です。詳しい情報はジャイロセンサICM-20648のデータシートに記載されています。
次回
エンコーダとジャイロセンサの値を読むことができるようになりました。次は、割り込みでこれらの値を読み込んで、リアルタイム制御に反映できるよう準備したいと思います。