質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

Q&A

解決済

3回答

3855閲覧

ArduinoとProcessingのシリアル通信

Aizawasan

総合スコア1

シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

0グッド

1クリップ

投稿2021/11/09 13:43

編集2021/11/09 13:58

前提・実現したいこと

Arduinoで計測したデータをProcessing上で表示したい
ArduinoからSerial.writeで送ったデータはProcessing上で見ることができました.

今回は複数センサ(現状8個,将来的には倍)からの情報をProcessingで表示したいと考えています.
マイコンの入力の都合で現在はセンサ4つのみ(P1~P4)実装しています.

シリアル通信では,取得したセンサ値を8ビット二つに分けて送信し,通信の前後で符牒を入れる形にしたいと思っています.

参考にしたサイト https://garchiving.com/arduino-x-processing-serial-communication/
のコードを元に改変しています.

Processingのコンソール

Processing上のコンソールではoverflowと表示される
myPort.available()の数字が1000などすごい数字になっている(そもそもこれの意味がよく分かりません)

overflow 984 overflow 834 overflow

該当のソースコード

Arduino

1void setup(){ 2 Serial.begin( 57600 ); 3} 4 5void loop(){ 6 int P1,P2,P3,P4,P5,P6,P7,P8; 7 P1 = analogRead( A0 ); 8 P2 = analogRead( A1 ); 9 P3 = analogRead( A2 ); 10 P4 = analogRead( A3 ); 11 12/* 13 P1=map(P1, 0, 1023, 0, 255); 14 P2=map(P2, 0, 1023, 0, 255); 15 P3=map(P3, 0, 1023, 0, 255); 16 P4=map(P4, 0, 1023, 0, 255); 17*/ 18/* 19 P1 = P1 * 5.0 / 1023.0; 20 P2 = P2 * 5.0 / 1023.0; 21 P3 = P3 * 5.0 / 1023.0; 22 P4 = P4 * 5.0 / 1023.0; 23*/ 24 25 if (Serial.available() == 1) { 26 byte inBuf[1]; 27 Serial.readBytes(inBuf, 1); 28 if (inBuf[0] == 's') { 29 //ここに送信処理を記述 30 Serial.println("send"); 31 digitalWrite(8,HIGH); 32 byte outBuf[18]; 33 34 outBuf[0] = 's'; // 1 35 outBuf[1] = (int16_t)(P1) >> 8; // 2 36 outBuf[2] = (int16_t)(P1) & 0xFF; // 3 37 outBuf[3] = (int16_t)(P2) >> 8; // 4 38 outBuf[4] = (int16_t)(P2) & 0xFF; // 5 39 outBuf[5] = (int16_t)(P3) >> 8; // 6 40 outBuf[6] = (int16_t)(P3) & 0xFF; // 7 41 outBuf[7] = (int16_t)(P4) >> 8; // 8 42 outBuf[8] = (int16_t)(P4) & 0xFF; // 9 43 outBuf[9] = (int16_t)(P5) >> 8; // 10 44 outBuf[10] = (int16_t)(P5) & 0xFF; // 11 45 outBuf[11] = (int16_t)(P6) >> 8; // 12 46 outBuf[12] = (int16_t)(P6) & 0xFF; // 13 47 outBuf[13] = (int16_t)(P7) >> 8; // 14 48 outBuf[14] = (int16_t)(P7) & 0xFF; // 15 49 outBuf[15] = (int16_t)(P8) >> 8; // 16 50 outBuf[16] = (int16_t)(P8) & 0xFF; // 17 51 outBuf[17] = 'e'; // 18 52 53 54 Serial.write(outBuf, 18); 55 } 56 else { 57 while (Serial.available() > 0)Serial.read(); 58 Serial.println("wait"); 59 60 } 61 } 62 if (Serial.available() > 1) { 63 while (Serial.available() > 0)Serial.read(); 64 } 65 66 Serial.print("P1: "); 67 Serial.println(P1); 68 /*Serial.print( "P1: " ); 69 Serial.println( P1 ); 70 Serial.print( "P2: " ); 71 Serial.println( P2 ); 72 Serial.print( "P3: " ); 73 Serial.println( P3 ); 74 Serial.print( "P4: " ); 75 Serial.println( P4 ); 76 77 Serial.write(P1); 78 */ 79 //delay( 100 ); 80} 81### 該当のソースコード 82 83```Processing 84import processing.serial.*; 85float P1, P2, P3, P4, P5, P6, P7, P8; 86int serialTimer; 87Serial myPort; 88 89 90int data; 91 92void setup() 93{ 94 size(500, 500); 95 myPort = new Serial(this, Serial.list()[4], 57600); 96} 97 98void draw() { 99 if (millis()-serialTimer > 50) { 100 serialTimer = millis(); 101 byte[] inBuf = new byte[18]; 102 println(myPort.available()); 103 if (myPort.available() == 18) { 104 myPort.readBytes(inBuf); 105 if (inBuf[0]=='s'&& inBuf[17]=='e') { 106 P1 = (inBuf[1]<<8)+(inBuf[2]&0xff);; 107 P2 = (inBuf[3]<<8)+(inBuf[4]&0xff);; 108 P3 = (inBuf[5]<<8)+(inBuf[6]&0xff);; 109 P4 = (inBuf[7]<<8)+(inBuf[8]&0xff);; 110 P5 = (inBuf[9]<<8)+(inBuf[10]&0xff);; 111 P6 = (inBuf[11]<<8)+(inBuf[12]&0xff);; 112 P7 = (inBuf[13]<<8)+(inBuf[14]&0xff);; 113 P8 = (inBuf[15]<<8)+(inBuf[16]&0xff);; 114 115 116 } else { 117 while (myPort.available()>0)myPort.read(); 118 println("missMatch"); 119 } 120 } else if (myPort.available() > 18) { 121 while (myPort.available()>0)myPort.read(); 122 println("overflow"); 123 } 124 byte[] outBuf = new byte[1]; 125 outBuf[0] = 's'; 126 127 myPort.write(outBuf); 128 } 129 130 background(0); 131 fill(240); 132 textSize(24); 133 text(nf(P1, 0, 2), 50, 50); 134 text(nf(P2, 0, 2), 50, 80); 135 text(nf(P3, 0, 2), 50, 110); 136 text(nf(P4, 0, 2), 50, 140); 137 text(nf(P5, 0, 2), 50, 170); 138 text(nf(P6, 0, 2), 50, 200); 139 text(nf(P7, 0, 2), 50, 230); 140 text(nf(P8, 0, 2), 50, 260); 141}

試したこと

Processing側でmy Port .clear()を入れるなど
他ウェブ上の記事も参考にしましたが,分からなくなってきてしまい,質問させていただくことになりました.

参考記事https://garchiving.com/arduino-x-processing-serial-communication/のコードをそのまま使いましたが(ポート周りは設定し直しています),Processingのコンソール上ではoverflowの表示は出ませんでした.
使っているセンサが違うので,Arduino側でセンサ値を適当な定数にして試しましたが,Processing上では0.00の表示のままでした(通信できてない?)

###環境
Arduino1.8.15
Processing3.3.5

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

分からなくなってきてしまい

わからなくなったのではなく、最初からわからないまま真似をしていたりしないでしょうか。
参照先サイトのヒトもあまりわかってないような気配もありますが。

まず、受信側のProcessingのプログラムと話を合わせるなら、そちらは一周期に18バイトピッタリを受け取ることしか考えていないのですから
Serial.write(outBuf, 18);
以外にシリアルに出力するSerial.print()の類は一切存在してはいけません。

他にもなにかあるかも知れませんが、少なくとも

Processing

1byte b=(byte)0xff; 2println(b<<8);

の結果が-256になるあたりからみて、
P1 = (inBuf[1]<<8)+(inBuf[2]&0xff);;
はまともに変換できないケースがでてくるでしょう。なぜだめかは「符号拡張」という言葉について調べてみるとよろしいかと思います。
(ところでなぜセミコロンが2つ?)


若干意地になって...「本当に質問のままのArduinoプログラム」でもデータを切り出して取得するProcessing側プログラム

Processing

1import processing.serial.*; 2 3final int SENSOR_NUM = 8; //センサー数 Arduino側と同じであること 4final char START_TRIG = 's'; //送信リクエスト文字 Arduino側と同じであること 5final char START_CHAR = 's'; //データヘッダ Arduino側と同じであること 6final char END_CHAR = 'e'; //データ終端 Arduino側と同じであること 7 8final int REQ_PERIOD = 50; //データリクエスト周期 9 10//この通信方法では浮動小数点数データは転送できない.., 11//こともないけれど普通やらないのでデータを取る変数はint 12int[] P = new int[SENSOR_NUM]; 13int serialTimer; 14Serial myPort; 15 16int count; 17byte[] inBuf = new byte[SENSOR_NUM*2+2]; 18 19void setup() { 20 size(500, 500); 21 myPort=new Serial(this, "COM13", 57600);//こちらの環境にあわせて 22 delay(3000); //Arduinoの起動を待つ 23 serialTimer=millis(); 24 myPort.write(START_TRIG); //リクエスト送信 25} 26 27void draw() { 28 if (millis()-serialTimer > REQ_PERIOD) { //送信リクエスト周期? 29 if (count==0) { //前回データ受信がなかった 30 println("NO DATA."); 31 } else if (count<SENSOR_NUM*2+2) { 32 println("TIMEOUT."); //リクエスト周期内に通信が完了しなかった 33 } else if (count>SENSOR_NUM*2+2) { 34 println("OVERRUN."); //余計な文字受信があった 35 } 36 myPort.write(START_TRIG); //リクエスト送信 37 serialTimer=millis();//時刻記録 38 count=0;//データ蓄積開始 39 } 40 while (myPort.available()!=0) { //受信済文字がある間ループ 41 int data=myPort.read(); 42 if (count<SENSOR_NUM*2+2) { 43 //規定文字数未受信なのでデータを溜める 44 inBuf[count]=(byte)data; 45 } else { 46 //既に受信完了しているので表示だけ 47 print((char)data); 48 } 49 count++; 50 if (count==SENSOR_NUM*2+2) {//規定のバイト数を受信した 51 if (inBuf[0]!=START_CHAR || inBuf[SENSOR_NUM*2+1]!=END_CHAR) { 52 //正しいフォーマットでなかったので一文字捨ててやり直し 53 print((char)inBuf[0]);//捨てられる一文字を表示しておく 54 for (int i=0; i<SENSOR_NUM*2+1; i++) { 55 inBuf[i]=inBuf[i+1]; 56 } 57 count--; 58 } else { 59 //正しいフォーマットだったので値取り込み 60 for (int i=0; i<SENSOR_NUM; i++) { 61 P[i]=((inBuf[i*2+1]<<8)&0xff00) + (inBuf[i*2+2]&0xff); 62 } 63 count++; 64 } 65 } 66 } 67 68 background(0); 69 fill(240); 70 textSize(24); 71 for (int i=0; i<SENSOR_NUM; i++) { 72 text(P[i], 50, 50+30*i); 73 } 74}

そして、できればこのくらいに書きたいな、というArduino側プログラム

Arduino

1const int SENSOR_NUM = 8; //センサー数 Processing側と同じであること 2const char START_TRIG = 's'; //送信リクエスト文字 Processing側と同じであること 3const char START_CHAR ='s'; //データヘッダ Processing側と同じであること 4const char END_CHAR ='e'; //データ終端 Processing側と同じであること 5 6const int INTERNAL_AD = 6; //内蔵AD数 INTERNAL_AD<=SENSOR_NUMであること 7const int SENSOR_PIN[INTERNAL_AD] = {A0, A1, A2, A3, A4, A5}; // 内蔵ADピンアサイン 8 9void setup() { 10 Serial.begin(57600); 11} 12 13void loop() { 14 uint16_t ads[SENSOR_NUM]; 15 //データ取得 (内蔵ADC) 16 for ( int i = 0; i < INTERNAL_AD; i++) { 17 ads[i] = analogRead(SENSOR_PIN[i]); 18 } 19 // 内蔵AD以外のデータ。質問に情報がないので乱数 20 for( int i=INTERNAL_AD;i<SENSOR_NUM; i++){ 21 ads[i]=random(1024); 22 } 23 24 if (Serial.read() == START_TRIG) {//送信リクエストを受信したら 25 Serial.print(START_CHAR);//開始文字送信 26 for(int i=0;i<SENSOR_NUM;i++){//各データ送信 27 Serial.write(ads[i]/256); 28 Serial.write(ads[i]); 29 } 30 Serial.print(END_CHAR);//終端文字送信 31 } 32}

投稿2021/11/09 14:33

編集2021/11/10 13:33
thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thkana

2021/11/09 22:46

あ、符号拡張の方は10あるいは12bitの値を扱っている範囲では大丈夫とは言えるか。気持ちよくはないけれど。
Aizawasan

2021/11/10 02:23

おっしゃる通り,実装のために必要な知識が一切足りていない状況でした. 符号拡張について調べてみます. ありがとうございました.
退会済みユーザー

退会済みユーザー

2024/02/10 23:58 編集

古いコメントに横か
bikakushida

2024/02/11 03:13 編集

>thkana 符号拡張について、int型は符号付4byteだよね。 (inBuf[i*2+1]<<8)&0xffffff00)まで指示しないと。 byte b = -128; println((b<<1)&0xff00); -256じゃなくて65280になっちゃうよ。マイナス値があるとことを想定したらこっちの方がまともに変換できない。まだ println(b<<1)このままのがいい。
thkana

2024/02/11 12:00

bikakushidaさん わざわざこのコメントのために?退会/新規アカウント取り直しご苦労様。 bが0x80だったら、演算結果として0x8000が欲しいのであって、0xffff8000がほしいわけじゃない。 のでは。今日ちょっと頭痛があって全然頭が回ってないのだけれど。
guest

0

ベストアンサー

まず、データを送信する前に、

Serial.println("send");

ってのが入ってますが、受信側ではこの文字列も含めて受信されてるため、オーバーフローになってますね

投稿2021/11/09 14:09

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Aizawasan

2021/11/10 02:24

該当の部分をコメントアウトしたところ望んでいた動作が出来ました! ありがとうございます!
y_waiwai

2021/11/10 02:35

今の質問での回答としてはこれでいけるでしょう、けど、他回答にもありますが、まだまだ問題は残っています 現状では、送信した、そのあとに受信した、とタイミング合わせれば受信はできるでしょうけど、それでは使いもんにはなりません まだまだ道程は遠いですけど、がんばってください
thkana

2021/11/10 03:38

> 該当の部分をコメントアウトしたところ望んでいた動作が出来ました 本当にそうかなぁ? 「それだけでうまくいくはずはない」のだけれど。
guest

0

あ、符号拡張の方は10あるいは12bitの値を扱っている範囲では大丈夫とは言えるか。気持ちよくはないけれど。

投稿2021/11/09 22:39

thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thkana

2021/11/09 22:46

先のコメントにしようとして間違えて回答にしてしまったため削除依頼中です。
退会済みユーザー

退会済みユーザー

2024/02/11 00:00 編集

符号拡
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問