Документ взят из кэша поисковой машины. Адрес оригинального документа : http://mavr.sao.ru/hq/sts/linux/comedi/doc/x94.html
Дата изменения: Unknown
Дата индексирования: Fri Dec 28 19:16:03 2007
Кодировка:

Поисковые слова: interacting galaxies
Writing programs that use comedi and comedilib

3. Writing programs that use comedi and comedilib

3.1. Your first comedi program

This example requires a card that has analog or digital input. Right to the source:

#include <stdio.h>	/* for printf() */
#include <comedilib.h>

int subdev = 0;		/* change this to your input subdevice */
int chan = 0;		/* change this to your channel */
int range = 0;		/* more on this later */
int aref = AREF_GROUND;	/* more on this later */

int main(int argc,char *argv[])
{
	comedi_t *it;
	lsampl_t data;

	it=comedi_open("/dev/comedi0");
	
	comedi_data_read(it,subdev,chan,range,aref,&data);
	
	printf("%d\n",data);
	
	return 0;
}

Should be understandable: open the device, get the data, print it out. This is basically the guts of demo/inp.c, without error checking or fancy options. Compile it using

cc tut1.c -lcomedi -o tut1

A few notes: The range variable tells comedi which gain to use when measuring an analog voltage. Since we don't know (yet) which numbers are valid, or what each means, we'll use 0, because it won't cause errors. Likewise with aref, which determines the analog reference used.

3.2. Converting samples to voltages

If you selected an analog input subdevice, you probably noticed that the output of tut1 is a number between 0 and 4095, or 0 and 65535, depending on the number of bits in the A/D converter. Comedi samples are always unsigned, with 0 representing the lowest voltage of the ADC, and 4095 the highest. Comedi compensates for anything else the manual for your device says. However, you probably prefer to have this number translated to a voltage. Naturally, as a good programmer, your first question is: "How do I do this in a device-independent manner?"

Most devices give you a choice of gain and unipolar/bipolar input, and Comedi allows you to select which of these to use. This parameter is called the "range parameter", since it specifies the "input range" for analog input (or "output range" for analog output.) The range parameter represents both the gain and the unipolar/bipolar aspects.

Comedi keeps the number of available ranges and the largest sample value for each subdevice/channel combination. (Some devices allow different input/output ranges for different channels in a subdevice.)

The largest sample value can be found using the function:

comedi_get_maxdata()

The number of available ranges can be found using the function:

comedi_get_n_ranges()

For each value of the range parameter for a particular subdevice/channel, you can get range information using the function:

   ptr=comedi_get_range(comedi_file,subdevice,channel,
	range);

which returns a pointer to a comedi_range structure. The comedi_range structure looks like

typedef struct{
        double min;
        double max;
        unsigned int unit;
}comedi_range;

The structure element 'min' represents the voltage corresponding to comedi_data_read() returning 0, and 'max' represents comedi_data_read() returning 'maxdata', (i.e., 4095 for 12 bit A/C converters, 65535 for 16 bit, or, 1 for digital input -- more on this in a bit.) The 'unit' entry tells you if min and max refer to voltage, current, etc.

"Could it get easier?", you say. Well, yes. Use the function comedi_to_phys(), which converts data values to physical units. Call it using something like

volts=comedi_to_phys(it,data,range,maxdata);

and the opposite

data=comedi_from_phys(it,volts,range,maxdata);

3.3. Another section

In addition to providing low level routines for data access, the comedi library provides higher-level access, much like the standard C library provides fopen(), etc. as a high-level (and portable) alternative to the direct UNIX system calls open(), etc. Similarily to fopen(), we have comedi_open():

file=comedi_open("/dev/comedi0");

where file is of type (comedi_t *). This function calls open(), like we did explicitly in a previous section, but also fills the comedi_t structure with lots of goodies -- information that we will need to use soon.

Specifically, we needed to know maxdata for a specific subdevice/channel. How about:

maxdata=comedi_get_maxdata(file,subdevice,channel);

Wow. How easy. And the range type?

range_type=comedi_get_rangetype(file,subdevice,channel);

Cool. Other information you need to know about a channel can be gotten in a similar way.

3.4. Your second comedi program

Actually, this is the first comedi program again, just that we've added what we've learned.

#include <stdio.h>      /* for printf() */
#include <comedi.h>     /* also included by comedilib.h */
#include <comedilib.h>  /* 'cuz we're using comedilib */

int subdev = 0;         /* change this to your input subdevice */
int chan = 0;           /* change this to your channel */
int range = 0;          /* more on this later */
int aref = 0;           /* more on this later */

int main(int argc,char *argv[])
{
        comedi_t *cf;
        int chan=0;
        lsampl_t data;
	int maxdata,rangetype;
	double volts;

        cf=comedi_open("/dev/comedi0");

	maxdata=comedi_get_maxdata(cf,subdev,chan);

	rangetype=comedi_get_rangetype(cf,subdev,chan);

        comedi_data_read(cf->fd,subdev,chan,range,aref,&data);

	volts=comedi_to_phys(data,rangetype,range,maxdata);

        printf("%d %g\n",data,volts);

        return 0;
}