ワイヤレス Arduino ロボットアーム製作:スマートフォンで制御・プログラミング
このチュートリアルでは、カスタムビルドの Android アプリケーションを使用してワイヤレスで制御およびプログラミングできる Arduino ロボットアームの作り方を学びます。ロボットパーツの設計と 3D プリント、電子部品の接続、Arduino のプログラミング、ロボットアーム制御用の独自 Android アプリケーションの開発まで、構築の全プロセスを紹介します。 以下の動画をご覧いただくか、書面によるチュートリアルをお読みください。 アプリのスライダーを使用して、ロボットアームの各サーボまたは軸の動きを手動で制御できます。「保存」ボタンを使用すると、各位置やステップを記録し、ロボットアームがこれらのステップを自動的に実行して繰り返すことができます。同じボタンで自動動作の一時停止、すべてのステップのリセットまたは削除も可能で、新しいステップを記録できます。 まず、Solidworks 3D モデリングソフトウェアを使用してロボットアームを設計しました。アームは 5 自由度を持ちます。 最初の 3 軸(腰、肩、肘)には MG996R サーボを使用し、他の 2 軸(手首ロール、手首ピッチ)とグリッパーにはより小型の SG90 マイクロサーボを使用しました。 この 3D モデルは Thangs で見つけてダウンロードでき、ブラウザ上で探索することもできます: Thangs からアセンブリ 3D モデルをダウンロード。 このチュートリアルをサポートしてくれた Thangs に感謝します。 3D プリント用 STL ファイル: 新しい 3D プリンター、Creality CR-10 を使用して、Arduino ロボットアームのすべてのパーツを 3D プリントしました。 ここで、この素晴らしい 3D プリンターを提供してくれた Banggood.com に感謝したいと思います。Creality CR-10 のプリント品質は価格を考えると驚異的で、ほぼ 90% 組み立て済みの状態で届くのも素晴らしい点です。 組み立てを完了するには、ボルトとブラケットを使用して上部と下部のフレームを接続し、付属のケーブルで電子部品をコントロールボックスに接続するだけです。 試用前に、ローラーホイールが十分に締まっているか確認することをお勧めします。緩んでいる場合は、エキセントリックナットを使用して締めることができます。これで、3D プリントベッドのレベリングを行えば、あなたの 3D 作品を現実に変える準備が整います。 Arduino ロボットアームのすべてのパーツがわずか数時間で準備できました。 関連記事: 3D プリンター必須アクセサリーとツール トップ 15 では、ロボットアームを組み立てましょう。ベースから始め、付属のネジを使用して最初のサーボモーターを取り付けました。次に、サーボの出力シャフトにラウンドホーンをボルトで固定しました。 その上に上部パーツを置き、2 本のネジで固定しました。 ここでも同様に、まずサーボ、次にラウンドホーンを次のパーツに取り付け、出力シャフトのボルトで互いに固定します。 肩軸では、このサーボがアームの残りの重量とペイロードを支えるため、何らかのスプリング、私の場合はゴムバンドを追加してサーボを補助するのが良いアイデアです。 同様の方法でロボットアームの残りを組み立てました。グリッパー機構には 4mm のボルトとナットを使用して組み立てました。 最後にグリッパー機構を最後のサーボに取り付け、Arduino ロボットアームが完成しました。 次の段階は電子部品の接続です。このプロジェクトの回路図は実はかなりシンプルです。Arduino ボードとスマートフォンとの通信用 HC-05 Bluetooth モジュールが必要です。6 個のサーボモーターの制御ピンを Arduino ボードの 6 つのデジタルピンに接続します。 サーボへの給電には 5V が必要ですが、これはすべてのサーボが消費する電流量を Arduino が処理できないため、外部電源から供給する必要があります。電源は最低 2A の電流を処理できる必要があります。すべてを接続したら、Arduino のプログラミングと Android アプリの作成に進みます。 この例に必要なコンポーネントは以下のリンクから入手できます: コードが少し長いため、理解しやすくするためにプログラムのソースコードをセクションごとに説明付きで掲載します。この記事の最後には完全なソースコードを掲載します。 まず、Bluetooth モジュールのシリアル通信用の SoftwareSerial ライブラリとサーボライブラリをインクルードする必要があります。これら両方のライブラリは Arduino IDE に含まれているため、外部からインストールする必要はありません。次に、6 個のサーボ、HC-05 Bluetooth モジュール、サーボの現在位置と前回位置を格納する変数、自動モード用の位置またはステップを格納する配列を定義します。 setup では、サーボと Bluetooth モジュールを初期化し、ロボットアームを初期位置に移動させます。write() 関数を使用して、サーボを 0〜180 度の任意の位置に移動させます。 次に、loop では Bluetooth.available() 関数を使用して、スマートフォンからの着信データがあるかどうかを常にチェックします。真の場合、readString() 関数を使用してデータを文字列として読み取り、dataIn 変数に格納します。到着したデータに応じて、ロボットアームに何をすべきか指示します。 Android アプリを見て、実際に Arduino にどのようなデータを送信しているか確認しましょう。 このアプリは MIT App Inventor オンラインアプリケーションを使用して作成しました。その仕組みは以下の通りです。上部には HC-05 Bluetooth モジュールとスマートフォンを接続するための 2 つのボタンがあります。左側にはロボットアームの画像、右側にはサーボ制御用の 6 つのスライダーと速度制御用の 1 つのスライダーがあります。 各スライダーには、ロボットアームの関節に適した異なる初期値、最小値、最大値があります。アプリの下部には、SAVE、RUN、RESET の 3 つのボタンがあり、これらを通じてロボットアームを自動実行するようにプログラミングできます。また、保存したステップ数を表示するラベルもあります。MIT App Inventor を使用してこのようなアプリを構築する詳細については、私の他の詳細なチュートリアルをご覧ください。 では、アプリケーションの背後にあるプログラム、つまりブロックを見てみましょう。まず、左側にはスマートフォンを Bluetooth モジュールに接続するためのブロックがあります。 次に、サーボ位置制御用のスライダーブロックと、ロボットアームのプログラミング用のボタンブロックがあります。スライダーの位置を変更すると、Bluetooth 関数 .SendText を使用して Arduino にテキストを送信します。このテキストは、どのスライダーが変更されたかを示すプレフィックスと、スライダーの現在値で構成されます。 上記の MIT App Inventor プロジェクトファイルと、スマートフォンにインストール可能な Android アプリのダウンロードファイルはこちら: したがって、Arduino 側では startsWith() 関数を使用して着信データのプレフィックスをチェックし、次に何をすべきかを判断します。例えば、プレフィックスが「s1」の場合、サーボ 1 を動かす必要があることがわかります。substring() 関数を使用して残りのテキスト、つまり位置値を取得し、整数に変換してその値でサーボをその位置に移動させます。 ここでは単純に write() 関数を呼び出せばサーボはその位置に移動しますが、その場合サーボは最大速度で動作し、ロボットアームには速すぎます。代わりに、FOR ループを使用して前回の位置から現在の位置までサーボを徐々に移動させ、各イテレーション間に遅延時間を実装することでサーボの速度を制御します。遅延時間を変更することでサーボの速度を変更できます。 同じ方法でロボットアームの各軸を駆動します。 それ以下に SAVE ボタンがあります。SAVE ボタンを押すと、各サーボモーターの位置が配列に格納されます。押すたびにインデックスが増加し、配列がステップバイステップで埋められます。 RUN ボタンを押すと、runservo() カスタム関数を呼び出して記録されたステップを実行します。この関数を見てみましょう。ここでは RESET ボタンが押されるまで記録されたステップを繰り返し実行します。FOR ループを使用して配列に格納されたすべての位置を実行し、同時にスマートフォンからの着信データがあるかチェックします。このデータは RUN/一時停止ボタンであり、ロボットを一時停止し、再度クリックすると自動動作を継続します。また、速度スライダーの位置が変更された場合、その値を使用して以下の FOR ループの各イテレーション間の遅延時間を変更し、サーボモーターの速度を制御します。 前述と同様に、これらの IF 文と FOR ループを使用してサーボを次の位置に移動させます。最後に RESET ボタンを押すと、配列のすべてのデータをゼロにクリアし、インデックスもゼロにリセットして、新しい動きでロボットアームを再プログラミングできるようにします。 これで完成です。ロボットアームで楽しんでください。 Arduino ロボットアームの完全なコードはこちら: この動画を気に入っていただき、新しいことを学んでいただけたなら幸いです。質問があれば下のコメント欄で自由にお尋ねください。また、私の Arduino プロジェクトコレクションもチェックしてみてください。概要
Arduino ロボットアーム 3D モデル


Arduino Robot Arm STL Files
1 file(s) 0.00 KB Download
ロボットアームの 3D プリント




ロボットアームの組み立て






Arduino ロボットアーム回路図

Arduino ロボットアームコード
#include <SoftwareSerial.h>
#include <Servo.h>
Servo servo01;
Servo servo02;
Servo servo03;
Servo servo04;
Servo servo05;
Servo servo06;
SoftwareSerial Bluetooth(3, 4); // Arduino(RX, TX) - HC-05 Bluetooth (TX, RX)
int servo1Pos, servo2Pos, servo3Pos, servo4Pos, servo5Pos, servo6Pos; // 現在位置
int servo1PPos, servo2PPos, servo3PPos, servo4PPos, servo5PPos, servo6PPos; // 前回位置
int servo01SP[50], servo02SP[50], servo03SP[50], servo04SP[50], servo05SP[50], servo06SP[50]; // 位置/ステップ格納用
int speedDelay = 20;
int index = 0;
String dataIn = "";void setup() {
servo01.attach(5);
servo02.attach(6);
servo03.attach(7);
servo04.attach(8);
servo05.attach(9);
servo06.attach(10);
Bluetooth.begin(38400); // Bluetooth モジュールのデフォルトボーレート
Bluetooth.setTimeout(1);
delay(20);
// ロボットアーム初期位置
servo1PPos = 90;
servo01.write(servo1PPos);
servo2PPos = 150;
servo02.write(servo2PPos);
servo3PPos = 35;
servo03.write(servo3PPos);
servo4PPos = 140;
servo04.write(servo4PPos);
servo5PPos = 85;
servo05.write(servo5PPos);
servo6PPos = 80;
servo06.write(servo6PPos);
}// 着信データをチェック
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.readString(); // データを文字列として読み取り制御用 Android アプリ




Arduino Robot Arm Control MIT App Inventor Project File
1 file(s) 24.85 KB Download
Arduino Robot Arm Control Android App
1 file(s) 2.57 MB Download
// 「Waist」スライダーの値が変更された場合 - サーボ 1 を位置に移動
if (dataIn.startsWith("s1")) {
String dataInS = dataIn.substring(2, dataIn.length()); // 数字のみ抽出。例: "s1120" から "120"
servo1Pos = dataInS.toInt(); // 文字列を整数に変換// FOR ループを使用してサーボの速度を制御
// 前回位置が現在位置より大きい場合
if (servo1PPos > servo1Pos) {
for (int j = servo1PPos; j >= servo1Pos; j--) {
// サーボを下方向に動作
servo01.write(j);
delay(20); // サーボ回転速度を定義
}
}
// 前回位置が現在位置より小さい場合
if (servo1PPos < servo1Pos) {
for (int j = servo1PPos; j <= servo1Pos; j++) {
// サーボを上方向に動作
servo01.write(j);
delay(20);
}
}
servo1PPos = servo1Pos; // 現在位置を前回位置として設定
}// 「SAVE」ボタンが押された場合
if (dataIn.startsWith("SAVE")) {
servo01SP[index] = servo1PPos; // 位置を配列に保存
servo02SP[index] = servo2PPos;
servo03SP[index] = servo3PPos;
servo04SP[index] = servo4PPos;
servo05SP[index] = servo5PPos;
servo06SP[index] = servo6PPos;
index++; // 配列インデックスを増加
}// 自動モード カスタム関数 - 保存されたステップを実行
void runservo() {
while (dataIn != "RESET") {
// "RESET" ボタンが押されるまでステップを繰り返し実行
for (int i = 0; i <= index - 2; i++) {
// すべてのステップ(index)を実行
if (Bluetooth.available() > 0) {
// 着信データをチェック
dataIn = Bluetooth.readString();
if (dataIn == "PAUSE") {
// 「PAUSE」ボタンが押された場合
while (dataIn != "RUN") {
// "RUN" が再度押されるまで待機
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.readString();
if (dataIn == "RESET") {
break;
}
}
}
}
// SPEED スライダーが変更された場合
if (dataIn.startsWith("ss")) {
String dataInS = dataIn.substring(2, dataIn.length());
speedDelay = dataInS.toInt(); // サーボ速度(遅延時間)を変更
}
}
// サーボ 1
if (servo01SP[i] == servo01SP[i + 1]) {
}
if (servo01SP[i] > servo01SP[i + 1]) {
for (int j = servo01SP[i]; j >= servo01SP[i + 1]; j--) {
servo01.write(j);
delay(speedDelay);
}
}
if (servo01SP[i] < servo01SP[i + 1]) {
for (int j = servo01SP[i]; j <= servo01SP[i + 1]; j++) {
servo01.write(j);
delay(speedDelay);
}
}// 「RESET」ボタンが押された場合
if (dataIn == "RESET") {
memset(servo01SP, 0, sizeof(servo01SP)); // 配列データを 0 にクリア
memset(servo02SP, 0, sizeof(servo02SP));
memset(servo03SP, 0, sizeof(servo03SP));
memset(servo04SP, 0, sizeof(servo04SP));
memset(servo05SP, 0, sizeof(servo05SP));
memset(servo06SP, 0, sizeof(servo06SP));
index = 0; // インデックスを 0 に
}/* DIY Arduino Robot Arm Smartphone Control by Dejan, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
#include <Servo.h>
Servo servo01;
Servo servo02;
Servo servo03;
Servo servo04;
Servo servo05;
Servo servo06;
SoftwareSerial Bluetooth(3, 4); // Arduino(RX, TX) - HC-05 Bluetooth (TX, RX)
int servo1Pos, servo2Pos, servo3Pos, servo4Pos, servo5Pos, servo6Pos; // 現在位置
int servo1PPos, servo2PPos, servo3PPos, servo4PPos, servo5PPos, servo6PPos; // 前回位置
int servo01SP[50], servo02SP[50], servo03SP[50], servo04SP[50], servo05SP[50], servo06SP[50]; // 位置/ステップ格納用
int speedDelay = 20;
int index = 0;
String dataIn = "";
void setup() {
servo01.attach(5);
servo02.attach(6);
servo03.attach(7);
servo04.attach(8);
servo05.attach(9);
servo06.attach(10);
Bluetooth.begin(38400); // Bluetooth モジュールのデフォルトボーレート
Bluetooth.setTimeout(1);
delay(20);
// ロボットアーム初期位置
servo1PPos = 90;
servo01.write(servo1PPos);
servo2PPos = 150;
servo02.write(servo2PPos);
servo3PPos = 35;
servo03.write(servo3PPos);
servo4PPos = 140;
servo04.write(servo4PPos);
servo5PPos = 85;
servo05.write(servo5PPos);
servo6PPos = 80;
servo06.write(servo6PPos);
}
void loop() {
// 着信データをチェック
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.readString(); // データを文字列として読み取り
// 「Waist」スライダーの値が変更された場合 - サーボ 1 を位置に移動
if (dataIn.startsWith("s1")) {
String dataInS = dataIn.substring(2, dataIn.length()); // 数字のみ抽出。例: "s1120" から "120"
servo1Pos = dataInS.toInt(); // 文字列を整数に変換
// FOR ループを使用してサーボの速度を制御
// 前回位置が現在位置より大きい場合
if (servo1PPos > servo1Pos) {
for (int j = servo1PPos; j >= servo1Pos; j--) {
// サーボを下方向に動作
servo01.write(j);
delay(20); // サーボ回転速度を定義
}
}
// 前回位置が現在位置より小さい場合
if (servo1PPos < servo1Pos) {
for (int j = servo1PPos; j <= servo1Pos; j++) {
// サーボを上方向に動作
servo01.write(j);
delay(20);
}
}
servo1PPos = servo1Pos; // 現在位置を前回位置として設定
}
// サーボ 2 を移動
if (dataIn.startsWith("s2")) {
String dataInS = dataIn.substring(2, dataIn.length());
servo2Pos = dataInS.toInt();
if (servo2PPos > servo2Pos) {
for (int j = servo2PPos; j >= servo2Pos; j--) {
servo02.write(j);
delay(50);
}
}
if (servo2PPos < servo2Pos) {
for (int j = servo2PPos; j <= servo2Pos; j++) {
servo02.write(j);
delay(50);
}
}
servo2PPos = servo2Pos;
}
// サーボ 3 を移動
if (dataIn.startsWith("s3")) {
String dataInS = dataIn.substring(2, dataIn.length());
servo3Pos = dataInS.toInt();
if (servo3PPos > servo3Pos) {
for (int j = servo3PPos; j >= servo3Pos; j--) {
servo03.write(j);
delay(30);
}
}
if (servo3PPos < servo3Pos) {
for (int j = servo3PPos; j <= servo3Pos; j++) {
servo03.write(j);
delay(30);
}
}
servo3PPos = servo3Pos;
}
// サーボ 4 を移動
if (dataIn.startsWith("s4")) {
String dataInS = dataIn.substring(2, dataIn.length());
servo4Pos = dataInS.toInt();
if (servo4PPos > servo4Pos) {
for (int j = servo4PPos; j >= servo4Pos; j--) {
servo04.write(j);
delay(30);
}
}
if (servo4PPos < servo4Pos) {
for (int j = servo4PPos; j <= servo4Pos; j++) {
servo04.write(j);
delay(30);
}
}
servo4PPos = servo4Pos;
}
// サーボ 5 を移動
if (dataIn.startsWith("s5")) {
String dataInS = dataIn.substring(2, dataIn.length());
servo5Pos = dataInS.toInt();
if (servo5PPos > servo5Pos) {
for (int j = servo5PPos; j >= servo5Pos; j--) {
servo05.write(j);
delay(30);
}
}
if (servo5PPos < servo5Pos) {
for (int j = servo5PPos; j <= servo5Pos; j++) {
servo05.write(j);
delay(30);
}
}
servo5PPos = servo5Pos;
}
// サーボ 6 を移動
if (dataIn.startsWith("s6")) {
String dataInS = dataIn.substring(2, dataIn.length());
servo6Pos = dataInS.toInt();
if (servo6PPos > servo6Pos) {
for (int j = servo6PPos; j >= servo6Pos; j--) {
servo06.write(j);
delay(30);
}
}
if (servo6PPos < servo6Pos) {
for (int j = servo6PPos; j <= servo6Pos; j++) {
servo06.write(j);
delay(30);
}
}
servo6PPos = servo6Pos;
}
// 「SAVE」ボタンが押された場合
if (dataIn.startsWith("SAVE")) {
servo01SP[index] = servo1PPos; // 位置を配列に保存
servo02SP[index] = servo2PPos;
servo03SP[index] = servo3PPos;
servo04SP[index] = servo4PPos;
servo05SP[index] = servo5PPos;
servo06SP[index] = servo6PPos;
index++; // 配列インデックスを増加
}
// 「RUN」ボタンが押された場合
if (dataIn.startsWith("RUN")) {
runservo(); // 自動モード - 保存されたステップを実行
}
// 「RESET」ボタンが押された場合
if (dataIn == "RESET") {
memset(servo01SP, 0, sizeof(servo01SP)); // 配列データを 0 にクリア
memset(servo02SP, 0, sizeof(servo02SP));
memset(servo03SP, 0, sizeof(servo03SP));
memset(servo04SP, 0, sizeof(servo04SP));
memset(servo05SP, 0, sizeof(servo05SP));
memset(servo06SP, 0, sizeof(servo06SP));
index = 0; // インデックスを 0 に
}
}
}
// 自動モード カスタム関数 - 保存されたステップを実行
void runservo() {
while (dataIn != "RESET") {
// "RESET" ボタンが押されるまでステップを繰り返し実行
for (int i = 0; i <= index - 2; i++) {
// すべてのステップ(index)を実行
if (Bluetooth.available() > 0) {
// 着信データをチェック
dataIn = Bluetooth.readString();
if (dataIn == "PAUSE") {
// 「PAUSE」ボタンが押された場合
while (dataIn != "RUN") {
// "RUN" が再度押されるまで待機
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.readString();
if (dataIn == "RESET") {
break;
}
}
}
}
// 速度スライダーが変更された場合
if (dataIn.startsWith("ss")) {
String dataInS = dataIn.substring(2, dataIn.length());
speedDelay = dataInS.toInt(); // サーボ速度(遅延時間)を変更
}
}
// サーボ 1
if (servo01SP[i] == servo01SP[i + 1]) {
}
if (servo01SP[i] > servo01SP[i + 1]) {
for (int j = servo01SP[i]; j >= servo01SP[i + 1]; j--) {
servo01.write(j);
delay(speedDelay);
}
}
if (servo01SP[i] < servo01SP[i + 1]) {
for (int j = servo01SP[i]; j <= servo01SP[i + 1]; j++) {
servo01.write(j);
delay(speedDelay);
}
}
// サーボ 2
if (servo02SP[i] == servo02SP[i + 1]) {
}
if (servo02SP[i] > servo02SP[i + 1]) {
for (int j = servo02SP[i]; j >= servo02SP[i + 1]; j--) {
servo02.write(j);
delay(speedDelay);
}
}
if (servo02SP[i] < servo02SP[i + 1]) {
for (int j = servo02SP[i]; j <= servo02SP[i + 1]; j++) {
servo02.write(j);
delay(speedDelay);
}
}
// サーボ 3
if (servo03SP[i] == servo03SP[i + 1]) {
}
if (servo03SP[i] > servo03SP[i + 1]) {
for (int j = servo03SP[i]; j >= servo03SP[i + 1]; j--) {
servo03.write(j);
delay(speedDelay);
}
}
if (servo03SP[i] < servo03SP[i + 1]) {
for (int j = servo03SP[i]; j <= servo03SP[i + 1]; j++) {
servo03.write(j);
delay(speedDelay);
}
}
// サーボ 4
if (servo04SP[i] == servo04SP[i + 1]) {
}
if (servo04SP[i] > servo04SP[i + 1]) {
for (int j = servo04SP[i]; j >= servo04SP[i + 1]; j--) {
servo04.write(j);
delay(speedDelay);
}
}
if (servo04SP[i] < servo04SP[i + 1]) {
for (int j = servo04SP[i]; j <= servo04SP[i + 1]; j++) {
servo04.write(j);
delay(speedDelay);
}
}
// サーボ 5
if (servo05SP[i] == servo05SP[i + 1]) {
}
if (servo05SP[i] > servo05SP[i + 1]) {
for (int j = servo05SP[i]; j >= servo05SP[i + 1]; j--) {
servo05.write(j);
delay(speedDelay);
}
}
if (servo05SP[i] < servo05SP[i + 1]) {
for (int j = servo05SP[i]; j <= servo05SP[i + 1]; j++) {
servo05.write(j);
delay(speedDelay);
}
}
// サーボ 6
if (servo06SP[i] == servo06SP[i + 1]) {
}
if (servo06SP[i] > servo06SP[i + 1]) {
for (int j = servo06SP[i]; j >= servo06SP[i + 1]; j--) {
servo06.write(j);
delay(speedDelay);
}
}
if (servo06SP[i] < servo06SP[i + 1]) {
for (int j = servo06SP[i]; j <= servo06SP[i + 1]; j++) {
servo06.write(j);
delay(speedDelay);
}
}
}
}
}
製造プロセス
- スマート貯金箱を作ろう:Arduino Nanoでコインアクセプターを制御
- Arduinoとスマホで作るスマート電圧計 – 簡単DIYプロジェクト
- IoTで遠隔操作する自作ロボットアーム:Arduino MKR1000とSimulink、ThingSpeak活用
- ArduinoとHC-SR04で作るサーボ駆動障害物回避ロボット
- ArduinoでBluetooth経由でLEDを制御 – シンプルDIYガイド
- Arduinoベースのヌンチャク操作6自由度ロボットアームキット
- Arduino Nanoとジョイスティックで2軸ステッピングモーターを制御:Visuinoで簡単プログラミング
- MobBob:Arduino製ロボットをAndroidスマホでシームレスに制御
- LittleArm 2C: 3Dプリント製Arduinoロボットアーム – STEM教育向け耐久設計
- ThimbleKrox: Arduino MicroとMPU-6050を用いた指装着型マウス制御
- Yama Seiki GA-2000CR:ロボットアームとパレットシステム搭載のコンパクト旋削センター