工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

このチュートリアルでは、あらゆる方向に移動できるArduinoメカナムホイールロボットの作り方を学びます。このユニークな移動性は、メカナムホイールと呼ばれる特殊なホイールによって実現されます。

以下の動画を見るか、書面チュートリアルをお読みください。

概要

メカナムホイールは購入すると高価なので、自分で設計・3Dプリントしました。よく動作し、このロボット台車の操作は非常に楽しいです。NRF24L01無線トランシーバーモジュールで無線制御できます(私の場合、以前の動画で作ったDIY RC送信機を使用)。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

スマートフォン経由のBluetooth制御も可能です。カスタムAndroidアプリであらゆる方向への移動と、スライダーでの速度制御ができます。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

このロボット台車の頭脳はArduino Megaボードで、各ホイールを個別に制御します。各ホイールはNEMA 17ステッピングモーターに取り付けられ、ステッピングモーターは精密制御可能なため、アプリに自動動作プログラミング機能を追加しました。Saveボタンで各位置/ステップを保存し、自動でそれらを繰り返し実行できます。同じボタンで一時停止、リセット/全ステップ削除も可能です。

メカナムホイールロボットの3Dモデル

このメカナムホイールロボットを3Dモデリングソフトで設計しました。ベースプラットフォームはシンプルな箱型で、8mm厚MDFボードで作ります。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

4つのステッピングモーターをプラットフォームに取り付け、モーターシャフトにメカナムホイールを装着。

Thangsで3Dモデルを探索・ダウンロードできます。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

アセンブリ3Dモデルのダウンロード(Thangs)

STLファイル(3Dプリント用):

メカナムホイールの仕組み

メカナムホイールは、円周にローラーが取り付けられたホイールです。これらのローラーはホイールの回転軸に対して斜め(45度)に配置されています。このため、ホイールが前後進すると斜め方向に力を発生させます。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

ホイールを特定のパターンで回転させることで、これらの斜めの力を利用し、ロボットをあらゆる方向に動かせます。

左ねじれ(左手系)と右ねじれ(右手系)の2種類のメカナムホイールが必要です。違いはローラーの向きで、ロボット上の特定位置に正しく取り付ける必要があります。各ホイールのトップローラーの回転軸がロボットの中心を向くように配置します。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

ホイール回転方向によるロボットの動きを簡単にデモします。

4輪すべて前進 → ロボット前進。すべて後退 → 後退。右移動:右ホイールを内側(ロボット中心方向)、左ホイールを外側に回転。斜め配置ローラーの合力で右に移動。左移動はその逆。対角線移動は2輪のみ回転させることで実現。

メカナムホイールロボットの製作

では実際の製作過程を見ていきましょう。ベースプラットフォームには8mm厚MDFボードを使用。テーブルソーで3Dモデルの寸法通りにカット。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

3mmドリルと25mmフォルスタービットで側面パネルにステッピングモーター取り付け用の開口部を加工。木工用接着剤とネジで組み立て。最重要ポイントはモーター取り付け穴を精密に加工し、すべてのホイールが地面と均等に接触するようにすることです。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

ベースプラットフォームは3Dプリントでも作れます(Web記事に3Dファイルを掲載)。最後にベースとカバーを白でスプレー塗装。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

メカナムホイールの製作。購入すると高いため自作しました。ホイールは外側・内側の2パーツで、M4ボルト・ナットで固定。各10個のローラーと、NEMA 17ステッピングモーター専用のシャフトカプラーを備えます。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現
Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

Creality CR-10 3Dプリンターで全パーツをプリント。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

ローラー用シャフトを作ります。3mm径のスチールワイヤーを使用し、長さ約40mmにロータリーツールでカット。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

ホイールの組み立て:2つの側面パーツとシャフトカプラーをM4ボルト・ナット4本で固定(ボルト長45mm)。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

ローラー取り付け:内側パーツの円周上の穴にシャフトを少し通し、M3ワッシャー、ローラーを入れ、シャフトを外側パーツのスロットまで押し込みます。反対側にワッシャーを入れるスペースがなかったため1枚のみ使用。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現
Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

10個すべてのローラーで同じ作業を繰り返し。簡単で楽しい作業です。ローラーが自由に回ることが重要です。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

最後に内側の穴に瞬間接着剤を数滴垂らし、シャフトが緩まないようにします。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

ホイールが完成したらロボット全体を組み立てます。まずステッピングモーターをベースプラットフォームに取り付け(M3ボルト12mm)。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

ホイールをモーターシャフトに取り付け。シャフトカプラーにM3ナット用スロットがあり、M3ボルトでホイールをシャフトに固定できます。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

トップカバー固定用に、ベースの2隅にネジロッドを立て、カバーにも同じ位置に穴を開けてカバーを着脱可能にしました。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

ベース背面に電源スイッチ用20mm穴、LED用5mm穴を開けました。

回路図

電子部品の接続に移ります。完全な回路図はこちら。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

4つのNEMA 17ステッピングモーターを4つのDRV8825ステッピングドライバー(A4988も可)で制御。ステッピングモーターとロボット全体の電源は12V(3S Li-Poバッテリーで約12V)。無線通信用にNRF24L01モジュール、Bluetooth通信用にHC-05モジュール。バッテリー電圧監視用の簡易分圧回路と、電圧が11V未満になったら点灯するLEDも搭載。

将来的にArduinoロボットアームプロジェクトと統合する予定で、サーボ駆動用5V(約3A)を供給する専用電圧レギュレーターも搭載しています(オプション)。

必要なコンポーネント:

  • ステッピングモーター – NEMA 17
  • DRV8825ステッピングドライバー
  • NRF24L01トランシーバーモジュール
  • HC-05 Bluetoothモジュール
  • Li-Poバッテリー
  • Arduino Megaボード

PCB設計

電子部品を整理し配線をすっきりさせるため、EasyEDAでカスタムPCBを設計。このPCBはArduino MEGAシールドとして機能し、Arduino Megaボードの上に直接装着できます。表裏両層で配線。未使用のArduinoピンもピンヘッダーで引き出し、将来の拡張に対応。12V、5V、GND接続ピン、ドライバーのステップ分解能選択用ピンも搭載。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

PCBプロジェクトファイルへのリンク。設計完了後、製造用ガーバーファイルを生成。

ガーバーファイル:

スポンサーのJLCPCBに発注。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

ガーバーファイルをドラッグ&ドロップでアップロード、ガーバービューアーで確認。問題なければ仕様を選択。今回はArduinoボードの色に合わせてPCB色を青に指定。初回注文なら最大10枚まで2ドルで注文可能。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

数日後にPCB到着。品質は素晴らしく、設計通りの仕上がり。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

PCB組み立て

PCBを組み立てます。小さな部品から:抵抗とコンデンサーをはんだ付け。Arduino接続用オスピンヘッダーを挿入・はんだ付け。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

メスピンヘッダーを配置・はんだ付け。ステッピングモーター接続用とステップ分解能選択用にはオスピンヘッダーを使用(モーター直結、ジャンパーで分解能選択可能)。ターミナルブロック、トリマー、電圧レギュレーターをはんだ付け。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

PCB完成。ドライバーを装着し、モーターを接続。まずステップ分解能選択用ジャンパーを装着。MS3ピンを5Vに接続して16分割ステップを選択。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

その上にDRV8825ドライバーを装着、NRF24L01モジュールとHC-05 Bluetoothモジュールを接続。PCBをArduinoボードに装着。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

バッテリーを適切なターミナルブロックに接続し、ベースプラットフォーム内に収納。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

電源スイッチを取り付け、もう一方のターミナルブロックに接続。スイッチのすぐ上にバッテリー残量表示LEDも取り付け。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

モーターをPCBに接続。重要:対向するモーターを接続する際、コネクターも対向させて接続します。これはプログラミング時に、例えば「前進」コマンドで両モーターが同じ方向に回るようにするためです(物理的には反対向きに取り付けられているため、一方は時計回り、他方は反時計回りになります)。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

最後にカバーを被せて、メカナムホイールロボットプロジェクト完成です。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

メカナムホイールロボット Arduinoコード

Arduinoコードを見てみましょう。実は2つの別々のコードがあります。1つはNRF24L01モジュールで制御するコード、もう1つはスマートフォンで制御するコードです。

NRF24L01モジュールでロボットを制御するArduinoコード:

/* === Arduino Mecanum Wheels Robot === Radio control with NRF24L01 by Dejan, www.HowToMechatronics.com Libraries: RF24, https://github.com/tmrh20/RF24/ AccelStepper by Mike McCauley: https://www.airspayce.com/mikem/arduino/AccelStepper/index.html */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <AccelStepper.h>
RF24 radio(48, 49); // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;
// Define the stepper motors and the pins the will use
AccelStepper LeftBackWheel(1, 42, 43); // (Type:driver, STEP, DIR) - Stepper1
AccelStepper LeftFrontWheel(1, 40, 41); // Stepper2
AccelStepper RightBackWheel(1, 44, 45); // Stepper3
AccelStepper RightFrontWheel(1, 46, 47); // Stepper4
int wheelSpeed = 1500;
// Max size of this struct is 32 bytes - NRF24L01 buffer limit
struct Data_Package {
  byte j1PotX;
  byte j1PotY;
  byte j1Button;
  byte j2PotX;
  byte j2PotY;
  byte j2Button;
  byte pot1;
  byte pot2;
  byte tSwitch1;
  byte tSwitch2;
  byte button1;
  byte button2;
  byte button3;
  byte button4;
};
Data_Package data; //Create a variable with the above structure
void setup() {
  // Set initial seed values for the steppers
  LeftFrontWheel.setMaxSpeed(3000);
  LeftBackWheel.setMaxSpeed(3000);
  RightFrontWheel.setMaxSpeed(3000);
  RightBackWheel.setMaxSpeed(3000);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening(); // Set the module as receiver
  Serial.begin(115200);
}
void loop() {
  // Check whether we keep receving data, or we have a connection between the two modules
  currentTime = millis();
  if ( currentTime - lastReceiveTime > 1000 ) {
    // If current time is more then 1 second since we have recived the last data, that means we have lost connection
    resetData(); // If connection is lost, reset the data. It prevents unwanted behavior
  }
  // Check whether there is data to be received
  if (radio.available()) {
    radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
    lastReceiveTime = millis(); // At this moment we have received the data
  }
  // Set speed - left potentiometer
  wheelSpeed = map(data.pot1, 0, 255, 100, 3000);
  if (data.j1PotX > 150) { moveSidewaysLeft(); }
  else if (data.j1PotX < 100) { moveSidewaysRight(); }
  else if (data.j1PotY > 160) { moveForward(); }
  else if (data.j1PotY < 100) { moveBackward(); }
  else if (data.j2PotX < 100 & data.j2PotY > 160) { moveRightForward(); }
  else if (data.j2PotX > 160 & data.j2PotY > 160) { moveLeftForward(); }
  else if (data.j2PotX < 100 & data.j2PotY < 100) { moveRightBackward(); }
  else if (data.j2PotX > 160 & data.j2PotY < 100) { moveLeftBackward(); }
  else if (data.j2PotX < 100) { rotateRight(); }
  else if (data.j2PotX > 150) { rotateLeft(); }
  else { stopMoving(); }
  // Execute the steps
  LeftFrontWheel.runSpeed();
  LeftBackWheel.runSpeed();
  RightFrontWheel.runSpeed();
  RightBackWheel.runSpeed();
  // Monitor the battery voltage
  int sensorValue = analogRead(A0);
  float voltage = sensorValue * (5.0 / 1023.00) * 3;
  // If voltage is below 11V turn on the LED
  if (voltage < 11) { digitalWrite(led, HIGH); }
  else { digitalWrite(led, LOW); }
}
void moveForward() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(wheelSpeed);
}
void moveBackward() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void moveSidewaysRight() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(wheelSpeed);
}
void moveSidewaysLeft() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void rotateLeft() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(wheelSpeed);
}
void rotateRight() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void moveRightForward() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(0);
  RightFrontWheel.setSpeed(0);
  RightBackWheel.setSpeed(wheelSpeed);
}
void moveRightBackward() {
  LeftFrontWheel.setSpeed(0);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(0);
}
void moveLeftForward() {
  LeftFrontWheel.setSpeed(0);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(0);
}
void moveLeftBackward() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(0);
  RightFrontWheel.setSpeed(0);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void stopMoving() {
  LeftFrontWheel.setSpeed(0);
  LeftBackWheel.setSpeed(0);
  RightFrontWheel.setSpeed(0);
  RightBackWheel.setSpeed(0);
}
void resetData() {
  // Reset the values when there is no radio connection - Set initial default values
  data.j1PotX = 127;
  data.j1PotY = 127;
  data.j2PotX = 127;
  data.j2PotY = 127;
  data.j1Button = 1;
  data.j2Button = 1;
  data.pot1 = 1;
  data.pot2 = 1;
  data.tSwitch1 = 1;
  data.tSwitch2 = 1;
  data.button1 = 1;
  data.button2 = 1;
  data.button3 = 1;
  data.button4 = 1;
}

解説: RF24ライブラリで無線通信、AccelStepperライブラリでステッピングモーター制御を行います。ピン定義、必要な変数宣言、setup()でステッピングモーターの最大速度設定と無線通信開始。

loop()ではRC送信機からのデータを読み取ります。RC送信機のコードと通信の詳細は専用チュートリアルをご覧ください。

受信データに応じて動作を決定。例えば左ジョイスティックを前方に倒すと値が160を超え、moveForward()を呼び出します。この関数は全モーター速度を正の値に設定するだけ。後退は負の値。他の方向も冒頭で説明した通りホイール回転を適切に設定します。

これらの命令を実行するため、loop()で全ステッピングモーターのrunSpeed()を呼び出します。また分圧回路からのアナログ入力でバッテリー電圧を読み取り、11V未満なら表示LEDを点灯させます。

スマートフォンでロボットを制御するArduinoコード:

/* === Arduino Mecanum Wheels Robot === Smartphone control via Bluetooth by Dejan, www.HowToMechatronics.com Libraries: RF24, https://github.com/tmrh20/RF24/ AccelStepper by Mike McCauley: https://www.airspayce.com/mikem/arduino/AccelStepper/index.html */
#include <SoftwareSerial.h>
#include <AccelStepper.h>
SoftwareSerial Bluetooth(A8, 38); // Arduino(RX, TX) - HC-05 Bluetooth (TX, RX)
// Define the stepper motors and the pins the will use
AccelStepper LeftBackWheel(1, 42, 43); // (Type:driver, STEP, DIR) - Stepper1
AccelStepper LeftFrontWheel(1, 40, 41); // Stepper2
AccelStepper RightBackWheel(1, 44, 45); // Stepper3
AccelStepper RightFrontWheel(1, 46, 47); // Stepper4
#define led 14
int wheelSpeed = 1500;
int dataIn, m;
int lbw[50], lfw[50], rbw[50], rfw[50]; // for storing positions/steps
int index = 0;
void setup() {
  // Set initial seed values for the steppers
  LeftFrontWheel.setMaxSpeed(3000);
  LeftBackWheel.setMaxSpeed(3000);
  RightFrontWheel.setMaxSpeed(3000);
  RightBackWheel.setMaxSpeed(3000);
  Serial.begin(38400);
  Bluetooth.begin(38400); // Default baud rate of the Bluetooth module
  Bluetooth.setTimeout(1);
  delay(20);
  pinMode(led, OUTPUT);
}
void loop() {
  // Check for incoming data
  if (Bluetooth.available() > 0) {
    dataIn = Bluetooth.read(); // Read the data
    if (dataIn == 0) { m = 0; }
    if (dataIn == 1) { m = 1; }
    if (dataIn == 2) { m = 2; }
    if (dataIn == 3) { m = 3; }
    if (dataIn == 4) { m = 4; }
    if (dataIn == 5) { m = 5; }
    if (dataIn == 6) { m = 6; }
    if (dataIn == 7) { m = 7; }
    if (dataIn == 8) { m = 8; }
    if (dataIn == 9) { m = 9; }
    if (dataIn == 10) { m = 10; }
    if (dataIn == 11) { m = 11; }
    if (dataIn == 12) { m = 12; }
    if (dataIn == 14) { m = 14; }
    // Set speed
    if (dataIn >= 16) { wheelSpeed = dataIn * 10; Serial.println(wheelSpeed); }
  }
  if (m == 4) { moveSidewaysLeft(); }
  if (m == 5) { moveSidewaysRight(); }
  if (m == 2) { moveForward(); }
  if (m == 7) { moveBackward(); }
  if (m == 3) { moveRightForward(); }
  if (m == 1) { moveLeftForward(); }
  if (m == 8) { moveRightBackward(); }
  if (m == 6) { moveLeftBackward(); }
  if (m == 9) { rotateLeft(); }
  if (m == 10) { rotateRight(); }
  if (m == 0) { stopMoving(); }
  //Serial.println(dataIn);
  // If button "SAVE" is pressed
  if (m == 12) {
    if (index == 0) {
      LeftBackWheel.setCurrentPosition(0);
      LeftFrontWheel.setCurrentPosition(0);
      RightBackWheel.setCurrentPosition(0);
      RightFrontWheel.setCurrentPosition(0);
    }
    lbw[index] = LeftBackWheel.currentPosition();
    lfw[index] = LeftFrontWheel.currentPosition();
    rbw[index] = RightBackWheel.currentPosition();
    rfw[index] = RightFrontWheel.currentPosition();
    index++;
    m = 0;
  }
  if (m == 14) {
    runSteps();
    if (dataIn != 14) {
      stopMoving();
      memset(lbw, 0, sizeof(lbw));
      memset(lfw, 0, sizeof(lfw));
      memset(rbw, 0, sizeof(rbw));
      memset(rfw, 0, sizeof(rfw));
      index = 0;
    }
  }
  LeftFrontWheel.runSpeed();
  LeftBackWheel.runSpeed();
  RightFrontWheel.runSpeed();
  RightBackWheel.runSpeed();
  // Monitor the battery voltage
  int sensorValue = analogRead(A0);
  float voltage = sensorValue * (5.0 / 1023.00) * 3;
  // If voltage is below 11V turn on the LED
  if (voltage < 11) { digitalWrite(led, HIGH); }
  else { digitalWrite(led, LOW); }
}
void runSteps() {
  for (int i = index - 1; i >= 0; i--) {
    // Run through all steps(index)
    LeftFrontWheel.moveTo(lfw[i]);
    LeftFrontWheel.setSpeed(wheelSpeed);
    LeftBackWheel.moveTo(lbw[i]);
    LeftBackWheel.setSpeed(wheelSpeed);
    RightFrontWheel.moveTo(rfw[i]);
    RightFrontWheel.setSpeed(wheelSpeed);
    RightBackWheel.moveTo(rbw[i]);
    RightBackWheel.setSpeed(wheelSpeed);
    while (LeftBackWheel.currentPosition() != lbw[i] & LeftFrontWheel.currentPosition() != lfw[i] & RightFrontWheel.currentPosition() != rfw[i] & RightBackWheel.currentPosition() != rbw[i]) {
      LeftFrontWheel.runSpeedToPosition();
      LeftBackWheel.runSpeedToPosition();
      RightFrontWheel.runSpeedToPosition();
      RightBackWheel.runSpeedToPosition();
      if (Bluetooth.available() > 0) {
        // Check for incomding data
        dataIn = Bluetooth.read();
        if ( dataIn == 15) {
          // If button "PAUSE" is pressed
          while (dataIn != 14) {
            // Wait until "RUN" is pressed again
            if (Bluetooth.available() > 0) {
              dataIn = Bluetooth.read();
              if ( dataIn == 13) { stopMoving(); break; }
            }
          }
        }
        if (dataIn >= 16) { wheelSpeed = dataIn * 10; dataIn = 14; }
        if ( dataIn == 13) { break; }
      }
    }
  }
  // Go back through steps
  for (int i = 1; i <= index - 1; i++) {
    // Run through all steps(index)
    LeftFrontWheel.moveTo(lfw[i]);
    LeftFrontWheel.setSpeed(wheelSpeed);
    LeftBackWheel.moveTo(lbw[i]);
    LeftBackWheel.setSpeed(wheelSpeed);
    RightFrontWheel.moveTo(rfw[i]);
    RightFrontWheel.setSpeed(wheelSpeed);
    RightBackWheel.moveTo(rbw[i]);
    RightBackWheel.setSpeed(wheelSpeed);
    while (LeftBackWheel.currentPosition() != lbw[i]& LeftFrontWheel.currentPosition() != lfw[i] & RightFrontWheel.currentPosition() != rfw[i] & RightBackWheel.currentPosition() != rbw[i]) {
      LeftFrontWheel.runSpeedToPosition();
      LeftBackWheel.runSpeedToPosition();
      RightFrontWheel.runSpeedToPosition();
      RightBackWheel.runSpeedToPosition();
      if (Bluetooth.available() > 0) {
        // Check for incomding data
        dataIn = Bluetooth.read();
        if ( dataIn == 15) {
          // If button "PAUSE" is pressed
          while (dataIn != 14) {
            // Wait until "RUN" is pressed again
            if (Bluetooth.available() > 0) {
              dataIn = Bluetooth.read();
              if ( dataIn == 13) { stopMoving(); break; }
            }
          }
        }
        if (dataIn >= 16) { wheelSpeed = dataIn * 10; dataIn = 14; }
        if ( dataIn == 13) { break; }
      }
    }
  }
}
void moveForward() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(wheelSpeed);
}
void moveBackward() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void moveSidewaysRight() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(wheelSpeed);
}
void moveSidewaysLeft() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void rotateLeft() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(wheelSpeed);
}
void rotateRight() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void moveRightForward() {
  LeftFrontWheel.setSpeed(wheelSpeed);
  LeftBackWheel.setSpeed(0);
  RightFrontWheel.setSpeed(0);
  RightBackWheel.setSpeed(wheelSpeed);
}
void moveRightBackward() {
  LeftFrontWheel.setSpeed(0);
  LeftBackWheel.setSpeed(-wheelSpeed);
  RightFrontWheel.setSpeed(-wheelSpeed);
  RightBackWheel.setSpeed(0);
}
void moveLeftForward() {
  LeftFrontWheel.setSpeed(0);
  LeftBackWheel.setSpeed(wheelSpeed);
  RightFrontWheel.setSpeed(wheelSpeed);
  RightBackWheel.setSpeed(0);
}
void moveLeftBackward() {
  LeftFrontWheel.setSpeed(-wheelSpeed);
  LeftBackWheel.setSpeed(0);
  RightFrontWheel.setSpeed(0);
  RightBackWheel.setSpeed(-wheelSpeed);
}
void stopMoving() {
  LeftFrontWheel.setSpeed(0);
  LeftBackWheel.setSpeed(0);
  RightFrontWheel.setSpeed(0);
  RightBackWheel.setSpeed(0);
}

解説: スマートフォン/Bluetooth制御用のコードも基本的に同じ仕組みです。無線モジュールの代わりにBluetoothモジュールを定義し、setup()で通信を初期化。スマートフォン/Androidアプリからの着信データを読み取り、それに応じてロボットの移動方向を指示します。

Androidアプリを見ると、ボタン押下時に0〜15の数字をBluetoothで送信しているだけです。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

アプリはMIT App Inventorで作成。詳細は専用チュートリアルをご覧ください。

Arduinoメカナムホイールロボット自作ガイド:全方向移動を実現

アプリと編集可能なプロジェクトファイルはこちらからダウンロードできます:

このアプリで自動動作をプログラミングするには、「SAVE」ボタンでステッピングモーターの現在位置を配列に保存。「RUN」ボタンでrunSteps()カスタム関数を呼び出し、for/whileループで記録済みステップを実行します。

このチュートリアルがお役に立てば幸いです。質問はコメント欄でどうぞ。Arduinoプロジェクトコレクションもご覧ください。


製造プロセス

  1. Bluetooth 制御 Raspberry Pi ロボットに音声フィードバックを追加して構築
  2. ArduinoとHC-SR04で作るサーボ駆動障害物回避ロボット
  3. Arduino UNOで作る完全自律ライントラッカーロボット ─ 入門に最適な自作キット
  4. Arduino Nanoで音声制御ロボットを自作
  5. PiBot:Arduino駆動の精密ピアノ演奏ロボット
  6. LittleArm 2C: 3Dプリント製Arduinoロボットアーム – STEM教育向け耐久設計
  7. 自律型ホームアシスタントロボット「O'nine」の構築 – ROS、Alexa、ロボットアーム完全ガイド
  8. Arduinoロボットアーム「LittleArm」をAndroidアプリでBluetooth制御
  9. Arduino向けスマート屋内ナビゲーションロボットキット
  10. WiDC: Wi-Fi FPVロボット – ライブ映像付きリモートコントロール
  11. Arduino UNOで作る会話型ヒューマノイドロボット「モフィザ」