見出し画像

ロボットアームを動かした。

市販のロボットアームを購入してマテハン(材料を運ぶ機械)を行うつくりました。購入したロボットアームは、Rollarm for Arduinoです。


1.購入したロボットアーム

垂直多関節型と呼ばれる人間の腕を模したロボットです。
他には、水平多関節型ロボット(スカラ型)があり、その中でも直交座標型、極座標型に分類されます。

1.1 ロボットアーム構造

ロボットアーム

上図が実際のロボットアームです。3軸のロボットアームでアームを回転させて、所定の動作ができます。
1)ボリュームによるロボットアーム操作
2)Arduinoによるプログラミング
3)ソフトによる操作があります。
各軸にはサーボモータが設置されており、プログラム上から角度を角度を指定すると、モータが指定の位置に動きます。
ロボット工学の専門用語では各軸をジョイントと呼び、ロボットの土台のジョイントをJ1軸、J2軸…として、根元から遠くなる方向に番号を割り振ります。

1.2 ロボットの動き

再度ロボットアームとロボットアームをモデル化した模式図を対比させます。
ボリュームは4つあり、ボリュームを回転することでサーボモータを任意の回転角度に制御します。それぞれのモータを制御します。
赤のボリューム:J1のサーボモータ
黄色のボリューム:J2のサーボモータ
オレンジのボリューム:J3のサーボモータ
白のボリューム:ハンド(ものをつかむ)

サーボモータの可動範囲は、J1軸,J2軸,J3軸,J4軸は10~170°です。
関節の記号は、JISB0138産業用ロボット・サービスロボットで腕や手の状態と運動記号などを定義されており、この記号を用いて模式図を書きました。
今回は、ロボットの動きを計算を簡略化するために、J3軸の角度を直角(90°)固定にしています。

ロボットアーム本体と模式図の対比

2.マテハンモデル

発泡スチロールの直方体をワークとみなして、ワークを障害物をまたいで移動させる動きを作りました。

マテハンモデル図

2.1 原点位置合わせ

ロボットのアタッチメントが計算値と実機との差を小さくするには、誤差になる要因をリストアップして低減させます。
1)原点位置
2)ジョイント(J1~J4)の角度
3)アーム間の距離
4)アームの自重たわみ
5)サーボモータに使用されている減速機のギヤバックラッシ
6)サーボモータ本体の位置精度
今回のロボットの場合、できることが限られていますので、2)を調整しました。
4)は、アームはプラスチック製でかつ、モータの質量も10gと軽量なため、影響なしとみなせると考えます。
1),3)はプログラムによるモデル化をする場合は、現物を測定して3DCADにすることで精度の検証は可能です。
ロボットアームを組み立てるときにボリュームの位置とアームの角度(モータの角度)をパソコン上の画面に表示させて、調整を行いました。
Arduinoでプログラムを書いて、アームの角度を指定位置に動くように指定して、ボュームの位置、アームの角度、実機の姿勢の誤差を小さくしています。ボリューム操作によるロボットの動きの精度を向上させます。
角度は、ジョイントの角度調整図に示す角度で調整を行いました。

ジョイントの角度調整

2.2 ティーチング

ロボットは、自動溶接ロボットのように腕を動かして自動化した動きをするためロボットの動きを定義し、ティーチングと呼びます。ロボットの動きを条件分けをして、動作の順序、速度、位置を教えます。

ティーチングは、オンラインティーチング、オフラインティーチングがあります。オンラインティーチングは、直接ロボットを操作してロボットに動きを記憶させます。代表的にはダイレクトティーチングがあります。
オフラインティーチングは、パソコンの画面にロボットの動きを表示させて、ロボッロボットの動きを再現します。これをおこなうには専用ソフトウェアが必要です。

今回のティーチングは、オンラインティーチングに該当します。
ロボットの動きは、ワークをつかんでから移動させてワークを離して初期位置に戻します。
プログラム上でティーチング内容は、ロボットの各動作をサーボモータの角度で示します。

ティーチング時に際し、ティーチング用のプログラムを作成しました。
商品付属のプログラムに購入したロボットアームにボリュームを回すと、ロボットアームが動くプログラムがありました。このプログラムをArduinoのシリアルモニタ上でサーボモータの角度を表示させるように修正を行いました。操作時にロボットの各段階の動きごとにサーボモータの角度を読み取りました。

2.3 マテハンのプログラミング

2.2で行ったティーチングを行い、ロボットステップごとに関節の角度を読み取ります。
サーボモータの動きは、商品付属のプログラムを修正変更したため、ぎこちないです。

動画

プログラム

/* Include -------------------------------------------------------------------*/
#include <Servo.h>    // Create servo object to control a servo 

/* Define -------------------------------------------------------------------*/
Servo Servo_0;
Servo Servo_1;
Servo Servo_2;
Servo Servo_3;

int M0 = 90, M1 = 90, M2 = 90, M3 = 135;//current_potanton M0,M1,M2,range 10-170,M3 range 100-180
//initial value input
int r0 = 0, r1 = 0, r2 = 0, r3 = 0;//motor value value range 10-170
/*
  - setup function
  ---------------------------------------------------------------------------*/
void setup() 
{
   int inideg;
  //Start the serial.
  Serial.begin(9600);
  
  //Attach the servos on pins to the servo object
  Servo_0.attach(4);//角度指定0to180degC
  Servo_1.attach(5);//角度指定0to180degC
  Servo_2.attach(6);//角度指定0to180degC
  Servo_3.attach(7);//角度指定0to180degC
  
  delay(8000);
  Serial.println("Initiali ze"); 

  //Set the initial positions of steering gears
  delay(2);
  Serial.println("SetInitialPosition"); 
  Servo_0.write(M0);
  Servo_1.write(M1);
  Servo_2.write(M2);
  Servo_3.write(M3);

  
  motor0_act(29,50,500);
  readstatus(false);
  motor1_act(155,50,500);
  readstatus(false);
  motor2_act(90,50,500);
  readstatus(false);
  motor3_act(170,50,500);
  readstatus(false);
  motor2_act(90,50,500);
  readstatus(false);
  motor1_act(90,50,500);
  readstatus(false);
  motor0_act(135,50,500);
  readstatus(false);
  motor1_act(155,50,500);
  readstatus(false);
  motor2_act(90,50,500);
  readstatus(false);
  motor3_act(135,50,500);
  readstatus(false);
  motor2_act(90,50,500);
  readstatus(false);
  motor1_act(90,50,500);
  readstatus(false);
  motor3_act(110,50,500);
  readstatus(false);
  motor0_act(90,50,500);
  readstatus(false);
  
  motor3_act(135,50,500);
  readstatus(false);

}

/*
  - loop function
   ---------------------------------------------------------------------------*/
void loop() 
{
  
}

void motor0_act(int motor0,int speedy,int pause){   
    if ((motor0 - M0) >= 0)
    {
      for (; M0 <= motor0; M0++)
      {
        Servo_0.write(M0); delay(speedy);
      }
    }
    else
    {
      for (; M0 > motor0; M0--)
      {
        Servo_0.write(M0);  delay(speedy);
      }
    }
    M0=Servo_0.read(); //今のモータ位置を確認する
    r0=M0;
    delay(pause);
}

void motor1_act(int motor1,int speedy,int pause){   
    if ((motor1 - M1) >= 0)
    {
      for (; M1 <= motor1; M1++)
      {
        Servo_1.write(M1); delay(speedy);
      }
    }
    else
    {
      for (; M1 > motor1; M1--)
      {
        Servo_1.write(M1);  delay(speedy);
      }
    }
    M1=Servo_1.read(); //今のモータ位置を確認する
    r1=M1;
    delay(pause);
}

void motor2_act(int motor2,int speed,int pause){   
    if ((motor2 - M2) >= 0)
    {
      for (; M2 <= motor2; M2++)
      {
        Servo_2.write(M2); delay(speed);
      }
    }
    else
    {
      for (; M2 > motor2; M2--)
      {
        Servo_2.write(M2);  delay(speed);
      }
    }
    M2=Servo_2.read(); //今のモータ位置を確認する
    r2=M2;
    delay(pause);
}

void motor3_act(int motor3,int speed,int pause){   
    if ((motor3 - M3) >= 0)
    {
      for (; M3 <= motor3; M3++)
      {
        Servo_3.write(M3); delay(speed);
      }
    }
    else
    {
      for (; M3 > motor3; M3--)
      {
        Servo_3.write(M3);  delay(speed);
      }
    }
    M3=Servo_3.read(); //今のモータ位置を確認する
    r3=M3;
    delay(pause);
}

void readstatus(bool flg)
{ //Record
  r0 = Servo_0.read();
  r1 = Servo_1.read();
  r2 = Servo_2.read();
  r3 = Servo_3.read();
  
  //print
  if (flg==true){
  Serial.println("M0,M1,M2,M3,r0,r1,r2,r3");}
  
  Serial.print(M0);
  Serial.print(",");
  Serial.print(M1);
  Serial.print(",");
  Serial.print(M2);
  Serial.print(",");
  Serial.print(M3);
  Serial.print(",");
  Serial.print(r0);
  Serial.print(",");
  Serial.print(r1);
  Serial.print(",");
  Serial.print(r2);
  Serial.print(",");
  Serial.println(r3);
    //---
  //Record the current value of the servomotorpotentiometer 
  Serial.print(r0);
  Serial.print(",");
  Serial.print(r1);
  Serial.print(",");
  Serial.print(r2);
  Serial.print(",");
  Serial.println(r3);
  //---
}
void Servo0(int deg){
 Servo_0.write(deg);
 Serial.print("servo0:");
 Serial.print(deg);
 Serial.println("deg"); 
}

void Servo1(int deg){
 Servo_1.write(deg);
 Serial.print("servo1:");
 Serial.print(deg);
 Serial.println("deg"); 
}

void Servo2(int deg){
 Servo_2.write(deg);
 Serial.print("servo2:");
 Serial.print(deg);
 Serial.println("deg"); 
}

void Servo3(int deg){
 Servo_3.write(deg);
 Serial.print("servo3:");
 Serial.print(deg);
 Serial.println("deg3"); 
}

3.まとめ

市販の学習ロボットアームを使って、市販品なのでできることは限られているもののロボットの考え方を体験しました。
カメラを使ってワークである発泡スチロールの塊を自動認識して、ロボットがアームを自動的に移動させたり、アームの速度を調整することで効率の良い動かし方もできるかもしません。

4.参考書籍

1)産業用ロボット The ビギニング

2)イラストでわかるロボット工学

3)絵ときでわかる ロボット工学


この記事が気に入ったらサポートをしてみませんか?