mfstuy
@mfstuy

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

無線ラジコンの動作改善

解決したいこと

IM920sLとarduinoを使って無線のラジコン(オムニホイール3駆)を作ったのですが、動きが不安定で困っています。
やっていることとしては、
送信側では4つのボタンを使い、それぞれ文字列を送信しています。
受信側は文字列を受信するとそれを符号ありの10進数に直し、分岐でモーターを制御しています。
ですがボタンを押し続けても、ほんの少し進んでは止まる、という動作を繰り返しています。

何かを受信したら100、そうでなかったら0としてシリアルプロッタに表示してみたところ下の画像のようになり、送信側で長押ししていても受信側では一定間隔で何も受信していない状態になっているようでした。↓
スクリーンショット 2024-01-05 180724.png

どうすれば改善できるか、教えてください。
(モーター制御はL293Dモータードライバシールドを使用しています)

該当するソースコード

送信

#include <SoftwareSerial.h>
SoftwareSerial IM920Serial(8, 9);  // RX, TX
int busy;

void setup() {
  IM920Serial.begin(19200);
  Serial.begin(19200);

  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  pinMode(6, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);

  pinMode(10, INPUT);
}

void loop() {
  do {
    busy = digitalRead(10);
  } while (busy != 0);

  if (digitalRead(4) == LOW) {
    IM920Serial.print("TXDU 0002,AA\r\n");
    Serial.println("AA send");
  }
  if (digitalRead(5) == LOW) {
    IM920Serial.print("TXDU 0002,BB\r\n");
    Serial.println("BB send");
  }
  if (digitalRead(6) == LOW) {
    IM920Serial.print("TXDU 0002,CC\r\n");
    Serial.println("CC send");
  }
  if (digitalRead(7) == LOW) {
    IM920Serial.print("TXDU 0002,DD\r\n");
    Serial.println("DD send");
  }
  delay(50);
}

受信

#include <SoftwareSerial.h>
#include <AFMotor.h>
#define m1SPEED 128
#define m2SPEED 128
#define m3SPEED 140

AF_DCMotor motor1(1);
AF_DCMotor motor2(2);
AF_DCMotor motor3(3);
SoftwareSerial IM920Serial(A4, A5);  // RX, TX
signed char num2;
void setup() {
  Serial.begin(19200);
  IM920Serial.begin(19200);

  motor1.setSpeed(m1SPEED);
  motor2.setSpeed(m2SPEED);
  motor3.setSpeed(m3SPEED);

  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);

  pinMode(10, INPUT);
}

void loop() {
  int busy;
  do {
    busy = digitalRead(10);
  } while (busy != 0);

  if (IM920Serial.available()) {                       //データが送られてきたら
    String input = IM920Serial.readStringUntil('\n');  //シリアル値をString型で読み取る
    Serial.println(input);                             //読み取った文字列を出力

    String rs = input.substring(11, 13);  //読み取った文字列の一部を文字列として切り出し
    char Buf[50];
    rs.toCharArray(Buf, 50);
    int num = strtol(Buf, NULL, 16);  //16進数→10進数に変換
    num2 = num;
    switch (num2) {
      case -86:  //前進
        motor1.run(RELEASE);
        motor2.run(FORWARD);
        motor3.run(BACKWARD);
        break;

      case -69:  //左旋回
        motor1.run(BACKWARD);
        motor2.run(BACKWARD);
        motor3.run(BACKWARD);
        break;

      case -52:  //右旋回
        motor1.run(FORWARD);
        motor2.run(FORWARD);
        motor3.run(FORWARD);
        break;

      case -35:  //後退
        motor1.run(RELEASE);
        motor2.run(BACKWARD);
        motor3.run(FORWARD);
        break;

      default:
        motor1.run(RELEASE);
        motor2.run(RELEASE);
        motor3.run(RELEASE);
        break;
    }
  } else {
    motor1.run(RELEASE);
    motor2.run(RELEASE);
    motor3.run(RELEASE);
  }

  delay(50);
}
0

2Answer

  • 受信側のsubstringの位置は正しいでしょうか?
-   String rs = input.substring(11, 13);  //読み取った文字列の一部を文字列として切り出し
+   String rs = input.substring(10, 12);  //では?
  • 送信側、受信側ともbusy = digitalRead(10);していますが、これは何をチェックされているのでしょうか?

↓下記Adafruit Motor ShieldのFAQの情報によると、このライブラリが10番ピンを使用しているようです。

What pins are not used on the motor shield?


前回のQ&Aはクローズされていますが、何をすることで解決できたのでしょうか?
後学のために、以前のQ&Aにフィードバックをお願いします。

0Like

Comments

  1. @mfstuy

    Questioner

    ・受信側のsubstringの位置は正しいでしょうか?
    送られて来るのは、例えば"BB"が送信された場合、00,0001,CA:BBとなるので(11, 13)で問題ないです。(シリアルモニタで確認済み)

    ・送信側、受信側ともbusy = digitalRead(10);していますが、これは何をチェックされているのでしょうか?
    IM920sLから出力されるbusy信号です。IM920sLをarduinoに接続するために、Arduino 用無線モジュールシールドを使用しています。IM920sLから出力されたbusy信号はArduino 用無線モジュールシールドを通して10ピンから出力されるため、その信号を読み取っています。

    ・下記Adafruit Motor ShieldのFAQの情報によると、このライブラリが10番ピンを使用しているようです。
    変え忘れてました...
    受信側のArduino 用無線モジュールシールドのはんだブリッジの位置を変えてソフトウェアシリアルの干渉しないるようにしていたので、busy信号に対応しているのは10ではなくA3でした。
    do{}while()の部分を消しても、A3にしても変化はありませんでした。

  2. 送られて来るのは、例えば"BB"が送信された場合、00,0001,CA:BBとなるので(11, 13)で問題ないです。(シリアルモニタで確認済み)

    そうであれば、num2をswitch文で振り分けて各caseに正しく分岐していることも確認されているのでしょうか?
    モーターが止まるということは、defaultに分岐する場合があるということですよね。

  3. @mfstuy

    Questioner

    確認しました。
    モーターが止まるのはswitch文のdefaultの中にある停止コマンドではなくelseの中にある停止コマンドによって止まっていました。

  4. elseの中にある停止コマンドによって止まっていました。

    elseは、受信データが来ていないという状態のため、モーターを停止させてしまうと、そうなるでしょうね。

    リモコンの操作仕様ですが、送信側でボタンを押している間だけ、その方向にモーターを回転させて、ボタンを離すと止まる仕様でしょうか?

    もし、そうであるなら、ボタンが押されたら、その方向のデータを一度だけ送信して、ボタンが押されている間は、ボタンが離れるのを待って、ボタンが離れたら、停止データを送信するのが良いと思います。
    データの送受信の頻度が減ります。その場合、受信側はnot availableの時にモータを止めてはいけません。停止データを受信したら停止させます。

純粋にデータの送信が間に合ってないだけな気がします。
データの受信ができなければすぐに受信失敗にするのではなく、
3回受信できなかったらとかにしたら解決するのではないのでしょうか

0Like

Comments

  1. @mfstuy

    Questioner

    動作が大幅に改善しました。
    しかしやはり一定間隔で受信出来なくなるので、動き的には元の小刻みな停止の間隔が長くなったといった感覚でした。

  2. それで改善するなら、やはり送信と受信の間隔がずれているということなので、
    受信側のdelayを削除するか、受信側でifで受信データをチェックするのではなく,受信するまでwhileで待つのがいいと思います。
    今は,送受信どちらも同じ時間のdelayで待っているので送信動作のある送信側のほうが処理に時間がかかり、結果として少しループの間隔がずれているのではないかと思います。

  3. @mfstuy

    Questioner

    受信するまでwhileで待機したら理想の動きをするようになりました!
    ありがとうございました。
    nak435さんもありがとうございました。

Your answer might help someone💌