ページへ戻る

− Links

 印刷 

inc​/mbed​/20140629 のソース :: なーおんWEB

xpwiki:inc/mbed/20140629のソース

« Prev[3]  
** mbed ことはじめ [#h40f2aa8]
*** まず頭に入れてくべきこと [#z5dd6b11]
-- [[mbedオフィシャルサイト:https://mbed.org/]] 全てはここから始まる。
-- [[mbedとは:Wikiedia:http://ja.wikipedia.org/wiki/Mbed]]
-- [[mbed と Arduino の違い:https://mbed.org/users/okini3939/notebook/mbed_vs_arduino/]]

*** 準備したもの [#i22ec0be]
-- mbed対応のマイコン。今回は、[[LPC1114FN28 を、秋月電子:http://akizukidenshi.com/catalog/g/gI-06071/]]で購入。 1個たったの120円!(税込)
-- USB-シリアル変換モジュール [[FT232RL 秋月で購入:http://akizukidenshi.com/catalog/g/gK-01977/]]。
-- Arduinoスターターキット [[SGK-ARD-KIT 千石電商で購入:http://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-0BPT]] arduino uno 付きで4,940円。 arduino unoの他に付属のセット品が色々入っていて、初めてには良いですね。 arduinoからいじり始めてみたものの、mbedを教えていただいたら断然そちらが面白くなってます。

*** 配線 [#z6974bcd]
- 参考
-- [[mbed LPC1114でLチカしてみた(1):http://www3.big.or.jp/~schaft/hardware/tips/LPC1114/page001.html]]:しなぷすのハード製作記
 マイコンとFT232RLの接続が参考になります。 プログラムを書き込んだあとリセットしなくても済みます。 なお、書き込みソフトはこのページの要領ではなく、LPC1114限定で下記ページのものが使いやすいです。
-- [[mbed LPC1114でLチカしてみた(2):http://www3.big.or.jp/~schaft/hardware/tips/LPC1114/page002.html]]:しなぷすのハード製作記
 LPC1114限定で「LPCISP」というソフトを公開しておられます。USB/serialコンバーター経由で一発書き込み、即座にリセットが働くので、楽ちんです。
|&ref(LPCISP_0.jpg,mw:360,mh:360);|

- ハード図
 ブレッドボードを使うとテストは楽にできるけど、一度バラしたら再現するのが面倒になっちゃいますんで、ちゃんと図面を書くクセをつけたいですね。今回は資料への使いまわしがしやすいようにEXCELでこんな感じで書いてみました。
-- LPC1114のLED回路はソース出力(PNP)でプラスコモン、FT232RLのLEDモニタ回路は、シンク出力(NPN)でマイナスコモンになっているみたいで、ちょっと混乱します。
 工業用制御部品に関していえば、日本国内やアジア圏ではシンク(NPN)でマイナスコモン、欧州ではソース出力(PNP)でプラスコモン が多いですが、欧州への輸出時にはCEマーク表示の関係で本質安全の考え方から必ずPNPにしないといけなくなるため、国内でもPNPへの変更が徐々に進んでいる・・ のかなあ?
 組み込み部品での状況は全くわからずです。

|&ref(mbed_UART_SERVO.jpg,mw:480,mh:360);|

|&ref(site://modules/dblog1/upimg/00215f18aa1dcaf25bbcdb400acb72dfcb.jpg,mw:360,mh:360);|

*** プログラム [#n356f22a]
 mbedはarduinoと違い、ほぼ素のC/C++で書けます。 オンラインコンパイラでビルドが通ったプロジェクトをエクスポートして、外部のIDEで編集・コンパイルできることからもそれを実感できます。

 とはいえまずはオンラインコンパイラで。

|&ref(mbed_WorkSpace_0.jpg,mw:480,mh:360);|

**** 使用ライブラリ [#tb797654]
- Servo
 mbedのオンラインコンパイラ上の「Import」でキーワード「Servo」で検索し、sford cstyles さんの [[mbed R/C Servo Library:http://mbed.org/users/simon/code/Servo/]]を試しに使ってみました。
- MySerial
 [[自作ライブラリ MySerial:http://mbed.org/users/naao/code/MySerial/]] です。mbed標準のRawSerialクラスを継承し、受信文字列のchar配列格納を簡単にできるようにしてみました。 現時点でのソースを貼っておきます。
-- GetString メソッドは、テンプレート化でオーバーロードしてあり、引数にポインタ変数指定でも char配列指定の参照でも使えるようにしました。
-- Wait時間の設定を追加してあります。
 その他APIは、[[こちらを参照:http://mbed.org/users/naao/code/MySerial/docs/930d325f3d31/classMySerial.html]]。

-- MySerial.h
#code(c,0-){{
/** mbed Serial Library extend RawSerial
 * Copyright (c) 2014 Naoki Okino
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#ifndef MBED_MYSERIAL_H
#define MBED_MYSERIAL_H

#include "mbed.h"
    
/** MySerial control class, based on a RawSerial
 *
 * Example:
 * @code
 * #include "mbed.h"
 * #include "MySerial.h"
 * 
 * MySerial pc(USBTX,USBRX);   //instance of MySerial Class
 * char cWord[16]; //receive chars  or cWord[256], cWord[1024] etc..
 * 
 * void readbuf()
 * {
 *   // int iRtn =  pc.GetString(6,&cWord);    //Serial received chars by pointer cWord
 *    int iRtn =  pc.GetString(6,cWord); //Serial received chars byref of cWord
 * }
 * int main() {
 *    pc.baud(9600);                  //set baud rate
 *    pc.format(8, MySerial::None, 1);//set bits for a byte, parity bit, stop bit
 *    pc.SetRxWait(0.01, 0.001);       //set wait getting chars after interrupted, each char
 *    pc.attach( readbuf, MySerial::RxIrq );    //Set Interrupt by Serial receive
 * }
 * @endcode
 */
class MySerial : public RawSerial{
    
public:
    /** constructor to get chars received by serial
     * 
     * @param PinName tx
     * @param PinName rx
     */
    MySerial(PinName tx, PinName rx);
   
    /** set wait getting chars after interrupted
     * 
     * @param float _fRxStartWait wait getting a 1st char after interrupted
     * @param float _fRxEachWait wait getting each char
    */
    void SetRxWait(float _fRxStartWait, float _fRxEachWait);

    /** function to get chars after received chars by serial
     * 
     * @param int size for get chars
     * @param *cWord returns got chars by pointer
     * @param returns success by 0
     */
    virtual int GetString(int size, char *cWord);
    
    /** overload function to get chars after received chars by serial
     * 
     * @param int size for get chars
     * @param cWord returns got chars by ref
     * @param returns success by 0
     */
    template <class X> int GetString(int size, X cWord)
    {
        return GetString(size, &cWord);
    }

protected:
    float fRxStartWait;
    float fRxEachWait;
    
};  /*  class MySerial  */

#endif
}}

-- MySerial.cpp
#code(c,0-){{
#include "MySerial.h"

MySerial::MySerial(PinName tx,PinName rx):RawSerial(tx,rx)          //constructor
{
    fRxStartWait = 0.01;    //wait getting a 1st char after interrupted
    fRxEachWait = 0.001;    //wait getting each char
}

void MySerial::SetRxWait(float _fRxStartWait, float _fRxEachWait)
{
    fRxStartWait = _fRxStartWait;   //wait getting a 1st char after interrupted
    fRxEachWait = _fRxEachWait;     //wait getting each char
}

int MySerial::GetString(int size, char *cWord)            //by pointer
{
    int i=0;
    int ichar;
    memset(cWord, '\0', strlen(cWord));  //initialise chars

    wait(fRxStartWait);

    while(1) {
        if(!readable())    {
            break;
        }
        ichar = getc();
        if(i<size) {
            cWord[i] =ichar;
            //putc(ichar);
        }
        i++;
        wait(fRxEachWait);
    }
    return 0;
}
}}

**** メイン [#w251f1f2]
- シリアルコマンド
ただの実験なので、<STX><ETX>などの制御コマンドは一切無しです。(汗)
-- 「start」で開始
-- 「pxxx」(xxxは角度)で位置決め
-- 「stop」で停止
です。
- 受信の割り込みと、50ms定時タイマ割り込みを受けてメインで動作及びLチカさせてみました。
-- 割り込みのIRQ変数名は、シリアルが「UART_IRQn」、定時タイマが「TIMER_16_0_IRQn」でしたので、割り込み優先度や割り込み禁止を個別に管理できます。 この辺の定義は、[[こちらに全部書いてあります:http://mbed.org/users/mbed_official/code/mbed-src/file/1b2bee05fe98/targets/cmsis/TARGET_NXP/TARGET_LPC11XX_11CXX/LPC11xx.h]]ね。

- まだ試していませんが、フロー制御を入れないと9600bps以外では取りこぼしが発生します。
- ソース
volatile のつけ方などわかっていないので、まだ適当です。
-- main.cpp
#code(c,0-){{
#include "mbed.h"
#include "Servo.h"
#include "MySerial.h"

Servo myservo(dp18);
MySerial pc(USBTX,USBRX);         //instance of MySerial Class
Ticker timer;
DigitalOut led2(LED2);            //alive check LED

volatile int cntRx=0;
volatile int cntRx_old=0;
volatile int timeUp=0;
volatile int timeUp_old=0;

char cWord[6]; //receive chars  or cWord[256], cWord[1024] etc..
char *pCword = cWord;    //pointer for cword
const char ccStart[6] = "start";
const char ccStop[5] = "stop";
const char ccMove_[2] = "p";

int readSize = 5;
int doStatus;
int iDeg;

void atRx()
{
    NVIC_DisableIRQ(UART_IRQn);
    cntRx++;
}

void atTimer()
{
    //NVIC_DisableIRQ(TIMER_16_0_IRQn);
    timeUp++;
}

void readbuf()
{
    pCword = cWord;    //pointer for cword

    //int iRtn =  pc.GetString( readSize, &cWord[0] ); //Serial received chars by pointer of cWord
    int iRtn =  pc.GetString( readSize, cWord ); //Serial received chars byref of cWord

    if(strcmp(cWord, ccStart)==0) {     // start
        doStatus=1;
        printf("started\n");
    } else if(strcmp(cWord, ccStop)==0) { // stop
        doStatus=0;
        printf("stopped\n");
    } else if(cWord[0]==ccMove_[0]) { // 1st char matches
        pCword++;                    // increment pointer to get after 2nd chars
        iDeg = atoi( pCword );
        printf("%d\n",iDeg);
    } else {                        //no action except for start/stop
        printf(" no match %s\n" , cWord);
    }
    if ((doStatus == 1) && (0 <= iDeg) && (iDeg <= 180)) {
        wait(0.01);                           // waits for the servo to get there
        myservo.position(iDeg - 83.0);
    }
}

int main()
{
    pc.baud(9600);                  //set baud rate
    pc.format(8, MySerial::Odd, 1);//set bits for a byte, parity bit, stop bit
    //pc.format(8, MySerial::None, 1);//set bits for a byte, parity bit, stop bit
    //pc.set_flow_control(MySerial::RTSCTS,dp26,dp25);
    pc.SetRxWait(0.01, 0.001);       //set wait getting chars after interrupted, each char

    wait(0.25);     //startup wait

    pc.attach( &atRx, MySerial::RxIrq );    //Set Interrupt by Serial receive
    NVIC_SetPriority(UART_IRQn, 120);
    timer.attach( &atTimer, 0.05 );
    NVIC_SetPriority(TIMER_16_0_IRQn, 10);

    myservo.calibrate(/* range */ 0.00099, /* angle +/- */ 90.0);

    while(1) {
        wait(0.01);

        if(cntRx != cntRx_old)
        {
            readbuf();
            cntRx_old = cntRx;
            NVIC_EnableIRQ(UART_IRQn);
        }

        if(timeUp != timeUp_old)
        {
            if( 10 <= timeUp )
            {
                led2 = !led2;
                timeUp=0;
            }
             timeUp_old = timeUp;
            //NVIC_EnableIRQ(TIMER_16_0_IRQn);
        }
    }
}
}}

** 実行結果 [#r5494d56]

シリアルコンソールには、定番のTeraTermではなく、「[[RS232cテストツール:http://homepage2.nifty.com/nonnon/Download/Rs232cTool/]]」というフリーソフトを使ってみました。

下図のように、コマンドを送ると帰ってきたアンサーが表示されます。
|&ref(Comm_0.jpg,mw:480,mh:360);|

** 総括 [#uadc2152]

 mbed、おもしろいです。 C/C++の入門にもなるし、ハード回路の勉強にもなります。

 次回は、オフラインでのコンパイルとデバグ環境にチャレンジしたいと思います。

[[inc/mbed]]

« Prev[3]