ESM8000工控主板搭载了NXP i.MX8M Mini Quad 64位异构处理器,包含了一颗主频1.6GHz的四核ARM Cortex-A53和一颗主频400MHz 的ARM Cortex-M4。Linux系统在Cortex-A53核心上运行,对于一些实时性要求极高的应用,Linux系统可能无法满足对中断事件的及时响应,而且频繁的中断响应也会大大的降低操作系统性能。对这类应用场合就可充分利用i.MX8MM异构多核结构,由高性能的Cortex-A53(Linux系统)完成人机交互、数据处理、通讯管理等复杂运算,而对于实时的数据采集、高速的中断事件响应等实时任务交由Cotex-M4完成。
旋转编码器是工业领域最常见的传感器之一,通过对编码器输出的A/B脉冲信号个数及相位的识别,就可以得到精确的转速或位置信息。以欧姆龙的E6B2系列旋转编码器为例,当编码器分辨率200个脉冲/转,每分钟旋转3000转时,编码器输出脉冲频率为10KHz,如果将编码器分辨率提高到2000个脉冲/转,则编码器输出脉冲频率为100KHz。对于高分辨率旋转编码器的支持,通常需要SOC内部具有专门针对编码器硬件的硬件脉冲计数器,或通过独立的单片机来实现。
对于ESM8000工控主板,主CPU i.MX8MM内部没有专门的硬件脉冲计数器,但我们可充分利用ESM8000的异构CPU结构,由i.MX8MM内的Cortex-M4 来对编码器脉冲信号进行解析和计算,而Linux系统只需要直接从M4处获取计算结果即可。这样就将高速中断的响应和处理全部交给了M4,Linux系统几乎没有任何负载。我们在M4上运行了FreeRTOS操作系统,具有很高的实时性,根据实际测试可以满足同时两路100KHz频率的脉冲输入。在Linux侧设计了相应的驱动程序和提供相应的驱动程序API,为客户外接高分辨率旋转编码器提供了一种快速低成本的解决方案。
接口硬件说明
下面是欧姆龙旋转编码器E6B2-CWZ1X输出的脉冲信号,对于速度或位置监测,只需要接入A相和B相信号,如果选择接入A /B相,只需要在软件设置中将初始电平极性设置为1(高电平)即可。
上图的左边是A、B相在编码器顺时针方向旋转时的波形,其特点是A相脉冲超前B相脉冲90°相位。而图的右边是编码器逆时针旋转时的波形,此时B相超前A相90°相位。
ESM8000的GPIO仅支持3.3V TTL电平信号输入,旋转编码器的脉冲信号通常需要经过隔离及电平转换电路后,才能接入ESM8000的相应管脚。ESM8000支持两路旋转编码器对应的管脚如下:
编码器 | 编码器信号 | ESM8000管脚 | 简要说明 |
旋转编码器1 | GPIO18 | 支持最高100KHz脉冲输入3.3V TTL电平信号 | |
GPIO19 | |||
旋转编码器2 | GPIO20 | ||
GPIO21 |
接口软件说明
在ESM8000的Linux系统中,可以通过RPMsg和Crotex-M4进行通讯来获取相关的信息,关于RPMsg的介绍可以参考《ESM7000异构CPU实时应用之二基于rpmsg的通讯机制》。为了方便使用,英创公司以字符设备的方式提供了相应的驱动文件,加载后会在/dev目录下生成em_rpmsg_rot0和em_rpmsg_rot1两个设备节点,分别对应两路旋转编码器的硬件接口。在驱动中会通过RPMsg和Crotex-M4进行通信以及数据的处理,但对于用户来说是不需要关心的,直接使用标准的字符设备操作函数即可。驱动会将用户程序对设备的操作通过RPMsg发送给Crotex-M4,然后由Crotex-M4实际对硬件执行对应的操作,如下图所示:
驱动文件在系统启动完成后会自动加载,如下图:
可以看到在/dev目录下会生成相应的设备节点,按照字符设备的操作操作流程,首先需要调用open函数打开设备节点,成功后会就返回句柄:
int fd; fd = open("/dev/em_rpmsg_rot1", O_RDWR); if(fd < 0) { printf("open device failed!\n"); return fd; }
通过返回的句柄,就可以调用write和read函数来操作设备了,我们使用write函数用于设置旋转编码器的采集,我们一共定义了五种操作,分别是设置正极性,设置负极性,开始,停止以及复位。具体定义以及通过write函数设置的代码如下:
#define ROT_POL_NEGATIVE 0 //负极性,初始电平为低 #define ROT_POL_POSITIVE 1 //正极性,初始电平为高 #define ROT_START 2 //启动旋转编码器采集 #define ROT_RESET 3 //复位计数 #define ROT_STOP 4 //停止旋转编码器采集 int cmd; //设置负极性 cmd = ROT_POL_NEGATIVE; ret = write(fd, &cmd, sizeof(cmd)); if(ret < 0) { printf("write cmd failed!\n"); } //启动 cmd = ROT_START; ret = write(fd, &cmd, sizeof(cmd)); if(ret < 0) { printf("write cmd failed!\n"); }
当启动了旋转编码器之后,程序中可以通过read函数来读取当前的计数值,计数值为一个整型数据,正负代表方向。根据计数值,根据实际应用的不同就可以计算出位置,角度等数据。
int val; //读取计数值,计数值为一个整型数据,正负代表方向 ret = read(fd, &val, sizeof(int)); if(ret < 0) { printf("read cmd failed!\n"); } printf("val = %d\n", val);
本文中仅通过旋转编码器来获取位置信息,同样的方法也可用来实现对转速的监控,感兴趣的客户,可以和英创的工程师联系,索取完整的测试代码。
成都英创信息技术有限公司 028-8618 0660