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

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

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

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

Arduino

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

Q&A

解決済

2回答

8409閲覧

ArduinoMegaにて複数のハードウェアシリアル通信をすると通信データが取れない

ISO130

総合スコア8

シリアルポート

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

Arduino

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

0グッド

0クリップ

投稿2020/08/20 14:15

前提・実現したいこと

ArduinoMega2560にて2つのGPSセンサを用いてハードウェアシリアル通信をしようと試みています。

GPSセンサはNeo6Mで、それぞれTX3-RX3(14,15ピン)とTX2-RX2(16,17ピン)に接続しています。

これにて2つのGPSセンサの各緯度経度情報を取り込もうとしています。

しかし、コンパイル後のシリアルモニタにて出力される各GPSセンサ値は両方とも0であり、値が入ってきません。

センサエラーを疑い、片方のGPSセンサを外し、コードからも片方の処理を無効化したところGPSセンサの値が取れるようになりました。(もう片方も同様の処理で値が取れることは確認しました。)

ということで、複数のシリアル通信のコード的な問題があり、現コードが間違っている、もしくは何か別の特有のコードがあるのではないかと思っています。

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

シリアルモニタの表示:

Start
No2Lati= 0.000000 No2Long= 0.000000
No3Lati= 0.000000 No3Long= 0.000000
No2Lati= 0.000000 No2Long= 0.000000
No3Lati= 0.000000 No3Long= 0.000000

と続く

該当のソースコード

skecth

1#include <TinyGPS++.h> 2#include <SoftwareSerial.h> 3static const uint32_t GPSBaud = 9600; 4 5// The TinyGPS++ object 6TinyGPSPlus gps1; 7TinyGPSPlus gps2; 8 9// The serial connection to the GPS device 10 11void setup(){ 12 Serial.begin(9600); 13 Serial2.begin(GPSBaud); 14 Serial3.begin(GPSBaud); 15 Serial.println("Start"); 16} 17 18void loop(){ 19 // This sketch displays information every time a new sentence is correctly encoded. 20// while (Serial2.available() > 0){ 21 delay(5000); 22 gps1.encode(Serial2.read()); 23 delay(5000); 24// if (gps1.location.isUpdated()){ 25 Serial.print("No2Lati= "); 26 Serial.print(gps1.location.lat(), 6); 27 Serial.print("\t"); 28 Serial.print("No2Long= "); 29 Serial.println(gps1.location.lng(), 6); 30// } 31// } 32// while (Serial3.available() > 0){ 33 delay(5000); 34 gps2.encode(Serial3.read()); 35 delay(5000); 36// if (gps2.location.isUpdated()){ 37 Serial.print("No3Lati= "); 38 Serial.print(gps2.location.lat(), 6); 39 Serial.print("\t"); 40 Serial.print("No3Long= "); 41 Serial.println(gps2.location.lng(), 6); 42// } 43// } 44}

試したこと

・GPSのコード部を単独のシリアル通信に変更すると1つのGPS値は取り込める
・2つのGPSセンサを使おうとするとGPS値が両方とも0になる
・delayを入れてみたが、効果なし

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

ArduinoIDE:1.8.13
Arduinoボード:osoyoo製のMEGA2560
GPSセンサ:neo-6M
TX3-RX3(14,15ピン)とTX2-RX2(16,17ピン)をそれぞれ使用

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

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

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

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

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

ozwk

2020/08/20 14:34

コメントアウトされているwhileやifはなんですか?
1T2R3M4

2020/08/20 15:34

Serial2,Serial3は標準でピンアサインされているのですか。
guest

回答2

0

GPS データ読み取り部分が不適切です

gps1.encode(Serial2.read());

では1バイトしか受信されず エンコードも完了しません

TinyGPSPlus-1.0.2\examples\DeviceExample
DeviceExample.ino より抜粋↓

while (ss.available() > 0) // シリアル受信データがあれば、 if (gps.encode(ss.read())) // gps.encode にデータを1バイト読み込み displayInfo(); // GPSデータを全て受信したらエンコードし表示する

まずは、DeviceExample.ino を Serial2 で動作するように変更し、同じ処理の Serial3 を追加することを勧めます

投稿2020/08/20 15:39

koujikuu

総合スコア401

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

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

ISO130

2020/08/21 00:58

ありがとうございます! ご指摘の通り、コメントアウト部を復帰させて、whileをifにしたら2機ともGPS値が取れるようになりました。 (whileだと片方のGPS値しか取れないようです) 大変助かりました。 ありがとうございます。
guest

0

ベストアンサー

コードからも片方の処理を無効化

というのは、

C++

1void loop(){ 2 delay(5000); 3 gps1.encode(Serial2.read()); 4 delay(5000); 5 Serial.print("No2Lati= "); 6 Serial.print(gps1.location.lat(), 6); 7 Serial.print("\t"); 8 Serial.print("No2Long= "); 9 Serial.println(gps1.location.lng(), 6); 10}

とした、という理解でいいですか? それで本当に動いたのかなぁ...?
ソフトシリアルをあまり信用していないので調べていないのですが、ソフトシリアルの受信バッファはGPSモジュールが10秒間送ってくるデータ量を保持できるだけの大きさがありましたっけ? ハードシリアルは64byteなので、それより大きいことはあまりないと思うのですが、そうだとするとNMEAセンテンス一つ分ぐらいしか取れないんじゃないか...
少なくとも5秒のdelayなんて冗談じゃない、と思います。何の意味があるのでしょう?

環境がないので自分では試せませんが

C++

1void loop(){ 2 if (Serial2.available() > 0){ 3 gps1.encode(Serial2.read()); 4 if (gps1.location.isUpdated()){ 5 Serial.print("No2Lati= "); 6 Serial.print(gps1.location.lat(), 6); 7 Serial.print("\t"); 8 Serial.print("No2Long= "); 9 Serial.println(gps1.location.lng(), 6); 10 } 11 if (Serial3.available() > 0){ 12 gps2.encode(Serial3.read()); 13 if (gps2.location.isUpdated()){ 14 Serial.print("No3Lati= "); 15 Serial.print(gps2.location.lat(), 6); 16 Serial.print("\t"); 17 Serial.print("No3Long= "); 18 Serial.println(gps2.location.lng(), 6); 19 } 20}

とかやってみるとどうなるでしょう。出来ればハードシリアル(PC側?)はボーレートを115200bpsにしてできるだけソフトシリアルの動作を阻害しないようにしたほうがいいと思います。

投稿2020/08/20 23:32

thkana

総合スコア7629

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

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

thkana

2020/08/20 23:59

あ、#include <SoftwareSerial.h> に騙されたか。 ソース上は確かに Serial2.begin(GPSBaud); Serial3.begin(GPSBaud); となってますね。 ソフトウェアシリアルの件は無しとしても、受信パッファ容量に限りがあるわけで、NMEAがどれくらいの頻度で湧いてくるモジュールか知りませんが、10秒間放置して1byteだけ処理するという方法で、例えGPS1台でもまともに処理が出来るとは思えません。
ISO130

2020/08/21 00:52

神様!ありがとうございます! if (Serial2.available() > 0){ ... if (gps1.location.isUpdated()){ の部分をコメント復帰したら確かに動作しました。 GPSの受信状態が悪いときにシリアルモニタが更新されない(0値でも出てほしかった)のがあり、該当部分を勝手にコメントアウトしていました。 そういうことはしてはだめですね。 なおご指摘のご懸念の通り、単品GPS動作時は上記のコードを生かしたままでした。なので値が取れたようです。 delayの件もありがとうございます。 ArduinoUNOでSoftwareSerialをさせていたときにdelayを入れると値が取れるときがあったと記憶しており、今回も極端に大きい値を入れていた次第です。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問