using outp.c

29 views
Skip to first unread message

mancane

unread,
Jun 4, 2009, 7:08:35 AM6/4/09
to Comedi: Linux Control and Measurement Device Interface
hi im tyring to output a digital/analog signal using outp.c

Im only having problems outputing the value that I want. for example i
wanna output an analog value of 5. how do I do that. also a hint on
how to use the digital part

Thanks

labrat

unread,
Jun 16, 2009, 3:27:14 PM6/16/09
to Comedi: Linux Control and Measurement Device Interface
On Jun 4, 7:08 am, mancane <ragha...@gmail.com> wrote:
> for example i wanna output an analog value of 5. how do I do that.

Either compute by hand the DAC bit value corresponding to 5 Volts, or
adapt my more user-friendly outp.c:

/*
* A little output demo
* Part of Comedilib
*
* Copyright (c) 1999,2000 David A. Schleef <d...@schleef.org>
*
* This file may be freely modified, distributed, and combined with
* other software, as long as proper attribution is given in the
* source code.
*/
/*
* A little output demo
*/

#include <stdio.h>
#include <comedilib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <getopt.h>
#include <ctype.h>
#include "examples.h"

comedi_t *device;

int main(int argc, char *argv[])
{
lsampl_t data;
int ret;
int maxdata, n_chans, n_ranges;
struct parsed_options options;

init_parsed_options(&options);
options.subdevice = -1;
options.n_chan = 1;
parse_options(&options, argc, argv, argv[0]);

device = comedi_open(options.filename);
if(device == NULL){
comedi_perror(options.filename);
exit(-1);
}

if (options.subdevice < 0) {
options.subdevice = comedi_find_subdevice_by_type(device,
COMEDI_SUBD_AO, 0);
if (options.verbose)
printf("Using subdevice %d\n", options.subdevice);
}

if (options.channel < 0) {
fprintf(stderr, "invalid channel: %d must be >= 0\n",
options.channel);
exit(-1);
}
n_chans = comedi_get_n_channels(device, options.subdevice);
if (options.channel >= n_chans) {
fprintf(stderr, "Invalid channel: %d > max chan %d\n",
options.channel, n_chans-1);
exit(1);
}
n_ranges = comedi_get_n_ranges(device, options.subdevice,
options.channel);
if (options.range >= n_ranges) {
fprintf(stderr, "Invalid range: %d > max range %d\n",
options.range, n_ranges-1);
exit(1);
}
maxdata = comedi_get_maxdata(device, options.subdevice,
options.channel);
if (options.physical) {
data = comedi_from_phys(options.value, comedi_get_range(device,
options.subdevice, options.channel, options.range), maxdata);
if (options.verbose > 1)
printf("Converted %g V to %d DAC bits\n", options.value, data);
} else {
data = (lsampl_t)options.value;
}
if (data > maxdata) {
fprintf(stderr, "Invalid data: %d > max data %d\n", data,
maxdata);
exit(1);
}

if(options.verbose >= 2){
printf("writing %d to device=%s subdevice=%d channel=%d range=%d
analog reference=%d\n",
data, options.filename, options.subdevice, options.channel,
options.range, options.aref);
}

ret = comedi_data_write(device, options.subdevice, options.channel,
options.range, options.aref, data);
if(ret < 0){
comedi_perror(options.filename);
if (options.verbose >=2)
fprintf(stderr, "check subdevice type with board_info\n");
exit(-1);
}

if(options.verbose >= 1)
printf("%d\n", data);

return 0;
}

labrat

unread,
Jun 16, 2009, 3:33:39 PM6/16/09
to Comedi: Linux Control and Measurement Device Interface
By the way, I've also got versions of inpn.c and dio.c that try and
use more of the struct parsed_options members. They even print usage
messages ;). This does make the code a bit more verbose, so I never
submitted a patch against comedilib with my versions, but I could if
people think they would be useful.

mancane

unread,
Jun 23, 2009, 10:32:33 AM6/23/09
to Comedi: Linux Control and Measurement Device Interface
Good day. I have managed to understand the ananlog output of the
outp.c Im now being confused by the digital part.

to make it easy for you to understand what Im stuck at : I wanna
control a 16 channel multiplexer. i need to control it digitally to
select the outputs. From the way multiplexers work im ok but to how to
put that in code Im struggling a bit.

Thanks

Ian Abbott

unread,
Jun 24, 2009, 8:25:00 AM6/24/09
to comed...@googlegroups.com
mancane wrote:
> Good day. I have managed to understand the ananlog output of the
> outp.c Im now being confused by the digital part.
>
> to make it easy for you to understand what Im stuck at : I wanna
> control a 16 channel multiplexer. i need to control it digitally to
> select the outputs. From the way multiplexers work im ok but to how to
> put that in code Im struggling a bit.

You can use the comedi_dio_bitfield() or comedi_dio_bitfield2()
functions to set the output bits of a DO or DIO subdevice. If it is a
DIO subdevice you need to configure the bits as outputs using the
comedi_dio_config() function.

--
-=( Ian Abbott @ MEV Ltd. E-mail: <abb...@mev.co.uk> )=-
-=( Tel: +44 (0)161 477 1898 FAX: +44 (0)161 718 3587 )=-

mancane

unread,
Jun 24, 2009, 8:57:05 AM6/24/09
to Comedi: Linux Control and Measurement Device Interface
Hi i have managed to do modify the outp. c code so that it can output
a digital bit using comedi_dio_write() function. so now what is
worrying me is that everytim i run it i have to specify that it must
choose subdevice 2 channel 1 and the specify the bit.

so in command when i run: ./outp -s2 -c1 0 which will write a 0 bit to
channel 1 of subdevice 2 which is my dio subdevice.
What i wanna achieve is that i run outp.c once and then it must write
digital bits to 4 channels at the same time without me specifying on
the command/terminal.

please look at my code. the commented out portions are from the outp.c
that comes with comedi to write a value/data

#include <stdio.h>
#include <comedilib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <getopt.h>
#include <ctype.h>
#include "examples.h"

comedi_t *device;


int main(int argc, char *argv[])
{

unsigned int bit;
//lsampl_t data;
int ret;
struct parsed_options options;

init_parsed_options(&options);
parse_options(&options, argc, argv);

device = comedi_open(options.filename);
if(!device){
comedi_perror(options.filename);
exit(-1);
}
bit = options.value;
// data = options.value;
if(options.verbose){


printf("writing %d to device=%s subdevice=%d channel=%d\n",bit,
options.filename, options.subdevice, options.channel);



//printf("writing %d to device=%s subdevice=%d channel=%d range=%d
analog reference=%d\n",
//data, options.filename, options.subdevice, options.channel,
options.range, options.aref);
}

ret = comedi_dio_write(device, options.subdevice,
options.channel,bit);

//ret = comedi_data_write(device, options.subdevice, options.channel,
options.range, options.aref, data); // need to chnage this line to use
for digital output. use comedi_dio_write();
if(ret < 0){
comedi_perror(options.filename);
exit(-1);
}

printf("%d\n",bit);
//printf("%d\n", data);

return 0;
}

The code outputs a digital bit to a specified channel only

Thanks




On Jun 24, 2:25 pm, Ian Abbott <abbo...@mev.co.uk> wrote:
> mancane wrote:
> > Good day. I have managed to understand the ananlog output of the
> > outp.c Im now being confused by the digital part.
>
> > to make it easy for you to understand what Im stuck at : I wanna
> > control a 16 channel multiplexer. i need to control it digitally to
> > select the outputs. From the way multiplexers work im ok but to how to
> > put that in code Im struggling a bit.
>
> You can use the comedi_dio_bitfield() or comedi_dio_bitfield2()
> functions to set the output bits of a DO or DIO subdevice.  If it is a
> DIO subdevice you need to configure the bits as outputs using the
> comedi_dio_config() function.
>
> --
> -=( Ian Abbott @ MEV Ltd.    E-mail: <abbo...@mev.co.uk>             )=-

Ian Abbott

unread,
Jun 24, 2009, 11:55:33 AM6/24/09
to comed...@googlegroups.com
On 24/06/09 13:57, mancane wrote:
> Hi i have managed to do modify the outp. c code so that it can output
> a digital bit using comedi_dio_write() function. so now what is
> worrying me is that everytim i run it i have to specify that it must
> choose subdevice 2 channel 1 and the specify the bit.
>
> so in command when i run: ./outp -s2 -c1 0 which will write a 0 bit to
> channel 1 of subdevice 2 which is my dio subdevice.
> What i wanna achieve is that i run outp.c once and then it must write
> digital bits to 4 channels at the same time without me specifying on
> the command/terminal.

To write 4 digital channels simultaneously you have to use the
comedi_dio_bitfield() or comedi_dio_bitfield2() functions. The
comedi_dio_write() function can only write a single channel.

--
-=( Ian Abbott @ MEV Ltd. E-mail: <abb...@mev.co.uk> )=-

mancane

unread,
Jun 24, 2009, 12:45:03 PM6/24/09
to Comedi: Linux Control and Measurement Device Interface
hi i saw the comedi_dio_bitfield2() function just after I posted my
question. but after looking at it i dont undestand the parameters.

can u please explain what each parameter means:


int comedi_dio_bitfield2(comedi_t * device, unsigned int subdevice,
unsigned int write_mask, unsigned int * bits, unsigned int
base_channel);

the first two I understand, the rest I cant. Also on parameter 2 I
understand that thats where I specify which subdevice to write to.
Usually in most of the examples they use options.subdevice to specify
to enable the user to do it in the command line(-s). How do I set this
parameter to be always pointed at the subdevice 2 without using the
options part.

Thanks a lot
> -=( Ian Abbott @ MEV Ltd.    E-mail: <abbo...@mev.co.uk>        )=-

Ian Abbott

unread,
Jun 25, 2009, 7:16:28 AM6/25/09
to comed...@googlegroups.com
On 24/06/09 17:45, mancane wrote:
> hi i saw the comedi_dio_bitfield2() function just after I posted my
> question. but after looking at it i dont undestand the parameters.
>
> can u please explain what each parameter means:
>
>
> int comedi_dio_bitfield2(comedi_t * device, unsigned int subdevice,
> unsigned int write_mask, unsigned int * bits, unsigned int
> base_channel);
>
> the first two I understand, the rest I cant. Also on parameter 2 I
> understand that thats where I specify which subdevice to write to.
> Usually in most of the examples they use options.subdevice to specify
> to enable the user to do it in the command line(-s). How do I set this
> parameter to be always pointed at the subdevice 2 without using the
> options part.
>
> Thanks a lot

It's easier to explain the simpler comedi_dio_bitfield() before
explaining comedi_dio_bitfield2():

int comedi_dio_bitfield(comedi_t * device, unsigned int subdevice,
unsigned int write_mask, unsigned int *bits);

This can optionally write any combination of the first 32 channels of
the digital subdevice and read the channels back. The 'bits' parameter
points to a variable holding the data to be written and will be set to
the data read back. The 'write_mask' variable is a bit vector
indicating which channels are to be written - set bit 0 to 1 to write
channel 0, set bit 1 to 1 to write channel 1, etc.

For example:

unsigned int data;
data = 0x4200;
comedi_dio_bitfield(device, subd, 0xFF00, &data);

will write 0x42 (binary 01000010) to channels 15 to 8 (determined by
write_mask = 0xFF00). So channel 15 gets set to 0, chan 14 = 1, chan 13
= 0, chan 12 = 0, chan 11 = 0, chan 10 = 0, chan 9 = 1, chan 8 = 0.
Then the first 32 channels are read back to '*bits' (data).

The comedi_dio_bitfield2() function is similar except that it starts at
the 'base_channel' instead of channel 0. Bit 0 of the write_mask
corresponds to the 'base_channel' channel, bit 1 of write_mask
corresponds to the 'base_channel+1' channel, etc. Logically, you can
think of it as 'write_mask' and '*bits' being shifted left by
'base_channel' ( << base_channel) before writing, and the data read back
is shifted right by 'base_channel' ( >> base_channel).

comedi_dio_bitfield() is equivalent to comedi_dio_bitfield2() with
base_channel = 0.


In practice, most drivers can't write individual bits to the hardware,
they can only write a byte or 16-or-32-bit word at a time, depending on
the hardware. They work around this limitation by remembering all the
previous data written to the subdevice's channels and combining it
(using the 'write_mask' value) with the new data before writing it to
the physical port addresses.

--
-=( Ian Abbott @ MEV Ltd. E-mail: <abb...@mev.co.uk> )=-

mancane

unread,
Jun 25, 2009, 11:44:23 AM6/25/09
to Comedi: Linux Control and Measurement Device Interface
Hi thanks for the explanation. Only got internet connection now. Im
gonna try it out and see what i get. Im sure i'll use your explanation
to suit what I need to do.

thanks
> -=( Ian Abbott @ MEV Ltd.    E-mail: <abbo...@mev.co.uk>        )=-

mancane

unread,
Jul 1, 2009, 7:54:20 AM7/1/09
to Comedi: Linux Control and Measurement Device Interface
hi

just a quick question:

unsigned int data = 0x0001;
ret = comedi_dio_bitfield2(device,options.subdevice,0x000F,&data,0);

what will this output???

I just want to compare. Im getting nothing. and when I run it and
print out my data it gives me a value of 225. Im confused. please help

thanks

Ian Abbott

unread,
Jul 1, 2009, 9:28:24 AM7/1/09
to comed...@googlegroups.com
On 01/07/09 12:54, mancane wrote:
> hi
>
> just a quick question:
>
> unsigned int data = 0x0001;
> ret = comedi_dio_bitfield2(device,options.subdevice,0x000F,&data,0);
>
> what will this output???
>
> I just want to compare. Im getting nothing. and when I run it and
> print out my data it gives me a value of 225. Im confused. please help
>
> thanks

Assuming your digital output subdevice has 8 channels, it should set
channels 3 downto 0 as follows: chan[3]=0, chan[2]=0, chan[1]=0,
chan[0]=1, and leave channels 7 downto 4 set to their original values.

The value read back is binary 11100001, so chan[7]==1, chan[6]==1,
chan[5]==1, chan[4]==0, chan[3]==0, chan[2]==0, chan[1]==0, chan[0]==1.

Note that the channe write_mask only affects the channels that are
written, not the channels that are read back. It will always read back
'min(comedi_get_n_channels(dev,subd)-base_channel,32)' channels.

--
-=( Ian Abbott @ MEV Ltd. E-mail: <abb...@mev.co.uk> )=-

mancane

unread,
Jul 1, 2009, 1:34:04 PM7/1/09
to Comedi: Linux Control and Measurement Device Interface
Hi

Ok that means the writing out part is ok i understand. The device im
using has 8 channels. Whats the importance of reading back the data
from the channels. Is this useful for me when I write another digital
number

thanks
> -=( Ian Abbott @ MEV Ltd.    E-mail: <abbo...@mev.co.uk>        )=-

mancane

unread,
Jul 1, 2009, 1:55:47 PM7/1/09
to Comedi: Linux Control and Measurement Device Interface
HI

I have tried running now the program just to test whether it is
working. I connected an and gate to the the outputs of the channel 0
and 1 and then the output of the and gate to an resitor and LED.

I changed the data to 0X0003 expeting chan[3] = 0, chan[2]=0 chan[1]=1
chan[0] = 1 and this should be able to give an output of 1 to my and
gate and the LED should go on but its not.

Am i missing something. please help

Ian Abbott

unread,
Jul 2, 2009, 6:49:26 AM7/2/09
to comed...@googlegroups.com
On 01/07/09 18:55, mancane wrote:
> HI
>
> I have tried running now the program just to test whether it is
> working. I connected an and gate to the the outputs of the channel 0
> and 1 and then the output of the and gate to an resitor and LED.
>
> I changed the data to 0X0003 expeting chan[3] = 0, chan[2]=0 chan[1]=1
> chan[0] = 1 and this should be able to give an output of 1 to my and
> gate and the LED should go on but its not.
>
> Am i missing something. please help

Have you configured the DIO channels as outputs using comedi_dio_config()?

--
-=( Ian Abbott @ MEV Ltd. E-mail: <abb...@mev.co.uk> )=-

mancane

unread,
Jul 3, 2009, 8:31:18 AM7/3/09
to Comedi: Linux Control and Measurement Device Interface
hi

I configured the channels using the code in the demo files called
dio.c. so I should be getting an output but im not

On Jul 2, 12:49 pm, Ian Abbott <abbo...@mev.co.uk> wrote:
> On 01/07/09 18:55, mancane wrote:
>
> > HI
>
> > I have tried running now the program just to test whether it is
> > working. I connected an and gate to the the outputs of the channel 0
> > and 1 and then the output of the and gate to an resitor and LED.
>
> > I changed the data to 0X0003 expeting chan[3] = 0, chan[2]=0 chan[1]=1
> > chan[0] = 1 and this should be able to give an output of 1 to my and
> > gate and the LED should go on but its not.
>
> > Am i missing something. please help
>
> Have you configured the DIO channels as outputs using comedi_dio_config()?
>
> --
> -=( Ian Abbott @ MEV Ltd.    E-mail: <abbo...@mev.co.uk>        )=-

mancane

unread,
Jul 3, 2009, 10:05:25 AM7/3/09
to Comedi: Linux Control and Measurement Device Interface
hi
i managed to get it to work. Something was wrong and I just rewrote
the code. But Im having a few problems.

What I have done is I took chan[0] and chan[1] and connected them to
an and gate and chan[2] and chan[3] , I connected them to another and
gate. both the outputs of the two and gates are connected to LEDS. I
did this so that I can check whether the code is ok. When I was
running it i was increamenting my data(manually in the code each time)
from 0x0000, 0x0001, 0x0002.........up to 0x000F. Now the thing is
from 4 till 7 both LEDS go on which is not supposed to be happening
and I dont understand why is that. Is there an explanation for that.

thanks 4 your time

Ian Abbott

unread,
Jul 3, 2009, 10:32:43 AM7/3/09
to comed...@googlegroups.com
On 03/07/09 15:05, mancane wrote:
> hi
> i managed to get it to work. Something was wrong and I just rewrote
> the code. But Im having a few problems.
>
> What I have done is I took chan[0] and chan[1] and connected them to
> an and gate and chan[2] and chan[3] , I connected them to another and
> gate. both the outputs of the two and gates are connected to LEDS. I
> did this so that I can check whether the code is ok. When I was
> running it i was increamenting my data(manually in the code each time)
> from 0x0000, 0x0001, 0x0002.........up to 0x000F. Now the thing is
> from 4 till 7 both LEDS go on which is not supposed to be happening
> and I dont understand why is that. Is there an explanation for that.
>
> thanks 4 your time

Rather than trying to second-guess the problem, it would be easier if
you posted the relevant bits of your code.

--
-=( Ian Abbott @ MEV Ltd. E-mail: <abb...@mev.co.uk> )=-

mancane

unread,
Jul 3, 2009, 11:18:01 AM7/3/09
to Comedi: Linux Control and Measurement Device Interface
hi


comedi_t *device;


int main(int argc, char *argv[])
{

unsigned int data;

int ret;
struct parsed_options options;

init_parsed_options(&options);
parse_options(&options, argc, argv);

device = comedi_open(options.filename);
if(!device){
comedi_perror(options.filename);
exit(-1);
}

data = 0x6;


ret = comedi_dio_bitfield2(device,2,0xF,&data,0);
if(ret < 0){
comedi_perror(options.filename);
exit(-1);
}

return 0;


when I run this code, according to me the output is supposed to 0110
but somehow the LED connected to the output of an and gate connected
to channels [2] and [3] goes on. I dont understand why?
> -=( Ian Abbott @ MEV Ltd.    E-mail: <abbo...@mev.co.uk>        )=-

Ian Abbott

unread,
Jul 3, 2009, 11:52:03 AM7/3/09
to comed...@googlegroups.com
On 03/07/09 16:18, mancane wrote:
> hi
>
>
> comedi_t *device;
>
>
> int main(int argc, char *argv[])
> {
>
> unsigned int data;
>
> int ret;
> struct parsed_options options;
>
> init_parsed_options(&options);
> parse_options(&options, argc, argv);
>
> device = comedi_open(options.filename);
> if(!device){
> comedi_perror(options.filename);
> exit(-1);
> }
>
> data = 0x6;
>
>
> ret = comedi_dio_bitfield2(device,2,0xF,&data,0);
> if(ret < 0){
> comedi_perror(options.filename);
> exit(-1);
> }
>
> return 0;
>
>
> when I run this code, according to me the output is supposed to 0110
> but somehow the LED connected to the output of an and gate connected
> to channels [2] and [3] goes on. I dont understand why?

Can you configure the DIO channels as outputs after opening the device,
but before the bitfield operations?

unsigned int n;

for (n = 0; n < 4; n++) {
ret = comedi_dio_config(device, 2, n, COMEDI_OUTPUT);
if (ret < 0) {
comedi_perror(options.filename);
exit(-1);
}

--
-=( Ian Abbott @ MEV Ltd. E-mail: <abb...@mev.co.uk> )=-

mancane

unread,
Jul 3, 2009, 12:32:42 PM7/3/09
to Comedi: Linux Control and Measurement Device Interface
Hi

The problem is still there. and I cant seem to see whats wrong

Thanks
> -=( Ian Abbott @ MEV Ltd.    E-mail: <abbo...@mev.co.uk>        )=-
Reply all
Reply to author
Forward
0 new messages