2017年1月28日土曜日

RX621で遊ぶ モータ制御してみる

RX621でMTU2を持ちいてモータ制御してみたメモ.
MTU2を用いてPWM出力と位相係数モードを使うことは難しいことではありません.
今回確認したかったのは,4モータを制御することです.

ちなみにピン選定はPDG(Peripheral Driver Generator)を使うと楽です.
コード生成機能はあまり使用しませんが,モジュールで使用するピンが簡単に
わかりやすく出力されるので,一目でピンを確認できます.

PDGを使用した結果4モータを制御するためには
MTU1,2,7,8を位相係数モード.(7,8はポートB)
MTU6,9をPWMモード2.
その他適当なピンをモータドライバにつなぐのが良いとわかりました.

以下MTU6のPWMモード2とMTU1,2の位相係数モードのイニシャライズメモ
その他もほとんど同じです.

//MTU6
SYSTEM.MSTPCRA.BIT.MSTPA8 = 0; //モジュールストップ状態の解除 MTU6
MTU6.TCR.BIT.TPSC =2; //PCLK/16
MTU6.TCR.BIT.CCLR = 1; //TGRAでカウントクリア
MTU6.TMDR.BIT.MD = 2; //PWMモード1
MTU6.TIORH.BIT.IOA = 1; //出力禁止
MTU6.TIORH.BIT.IOB = 2; //LOW->HIGH出力
MTU6.TIORL.BIT.IOC = 1; //出力禁止
MTU6.TIORL.BIT.IOD = 2; //LOW->HIGH出力
MTU6.TGRA = 3000-1;     //1kHz
MTU6.TGRB = 0;
MTU6.TGRC = 3000-1;     //1kHz
MTU6.TGRD = 0;
MTUB.TSTR.BIT.CST0 = 1; //カウント動作開始

//MTU1,MTU2
SYSTEM.MSTPCRA.BIT.MSTPA9= 0; //MTUストップ解除
MTUA.TSTR.BIT.CST1 = 0; //MTU1カウント停止
MTUA.TSTR.BIT.CST2 = 0; //MTU2カウント停止
PORT2.ICR.BYTE=0xff;   //ポート機能解除
IOPORT.PFCMTU.BIT.TCLKS = 0; //ポート設定

MTU1.TMDR.BIT.MD = 4; //位相係数モード
MTU1.TSR.BIT.TCFD = 1; //TCNTはアップカウント,フラグクリア
MTU1.TCNT = 0; //カウントストップ

MTU2.TMDR.BIT.MD = 4; //位相係数モード
MTU2.TSR.BYTE = 0xC0; //TCNTはアップカウント,フラグクリア
MTU2.TCNT = 0; //カウントクリア

MTUA.TSTR.BIT.CST1 = 1; //76543210
MTUA.TSTR.BIT.CST2 = 1; //MTU2カウント開始


モータドライバはこれ,モータはこれのエンコーダ付き
現在いじっている基盤にそのままモータドライバは乗らなかったので
別に基盤を作りました.





結構ゴチャゴチャしてきました.
とりあえずこれで4モータ動かし,回転数を取得できることは確認しました.
今回で回路の確認は終了したので
前にも書いたとおりマイクロマウスの製作に入りたいと思います.
とりあえずモータ買わないと.

RX621で遊ぶ SPI通信でジャイロセンサを使う

RX621でSPIで使用するメモ

使用したジャイロセンサはこれ

L3G4200D



Amazonで購入しました.秋月にデータシートと詳しい説明書がありました.
http://akizukidenshi.com/catalog/g/gM-06433/

今回はピンの関係からRSPI1のポートBを使用.
配線は以下のとおり

PE5(RSPCKB) -> SCL
PE6(MOSIB)    -> SDA
PE7(MISOB)    -> SDO
PE4(SSL0B)    -> CS

説明書によると,クロックはデフォルトでHIGH奇数エッジでデータ変化
偶数エッジでデータサンプルです.(データシート24ページ目)
16ビットで通信し,上位8ビットでデータレジスタ送信,下位8ビットでデータ受信します.

以下イニシャライズと16ビット送受信のサンプル


//SPI設定
SYSTEM.MSTPCRB.BIT.MSTPB16 = 0; //SPIストップ解除

RSPI1.SPCR.BIT.SPE = 0; //SPI機能停止

RSPI1.SPBR = 23; //100kHz

RSPI1.SPDCR.BIT.SLSEL = 0x01b; //SSL0,SSL1許可
RSPI1.SPDCR.BIT.SPLW = 0; //ワードアクセス

RSPI1.SPCMD0.BIT.CPHA = 1; //奇数エッジでデータ変化偶数でサンプル
RSPI1.SPCMD0.BIT.CPOL = 1; //アイドル時RSPCK=1
RSPI1.SPCMD0.BIT.SSLA = 0; //SSL0でアサート
RSPI1.SPCMD0.BIT.SSLKP = 1; //SSL信号を保持
RSPI1.SPCMD0.BIT.SPB = 15; //データ長16bit

PORTE.ICR.BIT.B7=1; //入力バッファ有効
IOPORT.PFHSPI.BIT.RSPIS = 1; //SPI端子portEに変更
IOPORT.PFHSPI.BIT.RSPCKE = 1; //RSPCKB有効
IOPORT.PFHSPI.BIT.MOSIE = 1; //MOSIB有効
IOPORT.PFHSPI.BIT.MISOE = 1; //MISOB有効
IOPORT.PFHSPI.BIT.SSL0E = 1; //SSL0B有効

RSPI1.SPCR.BIT.MSTR = 1;     //マスタモード

RSPI1.SPSR.BYTE = 0xA0; //ステータスクリア
RSPI1.SPCR.BYTE;     // SPCR空読み


//センサレジスタから1バイト読み出し
unsigned char rspi_read( unsigned char reg,unsigned char x ){
unsigned short  recv;
RSPI1.SPCR.BIT.SPE = 1; // enable
RSPI1.SPDR.WORD.H = reg<<8+x; // 送信
while( 0 == RSPI1.SPSR.BIT.SPRF ); // 受信完了待ち
recv = RSPI1.SPDR.WORD.H; // 受信バッファ読出し
RSPI1.SPCR.BIT.SPE = 0; // disable
recv = recv&0x00ff; //マスク
return(recv);
}


とりあえずWho_am_iレジスタから読み取る.
具体的には0x8fを送り,0xd3(211)が帰ってくればOK.






2017年1月24日火曜日

RX621で遊ぶ CMT割り込み,ブザー,シリアル(送信のみ)

RX621関連のその他のメモ

・CMT0割り込み

RXで割り込みを発生させるには,さまざまな方法がありますが,
最もシンプルな方法はCMT(コンペアマッチタイマ)であると思います.

以下はCMT0で1msで割り込みをかけるサンプル

//CMT0初期設定
void CMT0_init( void ){
  SYSTEM.MSTPCRA.BIT.MSTPA15 = 0; //モジュールストップ状態の解除 CMTユニット0
  CMT.CMSTR0.BIT.STR0 = 0; //カウント動作停止
  CMT0.CMCR.BIT.CKS = 1;   // PCLK/32 
  CMT0.CMCOR = 1499;     // 1ms/(32/48MHz)-1
  CMT0.CMCNT = 0; // カウントクリア
  ICU.IER[0x03].BIT.IEN4 = 1; // 割り込み要求許可
  ICU.IPR[0x04].BIT.IPR = 0x05; // 割り込み優先レベル 
  CMT0.CMCR.BIT.CMIE = 1; //割り込み許可
  CMT.CMSTR0.BIT.STR0 = 1; //割り込み開始
}

CS+では割り込み先関数がintprg.cに作成されます.
私はその中に実行する関数を書いています.

//intprg内  CMT0_Tick:実行したい関数
void Excep_CMT0_CMI0(void){
  CMT0_Tick();
}



・ブザーを鳴らす

ブザーは個人的にロボットのデバックには必須だと思っています.
動いている状態を目で追いつつ音で内部処理がわかるからです.
周波数が低いのでソフトウェアでもいけると思いますが,今回はMTU2を使用しました.

それだけでは面白くないので,トリガで割り込みをかけることでバックグラウンドで
再生できるようにしました.これは地味に便利です.
使ったのは一般的な圧電ブザーのこれ

#include"iodefine.h"
#include "vect.h"

static long buz_timer;

//MTU0初期設定
void buz_init( void ){
SYSTEM.MSTPCRA.BIT.MSTPA9 = 0; //モジュールストップ状態の解除 MTU2
MTU0.TCR.BIT.TPSC =2;       //PCLK/16
MTU0.TCR.BIT.CCLR = 1; //TGRAでカウントクリア
MTU0.TMDR.BIT.MD = 2; //PWMモード1
MTU0.TIORH.BIT.IOA = 2; //初期値LOWコンペマッチでHIGH出力
MTU0.TIORH.BIT.IOB = 1; //コンペアマッチでLOW出力
MTU0.TGRA = 2999; //1kHz
MTU0.TGRB = 1500;
IR(MTU0,TGIA0) = 0; //MTU0フラグクリア
IEN(MTU0,TGIA0) = 1; //MTU0割り込み許可
IPR(MTU0,TGIA0) = 0x01; //割り込み優先度設定
MTU0.TIER.BIT.TGIEA = 1; //割り込み許可
}

//ブザーセット
void buz_set( int hz , int t){
if( hz <= 0 ) MTUA.TSTR.BIT.CST0 = 0; //カウント動作停止
else{
MTU0.TGRA = 1500000/hz; //カウンタ設定
MTU0.TGRB = MTU0.TGRA/2; //TGRBはTGRAの半分
MTUA.TSTR.BIT.CST0 = 1; //カウント動作開始
buz_timer = hz*t/1000;
}
}

//TRGA割り込み
void Excep_MTU0_TGIA0(void){ 
buz_timer--;
if(buz_timer < 0){
buz_timer=0;
MTUA.TSTR.BIT.CST0 = 0;
}
}



P34から出力されます.
あとで気づきましたが,TMR(8ビットタイマ)でも波形を出せるみたい.
ブザーのような単純なモジュールは,こっちのほうが最適かもしれません.
しかし,私の配線ではピンがすべてかぶってしまっていました.


・シリアル通信

割り込みを使わない送信のみなら以下のプログラムで可能です.
PC等と相互に通信させたいなら,受信割り込みなどを使用する必要が
あります.ここはいずれキチンとしたヘッダとしてまとめたい所です.

//シリアル初期化(PCLKを別定義)
void sci1_init( unsigned short bps)
{
SYSTEM.MSTPCRB.BIT.MSTPB30 = 0; //SCI1ストップ解除
SCI1.SCR.BYTE = 0x00u; //SCI1停止
SCI1.SMR.BYTE = 0x00u; //PCLK分周無し、ストップビット1、パリティ無し、データ8bit、調歩同期式
SCI1.BRR = (PCLOCK / (16 * bps) + 1) / 2 - 1;
SCI1.SEMR.BYTE = 0x20u; //1bit=16ClockCycle、ノイズ除去機能有効、スタートビットはLOWレベルで検出
for(Cnt=0;Cnt<10000;Cnt++); //Wait

SCI1.SSR.BYTE &= ~0x78u;     //エラーフラグクリア
SCI1.SCR.BIT.TE = 1;         //送信許可
SCI1.SCR.BIT.RE = 1;         //受信許可

}

//1byte送信
short sci1_putc(char data)
{
while(SCI1.SSR.BIT.TDRE == 0);     //未送信データが送られるまで待つ
      SCI1.TDR = data;                    //送信データのセット 
      return(0);
}


RX621で遊ぶ I2CLCDを接続

前回製作したお遊びボードにI2CLCDを接続したメモ

LCDは以前使用したものを使用しました.
621のI2Cは1ユニットしかなく,P13,12がSDA,SCLにあたります.


適当にカウントさせるデモ



参考にさせていただいたサイト
http://blog.goo.ne.jp/lm324/c/9d7010ad7b7c5b2fe20a7ec9a9446dd1

LCDのイニシャライズ等はSwitchScienceのArduinoのサンプル
をRX向けにちょっと弄るだけで動作しました.
なのでここで書くことは特にないです.

このLCDはサッと気軽に使える上,小型なのでデバックにピッタリです.
気が向いたら,CGRAM等を弄っていきたいと思います.



2017年1月22日日曜日

RX621で遊ぶ

今回は買ってからずっと放置していたRX621ボードで遊んでみるメモです.

RX600系はRX62Tを触っていたので導入はそれほど難しくありませんでした.
レジスタの名前が少し違う程度です.ちなみに開発環境はCS+,FDTで書き込みます.



RX621マイコンボード  お値段 \2700

62T,62Gはモータ制御向け,62N,621は通信向けのマイコンとなっています.
62Nの621の違いはイーサネットがあるかどうかだけ.通信向けといっても
超高機能であるため,モータのひとつやふたつは簡単に制御できます.



ユニバーサル基盤一枚でお遊び基盤を作りました.
USB経由でも通信可能ですが,諸事情によりUART経由に変更しました.



とりあえずLEDチカチカまで確認しました.



なぜいきなりRXなんか触り始めたのかというと実はマイクロマウス
製作してみたいから.マシン自体は大学で製作したことがありますが,
自宅では初めてです.具体的な設計はこれからですが,ちょっと
変わったマシンにする予定であります.

とりあえず当分はお遊びボードで回路の確認です.



2017年1月15日日曜日

LPC1114FN28 I2Cキャラクタ液晶

先日SwitchScienceでいろいろ購入しました.



デュアルモータードライバTB6612FNG
I2C接続の小型LCD搭載ボード と5V版
レベルシフト回路搭載 microSDブレークアウト

無理やり3000円にするため,いろいろ買ってしまった.後悔はしていない.
とりあえず今回はLCDのテストをしてみたいと思います.



とっても小さくて良いです.サイトにあったArduinoのサンプルでテスト
させてみます.



動いた!以上!
しかし,使いたいのはLPC1114FN28なのでmbedでプログラムしなければならない.
一から作るのは非常に面倒だったので,サンプルの通信部分を書き直します.
以下コード

#include "mbed.h"
#define  byte unsigned char

I2C i2c(dp5, dp27);  //SDA,SCL
DigitalOut myled1(dp14); //dp13を出力に設定
const int addr = (0x3e<<1); //スレーブアドレス
byte contrast = 35;  // コントラスト(0~63)

void lcd_init( void );
void lcd_cmd(byte x) ;
void lcd_contdata(byte x);
void lcd_lastdata(byte x);
void lcd_printStr(const char *s);
void lcd_setCursor(byte x, byte y);

int main() {
    lcd_init();
    while(1) {
        lcd_setCursor(0, 0);
        lcd_printStr(" AQM0802A");
        lcd_setCursor(1, 1);
        lcd_printStr("  TEST  ");
        myled1 =  !myled1;
        wait(0.5);      //0.5秒待つ
    }
}

void lcd_init( void ){
  wait(0.5);
  //Wire.begin();
  lcd_cmd(0b00111000); // function set
  lcd_cmd(0b00111001); // function set
  lcd_cmd(0b00000100); // EntryModeSet
  lcd_cmd(0b00010100); // interval osc
  lcd_cmd(0b01110000 | (contrast & 0xF)); // contrast Low
  lcd_cmd(0b01011100 | ((contrast >> 4) & 0x3)); // contast High/icon/power
  lcd_cmd(0b01101100); // follower control
  wait(0.2);
  lcd_cmd(0b00111000); // function set
  lcd_cmd(0b00001100); // Display On
  lcd_cmd(0b00000001); // Clear Display
  wait(0.2);
}

void lcd_cmd(byte x) {
  //Wire.beginTransmission(I2Cadr);
  //Wire.write(0b00000000); // CO = 0,RS = 0
  //Wire.write(x);
  //Wire.endTransmission();
  char cmd[2];
  cmd[0] = 0x00;
  cmd[1] = x;
  i2c.write(addr, cmd, 2);
}

void lcd_contdata(byte x) {
  //Wire.write(0b11000000); // CO = 1, RS = 1
  //Wire.write(x);
  char cmd[2];
  cmd[0] = 0xc0;
  cmd[1] = x;
  i2c.write(addr, cmd, 2);
}

void lcd_lastdata(byte x) {
  //Wire.write(0b01000000); // CO = 0, RS = 1
  //Wire.write(x);
  char cmd[2];
  cmd[0] = 0x40;
  cmd[1] = x;
  i2c.write(addr, cmd, 2);
}

// 文字の表示
void lcd_printStr(const char *s) {
  //Wire.beginTransmission(I2Cadr);
  i2c.start();
  while (*s) {
    if (*(s + 1)) {
      lcd_contdata(*s);
    } else {
      lcd_lastdata(*s);
    }
    s++;
  }
  i2c.stop();
  //Wire.endTransmission();
}

// 表示位置の指定
void lcd_setCursor(byte x, byte y) {
  lcd_cmd(0x80 | (y * 0x40 + x));
}



動いた!と思いきや最初の一文字がずれるバグに遭遇.
スペース挿入で回避しています.まあヘッダを作るときにでも直すことにしましょう.


SPIでグラフィック液晶も動作させましたが,フォントを入れればならずプログラムも複雑です.
一方こちらはピンも少なく,プログラムも非常に単純になりました.
ロボットのデバック等,英数字しか扱わない環境ならこちらを用いたほうが良いでしょう.

2017年 明けましておめでとうございます

明けましておめでとうございます.
年が明けてからもう15日も過ぎました,早いですね.

さて、今年は大学以外でもいろいろ作る年にしたいです.
具体的にはRaspberry Piを使ったロボットなんかも面白そうだと思いました.
その過程で気になったことをメモに残しつつ,少しでも誰かの役にたてれば幸いです.
今年もどうぞよろしくお願いいたします.