工业机器人这块可以按配线 → 操作编程 → 通信程序来理解。下面用ABB / FANUC / KUKA / 汇川做主线,并补一套 C# 上位机通信示例。
1. 基本配线
机器人控制柜里通常有这几类线:
| 线路类型 | 作用 | 配线要点 |
|---|---|---|
| 动力电源 | 给控制柜、伺服供电 | AC 380V/220V 或 DC 24V,PE 必须可靠接地 |
| 电机动力线 | U/V/W 接伺服电机 | 用变频电缆,远离信号线,保持 ≥20cm 间距 |
| 编码器线 | 反馈位置、速度 | 屏蔽双绞,屏蔽层可靠接地,避免与动力线平行 |
| 数字 IO | 急停、安全门、夹爪、传感器 | 24V DI/DO,注意源型/漏型匹配 |
| 安全回路 | 急停、安全门、光幕 | 双通道常闭触点,严禁只用软件急停 |
| 通信线 | EtherCAT/Profinet/Modbus/TCP | 用屏蔽网线,金属接头,屏蔽层连续 |
急停/安全门接线要点
典型安全回路:
急停按钮 NC1 ──→ 安全回路 CH1 急停按钮 NC2 ──→ 安全回路 CH2 安全门 NC1 ──→ 安全回路 CH1 安全门 NC2 ──→ 安全回路 CH2 安全回路输出 ──→ 安全继电器/安全CPU ──→ 切断伺服使能关键规则:
- 急停、安全门、光幕都要用常闭触点。
- 必须双通道,不能只接一路。
- 安全回路不能和动力线、通信线混在同一线槽。
- 外部安全设备接入前,先确认控制器端子是否需要拆除短接片。
2. 基本操作与编程
2.1 坐标系
| 坐标系 | 含义 | 典型用途 |
|---|---|---|
| 关节坐标 | 逐轴运动 | 避障、回零、粗调姿态 |
| 世界/基坐标 | 固定空间坐标 | 通用定位 |
| 工具坐标 TCP | 以工具末端为原点 | 夹爪、吸盘、焊枪 |
| 工件坐标 | 以工装/托盘为原点 | 码垛、分拣、视觉补偿 |
TCP 标定错误会导致轨迹偏移、负载计算异常,甚至报警。
2.2 运动指令
| 运动类型 | 特点 | 适用场景 |
|---|---|---|
| 关节运动 | 各轴独立运动,路径不一定是直线 | 快速点到点 |
| 直线运动 | TCP 走直线 | 涂胶、搬运、取放 |
| 圆弧运动 | 三点定义圆弧 | 倒角、弧焊、曲线轨迹 |
ABB RAPID 示例:
MoveJ pHome, v1000, z50, toolGripper; MoveL pPick, v500, fine, toolGripper; SetDO doGripperClose, 1; WaitTime 0.3; MoveL pPlace, v800, fine, toolGripper; SetDO doGripperClose, 0;FANUC TP 示例:
J P[1:Home] 100% FINE ; L P[2:Pick] 500mm/sec FINE ; DO[1:Gripper]=ON ; WAIT 0.3(sec) ; L P[3:Place] 800mm/sec FINE ; DO[1:Gripper]=OFF ;KUKA KRL 示例:
PTP HOME Vel=100 % DEFAULT LIN Pick Vel=0.5 m/s CPDAT1 $OUT[1]=TRUE WAIT SEC 0.3 LIN Place Vel=0.8 m/s CPDAT2 $OUT[1]=FALSE3. 通信程序
机器人通信常见几类:
- TCP/IP Socket:通用,适合与上位机、视觉系统交换坐标、状态。
- Modbus TCP:适合与 PLC、夹爪、简单 IO 设备交互。
- EtherCAT / Profinet:适合产线实时联动,但通常需要控制器支持。
- 品牌 SDK:如 ABB PC SDK、FANUC FOCAS,适合深度二次开发。
3.1 通用 TCP 客户端
publicclassRobotTcpClient:IDisposable{privatereadonlyTcpClient_tcp;privatereadonlyNetworkStream_stream;privatereadonlybyte[]_buffer=newbyte[4096];publicRobotTcpClient(stringip,intport){_tcp=newTcpClient(ip,port);_stream=_tcp.GetStream();}publicvoidSend(stringmessage){byte[]data=Encoding.UTF8.GetBytes(message+"\n");_stream.Write(data,0,data.Length);}publicstringReceive(inttimeoutMs=1000){_stream.ReadTimeout=timeoutMs;intcount=_stream.Read(_buffer,0,_buffer.Length);returnEncoding.UTF8.GetString(_buffer,0,count);}publicvoidDispose(){_stream?.Dispose();_tcp?.Dispose();}}3.2 Modbus TCP 读写机器人 IO
usingModbus.Device;publicclassRobotModbusClient:IDisposable{privatereadonlyTcpClient_tcp;privatereadonlyModbusIpMaster_master;publicRobotModbusClient(stringip,intport=502,byteslaveId=1){_tcp=newTcpClient(ip,port);_master=ModbusIpMaster.CreateIp(_tcp);SlaveId=slaveId;}publicbyteSlaveId{get;}publicbool[]ReadCoils(ushortstart,ushortcount)=>_master.ReadCoils(SlaveId,start,count);publicvoidWriteCoil(ushortaddress,boolvalue)=>_master.WriteSingleCoil(SlaveId,address,value);publicushort[]ReadRegisters(ushortstart,ushortcount)=>_master.ReadHoldingRegisters(SlaveId,start,count);publicvoidDispose(){_master?.Dispose();_tcp?.Dispose();}}调用示例:
usingvarrobot=newRobotModbusClient("192.168.1.50");// 读取机器人 DI 状态bool[]inputs=robot.ReadCoils(0,8);// 控制夹爪robot.WriteCoil(10,true);// 夹紧robot.WriteCoil(10,false);// 松开3.3 产线联动建议
在分拣、搬运、视觉引导场景里,常见架构是:
视觉/上位机 ──TCP/Modbus──→ 机器人控制器 机器人 IO ──DI/DO──────→ PLC / 夹爪 / 传感器 安全回路 ──硬接线──────→ 急停 / 安全门 / 光幕上位机侧建议加上:
- 心跳检测;
- 断线重连;
- 超时报警;
- 指令应答机制;
- 机器人状态订阅。
4. 调试顺序
- 先确认机器人型号、控制器型号、通信选项。
- 检查电源、接地、急停、安全门。
- 用示教器点动,确认 TCP、工件坐标、负载数据正确。
- 单独测试 IO,确认夹爪、传感器、PLC 信号正常。
- 再做 TCP/Modbus 通信,先读后写。
- 最后接入视觉、PLC 和上位机联动流程。
如果你现在用的是ABB IRB、FANUC R-30iB、KUKA KR C4、汇川机器人其中一种,可以把具体型号、通信方式和要接的设备发出来,我可以按那个品牌把 IO 地址、坐标系设置和 C# 通信代码对齐成一套可直接调试的版本。
下面按配线 → 编程 → 通信补几组更贴近产线的案例,代码偏向可直接落到 C# 上位机里。
案例 1:ABB 搬运 + C# 视觉补偿
典型流程:视觉给坐标 → 上位机发偏移 → ABB 抓取 → 放置。
RAPID 程序:
MODULE MainModule VAR robtarget pHome; VAR robtarget pPick; VAR robtarget pPlace; VAR num gOffsetX := 0; VAR num gOffsetY := 0; VAR num gAngle := 0; PROC main() rInit; WHILE TRUE DO WaitDI diPartReady, 1; rGetVisionOffset; rPick; rPlace; ENDWHILE ENDPROC PROC rInit() MoveAbsJ jposHome, v1000, fine, toolGripper; Reset doGripper; ENDPROC PROC rGetVisionOffset() ! 上位机写入 D 寄存器或字符串,这里用字符串演示 ! 实际可用 PC Interface / Socket 接收 gOffsetX := StrToVal(gVisionData, "X"); gOffsetY := StrToVal(gVisionData, "Y"); gAngle := StrToVal(gVisionData, "A"); ENDPROC PROC rPick() MoveJ Offs(pPick, 0, 0, 200), v1000, z50, toolGripper; MoveL Offs(pPick, gOffsetX, gOffsetY, 0), v500, fine, toolGripper; Set doGripper; WaitTime 0.3; MoveL Offs(pPick, gOffsetX, gOffsetY, 100), v800, z30, toolGripper; ENDPROC PROC rPlace() MoveJ Offs(pPlace, 0, 0, 200), v1000, z50, toolGripper; MoveL pPlace, v500, fine, toolGripper; Reset doGripper; WaitTime 0.3; MoveL Offs(pPlace, 0, 0, 100), v800, z30, toolGripper; ENDPROC ENDMODULEC# 上位机侧可以用 Socket 或 ABB PC SDK 发送偏移量。
publicclassAbbVisionHelper{privatereadonlyTcpClient_tcp;privatereadonlyNetworkStream_stream;publicAbbVisionHelper(stringip,intport){_tcp=newTcpClient(ip,port);_stream=_tcp.GetStream();}publicvoidSendVisionOffset(doublex,doubley,doubleangle){stringmsg=$"VISION,{x:F2},{y:F2},{angle:F2}\r\n";byte[]data=Encoding.UTF8.GetBytes(msg);_stream.Write(data,0,data.Length);}publicvoidDispose(){_stream?.Dispose();_tcp?.Dispose();}}案例 2:FANUC 码垛 + 循环偏移
FANUC 码垛常用FOR循环和PR[]位置寄存器。
:LBL[1:MAIN] ; :CALL UFRAME_FIXTURE ; :CALL UTOOL_GRIPPER ; :J P[HOME] 100% FINE ; :FOR R[1]=1 TO 3 ; : FOR R[2]=1 TO 4 ; : CALL PICK ; : CALL PLACE(R[1],R[2]) ; : ENDFOR ; :ENDFOR ; :J P[HOME] 100% FINE ; :END ;子程序:
:LBL[100:PICK] ; :J P[APPROACH] 80% CNT100 ; :L P[PICK_POS] 200mm/sec FINE ; :DO[1:GRIPPER]=ON ; :WAIT 0.5(sec) ; :L P[APPROACH] 300mm/sec FINE ; :END ;放置子程序:
:LBL[200:PLACE] ; :PR[10:OFFSET].X=(R[2]-1)*100 ; :PR[10:OFFSET].Y=(R[1]-1)*80 ; :PR[10:OFFSET].Z=0 ; :L PR[10] 200mm/sec FINE Tool_Offset ; :DO[1:GRIPPER]=OFF ; :WAIT 0.3(sec) ; :L P[APPROACH] 300mm/sec FINE ; :END ;案例 3:KUKA 点位监控 + 文件交互
KUKA 常用ETHERNETKRL做 TCP 通信。控制器侧配置示例:
<ETHERNETKRL><CONFIGURATION><EXTERNAL><IP>192.168.1.20</IP><PORT>59152</PORT></EXTERNAL></CONFIGURATION><RECEIVE><RAW><ELEMENTTag="Cmd"Type="STRING"/></RAW></RECEIVE><SEND><RAW><ELEMENTTag="State"Type="STRING"/></RAW></SEND></ETHERNETKRL>KRL 主程序:
DEF MAIN() $OUT[1]=FALSE LOOP IF $IN[1]==TRUE THEN PTP HOME LIN P1 $OUT[1]=TRUE WAIT SEC 0.5 $OUT[1]=FALSE ENDIF ENDLOOP ENDC# 侧读取点位:
publicclassKukaTcpClient:IDisposable{privatereadonlyTcpClient_tcp;privatereadonlyNetworkStream_stream;publicKukaTcpClient(stringip,intport=59152){_tcp=newTcpClient(ip,port);_stream=_tcp.GetStream();}publicvoidSendCommand(stringcmd){byte[]data=Encoding.UTF8.GetBytes(cmd+"\r\n");_stream.Write(data,0,data.Length);}publicstringReceive(inttimeoutMs=1000){_stream.ReadTimeout=timeoutMs;byte[]buf=newbyte[1024];intn=_stream.Read(buf,0,buf.Length);returnEncoding.UTF8.GetString(buf,0,n);}publicvoidDispose(){_stream?.Dispose();_tcp?.Dispose();}}案例 4:机器人 + PLC + 上位机联动
产线里常见结构:
视觉/上位机 ──TCP/Modbus──→ 机器人 机器人 IO ──DI/DO──────→ PLC PLC ──Modbus/MC──→ 上位机 安全回路 ──硬接线──────→ 急停/光幕C# 侧可以封装一个简单调度器:
publicclassRobotWorkCell{privatereadonlyRobotTcpClient_robot;privatereadonlyPlcModbusTcpClient_plc;publicRobotWorkCell(RobotTcpClientrobot,PlcModbusTcpClientplc){_robot=robot;_plc=plc;}publicboolIsReady(){bool[]inputs=_plc.ReadCoils(0,1);returninputs.Length>0&&inputs[0];}publicvoidStartPickAndPlace(doublex,doubley){_robot.Send($"PICK,{x:F2},{y:F2}\n");}publicintGetCycleCount(){ushort[]v=_plc.ReadRegisters(200,1);returnv.Length>0?v[0]:0;}}案例 5:带心跳和重连的机器人客户端
工业现场不建议只用裸TcpClient,至少要处理假连接、超时和重连。
publicclassReliableRobotClient:IDisposable{privateTcpClient_tcp;privateNetworkStream_stream;privatereadonlystring_ip;privatereadonlyint_port;privatereadonlyint_reconnectMs;privateTimer_heartbeatTimer;publicboolIsConnected=>_tcp!=null&&_tcp.Connected;publicReliableRobotClient(stringip,intport,intreconnectMs=3000){_ip=ip;_port=port;_reconnectMs=reconnectMs;}publicvoidStart(){Connect();_heartbeatTimer=newTimer(_=>Heartbeat(),null,2000,2000);}privatevoidConnect(){try{_tcp=newTcpClient(_ip,_port);_stream=_tcp.GetStream();}catch{Task.Delay(_reconnectMs).ContinueWith(_=>Connect());}}publicvoidSend(stringmessage){if(_stream==null)return;byte[]data=Encoding.UTF8.GetBytes(message+"\n");_stream.Write(data,0,data.Length);}privatevoidHeartbeat(){if(!IsConnected){Connect();}else{Send("HEARTBEAT\n");}}publicvoidDispose(){_heartbeatTimer?.Dispose();_stream?.Dispose();_tcp?.Dispose();}}调试顺序
- 先确认机器人型号、控制器型号、通信选项、IP/端口。
- 检查电源、接地、急停、安全门、夹爪 IO。
- 用示教器跑单步程序,确认 TCP、工件坐标、负载正确。
- 单独测试 DI/DO,确认夹爪、传感器、PLC 信号正常。
- 上位机先做只读监控,确认协议、心跳、超时正常。
- 再加入坐标下发、启动/停止、报警复位、产量统计。
如果你把具体机器人型号发出来,比如ABB IRB-1200、FANUC LR Mate、KUKA KR AGILUS、汇川机器人,我可以把 RAPID/TP/KRL 程序、IO 地址和 C# 通信类对齐成一套可直接调试的版本。