Forums > Dev

emits floats outlets by NIDAQmx driver in an external

June 18, 2007 | 3:48 pm

Hi to all
I have this problem: i’m actually using a NIDAQmx 6008i card on WinXp, and i have the need of write an external that take care of its driver via the API provided.
The external should have ideally two messages ("start" and "stop") over the main inlet, and probably some arguments to set up the card. Then i should map all the phisical channel as outlets, in order to control the device in the best simple and intuitive way (i mean: i want to offer 8 outlets, even if i could use only some of them on some patch). These outlets should offer 8 floating point values, updating them in real time as they come from the card.

The card offer by API an integrated task-based system, based on an internal clock. At the moment i was able to write my external and start/stop the reading task over the phisical channels of the device: i write the values on the MAX window using a simple "post" function: the problem i still have is to transfer the value i read from the card in the 8 outlets. I’m not sure i have correctly understand in the manual what is the right method to write a value "into" an outlet, and what kind of data structure i should use for internal rapresentation of a float value to be send to the outlet.
In the example "thresh", for example, the value are updated by an internal clock watch, and the value are inserted from the user… i have indeed the need of generate the values from the reading task of the card and being able to emits them by the outlets… i hope i was clear in the description.

Sorry if this was a dummy question, thanks for the support

Alfredo Serafini


June 18, 2007 | 4:00 pm

hello seralf,
look at the SDK pdf or the maximum.c source file in the SDK:

use floatout() [see p.53 pdf/ line 161 maximum.c] to create an outlet
in your new() function. beware of the fact that these need to be
created in reverse right to left order.

call outlet_float() [see p.60 / line 88 in maximum.c] to output your
float value through the corresponding outlet.

hth

/*j

On 18/06/2007, at 17:48:31, seralf wrote:

>
> Hi to all
> I have this problem: i’m actually using a NIDAQmx 6008i card on
> WinXp, and i have the need of write an external that take care of
> its driver via the API provided.
> The external should have ideally two messages ("start" and "stop")
> over the main inlet, and probably some arguments to set up the
> card. Then i should map all the phisical channel as outlets, in
> order to control the device in the best simple and intuitive way (i
> mean: i want to offer 8 outlets, even if i could use only some of
> them on some patch). These outlets should offer 8 floating point
> values, updating them in real time as they come from the card.
>
> The card offer by API an integrated task-based system, based on an
> internal clock. At the moment i was able to write my external and
> start/stop the reading task over the phisical channels of the
> device: i write the values on the MAX window using a simple "post"
> function: the problem i still have is to transfer the value i read
> from the card in the 8 outlets. I’m not sure i have correctly
> understand in the manual what is the right method to write a value
> "into" an outlet, and what kind of data structure i should use for
> internal rapresentation of a float value to be send to the outlet.
> In the example "thresh", for example, the value are updated by an
> internal clock watch, and the value are inserted from the user… i
> have indeed the need of generate the values from the reading task
> of the card and being able to emits them by the outlets… i hope i
> was clear in the description.
>
> Sorry if this was a dummy question, thanks for the support
>
> Alfredo Serafini


June 18, 2007 | 6:04 pm

thanks for the help, jasch.

i look at "minimum" example, but my problem is that i have a callback function that does the reading task over every sample… the code works well if i take those samples and just print them in the MAX console, but if i try to use outlet_float() instead of print them, the program crashes.

Probably there is some problem with Threads or i do a wrong use of the reference for my outlets…?

i attach some little code (please note it is a very "working" version, based on "thresh" example :-), if you like to take a look over it to have a much clearer idea

suggestions are really welcome: i need this external to go well as it is intended to be used on a patch for my thesis very very soon… and maybe i have too much "rusty" C/C++ skills :-/

thanks very much for your reply, by the way, Alfredo


June 18, 2007 | 6:10 pm

I haven’t looked at the code example, but you typically can’t use
object outlets from threads other than the main one. You might look
at the defer() and defer_low() functions for a relatively painless
way to get back to the main thread from your callback.

jb

Am 18.06.2007 um 20:04 schrieb seralf:

> Probably there is some problem with Threads or i do a wrong use of
> the reference for my outlets…?


June 18, 2007 | 6:27 pm

thanks Jeremy, i’ll take a look on that on the manual: i didn’t know that function

Alfredo Serafini


June 19, 2007 | 4:27 am

i’m trying to use the defer_low() method without good results… can you please suggest me a very simple example, in order i could understand the mechanism?

(thanks for the support and the suggestions)

AS


June 19, 2007 | 7:55 am

void deferfun(t_myobject *x, t_symbol *s, long ac, t_atom *av)
{
if (ac && av && av->a_type == A_FLOAT) {
outlet_float(x->an_outlet, atom_getfloat(av));
}
}

void threadfun(t_myobject *x, double val)
{
t_atom a;

atom_setfloat(&a, val);
defer_low(x, (method)deferfun, NULL, 1, &a);
}

Am 19.06.2007 um 06:27 schrieb seralf:

>
> i’m trying to use the defer_low() method without good results…
> can you please suggest me a very simple example, in order i could
> understand the mechanism?
>
> (thanks for the support and the suggestions)
>
> AS


June 20, 2007 | 10:57 am

thanks very much to Jeremy to the fast reply and the example snippet.
I made several test using that example, but i still have problems.
If i don’t make use of the method defer_low the program crashes, if i use it the program slow down and down and then it seems to be blocked.
The fact is that if i write the samples taken from the card in the output window of MAX, they are written very fast and without problem, and i’m able to control the output with a simple "start"/"stop" message system to the first outlet of my external.
Indeed if i try to write the same values to the outlets the program crashes or blocks, as i say before.
How is it possible that in the output window i have no problem, and still i have in acting on outlets? are the two context managed by different threads maybe? any suggestions? i expect i could write in the same way any value in two context, i expect i have only difference regarding how to write the data structure (in the output window i only write long or float values)

my question is: taking for example the "uzi" internal (imagine an uzi with an infinite number of repetitions), is it possible to have an idea of its own implementation? maybe could fit my needs, a bit.

any suggestions are really welcome: i have to fix this problem as soon as possible, and i have no more idea on how i could :-(


June 20, 2007 | 11:42 am

OK, you’re causing the event queue to get backed up. Can you post the
code you’re using in your perform() method?

Probably here’s what you want to do:

As new values come in, buffer them to a static array somewhere.
Periodically flush this array (use a clock or qelem to do so). You
should be able to avoid the backlog if you don’t defer for every value.

jb

Am 20.06.2007 um 12:57 schrieb seralf:

> If i don’t make use of the method defer_low the program crashes, if
> i use it the program slow down and down and then it seems to be
> blocked.


June 20, 2007 | 2:58 pm

thanks for the good suggestions Jeremy.
I was thinking at the possibility to go and use a clock() or a quelem(), but i’m really new to write externals… (this is my first: i know i could start with something less particular, but i had no choice: i need this :-)
now i’m reading the manual and searching in the examples in order to understand how i could use the clock or quelem system.

I started my coding on the thresh example, then i converted my dataBuffer structure in a static structure: i was on the right way, then. But in this direction i don’t understand that much how to register a method to act periodically, when i need it to flush the values from my static buffer to the specifi outlets.

As you ask for a snippet, i attach my actual working code (i tried to make it a little more readable, sorry for the disorder)

as you could see there is a callback method (called from a thread managed by the card driver) called "EveryNSamplesCallback" that reads the samples…

you could see into that a line suche this:
post(…dataBuffer[i]);

in which i simply read the samples in order (and correctly print them on the output window). What i need to do is "simply" to put them in the specific outlets: i imagine i must code a method who acts the output to the outlets at some clock time, but i didn’t yet understand how… i’m looking at manuals and examples.

thanks very much for your support, by the way

Alfredo


June 20, 2007 | 3:13 pm

OK, were you previously calling defer_low 8 times at this point? If
so, you might try the following, which probably won’t back up the
scheduler, presuming that your callback isn’t being called every 8
samples. If it is, then you likely will need to do some buffering.

jb

t_atom a[8];

for (i = 0; i < 8; i++)
atom_setfloat(a+i, dataBuffer[i]);

defer_low(x, (method)outputfun, NULL, 8, a);

Then in outputfun:

void outputfun(t_myobj *x, t_symbol *s, long ac, t_atom *av)
{
for (i = 0; i < ac; i++)
outlet_float(x->out+i, atom_getfloat(av+i));
}

This presumes that you allocated your outlets as an array of void*s
beginning at x->out.

jb

Am 20.06.2007 um 16:58 schrieb seralf:

> in which i simply read the samples in order (and correctly print
> them on the output window). What i need to do is "simply" to put
> them in the specific outlets: i imagine i must code a method who
> acts the output to the outlets at some clock time, but i didn’t yet
> understand how… i’m looking at manuals and examples.


June 20, 2007 | 3:17 pm

>> OK, were you previously calling defer_low 8 times at this point?
yes, i did call defer_low into this cycle…

thanks for the example, i’ll try to follow your suggestion and i will let you know (i see that probably i have done some confusion here)

A.


June 21, 2007 | 5:05 am

i’m actually reading the section dedicated to qelem or clocks (i think qelem maybe could be the right choice)

introducing defer_low mechanism, i still have two problems:
1. to be able to update the values in the outlet: i used the inlets as in thresh example, then i have done some experiment on how to update their values, with no good results. Ok, this is surely a problem of mine: i must have done something wrong on the code, and i’ll fix it
2. stricly dependant on the precedent, i think: no way to update the value with the sample values i read from the card. The good news is that the mechanism it’s ok regarding the crashes: MAX does’nt crashes at all, then i am probably near to a fine solution (thanks to Jeremy). The values in my callback function are right, i have the problem of putting them in some atom structure for outputting them on outlets, and then "refresh" the outlets values (maybe i should invoke the _bang method from my callback simulating an input from user?)

i attach the last working-copy of the code, if like to propose to me some fix or snippet, thanks

(At the moment i’m working on a simple example on how to use clocks & qelems)

thanks, A.


June 21, 2007 | 9:07 am

A -

Let’s back up for a second. I think you’re grasping at tools without
necessary thinking through what the problem is that you’re trying to
solve.

How should your object function?

- The object receives values constantly, but outputs nothing until
the user sends a bang message (or the object polls itself, as if it
had an internal metronome). It then outputs the most recent values it
received.

- The object outputs values as soon as it receives them.

***

Your object appears to have 9 outlets:

- What are those outlets for?

- How do they function? The 8 to the right seem to send out a single
float value, but the 1 on the left appears to send out a list.

- What is the difference between the data being output from the
different outlets?

***

This should get us started.

jb

Am 21.06.2007 um 07:05 schrieb seralf:

> i’m actually reading the section dedicated to qelem or clocks (i
> think qelem maybe could be the right choice)
>
> introducing defer_low mechanism, i still have two problems:
> 1. to be able to update the values in the outlet: i used the inlets
> as in thresh example, then i have done some experiment on how to
> update their values, with no good results. Ok, this is surely a
> problem of mine: i must have done something wrong on the code, and
> i’ll fix it
> 2. stricly dependant on the precedent, i think: no way to update
> the value with the sample values i read from the card. The good
> news is that the mechanism it’s ok regarding the crashes: MAX
> does’nt crashes at all, then i am probably near to a fine solution
> (thanks to Jeremy). The values in my callback function are right, i
> have the problem of putting them in some atom structure for
> outputting them on outlets, and then "refresh" the outlets values
> (maybe i should invoke the _bang method from my callback simulating
> an input from user?)
>
> i attach the last working-copy of the code, if like to propose to
> me some fix or snippet, thanks
>
> (At the moment i’m working on a simple example on how to use clocks
> & qelems)
>
> thanks, A.
>


June 21, 2007 | 12:16 pm

yes, i know i must seem to be working with no idea :-)

the fact is that i have to make the things working and my code is not that "beautiful", at the moment…

please consider only the outlet from 0 to 7, the last has remains fsince i have used as a start-up for my code the "thresh" example, and i leave it there because i could use it (it is yet coded) for others data. If i will find no intereset in other data, i will remove that part. Sorry for being not that much clear on this point.

>> How should your object function?
The card receive voltages from a couple of sensors, and translates them in 8 samples channels: the standard reading messages is the one i used with the callback function.
At the moment the object receive two very simple mssages (start and stop) to control the reading, which is continuous (at about internal card clock rate), and is able to write the values correctly in the max ouput window with no problem. The values readen are stored in a static buffer dataBuffer[],in order to be transferred to the outlets objects.
if i try to write to the outlets for every sample, the program crashes… with the introduction of a defer mechanism seems to be ok, but i have problems in update the value: they are correctly printed in output but no way to write them in an outlet… seems like i must do some bang or some "refresh" to see the results changing in real time

i hope i was much clearer about my needs, sorry for some confusion, and thanks for the interest

Alfredo


June 21, 2007 | 12:38 pm

Here is a modified version of your file. I’ve disabled everything
which looked useless for your described needs. I haven’t tried to
compile this, but it should work. You don’t need clocks or qelems,
presuming that this doesn’t backlog the scheduler.

Note that we’re sending the 8 values to output to the defer_low
function. They are copied and arrive at the function where the
outlets are triggered in the main thread. You don’t need to save
these values – just pass them into defer_low.

Give it a try
jb

Am 21.06.2007 um 14:16 schrieb seralf:

>
> yes, i know i must seem to be working with no idea :-)
>
> the fact is that i have to make the things working and my code is
> not that "beautiful", at the moment…
>
> please consider only the outlet from 0 to 7, the last has remains
> fsince i have used as a start-up for my code the "thresh" example,
> and i leave it there because i could use it (it is yet coded) for
> others data. If i will find no intereset in other data, i will
> remove that part. Sorry for being not that much clear on this point.
>
>>> How should your object function?
> The card receive voltages from a couple of sensors, and translates
> them in 8 samples channels: the standard reading messages is the
> one i used with the callback function.
> At the moment the object receive two very simple mssages (start and
> stop) to control the reading, which is continuous (at about
> internal card clock rate), and is able to write the values
> correctly in the max ouput window with no problem. The values
> readen are stored in a static buffer dataBuffer[],in order to be
> transferred to the outlets objects.
> if i try to write to the outlets for every sample, the program
> crashes… with the introduction of a defer mechanism seems to be
> ok, but i have problems in update the value: they are correctly
> printed in output but no way to write them in an outlet… seems
> like i must do some bang or some "refresh" to see the results
> changing in real time
>
> i hope i was much clearer about my needs, sorry for some confusion,
> and thanks for the interest
>
> Alfredo


June 21, 2007 | 1:41 pm

thanks for yout time jeremy, but i see no attachment. could you please re-post?


June 21, 2007 | 1:45 pm

Try this.


June 21, 2007 | 2:22 pm

ok, thanks Jeremy.
i’ve tested your version:
1. in the output window all it’s ok: every sample is still correctly readen from the card and written
2. the program doesn’t crashes (defer_low seems to work good)
3. but the outlets don’t yet update their values: i verify this also connecting them to a "print" and a "bang" object in my patch, in order to see if something it’s given.
no outlets seems to bang when i start the reading process, then they receive no updated values… (i think i will go crazy on that thing)

i attach the last working copy of the code, if could be useful to you too to see i have made no others errors(i have removed the part not useful at all, maybe it’s more readable for you now, sorry)

thanks for your suggestions, and sorry for the time i’m stealing from you

Alfredo


June 21, 2007 | 2:32 pm

Alfredo,

Can you please put a post in the buffer2outlets function and verify
that it’s getting called? This is where the outlets should be firing.

Am 21.06.2007 um 16:22 schrieb seralf:

> i attach the last working copy of the code, if could be useful to
> you too to see i have made no others errors(i have removed the part
> not useful at all, maybe it’s more readable for you now, sorry)
>
>
> thanks for your suggestions, and sorry for the time i’m stealing
> from you

No worries – I’m home with a bad cold today, this is at least keeping
me amused. :D

jb


June 21, 2007 | 3:05 pm

(a bad cold? uh… here in rome we have a wheater inspired by Sahara)

you’re right: the method seems to miss
any suggestion?


June 21, 2007 | 3:16 pm

You need to verify that you’re loading the current version of the
external. As it’s written, that function should be getting called.
Double-check that there’s only one copy of the external where Max can
find it (the most recent!), and that you’re quitting and restarting
Max between tests.

jb

Am 21.06.2007 um 17:05 schrieb seralf:

>
> (a bad cold? uh… here in rome we have a wheater inspired by Sahara)
>
> you’re right: the method seems to miss
> any suggestion?


June 21, 2007 | 3:20 pm

yes, i rebuild the external every time, in order to avoid confusion about the version.
Regarding to max i have to close it every time, because it locks the object, or i can’t re-build it


June 23, 2007 | 5:05 am

Ok i have a (very-beta) version.
In order to make it work i have to use a clock system: no way to let it work with the defer system, probably i’m wrong with something, but it’s my first external and also the first time i write C code from long time… if you have any suggestion i still listen.
At the moment the object is really simple and i’m think about writing a system to let it receive arguments, instead of coding its start-up parametrization directly in the code, but it goes.
The aspect i don’t like at all is about the control side-effects of using a clock: i mean it seems to me to introduce another control-rate, with problems i should take care of, about Shannon-Nyquist Theorem and things like that… maybe am i wrong?
any suggestion are welcome, and thanks for all the precious help.

Alfredo Serafini


June 23, 2007 | 7:34 am

Try clock_delay(x->clock, 0);

jb

Am 23.06.2007 um 07:05 schrieb seralf:

> The aspect i don’t like at all is about the control side-effects of
> using a clock: i mean it seems to me to introduce another control-
> rate, with problems i should take care of, about Shannon-Nyquist
> Theorem and things like that… maybe am i wrong?


June 23, 2007 | 4:56 pm

yes, i have tried… at the moment i use a value round 25 and it’s ok: i saw that a too much little value causes the program to crash, maybe it reproduce a similar problem to the precedent…

i will take you informed :-)


Viewing 26 posts - 1 through 26 (of 26 total)