お久しぶりです、しゅうです。前回からひと月も経っていますね・・・笑
すっかり寒い時期になってきましたね、僕はまだまだ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 TXI1とSCI1 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だけ同時押しであとは順番に押していきます。
まとめ
以上で、UART通信経由でPi:Coのセンサ値を見ることができました。特に新しいアプリを導入しなくても見れるのは楽ですね。
あとは迷路解析やスラローム走行のプログラムを実装して、センサ値などのパラメータ調整をし終えたら16×16の迷路を走破するのみです!
