Arduinoのライブラリの依存性処理 [ATmarquino Arduino]
ATmarquinoで2つのシリアルインタフェースが欲しくなったのでソフトウエアシリアルを使ってみました。
ですが何故かこのソフトウエアシリアルの出力は文字化けしてしまって上手く受信できません。
そこでソフトウエアシリアルのソースコードを調べてみました。
判った事は、例えば受信の時のビットのサンプリング周期の設定には、時間関連のライブラリのdelayMicrosecondsが呼ばれていると云う事でした。
ライブラリdelayMicrosecondsのソースの一部を掲載します。長いのでコメントは省いています。
ATmarquinoは20MHzで動かしているので
#if F_CPU >= 16000000L
のみ着目してみます。
ここでは引数を4倍して、さらにインラインアセンブラのループで4サイクル消費する事となっていますので、元々の引数を16倍する事となります。16サイクル消費すると1μs掛かっている事になるからです。
ただしF_CPUが16MHz以上のボードは一律この16倍が適用されてしまうので、ATmarquinoで搭載した20MHzのセラロックの場合問題が生じます。
※ハードウエア的に作るタイマーの場合はF_CPUに応じて設定値が計算されるので正しく周期が得られる。
つまりArduino環境でCPUクロックの周波数を16MHzまたは8MHz以外の周波数を利用し、さらに何処かでdelayMicrosecondsを使う場合、その依存性を自分で解決する必要があると云う事です。
今回はボーレートがソフトウエアシリアルの想定より高いことから、初期化時に以下の様にすればよいと云う事になります。
SoftwareSerial uart2(RXD2, TXD2);
uart2.begin( (9600UL * 4) / 5 ); // スピードを設定
上記の様に速度を調整してソフトウエアシリアルの実力を確認する為に実験してみました。
ハードウエアシリアル(通常のTXD、RXD)のRXDと、ソフトウエアシリアルで設定したRXDを接続し、パソコンから送られたデータがUSB経由で受信したデータをソフトウエアシリアル側でも受けるようにします。
ソフトウエアシリアル側で受信したデータは内部でハードウエアシリアルのTXDに送出し、USBを経由してパソコンに戻します。つまりループバックプログラムです。
この時ボーレートは9600bpsとしました。
最初は、1byte受信したら1byte返すようにしましたが、ファイル転送の様に連続でデータが送られると全く上手く行きません。文字化けし放題です。
テキストファイルを転送する事とし、一行単位で返信するようにしても、やはり芳しくないです。
全体のスケッチを掲載します。
結局のところ他の処理が重なってくると、取りこぼしを頻発したり、文字化けを起こしてしまうようです。
このソフトウエアシリアルを実用的に使用するとすれば、少量のデータの転送程度にして、更に再送処理などを入れる必要があるでしょう。
ですが何故かこのソフトウエアシリアルの出力は文字化けしてしまって上手く受信できません。
そこでソフトウエアシリアルのソースコードを調べてみました。
判った事は、例えば受信の時のビットのサンプリング周期の設定には、時間関連のライブラリのdelayMicrosecondsが呼ばれていると云う事でした。
ライブラリdelayMicrosecondsのソースの一部を掲載します。長いのでコメントは省いています。
void delayMicroseconds(unsigned int us) { uint8_t oldSREG; #if F_CPU >= 16000000L if (--us == 0) return; us <<= 2; us -= 2; #else if (--us == 0) return; if (--us == 0) return; us <<= 1; us--; #endif oldSREG = SREG; cli(); __asm__ __volatile__ ( "1: sbiw %0,1" "\n\t" // 2 cycles "brne 1b" : "=w" (us) : "0" (us) // 2 cycles ); SREG = oldSREG; }
ATmarquinoは20MHzで動かしているので
#if F_CPU >= 16000000L
のみ着目してみます。
ここでは引数を4倍して、さらにインラインアセンブラのループで4サイクル消費する事となっていますので、元々の引数を16倍する事となります。16サイクル消費すると1μs掛かっている事になるからです。
ただしF_CPUが16MHz以上のボードは一律この16倍が適用されてしまうので、ATmarquinoで搭載した20MHzのセラロックの場合問題が生じます。
※ハードウエア的に作るタイマーの場合はF_CPUに応じて設定値が計算されるので正しく周期が得られる。
つまりArduino環境でCPUクロックの周波数を16MHzまたは8MHz以外の周波数を利用し、さらに何処かでdelayMicrosecondsを使う場合、その依存性を自分で解決する必要があると云う事です。
今回はボーレートがソフトウエアシリアルの想定より高いことから、初期化時に以下の様にすればよいと云う事になります。
SoftwareSerial uart2(RXD2, TXD2);
uart2.begin( (9600UL * 4) / 5 ); // スピードを設定
上記の様に速度を調整してソフトウエアシリアルの実力を確認する為に実験してみました。
ハードウエアシリアル(通常のTXD、RXD)のRXDと、ソフトウエアシリアルで設定したRXDを接続し、パソコンから送られたデータがUSB経由で受信したデータをソフトウエアシリアル側でも受けるようにします。
ソフトウエアシリアル側で受信したデータは内部でハードウエアシリアルのTXDに送出し、USBを経由してパソコンに戻します。つまりループバックプログラムです。
この時ボーレートは9600bpsとしました。
最初は、1byte受信したら1byte返すようにしましたが、ファイル転送の様に連続でデータが送られると全く上手く行きません。文字化けし放題です。
テキストファイルを転送する事とし、一行単位で返信するようにしても、やはり芳しくないです。
全体のスケッチを掲載します。
#include <SoftwareSerial.h> #define TXD2 18 #define RXD2 19 /****************************************************************************/ /* 変数定義 */ /****************************************************************************/ SoftwareSerial uart2(RXD2, TXD2); /****************************************************************************/ /* プロトタイプ宣言 */ /****************************************************************************/ /****************************************************************************/ /* 初期化処理 */ /****************************************************************************/ void setup() // run once, when the sketch starts { pinMode(RXD2, INPUT); pinMode(TXD2, OUTPUT); uart2.begin( (9600UL * 4) / 5 ); // スピードを設定 Serial.begin( 9600 ); //ボーレートは38400bpsとする } /****************************************************************************/ /* main?処理 */ /****************************************************************************/ void loop() { int w,r,n; char c,buf[ 128 ]; for( w = r = 0;; ) { c = uart2.read(); //uart2から1文字取り込み n = w; if( ++n >= sizeof(buf) ) n = 0; /*リングバッファの終端を越える場合は、ポインタを先頭に戻す*/ if( n != r ) /*上書きは行わない*/ { buf[ w ] = c; /*バッファに保存*/ w = n; /*書き込みポインタの更新*/ } if( n == r || c == 0x0a ) /*改行コードを探す*/ { for( ;w != r; ) /*バッファに溜まったすべてのデータを送信する*/ { Serial.print( buf[ r ], BYTE ); /*パソコンがわに送信*/ if( ++r >= sizeof(buf) ) r = 0; /*リングバッファの終端を越える場合は、ポインタを先頭に戻す*/ } } } }
結局のところ他の処理が重なってくると、取りこぼしを頻発したり、文字化けを起こしてしまうようです。
このソフトウエアシリアルを実用的に使用するとすれば、少量のデータの転送程度にして、更に再送処理などを入れる必要があるでしょう。
Making Things Talk -Arduinoで作る「会話」するモノたち
- 作者: Tom Igoe
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/11/17
- メディア: 大型本
2009-04-08 21:43
nice!(0)
コメント(0)
トラックバック(0)
コメント 0