レベル変換 (5) UART その5 Arduino UNOが受信-2
- 1回目 UART端子の初期電圧
- 2回目 5Vで動作するArduino UNOから送信し、3.3Vで動作する「Spresense」もしくは「ラズパイ」が受信する
- 3回目 5Vで動作するArduino UNOから送信し、3.3Vで動作する「Trinket M0」もしくは「ESP32(DevKitC)」が受信する
- 4回目 3.3Vで動作する「Spresense」もしくは「ラズパイ」からの送信を5Vで動作するArduino UNOが受信する
今回は、3.3Vで動作する「Trinket M0」もしくは「ESP32(DevKitC)」からの送信を、5Vで動作するArduino UNOが受信する実験をします。
●Trinket M0とESP32(DevKitC)の特徴
Trinket M0とESP32(DevKitC)は3.3Vで動作します。I/O端子もHIGHは3.3Vなので、Arduino UNOの端子電圧5Vが直接かからないようにしなければなりません。
UARTで使われる端子は、何も信号がない状態ではマーク=HIGHになると想定していました。第1回の実験では、Arduino UNOとラズパイは、送受信の端子はともにHIGHでした。しかし、Trinket M0とESP32(DevKitC)では、送信端子はHIGH、受信端子はLOWでした。
●Trinket M0(3.3V)から送信してArduino UNO(5V)で受信する
Trinket M0のUARTは、3番のRxと4番のTxがデフォルトで利用できます。開発言語はMicroPythonとArduino IDEが使えます。ここでは、デフォルトで使えるMicroPythonでプログラムを作りました。
接続です。MOSEFETのBSS138を使ってレベル変換を行います。双方のマイコンのマーク状態はHIGHなので、プルアップ抵抗は省略しています。
送信するTrinket M0のプログラムです。
import board
import busio
import time
uart = busio.UART(board.TX, board.RX, baudrate=9600)
while True:
print("send")
uart.write("123\n")
time.sleep(0.1)
受信するArduino UNOのスケッチです。
#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()) {
Serial.write(mySerial.read());
}
delay(1);
}
受信しているシリアルモニタです。
Analog Discovery2を使って、これらの実験中の波形を示します。画面の上側ブロックがアナログ信号です。オレンジ色がTrinket M0からの送信波形で、青色がArduino UNOの10番ピンの受信波形です。
下側のブロックはUARTのデータをデコードして表示する画面です。オシロスコープのチャネル1(オレンジ色)にDIO2ピンを、オシロスコープのチャネル2(青色)にDIO1ピンをつないでいます。送信している"123"を正しくデコードしています。HIGH/LOWは電源の50%付近を境に判断しているようなので、マイコンが正しくHIGH/LOWを判断できなくとも、デコードできる場合が多いです。
Trinket M0の送信しているTx(4番)のLOWは-0.1V、HIGHは3.3Vです。
Arduino UNOの10番ピンは、LOWが0V、HIGHが3.7Vで、正常に受信できています。Arduino UNOのマイコンATMega328のI/OピンのHIGH Vih電圧は、約2.7V(グラフの読み、スペックは3.0V)です。したがって、5Vではなく3.7Vでもマージンをもっています。
レベル変換回路の送受信端子にそれぞれプルアップ抵抗を取り付けました。
波形です。 Trinket M0の送信しているTx(4番)のLOWは0V、HIGHは3.3Vです。
Arduino UNOの10番ピンは、LOWが0.1V、HIGHが3.9Vで、正常に受信できています。
●ESP32(3.3V)から送信してArduino UNO(5V)で受信する
デフォルトのUARTはRXD0とTXD0ですがシリアルモニタと兼用なので使わず、UART2のIO17(Tx)を利用しました。
接続です。
ESP32の送信スケッチです。
HardwareSerial mySerial(2); // UART2 16-Rx,17-Tx
void setup() {
Serial.begin(9600);
mySerial.begin(9600);
}
void loop() {
mySerial.write("123\n") ;
delay(10);
}
波形です。ESP32の送信しているIO17のLOWは0V、HIGHは3.3Vです。
Arduino UNOの10番ピンは、LOWが0.1V、HIGHが3.9Vで、正常に受信できています。
コラム 実測したArduino UNOのVih
Arduino UNOで使われているATMega368のI/O端子がHIGHを認識する電圧、Vihは0.6*Vddとデータシートに書かれています。電源電圧5Vで利用しているので3.0Vです。次のスケッチを使って、HIGHになる電圧を測りました。
5VとGND間に10kΩのボリュームをつなぎ、摺動接点を2番ピンにつないでいます。2番ピンの電圧をシリアルモニタに表示しています。表示は0か1です。ボリュームを回していき、0から1の表示に変わったときの2番ピンの電圧をテスタで読み取ります。
void setup() {
pinMode(2, INPUT);
Serial.begin(9600);
}
void loop() {
Serial.println( digitalRead(2) );
}2.30V付近でした。電圧を上げるときと下げるときで0.01Vぐらいの差がありました。Arduino UNOの5Vは実測4.90Vでしたからちょっと低めです。データシートの3.0Vと比べても相当低めの電圧でHIGHを判断していることがわかります。これは、もちろん、製造された時期などで微妙に異なることが推測できます。