EC机器人第三方力控使用

2025-09-08

1.简介

在当前开发的力控模式中,机器人末端装有六维力传感器,用于检测外界环境对机器人施加的力度,配合适当的控制策略,可以达到调整机器人期望的运行轨迹和外界接触力的目的。该模式目前主要应用于曲面打磨、轴孔装配等工艺。 使用该模式需要首先完成以下三个步骤:

(a) 传感器的安装与配置

(b) 传感器标定

(c) 负载辨识

在进行上述操作前,请务必按照传感器的要求进行预热,具体步骤如下文所示。

2.力传感器的安装与配置

机器人版本建议3.9.2以上,机械臂末端工具IO版本需要更新至v8.2.727及以上的版本。

末端工具IO版本查看方法:

依次查看0002,0003,0004分别有数字,如0002:8,0003:2,0004:1209则此末端工具 IO版本为 V8.2.1209

2.1安装

对传感器的安装无特定要求(尽量与工具坐标系保持一致),但在传感器安装完成后,用户需要在传感器的 参数设置界面进行一些设置,具体的内容如下所示。

2.2接线

力传感器的线可直接接在末端IO上,下图是末端IO的对应的针脚。力传感器通常需要接线24V,0V,RS485+,RS485-。


2.3参数配置

2.3.1 工艺配置

运行准备-工艺配置-勾选末端IO-设置,重启后生效(注意:不要勾选末端力矩传感器)。

2.3.2 力控模式配置

扩展-力控模式配置-选择LUA数据源-设置数据间隔和容差-点击设置 。

注:用户可根据需求设置“数据间隔”和“容差”,数据间隔表示数据输入周期,单位为 ms,建议将数据间隔与容差的乘积设置为1000,请注意当输入力/力矩数据时,若其间隔时间 超过容差乘以数据间隔时,系统将会报错。

2.3.3 传感器参数设置

扩展-力控模式配置-传感器参数-输入参数后-点击设置

注:1.所选单位必须与传感器的单位保持一致

2.  若有转接板,则此处传感器的厚度包含转接板的厚度,质量也包含转接板的质量

3.  安装方式:传感器坐标系和法兰坐标系只相差一个Z向旋转角度称为正装

4.  查找传感器手册,确定传感器Z轴方向,和X轴Y轴方向,保证传感器方向和法兰坐标系一致


2.3.4 力控参数设置

扩展-力控模式配置-力控参数-输入参数-点击设置。

注:该功能用于调节力跟踪的灵敏度。需要注意的是,力跟踪数值设置的越大,装配的负 载就越大,机器人会出现明显的抖动。

以上步骤完成后,可以点击监视-力控传感器数据,若以上步骤都正确,则传感 器数据在不断变化,可施加不同方向的力,看力的方向是否和法兰坐标系一致, 后续的步骤可参考用户手册_3.10.2力控功能章节进行传感器标定,负载辨识及负载惯量辨识。设置完成后即可正常使用。

3.传感器标定

参考用户手册6.5.9.2传感器标定章节

5.负载辨识

参考用户手册6.5.9.3负载辨识章节

6.负载惯量辨识

参考用户手册6.5.9.4负载惯量辨识章节

7.  编程(通过lua读取传感器数据)

机器人与力传感器之间通过RS485通讯来读取传感器数据,按照指定格式解析,并写入控 制器中。可参考下方脚本,下方脚本是鑫金诚的传感器,如需适配其它品牌传感器,可按照这个脚本编写。


function str2hex(str)

   --判断输入类型

   if (type(str) ~= "string") then

       return nil, "str2hex invalid input type"

   end

   --滤掉分隔符

   str = str:gsub("[%s%p]", ""):upper()

   --检查内容是否合法

   if (str:find("[^0-9A-Fa-f]") ~= nil) then

       return nil, "str2hex invalid input content"

   end

   --检查字符串长度

   if (str:len() % 2 ~= 0) then

       return nil, "str2hex invalid input lenth"

   end

   --拼接字符串

   local index = 1

   local ret = ""

   for index = 1, str:len(), 2 do

       ret = ret .. string.char(tonumber(str:sub(index, index + 1), 16))

   end


   return ret

end


--[[

-- extract_nice_frame: 从raw_data中返回符合要求的数据帧

-- return: 若无有效数据返回nil, 否则返回完整的一帧数据

--]]

function extract_nice_frame(raw_data)

   local begin_idx, end_idx, valid_data

   local len = string.len(raw_data)

   local actual_frame_len = FRAME_LEN * 2  -- FRAME_LEN * 2 代表16进制数据转换成ASCII后的长度


   if len <  actual_frame_len then     -- 先判断字符长度是否满足

       --elite_print("recv wrong data len: "..len)

       return nil

   end


   if (FRAME_END) then -- 一帧数据包含固定帧尾的情况

       begin_idx, end_idx = string.find(raw_data, FRAME_BEGIN..'.*'..FRAME_END, 1, false)  --string.find 会匹配满足要求的最长字串

       if (not begin_idx or not end_idx) then

           return nil

       elseif (end_idx - begin_idx == actual_frame_len - 1) then -- 正好符合帧的格式,这是大多数情况

           valid_data = string.sub(recv_buff, begin_idx, begin_idx + actual_frame_len -1)

           return valid_data

       elseif (end_idx - begin_idx > actual_frame_len - 1) then

           local idx1,idx2

           idx1 = begin_idx

           repeat

               -- 比较帧最后的字符是否为帧尾

               local sub_star_idx = idx1 + actual_frame_len - string.len(FRAME_END)

               local sub_end_idx = sub_star_idx + string.len(FRAME_END) - 1

               local tmp_tail = string.sub(raw_data, sub_star_idx, sub_end_idx)

               if (tmp_tail == FRAME_END) then

                   valid_data = string.sub(raw_data, idx1, idx1 + actual_frame_len -1)

                   return valid_data

               end


               idx1, idx2 = string.find(raw_data, FRAME_BEGIN, idx1 + string.len(FRAME_BEGIN))

           until(not idx1)

           return nil

       end

   else -- 没有固定帧尾的情况

       begin_idx, end_idx = string.find(raw_data, FRAME_BEGIN)

       if (begin_idx and end_idx and begin_idx <= len - actual_frame_len) then

           local idx1,idx2 = string.find(raw_data, FRAME_BEGIN, end_idx + 1)

           if (not idx1 or idx1 > len - actual_frame_len) then  -- 没固定帧尾时,这两种条件下截取的一定是有效帧

               valid_data = string.sub(recv_buff, begin_idx, begin_idx + actual_frame_len -1)

               return valid_data

           end

       else

           return nil

       end

   end

   return nil

end

---------------------------End of Internal Function--------------------------


-------------------------- User Config First---------------------------------

--  脚本运行前请先配置下面的基本参数

FRAME_LEN = 16 -- 传感器发送的一帧数据帧的长度,单位:字节

FRAME_BEGIN = "204E" -- 数据帧的帧头标识,此处以鑫精诚sensor为例,如果是坤为sensor填入"48AA"

FRAME_END = nil -- 数据帧的帧尾标识, 如果没有帧尾请填入nil,此处以鑫精诚sensor为例.如果是坤为sensor填入"0D0A"

FRAME_MAX_RECV_TM = 40 -- 串口每次接收等待的最大时间,unit: ms


SERIAL_speed = 115200 -- 串口波特率

SERIAL_bits = 8 -- 串口传输数据位

SERIAL_event = "N" -- 串口传输停止位

SERIAL_stop = 1 -- 串口传输停止位

TCIorController = 2 -- 1使用末端Tci, 2使用控制柜485接口

-------------------------- End of User Config First -------------------------


-- 用户变量

Control_script = "D0" --控制脚本运行

SCRIPT_MODE = "D1" --将脚本指令写入到传感器1:停止持续传输数据

FX = "D2" --传感器参数

FY = "D3" --传感器参数

FZ = "D4" --传感器参数

MX = "D5" --传感器参数

MY = "D6" --传感器参数

MZ = "D7" --传感器参数

ID = "D8" --传感器地址


---------------------------Script start------------------------------------

frame_idx = 0

torque = {0, 0, 0, 0, 0, 0}

err_tm = 0

stop_push_force()

if (TCIorController == 1) then

   tci_close()

end

if (TCIorController == 2) then

   rs485_close()

end


sleep(0.5)

if (TCIorController == 1) then

   open = tci_open()

end

if (TCIorController == 2) then

   open = rs485_open()

end


if (open >= 0) then

   if (TCIorController == 1) then

       tci_setopt(SERIAL_speed, SERIAL_bits, SERIAL_event, SERIAL_stop)

   end

   if (TCIorController == 2) then

       rs485_setopt(SERIAL_speed, SERIAL_bits, SERIAL_event, SERIAL_stop)

   end

else

   elite_print("串口打开失败!")

   exit() -- 并没有exit函数,只是为了让系统报错,脚本退出执行

end

sensor_init() -- User implement

start_push_force()

last_tm = os.clock()


-------------------------------main loop-------------------------------------------------------

repeat

   now_tm = os.clock()

   if TCIorController==1 then

       ret, recv_buff = tci_recv(FRAME_MAX_RECV_TM, 1, FRAME_LEN * 2) --接收2帧长度的数据,确保有一帧为有效数据

   end

   if TCIorController ==2 then

       ret,recv_buff = rs485_recv(FRAME_MAX_RECV_TM, 1, FRAME_LEN * 2) --接收2帧长度的数据,确保有一帧为有效数据

   end


     valid_frame = extract_nice_frame(recv_buff)

   --elite_print("valid_frame : ",valid_frame)


   if (valid_frame) then

       torque = convert_str_to_torque_array(valid_frame) -- User implement

       last_tm = now_tm

   else

       torque = {0, 0, 0, 0, 0, 0}

       err_tm = now_tm - last_tm -- 计算传感器数据异常的持继时间

       set_global_variable("D9", err_tm)

   end


   push_external_force(frame_idx, torque)

   tci_flush()

   frame_idx = frame_idx + 1

   if frame_idx >= 65535 then

       frame_idx = 1

   end


   sleep(0.001)

until (get_global_variable("D0") == 0)


stop_push_force()

if TCIorController==1 then

   tci_close()

end

if TCIorController==2 then

   rs485_close()

end



注:力传感器要改为连续发出数据模式。


download-669.svg comicon14.svg

电话咨询

download-397.svg comicon15.svg

免费试用

Vector.svg Frame.svg

微信小程序

img1.jpg

微信小程序

准备好突破增长瓶颈,开启智能制造了吗?
了解我们的机器人如何帮助您的业务增长
欢迎下载艾利特机器人资料

我已阅读并同意艾利特《隐私政策》《法律声明》

我已知晓并同意艾利特通过电子邮件发送相关资料

提交