前の手順は、ソフトウェアと物理の2つの部分に分かれていました。 双方向の変更はそれほど多くなかったため、今回はすべてが1つのコピーになります。 説明した部分が必要な理由を簡単に思い出しますが、完全に理解するには、最初の2つの部分を確認することをお勧めします。
物理的な部分
最初の記事で説明したすべての同じ原則に基づいて:
- Arduino UnoとMotor Shieldのサンドイッチ。
- モーターシールドに接続された2つのモーター。
変更点は次のとおりです。
- 奇妙なことに、ボールを打つ原因となるショック部分が現れました。
- 現在、ケースは完全に私のものであり、3Dプリンターで印刷されています。
本体
フォームは、ボードと2つのホイールの両方が収まる円です。 衝撃力がかかる部分の延長。

これを設計するときは、次のことに注意してください。
- ハイサイド。 ロボットはゲーム中に衝突し、側面はワイヤーだけでなくライバルもワイヤーから保護します。
- 重心と安定性。 もちろん、重心はボードのある場所です。 ホイールは近くにあるため、滑ることはありません。 さらに、バッテリーはボードの上部に配置されます。
- ロボットが鼻や背中を突くのを防ぐため、キット内のあちこちにボールを入れます(ボールがない場合は、他のスライドデザインに交換できます)。
- デザインの剛性。 プラットフォームは、回路基板とモーターの重量で垂れ下がってはなりません。 固くしないでください、硬い材料(合板)を使用するか、ラックでプラスチック構造を強化しないでください

そして今、主なナンセンス
「ペッキング」がないために追加されたボールは、車輪が床に届かないようにプラットフォームを上げました。 これを回避するには、より大きな直径のホイールを使用するか、支持構造を短くします。 通常、これは事前に計算されます!
ショック部分。 彼女はヒットしません。 ビートですが、十分にクールではありません。 最初のモデルには、除雪機のバケットに似た部品が接続されたサーボマシンがありました。 サーボの位置(0度から30度)を変更することで、打撃をシミュレートできます。 しかし、サーボが遅いことが判明したため、打撃はデュースに行きます。
解決方法は2つあります:衝撃にジャークを追加するか、サーボをソレノイドに置き換えます。 最初のオプション-ストローク中にホイールに速度を適用することにより、運動量を増やすことができます。 実際には、これは次のとおりです。ユーザーがヒットボタンを押すと、ロボットはスポットから(わずかに)起動し、同時にストライクを行います。
2番目のオプション-ソレノイドはショック部分を押します。ここでは、すべてがショックの力(速度)に依存し、ショックの力(速度)はソレノイドの特性に依存します。

ソフトウェア部
すでに1つの記事である良い伝統により、このセクションを2つの部分に分けます。 最初にAndroidアプリ、次にArduinoスケッチ。
Android
思い出させてください、このアプリケーションは私がゼロから作成したものです。 過去6か月間、この問題についてもう少し理解したので、
まず、単純化に進みましょう。 現在、通信プロトコルは次のとおりです。「開始文字」+「値」+「終了文字」(これらの値の取得方法とその内容を理解するには、アプリケーションの完全な分析を参照してください )。 これは、速度と角度の両方で機能します。 ストライクは1種類しかないため、彼はそのような知恵を必要としません。したがって、チームは1つの「/」文字で構成されます(段落を通してヒットしたチームについて)。
private void sendCommand(String speed, String angle) { String speedCommand = "#" + speed + "#"; // String angleCommand = "@" + angle + "@"; try { outputStream.write(speedCommand.getBytes()); // outputStream.write(angleCommand.getBytes()); } catch(Exception e) { e.printStackTrace(); } }
典型的なコマンドは次のようになります:#125#@ 180 @、125は速度、180は角度です。 もちろん、これはまだ単純化できますが、タスクの1つは、明度と読みやすさを維持することでした。そのため、後で子供にも含めて簡単に説明できます。
「ヒット」ボタンをクリックするとトリガーされる新しいsendHit()コマンドが表示されます。 彼女は1つの「/」記号を送信します。 通常のbluetooth 2.0+は同時に受信したデータの影響を受けない、つまり、キューに入れる方法を知っており、失わないため、これを制御する必要はありません。 Bluetooth Low Energy 4.0+を使用する場合(突然)、すでにキューを手動で整理する必要があります。そうしないと、データが失われます。
... bHit = findViewById(R.id.b_high_hit); // bHit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { threadCommand.sendHit(); // "" } }); ... private void sendHit() { try { outputStream.write("/".getBytes()); // }catch (Exception e) { e.printStackTrace(); } } }
Arduino
コマンドを送信するためのプロトコルが変更され、受信アルゴリズムも変更されました。 彼は単純化した。 トラッキングキックも追加された場合は1つ。 スケッチの完全な分析はこちらです。
bt.read()は1文字を読み取ります。 「#」に等しい場合、速度記号が始まります。 終了文字「#」が表示されるまで読みます。 ここでforループを使用することはできません。これは、速度の長さが事前にわからないためです(1桁、2桁、または3桁の数値を使用できます)。 結果の値は変数に書き込まれます。
ターンでも同じことが起こります。 速度と角度の両方を読み取った後、すべてを関数turn(int speed、int angle)に渡します。
void loop() { if(BTSerial.available() > 0) {// char a = BTSerial.read(); // if(a == '#') { // sp=""; char b = BTSerial.read(); while( b != '#') { // , sp+=b; b = BTSerial.read(); } } else if (a == '@') {// val = ""; char b = BTSerial.read(); while(b != '@') { // val+=b; // b = BTSerial.read(); } turn(val.toInt(), sp.toInt()); // , } else if (a == '/') { //, Serial.println(a); servo.write(30); // delay(150); servo.write(0); // } lastTakeInformation = millis(); } else { if(millis() - lastTakeInformation > 150) { // 150 // lastTakeInformation = 0; analogWrite(speedRight, 0); analogWrite(speedLeft, 0); } } delay(5); }
方向転換()関数は、移動する方向(前方、後方)および方向転換する方向(右、左、まっすぐ)を決定します。 バイトが失われた場合にロボットの速度が低下しないように、(speed> 0 && speed <70)の制限が必要です。 送信速度を上げたときにこれに直面しました(チーム間で100-300msの遅延で再生しました)-時には、速度の値が0、40に達せずに変化しました(たとえば、実際には240が送信されました)。 松葉杖ですが、動作します。
これは、「制御されない要因に対する保護」と呼ばれます。
void turn(int angle, int speed) { if(speed >= 0 && speed < 70) return; if(speed > 0) { digitalWrite(dirLeft, HIGH); digitalWrite(dirRight, HIGH); } else if (sp < 0) { digitalWrite(dirLeft, LOW); digitalWrite(dirRight, LOW); } if(angle > 149) { analogWrite(speedLeft, speed); analogWrite(speedRight, speed - 65); // } else if (angle < 31) { analogWrite(speedLeft, speed - 65); // analogWrite(speedRight, speed); } else { analogWrite(speedLeft, speed); analogWrite(speedRight, speed); } }
合計ではなくMIPTでの競争
私たちのロボットで、私たちはモスクワの物理工学研究所(ドルゴプルドニ、2019年4月14日)で開催されたロボットサッカー大会に参加しました。 私たちはなんとか1 \ 4の決勝に到達しましたが、それ以上は進みませんでした。

プロセス自体は私たちにとって興味深いものでしたが、ここでは、現場でロボットを見ることによってなされた結論を説明します。
- より強力な必要があります。 4輪以上の強力なエンジンと他の車輪が望ましい。 もちろん、より有利に見えたのは四輪モデルでしたが
- 管理は高くありません。 ロボットをタンクターンに移動する必要があります(車輪が反対方向に回転するため、ある地点で旋回します)。そうでない場合、旋回半径が大きすぎます。 そして一般的に、比例速度の円ではなく、4つの矢印のあるオプションがフットボールに適しています。 説明したオプションは、継続的に運転するレースに適しています。ここでは明確にする必要があります(軸を中心に10度回転し、ボールを狙い、ボタンを押しました。速度...あなたは何らかの形でこのことを組み合わせる必要があります)。
コメントと提案は非常に幸せです。 以前の記事では、記事自体よりもコメントが興味深い場合があります。 サーシャとダナに感謝します 。