UniSet/ОписаниеCOMEDI

Материал из Etersoft wiki
Перейти к: навигация, поиск

Описание COMEDI

УСТАНОВКА COMEDI

Чтобы установить comedi, нужно установить пакеты comedi и libcomedi или собрать программы с вышеуказанными названиями из исходников:

$ su -
# cd /path/to/comedi_src
# ./configure && make && make install && make clean
# cd /path/to/comedilib_src
# ./configure && make && make install && make clean


(для написания собственных драйверов устройств, используя comedi, вам также придётся установить пакет libcomedi-devel)

Замечу, что и для популярного ныне языка python также присутствуют comedi-расширения. (см. пакеты python-comedi, python-libcomedi)



НАСТРОЙКА COMEDI

Для настройки comedi используется команда comedi_config.

Чтобы добавить нужное устройство, следует использовать вышеуказанную команду от лица супер пользователя(root) следующим образом

# comedi_config /dev/comediN module [options]

Где 0 <= N <= 15,

module - заданный модуль нужного устройства comedi. набор модулей находится в разделе libcomedi/drivers. Перед запуском модуль следует явно загрузить командой

# insmod modulename.ko
options - различные параметры, передаваемые модулю. Представляют собой набор параметров, разделённых запятыми. Здесь могут быть указаны, например, базовый адрес устройства и назначаемый ему номер прерывания.

Для корректного отключения заданного модуля от устройства /dev/comediN следует использовать команду comedi_config с ключом -r.

Для получения более подробной информации обратитесь к руководству (man) по comedi_config.


ПРИМЕР НАСТРОЙКИ COMEDI С МОДУЛЕМ UNIOXX5

$ su -
# insmod unioxx5.ko
# comedi_config /dev/comedi0 unioxx5 0x110
# comedi_config -r /dev/comedi0 unioxx5


В строке 3 мы создаём comedi-устройство, приаттачивая к нему модуль unioxx5 (загруженный в строке 2) и передаём ему базовый адрес - 0x110.

В строке 4 мы удаляем comedi-устройство.


Comedi API

Прежде всего в программу нужно вставить заголовочный файл <comedilib.h>.


comedi_open

1. comedi_t * comedi_open(const char * filename);

Открывает заданное comedi-устройство.
Возвращает указатель на структуру comedi_t при успешном выполнении, NULL при ошибке.


[пример]:
/* ... */

comedi_t* it;
    

if((it = comedi_open("/dev/comedi0")) == NULL)
    //error

/* ... */


comedi_close

2. int comedi_close(comedi_t * device);

Закрывает заданное comedi-устройство открытое ранее с помощью comedi_open(см. пункт [3].1)
В случае успеха возвращает 0, в случае ошибки - -1.


comedi_perror

3. void comedi_perror(const char * s);

Выводит в stderr сообщение о последней ошибки, возникшей при использованиии comedi_* функций.
Передаваемый параметр s - текстовая строка, описывающая ошибку.
Данная функция имеет аналогичный принцип действия с функцией perror() из стандартной библиотеки C.

comedi_strerror

4. char * comedi_strerror(int errnum);

возвращает строку, содержащую сообщение об ошибке comedi с заданным кодом errnum.
данная функция имеет аналогичный принцип действия с функцией strerror() из стандартной библиотеки C.


comedi_errno

5. int comedi_errno(void);

Возвращает код последней произошедшей в comedi ошибки.


comedi_dio_config

6. int comedi_dio_config(comedi_t * device, unsigned int subdevice, unsigned int channel, unsigned int direction);

Настраивает заданный канал в устройстве с цифровым вводом/выводом на вход или на выход.


device - это указатель на comedi_t, т.е. устройство, предварительно открытое с помощью функции comedi_open(см. пункт [3].1).
subdevice - номер подустройства. (в unioxx5 всего 4 подустройства [от 0 до 3])
channel - номер канала. (в unioxx5 всего 24 канала [от 0 до 23])
direction - может иметь следующие значения:
COMEDI_INPUT - настроить канал на вход
COMEDI_OUTPUT - настроить канал на выход


в случае успеха функция возвращает 1, в случае ошибки - -1


[пример]:
/* ... */
comedi_t* it;

if((it = comedi_open("/dev/comedi0")) == NULL) {
       comedi_perror("can't open /dev/comedi0");
       exit(1);
}

/* настраиваем 6-й канал 1-го подустройства на выход */

if(comedi_dio_config(it, 0, 5, COMEDI_OUTPUT) < 0) {
             comedi_perror("something going wrong");
             exit(1);
}
/* ... */


comedi_dio_read

7. int comedi_dio_read(comedi_t * device, unsigned int subdevice, unsigned int channel, unsigned int * bit);
Считывает значение из заданного канала заданного подустройства.


device - это указатель на comedi_t, т.е. устройство, предварительно открытое с помощью функции comedi_open(см. пункт [3].1).
subdevice - номер подустройства. (в unioxx5 всего 4 подустройства [от 0 до 3])
channel - номер канала. (в unioxx5 всего 24 канала [от 0 до 23])
bit - указатель на unsigned int. здесь будет сохраняться считанное функцией значение.


в случае успеха ф-я возвращает 1, в случае ошибки - -1.


[пример]:
/* ... */
comedi_t* it;
unsigned int data;

if((it = comedi_open("/dev/comedi0")) == NULL) {
            comedi_perror("can't open /dev/comedi0");//
             exit(1);//
}

/* считываем данные из 9-го канала 2-го подустройства */
if(comedi_dio_read(it, 1, 8, &data) < 0) {
             comedi_perror("can't read data");//
             exit(1);
}

printf("readed data is %d\n", data);//
/* ... */


comedi_dio_write

8. int comedi_dio_write(comedi_t * device, unsigned int subdevice, unsigned int channel, unsigned int bit);

Записывает заданное значение bit в канал channel подустройства subdevice устройства device. В случае успеха функция возвращает 1, в случае ошибки - -1.


[пример]:
/* ... */
comedi_t* it;

if((it = comedi_open("/dev/comedi0")) == NULL) {
            comedi_perror("can't open /dev/comedi0");
            exit(1);
}

/* Записываем значение 0 в 24-й канал 4-го подустройства */
if(comedi_dio_write(it, 3, 23, 0) < 0) {
            comedi_perror("can't write some data");
            exit(1);
}

/* ... */


comedi_data_read

9. int comedi_data_read(comedi_t * device, unsigned int subdevice, unsigned int channel, unsigned int range, unsigned int aref, lsampl_t * data);

считывает данные из канала channel подустройства subdevice устройства device. Для аналого-цифрового преобразования(если оно возможно)
устройство должно быть сконфигурированно на использование требуемого диапазона range и(если это возможно)
должно быть задано корректное описание типа аналогового устройства aref.
Тип аналогового устройства, не поддерживаемый данным устройством, игнорируется без какого-либо предупреждения пользователю.
Т.о. данная функция считывает одно значение из заданного канала и записывает его в data.


ВНИМАНИЕ!: comedi_data_read() не подразумевает самостоятельной реализации каких-либо пауз для сложного аналогового ввода(как правило, этот механизм
необходим для аналого-цифрового преобразования, которое занимает некоторое время). Если вы переключаетесь между различными каналами ихотите
использовать механизм точного аналогового чтения, используете comedi_data_read_delayed().


Если функция закончила своё выполнение удачно, она возвращает 1, в противном случае - -1.


[пример]:
/* ... */
comedi_t* it;
lsample_t data;

if((it = comedi_open("/dev/comedi0")) == NULL) {
            comedi_perror("can't open /dev/comedi0");
            exit(1);
}

/* считываем данные из 12го канала 3го подустройства */
if(comedi_data_read(it, 2, 11, 0, AREF_GROUND, &data) < 0) {
            comedi_perror("can't write some data");
            exit(1);
}

printf("readed value is %d\n", *data);
/* ... */


comedi_data_write

10. int comedi_data_write(comedi_t * device, unsigned int subdevice, unsigned int channel, unsigned int range, unsigned int aref, lsampl_t data);

записывает данные data в канал channel подустройства subdevice устройства device. (range и aref описаны в пункте 9).
В случае успеха функция возвращает 1, в случае ошибки - -1.


[пример]:
/* ... */
comedi_t* it;
lsample_t data = 0xFF;

if((it = comedi_open("/dev/comedi0")) == NULL) {
            comedi_perror("can't open /dev/comedi0");
            exit(1);
}

/* записываем 0xFF в 6й канал второго подустройства  */
if(comedi_data_write(it, 1, 5, 0, AREF_GROUND, &data) < 0) {
            comedi_perror("can't write some data");
            exit(1);
}

/* ... */


COMEDI драйвер для Fastwel UNIOxx-5

Имя модуля: unioxx5.ko

Comedi драйвер для UNIOxx-5 предоставляет следующие операции:

  • аналоговые/цифровые чтение и запись
  • возможность изменения состояния одного из 24х каналов(т.е. настройка на вход или выход)

Во время аттача драйвера к comedi устройству(реализуется с помощью вызова comedi_config), в dmesg выводятся идентификаторы всех аналоговых модулей, установленных на плате, и их позиции(от 0 для 11). Цифровые модули, как таковые, не обнаруживаются, поэтому драйвер считает, что на всех позициях, где не установлены аналоговые модули, присутствуют модули цифровые.

Также модуль автоматически определяет кл-во подустройств(к слову, он умеет работать только с подустройствами тирпа g01).

Операции над дискретными и аналоговыми модулями происходят, используя общий диапазон доступных каналов(0 .. 24), поэтому их паралельное выполнение невозможно. Это условие контролируется непосредственно драйвером.

Также при каждой операцией над тем или иным модулем проверяется тип модуля: аналоговый он или цифровой и способен ли он читать/записывать.


Цифровые чтение/запись

Перед тем, как читать или записывать в определённый канал нужного подустройства, требуется явно сконфигурировать соответсвующий канал на вход или выход. Реализуется это с помощью ф-ии comedi_dio_config, которая, как видно из названия, применима только к цифровым модулям.

comedi_dio_read() - ф-я цифрового чтения
comedi_dio_write() - ф-я цифровой записи


Аналоговые чтение/запись

В отличие от соответствующих операций над цифровыми модулями, для аналогового чтения/заиси не требуется явно конфигурировать нужные каналы, т.к. это делается автоматически при вызове ф-ий чтения/записи.

comedi_data_read() - ф-я аналогового чтения
comedi_data_write() - ф-я аналоговой записи


При указании номера канала нужно иметь в виду, что аналоговые операции применимы только к 12 модулям, каждый из которых имеет два канала - A и B.

Номер модуля = номер канала / 2.

Причём чётные номера каналов являются каналом A соответсвующего модуля, а нечётные - каналом B.

Например, канал с номером 8 будет являться каналом A 4го модуля, а канал 13 - канаом B 6го модуля.