🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

シリアルポート

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Arduino

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

Q&A

解決済

2回答

3268閲覧

Arduinoでシリアルデータが受信できない時があります

Alyn

総合スコア51

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

シリアルポート

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Arduino

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

0グッド

0クリップ

投稿2021/01/06 01:26

編集2021/01/06 03:20

前提・実現したいこと

PC(MFC)から送信される0x00~0xFFまでのバイナリデータをArduinoで正しく受信したいです。

発生している問題

送信するデータ内容によって、データが消失したか何かで無限ループから抜け出せなくなりました。

該当のソースコード

Arduino

1const int DataMax = 12; 2byte rxData[50][DataMax] = { 0 }; 3int rxCount = 0; 4 5const int Cpin = 7; 6const int Spin = 8; 7const int Upin = 9; 8 9void setup() 10{ 11 Serial.begin(9600); 12 pinMode(Cpin, OUTPUT); 13 pinMode(Spin, OUTPUT); 14 pinMode(Upin, OUTPUT); 15 digitalWrite(Cpin, HIGH); 16 digitalWrite(Spin, HIGH); 17 digitalWrite(Upin, HIGH); 18} 19 20void loop() 21{ 22 SerialRead(); 23} 24 25bool SerialRead() 26{ 27 int recv = 0; 28 bool result = false; 29 30 //シリアル受信判定 31 if(Serial.available() > 0) 32 { 33 recv = Serial.read(); //1byteずつ吐き出し 34 35 //ヘッダー分岐 36 switch(recv) 37 { 38 case 'C' : 39 { 40 Hedder_C(); 41 digitalWrite(Cpin, LOW); 42 setupData(); 43 digitalWrite(Spin, LOW); 44 result = true; 45 break; 46 } 47 case 'U' : 48 { 49 Hedder_U(); 50 digitalWrite(Upin, LOW); 51 result = true; 52 break; 53 } 54 default: 55 { 56 break; 57 } 58 } 59 } 60 61 return result; 62} 63 64void Hedder_C() 65{ 66 int recv = 0; 67 68 //データ数取得 69 while(1) 70 { 71 recv = Serial.read(); //1byteずつ吐き出し 72 if(recv != -1) 73 { 74 rxCount = recv; 75 rxCount++; 76 break; 77 } 78 } 79} 80 81void setupData() 82{ 83 int recv = 0; 84 85 for(int k = 0; k < rxCount; k++) 86 { 87 //ヘッダー取得 88 while(1) 89 { 90 recv = Serial.read(); //1byteずつ吐き出し 91 if(recv == 'S') 92 { 93 //データ本体取得 94 for(int j = 0; j < DataMax; j++) 95 { 96 while(1) 97 { 98 recv = Serial.read(); //1byteずつ吐き出し 99 if(recv != -1) 100 { 101 rxData[k][j] = (byte)recv; 102 break; 103 } 104 } 105 } 106 break; 107 } 108 } 109 } 110} 111 112void Hedder_U() 113{ 114 int recv = 0; 115 int pos = 0; 116 117 //データ位置取得 118 while(1) 119 { 120 recv = Serial.read(); //1byteずつ吐き出し 121 if(recv != -1) 122 { 123 pos = recv; 124 break; 125 } 126 } 127 128 //データ本体取得 129 for(int j = 0; j < DataMax; j++) 130 { 131 while(1) 132 { 133 recv = Serial.read(); //1byteずつ吐き出し 134 if(recv != -1) 135 { 136 rxData[pos][j] = (byte)recv; 137 break; 138 } 139 } 140 } 141}

受信するシリアルデータ

  1. 総データ数:0x43(ヘッダーC), 0x00(データ数-1)
  2. データ設定:0x53(ヘッダーS), 0x34, 0xB8, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00(データ12byte)

[受信できたデータ設定]
0x53, 0x34, 0xB8, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

0x53, 0x34, 0xB8, 0x64, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

0x53, 0x34, 0xB8, 0x64, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

0x53, 0x34, 0xB8, 0x64, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00

0x53, 0x34, 0xB8, 0x64, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00

[受信できないデータ設定]
0x53, 0x34, 0xB8, 0x64, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

0x53, 0x34, 0xB8, 0x64, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00

通信シーケンス

  1. 総データ数を受信する
  2. 受信した総データ数分だけデータ設定が来るので、それを配列に格納する

※記述はないがヘッダーUで特定のデータの中身を書き換える

試したこと

ボーレートを115200や9600を試してもダメでした。

追記

全ての組み合わせを確認できたわけではありませんが、メッセージの6(0開始)番目が0以外だと必ず発生しました。

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

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

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

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

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

A_kirisaki

2021/01/06 03:12

この場合実際のヘッダー C って 0x43, 0x06 になって、二つのデータ設定が受信できてないって感じですか?
Alyn

2021/01/06 03:15

ヘッダーは問題なく受信できています。例えばデータ設定が7つの場合は総データ数のメッセージが「0x43, 0x06」で届きます。
A_kirisaki

2021/01/06 03:22

7 つのデータはどんなパターンでも受け取れる?それとも下の二つのパターンだけ受け取れない?どうやって確認しました?(質問攻めで大変だと思いますが解決に向けてなので)
Alyn

2021/01/06 03:40

LEDが消灯するかでやっています。本当はLCDを使いたいのですが、今手元にないので正しく受信できればLEDを消せますのでそれで検証しています
guest

回答2

0

自己解決

配列の宣言に誤りがありました。上記コードはコピーしたものではないため気づきませんでした。

投稿2021/01/06 04:37

Alyn

総合スコア51

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

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

guest

0

回答ではありません

メッセージ形式が必ずヘッダデータがきて、一定バイト数、の通信であるなら、
1文字づつ処理するのではなく、そのメッセージのサイズ+αのバッファを用意しておき、
まずは一つのメッセージを受信する処理を書きましょう。
そして、メッセージの受信が完了したら、そのメッセージに対しての処理を行う、というふうにします。
そうすることで、受信部の問題の検証がやりやすくなります

投稿2021/01/06 01:41

y_waiwai

総合スコア88040

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

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

Alyn

2021/01/06 02:23

回答ありがとうございます。Arduinoにはシリアル受信の関数が1byteずつ読み出すものしかないためできません…
y_waiwai

2021/01/06 02:28

1バイトの受信データをバッファに順番に格納していくような関数を作りましょう。 そこに余計な処理はいりません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問