blavince's BLOG

Giving is a reward in itself.

0%

C# 整合 EPSON Robot 與 Basler Camera

機械手臂常用於取代重複性工作, 而機械手臂有眾多的廠家, 如: ABB、EPSON、TM、Nachi、Kawasaki...等等; 剛好有機會接觸 Epson Robot + Basler Camera 的組合.

前言

導入 EPSON 與 Basler 提供的 DLL ( C# 導入外部 DLL ), 建立開發環境, 整合後呼叫方法完成定點取像任務.

RCAPINet.dllBasler.Pylon.dll

本文

  1. Basler 擷取圖像

  2. Epson Robot

    • 座標軸
    • 移動指令
      • Jump
      • Go
      • Move
      • Bgo
  3. 定點取像

1. Basler 擷取圖像

Basler 的相機提供 USB 和乙太網路的連接方式, 透過官方軟件 - pylon 設定好 Camera 的 IP, 使開發環境在同一個網域內; 如下圖確認已經在同一個網域 (192.168.10.102) 後, 透過 ToolPylon IP Configurator 來確認是否判讀到裝置.

編寫操作方法,

  1. 加入 using:

    1
    using Basler.Pylon;
  2. 宣告 Camera 實例及方法(對應裝置 S/N 碼):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    namespace CCD
    {
    public class Basler
    {
    private Camera _camera;
    public void camera_init(string camera_sn)
    {
    _camera = new Camera(camera_sn);
    }
    }
    }
  3. 開啟/關閉 攝像頭:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public bool ccd_on()
    {
    try
    {
    int timeout = 1000;
    _camera.Open(timeout, TimeoutHandling.ThrowException);
    _camera.Parameters[PLCamera.PixelFormat].SetValue("Mono8");
    return true;
    }
    catch(Exception ex)
    {
    return false;
    }
    }

    public void ccd_off()
    {
    _camera.Close();
    }
  4. 擷取圖像:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public Bitmap GrabResult2Bmp(IGrabResult grabResult)
    {
    Bitmap b = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format32bppRgb);
    BitmapData bmpData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, b.PixelFormat);
    pxConvert.OutputPixelFormat = PixelType.BGRA8packed;
    IntPtr bmpIntpr = bmpData.Scan0;
    pxConvert.Convert(bmpIntpr, bmpData.Stride * b.Height, grabResult);
    b.UnlockBits(bmpData);
    return b;
    }

    public Bitmap take_one_picture(int exposure_time)
    {
    _camera.Parameters[PLCamera.ExposureTimeRaw].SetValue(exposure_time);
    IGrabResult grab_pic = _camera.StreamGrabber.GrabOne(5000);
    return GrabResult2Bmp(grab_pic);
    }

呼叫方法 take_one_picture(int exposure_time) 就能夠得到 Bitmap 格式的圖像.

2. Epson Robot

  1. 座標軸:
    不管四軸或者六軸手臂, 所謂的 座標點 皆是指機械手臂的末端位置, 而手臂本身就是座標系. 在此認知下, 可以定義出 座標點(x,y,z,u) 所代表的 3D 空間位置及當下位置的旋轉角度(u). 座標系可再分成機器人座標系、工具座標系及本地座標系, 但在此先不介紹.

  2. 移動指令:
    機械臂的移動大致分成 直線移動點到點 (PTP) 移動:

  • Jump: 以門控動作移動至目標座標的動作 (PIP 動作), 優點可以避開障礙物.

  • Go: 用於在當前位置~指定位置之間以 PTP 動作 移動機械臂

  • Move: 用於在當前位置~指定位置之間以 直線插補動作 移動機械臂, 與 Go 最大不同在於所有關節同時移動.

  • BGo: 用於在已選擇的本地座標系上執行偏移 PTP 動作

宣告實例及變數:

1
2
3
4
5
6
7
8
9
namespace Robot
{
public class Epson
{
private RCAPINet.Spel spl;
private string Projectpath;
private string pts_path;
}
}

開啟方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public void ini_robot_on()
{
spl = new RCAPINet.Spel();
spl.AsyncMode = true; //開啟同步模式
spl.ServerInstance = 1; //指定實例, 如果同時使用 2 隻以上的手臂就 2, 3, ...
spl.Connect(2); //指定實例的編號, 對應 RC+ 程序內的編號

spl.Initialize();
spl.Project = Projectpath; //指定到 <專案路徑> 的方案檔(main.sprj)
spl.Reset();

reload_points(); //重新讀取點位檔
spl.MotorsOn = true; //打開馬達
spl.PowerHigh = true; //設為高功率
initial_output_IO(); //初始化I/O狀態
robot_para(); //初始化機械手臂參數
}

public void set_project_path(string path)
{
Projectpath = path + "\\Data\\main\\main.sprj";
pts_path = path + "\\Data\\main\\robot_project_points.pts";
}

public void reload_points()
{
spl.ClearPoints();
spl.ImportPoints(pts_path, "robot1.pts");
spl.LoadPoints("robot1.pts");
}

public void robot_para()
{
spl.Accel(100, 100); //(加速度,減速度)設置 0~100
spl.Speed(100); //速度設置 0~100
spl.Fine(0, 0, 0, 0, 0, 0); //馬達以 pulse 作定位, 設為 0 代表需為最精準
spl.Tool(0); // Tool 座標系
spl.LimZ(0); // Limz: Jump 上升時的高度限制
spl.MemOff(1); // Epson 提供的 memory 管理系統
}

public void jump(string position)
{
spl.Jump(position);
}

機械臂還有許多進階的指令如: 並行處理 !..!、 CP、 Till、 Local … 等等, 可以針對開發需求去優化機械臂, 例如可改寫 jump 方法如下透過監控 MemSw(1)、MemSw(2) 及 Sw(0) 的訊號來判斷是否暫停/繼續機械臂動作任務 :

1
2
3
4
5
6
7
8
9
10
11
12
13
public void jump(string position)
{
spl.Till("MemSw(1) = On Or MemSw(2) = On Or Sw(0) = On");
spl.Jump(position);
if (spl.TillOn())
{
do
{
spl.WaitMem(1, false, 5);
} while (spl.TW());
jump(position);
}
}

HINT:
更多詳細介紹參照 EPSON 的官方文件.
ex:
安裝完 EPSON SDK 後, 在 C:\EpsonRC70\manuals\English\ … 底下
1. e_SPEL+Ref73_r1.pdf
2. e_RC+API70_r9.pdf
3. …

3. 定點取像

整合上述兩個 dll 及方法後, 將攝像頭架設於機械臂的末端並完成定點 (P1點) 取像任務:

1
2
3
4
5
6
7
8
9
10
11
12
13
public void capture_task(string camera_sn, string P1, int exposure_time)
{
Robot.Epson rbt; //宣告機械臂實例
CCD.Basler bsr; //宣告攝像頭實例

rbt.ini_robot_on(); //開啟機械臂
bsr.camera_init(camera_sn); //設置攝像頭S/N
bsr.ccd_on() //開啟攝像頭

rbt.jump(P1); //以 jump 方式移動至 P1 點
Thread.Sleep(100);
Bitmap Image = bsr.take_one_picture(exposure_time); //取像
}