《电子技术应用》
您所在的位置:首页 > 嵌入式技术 > 设计应用 > 基于ARM+Linux的直流伺服控制系统设计
基于ARM+Linux的直流伺服控制系统设计
来源:电子技术应用2012年第8期
张海波1,2,陈 涛1,王建立1,李洪文1,邓永停1,2
1.中国科学院长春光学精密机械与物理研究所,吉林 长春130033; 2.中国科学院研究生院,北京100039
摘要: 目前大多伺服控制系统依赖计算机实现,系统体积功耗大、成本高。针对此问题,以ARM9 S3C2440芯片和CPLD EPM570T144芯片为硬件平台,在嵌入式Linux操作系统下设计了直流伺服控制系统。ARM实现控制算法,得出控制量给CPLD ,CPLD主要用作控制接口扩展和信号处理。详细介绍了Linux设备驱动设计和伺服控制应用程序设计。实验结果证明,系统能够实现等速跟踪、位置跟踪和正弦跟踪等控制功能,并能实现复杂控制算法,以满足控制系统实时性和高速性要求。
中图分类号: TP23
文献标识码: B
文章编号: 0258-7998(2012)08-0033-04
DC-servo control system design based on ARM and Linux
Zhang Haibo1,2,Chen Tao1,Wang Jianli1,Li Hongwen1,Deng Yongting1,2
1.Changchun Institute of Optics, Fine Mechanics and Physics ,Chinese Academy of Sciences, Changchun 130033,China; 2.Graduate College of the Chinese Academy of Sciences, Beijing 100039,China
Abstract: As most servo control systems depend on computers and have large size and high cost at present, the DC-servo control system is designed in embedded Linux operating system based on ARM9 S3C2440 chip and CPLD EPM570T144 chip. ARM is used to achieve the control algorithm and give control data to CPLD.CPLD is basically used to extend control interface and process signals. The Linux device driver design and servo control program design are discussed in detail. The experiment result proves that the system has functions of constant velocity tracking, position tracking, sine tracking and etc. It can achieve complicated control algorithm and satisfy the requirement of high speed and real-time control of control system.
Key words : ARM9;embedded Linux;CPLD;Linux device driver;servo control

    随着数字信息技术的不断发展,人们对伺服控制系统的实时性、稳定性和复杂性的要求越来越高,单靠顺序结构的软件设计已经不容易满足上述要求。目前很多伺服控制系统的控制器采用PC/104结构或依赖上位计算机,根据实际的控制系统需要扩展相应的控制电路,使得系统体积大、成本高、可靠性不易保证,且用户交互性不好。嵌入式Linux操作系统由于具有代码开源、可移植性、软硬件可裁剪性、资源丰富及支持多种硬件平台和接口等特点,并且从2.6版本以后的Linux实时性有了很大的提高,正被越来越多地应用于伺服控制系统中。通过嵌入式Linux操作系统对控制系统的软硬件资源进行分配、调度、控制和协调,能够充分发挥控制系统的性能。ARM处理器以其体积小、低功耗、低成本、高性能、文档丰富及嵌入式软件多等优点而得到广泛的应用。因此,本文以ARM9CPLD为硬件平台,在嵌入式Linux操作系统下设计了直流伺服控制系统。

1 硬件平台
    系统原理框图[1]如图1所示。系统以ARM作为主控芯片,主要负责运行操作系统并实现控制算法、人机交互和多机通信等。CPLD EPM570T144主要负责从ARM接收数据,产生相应的PWM波;接收编码器输出信号,并对其进行处理,得到编码器的值,将其送给ARM,从而实现电机的闭环控制。CPLD和ARM之间通过地址总线(13根)、数据总线(16根)、控制总线(片选、读写使能信号等)与GPIO口(作为外部中断使用)连接,即CPLD类似于ARM的一个外部存储器(CPLD挂接在ARM的bank1存储空间上,地址空间为0x08000000~0x10000000),ARM和CPLD的数据交换类似于对存储器的读写操作。这种总线方式扩展,使得系统数据交换快速、操作简单。控制板通过JTAG、UART、USB和网口与上位机连接,在目标板和上位机之间建立交叉开发环境,可在控制板和上位机之间实现程序下载调试、文件传输和通信等,便于系统软件开发和调试。

2 CPLD程序设计
    CPLD程序分为电机辨向、四倍频、编码器脉冲计数、PWM波生成和总线数据读写5个模块,如图2所示。采用VHDL语言,依据自底向上设计的方法,以便于程序开发和移植。

    采用增量式编码器,需对编码器输出的ABZ码进行处理[2],经过辨向、倍频、计数后得到编码器值。ARM与CPLD之间通过双向总线交换数据,CPLD读取ARM写入数据总线的数据,产生对应的PWM波。当CPLD中的编码器值可读后,CPLD采用中断方式通知ARM,然后将编码器值写到数据总线上供ARM读取。由于CPLD与ARM的其他外设共用数据总线,所以在CPLD对总线进行操作时要特别注意,除了CPLD往总线上写数据外,其他时刻都应该将总线置为高阻态,以让出总线的使用权,否则其他外设(如网口、ADC接口等)会因CPLD一直占用总线而不能正常工作。
    CPLD应用计数法产生PWM波[3],CPLD时钟频率为100 MHz,设置PWM总计数值为8 000。CPLD根据ARM给定的0~8 000的计数值对时钟计数,产生两路反相的PWM波。为防止功率放大器的H桥同一侧上下同时导通,一般设置有3~5 μs的死区,本设计中设置为5 μs的死区。
3 设备驱动设计
3.1 设备驱动简介

    设备驱动是连接应用程序与硬件设备的桥梁,驱动程序为应用程序提供了接口函数,用户在应用程序中调用相应的接口函数便可实现对硬件设备的操作,因此,驱动程序的开发是嵌入式系统开发的关键环节。Linux设备驱动分为字符设备驱动、块设备驱动和网络设备驱动[4]。本文中控制板上移植了Linux2.6操作系统,该操作系统下需设计ARM读写CPLD的数据及对CPLD产生的中断信号响应的驱动,这一要求采用字符设备驱动来实现。应用程序通过系统调用对设备文件进行诸如read、write等操作时,系统调用通过设备文件的主设备号找到相应的设备驱动程序,然后读取设备驱动程序中初始化的file_operations结构体,获取相应操作(read/write等)对应的函数指针,接着把控制权交给该函数。因此,编写设备驱动程序的主要工作就是编写这些文件操作的接口函数,并填充file_operations的各个域。
3.2 设备驱动程序设计
    为便于开发和调试,设备驱动使用模块的方式动态加载到内核中去。加载模块的方式与以往的应用程序开发有很大的不同。以往在开发应用程序时都有一个main()函数作为程序的入口点,而在驱动开发时却没有main()函数,模块在调用insmod命令时被加载,此时的入口点为module_init()函数,在该函数中完成设备的注册、设备文件的创建和相关内存及寄存器的地址映射。同样,模块在调用rmmod命令时被卸载,此时的入口点为module_exit()函数,在该函数中将不用的资源返还给操作系统,把注册的设备、创建的设备文件及IO内存映射等注销掉。在设备完成注册和加载之后,用户的应用程序就可以对该设备进行一定的操作,如read、write等。而驱动就是用于实现这些操作,在用户应用程序调用相应入口函数时执行相关的操作,module_init()入口点函数则不需要完成其他如read、wirte之类的功能。驱动程序需要定义和实现open、read、write等函数,并填充到file_operations结构中,file_operations结构把应用程序中的系统调用与驱动中对应的函数联系在一起。file_operations结构体如下所示:
static struct  file_operations    cpld_drv_fops = {
    .owner    = THIS_MODULE,
    .write    = cpld_drv_write,
    .read    = cpld_drv_read,
    .open    = cpld_drv_open,
    .release    = cpld_drv_close,
    .fasync    = cpld_drv_fasync,
};
其中,write()函数实现向CPLD中写入数据,read()函数实现ARM从CPLD读取数据。设备驱动运行在内核空间,而应用程序运行在用户空间,设备驱动程序不能直接访问用户空间的地址,在read()和write()函数中分别调用内核函数copy_to_user()和copy_from_user()实现数据的转移。read函数实现读取CPLD中的编码器值,write函数实现将产生PWM波的计数值写入CPLD中,这两个函数实现了内核空间与用户空间的数据交换。从驱动程序结构看,驱动程序由三部分组成:结构体struct file_operations及其成员函数的实现、设备初始化module_init()和设备注销module_exit()。
    读写CPLD需要对内存进行读写操作[5]。CPLD产生的读中断信号连接到ARM的GPF1口,CPLD的使能信号由ARM的GPF0产生,因此需要配置相应的寄存器。驱动程序中需要对内存和寄存器进行操作,本操作系统下不能直接对内存和寄存器的物理地址进行操作,需先将相应的内存和寄存器的物理地址映射到内核的虚拟地址空间,通过对映射后的虚拟地址进行操作实现对寄存器和内存的操作。
    ARM对CPLD的读操作采用异步通知和内核中断方式[5]实现,这样可减少系统开支。首先在驱动的open()函数中调用request_irq()函数注册内核中断,并在内核中实现中断处理函数,在内核中断处理函数中调用kill_fasyn()函数给指定的应用程序发送信号,通知应用程序CPLD中的编码器值可读。当CPLD无可读中断产生时,将read()函数放入等待队列,主程序一直处于睡眠状态,而不是应用程序主动去调用read()函数来等待中断的产生,即采用异步通知方式,调用内核中的fasync_helper()函数来实现。当CPLD有可读中断产生时,在中断处理函数中通过kill_fasync()函数,向进程发送信号SIGIO,触发应用程序中signal声明的异步触发函数,使用POLL_IN表明有数值可以读取。另外,要注意,在进入中断服务程序后,首先通过中断自旋锁spin_lock_irq()关闭所有中断,以防止其他中断源中断kill_fasync的工作,在中断服务程序结束时,再通过spin_unlock_irq()打开中断。中断处理函数部分代码如下:
spinlock_t lock;
static irqreturn_t eint1_irq(int irq, void *dev_id)
//中断服务程序
{
    spin_lock_irq(&lock);//关闭中断
    kill_fasync (&eint1_async, SIGIO, POLL_IN);
//产生中断后,驱动向应用程序发送数据可读信号
    spin_unlock_irq(&lock);//开中断
    return IRQ_RETVAL(IRQ_HANDLED);
}
4 应用程序设计

 


    在应用程序[6]中,通过函数signal()注册信号处理函数,以接收内核发来的数据可读信号。为了打开设备文件的异步触发机制,用户程序需指定当前进程为内核发送信号的接收进程,可以通过fcntl系统调用的F_SETOWN命令来设置该值。用户程序还必须通过另一个fcntl命令设置设备的FASYNC标志,打开异步触发机制。只要内核中有CPLD可读中断产生,输入文件就会产生一个SIGIO信号,信号发送给应用程序,应用程序调用信号处理函数。在信号处理函数中读取编码器的值,通过控制算法得到控制数据(即PWM波计数值),然后将PWM波的计数值写入到CPLD中。主程序流程图如图3所示,部分代码如下:
int main(int argc, char **argv)
{
    int Oflags;
    signal(SIGIO, signal_fun);//注册信号处理函数
    Init(argc,argv);     //打开设备,控制参数初始化
    …
    fcntl(fd_cpld, F_SETOWN, getpid());    
//指定当前进程为接收信号进程
    Oflags=fcntl(fd_cpld, F_GETFL);//返回当前的信号标志
    fcntl(fd_cpld, F_SETFL, Oflags | FASYNC);
//打开异步触发机制
    while(1)
    {
        sleep(1000);//进程睡眠,等待内核发送中断信号
    }
    ……
    return 0;
}
    由于Linux是多任务系统,各个进程间采用一定的调度算法调度,进程间会不时地切换,因此编写程序时要特别考虑系统进程调度的问题。控制程序对实时性有一定的要求,因此,要将控制程序进程设置为实时进程且要具有较高的进程调度优先级,同时控制程序中要尽量少地使用系统调用,以保证控制系统的实时性。
5 实验结果
    控制板通过串口、网口与计算机(装有Linux系统)建立交叉编译环境,程序在计算机上编译调试。利用网线通过nfs(网络文件系统)服务,在计算机和控制板之间实现网络文件共享,可直接在控制板上访问计算机上的共享文件、执行计算机上编译好的程序,无需将计算机上编译好的程序下载到板子上。这种交叉开发的方式将程序和实验数据直接存储在计算机上,可节省控制板上的存储空间,便于程序开发和进行实验数据分析。
    实验过程中,首先要对电机参数进行辨识。电机参数辨识的方法[7-8]很多,本实验采用阶跃响应法测得电机的模型参数,近似为一阶惯性环节。编码器为增量式编码器,电机转一圈产生20 000个码,即一个码值对应0.018°,编码器值采样周期为2 ms。将电机一个采样周期内转过的角度值除以采样周期作为速度反馈值,将电机转过的角度进行累加得到位置反馈值,电机最高转速为900°/s,最低转速为9°/s,采用PI控制[9-10]。图4为系统速度阶跃响应曲线,速度响应误差为每1个采样周期1个码值。图5为系统位置阶跃曲线,设定速度环最大速度为180°/s。位置环采用抗积分饱和算法,以消除因积分饱和引起的过大的超调,位置阶跃稳态误差为0。图6是系统的速度正弦跟踪曲线,正弦引导函数为:v=180°sin(0.8πt),跟踪误差在正反转速度换向处跟踪误差较大。

    实验结果表明,基于ARM9和CPLD硬件平台,在嵌入式Linux操作系统下,系统能够实现等速跟踪、位置定点和正弦跟踪等功能,满足控制实时性要求,可实现伺服控制。系统体积小、成本低、功耗小、接口丰富、便于开发,且Linux系统具有很好的文件管理功能,有助于实验数据的存储和导出,便于实验结果分析。系统进一步完善后可将控制程序设计成图形界面,利用触摸屏输入和显示伺服控制结果,则可实现控制结果实时显示,可视化效果好,整个系统可脱离计算机工作,具有广泛的应用价值。
参考文献
[1] 李金洪,杨小军.基于DSP和FPGA的经纬仪控制系统设计[J].电子技术应用,2010,36(7):48-51.
[2] 钞靖,王小椿,姜虹.基于FPGA的光电编码器四倍频电路设计[J].仪表技术,2007(6):17-21.
[3] 耿伟松,于海东.基于CPLD的PWM发生器设计[J].制造业自动化,2010,32(6):151-153.
[4] 韦东山.嵌入式Linux应用开发完全手册[M].北京:人民邮电出版社,2008.
[5] 宋宝华.Linux设备驱动详解[M].北京:人民邮电出版社,2008.
[6] 孙程建.基于Linux的嵌入式数控系统底层软件设计[D].武汉:武汉科技大学,2007.
[7] 王帅,陈涛,李洪文,等.光电跟踪伺服系统的频率特性测试与模型辨识[J].光学精密工程,2009,17(1):78-83.
[8] 王伟国,陈涛,沈湘衡.直流伺服系统机械时间常熟测试方法的研究[J].仪器仪表学报,2005,26(8):66-70.
[9] 李洪文.基于内模PID控制的大型望远镜伺服系统[J].光学精密工程,2009(2):327-332.
[10] 刘金锟.先进PID控制及其MATLAB仿真[M].北京:电子工业出版社,2003.

此内容为AET网站原创,未经授权禁止转载。