intermittent report latency on IOW24

This is the English forum for all topics related to IO-Warrior. Please post in English only

Moderator: Guido Körber

Post Reply
dimaq
Posts: 4
Joined: Wed Dec 29, 2004 9:02 pm
Location: Helsinki
Contact:

intermittent report latency on IOW24

Post by dimaq »

Hi, I'm trying to use IOW24 to monitor some real-life events. I'm using a photo interrupter plus inverting buffer that feeds the signal to a pin on port1. I run linux and use python + libusb to read the reports IOW24 generates in the interrupt queue. Basically my code waits for interrupt transactions in a loop. IOW24 generates reports at XX Hz on it's own plus when port1 state changes due to my signal.

According to my calculation my event should generate a 7.3ms pulse. When I get the reports, the time difference (up,down) is usually 7.xxx ms, however, sometimes I a pair of reports (up,down) is skipped entirely, and sometimes the time difference is something like 58ms.

Does anyone know what might be going on here?

Thanks
Robert Marquardt
Posts: 543
Joined: Mon Dec 01, 2003 6:09 pm

Post by Robert Marquardt »

Time lags are completely normal. USB does not guarantee any timing on HID reports. The reports read are also usually timed every 8 msec. the IOWarrior sets the polling time to the minimum for low-speed HID devices which is 10 msec. The OS only tries to get a report in this polling time raster, but most OSes adjust to the nearest power of 2 which is 8 msec.

So 8 msec is the best you can get. The OS is free to work slower.
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

Hello dimaq,

Besides the timing issues caused by the OS / USB-Bus from the previous post, the are a few more resaons that come to my mind.

What about the memory-management in Python, doesn't this language use some kind of Garbage-Collector?
As far as I know libusb is not thread-safe: You do not more than one thread in your app?

The upper limit for the iput frequency of the IOWarrior24 is something like 62.5 Hz
In other words if you want to measure timespans like you do in your app, the minimum duration for an ON-OFF-Event must be >= 8ms. If your interrupts last something like 7.245 ms they are simply too short to be noticed by the IOW24.
There are no programming hacks to get below this hardware-limit, but an IOWarrior56 allows for an higher input-frequency of 500Hz.

Eberhard


.
Robert Marquardt
Posts: 543
Joined: Mon Dec 01, 2003 6:09 pm

Post by Robert Marquardt »

The signals on the pins can be short pulses of course. The IOWarrior just cannot report changes of the pins faster than the 8 msecs polling time.

The time lag of 58 msecs is happening in the OS. It does read the reports each 8 msecs (if a report is coming that often) and buffers the reports. The time lag now happens in the read of the python thread. It may simply not get CPU time at all. So you do not lose reports, but you may get any length of time lags.
dimaq
Posts: 4
Joined: Wed Dec 29, 2004 9:02 pm
Location: Helsinki
Contact:

Post by dimaq »

Thanks for all the useful reponses.

I narrowed the problem down to timeout set on DeviceHandle.interruptRead() (python wrapper on libusb): if I set a large timeout, I get all the events - I could test down to 3ms pulse. However if I set a short timeout - 10ms or shorter - it start losing reports, about 1 out of 10 at 10ms. So apparentely iow/OS usb stack/libusb/etc. does not buffer those reports. Does anyone know how I can change this?

I used polling (short timeouts) specifically because I read that libusb is not multithreaded and I wanted to send some control messages to iow.

Perhaps blocking on interrupt read in one thread and sending control messages from the other might work even though libusb is not thread-safe for a given handle.

Otherwise I may have to add a latch on my signal.
Guido Körber
Site Admin
Posts: 2856
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Post by Guido Körber »

I am not sure what you are doing there, but it is impossible to get 3msec pulses reliably using an IOW24 or IOW40. These chips can send data only every 8msec, which is the rate at which the host controller polls them.

It is possible to get the reports for two changes that happen in less than 8msec because the IO-Warriors are double buffering the data internally, one report in the transmit buffer and another in the status buffer. But if another change does happen before the status buffer can be loaded into the transmit buffer you will lose the older status.
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

dimaq wrote: Perhaps blocking on interrupt read in one thread and sending control messages from the other might work even though libusb is not thread-safe for a given handle.
Believe me, I tried it, it doesn't work. Sorry! It will mess up your app at some point. Might take a few minutes ;-), but it will happen!

Eberhard
Robert Marquardt
Posts: 543
Joined: Mon Dec 01, 2003 6:09 pm

Post by Robert Marquardt »

Setting the timeout IowKitSetTimeout low does not make sense. It is only for making the read fail after some time if *no* data comes.
The Windows HID driver buffers reports and the iowkit.dll buffers reports. Each 128 of them so there is no data loss for 8 * 128 msecs = 1 sec. Not 2 secs because the reader thread of iowkit.dll keeps the Windows queue dry.
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

Robert Marquardt wrote:Setting the timeout IowKitSetTimeout .......
The OP was talking about the timeout in the read-function from libusb. He is not using the IowKit-lib at all.

Eberhard
dimaq
Posts: 4
Joined: Wed Dec 29, 2004 9:02 pm
Location: Helsinki
Contact:

Solved!

Post by dimaq »

Sorry for ms confusion - my events are normally 70ms long and I managed losing those. I don't really care about pulse length, I only need to count the pulses

I resolved the issue by adjusting the report frequency, now when I get "idle" reports often, I can set a long timeout on bulkRead() and still wake up often enough to do other things in the usb thread.

Sadly python's interface to libusb does not release the GIL when it waits for usb data, thus multithreading is still rough - this was resolved by adding a small time.sleep() after each usb call - that way other python threads don't starve.

Thanks for your comments
Post Reply