Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 同步数据采集的硬件中断_Python_Linux_Hardware Interface - Fatal编程技术网

Python 同步数据采集的硬件中断

Python 同步数据采集的硬件中断,python,linux,hardware-interface,Python,Linux,Hardware Interface,我正在寻找一种使用外部TTL脉冲触发数据采集软件的简单方法。我需要用一个5赫兹的参考时钟同步地从多个来源采集数据。采集不需要实时优先级,但我希望确保尽快触发我的软件,并且每个外部时钟周期正好触发一次。我更愿意通过某种方式从外部触发器获取中断,而不需要使用快速轮询循环。据我所知,在像Linux这样的现代操作系统中,不能只使用并行端口引脚进行中断。有什么想法吗 我还考虑在我的网络上生成广播数据包,以通知网络上的其他机器已发生触发事件。但是,由于网络延迟,在两次触发器之间的200ms时间内可能没有足够

我正在寻找一种使用外部TTL脉冲触发数据采集软件的简单方法。我需要用一个5赫兹的参考时钟同步地从多个来源采集数据。采集不需要实时优先级,但我希望确保尽快触发我的软件,并且每个外部时钟周期正好触发一次。我更愿意通过某种方式从外部触发器获取中断,而不需要使用快速轮询循环。据我所知,在像Linux这样的现代操作系统中,不能只使用并行端口引脚进行中断。有什么想法吗


我还考虑在我的网络上生成广播数据包,以通知网络上的其他机器已发生触发事件。但是,由于网络延迟,在两次触发器之间的200ms时间内可能没有足够的时间进行采集。

对于如此缓慢的数据速率,轮询是一种很好的方法。以1毫秒的速度投票,应该可以。尝试使用硬件中断会引起很大的痛苦

如果你想通过谷歌搜索“中断Linux GPIO”,那就用谷歌搜索“中断Linux GPIO”。)


您是否考虑过使用串行设备而不是使用并行端口?由于您有一个TTL信号,您可能需要一个电平转换器将TTL转换为RS232+/-12V电平。使用串行设备后,可以使用标准的串行
ioctl()
调用来检测控制信号状态的变化

具体地说,您可以在连接的串行设备上使用
TIOCMIWAIT
ioctl来等待DCD线路上的更改,您可以将该线路连接到时钟源

您的用户空间应用程序将在等待
TIOCMIWAIT
ioctl系统调用时被阻止,直到您的时钟线上出现状态更改,此时您的应用程序将变为可运行并从ioctl返回。您可能必须小心处理串行控制信号上升沿和下降沿上的状态变化中断的情况。在某些UART硬件(如TL16C554A UART)上,您可能只会收到一个信号向单一方向转换的中断。例如,对于TL16C554A,TIOCMIWAIT的
TIOCMIWAIT
仅在任何环的上升沿上下降,以指示信号变化

以这种方式使用串行IOCTL的另一个优点是,如果需要,您可以使用支持
TIOCMIWAIT
的USB串行加密狗(如PL2303),并且仍然保持用户级软件兼容性,尽管这会导致USB延迟增加

如果您需要的延迟低于通过用户空间可以实现的延迟,那么最好编写一个内核驱动程序模块,它可以处理计时和采样,但除非绝对需要,否则我不会建议使用这种方法。开发用户空间代码更容易

下面是一些使用
TIOCMIWAIT
ioctl的不完整C代码示例片段

int serial_fd = open(cmdline.device_name, O_RDWR | O_NONBLOCK | O_NOCTTY);
static const unsigned int ri_flag = TIOCM_RNG;

/* Set up serial port here using tcsetattr.  Set CRTSCTS | CLOCAL to ensure status interrupts
 * are generated.
 */

while (1) {
        /* Wait for positive RI transition.  TIOCMIWAIT takes a mask
         * as argument, only returning when the appropriate signal has changed.
         */
        if (ioctl(serial_fd, TIOCMIWAIT, ri_flag)) {
            fprintf(stderr, "ioctl() failed waiting for RI edge [%s]\n", strerror(errno));
            break;
        }

        /* Do sensor sampling here.  You could use TIOCMGET to first verify that
         * the clock line is in the expected state, eg high, before continuing.
         */
}

根据Austin Phillips的回答,我最终使用串行端口CTS行作为触发器,使用
TIOCMIWAIT
ioctl。由于RS232需要+/-12V电平,我能够从其他串行控制线路获得该电平移位器所需的电源


可以找到实现此解决方案的Python代码:

考虑将外部脉冲源连接到真实(!不是USB到RS232转换器)串行端口的“CD”ping。然后,您可以使用“PPS api”获得一个尽可能精确的时间戳,从该时间戳中pin“变高”

您可能需要一个TTL信号移位器;并非所有串行端口都能在TTL信号电平下正常工作

PPS api通常用于计时。例如,将GPS模块的PPS pin连接到您的电脑,并让NTP与之同步。这会给你微秒的准确度

这个PPS api应该比任何其他用户空间解决方案(例如,TIOCMIWAIT ioctl)更准确,因为当中断(由CD信号变化触发)进入时,它完全在内核中处理。使用ioctl解决方案,您至少有一个上下文开关。我在raspberry pi上做了一些测试,一个用户空间解决方案给出了至少6us的抖动

PPS api提供从检测到脉冲开始的时间戳

为什么不使用USB到RS232转换器:我在某处读到(关于计时)USB设备每+/-1ms轮询一次。这个轮询频率还取决于系统对其他USB设备的繁忙程度,我认为USB设备的内部时钟也可能会影响一些事情。但我从未测量过这个

相关网址:

  • 描述PPS API的RFC
  • Linux实现PPS API(在标准内核中)
  • 提到为什么不使用USB计时的线程

关于网络功能:使用UDP广播,不要使用TCP。

这正是我想要做的。我不知道我仍然可以通过USB适配器使用RS232中断。这当然简化了事情。看起来我可以很容易地在Python中使用问题来实现这一点。Python ioctl示例在真正的串行端口上工作得非常好!每当我使用Keyspan USB适配器尝试此操作时,ioctl都会返回一个“参数错误”,但最好不要有延迟,而是使用真正的com端口。现在只需要构建TTL至+/-12V电平移位器。@Mike我查看了源代码,键盘平移驱动程序不支持
TIOCMIWAIT
。只有一些usb串行驱动程序支持此功能,请在linux源目录
drivers/usb/serial
中的驱动程序文件中查找
.tiocmiwait
。PL2303是一种非常常见的usb串行适配器。您可能会找到其中一个,并在加密狗中绕过+/-12V前端。另外,Maxim生产一系列电平转换器IC。要进行电平转换,请设置RTS(1)、setDTR(0)并使用2N4401