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
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
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
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 | 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
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
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
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
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
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
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.
>
--
./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)