Processingのシリアル通信で「Error, disabling serialEvent()」というエラーがでたら
ProcessingでArduinoとかとシリアル通信をやるとき、
Error, disabling serialEvent() for <ポート番号>
というエラーにでくわすことがあります。
なぜこのエラーがでるのか、なにを疑えばいいのか
このエラーメッセージを表示しているのは、Serialライブラリの以下の箇所です。
processing/Serial.java at master · processing/processing · GitHub
if (serialEventMethod != null) { if ((0 < bufferUntilSize && bufferUntilSize <= inBuffer-readOffset) || (0 == bufferUntilSize && bufferUntilByte == buffer[inBuffer-1])) { try { // serialEvent() is invoked in the context of the current (serial) thread // which means that serialization and atomic variables need to be used to // guarantee reliable operation (and better not draw() etc..) // serialAvailable() does not provide any real benefits over using // available() and read() inside draw - but this function has no // thread-safety issues since it's being invoked during pre in the context // of the Processing applet serialEventMethod.invoke(parent, this); } catch (Exception e) { System.err.println("Error, disabling serialEvent() for "+port.getPortName()); System.err.println(e.getLocalizedMessage()); serialEventMethod = null; } } }
このコードから、serialEvent()関数の実行により例外が発生したときにこのメッセージが表示されることがわかります。つまり、「Error, disabling serialEvent() 」というメッセージがでたら、serialEvent()関数の中で何かまずい処理をやっていないか疑うべきです。
エラーがでる例
ひとつ例を見てみましょう。以下のコードは一見すると問題なさそうに見えますが、実行すると「Error, disabling serialEvent() 」というエラーがでます。
import processing.serial.*; Serial serial; void setup() { size(400,300); serial = new Serial( this, Serial.list()[0], 9600 ); // シリアル通信を設定 } void draw() { background(0); } void serialEvent(Serial port) { if ( port.available() > 0 ) { // データが受信されたら String recv = port.readStringUntil('\n'); // 改行まで文字列を読み込む recv = recv.replace("\n", ""); // 受信したデータから改行を消す println(recv); // 受信したデータを表示する } }
原因はどこかと言うと、
String recv = port.readStringUntil('\n'); // 改行まで文字列を読み込む recv = recv.replace("\n", ""); // 受信したデータから改行を消す
の部分です。
readStringUntil()の受信結果はnullになる可能性があり、recvがnullだった場合にreplace()のところでエラーが発生します。ここでせめて「NullPointerException」と言ってくれればすぐに気づきそうなものですが、「Error, disabling serialEvent() for <ポート番号>」と言われると通信エラーかな?と思ってしまいますし、通信相手のデバイスが悪いのかな? ケーブルが悪いのかな?とハードウェアのほうを疑いだすとなかなか気づけません。
たまにこの罠にひっかかるので備忘録として書きました。以上。