艾 红,钱运锴
(北京信息科技大学自动化学院,北京 100192)
采集生产过程的实时数据进行监控和监测是科学管理生产的重要基础。如果生产过程分布范围不大,可采用近距离监测。但有的生产现场分布地域较广,如电力、铁路、采矿和石油等,要对相距遥远的生产过程进行远程监控和监测,如仍沿用就近监测的办法在技术上和经济上都是不足取的,必须采用远程监测技术。远程监控是利用计算机、测量仪表、远程通信设备对遥远现场的数据进行监控和测量。基于嵌入式网络技术,研究并实现了一种用于嵌入式设备的监控系统。该系统采用客户端和服务器架构,通过在嵌入式设备中内建一个嵌入式WEB服务器,可使得相应的嵌入式设备直接接入Internet。同时用户可使用标准的网络浏览器,对此设备进行访问控制和管理[1-2]。
通常嵌入式系统的软件编译和执行是在两个不同平台上进行的。编译过程在宿主机即PC机的Linux虚拟机中完成,执行是在目标机即S3C2410为核心的嵌入式系统硬件平台。在宿主机上通过跨平台交叉编译器把源文件编译成目标平台上可执行的文件,再通过串口或者网络下载至目标平台上的Flash或者其他存储介质,然后由目标机运行这些文件。交叉编译器和一般的编译器功能类似,是把源代码通过编译器编译成目标文件,然后通过链接器、可重定位器程序和定位器把目标文件重新定位成可执行文件。与通用的编译器之间最大的差别在于跨平台编译器编译出来的可执行程序通常只能在特定CPU所属平台上运行。所以一般来说每种CPU都对应有不同的跨平台编译器。系统设计采用基于ARM9的S3C2410开发板,使用的ARM交叉编译器为 arm-linux-gcc-3.3.2版本,对目标平台的操作通过Xshell软件完成。将平台与PC机通过串口连接,配置好端口和波特率后,便可通过串口在目标平台上执行相关指令[3-4]。
Linux中的驱动设计是嵌入式Linux开发中十分重要的部分,不仅要熟悉Linux的内核机制、驱动程序与用户级应用程序的接口关系、考虑系统中对设备的并发操作等等,而且还要熟悉所开发硬件的工作原理。Linux的驱动开发调试有两种方法,一种是直接编译到内核,再运行新的内核来测试。另外一种是编译为模块形式,单独加载运行调试。第一种方法效率较低,但在某些场合是唯一的方法。模块方式调试效率很高,使用insmod工具将编译的模块直接插入内核,如果出现故障,可以使用rmmod从内核中卸载模块。不需要重新启动内核,使驱动调试效率大大提高。系统设计中的驱动除USB摄像头驱动外均编译为模块形式。当模块与内核链接时,insmod会检查模块和当前内核版本是否匹配。每个内核版本都需要特定版本的编译器支持。如系统用到Linux-2.6.24内核需要3.3.2的GCC版本编译器。Linux-2.6版本的insmod命令装载模块时,从/lib/modules目录和内核相关的子目录中查找模块文件,可以使用命令insmod module.ko从当前目录装载。驱动程序与应用程序不同,驱动程序没有main函数,通过使用宏module_init(初始化函数名)将初始化函数加入内核全局初始化函数列表中,在内核初始化时执行驱动的初始化函数,完成驱动的初始化和注册。驱动程序中有一个宏module_exit(退出处理函数名)注册退出处理函数,它在驱动退出时被调用[5]。
远程视频监控部分由USB摄像头、基于ARM的嵌入式流媒体服务器、网络传输和客户端浏览器等几部分组成如图1所示。
图1 远程视频监控系统组成
现场的图像数据通过USB摄像头采集,通过USB传输到基于ARM的嵌入式流媒体服务器即BOA服务器,进行图像压缩和处理,通过网络向远程客户端传输视频图像。客户端通过浏览器对现场进行远程监控。
系统设计使用的USB摄像头芯片型号为中芯微ZC301P。USB摄像头驱动程序实现原理如图2所示。
图2 摄像头驱动程序实现原理
在驱动代码中,首先应声明一个video_device结构,使USB驱动与内核提供的视频驱动挂钩,并为其指定文件操作函数指针数组fops向系统注册。当应用程序发出文件操作的相关命令时,内核根据这些指针调用相应函数,并将该结构作为参数传递给它们,实现驱动与内核之间的通信。例如:
摄像头驱动程序是根据S3C2410开发板的配置进行一定修改后,通过交叉编译生成的。根据摄像头的型号,采用spca5xx-20060501.tar.gz驱动源码包,解压后修改 Makefile文件,指定交叉编译工具CC=armv4l-unknown- linux- gcc。修改Kconfig文件,添加摄像头的相关信息。修改usb-ochi.c文件,删除与PCI接口相关的代码。初始化主机控制器寄存器的起始地址,初始化USB主机控制器寄存器的中断向量。执行make命令,生成所需要的.ko驱动文件。驱动程序设计完成后,使用动态加载的方法添加到内核中。在宿主机上交叉编译好驱动模块,通过NFS共享将文件下载到ARM开发板上,将驱动挂载命令insmod写入/etc/init.d/rcS文件中,当开发板启动时自动加载模块。加载过程中出现USB相关信息。说明USB摄像头驱动成功添加,随后便可以进行用户级软件即应用程序的开发。
浏览器是一个显示网页服务器或档案系统内的HTML文件,浏览器是经常使用到的客户端程序。WEB服务器通常是在远程机器上,负责对浏览器页面请求做出响应,返回HTML编码或类似的数据流。WEB服务器传送页面使浏览器可以浏览。WEB服务器是一种专门处理超文本传送协议HTTP(hypertext transport protocol)请求的服务器[6]。嵌入式WEB服务器架构如图3所示。
图3 嵌入式WEB服务器架构
远程视频监控所需的嵌入式流媒体服务器是建立在WEB服务器之上的,系统在S3C2410开发板上植入BOA服务器,在其基础上运行流媒体服务器,并用于处理远程客户端的请求,实现视频监控和现场A/D数据采集功能。系统采用boa-0.94.13版本,需要的源码在虚拟机 Linux系统的 boa-0.94.13目录下。设置目标平台和制定交叉编译器。
进入/src目录,修改compat.h文件,使#define TIMEZONE_OFFSET(foo)foo->tm_gmtoff生效。运行./configure命令生成Makefile文件,修改Makefile文件如下所示。
指定交叉编译器的前缀为arm-linux-gcc,使得编译后的BOA服务器能在ARM开发板上正常运行。编译生成BOA服务器镜像。即在/src中执行make命令,得到可执行的boa文件。将BOA服务器镜像下载到开发板并进行相关配置。BOA服务器的正常运行需要正确配置服务器相关的配置文件。BOA服务器运行时会自动在/etc/boa/目录下寻找BOA服务器的配置文件boa.conf。通过NFS共享文件夹将BOA服务器镜像共享到ARM开发板的/bin目录下。
配置/etc/boa/boa.conf文件主要内容如下所示。
保存BOA服务器的配置文件boa.conf,在var/log/boa中建立error_log文件存放错误信息。完成BOA服务器的移植工作,随后便可通过在PC机的浏览器地址栏中输入服务器的地址浏览服务器主页。
由于在移植BOA服务器的过程中将服务器默认首页设置为index.html文件,需要创建一个index.html文件作为服务器的主页。用HTML语言编写主页,通过浏览器观察摄像头的拍摄画面和A/D转换的数据采集值。主页设计中建立两个按钮分别是远程视频监控和AD数据采集。网页页面背景为白色,在HTML语言中白色的编码为“#FFFFFF”,即:<body bgcolor="#FFFFFF">。以远程视频监控为例,整个代码写在一个以<td>开头,</td>结尾的单元格中。如
其中“input”为按钮,类型为“点击”(submit),按钮名称写在“value”中,并通过“style”设置按钮大小。保存 index.html文件,将其拷贝到ARM开发板的/var/www/目录中,用命令ifconfig eth0 192.168.1.13设置 BOA服务器地址,即开发板地址为192.168.1.13。进入/bin目录,使用命令 ./boa后台执行 boa程序,打开PC机IE浏览器,在地址栏输入BOA服务器地址192.168.1.13,即可看到 index.html的内容。
系统采用Spcaserv流媒体服务器完成对视频数据的采集、压缩和传输。成功加载USB摄像头的驱动并移植好BOA服务器之后,需要移植嵌入式流媒体服务器Spcaserv。
Spacserv流媒体服务器是建立在WEB服务器之上的,WEB服务器采用 BOA服务器,通过 Linux下的 V4L API函数、MJPEG图像压缩器和TCP网络传输协议完成视频图像信号的获取、压缩和传输。Spcaview是Linux系统下用于实现网络视频服务器的软件包。Spcaview可以用来纪录数据流,也可以用在客户端播放数据,Spcaserv流媒体服务器带有JPEG图像压缩器,可对其直接进行交叉编译。编译后可工作在ARM9开发板上,配合嵌入式Linux专用的spca5xx网络摄像头驱动实现视频采集。对于USB口摄像头,其驱动程序中需要提供基本的I/O操作接口函数open、read、write和close的实现。在打开视频采集设备后,分别通过ioctl(vd- >fd,VIDIOCGCAP,&(vd- >ca-pability))函数的VIDIOCGCAP控制命令,获取关于视频采集设备所能显示的最大图像大小和信号源的通道数。通过ioctl(vd- >fd,VIDIOCGPICT,&(vd- >picture))的 VIDIOCGPICT获取一些关于图像的亮度和对比度等信息。
采用spcaview-20061208源码包,在虚拟机Linux系统中解压并进入源码目录,修改Makefile文件,使其在交叉编译环境下编译生成系统所需要的Spcaserv流媒体服务器程序,但是Spcaview的安装依赖libsdl库,因此需要先安装 SDL-1.2.12.tar.gz。在 SDL-1.2.12 的源码目录中,打开 configure配置文件,指定目标板的交叉编译工具和虚拟机的编译工具,执行make以及make install安装libsdl库。安装完成后进行spcaserv软件的安装。语句如下所示。
修改完成后执行make spcaserv命令,生成可执行文件spcaserv,通过NFS共享文件夹将spcaserv和spcaview-20061208源码包中的http-java-applet文件夹拷贝到ARM开发板上。其中,http-java-applet文件夹的内容在BOA服务器的/var/www文件夹中。
客户端通过浏览器窗口实现远程视频监控需要建立HTTP服务器。在BOA服务器的基础上,通过服务器主页中的“远程视频监控”按钮连接到相应的监控网页,在http-java-applet文件夹中的index.html文件,设计网页代码。当“远程视频监控”按钮按下时,网页自动打开index1.html文件,将设计的远程视频监控界面保存至index1.html。打开BOA服务器主页后,点击“远程视频监控”按钮,浏览器中显示远程视频监控界面网页。
插入USB摄像头,将ARM开发板IP地址设置为“192.168.1.13”,后台运行 BOA 服务器,执行 spcaserv程序,具体指令如下所示。
在PC机上打开IE浏览器,输入BOA服务器地址,看到主页后,点击“远程视频监控”按钮进入远程视频监控界面如图4所示。
图4 远程视频监控界面
图4中表明USB摄像头实现了对双容水箱液位控制系统的电动调节阀工作情况进行监视。点击“返回”按钮,浏览器页面返回到BOA服务器主页,实现了远程视频监控功能。
客户端为HTML网页形式,用户通过点击网页按钮执行相应的后台CGI程序,对ARM开发板上的3路A/D输入量进行采样,通过网络传输采集的数据最终在网页上显示。
A/D转换器是将连续变化的模拟信号转换为数字信号,便于计算机系统进行处理、存储和显示。A/D控制器寄存器可以同时外接8个模拟量输入,精度为10位。A/D控制寄存器还集成了触摸屏控制器,因此,A/D转换和触摸屏驱动不能同时启用。A/D设备驱动是通过交叉编译器编译驱动模块生成s3c2410_adc.ko驱动文件,通过NFS共享将文件下载到ARM开发板上。通过驱动挂载命令insmod s3c2410_adc.ko加载驱动,查找设备号,为A/D设备创建设备节点。执行cat/proc/devices命令查看A/D设备号显示为252。使用命令mknod/dev/adc c 252创建A/D设备节点,之后便可以进行应用程序的开发。
命名数据采集页面为adc.html,文件中包含了HTML代码和JavaScript脚本。HTML代码用于编辑页面的样式,采集三路A/D数据,建立一个三行两列的table表格,显示三路的通道名称和相应的A/D值。为了能够随时停止A/D数据采集,需要在网页上设置“停止采集”按钮,当按下该按钮时,自动运行后台“停止”程序。在设计页面时可采用input按钮来完成“停止采集”的目的。如下所示。
为了使网页能够动态地刷新ARM开发板传来的数据,需要编写JavaScript脚本。通过两个函数loadXML和getmessage实现。loadXML函数调用getmessage函数。loadXML函数的作用是载入一个.XML文件,loadXML函数设计如下所示。
此处加载的是adc.xml文件。LoadXML函数在页面被打开时调用,在该函数的末尾语句setTimeout("loadXML()",1 000)的作用是让这个函数每1 000 ms即1 s重新执行一次,避免了手动刷新的麻烦。
getmessage函数的作用是从服务器的adc.xml文件中解析出需要的数据在页面上显示。因此,这个函数和服务器上的adc.xml文件是紧密相关的。
通用网关接口CGI(Common Gateway Interface)是HTTP服务器与你的或其他机器上的程序进行交互的一种工具,程序需运行在网络服务器上。绝大多数的CGI程序被用来解释处理来自表单的输入信息,并在服务器产生相应的处理或将相应的信息反馈给浏览器。CGI程序使网页具有交互功能。CGI的处理过程是通过Internet把用户请求送到服务器。服务器接收用户请求并交给CGI程序处理。CGI程序把处理结果传送给服务器。服务器把结果送回到用户。CGI工作原理如图5所示。
图5 CGI工作原理
A/D数据采集功能使用CGI程序分别控制数据采集的开始和数据采集的结束。A/D数据采集CGI程序是由.c文件经过交叉编译器编译生成。有采集开始程序和采集停止程序,程序执行流程图如图6所示。
采集开始和采集停止程序说明如下。
7.4.1 采集开始程序run.c
程序调用fork()函数创建两个线程。一个用于打印HTML代码,使页面跳转到adc.html页面打印完HTML信息后该线程就退出。另一个子线程执行A/D数据采集,读取三个通道的A/D值进行转换,并将读取的结果写入adc.xml文件中供用户检索。程序通过函数adcfd=open("/dev/adc",O_RDWR)打开A/D设备,并将返回值给adcfd,当A/D设备成功打开时即adcfd>0时,程序通过open()函数打开adc.xml文件准备写入数据。将adc.xml文件上锁,防止其它进程对其进行操作。打开adc.xml后,程序检测文件中<stop>标签的值,如果为‘$',说明用户按下了“停止采集”按键,程序向<stop>标签中重新写入‘A'后,解除 adc.xml的锁定状态,关闭 adc.xml文件和 A/D数据采集设备,程序终止。
图6 采集开始和采集停止程序流程图
如果<stop>不为‘$',说明用户要求读取A/D数据采集值,程序执行getdata函数,向adc.xml文件中写入三路通道的测量值。程序通过 ioctl(adcfd,j,0);依次打开三个通道,用read()函数读通道值存放在temp中,以ASCII码的形式写入对应的 buf[i]中,完成对 adc.xml文件内容的更新。
7.4.2 采集停止程序stop.c
采集停止程序在用户按下“停止采集”按钮后执行,使页面跳转到主界面,修改adc.xml文件的<stop>标签值为‘$',使得采集开始程序run.c检测到相应变化而停止运行。
采集开始程序和采集停止程序都在ARM开发板上运行,因此要在交叉编译环境下进行编译,使用语句arm-linux-gcc-o run.cgi run.c和 arm -linux-gcc -o stop.cgi stop.c进行编译生成.cgi文件下载到开发板上运行。成功加载A/D设备驱动后,后台运行BOA网络服务器。在PC机浏览器地址栏输入服务器地址,进入BOA服务器主页后点击“AD数据采集”按钮,看到图7所示的AD数据采集界面。
图7 A/D数据采集界面
改变ARM开发板上的3路电压值,可在页面中看到相应的A/D数据采集值随着变化。
应用嵌入式技术设计了一种基于Linux和S3C2410的集视频采集传输系统、A/D数据传输系统和SOCKET网络传输为一体的远程监控系统,实现了嵌入式Linux在ARM平台上的剪裁和移植,嵌入式WEB服务器BOA的建立,USB摄像头在Linux下的驱动程序开发。基于V4L的流媒体网络服务器的建立实现了视频数据网络传输。通过A/D转换设备在Linux下的驱动程序开发和SOCKET网络接口程序设计,实现了基于TCP协议的网络数据传输。
[1]王洪涛.基于ARM&Linux的嵌入式远程监控系统.仪表技术与传感器,2009(5):8-57.
[2]杨春杰.基于ARM的GPRS定位系统设计.计算机应用,2008,(4):36-37.
[3]汪忠华,章益品,姚银花等.基于ARM的GPRS地面目标跟踪及报警系统的设计与实现.国外电子元器件,2007(6):35-36.
[4]赵海峰,马后勇,梁斌.基于嵌入式LINUX的WEB监控系统设计.无限电工程,2010(4):23 -26.
[5]吴彰良,孙长库,刘洁.基于图像处理的油封缺陷自动检测与分类识别方法.仪器仪表学报,2013,34(5):1093 -1094.
[6]肖理庆,王化祥,程红林等.改进遗传算法的 ERT有限元模型拓扑结构优化.仪器仪表学报,2012,33(7):1490-1493.