TOP  >  なーお'nぶろぐ  >  なーお  >  マイコン  >  mbed ことはじめ

なーお さんの日記

 
2014
6月 30
(月)
09:00
本文

まずは現物から

  • LPC1114FN28とFT232RL USB/serialコンバーターで、シリアル通信+サーボモーターを回してみる。
    t_00215f18aa1dcaf25bbcdb400acb72dfcb.jpg
    以下、準備から実際のプログラムソースまでメモっておきます。

まず頭に入れてくべきこと anchor.png

準備したもの anchor.png

    • Arduinoスターターキット SGK-ARD-KIT 千石電商で購入 arduino uno 付きで4,940円。 arduino unoの他に付属のセット品が色々入っていて、初めてには良いですね。 arduinoからいじり始めてみたものの、mbedを教えていただいたら断然そちらが面白くなってます。

配線 anchor.png

  • 参考

 マイコンとFT232RLの接続が参考になります。 プログラムを書き込んだあとリセットしなくても済みます。 なお、書き込みソフトはこのページの要領ではなく、LPC1114限定で下記ページのものが使いやすいです。

 LPC1114限定で「LPCISP」というソフトを公開しておられます。USB/serialコンバーター経由で一発書き込み、即座にリセットが働くので、楽ちんです。

LPCISP.jpg
  • ハード図

 ブレッドボードを使うとテストは楽にできるけど、一度バラしたら再現するのが面倒になっちゃいますんで、ちゃんと図面を書くクセをつけたいですね。今回は資料への使いまわしがしやすいようにEXCELでこんな感じで書いてみました。

    • LPC1114のLED回路はソース出力(PNP)でプラスコモン、FT232RLのLEDモニタ回路は、シンク出力(NPN)でマイナスコモンになっているみたいで、ちょっと混乱します。

 工業用制御部品に関していえば、日本国内やアジア圏ではシンク(NPN)でマイナスコモン、欧州ではソース出力(PNP)でプラスコモン が多いですが、欧州への輸出時にはCEマーク表示の関係で本質安全の考え方から必ずPNPにしないといけなくなるため、国内でもPNPへの変更が徐々に進んでいる・・ のかなあ?

 組み込み部品での状況は全くわからずです。

mbed_UART_SERVO.jpg
00215f18aa1dcaf25bbcdb400acb72dfcb.jpg

プログラム anchor.png

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

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

mbed_WorkSpace.jpg
使用ライブラリ anchor.png
  • Servo

 mbedのオンラインコンパイラ上の「Import」でキーワード「Servo」で検索し、sford cstyles さんの mbed R/C Servo Libraryを試しに使ってみました。

  • MySerial

 自作ライブラリ MySerial です。mbed標準のRawSerialクラスを継承し、受信文字列のchar配列格納を簡単にできるようにしてみました。 現時点でのソースを貼っておきます。

    • GetString メソッドは、テンプレート化でオーバーロードしてあり、引数にポインタ変数指定でも char配列指定の参照でも使えるようにしました。
    • Wait時間の設定を追加してあります。

 その他APIは、こちらを参照

    • MySerial.h
Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
 
 
 
 
 
 
 
 
 
 
 
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
 
-
|
|
|
|
|
-
|
|
|
|
|
|
|
!
|
|
|
|
|
-
|
|
|
|
|
|
|
!
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
!
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
!
|
|
|
-
|
|
|
!
|
|
|
|
|
|
|
|
|
|
|
!
 
 
 
 
/** 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
Everything is expanded.Everything is shortened.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
 
 
 
 
 
 
-
|
|
|
|
|
!
 
 
 
 
 
-
|
|
|
|
|
!
 
 
 
 
 
-
|
|
|
|
|
|
|
|
|
|
|
|
|
-
|
-
|
|
|
!
|
|
|
-
|
|
|
-
!
!
|
|
|
|
|
!
|
|
|
!
#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;
 
}
メイン anchor.png
  • シリアルコマンド

ただの実験なので、<STX><ETX>などの制御コマンドは一切無しです。(汗)

    • 「start」で開始
    • 「pxxx」(xxxは角度)で位置決め
    • 「stop」で停止

です。

  • 受信の割り込みと、50ms定時タイマ割り込みを受けてメインで動作及びLチカさせてみました。
    • 割り込みのIRQ変数名は、シリアルが「UART_IRQn」、定時タイマが「TIMER_16_0_IRQn」でしたので、割り込み優先度や割り込み禁止を個別に管理できます。 この辺の定義は、こちらに全部書いてありますね。
  • まだ試していませんが、フロー制御を入れないと9600bps以外では取りこぼしが発生します。
  • ソース

volatile のつけ方などわかっていないので、まだ適当です。

    • main.cpp
Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
|
|
|
|
!
 
 
 
 
 
-
|
-
!
|
|
!
 
 
 
 
 
-
|
|
|
|
|
-
!
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
-
|
|
|
!
|
-
|
|
|
|
|
!
|
!
 
 
 
 
 
-
|
|
|
|
|
-
!
-
!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
!
|
|
|
|
|
-
|
|
|
-
|
|
|
|
|
!
|
|
|
-
!
!
|
!
|
!
#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);
 
        }
 
    }
 
}

実行結果 anchor.png

シリアルコンソールには、定番のTeraTermではなく、「RS232cテストツール」というフリーソフトを使ってみました。

下図のように、コマンドを送ると帰ってきたアンサーが表示されます。

Comm.jpg

総括 anchor.png

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

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

inc​/mbed

閲覧(32256)

新しくコメントをつける

題名
ゲスト名
投稿本文
より詳細なコメント入力フォームへ