SoftwareSerialの「文字化け」や「受信データの破損」対策をする [Arduino/ESP-WROOM-02]
ArduinoからESP-WROOM-02を使用する際のシリアル通信には「HardwareSerial」と「SoftwareSerial」の2種類があります。
HardwareSerialは問題ありません。問題なのはSoftwareSerialです。SoftwareSerialでシリアル通信のbaudrate(ボーレート)が「115200bps」だと必ず受信データが破損して文字化けが発生します。
今回は検証結果と対策をご紹介します。
1. 配線図
今回は検証の為、電源はArduinoの「3.3V」を使用します。ESP-WROOM-02は実行用(Flash Boot Mode)の配線です。
<※本来は「TX/RX」は5Vなのでレベル変換(FXMA2102、PCA9306)を使用して3.3Vにします。(省略)
2. HardwareSerialの検証(115200bps)
スケッチ
ATコマンドでバージョン情報をシリアルモニターへ表示します。
// シリアルバッファを取得する // ※バッファは最大64バイトなので、時間で繰り返し取得します。 String getSerialBuffer(Stream* mySerial,uint32_t readTime){ char c; String result = ""; uint32_t st = millis(); // readTimeの間、シリアルバッファを読み込む while ((millis() - st) < readTime) { while(mySerial->available() > 0){ c = mySerial->read(); if(c == '\0'){ continue; } result += c; } } return result; } void setup() { Serial.begin(115200); delay(10); // ATコマンドでバージョン情報を取得する Serial.println("AT+GMR"); String str = getSerialBuffer(&Serial,1000); // ゴミの削除 str.replace("AT+GMR",""); str.replace("\r\r\n",""); str.replace("\r\nOK",""); Serial.println(str); } void loop() { }
実行結果
ハードウェアシリアルは正常に表示されます。
3. SoftwareSerialの検証1(115200bps)
ATコマンドでバージョン情報をシリアルモニターへ表示します。
#include <SoftwareSerial.h> SoftwareSerial mySerial(2,3); // TX, RX // シリアルバッファを取得する // ※バッファは最大64バイトなので、時間で繰り返し取得します。 String getSerialBuffer(Stream* mySerial,uint32_t readTime){ char c; String result = ""; uint32_t st = millis(); // readTimeの間、シリアルバッファを読み込む while ((millis() - st) < readTime) { while(mySerial->available() > 0){ c = mySerial->read(); if(c == '\0'){ continue; } result += c; } } return result; } void setup() { Serial.begin(115200); mySerial.begin(115200); // ATコマンドでバージョン情報を取得する mySerial.println("AT+GMR"); String str = getSerialBuffer(&mySerial,1000); Serial.println(str); } void loop() { }
実行結果
ハードウェアシリアルの実行結果と見比べてみるとわかりますが、ソフトウェアシリアル(115200bps)の受信データは破損しています。
4. SoftwareSerialの検証2(9600/115200bps)
最初に115200bpsでバージョン情報を表示後、シリアル通信速度を9600bpsに変更してから2回目のバージョン情報をシリアルモニターへ表示します。
#include <SoftwareSerial.h> SoftwareSerial mySerial(2,3); // シリアルバッファを取得する // ※バッファは最大64バイトなので、時間で繰り返し取得します。 String getSerialBuffer(Stream* mySerial,uint32_t readTime){ char c; String result = ""; uint32_t st = millis(); // readTimeの間、シリアルバッファを読み込む while ((millis() - st) < readTime) { while(mySerial->available() > 0){ c = mySerial->read(); if(c == '\0'){ continue; } result += c; } } return result; } void setup() { Serial.begin(9600); mySerial.begin(115200); delay(10); // 1回、実行をするとESP-WROOM-02のシリアル通信速度が9600となります。 // 2回目以降は通信速度が115200の「1.」「2.」は実行されませんのでご注意を。 // ※デフォルトの115200に戻すには、USB電源(給電)をはずせばOKです。 // 1. バージョン情報[115200] mySerial.println("AT+GMR"); Serial.println(getSerialBuffer(&mySerial,1000)); // 2. シリアル通信速度の変更[115200] // 通信速度 : 9600 // データ : 8bits // ストップ : 1bit // パリティ : none // フロー制御 : none mySerial.println("AT+UART_CUR=9600,8,1,0,0"); Serial.println(getSerialBuffer(&mySerial,1000)); mySerial.begin(9600); delay(10); // 3. バージョン情報[9600] mySerial.println("AT+GMR"); Serial.println(getSerialBuffer(&mySerial,1000)); } void loop() { }
実行結果
115200bpsは「文字化け」が発生して、9600bpsは正常に表示されます。
この事からArduinoからSoftwareSerialでESP-WROOM-02を操作するには「115200bps」を使用してはいけない事となります。
AT+UART_CURのフロー制御について(メモ書き)
ESP8266 AT Instruction Set(ATコマンド)(p18)から抜粋。
本文 | 日本語訳 |
---|---|
Flow control needs hardware support: MTCK is UART0 CTS and MTDO is UART0 RTS. | フロー制御にはハードウェアサポートが必要:MTCKはUART0 CTS、MTDOはUART0 RTS。 |
ここを見る限り「MTCK = GPIO_13」「MTDO = GPIO_15」のようです。
http://www.esp8266.com/viewtopic.php?p=40512
※但し、Arduinoからは使用する事はできません。ESP-WROOM-02にArduinoスケッチを書き込む場合のようです。
掲示板
ArduinoやRaspberry Piなどの電子工作の掲示板を作成しました。質問やわからない事は電子工作 (Arduino・ラズパイ等)でユーザー同士で情報を共有して下さい。