ESP32のシリアル通信機能を利用して、外部機器とコマンドのやり取りをしようとしています。
115.2kボー、Serial2で通信を行い、通常はコマンドを正しく送受出来ていることが確認できています。
ただ、ごくまれに隣り合った2つのバイトデータの順序が逆になることがあり、その原因を調査しています。
「00 01 02 03 04」→ 「00 01 03 02 04」のような感じです。
通信ラインをオシロスコープで監視し、入れ替わった瞬間の通信データを確認しましたが、通信ライン上では入れ替わっておらず、Serial2.readBytesした時に入れ替わっているようでした。
読取る方法を変えてみようと、Serial.readBytesをreadやreadBytesUntilに変えてみましたが、同様の現象が発生しました。
どのように解決すればよいでしょうか?
ESP32はESP32-WROOM-32Eを使用しています。
C++
1// 簡略化したソース 2#define DEB_OUT(...) Serial.printf(__VA_ARGS__) 3 4void setup() 5{ 6// ~~~ 略 ~~~ 7 Serial.begin(115200, SERIAL_8N1); 8 Serial2.begin(115200, UART_CONF, RX2PortNo, TX2PortNo); 9 xTaskCreatePinnedToCore(UART_ReadTask, "UART_ReadTask", 4096, NULL, 10, &TaskUART, 0); 10// ~~~ 略 ~~~ 11 12} 13 14void UART_ReadTask(void* arg) 15{ 16 while (1) 17 { 18 char tmp[64]; // ESP32シリアル通信用の受信バッファは64バイトまで格納することが出来る 19 size_t readBts = 0; 20 int len = Serial2.available(); 21 if (len > 0) 22 { 23 if (len > 64) {len = 64;} 24 readBts = Serial2.readBytes(tmp, len); 25 if (readBts) 26 { 27 DEB_OUT("\tResponse: "); // ここのデバッグ出力で既に入れ替わっている 28 for (int i=0; i<readBts; i++)DEB_OUT("%02X ", tmp[i]); 29 DEB_OUT("\n"); 30 cmdCtrl.SetData((UByte*)tmp, (UWord)readBts); // コマンド解析 31 } 32 } 33 vTaskDelay(1); 34 } 35} 36
//-------------------------------------------------------------------------------------
// 以下追記
//-------------------------------------------------------------------------------------
GW期間中、PCを触れる環境でなく、ご回答、ご指摘いただいていながらお返事が遅くなり申し訳ございません。
デバッグ出力ですが、減少が起きた時のスクリーンショットが残っていました。
以下が、この入れ替わった時の通信ラインの波形です。
入れ替わった時(上記 ID IS CHANGED を出力した時)に青いラインがハイになるようにして、直前の通信データを確認しています。
02 をスタートコード、0D をエンドコードとしたフォーマットで、赤枠内のデータを収集するような動作を行っています。
デバッグ出力自体はこのフォーマット全体を出力しています。
これらのデータが、以下のような間隔で送られてきています(黄色の縦線一つが上図のデータ全部相当)
およそ100ms強ほどの間隔で「送られてくるとき」「送られてこないとき」が切り替わり、「送られてくるとき」は最短15ms間隔ほどで数発送られてきます。
//-------------------------------------------------------------------------------------
// 以下再追記
//-------------------------------------------------------------------------------------
通信処理部をメインループで行うようにすると、現象が起きなくなりました。シリアル通信をマルチタスクですると問題があるのかもしれません。
現象の原因はわからないのですが、もう少し様子を見て、問題なさそうならシングルタスクにして(ひとまず)解決にするのもアリかもしれません。
該当部のみ書き出した、現象確認用のソースを作成しました。
C++
1#include <Arduino.h> 2#include "comm.h" 3#include <rom/rtc.h> 4 5TaskHandle_t TaskUSB = NULL; 6TaskHandle_t TaskUART = NULL; 7const UByte RX2PortNo = 16; 8const UByte TX2PortNo = 17; 9 10void USB_ReadTask(void* arg); 11void UART_ReadTask(void* arg); 12 13// *** USE_UARTReadTask をコメントアウトしていると、減少が発生しない 14//#define USE_UARTReadTask 15//#define USE_USBReadTask 16 17void setup() { 18 // put your setup code here, to run once: 19 SetupIO(); 20 Serial.begin(115200, SERIAL_8N1); 21 Serial2.begin(115200, SERIAL_8N1, RX2PortNo, TX2PortNo); 22// Serial2.setTimeout(10); // 読み取りタイムオーバー時間の設定:readuntil系で必要。 23 24#ifdef USE_UARTReadTask 25 xTaskCreatePinnedToCore(UART_ReadTask, "UART_ReadTask", 4096, NULL, 10, &TaskUART, 0); 26#endif 27#ifdef USE_USBReadTask 28 xTaskCreatePinnedToCore(USB_ReadTask, "USB_ReadTask", 4096, NULL, 10, &TaskUSB, 0); 29#endif 30} 31 32void UART_ReadTask(void* arg) 33{ 34 while (1) 35 { 36 char tmp[64]; // ESP32シリアル通信用の受信バッファは64バイトまで格納することが出来る 37 size_t readBts = 0; 38 39 int len = Serial2.available(); 40 if (len > 0) 41 { 42 if (len > 64) {len = 64;} 43 readBts = Serial2.readBytes(tmp, len); 44 if (readBts) 45 { 46 DEB_OUT("\tIF < RW: "); 47 for (int i=0; i<readBts; i++) 48 { 49 Serial.write(tmp[i]); 50 DEB_OUT("%02X ", tmp[i]); 51 } 52 DEB_OUT("\n"); 53 } 54 } 55 vTaskDelay(1); 56 } 57} 58 59void USB_ReadTask(void* arg) 60{ 61 while (1) 62 { 63 int len = Serial.available(); 64 if(len) 65 { 66 for(int i=0;i<len;i++) 67 { 68 int ch = Serial.read(); 69 Serial2.write(ch); 70 } 71 } 72 vTaskDelay(1); // delay(1); 73 } 74} 75 76void loop() { 77 int len; 78 // put your main code here, to run repeatedly: 79 if (digitalRead(SW_RD_TRIG) == 0) 80 { 81 digitalWrite(EN_POWER, 0); 82 } 83#ifndef USE_UARTReadTask 84 //------------------------------------------------------------------------------- 85 // UART_ReadTask 86 len = Serial2.available(); 87 char tmp[64]; // ESP32シリアル通信用の受信バッファは64バイトまで格納することが出来る 88 if (len > 0) 89 { 90 if (len > 64) {len = 64;} 91 size_t readBts = Serial2.readBytes(tmp, len); 92 if (readBts) 93 { 94 for (int i=0; i<readBts; i++) 95 { 96// while(Serial.availableForWrite() == 0); 97 Serial.write(tmp[i]); 98 } 99 DEB_OUT("\n"); 100 } 101 } 102#endif 103#ifndef USE_USBReadTask 104 //------------------------------------------------------------------------------- 105 // USB_ReadTask 106 len = Serial.available(); 107 if(len) 108 { 109 for(int i=0;i<len;i++) 110 { 111 int ch = Serial.read(); 112// while(Serial.availableForWrite() == 0); 113 Serial2.write(ch); 114 } 115 } 116 //------------------------------------------------------------------------------- 117#endif 118}
回答3件
あなたの回答
tips
プレビュー