The Orocos Comedi Interface

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

1. Introduction
2. Comedi setup
2.1. Loading kernel modules
2.2. Configuring the devices
2.3. Looking up the sub-device info
3. Setting up the Orocos Comedi classes
4. Using SubDevices
4.1. Direct Device Interface
4.2. Using Helper Objects

1. Introduction

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.

2. Comedi setup

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.

2.1. Loading kernel modules

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.

2.2. Configuring the devices

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.

2.3. Looking up the sub-device info

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]Note

Subdevices for incremental encoders are called counters.

3. Setting up the Orocos Comedi classes

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.

4. Using SubDevices

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.

4.1. Direct Device Interface

There are 6 classes which define the interface of the possible subdevices:

Table 1. IO Interface Classes

InterfaceComedi ImplementationDescription
RTT::AnalogInInterfaceOCL::ComediSubDeviceAInReading analog input channels
RTT::AnalogOutInterfaceOCL::ComediSubDeviceAOutWriting analog output channels
RTT::DigitalInInterfaceOCL::ComediSubDeviceDInReading digital bits
RTT::DigitalOutInterfaceOCL::ComediSubDeviceDOutWriting digital bits
RTT::PulseTrainGeneratorInterfaceOCL::ComediPulseTrainGeneratorSends out block waves
RTT::EncoderInterfaceOCL::ComediEncoderA position/turn incremental encoder

Consult the API documentation for the available functions.

4.2. Using Helper Objects