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

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

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

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

Arduino

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

Q&A

解決済

3回答

5834閲覧

複数の値をシリアル通信で送りたいが0を受け取ってしまう。

ISO130

総合スコア8

シリアルポート

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

Arduino

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

0グッド

0クリップ

投稿2020/09/04 17:32

前提・実現したいこと

ESP32からシリアル通信で2つの値を送り、ArduinoUNOで2つの値に受け取りたいと思っています。
webの情報を参考に実施したのですが、UNOで受け取れた値が双方とも0です。
(正確に言うと、ヘッダー付きの計3つを送っているのですが、UNO側ではヘッダーにすべての値が入ってしまい、
残り2つの値にはゼロが入ってしまいます。)

発生している問題・エラーメッセージ

ArduinoUNOにて Serial.println(header); と記載した場合のシリアルモニタ出力は 255 100 200 Serial.println(lat_dis_c); と記載した場合のシリアルモニタ出力は 0 Serial.println(lon_dis_c); と記載した場合のシリアルモニタ出力は 0

該当のソースコード

arduino

1 2(ESP32:送信側) 3 4HardwareSerial mySerial1(1); 5void setup() { 6 Serial.begin(115200); 7 mySerial1.begin(9600, SERIAL_8N1, 32, 33);// ピンを変更 (RX=32, TX=33) 8} 9 10void loop() { 11 int data = 100; 12 int data2 = 200; 13 mySerial1.write(255); 14 mySerial1.write(data); 15 mySerial1.write(data2); 16} 17 18(ArduinoUNO:受信側) 19 20#include <SoftwareSerial.h> 21#define RX_PIN 3 22#define TX_PIN 4 23 24SoftwareSerial mySerial(RX_PIN,TX_PIN); 25 26void setup() { 27 Serial.begin(115200); 28 mySerial.begin(9600); 29} 30 31void loop() { 32 int lat_dis_c; 33 int lon_dis_c; 34 35 if (mySerial.available()>0){ 36 uint8_t header = (uint8_t)mySerial.read(); 37 if (header == 0xFF) // check if incoming byte is header 38 { 39 uint8_t lat_dis_c = mySerial.read(); 40 uint8_t lon_dis_c = mySerial.read(); 41 } 42 43// Serial.println(header);  44 //ここだけをコメント復帰させるとシリアルモニタは 45 // 255 46 // 100 47 // 200 で出力 48 49// Serial.println(lat_dis_c); 50 //ここだけをコメント復帰させるとシリアルモニタは 51 // 0 で出力 52 53// Serial.println(lon_dis_c); 54 //ここだけをコメント復帰させるとシリアルモニタは 55 // 0 で出力 56 } 57} 58 59 60

試したこと

header が配列のようになっているので、要素(header[1]のような記述)を取り出そうと試みたりしたが、
文法エラーと怒られうまくいかない。

補足情報(FW/ツールのバージョンなど)

ArduinoUNO
ESP32-DevModule

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

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

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

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

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

guest

回答3

0

バイナリで送ってるようですが、慣れないうちは文字列に変換し、改行を区切りにして送るようにしましょう
そうすればパソコンで受信確認ができ、デバッグもやりやすいです

んで、available()ってのは受信文字があるかどうかのチェックなので、一文字読み出しごとにこれをチェックしないと意味がないです

投稿2020/09/04 22:33

y_waiwai

総合スコア88042

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

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

ISO130

2020/09/05 21:36

ありがとうございます。 なんとかバイナリで送れるようになり解決できました。
guest

0

ベストアンサー

思い出して下さい。
・9600bpsで1byteのデータ転送にはおおよそ1ms掛かること。
・Serial::read()/SoftSeria::read()はデータを受信していないときは0 -1を返すこと。

いま、シリアルの1バイト、255が受信できたところだとします。
if (mySerial.available()>0){
Serial::available()は受信している文字数を返しますから、1を返してif文の実行に入ります
uint8_t header = (uint8_t)mySerial.read();
で255すなわち0xFFを取り込みました。ここまで何μ秒でしょうか。少なくともmsの時間はかかっていません。そうすると、
uint8_t lat_dis_c = mySerial.read();
uint8_t lon_dis_c = mySerial.read();
は、受信データがないのでそれぞれ0 -1を返します。が、mkgt00さんが他の回答で指摘されているように、ここで宣言された変数は{ }のなかでしか寿命を持たず、関数冒頭で宣言されてSerial.printlnに渡っている変数とは別物。こちらは「たまたま0」だったため、0が表示されている、ということのようです。

続いて100を受信しました。
if (mySerial.available()>0){
uint8_t header = (uint8_t)mySerial.read();
100を受信します。0xffとは異なります。if文の中には入りません。100のデータは捨てられます。

続いて200を受信しました。
if (mySerial.available()>0){
uint8_t header = (uint8_t)mySerial.read();
200を受信します。0xffとは異なります。if文の中には入りません。200のデータは捨てられます。

最初に戻る。

以上の流れで、headerだけに255,100,200が受信されます。

やり方はいろいろあるでしょうが、Serail.read()が確実にデータを受信できるようにしてやって下さい。

投稿2020/09/04 22:31

編集2020/09/05 22:28
thkana

総合スコア7703

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

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

ISO130

2020/09/05 21:34 編集

大変ありがとうございます! 通信時間のタイミングが重要ということ、大変勉強になりました。 ということで送信側にdelayを与え動きを制御し、受信側でも if (mySerial.available()>2) として、 3バイト分の情報が来たら処理をするというようにしました。 また、スコープ範囲外にlat_dis_c とlon_dis_c シリアルモニタ表示があったのが原因で0になっていたのもわかりましたので、範囲内に表示コードをおいたところ出力されました。 ありがとうございました!
thkana

2020/09/05 22:31

mkgt00さん 指摘ありがとうございます。修正しました(0の消し線ってなんだかわかりにくいなぁ)。ちなみにSerial.read()も同様ですね。SoftwareSerialはSerialに仕様は合わせているでしょうから当然といえば当然ですが。
guest

0

変数の有効範囲の問題でしょうか。以下のプログラムを動かしてみました。

Arduino

1void setup() { 2 // put your setup code here, to run once: 3 int lat_dis_c = 1000; 4 int lon_dis_c = 2000; 5 6 Serial.begin(115200); 7 8 { 9 uint8_t lat_dis_c = 128; 10 uint8_t lon_dis_c = 255; 11 12 Serial.println(lat_dis_c); 13 Serial.println(lon_dis_c); 14 } 15 16 Serial.println(lat_dis_c); 17 Serial.println(lon_dis_c); 18} 19 20void loop() { 21 // put your main code here, to run repeatedly: 22 23}

シリアルモニタの出力は、以下の通りです。

128
255
1000
2000

Uno側のloop()の開始直後の変数定義を、int lat_dis_c = 1000; とかにしてみたら、どうなりますか?

あと、以下では、1バイト以上のデータがバッファにあることはわかりますが、3バイトあるかはわからないと思います。とはいえ、> 2にしていいかは考えないといけないですが。

Arduino

1if (mySerial.available()>0)

また、SoftwareSerial.read()の戻り値は、int です。送られてくるデータは uint8_t ですが、データがない場合は、-1 が返ります。

投稿2020/09/04 20:34

編集2020/09/05 00:02
mkgt00

総合スコア165

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

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

ISO130

2020/09/05 21:27 編集

ありがとうございます! ご指摘の通り、変数の有効範囲が重要でした。if文の外では入ったいた値が捨てられて0になっていたようです。 スコープ範囲内で処理するようにしてみます! ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問