レベル変換 (2) UART その2 Arduino UNOから送信-1
前回、マイコン・ボードのUART端子の初期電圧を調べました。Arduino UNOは送信と受信共にHIGH(5V)でした。送信端子Tx(11番ピン)から各種マイコン・ボードへデータを送ります。
今回、「Arduino UNOとSpresense」、「Arduino UNOとラズパイ」をつないでレベル変換回路を試します。
●受信側のI/Oが5Vの場合
◆5V動作時のSpresenseが受信
Arduino UNOからの送信と受信側Spresenseの電圧はともに5Vなので、I/O同士は直接接続できます。
送信側のArduino UNOのスケッチです。11番ピンから送信します。
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup(){
mySerial.begin(9600);
}
void loop(){
mySerial.write("123");
}
(0、1番)を使った受信側のSpresenseのスケッチです。0番ピンで受信します。Spresenseの0、1番のUARTはArduino UNOがUSB-シリアルとつながっているのと異なり、独立しています。0番で受信してシリアルモニタで表示するのに信号はぶつかりません。
void setup() {
Serial.begin(9600);
Serial.println("Goodnight moon!");
Serial2.begin(9600);
}
void loop() {
if (Serial2.available() > 0) {
Serial.println(Serial2.read());
}
}
Spresenseのシリアルモニタです。受信できています。
SoftwareSerialを利用します。(10、11番)を使った受信側のSpresenseのスケッチです。10番ピンで受信します。
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup() {
Serial.begin(9600);
Serial.println("Goodnight moon!");
mySerial.begin(9600);
}
void loop() {
if (mySerial.available() > 0) {
Serial.println(mySerial.read());
}
}
Analog Discovery2を使って、これらの実験中の波形を示します。画面の上側ブロックがアナログ信号です。オレンジ色が送信波形で、青色がSpresenseの0番ピンの受信波形です。直結しているので、まったく同じ波形が観測できます。
下側のブロックはUARTのデータをデコードして表示する画面です。オシロスコープのチャネル1(オレンジ色)にDIO2ピンを、オシロスコープのチャネル2(青色)にDIO1ピンをつないでいます。送信している"123"を正しくデコードしています。HIGH/LOWは電源の50%付近を境に判断しているようなので、マイコンが正しくHIGH/LOWを判断できなくとも、デコードできる場合が多いです。
UARTのデータはLSBから送られています。I2CなどはMSBから送られます。
青色が、ソフトウェア・シリアルで受信しているSpresenseの10番ピンの波形です。ハードウェアのUARTとまったく同じ波形です。
●受信側のI/Oが3.3Vの場合
◆3.3V動作時のSpresenseが受信
送信側の5Vを受信側の3.3Vへ電圧を変えるには、抵抗による分圧が一番簡単です。
しかし、SpresenseのI/Oは1kΩで電源にプルアップされているので、0番のRx端子は信号がないときには3.3Vです。電圧の高いほうから低いほうへ電流が流れるので、I/O端子に5Vがかかると、Spresenseの電源へ電流が流れるので、望ましくありません。
拡張ボードには、ロジック・レベル・トランスレータLSF0204Rが入っており、5Vトレランスです。メイン・ボードへは1.8Vに変換されます。したがって、直結しても壊れないと思われます。けれど、筆者の勘違いもあるかもしれないので、直列に4.7kΩを入れて実験しました。波形を見ます。
LOWが3Vなので、通信できていません。直結しました。Spresenseの0番ピンには5Vの信号が入っています。
5Vトレランスなので直結しても問題はないのですが、5V側の電圧を阻止するためにスイッチング・ダイオード1N4148を入れました。このときの波形です。
Arduino UNOの11番ピンからLOWが送られると、ダイオードのカソードよりアノードが高い電圧になるので電流が流れ、Spresenseの0番ピン端子もLOWになります。Arduino UNOからHIGHが送られると、ダイオードのアノード(3.3V)よりカソード(5V)が高い電圧になるので電流は流れず、Spresenseの0番ピンは1kΩで3.3VへプルアップされているのでHIGHになります。
観測結果は、LOWは1.0V、HIGHは3.6Vでした。LOWが少し高めの電圧になっています。Cortex-Mは入力のLOW電圧はVcc*0.2なので、3.3*0.2=0.66Vです。ロジック・レベル・トランスレータLSF0204Rの入力のLOW電圧はVref*0.3なので、3.3*0.3=0.99Vです。したがって、LOWの入力電圧1.0Vはぎりぎりですが通信できています。
順方向電圧Vf=700mVの1N4148から、Vfが約半分の電圧のショットキー・ダイオードSD103Aに変更しました。LOWは0.5Vまで下がりました。問題なく通信できています。
つぎに、抵抗による分圧(1kと2.2kΩ)を使いました。LOWが1.6Vなので、SpresenseのLOWレベルを満足しないので、受信はできませんでした。SpresenseのI/Oポートには1kでプルアップされています。
「470Ωと10k」でLOWが1.2V、「330Ωと10k」でLOWが1.1V付近になって受信できましたが、HIGHが4Vを超えています。問題はないのですが、抵抗分割はすんなり抵抗値が決まりません。10kを取り外し、330ΩだけにするとLowは1.0V、HIGH=4.3Vで通信できました。
◆Raspberry Pi
ラズパイの電源は3.3Vです。I/OもHIGHは3.3Vです。RxD0、TxD0の端子はCPUから直接GPIOへ出ています。パワーオン・リセット後、HIGHになります。CPUの初期化の段階もしくは内部がUARTモジュールにつながっていて、マーク状態になっているのかもしれません。
ラズパイのI/Oは5Vトレラントではないので、3.3Vを超えないようにします。最初は、MOSFETのBSS138を使ったレベル変換回路を通してつなぎます。
送信側のArduino UNOのスケッチです。11番ピンから送信します。
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup() {
Serial.begin(9600);
Serial.println("Goodnight moon!");
mySerial.begin(9600);
}
void loop() {
mySerial.println("123");
delay(10);
}
ラズパイの受信側のPythonスクリプトと実行結果です。問題なく通信できています。ラズパイは10番ピン(GPIO15)で受信しています。
波形です。オレンジ色がArduino UNOの11番ピン、青色がラズパイの10番ピンで、HIGHは3.5V、LOWは0.2Vです。
MOSFETを使ったレベル変換回路は、本来、入出力の両方を抵抗でそれぞれの電源へプルアップします。前回調べたように、Arduino UNOのマーク(HIGH)状態なので、プルアップ抵抗を省略しました。
次はダイオードの回路です。ショットキー・ダイオードSD103Aを入れました。
波形です。HIGHは3.5V、LOWは0.8Vです。問題なく通信できています。
波形の立ち上がりがなまっているので、ラズパイのRxD0 10番ピンを10kΩで3.3Vへプルアップしました。立ち上がりがシャープになりました。
二つのマイコン間を抵抗だけでつないでみます。10kから22k程度の抵抗で通信はできましたが、HIGHが4V弱あり、ラズパイのI/O電圧の規格上限を超えています。長時間の動作は避けたいところです。
HIGHの電圧を下げるために青色LEDを入れました。
波形です。受信しているのは青色で、HIGHは2.8V、LOWは1.2Vです。問題なく通信できています。LEDに直列にショットキー・ダイオードを入れると、HIGHは3.0V、LOWは1.28Vになりましたが、通信できています。
分割抵抗で電圧を調整します。1kと1.2kで分圧したところ、LOWは0.2V、HIGHは2.9Vでした。通信は問題なくできました。
検索すると、ラズパイのHIGH(Vih)は2.1~2.3V、LOW(Vil)は0.8Vのようです。通信時のノイズなどの影響を考慮すれば、HIGHは3.3V、LOWは0Vにできるだけ近づけたレベル変換回路を選ぶのがよいといえます。
ここでは9600bpsで実験しています。波形がシャープなほうが、転送速度を上げていったときにも対応できるでしょう。