1 <?xml version="1.0" encoding="utf-8"?>
2 <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3 "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
4 <!ENTITY % comedilib_entities SYSTEM "comedilib.ent">
8 <section id="writingprograms" xmlns:xi="http://www.w3.org/2001/XInclude">
10 Writing &comedi; programs
13 This section describes how &comedi;
14 can be used in an application, to communicate data with a set
16 <xref linkend="acquisitionfunctions"/> gives more details about
17 the various acquisition functions with which the application
18 programmer can perform data acquisition in &comedi;.
21 Also don't forget to take a good look at the
22 <filename class="directory">demo</filename>
23 directory of the Comedilib source code. It contains lots of examples
24 for the basic functionalities of &comedi;.
27 <section id="firstprogram">
29 Your first &comedi; program
33 This example requires a card that has analog or digital input. This
34 progam opens the device, gets the data, and prints it out:
36 <xi:include href="../demo/tut1.c" parse="text"/>
40 The source code file for the above program can be found in Comedilib,
41 at <filename>demo/tut1.c</filename>. You can compile the program using
45 cc tut1.c -lcomedi -lm -o tut1
50 <link linkend="func-ref-comedi-open">comedi_open</link>
51 </function> call can only be successful if the
52 <filename>comedi0</filename> device file is configured with a
53 valid &comedi; driver. <xref linkend="cardconfiguration"/> explains
54 how this driver is linked to the <quote>device file</quote>.
57 The <parameter class="function">range</parameter> variable tells
58 &comedi; which gain to use when measuring an analog voltage. Since we
59 don't know (yet) which numbers are valid, or what each means, we'll
60 use <literal>0</literal>, because it won't cause errors. Likewise
61 with <parameter class="function">aref</parameter>, which determines the
62 analog reference used.
67 <section id="convertingsamples">
69 Converting between integer data and physical units
73 If you selected an analog input subdevice, you probably noticed
74 that the output of <command>tut1</command> is an unsigned
75 number, for example between <literal>0</literal>
76 and <literal>65535</literal> for a 16 bit analog input. &comedi;
77 samples are unsigned, with <literal>0</literal> representing the
78 lowest voltage of the ADC, and a hardware-dependent maximum
79 value representing the highest voltage. &comedi; compensates
80 for anything else the manual for your device says (for example,
81 many boards represent bipolar analog input voltages as signed
82 integers). However, you probably prefer to have this number
83 translated to a voltage. Naturally, as a good programmer, your
84 first question is: <quote>How do I do this in a
85 device-independent manner?</quote>
90 <function><link linkend="func-ref-comedi-to-physical">comedi_to_physical</link></function>, <function><link linkend="func-ref-comedi-to-phys">comedi_to_phys</link></function>,
91 <function><link linkend="func-ref-comedi-from-physical">comedi_from_physical</link></function> and <function><link linkend="func-ref-comedi-from-phys">comedi_from_phys</link></function>
92 are used to convert between &comedi;'s integer data and floating point numbers corresponding
93 to physical values (voltages, etc.).
98 <section id="secondprogram">
100 Your second &comedi; program
105 Actually, this is the first &comedi; program again, except
106 we've added code to convert the integer data value to physical units.
110 <xi:include href="../demo/tut2.c" parse="text"/>
113 The source code file for the above program can be found in
114 the Comedilib source at <filename>demo/tut2.c</filename> and if
115 installed as a package usually at
116 <filename>/usr/share/doc/libcomedi-dev/demo/</filename> with all the
117 other tutorial/demo files.
121 <section id="asyncprogram">
123 Asynchronous acquisition
126 Of special importance is the so called
127 "asynchronous data acquisition" where &comedi; is sampling
128 in the background at a given sample rate. The
129 user can retrieve the data whenever it is convenient.
130 &comedi; stores the data in a ring-buffer so that
131 programs can perform other tasks in the foreground, for example
132 plotting data or interacting with the user.
133 This technique is used in programs such
134 as <command>ktimetrace</command> or <command>comedirecord</command>.
137 There are two different ways how a sequence of channels is
138 measured during asynchronous acquisition (see also the Figure in
142 The channels are measured with the help
143 of a multiplexer which switches to the next channel after each measurement.
144 This means that the sampling rate is divided by the number
148 The channels are all measured at the same time, for example
149 when every channel has its own converter. In this case the
150 sampling rate need not to be divided by the number of channels.
153 How your &comedi; device handles the asynchronous acquisition can be found out
154 with the command <command>comedi_board_info -v</command>.
157 The program <filename>demo/tut3.c</filename> demonstrates the
158 asynchronous acquisition. The general strategy is always
159 the same: first, we tell &comedi; all sampling parameters such as
161 the number of channels and anything it needs to know
162 so that it can run independently in the background.
163 Then &comedi; checks our request and it might
164 modify it. For example we might want to have a sampling rate of
165 16kHz but we only get 1kHz. Finally we can start
166 the asynchronous acquisition. Once it has been started we
167 need to check periodically if data is available and
168 request it from &comedi; so that its internal buffer
172 In summary the asynchonous acquisition is performed in the following
177 Create a command structure of type <type><link linkend="ref-type-comedi-cmd">comedi_cmd</link></type>
180 Call the function <function><link linkend="func-ref-comedi-get-cmd-generic-timed">comedi_get_cmd_generic_timed</link></function>
181 to fill the command structure with your comedi device,
182 subdevice, sampling rate and number of channels.
185 Create a channel-list and store it in the command structure. This
186 tells comedi which channels should be sampled in the background.
189 Call <function><link linkend="func-ref-comedi-command-test">comedi_command_test</link></function> with your command structure. Comedi might modify your requested sampling rate and channels.
192 Call <function><link linkend="func-ref-comedi-command-test">comedi_command_test</link></function> again which now should return zero for success.
195 Call <function><link linkend="func-ref-comedi-command">comedi_command</link></function> to start the asynchronous acquisition. From now on the kernel ringbuffer will be filled at the specified sampling rate.
198 Call periodically the standard
199 function <function>read</function> and receive the data. The
200 result should always be non zero as long as the acquisition
204 Convert the received data either into
205 <type><link linkend="ref-type-lsampl-t">lsampl_t</link></type> or
206 <type><link linkend="ref-type-sampl-t">sampl_t</link></type> depending
207 on the subdevice flag <constant>SDF_LSAMPL</constant>.
210 Poll for data with <function>read</function> as long as it returns
211 a positive result or until the program terminates.
216 The program below is a stripped down version of the
217 program <filename>cmd.c</filename> in the demo directory. To
221 gcc tut3.c -lcomedi -lm -o tut3
224 It requests data from two channels at
225 a sampling rate of 1kHz and a total of 10000 samples.
226 which are then printed to stdout. You can pipe the data
227 into a file and plot it with gnuplot. As mentioned above, central in this
228 program is the loop using the standard C <function>read</function> command
229 which receives the buffer contents. Below is an
230 extract from <filename>tut3.c</filename> showing the
234 <xi:include href="../demo/tut3_part.c" parse="text"/>
237 For advanced programmers the
238 function <function><link linkend="func-ref-comedi-get-buffer-contents">comedi_get_buffer_contents</link></function>
239 is useful to check if there is actually data in the ringbuffer
240 so that a call of <function>read</function> can be avoided for example
241 when the data readout is called by a timer call-back function.
246 <title>Further examples</title>
248 See the <filename>demo</filename> subdirectory of Comedilib
249 for more example programs. The directory contains a
250 <filename>README</filename> file with descriptions of the various