博世力士乐控制器在移动机器人中的应用

前言

  提起博世力士乐(bosch rexroth),大家可能更熟悉它的液压元器件或者电子控制单元。随着技术的进步和新的需求,博世力士乐也在向机器人方向扩展。

1 简介

  我们使用的博世力士乐控制器是RC系列,具体型号是RC28-14/30(FLASH版),控制器的外形如下图所示。外壳是铸铝,端口接线通过防水的密封连接器引出。看它长的严严实实的就知道是给经常干脏活的移动机械设计的。
  您可能会问,它与普通的工业PLC相比有什么特点呢?它的一大优点是防护等级高,防水防尘,而且不需要扩展模块就能接受电流、电压、电阻输入,电流、电压、脉冲PWM输出,不用买信号调理模块,这对于液压控制是一大福音。但是它也有缺点,比如支持的通信方式有点少。有多么少呢?它只有CAN接口,是的,像常用的RS232、485、以太网统统没有(有些型号有RS232,但仅用于下载程序)。另外,这款控制器出货量肯定和PLC没法比,属于小众产品,所以编程软件相对来说不是那么强大易用,网上的技术资料也非常匮乏,而且基本上都是英文的。

  

  简单介绍一下这款控制器的基本组成,如下图所示。由英飞凌TriCore™ TC1797 32位芯片和内存等组成的硬件之上运行着一个微型嵌入式操作系统,操作系统提供一些硬件抽象API给上面的运行时系统(相当于软PLC),编程上位机通过CAN总线以KWP2000协议的格式将用户的程序下载到运行时系统中执行。

  TC1797芯片上有三个核,一个MCU控制核、一个DSP数字处理核、一个RISC控制核。所以,这款控制器的浮点数值计算应该还可以,能运行一些简单的算法。在数据存储方面,有4MB的pFlash用来存储程序代码,有64kByte的dFlash用来存储非易失数据,还有32kByte的外部EEPROM。

2 接线

  控制器供电的电压是DC12或者24V。供电必须接的线是:202、240、245。202接电源负极,240、245接正极。245和258接任何一个都行。接了这三根线,你就能向控制器下载运行程序了。如果你要让控制器带动负载,那还要接201。

  这个控制器一共有4个CAN通信口,默认的程序下载口是第一个,即CAN1。所以我们要接CAN1的两个端子,也就是215和216,如下图。因为控制器只有CAN口没有其它通信口,所以我们下载程序要通过CAN口,而电脑只有USB接口。所以我们需要一个CAN转USB的转换器。但是,不是所有厂家的转换器都可以用,博世力士乐控制器只支持德国的PEAK、Vector、Sontheim等厂家的,所以国产的肯定用不了了。

   

  笔者使用的是PEAK的PCAN-USB,如下图。这么个小东西要3000多块,好贵啊。215端子是高电平因此接PCAN-USB的7号口。上图中间并联的120欧姆电阻是防干扰的,如果不用也可以。

 

  PCAN-USB插入电脑是自动识别的,如果没有识别可以安装驱动程序,在这里下载。如果PCAN-USB的驱动安装正常,控制器接线也正常的话,打开PCAN-USB的上位机PcanView后可以看到控制器,如下图。PcanView也是在这里下载。控制器的CAN1波特率总是250kb/s,因此注意PcanView中的波特率设置要一样。

3 程序下载

3.1 编程工具BODAS-design

  接好线后我们就可以开始写程序了。博世力士乐控制器支持两种编程语言,一种是PLC领域用的IEC 61131-3语言(例如梯形图、ST),一种是计算机领域用的C语言。如果选择PLC编程语言,可以使用博世力士乐免费提供的BODAS-design 3.0软件进行程序开发。如果选择C语言,那要使用TriCore development suite编译器,编辑器推荐使用Eclipse,程序下载软件使用BODAS-service。
  BODAS-design软件其实就是深度定制的Codesys,版本还是老旧的2.3版本。现在Codesys最新版都到了3.5版本了,所以后面博世力士乐估计是不打算升级BODAS-design了。BODAS-design的界面长下面这样。没错,它不仅长得丑,使用起来也相当难用,不支持指令自动补全、查看引用跳转等便利的操作,而且界面不能自定义,是我用过的最傻最丑的开发软件之一。所以各位高手如果您有能力还是自己开发控制器和上位机吧。

3.2 电脑连接控制器

  在BODAS-design 3.0软件中,点击Online—Communication Parameters,出现以下面板。Interface选择你使用的CAN工具,以PEAK厂家的CAN-USB工具为例。CAN Timeout可以设置小一点,让扫描速度更快,这里设为100毫秒。控制器默认的波特率是250K。

 

  配置好后,点Scan就会开始扫描控制器,如下图。过一会就会扫到控制器,扫到后会在弹出的窗口中显示控制器的信息,如下图(如果看不到用鼠标点一下图中的红色箭头所指的地方)。与控制器标签上的序列号对比就知道是不是对应的。

3.4 程序下载

  写好程序后按快捷键F11开始编译程序,程序编译无误后,按快捷键Alt+F8或者点击Login下载程序,此时会弹出一个确认下载的窗口,过一会就会下载完毕。然后再按F5或者点击Run,程序就开始运行了,此时我们可以在BODAS-design中监视程序运行过程中变量的实时值。

3.5 帮助文档

  想要了解控制器的编程方式,官方提供了一个比较基本的例子模板,在这里:C:\Program Files (x86)\Bosch Rexroth\BODAS-design 3.0.17\Projects\Boschrexroth_Templates\RC28-14_Family_series_30_Target_V1.0。如果你是第一次接触博世力士乐的控制器,那么可能还是看不懂,因为这款控制器的很多功能是通过厂家自定义的函数实现的,这时就必须查阅帮助文档了,主要的文档在这里C:\Program Files (x86)\Common Files\CAA-Targets\RC28-14_30_Family_FLASH_V1.5\HelpCAA-Merger-3.chm。还有关于Codesys的标准文档:在BODAS-design里按F1就会出现,如下图。其中只有第二部分是与控制器有关的,其它的都是普通的Codesys介绍。

4 程序开发

4.1 特点

  虽然博世力士乐控制器的编程语言和操作方式继承了Codesys,但是还是有些地方不一样。首先,在帮助文档中提到,PLC_PRG程序块只应该被用来初始化。但是在Codesys中,PLC_PRG可以执行任何循环任务。

4.2 任务

  我们首先复习一下codesys编程中的基本概念。“任务”(Task)是完成一些具体功能的程序,例如处理数据的计算任务、发送接收数据的通信任务等等。用户想实现的功能都体现为一个个的任务,围绕这些任务可以再拆分为一些更基础的函数(一般是FB或者FC类型),任务一般是PRG类型。与函数(例如FB或者FC)相比,任务是可以相互之间并行执行或者调用的。FB或者FC也可以相互调用,但是它们都是供任务使用的。熟悉计算机的同学应该知道,任务就相当于进程。
  任务可以是循环执行的,这时由控制器定时器周期性的触发。当然任务也可以是由事件触发的。我们假设用户的任务是按照固定的时间间隔周期执行的,毕竟这是最常用的任务运行方式。博世力士乐控制器对执行周期有一定要求,执行周期的范围是1ms~90ms,如果你非要定义成100ms那么在编译时也不会报错,但是这个任务不会被执行,要注意这一点。另外,用户最多能定义20个任务,再多就不行了。好,知道这些我们就可以开始编程了。

4.3 标准程序组成

  博世力士乐为自家的控制器定义了一些“规章制度”和专用函数,所以在博世力士乐控制器中,一个标准的程序组成是下面这样的,与传统的codesys不一样,我们依据模板照猫画虎即可。
  ① 首先,调用sys_init函数进行控制器初始化。这一步是强制的,也就是说用户要想用控制器这一步必须要做。这一步就是设置控制器的软硬件类型,照着模板做即可,如下。sys_init函数只能在PLC_PRG中调用;

stSysInit_u16:UINT;                                      (* State of Sys_init(...) *)
SW_Name_as8:STRING(32) := 'Template RC28-14 family';  (* Software Name *)
HW_Name_as8:STRING(32) := 'RC30-00D6';                 (* Hardware Name *)
stSysInit_u16 := sys_init(ADR(SW_Name_as8), ADR(HW_Name_as8));

  ② 然后用户实现自己的任务程序(PRG类型),假设它叫MAIN_Task吧。
  ③ 然后调用sys_registerTask函数注册MAIN_Task任务,这个函数的作用是让控制器以我们设定的时间周期和优先级执行这个任务。CYCLE_D就是任务的运行周期,取值范围是1~90,MAIN_TASK_PRIO_D是任务优先级,取值范围是0~126,数越大优先级越高。我们知道在Codesys中,PRG类型的程序块是允许被其它程序块调用的,那么这里大家可能就会疑惑了,为什么还要用sys_registerTask函数去注册它呢?如果用户希望一个任务(例如上面的MAIN_Task)以独立的方式和固定周期运行,那就要用sys_registerTask函数。假设你的任务只被另一个任务调用而自己不单独运行,即使它是PRG类型的,那么也不需要用sys_registerTask函数注册,直接在其它任务中调用它即可。对于后面一种情况,如果你非要多此一举用sys_registerTask函数注册它,那编译器也不会报错,但是注意你相当于在PLC_PRG里以可能另一种周期启动了它(在本该调用的地方之外又错误的调用了),这时程序计算的结果可能就不对了。所以,注意区分哪些程序是自己循环执行的,哪些程序是以为被别人调用才执行的,只有前者才需要注册;

stMAIN_Task_u16 := sys_registerTask(INDEXOF(MAIN_Task),
                                            MAIN_TASK_PRIO_D,
                                            CYCLE_D,
                                            0,
                                            ADR(MAIN_Task_Handle_u8));

  ④ 然后在PLC_PRG中调用sys_initTC函数初始化trigger check point。这个trigger check point可以翻译成触发检查点。设置这个检查点的目的是让控制器监视我们的任务是不是真的按照我们设置的周期在运行。如果不理解,帮助文档中举了一个例子,搜索sys_initTC函数可以找到。这个常规操作我们照着做即可。sys_initTC函数与sys_triggerTC函数配合使用,sys_initTC函数只能放在PLC_PRG中,sys_triggerTC函数则要放在用户的任务程序中。在用户的整个项目中,至少要放置一个检查点,如果一个都没有编译就会报错。另外,sys_triggerTC函数要放在循环能执行的地方,如果你放在初始化里,只能执行一次那也是不对的;
  ⑤ 最后调用diag_setVarsCallBacksys_setVSS等函数从EEPROM中读配置、设置引脚等;

4.4 输入输出

  该控制器支持的输入输出类型非常丰富。在帮助文档CAA-Merger-3.chm中,搜索in或者out可以查看输入输出端口的类型。

  输入分为以下几种,其中,IN表示输入端口,x表示端口编号,例如IN_3_DI,剩下的几个字母中,F表示频率输入、D表示数字量输入、A表示模拟量输入。
  IN_x_DI:表示数字量输入
  IN_x_AI:表示模拟量输入
  N_x_AIV:表示模拟电压输入
  N_x_AIC:表示模拟电流输入
  IN_x_FI:表示频率输入

  输出分为以下几种,其中,OUT表示输出端口,x表示端口编号,例如OUT_3_POH,剩下的几个字母中,P表示PWM输出、D表示数字量输出、A表示模拟量输出;
  OUT_x_DOH:表示数字量输出
  OUT_x_POH:表示PWM输出高阻 Proportional (PWM) high side output stage
  OUT_x_POH_CL:表示带闭环的PWM输出,CL表示Closed Loop,闭环的意思是指控制器内部对输出PWM电流的闭环控制,使其不受外界影响,始终保持与给定值一致;
  OUT_x_AOC:表示电流模拟量输出
  OUT_x_AOV:表示电压模拟量输出

4.5 CAN通信设置

  CAN通信的使用包括以下几个步骤:
  ① 首先,使用can_init函数初始化CAN口,比如下面的例子。其中,输入参数CAN_1表示第一个CAN口(注意是从1开始,不是从0开始的),第二个参数BAUD_250K表示设置这个CAN口的波特率为250K。

can_init(CAN_1, BAUD_250K);

  ② 然后配置帧头和邮箱数量,如下。2表示使用2个邮箱,最多能使用20个,16#100表示帧头Id(16进制),CAN_STD_DU8表示标准帧,如果想用扩展帧输入CAN_EXD_DU8。这些初始化的工作只需要执行一次即可,所以可以放在PLC_PRG里;

can_cfgTxDatabox(CAN_1, 2, 16#100, CAN_STD_DU8);

  ③ 到此为止就完成初始化了,然后我们就能接收和发送CAN消息了。接收消息的例子如下。第二个参数3表示使用3个邮箱,DataboxData_au8是接收到的消息数据存放的位置,是一个8个byte的数组,最后一个参数不用管;发送消息使用can_sendDatabox函数,其格式与接收函数一样,不再举例了;

can_getDatabox(CAN_1, 3, ADR(DataboxData_au8[1]), ADR(DataboxNumBytes_u8))
4.6 codesys函数
4.6.1 获取系统时间

  先介绍基础函数。首先是获取控制器时间的函数Time。使用方法是首先在局部变量区定义时间类型的变量tx:=TIME,如下图左。不管什么控制器,内部肯定有一个硬件定时器,我们在程序块中使用Time()函数即可得到定时器提供的时间,如下图右。可见Time()函数获取的是控制器从上电启动开始到现在的时刻所经过的时间,单位是“时/分/秒/毫秒”,最小时间分辨率是毫秒,无法达到微秒级精确度。

 

  但是有时我们想使用计数形式的时间,这时可以使用TIME_TO_DWORD函数将时间转换成整数,如下图所示,每过1毫秒加1。你要是想按秒计数除以1000即可。DWORD是32位整数类型,最大可表示数值是4294967295。最后,这其实就是OSCAT库中的T_PLC_MS函数,只不过是把Time()函数包装了一下,然后提供整数接口,没什么神奇的。

5 机器人软件

  最近,博世力士乐推出了移动机器人的定位软件套件:ROKIT Locator。其实就是二维的激光SLAM软件。这个技术现在已经比较成熟了。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注