2016年12月18日日曜日

LPC1114FN28 ロータリーエンコーダを使ってみる

先日,AliExpressで注文していたモータが届いたので,ArduinoとLPC1114FN28で
テストさせてみました.

モータはFaulhaber 1524009SRギア,エンコーダ付.ふたつで\3779でした.



コネクタは取り替えてしまいました.

初めての海外サイトでのお買い物.ちょっとだけ苦労しました.
海外だからきっと不親切だろうなーと思っていましたが,
ちゃんと追跡してくれるし,12/5発送で12/17到着も予定どうりでした.
高分解能のエンコーダ付でこのお値段はなかなかだと思います.
あとは動けば完璧.

・Arduino

Arduinoではおそらく高速回転での制御は無理と判断し,エンコーダのみのテストです.



こちらのサイトにあるプログラムを用いてテストしました.
見事,パルス数がかえってきました.
ちなみにこのArduino互換ボード,3.3V,5Vが切り替えられるのですが,
エンコーダはどちらでも動作しました.よってLPC1114FN28での検証が可能です.

・LPC1114FN28

こちらは,実際にモータを回し,テストしました.



モータ電源はエネループ直列4個,約4.8Vです.
検証に用にはQEIライブラリを使用.ソフトウェアでカウントします.
以下回転数を出力するサンプル

#include "mbed.h"
#include "QEI.h"

DigitalOut myled(LED1);

Serial pc(dp16, dp15);
QEI wheel (dp1, dp2, NC, 512,QEI::X2_ENCODING);
Ticker get_rpm;
int rpm;
int palse;

void flip(){
    palse = wheel.getPulses();
    wheel.reset();
    rpm = 60000*palse/1024;
 }

int main() {
    pc.baud(115200);
    get_rpm.attach_us(&flip,1000);
    while(1){
        wait(0.1);
        //pc.printf("Pulses is: %i\n", wheel.getPulses());
        pc.printf("rpm is: %i\n", rpm);
    }

}

エンコーダは2相1024パルスなので1ms割り込みで 6000*palse/1024
してやることで,回転数に変換できます.

回転数取得の様子



モータのスペック表から回転数定数は1140[rpm/V].よって
1140*4.8=5472[rpm]が大体の出力になるはずです.
ギアがついているとはいえかなり近い値になりました.




モータのテストが終わったので次回は速度制御に移りたいと思います.
このモータもう一組買おうかな・・・

2016年12月17日土曜日

LPC1114FN28でグラフィックLCDを使う

最近はLPC1114FN28にいろんなものをつなげて遊んでいるcake tetuです.
Arduinoゲーム機でも使ったSPIグラフィックLCDをLPCにつなげてみたメモ.

使用したのは超小型グラフィックLCD AQM1248a のピッチ変換キット.
750円でグラフィック表示できるんだからすごい.

使うといっても自分はほとんど何もしていません.
ちょうどよいライブラリがあったのでそれをほんの少し書き換えただけで使用できました.
https://developer.mbed.org/users/masato/code/Nucleo_AQM1248A/
非常に簡単かつ,使いやすいです.感謝いたします.
ページにあるとおりaqm1248a_lcd.cppの上のほうのマクロを書き換えました.

#if defined(TARGET_LPC1768)
    //: _spi(p5,NC,p7),_reset(p6),_A0(p8),_CS(p11),GraphicsDisplay(name) // for mbed LPC1768
    : _spi(dp2,NC,dp6),_reset(dp9),_A0(dp10),_CS(dp11),GraphicsDisplay(name) // for mbed LPC1114FN28
#else // defined(TARGET_NUCLEO_L152RE) || defined(TARGET_KL05Z)
    //: _spi(D11,D12,D13),_reset(D9),_A0(D8),_CS(D10),GraphicsDisplay(name) // for nucleo L152RE or other
    : _spi(dp2,NC,dp6),_reset(dp9),_A0(dp10),_CS(dp11),GraphicsDisplay(name) // for mbed LPC1114FN28
#endif

reset,A0,CSはおそらくどのピンでも可能です.今回はそれぞれdp9,dp10,dp11を割り当てました.
よって配線は以下のとおり

LCD        LPC
Vdd       ->       3.3V
CS        ->       dp11
reset     ->       dp9
RS        ->       dp10
SCLK    ->       dp6
SDI       ->       dp2
Gnd      ->       GND



文字の表示と丸が端を回るサンプル

#include "mbed.h"
#include "aqm1248a_lcd.h"
#define TARGET_LPC1768

DigitalOut myled(LED1);
aqm1248a_lcd lcd;   //LCD宣言
int px,py;          //サークル座標

int main() {
    lcd.setmode(NORMAL);
    lcd.set_contrast(25);   //コントラスト調整
    lcd.cls();              //LCDクリア
    lcd.locate(10,15);
    lcd.printf("This is AQM1248A demo");
    lcd.locate(10,25);
    lcd.printf("   for LPC1114FN28   ");
    lcd.rect(8, 13, 118, 35, 1);
    lcd.circle(3, 3, 3, 1);
    while(1) {
        px=3,py=3;
        for(px=3;px<124;px+=3){
            lcd.fillcircle(px-3, py, 3, 0);
            lcd.circle(px, py, 3, 1);
            wait(0.1);
        }
        lcd.fillcircle(px-3, py, 3, 0);
        px=124,py=0;
        for(py=3;py<44;py+=3){
            lcd.fillcircle(px, py-3, 3, 0);
            lcd.circle(px, py, 3, 1);
            wait(0.1);
        }
        lcd.fillcircle(px, py-3, 3, 0);
        px=124,py=44;
        for(px=124;px>3;px-=3){
            lcd.fillcircle(px+3, py, 3, 0);
            lcd.circle(px, py, 3, 1);
            wait(0.1);
        }
        lcd.fillcircle(px+3, py, 3, 0);
        px=3,py=44;
        for(py=44;py>3;py-=3){
            lcd.fillcircle(px, py+3, 3, 0);
            lcd.circle(px, py, 3, 1);
            wait(0.1);
        }
        lcd.fillcircle(px, py+3, 3, 0);
    }
}





さすがmbed.いとも簡単に動かすことができました.
しかし,フォントなどを入れているので Flash 20.8kbyte,RAM 1.1kbyteとります.
できることは非常に多いグラフィック液晶ですが,デバック用途で数字を表示
させるだけであれば,I2c通信のキャラクタ液晶のほうがいいのかもしれません.
そちらのほうもいずれ触れていきたいところです.


2016年12月13日火曜日

マトリックスLEDで遊ぶ その2

前回秋月のマトリックスLEDで一列ごとにスクロールさせるプログラムを作ってみました.
今回はさらに文字をスクロールさせて遊んでみることにします.

ダイナミック点灯にはタイマ割り込みを使用しました.

Ticker name; タイマ初期化
name.attach(&fptr,time);  で使用します.
簡単ですね.私はRenesasのRXマイコンを使用したことがありますが,
そこでは割り込み発生にも苦労しました.

今回は100usの割り込みを発生させ,900us点灯->100us消灯->列をずらす処理に
しました.割り込み周期等は完全に感覚です.


スクロール処理は表示部分8bit×8とバッファ8bit×8を用意し,バッファすべてを表示させたら
次の文字をバッファに読み込むという処理です.これはメインループ.
真夜中に作ったもんで頭が回らず自分で見てもあんまりいいプログラムではないです.何回 i 使うんだ(笑) 一応メモ用に公開しておきます.

#include "mbed.h"
#include "dots.h"

BusOut row(dp27,dp13,dp5,dp14,dp9,dp11,dp6,dp10);     //Row Cathode
//BusOut col(dp25,dp2,dp1,dp28,dp4,dp26,dp18,dp17);     //Col Anode
BusOut col(dp17,dp18,dp26,dp4,dp28,dp1,dp2,dp25);     //Col Anode

Ticker led_ctrl;    //LED点滅
uint16_t    out_col=0,out_row=1,st_led=0;

uint8_t pat[8];  //LED表示パターン
uint8_t pat_buf[8];  //LED表示次パターン

//LED点滅用割り込み
void led_out(){
    switch(st_led){
        case 0: row = ~out_row;
                col = pat[out_col];
                out_row*=2;
                out_col++;
                if(out_row>255){
                    out_row=1;
                    out_col=0;
                }
                break;
        case 10: col=0x00;
                break;
             
        default:break;
    }
    st_led++;
    if(st_led>10) st_led=0;
}

int main() {
    int i,j;
    int shift=0;
    row = 0x00;    //COL初期化
    col = 0x00;    //ROW初期化
    led_ctrl.attach_us(&led_out,100);
 
    //配列初期化
    for(i=0;i<8;i++){
        pat[i] = 0x00;
    }
 
    //表示配列初期化
    for(i=0;i<8;i++){
        pat_buf[i] = h[i];
    }
 
    while(1){
        for(i=0;i<8;i++){
            //配列シフト
            for(j=0;j<7;j++){
                pat[j] = pat[j+1];
            }
            pat[7]=pat_buf[0];  //末尾に代入
            //配列バッファシフト
            for(j=0;j<7;j++){
                pat_buf[j] = pat_buf[j+1];
            }
            wait(0.25);
        }
     
        //表示させたいパターンを挿入
        shift++;
        if(shift>6) shift=0;
        switch(shift){
            case 0: for(i=0;i<8;i++){ pat_buf[i] = h[i];}
                    break;
                 
            case 1: for(i=0;i<8;i++){ pat_buf[i] = e[i];}
                    break;
                 
            case 2: for(i=0;i<8;i++){ pat_buf[i] = l[i];}
                    break;
                 
            case 3: for(i=0;i<8;i++){ pat_buf[i] = l[i];}
                    break;
                 
            case 4: for(i=0;i<8;i++){ pat_buf[i] = o[i];}
                    break;
                 
            case 5: for(i=0;i<8;i++){ pat_buf[i] = ex[i];}
                    break;
                 
            case 6: for(i=0;i<8;i++){ pat_buf[i] = 0x00;}
                    break;
         
            default:break;
        }
    }
}

今回の表示パターン

uint8_t h[8]= {
    0xc6,
    0xc6,
    0xc6,
    0xfe,
    0xc6,
    0xc6,
    0xc6,
    0x00
};

uint8_t e[8]= {
    0xfe,
    0xc0,
    0xc0,
    0xfc,
    0xc0,
    0xc0,
    0xfe,
    0x00
};

uint8_t l[8]= {
    0xc0,
    0xc0,
    0xc0,
    0xc0,
    0xc0,
    0xc0,
    0xfe,
    0x00
};

uint8_t o[8]= {
    0x7c,
    0xc6,
    0xc6,
    0xc6,
    0xc6,
    0xc6,
    0x7c,
    0x00
};

uint8_t ex[8]= {
    0x66,
    0x66,
    0x66,
    0x66,
    0x00,
    0x66,
    0x66,
    0x00
};



動作の様子




とりあえず好きなパターンを表示できるようになりました.
マトリックスLEDの制御は,配列の操作などがとにかくややこしい.
しかし,その分効率の良いコードを目指そうと頭を使うので,
結構勉強になります.
気が向いたらASCIIコードを表示,シリアルで文字列送信等をやる予定です.

2016年12月3日土曜日

LPC1114FN28 I2C通信テスト

前にmbedの基本的な使い方についてメモし,次はi2c,SPI,割り込みを
書きますなんていってましたが,具体的なサンプルもあったほうがいいと思うので
一つずつ書いていこうと思います.
今回はLPC1114FN28を二つ使用し,通信させてみます.

・回路

  回路図は省略します.
  SDA(dp5),SDL(dp27)を接続.それぞれを1k抵抗でプルアップします.
  1kで問題ありませんでしたが,2.2k程度が良いようです.
  それぞれのdp14に確認用LEDを配置します.



・プログラム


Slave
#include "mbed.h"
#define SLVADRS (0x20<<1)   //Slaveアドレス

I2CSlave slave(dp5, dp27);  //SDA,SCL
DigitalOut  myled(dp14);    //受信確認LED
int main() 
{
     char num[2];  //送信配列
     num[0] = 0;   //初期化
     slave.address(SLVADRS);  //Slaveアドレス設定
     while (1) {
         int i = slave.receive();   //受信
         if(i == I2CSlave::ReadAddressed){
             slave.write(num,1); //
             num[0]++;       //加算
             myled = !myled; //dp14よりトグル出力
        }
     }
}

Slaveが送信要求を受けるとLEDが点滅し,前回の送信+1の値を送信します.
今回のプログラムを応用することで,LPC1114をセンサとして使用なんてことも可能です.

Master
#include "mbed.h"
I2C i2c(dp5, dp27);  //SDA,SCL
Serial pc(dp16, dp15); //TX,RX
DigitalOut myled(dp14); //起動確認LED
const int addr = (0x20<<1); //スレーブアドレス
int main() {
    char buf[2];//受信配列
    int err;    //エラーチェック
    while(1) {
        err = i2c.read(addr, buf, 1);   //スレーブから受信
        wait(0.5);
        pc.printf("State = %d num =  %d\n",err, buf[0]);  //シリアル出力
        myled = !myled;         //dp14よりトグル出力
    }
}

Masterは1byte受信し,PCにシリアルで送信します.一応エラーチェックもします.
動作の様子


無事動作していることを確認しました.


i2cデバイスは,パラレル通信に比べピンの量を節約できるので,
積極的に活用していきたいところです.
特に同じ3.3VのデバイスであるRaspberry PIと2ピンで接続できるのはうれしい.

次回は割り込みorSPIについてサンプル書いていきたいと思います.

マトリックスLEDで遊ぶ

どうも,cake tetuです.
今回は気まぐれで買ってみたマトリックスLEDで遊んでみたメモです.
今回購入したのはこちら













秋月電子通商で購入した青色ドットマトリクスLED 8x8ドット MOA20UB018GJ
調子に乗って青色を買ってしまいました.
順方向電圧が3.5VあるのでLPC1114では動かないのでは?と思っていましたが
テストしたところあっさり動いたのでよしとしました.

・回路等
  回路図等は今回は省略,しかし注意すべき点はピンが少ないため
  オープンドレイン端子をつなぐことになるのですが,その際にLEDの
  カソード(今回はRow)に接続すること.これでピンをほぼすべて使い,何とか
  全LEDを制御できます.
  先述のようにマイコンはLPC1114FN28を使用,mbedで開発しました.
  
・テストで使用したプログラム
  今回使用したプログラムです.縦横にスクロールするように点灯します.

   #include "mbed.h"

    BusOut row(dp27,dp13,dp5,dp14,dp9,dp11,dp6,dp10);     //Row Cathode
    BusOut col(dp25,dp2,dp1,dp28,dp4,dp26,dp18,dp17);     //Col Anode
    int main() {
      int i;
      uint16_t j;
      row = 0;    //COL初期化
      col = 0;    //ROW初期化
      while(1) {
        //COL点灯8=>1
        j=128;
        for(i=0;i<8;i++){
          col = j;
          wait(0.1);
          j = j/2;
        }
        //COL点灯1=>8
        j=1;
        for(i=0;i<8;i++){
          col = j;
          wait(0.1);
          j = j*2;
        }
        //ROW点灯8=>1
        col = 255;
        j=128;
        for(i=0;i<8;i++){
          row = ~j;
          wait(0.1);
           j = j/2;
        }
        //ROW点灯1=>8
        j=1;
        for(i=0;i<8;i++){
          row = ~j;
          wait(0.1);
          j = j*2;
        }
        row=0;
      }
  }

  BusOutが非常に便利で,これにより適当にピンをつないでしまってもまとめて定義
  しなおすことができます.col,rowに8ビットで代入するだけで点灯させることが可能です.


  動作の様子
  


  見ているだけで楽しい(笑)


たかがLEDを点灯させるだけで簡単だろと思っていましたが,ピンの接続がややこしく,
予想外に時間がかかってしまいました.意外と奥が深いマトリックスLED.
気が向いたらシリアル通信で文字を送るプログラム等を製作したいです.
12月も忙しい予感がするのであんまりいろんなことできないかな

  
  

2016年12月1日木曜日

LPC1114FN28個人的まとめ(mbed)

どうもお久しぶりです。
大学がちょっと忙しく気付いたら11月終わる・・・
その間にもちょくちょく遊んではいましたが本格的に開発には至れませんでした。
そんな中,いまさらですがmbedで遊んでみたことを個人的にメモします.
リファレンス見るほうがはるかにわかりやすいかも.

・デジタル入出力

      DigitalOut name(pin);  デジタル出力設定
  DigitalIn name(pin);  デジタル入力設定
  
   name=1;のように書くことで動作します.

・アナログ入力

   AnalogIn   name(pin);   アナログピン入力設定
    val = name.read_u16()  値の読み出し
 
    上位12ビットが有効だとか
 

・PWM出力

PwmOut name(pin);  PWM出力設定
  Duty比の入力はname=val(float 0~1.0)のようにします.

  name.period(ms);
  周期を設定します.未指定の場合は20[ms]

  name.pulsewidth(val)
  パルス幅を設定します.サーボモータ等で使用できるかも.

・シリアル通信

Serial  name(tx, rx);  シリアルポートオープン
  name.baud(baudrate); クロックレート指定

  name.format(bits, parity, stop_bits)
  通信方式指定.当分は初期設定から動かすことはなさそう.

  val = name.getc(); 受信
  val = name.readable(); 受信チェック
  文字列の受信について少しひねる必要がありそう.

  name.putc('A'); 一文字送信
  name.printf("Hello");  数値,文字列などを送信
  未確認ですがputc()のほうが早いと思われます.
  センサデータなどをだらだら出力する使い方では,がんばって8bitに収めたほうが
  よさそうです.

  ※私の環境のせいなのかシリアル変換ケーブルのDTRピンを使用すると
シリアルポートを開いた時にマイコンが停止しました.設定で回避できるのかな・・・
    いずれは割り込みを使っていきたい.
 
今回プラスI2C,SPI,タイマ割り込み等を使用できれば,当分は自宅内の電子工作で困らなさそうです.使ってみた感想はmbedはArduinoより若干難しいレベルで本内容を全部チェックしても2時間ぐらいでした.しかし,いづれはガシガシレジスタをいじっていきたいところ.
とりあえず当分はmbedを使い,LCDやモータを回して遊びたいです.
次回はI2C,SPI,タイマ割り込み等を書きたいと思います.