2017年2月13日月曜日

Raspberry pi3 i2c経由でサーボを使う

Raspberry pi3からあらゆるモジュールをギュインギュイン
動かしたいですが,正直GPIOを制御するのはめんどくさそうです.
モータなどリアルタイム性が高いものは他のマイコンに任せるのが
いいと思いました.

そこでArduinoにサーボモータを接続し,i2c経由でアクセスしてみます.

こんな感じ.テストなのでごちゃごちゃです.



サーボは一般的なSG90です.
Rpi3 -> arduino
GPIO2 -> a4(SDA)
GPIO3 -> a5(SCL)
GND -> GND

arduino->SG90
Vcc -> Vcc
GND -> GND
Sig -> D4(サーボ1)
Sig -> D5(サーボ2)

Arduinoは3.3Vで起動しACアダプタから外部電源を取ります.
そうしなければサーボを動かした瞬間落ちます.

Arduino側プログラム
#include<Servo.h>
#include <Wire.h>

Servo servo_pan;
Servo servo_tilt;
byte recv_data[256];
byte addr = 8;// Slave ID #8
byte deg_pan = 0;
byte deg_tilt = 0;

void setup() {
    servo_pan.attach(4);
    servo_tilt.attach(5);
    Wire.begin(addr);
    Wire.onReceive(receiveEvent);
    Wire.onRequest(requestEvent);
    Serial.begin(115200);
}

void loop() {
    if(deg_pan>=0 && deg_pan<=180){servo_pan.write(deg_pan);}
    if(deg_tilt>=0 && deg_tilt<=180){servo_tilt.write(deg_tilt);}
    delay(1000);
}

void receiveEvent(int a){
  int i=0;
  //delay(100);
  while (Wire.available()) {
    recv_data[i] = Wire.read();
    Serial.print(recv_data[i],DEC);
    Serial.print(" ");
    i++;
  }
  if(i>0){Serial.println(' ');}
  if(i>1){
      if(recv_data[0] == 4){ deg_pan = recv_data[1]; }
      else if(recv_data[0] == 5){ deg_tilt = recv_data[1]; }
  }
}

void requestEvent() {
  Wire.write(addr);
}

一応シリアル通信でデバックできるようにしておきました.
マスタからはレジスタ(4or5),角度(0~180)を送ります.
マスタからの読み出しはi2cdetectコマンドで使用するので
アドレスを返すようにしておきます.

とりあえず動作確認
Rpi3でi2cを使えるようにする.
こちらを参考にライブラリをインストールしました.
以下コマンドで接続デバイスを確認します.
$ sudo i2cdetect -y 1
上記のArduinoプログラムでは0x08がスレーブアドレスです.
コマンドからは
$ sudo i2cset -y 1 0x08 0x04 "角度"
で操作できます.


接続まで確認しました.Arduinoを使用したのはATmega328と
クリスタル等数セットが余っていたので何かに利用できないかと思ったからです.
とりあえずブラウザからアクセスできるカメラマウントの製作を目指します.

Raspberry Pi3 WEBカメラでストリーミングしてみる

お久しぶりです.
今更ながらRaspberry pi3とWEBカメラを購入したので
動作確認をしました.Raspberry pi3のセットアップ等は
わかりやすいサイトが多々あるので割愛します.

WEBカメラは動作実績のある
LOGICOOL ウェブカム HD画質 120万画素 C270
を使用しました.



ちょっと大きいですがマイクもついているので
音声処理ソフトウェアも使えそうです.

ソフトウェアにはmjpg-streamerを使用しました.セットアップ等は
こちらのサイトを参考にさせて頂きました.というかまんまです.

できた動画がこちら


動作確認ができました.
しばらくは画像処理,音声処理等で遊びつつ
何を作るか考える予定です.

ちなみにこのカメラには第二関節?のところにおもりがついています.
サーボモータを取り付けるときは外した方がよさそうですね.




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

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