しゅうのマイクロマウス研修キット製作研修

センサ値を見る – しゅうのマイクロマウス研修 – Part 11

センサ値を見る - しゅうのマイクロマウス研修 - Part 11 しゅうのマイクロマウス研修

お久しぶりです、しゅうです。前回からひと月も経っていますね・・・笑
すっかり寒い時期になってきましたね、僕はまだまだMac上でPi:Coの開発を進めています。
ブザーを鳴らしたりモータやスイッチ(モード変更とか)の部分は無事できています。これらは、CS+の時のものをそのまま持ってくれば使えます。
センサ値を見る、すなわちUSB通信を行うところ、で躓きました。今回は短めですが、Mac上でセンサ値を見る手順を解説していきます。

必要なもの

最初はCS+の時に使っていたusb.cあたりが必要かなと思っていましたが、よくよく考えるとMacで開発するにあたりUSB通信をやめてUART通信に移行していました。なので今まで使っていたUSB用のプログラムは持ってこなくても大丈夫です。
代わりにsci.cを使います。もちろんsci.hも書きます。今回は、CS+の時とは別に1からファイルを作ります。必要なファイルや変更箇所をいったんまとめると次の表のようになります。

プログラム (修正)内容
sci.c UART通信で文字を画面上に出力する関数が用意されている
sci.h 外部のプログラムが関数を読み込めるようにする
intprg.c sci.cで定義した2つの割り込み関数を追加
init.c SCIを使うための初期化
init.h init.cに追加した関数を追加
adjust.c PC上にセンサ値を表示する関数を追加

以上のプログラムをビルドしたら、最後にターミナルに表示させる方法をご紹介します。

sci

以下がsci.cの中身です。

#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include "iodefine.h"
#include "sci.h"

#define BUFF_SIZE 100

static char sci1_buff[BUFF_SIZE];
static int sci1_length;
static int sci1_point;


int SCI1_PRINTF(const char *format, ...){
	va_list arg;
	
	while(SCI1.SSR.BIT.TEND == 0);			//前回の送信がおわるまで待つ

	va_start(arg, format);
	sci1_length = vsprintf(sci1_buff, format, arg);
	va_end(arg);

	if(sci1_length < 1) return -1;			//送信する文字が0または、変化ができなかった場合
	sci1_point=0;
	
	SCI1.SCR.BIT.TE		= 1;				//シリアル送信動作許可
	SCI1.SCR.BIT.TIE	= 1;				//TXI割り込み要求を許可
	SCI1.TDR = sci1_buff[sci1_point++];

	return 0;
}

/*---- Interrupting procedures ----*/
void int_sci1_txi(void){
	if(sci1_point == sci1_length){
		SCI1.SCR.BIT.TIE = 0;
		SCI1.SCR.BIT.TEIE = 1;
	}else{
		SCI1.TDR = sci1_buff[sci1_point++];
	}
}

void int_sci1_tei(void){
	SCI1.SCR.BIT.TE = 0;
	SCI1.SCR.BIT.TIE = 0;
	SCI1.SCR.BIT.TEIE = 0;
}

sci.hには、sci.cで定義した3つの関数を書いておけば問題ないです。また、最後の2つの関数はintprg.cに書き足しておきます。SCI1 TXI1SCI1 TEI1に該当する関数があるのでそこにint_sci1_txi();int_sci1_tei();をそれぞれ書き込みます。
ここで、ポイントとして、今回はマイコンから値を送ってもらうだけでPCからは特に情報を送る必要がありません。したがって、RXに関する諸設定はしていません。もしPCから命令を送る(例えば、実行して欲しいモード番号など)際はRXに関する諸設定も書いておく必要があります。それについてはまたの機会でお話しします!

init.c

sci.cを書いた時に、SCI1あたりのレジスタを設定しているのがわかるかと思います。なので必然的に初期化の処理でSCI周りも設定する必要があります。以下が、init.cに追加したコードです。init_all関数とinit.hに追加するのも忘れずに!

void init_sci1(void){
	SYSTEM.PRCR.WORD = 0xA502;
    MSTP(SCI1) = 0;
	SYSTEM.PRCR.WORD = 0xA500;

	SCI1.SCR.BYTE = 0x00;
	while (0x00 != (SCI1.SCR.BYTE & 0xF0));	// Wait until the interruption request is banned
	PORT2.PODR.BIT.B6 = 1;			// Switching the value to high for the direction of TXD
	PORT2.PDR.BIT.B6 = 1;			// Configure to output
	PORT3.PDR.BIT.B0 = 0;			// Configure to input
	PORT2.PMR.BIT.B6 = 0;			// Set as a general port
   	PORT3.PMR.BIT.B0 = 0;			// Set as a general port

   	MPC.PWPR.BIT.B0WI  = 0;
   	MPC.PWPR.BIT.PFSWE = 1;
   	MPC.P26PFS.BIT.PSEL = 0x0A;		//TXD1
   	MPC.P30PFS.BIT.PSEL = 0x0A;		//RXD1
   	MPC.PWPR.BIT.PFSWE = 0;
   	MPC.PWPR.BIT.B0WI  = 1;

        SCI1.SCR.BIT.CKE = 0;
	SCI1.SMR.BYTE = 0x00;			// 1 stopbit parity - None, StartStop synchronization - 8 bit
	SCI1.SCMR.BYTE = 0xF2;			// 32clock
  	SCI1.SEMR.BYTE = 0x10;			// For 115200
	SCI1.BRR=25;				// 115200

	PORT2.PMR.BIT.B6 = 1;			// Use as TXD1
	PORT3.PMR.BIT.B0 = 1;			// Use as RXD1
	IPR(SCI1, TXI1) 	= 1;		// Setting the interruption level 
	IPR(SCI1, TEI1) 	= 1;		// Setting the interruption level
	IR(SCI1, TEI1) 		= 0;
	IR(SCI1, TXI1) 		= 0;
	IEN(SCI1, TXI1) 	= 1;
	IEN(SCI1, TEI1) 	= 1;	
}

これでMTUやCMTと同様に、SCIを割り込ませて使うことができます。ここでは将来的に別の用途でSCIを使うかもしれないのでinit_sci1という名前にしてあります。

adjust.c

最後に実際にSCI関数を使用していきます。

// Check thhe sensor values
void view_adc(void){
    unsigned int i;
    MOT_POWER_OFF;

    while(1){
        SCI1_PRINTF("r_sen  is\t%d\r\n",(sen_r.value));
        SCI1_PRINTF("fr_sen is\t%d\r\n",(sen_fr.value));
        SCI1_PRINTF("fl_sen is\t%d\r\n",(sen_fl.value));
        SCI1_PRINTF("l_sen  is\t%d\r\n",(sen_l.value));
        SCI1_PRINTF("VDD    is\t%d mV\r\n",((10+51)/10*3300*S12AD.ADDR8/4095));

        for(i=0; i<0x3fffff; i++);
        
        // Screen clear sequence
        SCI1_PRINTF("\x1b[2J");      //Clears the screen
        SCI1_PRINTF("\x1b[0;0H");    //Moves the cursor to 0,0
    }
}

これであとは、調整モードのどれかでview_adc();のように呼び出すと値が見れるようになります。見るためには物理的にモードを実行するのと、もう1つ手順が必要になります。

MacのTerminalで値を見る

1行で見れます。注意点として1点だけ、init.cでSCIを初期化した時、SCI.BRRでボーレート*1を決めました。今回は115200で、次に紹介するscreenコマンドを実行する時に転送/受信速度として指定します。screenコマンドが見つからない!という場合は先に紹介するコマンドを実行してインストールしましょう。

$ brew install screen 

そして表示させるコマンドはこちら。

$ screen /dev/tty.usb0 115200

ここでは接続先のデバイスIDが/dev/tty.usb0である場合を示しています。わからない場合は、デバイスを接続した状態で

ls /dev/tty.*

or

ls /dev/

を実行して調べてください。

Pi:Coのview_adc関数と先のコマンドを実行すると次のように光センサの値とバッテリーの残量が表示されます。
光センサの値とバッテリーの残量
こちらのscreenコマンドを終了するためには、Ctrl+Aを押してからKを押し、Yを押します。最初のCtrl+Aだけ同時押しであとは順番に押していきます。

*1 ボーレート(baud rate)はデータを1秒間にデータを何回変調させるかを示します。ただし、1回の変調で1 bitのデータとは限りません。例として、100 baud rateの時、変調するのが2 bitずつの場合は転送速度が200 bpsということになります。すなわち、baud rate≠bits per secondに注意してください。

まとめ

以上で、UART通信経由でPi:Coのセンサ値を見ることができました。特に新しいアプリを導入しなくても見れるのは楽ですね。

あとは迷路解析やスラローム走行のプログラムを実装して、センサ値などのパラメータ調整をし終えたら16×16の迷路を走破するのみです!

タイトルとURLをコピーしました