Copyright © 2008 Peter.Soetens@fmtc.be
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation, with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of this license can be found at http://www.fsf.org/copyleft/fdl.html.
Abstract
This document explains how to setup the Comedi layer for Orocos applications.
Table of Contents
The aim of this package is to make Comedi devices available as the interfaces defined in the Orocos Device Interface. It gives a short introduction to configuring Comedi devices under Linux and then demonstrates how the Orocos Comedi classes can be used to access these devices.
For each device supported by comedi, you need to
Load the kernel module device driver
Configure the device with comedi_config
Take notes of the device's subdevices using comedi_info
The Orocos Debian repository contains all the above modules and tools in the libcomedi-dev and comedi-modules packages, but the same procedure can be used if you compiled Comedi from source.
Head over to the
Comedi supported hardware listing and look up your
PCI card. The list will tell you which kernel modules drives this
card. For example, the NI-6527 is driven by the ni6527 kernel module.
Then you must type at the prompt:
modprobe ni6527
Which loads this module. Look at the output of dmesg
to see if the device was found. Repeat this procedure for each
Comedi supported card type you have. It is possible that one driver
drives multiple types of cards, for example, such as the ni_pcimio
driver.
When all went well, you can inspect /proc/comedi
and see if your cards are listed by typing cat /proc/comedi.
Now each device needs to be attached to a
/dev/comediN
device descriptor, where
N starts from zero.The
comedi_config tool does this job. For each
PCI card, you need to lookup what the device name is. This may
be another name than the kernel module, or be very similar.
See cat /proc/comedi for the correct names.
So for our NI 6527 card, you type:
comedi_config -f /dev/comedi0 ni6527
This assigns the first ni6527 card in your PC to /dev/comedi0
.
You can repeat this for each PCI card, but must assign them
to another dev file descriptor number.
The last step you need to take is listing the subdevices and their number by using comedi_info -f /dev/comediN. For Our NI-6527 card, this would be:
comedi_info -f /dev/comedi0
Now note that the digital Input subdevice is number 0. You will need this number to finally setup your Orocos Comedi device classes. Note each subdevice you will use.
Note | |
---|---|
Subdevices for incremental encoders are called counters. |
The last step is creating the necessary objects. First create a OCL::ComediDevice object for each configured card in your system:
int minor = 0; ComediDevice* cdev0 = new ComediDevice( minor );
Where minor is the same number as your
/dev/comedi0
device descriptor used earlier.
Next for each sub device on your card, create a
ComediSubDeviceX
object. For example,
for digital inputs you write:
int subdev = 0;
DigitalInInterface* cdev0_DIn = new ComediSubDeviceDIn
( cdev0, 0 );
The first argument is the ComediDevice created earlier, the second argument is the subdevice. An error will be printed if the subdevice is not a Digital input.
As you can see, the OCL::ComediSubDeviceDIn is an implementation of the RTT::DigitalInInterface class of the Real-Time Toolkit. These interfaces can be name served such that other parts of the application can pick the device up just by using its name. You need to provide a name argument upon construction of the ComediSubDevice object:
int subdev = 0;
DigitalInInterface* cdev0_DIn = new ComediSubDeviceDIn
( cdev0, "Digital1", 0 );
// Somewhere else in the application, for example in a component's
// configureHook():
bool MyComponent::configureHook() {
// ... din is a DigitalInInterface*
din = DigitalInInterface::getObject("Digital1");
if ( din == 0 ) {
log(Error) << "Device 'Digital1' not found !" << endlog();
return false;
}
return true;
}
Even better, you could make 'Digital1' an Orocos property such that you can reconfigure for using another subdevice.
This name serving allows that multiple components use the same subdevice such that you can optimally use all the channels of your devices.
Orocos provides two ways of writing or reading a channel: directly using the device interface class or using a helper object. Both are equivalent from a performance point of view, as the helper objects are inlined.
There are 6 classes which define the interface of the possible subdevices:
Table 1. IO Interface Classes
Interface | Comedi Implementation | Description |
---|---|---|
RTT::AnalogInInterface | OCL::ComediSubDeviceAIn | Reading analog input channels |
RTT::AnalogOutInterface | OCL::ComediSubDeviceAOut | Writing analog output channels |
RTT::DigitalInInterface | OCL::ComediSubDeviceDIn | Reading digital bits |
RTT::DigitalOutInterface | OCL::ComediSubDeviceDOut | Writing digital bits |
RTT::PulseTrainGeneratorInterface | OCL::ComediPulseTrainGenerator | Sends out block waves |
RTT::EncoderInterface | OCL::ComediEncoder | A position/turn incremental encoder |
Consult the API documentation for the available functions.