4

私はロボットに取り組んでいます。これは私たちの大学の夏のロボット工学ワークショップの一部です。A-WITのC-STAMPマイクロコントローラーを使用しています。動かす、左に曲がる、右に曲がる、後退することができました。コントラスト センサーを使用して、黒いテープに沿って移動することさえできました。

テーブルの黒いテープに向かって 30 ~ 45 度の角度でロボットを送ると、ロボットは自動的に整列し、黒いテープに沿って動き始めます。おそらく以下の私のプログラミング ロジックが原因で、少しぎくしゃくします。while ループを実行し、常に if ステートメントをチェックしているため、数ミリ秒ごとに左右に回転しようとします。しかし、大丈夫です。動作します。動作するほどスムーズではありませんが、動作します! 問題は、ロボットを黒いテープの長方形の経路に入れないことです。黒いテープの角に達するとすぐに、左または右に曲がるのではなく、まっすぐ進みます。

私の 2 つのセンサーは、ロボットの真下、前輪の隣、ほぼ床レベルにあります。0 から 8 までの「インデックス」値があります。8 が最も明るいコントラストで、0 が最も暗いコントラストです。したがって、ロボットが黒いテープ ゾーンに移動すると、インデックス値が低下し、それに基づいて、ロボットに左または右に曲がるように指示する if ステートメントがあります。

これが私の試みです。混乱を避けるために、ソース コード全体は投稿しませんでしたが、黒いテープに沿ったロボットの動きに関与する論理部分のみを投稿しました。

while(1) {

    // don't worry about these.
    // 10 and 9 represent Sensor's PIN location on the motherboard
    V = ANALOGIN(10, 1, 0, 0, 0);
    V2 = ANALOGIN(9, 1, 0, 0, 0);

    // i got this "formula" from the example in my Manual. 
    // V stands for voltage of the sensor.
    // it gives me the index value of the sensor. 0 = darkest, 8 = lightest.
    index = ((-(V - 5) / 5) * 8 + 0.5);
    index2 = ((-(V2 - 5) / 5) * 8 + 0.5);

    // i've tweaked the position of the sensors so index > 7 is just right number.
    // the robot will move anywhere on the table just fine with index > 7. 
    // as soon as it drops to or below 7 (i.e. finds black tape), the robot will 
    // either turn left or right and then go forward.

    // lp & rp represent left-wheel pin and right-wheel pin, 1 means run forever.
    // if i change it from 1 to 100, it will go forward for 100ms.
    if (index > 7 && index2 > 7)
        goForward(lp, rp, 1);

    if (index <= 7) {
        turnLeft(lp, rp, 1);
        goForward(lp, rp, 1);
        // this is the tricky part. i've added this code last minute
            // trying to make my robot turn, but i didn't work.
        if (index > 4) {
            turnLeft(lp, rp, 1);
            goForward(lp, rp, 1);
        }
    }

    else if (index2 <= 7) {
        turnRight(lp, rp, 1);
        goForward(lp, rp, 1);
            // this is also the last minute addition. it's same code as above
            // but it's for the 2nd sensor.
        if (index2 > 4) {
            turnRight(lp, rp, 1);
            goForward(lp, rp, 1);
        }
    }
}

私はそれを理解しようとして一日中過ごしました。私はほとんどすべての道を使い果たしました。スタックオーバーフローで解決策を求めることは、私の最後の選択肢です。

前もって感謝します!コードについて質問がある場合はお知らせください。ただし、コメントは一目瞭然です。

これは、誰かが疑問に思った場合に備えて、私の goForward 関数です。

void goForward(BYTE lp, BYTE rp, WORD t)
{
    WORD i;

    for(i = 0; i < t; i = i + 1){
        PULSOUT(lp, 400, 1, 1);
        PULSOUT(rp, 800, 1, 1);
        PAUSE(17);
    }
}

更新:これが私がこれまでに思いついたことです。以前に投稿したすべての if ステートメントを消去し、ロジックをゼロから作成することにしました。

// if there's enough bright light in both sensors at the same time
    // robot will move forward forever.
    if (index > 7 && index2 > 7)
        goForward(lp, rp, 1);

    // but if there's not enough bright light anymore (i.e. reached black tape)
    // proceed to the else-statement.
    else {
        // if left sensor detects the black tape then turn right
        // if doesn't detect the black tape then keep going forward
        if (index2 <= 7)
            turnRight(lp, rp, 1);
        else
            goForward(lp, rp, 1);

        // if right sensor detects the black tape then turn left
        // if it doesn't detect the black tape then keep going forward
        if (index <= 7) 
            turnLeft(lp, rp, 1);
        else 
            goForward(lp, rp, 1);
    }

    // The reason for turnLeft and turnRight is to keep robot re-alligning
    // to the black tape. It will happen so fast (every 1ms) that the jerking
    // shouldn't even be noticeable.
4

5 に答える 5

3

コーナーに遭遇したときに発生する[サイクルn]「テープが見える」→[サイクルn+1]「テープが見えない」という突然の発生をトラップする必要があります。

ステート マシンは、この種の問題を処理する優れた方法です。ステート マシンでは、特定の状態のコードが分離され、状態が true の場合にのみ実行されます。この分離により、「クロストーク」が防止され、状態ごとに 1 つの既知のコード ブロックが提供されます。

あなたの例を考えると、フローは次のようになります。

:Loop

State == Moving forward and on tape.
  read sensors
  delta = abs(valueLastCycle - valueThisCycle);
  if (delta >= bigChangeValue){
    // the tape was just gone. 
    // change state and handle this situation.
    CurrentState = suddenValueChange;
  }else
    if (index <= 7) {
        turnLeft(lp, rp, 1);
        goForward(lp, rp, 1);
    else if (index2 <= 7) {
        turnRight(lp, rp, 1);
        goForward(lp, rp, 1);
    }
   ...
State == suddenValueChange
 ...
 code that handles sudden value change event
 maybe:
 Stop Robot;
 Move backwards slowly until on tape or distance x
 etc...

Goto Loop

スキャン レートを上げると効果があるように見えるかもしれませんが、ロボットの動きが速ければ速いほど、スキャン レートも速くなります。つまり、テープ上からテープから離れてジャンプする可能性があり、その場合、現在のコードは失敗します。

于 2010-06-11T02:03:54.750 に答える
2

私の推測では、turnLeft/TurnRight の直後に goForward が回転を「キャンセル」するのでしょうか? ターニングの実装方法にもよりますが、

于 2010-06-11T01:06:23.030 に答える
2

while ループは、コーナーをキャッチするのに十分な速さで実行されますか? 両方のセンサーがテープ上にあると報告し、次のサイクルで両方のセンサーがテープから離れている場合、それを検出することはできませんよね? センサーは、テープ上とテープ外で同じ値 (8) を報告しますか?

コードを高速化してみてください。コード全体を見ないで推奨するのは難しいですが、必要のない if ステートメントを評価している可能性があるようです。最初の IF の後に ELSE を追加してください。

goforward の実装がループを長時間ブロックしているようです。1 は永久に実行するという意味ではありません。for ループを 1 回実行してから、17 (ミリ秒?) PAUSE します。一時停止は何のためですか? それを除く。これはおそらくジャークを引き起こし、次のセンサー値のセットが入ってくるのを防ぎます。

于 2010-06-11T01:17:27.667 に答える
2

コードについて心配する前に、「計画」が理にかなっていることを確認してください。

ロボットを手で動かし、センサーが白黒の領域をいつ通過するかを観察することから始めます。動作を考え出し、それを手でシミュレートしてみてください。これが期待どおりに機能しない場合は、動作を修正する必要があります。

提案: ループを追加して、何かがおかしいと思われる場合に、ロボットが通常の動作を再開する前にそれを修正するようにすることをお勧めします。(たとえば、100 ミリ秒間右/左に回転するのではなく、センサーが正しいものを認識するのにかかる限り、その動作を行います。)

于 2010-06-11T01:17:47.217 に答える
1

現在、あなたのコードを見ると、ロボットが黒を見るたびに永遠に前進します。今後どのように実装されるかはよくわかりません。

疑似コードでは、コードは次のように述べています。

if you see black
 go forward forever
if you don't see black
 turn left or right

あなたのロボットがそのようなロジックでどのように永遠に前進するか分かりますか? 繰り返しますが、今後がどのように実装されるかはわかりませんので、間違っている可能性があります。

于 2010-06-11T01:09:01.080 に答える