使用继电器控制设备
我最近被赋予一项奇怪的任务,即在工厂车间以设定的间隔发出噪音。公司希望使用这种噪音为特定事件提供重要的听觉提示。这些事件包括员工应该打卡上班、打卡下班、休息以及从休息返回的时间。我实施的解决方案一直运行良好,所有相关人员都对结果感到满意。我从打卡上下班的员工那里获得的感激之情与他们个人计时器的不准确性直接相关——那些手表走得快的员工很欣赏他们在打卡上班前拥有的明显的额外时间。然而,稍后,当他们手腕上的手表清楚地显示该下班时,他们会因为我延迟打卡下班而咒骂我。
我工作的公司使用条形码打卡终端,这些终端遍布整个工厂,用于记录员工的上下班时间。此外,条形码打卡机还记录每位员工正在执行的工作。当员工打卡上班或下班时,员工会扫描他或她的身份识别徽章和代表该人员正在从事的工作的条形码。打卡终端将此数据复制到缓冲区,以及扫描项目的时间戳。CMINet,一个在两台 Microsoft Windows NT 系统上运行的数据收集系统,用于从打卡机获取数据。每分钟左右轮询一次打卡机,以检索保存在打卡终端缓冲区中的数据。在轮询期间,打卡机也被设置为轮询机器的当地时间。从打卡机获取的数据稍后被导入到企业资源计划 (ERP) 系统中,用于工作成本核算和工资单。
公司关于迟到的政策规定,“如果员工在分配的上班时间一分钟或更长时间后打卡上班,将被视为迟到。” 鉴于公司关于迟到的政策,事件铃声需要与条形码打卡机和运行 CMINet 的机器完美同步。理论上,这种同步将缓解记录的上班时间、记录的下班时间和真实的当地时间之间的差异。正确的时间同步是关键,但本文并未对此进行深入讨论。
考虑到晚到一分钟或更长时间等于迟到的规则,以及员工在从休息返回时总是会面临时间挑战这一事实,决定安排铃声响起会很有用。因此,需要一个关键任务的噪音制造系统,我被赋予了实施它的任务。
根据手头的问题,该项目必须满足以下要求
使用铃声系统提供听觉提示。铃声需要足够响亮和令人讨厌,即使在长时间暴露后也能被注意到。
提供一种通过计算机闭合电路的简单方法。
为所有时间敏感系统提供准确的时间同步,包括将触发铃声的机器、运行 CMINet 的机器,以及间接的条形码打卡机。
在定义了需求之后,我开始制定计划。购买了五个新的 12VAC 铃铛和一个 12VAC 电源。这些是报警系统或任何发声系统中常用的相同类型的铃铛。铃铛以与旧闹钟相同的方式物理敲击自身,并且发出很大的分贝。铃铛需要接线,以便连接两根电线即可使工厂中的所有铃铛响起来。
为了控制铃铛,我们需要暂时闭合铃铛的电路。有人向我推荐了一种特定的继电器设备,AR-2,可以通过串行端口由计算机控制。该设备将用于完成铃铛电路,使其响起。AR-2 由 Electronic Energy Control, Inc. (EECI) 出售,价格约为 44 美元。它在一块电路板上有两个继电器,都可以连接为常开 (NO) 或常闭 (NC) 继电器。对于此项目,仅使用一个接线为 NO 的继电器。还购买了一个用于容纳电路板的外壳 (EN-B)。在外壳上安装了一个紧急开/关开关,以备发生严重错误时使用。AR-2 的文档记录得很好,我知道可以用 C 语言编写一个程序来控制它。可以使用 cron 作业来调度此程序。
对于时间同步,选择了 NTP 协议。由于广泛采用的定义明确的协议,NTP 客户端和服务器不太可能出现互操作性问题。此外,NTP 客户端可以处理网络延迟、夏令时和本地时区。几乎今天使用的每个主要操作系统都有免费客户端可用。使用这些客户端的计算机可以轻松获得至少精确到毫秒的时间源。良好的精度正是我们在尝试同步多个系统时所需要的。
五个 12VAC 铃铛安装在整个工厂和指定的休息区,以便每个人都能听到它们。铃铛以串联和并联混合的方式与供应商提供的 12VAC 电源接线。电源的一根引线保持未连接,以提供一个可以打开和关闭铃铛的点。
我获得了我们公司的一台备用 Dell PC 用于此项目,这是一台基本的 PC,配备 Pentium III 750MHz 处理器、128MB SDRAM、40GB IDE 硬盘和 IDE CD-ROM。我使用了现有的东西,实际上,这台计算机的功能远远超出必要。
AR-2 继电器设备连接到计算机的串行端口,并通过 DTR(数据终端就绪)和 RTS(准备发送)控制线进行控制。将 RTS 设置为高电平会激励第一个继电器,将 DTR 设置为高电平会激励第二个继电器。闭合铃铛电路只需要一个继电器,所以我只需要能够切换 RTS 信号。文档中提供了 GWBASIC 和 Turbo C 中的示例程序。我想使用 GCC 编写一个程序来控制继电器,但 C 编程经验很少,因此我在 Web 上搜索了一些有据可查的 C 程序示例,这些程序使用了串行端口。
我找到的第一个有趣的程序是 Harvey J. Stein 的 UPS HOWTO 中的 upscheck.c。upscheck 本身是 Miquel van Smoorenburg 的 powerd.c 的修改版本,同时使用了 RTS 信号和 DTR 信号。该程序最初用于诊断或检查 UPS 与 PC 通过串行端口的通信。启动程序时,您可以使用参数指示 UPS 连接到哪个串行设备,以及是否将 RTS 和/或 DTR 设置为高电平。程序打开端口并设置或清除指示的串行控制线后,程序将监视另一条控制线以获取来自 UPS 的反馈。该程序完成了我需要的一切以及更多。我所要做的就是删除监视部分,我就有了我的 C 程序来控制 AR-2 上的两个继电器(清单 1)。该程序使用以下命令编译
[root@pluto ar-2]# gcc -o ar-2 ar-2.c [root@pluto ar-2]# ./ar-2 Usage: ar-2 <device> <bits-to-set> <hold-time>
清单 1. ar-2.c
#include <sys/types.h> #include <sys/ioctl.h> #include <fcntl.h> #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include <signal.h> /* Main program. */ int main(int argc, char **argv) { int fd; int sleep_time; /* These TIOCM_* parameters are defined in * <linux/termios.h>, which * is indirectly included here. */ int dtr_bit = TIOCM_DTR; int rts_bit = TIOCM_RTS; int set_bits; int flags; int status, oldstat = -1; int count = 0; int pc; if (argc < 3) { fprintf(stderr, "Usage: ar-2 <device> " "<bits-to-set> <hold-time>\n"); exit(1); } /* Open monitor device. */ if ((fd = open(argv[1], O_RDWR | O_NDELAY)) < 0) { fprintf(stderr, "ar-2: %s: %s\n", argv[1], sys_errlist[errno]); exit(1); } /* Get the bits to set from the command line. */ sscanf(argv[2], "%d", &set_bits); /* get delay time from command line. */ sscanf(argv[3], "%d", &sleep_time); ioctl(fd, TIOCMSET, &set_bits); sleep(sleep_time); close(fd); }
该程序编译时没有错误,更好的是,它运行时也没有错误。使用该程序非常简单,但让我们简要讨论一下。AR-2 需要三个参数:device、bits-to-set 和 hold-time。Device 指的是寻址 AR-2 所连接的串行设备的特殊字符设备。例如,如果设备连接到 COM1,则设备将为 /dev/ttyS0。Bits-to-set 有点复杂。它是一个十进制数,必须转换为二进制才能理解。位 2 控制 RTS 或继电器 1,位 3 控制 DTR 或继电器 2。因此,十进制数 4,在二进制中为 100,其第一位设置为零,第二位设置为零,第三位设置为一。因此,如果 bits-to-set 参数是十进制数 4,则 DTR 线将设置为高电平,而 RTS 线将保持低电平。最后一个参数 Hold-time 只是调制解调器控制线应保持在 bits-to-set 参数请求的状态的秒数。
我对 AR-2 板通电,并将其连接到串行端口,以测试该程序是否按我希望的方式工作。在 AR-2 连接到 ttyS0 (COM1) 的情况下,我尝试通过使用命令将位 2 设置为高电平来激励第一个继电器,从而将 RTS 设置为高电平./ar-2 /dev/ttyS0 2 5。该程序成功地将 RTS 设置为高电平五秒钟。程序退出后,它将 RTS 线置于其原始低电平状态,从而使继电器断电。接下来,我使用命令将位 4 设置为高电平,从而将 DTR 设置为高电平./ar-2 /dev/ttyS0 4 5。通过同时设置位 4 和 2,可以使用十进制数 6 作为 bits-to-set 参数,将 RTS 和 DTR 都设置为高电平。板上的 LED 有助于确定 AR-2 程序和 AR-2 板是否都在运行。
感谢 upscheck.c 及其作者,我能够将 RTS 和 DTR 控制线在指定的时间内置于低电平或高电平状态。如果没有 UPS HOWTO 中列出的源代码,事情就不会那么顺利。稍作努力,我就能够找到接近我需要的 C 源代码,并对其进行修改以满足我的需求。我现在可以从单个串行端口控制两个继电器。
此时,可以将铃铛连接到 AR-2 上的第一个继电器,使用 NO 触点。但是,在连接所有东西之前,我想将 AR-2 放在一个外壳中,一个漂亮的小盒子来容纳所有这些东西,这样电子设备就不会暴露出来。我使用了 EECI 推荐和销售的 EN-B 外壳。它由两个塑料件组成,一个顶部和一个底部,带有黑色塑料插件,用于覆盖两侧的开口。对于这项工作来说,外壳有点大,但它可以使用。我不得不切割黑色塑料插件,以便可以访问外部连接器。此外,还为 AR-2 上的串行连接器切割了一个孔,该连接器将用于连接到计算机的串行端口。为为 AR-2 板供电的母电源连接器钻了一个孔。为了连接继电器和铃铛电路,我选择了一个红色和黑色香蕉夹,这在大多数电子商店都可以找到。又为香蕉夹钻了两个孔。为了增加功能,我在外壳顶部添加了一个电源开关和一个电源 LED,以便可以打开和关闭 AR-2 板的电源。当 AR-2 板打开时,LED 会亮起。在测试和封装了电子设备后,是时候转向计算机了。
我选择了 Red Hat 7.3 作为操作系统。完成了全新安装,选择 Server 作为安装类型。Red Hat 安装完成后,我开始自定义该盒子。我将 ar-2.c(upscheck.c 的修改版本)复制到该盒子并编译了它。成功编译后,我将生成的二进制文件 ar-2 复制到 /usr/bin/ 目录,因为 AR-2 程序在特定时间从 cron 运行。
我想允许远程管理铃铛的 cron 作业,所以我真的不希望它们以 root 身份运行。因此,我决定为铃铛的特定任务添加一个用户,并使用命令为其指定用户名 bell,useradd bell。用户 bell 不需要本地或远程登录,因此将用户的 shell 更改为非功能性 shell 是一个好主意,命令如下usermod -s /sbin/nologin bell.
这里出现了一个权限问题,需要注意。在 Red Hat 7.3 中,/dev/ttyS* 设备的权限设置为只有 root 和 uucp 组的成员才能对其进行读写访问。但是,用户 bell 需要能够写入串行端口,以便控制连接的继电器设备。默认情况下,用户 bell 没有对串行设备的读写访问权限。为了解决这个问题,我决定让用户 bell 成为 uucp 组的成员。作为 root 用户,我使用命令将用户 bell 添加到 uucp 组usermod -G uucp bell。现在 bell 可以使用 /dev/ttyS0 设备上的 AR-2 来操作串行端口的控制线。
为了远程管理 bell 的 cron 作业,我选择了一个许多 Linux 用户熟悉的基于 Web 的工具 Usermin。我还下载了 Webmin 以配置 Usermin,并将它们都安装了。安装后,我登录到 Webmin 并使用 Usermin Configuration 模块配置了 Usermin。由于只有用户 bell 应该能够使用 Usermin,我使用了 Allowed Users and Groups 模块并选择了“Only allow listed users”;bell 当然是我添加到列表中的唯一用户。接下来,我使用 Available Modules 来限制除 Scheduled Cron Jobs 模块之外的所有模块。最后但并非最不重要的一点是,我进入 User Interface 模块,并为 Go direct to module if user has only one option 单击了 Yes。现在 bell 是唯一可以登录 Usermin 的用户,并且当用户 bell 登录时,Usermin 会直接跳转到显示 Scheduled Cron Jobs。我还启用了强制 SSL 加密。Webmin 不需要用于任何其他用途,所以我使用以下命令停止了它service Webmin stop。为了确保它不会在重新启动时重新启动,我输入了chkconfig webmin off.
现在我们可以以用户 bell 身份登录 Usermin,并通过使用命令轻松安排铃铛应该响铃的时间以及持续时间/usr/bin/ar-2 /dev/ttyS0 2 2。员工可以放心地知道铃声总是让他们知道何时开始跑步。管理层可以安心,因为他们又多了一个工具来帮助保持事情顺利进行,我可以安心,因为它在 Linux 上运行,这意味着我不必担心不断地照顾它。
这是一个简单的练习,说明了如何通过串行接口使用继电器控制设备。此示例中使用的低成本继电器能够控制任意数量的电气设备。还有可用的继电器板,每个串行端口最多可以扩展到 128 个继电器,更不用说模拟和数字输入卡了。
资源
Electronic Energy Control, Inc.: www.eeci.com
Red Hat: www.redhat.com
UPS HOWTO: www.tldp.org/HOWTO/UPS-HOWTO.html
Usermin 和 Webmin: www.usermin.com 和 www.webmin.com
Jason Ellison 来自阿拉巴马州费尔霍普,目前是 Delphi 的网络分析师。他还在 Delphi 维护多个 Linux 和 AIX 系统。