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

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

新規登録して質問してみよう
ただいま回答率
85.49%
XBee

XBeeは、Digiインターナショナル社が提供するZigBee規格対応の通信モジュール。IoTプロトタイプの無線化などに用いられます。PCの専用ソフトウェアから全てのモジュールの設定ができるため、比較的簡単に使用することが可能です。

Arduino

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

Q&A

解決済

1回答

638閲覧

XBeeでのシリアル通信で予期せぬループをしてしまう。

kazumagic

総合スコア13

XBee

XBeeは、Digiインターナショナル社が提供するZigBee規格対応の通信モジュール。IoTプロトタイプの無線化などに用いられます。PCの専用ソフトウェアから全てのモジュールの設定ができるため、比較的簡単に使用することが可能です。

Arduino

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

0グッド

0クリップ

投稿2019/04/09 08:29

前提・実現したいこと

XBeeとArduino化したATMega328P-PUチップを二つ使用して、シリアル通信でセンサーから受け取った値に対して、12V電圧のオンオフを制御したい。(土が乾いていたらポンプで水やりができるプログラム)

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

土壌センサが読み取った値によって、乾燥していれば'T'をもう一方のXBeeに送信する。'T'を受け取れば電圧がかかるようになっている。初めに湿っている状態では電圧がかからなく、そこから乾燥状態にすれば電圧がかかったが、その後に湿っている状態に戻しても電圧がかかったままになってしまう。('T'がずっと送信された場合のループが繰り返される)

該当のソースコード

Arduino スケッチ

センサー側

const int SensorIn = A5;//土壌湿度センサー値取得ピン番号

//初期設定
void setup(){
Serial.begin(9600);
pinMode(SensorIn, INPUT);}

//機能:土壌湿度センサーの値を読み込む関数
int SensorRead(){
int SensorValue = 0;
for(byte i=0;i<=10;i++){ //A3ポートの電圧を10回読み平均値を出す
delay(10); //一定時間電流を流して測定値を安定させる
SensorValue = SensorValue + analogRead(SensorIn);
}           //センサー電圧を10回読み合計する
return SensorValue / 10;} //センサー電圧平均値を返す

//メインループ
void loop(){
if(SensorRead()<350) { //土が乾燥していた場合以下実行
Serial.print('T'); // 文字'T'を送信
delay(10); // シリアル通信があふれないよう
}
}

受信側

const int Power = 8;//12V制御ピン番号

//初期設定
void setup(){
Serial.begin(9600);
pinMode(Power, OUTPUT);
}

//メインループ
void loop(){
if(Serial.available() > 0){ //土が乾燥していた場合以下実行
if (Serial.read() == 'T') {
digitalWrite(Power, HIGH);//水を出す
delay(5000);//5秒待つ
}
else{
digitalWrite(Power, LOW);
}
}//水を止める
digitalWrite(Power, LOW);
delay(1000);
}//1秒待つ

試したこと

センサー側で一度乾いた状態を作って、受信側が電圧を出力する状態にした後に、センサー側の電源を切っても受信側は’T’を受信した場合のループを繰り返した。

受信側の電源を切って、再度電源を入れると'T'を受信して起こるループは止まった。
ただもう一度乾いた状態を作って、湿った状態にしても電圧がかかる状態がループした。

よろしくお願いいたします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

if(SensorRead()<350) {

これが成立している間、送信しっぱなしになるので、この関数の戻り値が各状態のときにどうなってるか、どっかに出してみてみることですな。


if (Serial.read() == 'T') {

digitalWrite(Power, HIGH);//水を出す
delay(5000);//5秒待つ
}

シリアル入力のバッファが16バイトあるとどっかで読んだ覚えがあるので、
Tの送信が終わっても、16回水が出ることになるけど、それは想定した動作なのかな?

投稿2019/04/09 08:44

編集2019/04/09 08:51
y_waiwai

総合スコア87747

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

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

y_waiwai

2019/04/09 08:58

送信しっぱなしになるなら、そのときのSensorRead()の戻り値はどうなってるの?
kazumagic

2019/04/09 09:13

確かに16回出てました! どのように変更すれば1回の動作で収まるでしょうか? よろしくお願いします。
y_waiwai

2019/04/09 09:27

送信しっぱなしってのが問題じゃないの?それをどうにかしないとどうしようもない気がしますが
kazumagic

2019/04/09 09:37

戻り値は湿っている状態で900近くあったので、送信しっぱなしにはなっていないみたいです。16回の繰り返しの後は動作が停止していました。
y_waiwai

2019/04/09 09:46

なら水を出したあと、受信データをなくなるまで読み捨てればいい。 んだけど、5秒なにもできずに待つだけ、ってのはちとどうにかしたほうがいい気がします
kazumagic

2019/04/09 12:23

はい。分かりました! 繰り返し動作がされることは思ってもみなく、終わりなくループしているものと勘違いしていました。 とても勉強になりました。 本当にありがとうございました。
thkana

2019/04/09 15:04

ちなみに、Arduino UNOの受信バッファは64byteだったかと。 https://www.arduino.cc/en/serial/available いずれにしろ、数秒をdelayで待つ、なんてのは基本的にやらないほうがいいことです。
kazumagic

2019/04/10 02:28

すみません。 数分で止まったので16回だと勝手に思ってました。 64byteで確認できました。 数秒をdelayで待つことのデメリットが分かりません。 よければ教えていただけないでしょうか。 実際は3分ほど水やりをして、再度センサーで判定を行うの繰り返しを考えています。 よろしくお願いします。
thkana

2019/04/10 14:36

> 数秒をdelayで待つことのデメリット 今回で言えば、送信側が100ms周期で動いていることに対するアンバランスですね。 一般論としては、待っている間なにも出来ない、というのが欠点となり得ます。例えば、「緊急停止スイッチ」を追加したとして、そのスイッチを操作しても最悪5秒システムが反応しない、などという事態になります。質問の件だけについて言えば5秒の無反応で支障はないのかも知れませんけれど。 反応の良いシステムはゆっくりでいいアプリケーションに使えますが、反応の悪いシステムでは不具合が出るので、だったらどちらで作っておいたほうが得か(大した手間でもないので)、というあたり。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問