[comedi] [usbdux-fast] 3 channel data oddities

59 views
Skip to first unread message

Thor Andreassen

unread,
Sep 12, 2011, 6:54:52 AM9/12/11
to comed...@googlegroups.com
Hi, I've happily continued my fiddling around with the usbduxfast.

The application I'm working towards, which is ultrasonic reception,
requires a fairly high sample rate, so I was hoping I could run it
with 3 channels at 500KHz, but I get odd results. Thus I tried the test
program provided at [1], this gives the expected results for 16 and 2
channels, but not for 3 [2], the input signal is a 1KHz sinusoid with
800mVpp.

For the above test I only changed the channel number on line 92 and
recompiled, is this the right way to go about it?

I've read about the 3 channel limitation on this mailinglist and in the
driver source code, but I cannot determine if this is an inherent
hardware limitation, or if it could be possible to break it by improving
the firmware code?

[1] http://www.linux-usb-daq.co.uk/drivers2/test/usbduxfast_test.tar.gz
[2] http://postimage.org/gallery/1e99yx9ew/c9a1c0d4/

--
best regards
Thor Andreassen

Bernd Porr

unread,
Sep 12, 2011, 7:07:32 AM9/12/11
to comed...@googlegroups.com
Hi Thor,

if you want to sample with 4 channels then run the board at 16 channels
and connect your signal 0 to channel 0,4,8,12, your signal 1 to channel
1,5,9,13 and so on. Then re-shuffle the data once it's in the buffer.

The limitation is hardware related. The FX2 GPIF can only count to 3! In
the design I should have added feedback from the (external) counter to
the FX2 but the problem is that the GPIF is only a finite state machine
with 8 states. That limits things quite a lot.

If, then we need a hardware re-design and a change in the
firmware/driver. It's on my list but I have been busy developing a 24bit
sigma delta board recently. Once that's out then I'll have a look.

/Bernd

--
www: http://www.berndporr.me.uk/
http://www.linux-usb-daq.co.uk/
http://www.imdb.com/name/nm3293421/
Mobile: +44 (0)7840 340069
Work: +44 (0)141 330 5237
University of Glasgow
School of Engineering
72 Oakfield Avenue (Rankine Building for deliveries)
Glasgow, G12 8LT

Thor Andreassen

unread,
Sep 13, 2011, 5:55:59 AM9/13/11
to comed...@googlegroups.com
On Mon, Sep 12, 2011 at 12:07:32PM +0100, Bernd Porr wrote:
> Hi Thor,

Hi Bernd, thank you very much for all your help.



> if you want to sample with 4 channels then run the board at 16
> channels and connect your signal 0 to channel 0,4,8,12, your signal
> 1 to channel 1,5,9,13 and so on. Then re-shuffle the data once it's
> in the buffer.

Of course that is the way to do it, effectively I get 4 times the sample
rate, excellent. Btw. if the data is emitted directly to stdout, like in
the attached program [*], the reshuffling can easily be done with the
sox [1] remix effect like so:

./adc | tee >(sox -c16 -t s16 - ch1.s16 remix 1 5 9 13) \
>(sox -c16 -t s16 - ch2.s16 remix 2 6 10 14) \
>(sox -c16 -t s16 - ch3.s16 remix 3 7 11 15) \
>(sox -c16 -t s16 - ch4.s16 remix 4 8 12 16)

> The limitation is hardware related. The FX2 GPIF can only count to
> 3! In the design I should have added feedback from the (external)
> counter to the FX2 but the problem is that the GPIF is only a finite
> state machine with 8 states. That limits things quite a lot.

Ok.

[...]

So now I get the desired sample rate in the desired number of channels,
this is great, only trouble is that I can't seem to get continuous
acquisition to work.

To simplify matters I tried reducing the cmd.c program to only the
essential parts (see attached), when I run this program it inevitably
hangs on a read call. The symptoms are very similar to what Jan-Matthias
described here [2], might it be a similar issue?

To make sure it wasn't my reduction that caused it, I tried increasing
n_scan in the cmd.c program to a million, and this causes the same
symptoms.

On a side note, I've tried to find someway to make the acquisition event
driven, eg. with callback functions, but found nothing in the API that
allows this, am I blind or is it not supported?

[*] Compile with: gcc -Wall -lcomedi -lm adc.c -o adc

[1] http://sox.sf.net/
[2] http://groups.google.com/group/comedi_list/browse_thread/thread/08a7a15a09d238dd

adc.c

Bernd Porr

unread,
Sep 13, 2011, 6:56:50 AM9/13/11
to comed...@googlegroups.com
Hi Thor,

I've played a bit with your code. The issue is not comedi but writing to
stdout which seems to be way too slow. I put a write to /dev/null in it
and it runs forever. If you look into dmesg you will get a comedi buffer
overflow. The bugs you are referring have been fixed a while ago. I
remember that a buffer overflow left the driver in an undefined state
but that has been fixed. So, the bottomline is that you need to save
your data somewhere quickly or increase the write buffer dramatically so
that the hard drive store the data more effectively.

/Bernd

--

Mobile: +44 (0)7840 340069
Work: +44 (0)141 330 5237
University of Glasgow
School of Engineering

72 Oakfield Avenue (for deliveries: Rankine Building)
Glasgow, G12 8LT

adc.c

Bernd Porr

unread,
Sep 13, 2011, 6:57:53 AM9/13/11
to comed...@googlegroups.com
forgotten to say: Very cool commandline!

./adc | tee >(sox -c16 -t s16 - ch1.s16 remix 1 5 9 13) \
>(sox -c16 -t s16 - ch2.s16 remix 2 6 10 14) \
>(sox -c16 -t s16 - ch3.s16 remix 3 7 11 15) \
>(sox -c16 -t s16 - ch4.s16 remix 4 8 12 16)

/Bernd

--

Mobile: +44 (0)7840 340069
Work: +44 (0)141 330 5237
University of Glasgow
School of Engineering

Thor Andreassen

unread,
Sep 13, 2011, 11:53:13 AM9/13/11
to comed...@googlegroups.com
Hi Bernd thank you for your help.

I used the attached patch to test writing to a file. I get almost
identical results.

I tried comparing the straces of the two scenarios (sorry for any line
wrapping).

strace ./adc > /dev/null

ends with

8<-------8<-------8<-------8<-------8<-------
...
write(1, "+\10(\10\5\10\355\7\376\7\366\7\376\7\376\7\34\10\34\10\361\7\360\7\35\10\34\10\377\7\17\10"..., 4096) = 4096
write(1, "\37\10\357\7\357\7\37\10\33\10\0\10\20\10+\10'\10\6\10\355\7\375\7\365\7\376\7\0\10\33\10"..., 4096) = 4096
read(3, "\356\7\36\10\33\10\377\7\16\10+\10'\10\0\10\355\7\374\7\364\7\374\7\376\7\33\10\37\10\357\7"..., 4096) = 1536
read(3, "$\10\362\7\360\7\35\10\34\10\377\7\17\10,\10&\10\4\10\356\7\0\10\365\7\375\7\376\7\32\10"..., 4096) = 1024
read(3,
8<-------8<-------8<-------8<-------8<-------

and

strace ./adcf

ends with

8<-------8<-------8<-------8<-------8<-------
...
write(3, "\365\7\372\7\375\7\31\10\35\10\360\7\356\7\34\10\32\10\377\7\17\10*\10&\10\3\10\355\7\374\7"..., 4096) = 4096
read(4, "\357\7\36\10\32\10\375\7\17\10,\10%\10\4\10\357\7\376\7\364\7\373\7\0\10\35\10\33\10\357\7"..., 4096) = 3072
read(4, "\355\7\37\10\34\10\0\10\17\10-\10(\10\5\10\355\7\375\7\365\7\376\7\0\10\33\10\33\10\360\7"..., 4096) = 1536
read(4, "\375\7\365\7\374\7\375\7\33\10\34\10\357\7\355\7\36\10\34\10\377\7\17\10+\10(\10\5\10\356\7"..., 4096) = 1024
read(4,
8<-------8<-------8<-------8<-------8<-------

Maybe it is platform specific? I'm running this with the precompiled
Debian kernel: linux-image-3.0.0-1-686-pae.

When I find time, I'll compile the driver from source, and see about
applying the changes discussed in [1] to drivers/usbduxfast.c.

[1] http://groups.google.com/group/comedi_list/browse_thread/thread/08a7a15a09d238dd

Thor

adc.patch

Bernd Porr

unread,
Sep 13, 2011, 12:52:50 PM9/13/11
to comed...@googlegroups.com
Hi,

3.0.0 should be absolutely fine and there's no need to patch anything in
the usbduxfast driver. I would rather experiment with different buffer
sizes to fix the problem. Note I used a read buffer of 1M and not just
4096 bytes. Do you get "buffer overflow" in dmesg?

/Bernd
P.S.: I just compiled from comedi.org and there seems to be a problem
but the kernel driver is def fine.

--

http://www.imdb.com/name/nm3293421/


Mobile: +44 (0)7840 340069
Work: +44 (0)141 330 5237
University of Glasgow
School of Engineering

Thor Andreassen

unread,
Sep 15, 2011, 9:21:17 AM9/15/11
to comed...@googlegroups.com
Hi,

Yes a "buffer overflow" message in dmesg accompanies the hanged read.

Increasing the buffer size and leaving the machine alone seems quite
stable, but when the machine load is increased an overflow usually
occurs.

Is there some way to release the hang or check if the read will hang? I
tried with poll.c from the demo directory, but it exhibits the same
issues.

Thanks.

--
best regards
Thor Andreassen

Bernd Porr

unread,
Sep 15, 2011, 11:19:10 AM9/15/11
to comed...@googlegroups.com
Hi,

probably a good idea to incease the ringbuffer in the kernel space.
Sorry, can't remember the command but there is only in comedilib. The
other option is to increase the priotity of your program. There's also a
c call which uses a differnt scheduling model. Sorry. A bit in a rush.

/Bernd

Thor Andreassen wrote:
> Hi,
>
> Yes a "buffer overflow" message in dmesg accompanies the hanged read.
>
> Increasing the buffer size and leaving the machine alone seems quite
> stable, but when the machine load is increased an overflow usually
> occurs.
>
> Is there some way to release the hang or check if the read will hang? I
> tried with poll.c from the demo directory, but it exhibits the same
> issues.
>
> Thanks.
>

--

Mobile: +44 (0)7840 340069
Work: +44 (0)141 330 5237
University of Glasgow
School of Engineering

Thor Andreassen

unread,
Sep 22, 2011, 6:48:43 AM9/22/11
to comed...@googlegroups.com
Hi,

I'll try your suggestions and report back with my progress. It might be
awhile, as other matters have higher priority.

Thank you for your help.

--
best regards
Thor Andreassen

Bernd Porr

unread,
Sep 22, 2011, 7:20:14 AM9/22/11
to comed...@googlegroups.com
Hi Thor,

I've used this command (as root) to change the scheduler to SCHED_RR.
Setting this your program will run at the highest priority. Make sure
you have a sleep command somewhere in it because it might block all
other processes and you need to reboot your computer. It's a while I
used it so it's behaviour might be a bit nicer now.

/Bernd

SYNOPSIS
#include <sched.h>

int sched_setscheduler(pid_t pid, int policy,
const struct sched_param *param);

int sched_getscheduler(pid_t pid);

struct sched_param {
...
int sched_priority;
...
};

DESCRIPTION
sched_setscheduler() sets both the scheduling policy and the
associated
parameters for the process whose ID is specified in pid. If pid
equals
zero, the scheduling policy and parameters of the calling
process will
be set. The interpretation of the argument param depends
on the
selected policy. Currently, Linux supports the following
"normal"
(i.e., non-real-time) scheduling policies:

SCHED_OTHER the standard round-robin time-sharing policy;

SCHED_BATCH for "batch" style execution of processes; and

SCHED_IDLE for running very low priority background jobs.

The following "real-time" policies are also supported, for
special
time-critical applications that need precise control over the
way in
which runnable processes are selected for execution:

SCHED_FIFO a first-in, first-out policy; and

SCHED_RR a round-robin policy.


Thor Andreassen wrote:
> Hi,
>
> I'll try your suggestions and report back with my progress. It might be
> awhile, as other matters have higher priority.
>
> Thank you for your help.
>

--

Thor Andreassen

unread,
May 30, 2012, 8:22:25 AM5/30/12
to comed...@googlegroups.com

On Tuesday, September 13, 2011 11:55:59 AM UTC+2, Thor Andreassen wrote:

[...]
 

./adc | tee >(sox -c16 -t s16 - ch1.s16 remix 1 5  9 13) \
            >(sox -c16 -t s16 - ch2.s16 remix 2 6 10 14) \
            >(sox -c16 -t s16 - ch3.s16 remix 3 7 11 15) \
            >(sox -c16 -t s16 - ch4.s16 remix 4 8 12 16)

I realized that this could be simplified if 16 is divisible by the number of actual
channels you are using, e.g. if your total sample rate is 1MHz and you have four
channels the following would suffice:

./adc | sox -c4 -r250k -t s16 out.wav

Thor Andreassen

unread,
May 15, 2013, 4:17:53 AM5/15/13
to comed...@googlegroups.com

The input file (stdin) was missing from the above, the correct notation is:

./adc | sox -c4 -r250k -t s16 - out.wav
Reply all
Reply to author
Forward
0 new messages