PIC AVR 工作室別館 arduinoの館->TopPage->標準機能->シリアル入出力

arduinoのシリアル入出力について

arduinoのシリアル入出力は、AT-MEGA168が内蔵しているUSART機能を使って実現 されています。このシリアル入出力機能の概要と使い方をまとめていきたいと思います。

arduinoのシリアル入出力機能

arduinoのシリアル入出力について

arduino-IDEでスケッチをコンパイルした後、PC側から実行プログラムを書き込むためのケーブルとしてUSBもしくは シリアルケーブルが使われていますが、プログラムの実行時にはこのケーブルをarduinoとPC側ソフト間 (もしくはPC以外のマイコンなどとの間)のシリアル通信に利用することも出来ます。

arduinoでは一般的に、arduino-IDEの画面下部(シリアルモニター)とarduinoの間でのデータ通信用途で使われることが 多いですが、それ以外にもシリアル通信を行うウィンドウズアプリや、シリアル通信を行う各種マイコンとも通信が可能です。

arduinoの言語仕様では、この通信機能を簡単に利用する命令が用意されています。

シリアル入出力ピンについて

arduinoの入力端子のうち、デジタル0番、デジタル1番ピンの2本はシリアル入出力としても割り当てられています。 デジタル0番(RXピン)は受信用で、PCなどから送られてきた信号を受信します。デジタル1番(TXピン)は送信用で、 arduinoからPCなどに信号を送ります。これらのピンはボード上でAT-MEGA168(もしくはAT-MEGA8)の PD0(RXD)、PD1(TXD)ピンに直結されています。

これらMEGA168のRXD、TXDの各ピンは、各種マイコン(PICやAVRなど)と直接直結して 通信を行うことが可能になっています。

もしarduino-IDEからarduinoへの書き込みが出来ているのであれば、既に「PCとarduinoがシリアル通信可能な 状態になっている」ので、あまりあまり細かいことは考えなくてもarduinoボード上の実行プログラムとPCとの間で 通信することが可能です。

(実際はUSBタイプにしてもシリアル接続タイプにしてもPC側の信号規格がarduinoの入出力規格と差異があるので、 PC側の通信仕様に合うような信号変換機能が内蔵されています…後述)

シリアル入出力の命令一覧

シリアル入出力を利用するには以下の命令や関数を使用します。(arduinoの標準機能に組み込まれています)

Serial.begin(通信速度)  … 初期化と通信速度の設定
変数 = Serial.read()  … 受信済みの1バイトを読込む(int型)
Serial.print(データ)  … 文字列・数値を出力(浮動小数不可)
Serial.println(データ)  … Serial.print+改行文字を付加
変数 = Serial.available() … バッファ中のバイト数(int型)
Serial.flush()    … 読み込みバッファのフラッシュ

大抵の場合、上の5つの命令や関数を利用すれば事足りるかと思われます。次項でそれぞれの命令・関数について補足します。

シリアル入出力の各命令の補足

Serial.begin(通信速度)について

シリアル通信機能の使用を宣言する命令です。カッコ内に通信速度を指定します。単位は「ビット/秒」です。 通常は9600とか19200とかがよく用いられます。通信相手(例えばPC)と速度を合わせておく必要があります。 なお、その他の通信条件(パリティービットやストップビット数など)は指定できません(必要もないでしょうけど)。

別に9600のような「良く使われる速度」を選ぶ必要はなく、中途半端な速度でも構わないのですが、 当然通信相手も同じ速度でやり取りできるようになってなければなりません。

Serial.read()について

相手機器から送られたデータを1バイト読み出し、戻り値として返す関数です。int型です。 なお、全然データが届いていない時や、届いたデータをすべて読み尽くした後で更にSerial.read()で読み出すと、 戻り値は「-1」になります。読み出すべきデータが届いているかどうかはSerial.available()で調べられます。

Serial.print(データ)について

相手の機器にデータを送出する命令です。データには「文字列」「数値(intなど)」が指定できますが、 「浮動小数(float型など)」は使用できないので一旦別の形に変換(キャスト)してから送る必要があります。

なお、数値のデータは10進数表記のascii文字に自動的に変換されて送信されます。変換方法を明示指定 することで様々な変換方法に変更することが可能ですが、書式指定方法については事項に記載します。 arduino-IDEへ送信する用途の範囲では、書式指定はあまり必要ないと思います。

Serial.println(データ)について

基本機能は上記のSerial.print(データ) と同じです。ただ、データ送信後に改行マークが付加されます。

改行マークはwindows用の「cr/lf」だけです。linux用の「lf」や、mac用の「cr」には変更できません。

Serial.available()について

読み込みバッファにデータが届いているかを調べて、戻り値としてバイト数を返す関数です。int型です。 バッファとはナンゾヤについては後述します。戻り値が1以上なら読み込みデータが1バイト以上存在していることを さします。0の時はバッファが空っぽということです。なお、arduinoは最大で128バイトまで受信データを バッファリングしています。

Serial.flush()について

読み込みバッファに届いているデータをすべて破棄します。通常は使う必要がない ものですが、arduinoと別の機器の起動タイミング(リセット信号のタイミング)などの兼ね合いでゴミデータを拾う 恐れがあるときなど、ゴミデータを捨てるのに使います。バッファとはナンゾヤについては後述します。

送出データの書式指定方法について

Serial.print()の引数に書式キーワード(以下のDECとかHEXとか)を指定すると、その数値は指定されたフォーマットの ascii文字に変換して送出されます↓。(BYTEだけは例外でascii文字変換されません)

Serial.print(データ, DEC) …Serial.printと同じ10進表記
Serial.print(データ, HEX) …データを16進表記のascii文字で送出
Serial.print(データ, OCT) …データを8進表記のascii文字で送出
Serial.print(データ, BIN) …データを2進表記のascii文字で送出
Serial.print(データ, BYTE) …ascii文字の変換をしないで送出

使い方は、このようにHEXとかOCTなどのキーワードを、データの後ろにカンマを挟んでくっ付けるだけです。 (なお、これらのキーワードは大文字にする必要があります)

例として、Serial.print(18, HEX); を実行する場合を考えてみます。10進数で18は16進数では0x12 となりますが、この12をascii文字の”1”と”2”の2文字にして送出することになります。これは、 asciiコードで言うと「0x31」と「0x32」の2バイトです。

Serial.print(18); とだけ指定した場合は、”1”と”8”の2文字が送出されるのと比較してみてください。

なお、同じようにSerial.print(18, BIN); の場合は、10進数で18は2進表記で0b10010となるので、 ”1”、”0”、”0”、”1”、”0”の計5文字のascii文字として送出されます。

「BYTE」指定は少し例外的です。BYTEを指定するとascii文字への変換が行われず、1バイトのバイナリーデータ として送出されます。Serial.print(18, BYTE); なら、16進の「0x12」1バイトデータだけがそのまま送出されます。

BYTE以外のキーワードの場合はascii文字なので、arduino-IDEのシリアルモニターやハイパーターミナル、Tera Term等 といったascii文字ベースの通信ソフト相手でも文字化けせずに送受信できます。BYTE指定の場合はascii文字以外 の値でもそのまま送出してしまうので、注意が必要です。

通常、BYTEキーワードはバイナリデータに対応した通信ソフトとの接続や、arduino対マイコン、arduino対arduino といった接続の時に使われます。一般に、ascii文字で通信する場合と比べて少ないデータ量でやり取りすることが可能です。

arduinoの場合、通常は「指定無し」か「HEX」のどちらかを使うことが多いと思います。

ちなみに、asciiコードの一覧表は、 公式サイトのASCII chartのページにあります。

サンプルスケッチ

シリアル入出力を使ってサンプルスケッチを書いてみます。

サンプル1:各種データをPCに送信

まずはarduinoからPC宛にデータを送る処理です。(for文の不等号はhtmlタグと混同されないように 全角文字に変えてあります。適宜半角に置き換えて使ってください)

int i;

void setup() {
  Serial.begin(9600);
  Serial.println("start");
}

void loop() {
  for(i=0;i<10;i++){
    Serial.print(i);
    Serial.print(",");
  }
  Serial.println("");  //line feed
  Serial.println(123,HEX);  //0x7B
  Serial.println(0x30,BYTE);  //ascii"0"

  for(;;);  //halt
}

実行プログラムをアップロードしたら、上部メニューボタンの一番右(シリアルモニター)を押してください。 (↓この図では黄色っぽく変わっている所がそのボタン)

画面の下部の黒いところ(シリアルモニター画面上)に実行結果が表示されます。(arduinoから送られてきた データは、この黒い画面に順次表示され、スクロール表示されます)

処理内容を簡単にご説明。まずsetup関数ですが、9600bpsで通信速度を設定し、”start”の文字列を送信します。

次にloop関数について。まずfor文で0~9をカンマつきで表示し、改行します。次に、123を16進数表記(0x7B) で送信します。最後に16進数の数値0x30を「BYTE」指定によってasciiコード変換せずそのまま送信します。 なお、0x30はasciiコード表では”0”に該当します。

サンプル2:PCから送られてきたデータを加工して送信

つぎにPCから送られてきたデータを元にして、加工後のデータをPCに送り返す処理です。 (先ほど同様、不等号と”&”マークは適宜半角に戻して使ってください)

int c;

void setup() {
  Serial.begin(9600);
  Serial.println("start");
}

void loop() {
  for(;;){
    if(Serial.available()>0){
      c = Serial.read();
      if ((c>='a')&(c<='z')){
        c = c - 'a' + 'A';
        Serial.print(c,BYTE);
      }
    }
  }
}

(あまり行儀のいいスケッチではないのですが、見た目が解り易そうな形にしてみました)

arduinoにアップロードしたらシリアルモニターをオンにしてください。arduino-IDEのシリアルモニタには テキスト入力のボックスがあるので、そこに文字や数字を適当に入力し、「SEND」ボタンを押すとarduinoに送信されます。 ↓この例では、「a0b1c4」の6文字を入力してみました。

「SEND」を押すと、arduinoは送られたデータを頭から1文字ずつ読み出します。読み出したデータがアルファベットの小文字の時だけ 大文字に変換し、それをPC側に送り返します。↓先ほどの文字列なら数字は無視されてabcの3文字が「ABC」と 大文字に変換されてPC側に返信されます。↓こんな風になります。

色々な文字列を入力してみてください。

このスケッチのポイントは2つです。一点目は、Serial.available()関数を使ってPCから何らかのデータが送られて 来ているかをチェックしていること。データが送られてくるまではグルグルと待ちつづけ、送られてきていれば Serial.available()関数はそのバイト数を返すので、if文内の処理を実行します。

もう一点はasciiコードとの比較の仕方。スケッチ中に出てくる’a’や’z’というようなアポストロフィーで 括った文字は、それぞれ小文字aのasciiコード、小文字zのasciiコードを指します(arduinoやC言語の言語仕様です)。 つまり、入力されたデータがasciiコードのa~zの中に入っているかを判別し、入っていれば小文字と見做して 大文字に変換しています。

シリアル通信の経路について整理

arduino上の実行プログラムとarduino-IDEの間では、どんな経路で通信内容が届いているのかを 簡単にまとめてみました。

また、arduinoやマイコンなどで使われるシリアル通信の信号とRS-232C信号の比較、そしてarduinoの内部バッファ などについても簡単な図に纏めてみました。

この項は比較的些細な内容なので、時間があるときにでも読んでください。

シリアル版arduinoの接続について

まずはシリアル版arduinoとarduino-IDEを接続した時の関連図を画にしてみます。(その方がUSB版を理解しやすいので)

上記のサンプルスケッチでは、arduinoボード上で動く実行プログラムとarduino-IDE上のシリアルモニタを 接続して実行するものでしたが、このサンプルスケッチを念頭に置きながらご覧ください。

arduino-IDEと実行プログラムの間でデータをやりとりしているときの通信経路です。arduino本体とPCは、 9ピンのシリアルケーブルというものを使って接続して使います。

このシリアル9ピンというのは、電気的にはいわゆるRS-232Cとほぼ同じ方法で通信を行うためのケーブルです。 RS-232Cは25ピンのケーブルを使い、かなり厳格に規格化されたモノですが、世の中の小型化のおり、25ピンでは 大きすぎて邪魔だということで9ピンに圧縮されました。一般的なwindowsマシンに登載されている9ピンのコネクタは、 厳密にはRS-232Cの規格を満たしていません。ただ、変換コネクタなどで25ピンにしてしまえばRS-232Cの機器とも 普通に通信できるので、一般的には「9ピンのRS-232C」などと呼ばれることが多いです。

LANやUSBなどと比べるととても原始的な仕組みであり、それゆえ非力なワンチップマイコンでも処理が容易なため、 多くのマイコンはこのシリアルI/Fをハードウェア機能として登載しています。USARTなどと呼ばれる機能がそれです。 登載していないマイコンでも、(プログラム書くのは面倒ですが)ソフトウェアである程度実現できます。 そして簡単な仕様ゆえ、マイコン対マイコンやマイコン対PCの接続では今でも良く使われているI/F方式です。

ただ、詳しくは後述しますが、マイコンは一般に5Vや3.3Vの電圧で動いているため、USARTもこれらの電圧を前提にしている のに対し、RS-232Cは遠くまで信号を伝達(といっても15m程度)出来るように約15Vという高い電圧を使うことになっています。 (しかも正負の論理も逆転してます)

そのため、arduinoボード上ではトランジスタ2個を使って電圧変換を行っています。ただしこの電圧変換回路は簡易的で、 一応PCとの接続には問題無いレベルにはなっているようですが、RS-232Cの規格は満たしていません(電圧がかなり低い)。

ちなみにこの変換、一般的にはMAX232(及び互換品)というICを使うことが多いです。電圧変換と論理反転をいっぺんに 行ってくれます。

そういうわけで、電圧変換を行ってから9ピンシリアルケーブルでPCのシリアル端子に接続されます。(最近のノートPCなどは 既にこの9ピン端子が登載されていないものも多いのですが、マイコン野郎であれば市販のUSB-シリアル変換ケーブルの1本くらい お持ちの方が多いかと思われます…)

そしてarduino-IDEは、この図のようにwindowsのシリアルドライバ、シリアルケーブルを経由してarduino本体と接続しています。

ちなみに、スケッチをコンパイルして出来上がった実行ファイルも、この経路を通ってarduinoにアップロードされています。

なお、本来のRS-232Cの通信では、データが一度にたくさん送られてきてしまった場合通信相手に 「一旦送信を中断してくれ」とか、ある程度余裕が出来たら「また送って良いよ」と伝える信号線も存在しています (これを使ってデータ量を制御するのをフロー制御といいます)。ですが、arduinoとarduinoIDEの間では使われていません。 スケッチを作成する上では、この点について考慮が必要です。詳しくは下記のバッファ機能のところをご参照ください。USB版でも同様です。

USB版arduinoとarduino-IDEの接続について

次にUSB版arduinoとarduino-IDEを接続した時の関連を図にしてみます。

先ほどのシリアル接続の図と比較すると、違っているのはFT232RLとFT232RLドライバに囲まれた部分です。

FT232シリーズは、USBとシリアルの信号を変換する、その筋では有名なICです。このFT232RLを登載することで、 USB版のarduinoは、windowsアプリから見るとシリアル接続されているのと同様に扱われます。

arduinoと接続されたFT232RLはシリアル信号をUSBの信号に変換する働きをもっていて、 USBを伝わってPCに届いた信号は、FT232RLドライバを通してwidowsアプリからはシリアルポート として扱うことが出来るので、arduino-IDE側はシリアル接続の機能のままでarduinoと通信することが出来るわけです。

(細かいことを言うと、FT232RLを通してMEGA168にリセットをかけることが可能なので、arduino-IDEは この機能を使って実行プログラムのアップロード時に強制的にMEGA168にリセットをかけ、自動的にブートローダを起動させる ことが出来るようになっています)

arduinoのシリアル通信機能が持つバッファ機能

上述の通りarduinoはフロー制御を利用していません。なので、arduinoがPCやその他のマイコンとシリアル通信で接続する場合、 通信相手がいっぺんにたくさんのデータを送って来てしまったら、arduinoがデータを受けきれなくなって、データが捨てられて しまう恐れがあります。そうならないような仕組みとして、「バッファ機能」があります。

シリアル通信機能のバッファには入力用(受信バッファ)と出力用(送信バッファ)の2つがあります。 特に重要なのは受信用バッファの方です。

arduinoの受信バッファは、MEGA168に登載されている1024バイトのSRAMのうち128バイトが割り当てられていて、 送られてきたデータを一時的に蓄える「緩衝材」の機能を果たしています。

もう少し細かく言うと、MEGA168のUSART機能には、データを1バイト受信する毎にハードウェア割り込みが生じ、 その都度受信処理が確実に行えるような機能が登載されていて、arduinoはこれを共通ルーチン(スケッチをコンパイルすると自動的に 取り込まれる共通プログラム部分)内部で利用していて、届いた受信データを自動的にバッファへ格納する動作を行ってくれています。

実は、Serial.read()関数で1バイト読み出しを行う時にはこのバッファから1バイト読み出す動作を行っています。 また、Serial.available()関数は、このバッファに溜まっているバイト数を返す関数というわけです。

この128バイトのバッファを利用することによって、少しくらいの間であればデータの読み出しをサボっていても データがすぐに消えて無くなってしまうことはありません。さて、例として9600bpsで通信をする場合に サボっていても大丈夫な時間はどのくらいでしょうか? →9600bpsの場合、1秒間に960バイトのデータを 受けることになる(もろもろ併せて1バイトあたり10ビット分受信する必要あり…後述)ので、 答は1/960×128=約0.13秒です。

マイコンにとっては充分長い時間なのですが、人間にとってはあっという間ですね。ユーザーは、バッファが溢れることが ないように考慮してスケッチを書く必要があります。念頭においておいてください。

この辺の仕組みにご興味のある方は、arduinoをインストールしたフォルダの中にある、以下の場所のソースプログラムを 眺めてみてください。 → arduino\arduino-0011-win\arduino-0011\hardware\cores\arduino

なお、送信バッファはSRAM上には設けられていません。MEGA168が持つUSART機能(ハードウェア)が 持つ1バイト(8ビット)分のバッファ機能を利用しています。Serial.print()命令で1バイトを送信すると、この命令は 1バイトのバッファに書き込んだらすぐに後続処理の実行を始めます。もちろん、このバッファが空でないときは 空になるまで待ってから書き込むようになっていますので、連続してデータ送信をしてもバッファが上書きされてしまう ことはありません。

そして、それを受け取るPC側ではWINDOWSの仕組みとして同様なバッファを持っているので、 ひとまずデータを送りまくっても大丈夫です。相手がPCではなくマイコンの場合は、相手側の処理能力やバッファ容量などを 考慮し、それを上回らないデータ量(通信速度)に設計しないといけません。

あと一点気を付けるとしたら、1バイトの送信バッファにデータを書き込むとすぐに後続のスケッチの処理を 継続してしまうので、送ったタイミングと実際に相手がデータを受け取るタイミングにはわずかにズレが 生じます(9600bpsなら1/960秒…約0.001秒)。タイミングクリティカルな処理をしている場合は 注意が必要です。

通信経路についてのまとめ

シリアル版、USB版ともに、arduinoとarduino-IDEの間を流れる信号にはRS-232Cを元にしたシリアルi/f の方式が利用されています。そして、arduinoがデータを受け取る場合にはSRAM上に設けられたバッファ(128バイト)が使用されます。

RS-232Cとマイコンのシリアルi/fの比較

既にarduinoとPCを繋ぐi/fはRS-232Cを元にしたシリアル通信であることはご説明いたしました。

実際に何かモノを作るときには、スケッチだけでなく「回路を組む」必要があるわけですが、シリアルi/fをPCとの 接続だけに使うのであればこの節を読む必要はありません。シリアルi/fを使って別のマイコンや機器と接続する時に 必要となる情報をまとめておきたいというのがこの節のお話です。

arduinoはgainerと違ってスタンドアロンでも動かすことが出来ます(gainerは常時PC接続が必要)。 その際、arduinoのデジタル0番、1番ピンを外部機器とシリアル通信で接続することも出来るわけですが、 実際に回路を組んで接続するとなると電気特性も解ってなければ途方に暮れてしまいます。

というわけで、極々簡単なレベルに留めますが、RS-232Cとシリアルi/fの電気特性を簡単に纏めておきたいと 思います。

arduinoが入出力するシリアルi/fについて

arduinoが入出力するシリアル信号を簡単に漫画にしてみます。9600bpsで通信する際に、arduinoのデジタル0番、 1番ピンで入出力される信号のうち1バイト分を取り出した図です。

一般的なマイコンのシリアル入出力端子で入出力される電圧とそのタイミングを表した図です。arduinoであれば、 登載されているAT-MEGA168(もしくはMEGA8)の端子の電圧です。

まず図中①の濃い水色部分について。アイドリング状態、つまりデータが全く送受信されていない状態を示しています。 データを送信していない時、arduinoは常時5Vを出力しており、同様に5Vが入力されている間はアイドリング状態である と判断しています。

次に②の薄い水色部分について。この部分をスタートビットといいます。電圧を1ビット分の長さ、つまり1/9600秒の間”0V”に 落とす事が通信開始のトリガーとなります。スタートビットは1ビット分の0Vで表現されます。データを出力する時にはMEGA168内蔵の USART機能(ハードウェア)が自動的に作り出してくれます。データを入力する際もMEGA168内蔵のUSART機能が 自動的に検知してくれます。

次に③の部分です。8つの黄色が8ビットのデータをあらわしています。1/9600秒毎にHIGHとLOWを8ビット分 入出力することで表現します。HIGH=5V、LOW=0Vで表現します。この8ビットの入出力タイミングや電圧についても MEGA168内蔵のUSART機能が自動的に判断/設定して入出力してくれます。

最後に④の部分です。この部分をストップビットといいます。8ビット分データの入出力が終ったら間髪いれず1ビット分 (1/9600秒分)の5Vがくっ付きます。arduinoがデータ出力をする時にはUSART機能が自動的に付加してくれますし、 入力の時にはUSARTが自動的に認識してくれて、1バイト分のデータ受信を完了したことを検知します。

このように①~④の1バイト分(スタートビット、ストップビットを含めて計10ビット分)の授受が終るとまた①の状態に戻ります。

つまりarduinoのシリアル通信では、データは必ず1バイト毎に区切られて送受信することになります。 ”100文字の文字列”などの場合でも、必ず1バイト毎に区切って、スタートビットとストップビットに挟んで送受信されます。 もちろん、MEGA8登載マシンでも同様です。

RS-232Cの送受信について

RS-232Cも、当然ながらarduino内蔵USARTによるシリアル通信方法と基本は変わりません。特にタイミングは 全く一緒です。変わるのは「電圧」です。実際に図示して見てみたいと思います。

さっきと違うところを探してみてください。

まずは①が-15Vになっていること。②が15Vになっていること。③が-15Vと15Vで表現されていること。④が-15Vに なっていること。そして、③のHIGHとLOWが上下逆になっていることです。

これらすべてを簡単にまとめると、「論理が反転していて(負論理)、真が-15V、偽が15Vになっている」ということに なるかと思います。

「負論理」というのはデジタル信号を電圧で表現する際の表現方法の一種で、AT-MEGA168等各種マイコンの入出力のように 5V(=高い電圧)をHIGH、0V(=低い電圧)をLOWと定義する場合を「正論理」といい、その逆を「負論理」といいます。

一般的に通信時の論理はどちらを正、どちらを偽としても構わないのですが、少なくとも通信相手同士では認識が一致している 必要があります。RS-232C規格を使う場合は送受信側ともに負論理を使うことで統一されているという訳です。

このことを踏まえて実際の回路設計を行えばいいわけです。

では具体的にどの様な回路を用いれば良いのか、ということになるわけですが、実際によく使われるようなケースを例にとって お話したいと思います。

まず、arduino対arduinoの場合です。この場合は、arduinoの入出力ピン(シリアルコネクタではなくデジタル0番と1番のことです)は 「正論理」同士なので、片方のデジタル0番を相手の1番に、相手の0番を1番に繋げば通信が可能となります。 そう、つまり直結すればOKです。また同様に、arduino対各種マイコンでもおなじです。(あ、3.3Vマイコンや2.5Vマイコン みたいに電圧が異なる場合は、電圧変換が必要ですね)

次にarduino対RS-232C機器の場合です。例えば「通信モデム」などと接続する場合が該当します。

RS-232C対応機器との通信論理は「負論理」ですし、電圧も高いので、この変換をする必要があります。 電圧変換には色々な方法があります。シリアル版arduinoのボード上ではトランジスタ2個で簡易的に行っているのですが、 少々怪しい匂いがするので、そこそこきちんと行うのであれば専用の変換ICを用いるのが便利かと思います。

代表例としてはMAX232(及び互換品)が挙げられます。このICは、「論理の反転」と「電圧の変換」を同時に 行ってくれる便利なICです。データシートに色々書いてあるので仕様の詳説はしませんが、秋月などでは セラミックコンデンサー付属のものでも200円程度で手に入るはずです。作例もたくさん公開されているので、 MAX232などと検索を掛けてみてください。5V単電源や3.3v単電源から高電圧の正負両電源を作り出して くれたり、入力した高電圧を5Vや3.3Vに変換してくれます。

なお、USB版の場合はそもそも簡易的な電圧変換機能すら付いてないので、この手の変換ICを 使うのが便利ではないかとおもいます。

まとめ、及び補足

RS-232C対応機器と接続する時には論理反転と電圧の変換が必要になると書きましたが、そういう機会は殆どないだろうし、 普通はarduino同士や他のマイコンボードとの接続といった用途が多いと思います。その時はシリアル通信コネクタ同士を 直結でOKです。(それぞれの出力を相手の入力に接続)

本当は、RS-232Cで使われる通信の条件はもっと色々なバリエーションがあります。例えばストップビット。上記ではストップビットの ビット長は1ビットと言っていますが、1.5ビット、2ビットというのもあります(MEGA168では1ビットと 2ビットだけしか選択できない)。データ長も8ビットを使うようにお話しましたが、7ビット、6ビット、5ビット、9ビット というモードもあります。また、データとストップビットの間には通信エラーを検知するためのパリティービットを 設けることも可能です(検知だけで訂正は出来ない)。

ですが、通常シリアル通信では「データ長=8ビット、ストップビット1ビット、パリティー無し、として使われることが多く、 大抵のマイコンやPCでもこの条件で行われています。もちろんarduinoもこれです。

あとすでに少し触れましたが、RS-232Cの規格にはフロー制御も盛り込まれています。が、arduinoなどのような マイコン間では、使用するピンを少なくするためにフロー制御を行わないことが多いです。充分なバッファや送受信処理 のロジックなどによってデータの取りこぼしが行われないようにするのが一般的です。

それ以外にも電圧を±15Vという表現をしていますが、厳密なRS-232Cの規格に則った表現ではないと 認識しております。詳しくはRS-232Cを詳説したサイトなどをご覧ください。

ちなみに、公式サイトで「公式arduino」と謳われているarduinoボードの場合は上記の考え方でOKですが、 互換ボード、特にUSBタイプの互換ボードではボード上の回路が公式版と異なっているものもあり、それが原因で 注意を要するものもあります(下手をするとショートして壊れてしまう場合あり!)。詳しくは下記注意点をご参照ください。

シリアル入出力機能の注意点

電流保護抵抗についてについて(互換ボードの場合の注意点)

USB接続タイプのarduino互換ボードでは、デジタル0番、1番の各ピンでシリアル信号の接続をする時に注意を 要する場合があります。

例えば、私の持っているreduino-nanoです。これはもともと完全互換ボードを謳っているわけではないのですが、 購入するとデフォルトでブートローダーが書き込まれており、大抵のスケッチは修正することなく動く、arduino準互換品です。 本家のarduino-nanoに似たサイズと機能を併せ持ちつつ、しかもこの細くて小さいボード上に拡張ピンが生えているので ブレッドボードを使わずとも色々な実験が出来てしまうスグレモノです。しかも少し安い!

完全互換ではないので、拡張ピンが生えているという点以外にも多少オリジナルとは差があるのですが、 その一つはLEDの接続ピン。通常LEDはデジタル13番に繋がっていますが、reduino-nanoは3番ピンに繋がって います。まぁ、これはあまり本質的な差異ではありません。

差のもう一つはシリアル通信機能部分の回路のこと。USB接続対応タイプなので、Diecimilaと同様にFT232RL というUSB-シリアル変換ICを登載していて、arduino-IDEとはケーブル1本で簡単に接続が出来るようになっていますが、 自動リセット機能が付いていないのと、あともう1点。このICとAT-MEGA168のUSARTピン (arduinoでいうデジタル0番、1番のピン…この図ではそれぞれPD0、PD1と表記)の接続方法が少しだけ違っています。

ちなみにこの回路図はarduinoの公式サイトに載っているDiecimilaの回路の一部分を編集しなおしたものです。 オリジナルのDiecimilaの場合、この図のようにAT-MEGA168とFT232RLの間に1kΩの抵抗(R11とR12)が 挟まっているのがお判りいただけるかと思います。reduino-nanoにはこの抵抗がありません。

PC上のarduino-IDEと接続する範囲ではどちらも何の問題もありません。(あたりまえですが)

これが問題になるのは、デジタル0番・1番ピンを経由して各種マイコンとシリアル接続をしたいという場合です。 arduinoはgainerと違って、スタンドアロンでも稼動できるようになっているので、このように他のマイコンとシリアル接続 することも本来可能なのです。

FT232RLを経由してPCとシリアル接続している端子(図のPD0、PD1)は、arduinoボード上のデジタル0番、1番の各ピンに 直結されています。この0番1番を使って他のマイコンとシリアル接続をする場合に先ほどのR11、R12の抵抗が 意味を持ってきます。

これらの抵抗は一般に保護抵抗などと呼ばれています。何を保護しているかというと、このデジタル0番、1番に 信号(すなわち0Vや5Vの電圧)が加わった時に、信号同士が衝突(ショート)してしまわないという働きをしています。

どの信号とショートするというのでしょうか???

デジタル0番ピン(この図ではPD0端子)はシリアル入力端子です。PCと接続している時にはFT232RLの TXD端子を経由してPCからの信号を入力しています。言い換えると、FT232RLのTXD端子が常時0Vか5Vの 信号をデジタル0番端子に向かって出力しています。

一方、別のマイコンからシリアル通信の信号を入力しようとするとデジタル0番端子から入力することになるのですが、 このマイコンからデジタル0番を経由して入ってくる信号と、FT232RLから入ってくる信号がショートするのです。

このときにR11が挟まっていると、FT232RLの信号はR11によって限りなく0に近い状態に弱められ、 PD0にはデジタル0番から入ってきた信号だけが届けられることになります。

一方R11が挟まってないと、FT232RLが出力する信号とデジタル0番から入ってくる信号が導線で直結される ことになり、0Vと5Vがショートすることになります。下手をすれば煙や火が出ることになりかねません。

ちなみに公式にarduinoを名乗っているボードの回路図を眺めてみたところ、この保護抵抗はすべて入っているようです。

まぁ、現実にはシリアル入出力はPC上のIDEとの接続専用に、他のマイコンとはSPIやTWI(I2C)といった シリアル接続機能を使うことが多いだろうと思いますので、あまり問題になることは無いでしょう。私自身、reduino-nanoを 使っていて殆ど困ったことはありません。

なお、arduinoのデジタル1番から出力する場合については、R12が存在しなくてもショートすることはありません。 出力機能だけであれば安心して使ってください。

というわけで、公式にarduinoを名乗っていない互換ボードについては、この保護抵抗が入っているのかどうかを 回路図で一度ご確認されることをお勧めします。