Hardware interrupt for synchronous data collection

I am looking for a simple means to run my data collection software using an external TTL pulse. I need to sample data from several sources synchronously with a 5 Hz reference clock. The acquisition does not require real-time priority, but I want my software to be launched as soon as possible and exactly once per external clock cycle. I would rather do this, somehow get an interrupt from an external trigger, without using a quick polling loop. As far as I can tell, you cannot just use the parallel port to interrupt in a modern OS such as Linux. Any ideas?

I am also thinking of creating broadcast packets on my network to notify other computers on the network of the occurrence of a trigger event. However, due to network latency, there may not be enough time for 200 ms between triggers to receive.

+6
source share
4 answers

Instead of using a parallel port, do you think you are using a serial device? Since you have a TTL signal, you may need a level converter to convert TTL to RS232 +/- 12V levels. After using the serial device, you can use standard ioctl() serial calls to detect a change in the state of the control signal.

In particular, you can use TIOCMIWAIT ioctl on a connected serial device to wait for a change, for example, of a DCD line that you would connect to a clock source.

Your user space application will be blocked waiting for the TIOCMIWAIT ioctl system call until the state on your watch line changes, after which your application becomes executable and returns from ioctl. You may need to make sure that you deal with a situation where you receive a state interrupt change on both the rising and falling edges of your serial control signals. On some UART devices (for example, TL16C554A UART), it is possible that you only get an interrupt for a signal to go in one direction. For example, for the TL16C554A, TIOCMIWAIT will only leak to the leading edge of any change in the Ring Indicate signal.

Using serial ioctls in this way also has the advantage that you can use a USB-Serial dongle that supports TIOCMIWAIT if required (for example, PL2303) and still maintain user-level software compatibility, albeit at the expense of increased latency due to USB.

If you need lower latency than can be achieved with user space, it is best to write a kernel driver module that can handle synchronization and sampling, but I would not suggest this route if it is absolutely necessary. Easier to develop user space code.

Here are some partial examples of C code snippets for using TIOCMIWAIT ioctl.

 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. */ } 
+7
source

Polling is a great method for such a slow data rate. Poll in 1 ms. That should be good. Trying to use hardware interrupt will cause a lot of pain.

Google for "Interrupting Linux GPIO" if you want to do this with difficulty. :)

https://developer.ridgerun.com/wiki/index.php/How_to_use_GPIO_signals

+3
source

I ended up using the CTS serial port string for the trigger using the TIOCMIWAIT ioctl per Austin Phillips response. Since RS232 requires +/- 12 V levels, I was able to get the required power for this level switch from other serial control lines.

Level shifter schematic

Python code for implementing this solution can be found in the question: Python serial port communication signals (RS-232)

+2
source

Consider connecting an external pulse source to the "CD" pin of a real (! Not a USB to RS232 converter) serial port. Then you can use the “PPS api” to get the exact timestamp from which the pinch “climbed up” as far as possible.

You may need a TTL switch; not all serial ports work correctly with TTL signal levels.

PPS api is usually used to save time. For instance. connect the PPS pin of the GPS module to the computer and enable NTP synchronization. This gives you microsecond accuracy.

This PPS api should be more accurate than any other user-space solution (e.g. TIOCMIWAIT ioctl), since it is fully processed in the kernel immediately when an interrupt occurs (caused by a change in the CD signal). Ioctl solution you have at least a context switch. I did some testing on raspberries pi and the user space solution gave at least 6x jitter.

PPS api gives you a timestamp when an impulse was detected.

Why don't you use a USB to RS232 converter: I read somewhere (regarding timing) that USB devices are polled once every +/- 1 ms. This polling rate also depends on how busy the system is with other USB devices, and I think that the internal clock of a USB device can also affect things. I have never measured this, though.

Relevant URLs:

Regarding network functions: use UDP broadcasts, do not use TCP.

+2
source

Source: https://habr.com/ru/post/948507/


All Articles