Российский производитель и разработчик сертифицированного измерительного оборудования с 1987 года


Пример IoAsync для Linux

Вы не вошли.

 Поиск | Регистрация | Вход 

Александр Александрович
09.02.2015 14:24:13
#1

Гость

Пример IoAsync для Linux

Добрый день!

Уважаемые разработчики, я (да и многие другие думаю) очень благодарны за отлично документированный программный интерфейс lcomp. К сожалению, не всегда понятна общая картина их использования.
Я был бы очень признателен, если бы вы написали комплексный пример использования IoAsync на линукс "под ключ" с учетом следующих подводных камней:
(На примере Е-14-140М)

  • Инициализация устройства

  • В диф. режиме

    • Чтение с 1-го канала

    • Чтение с 11-го канала

    • Чтение с 16-го канала

  • В режиме с общей землей

    • Чтение с 1-го канала

    • Чтение с 11-го канала

    • Чтение с 25-го канала

  • Преобразование отсчетов в реальные значения

В комплекте с драйверами lcom_linux, идет документация, однако

  • Полный пример есть только для чтения из кольцевого буфера

  • Примеры IoAsync и преобразования значения сильно фрагментированы

11-ый и 25-ый канал взят как пример не кратности 2.

Понимаю, что прошу много, но это сильно поможет и облегчит задачу многим.

Заранее спасибо.

С уважением,
Александр Александрович

09.02.2015 16:08:50
#2

Сотрудник "Л Кард"
Откуда: Москва
Здесь с 23.04.2014
Сообщений: 3,727

Re: Пример IoAsync для Linux

... прочитать одиночный отсчет с АЦП

Для этого нужно выполнить шаги приведенные ниже.

Подключить библиотеку LComp так как описано в главе "Подключение и работа с библиотекой (на CPP)" раздела "Описание API DLL библиотеки"

После вызова OpenLDevice,LoadBios и ReadPlataDecr выполнить следующий код:

      ASYNC_PAR pp;
      pp.s_Type = L_ASYNC_ADC_INP;
      pp.Chn[0] = 0x00; // 0 канал дифф. подключение (в общем случае лог. номер канала)
      pI->IoAsync(&pp);
      cout << (short)pp.Data[0] << endl; // в Data[0] код АЦП
   
При этом на экран будет выведен один отсчет с 0 канала АЦП.

Завершить работу с библиотекой так как описано в главе "Подключение и работа с библиотекой (на CPP)" раздела "Описание API DLL библиотеки"

Прочитать таким образом кадр отсчетов с АЦП невозможно. Только один отсчет с одного канала.

Более подробно о возможностях функции IoAsync можно прочитать в ее описании

Дифф каналы 0x00 - нулевой канал 0x01 - 1 канал  0x0B - 11 канал
Однополюсный  0x20 - нулевой 0x21 первый 0x2B  11 канал
Подробнее смотреть в документации   - Логический номера канала. Там еще усиление можно закодировать.

Перевод в физические величины  (код АЦП)*(входной диапазон)/(масимальный код АЦП)

максимальный код тоже лучше посмотреть в описании на модуль. Может 8000, может 8100...

Александр Александрович
10.02.2015 13:27:40
#3

Гость

Re: Пример IoAsync для Linux

Добрый день!
Спасибо большое за ответ. Исходя из него, я написал общий пример получения данных при помощи IoAsync. Пункт про получение реальных значений у меня не получилось до конца понять.
Не могли бы вы сказать, где искать:

  • Код АЦП

  • входной диапазон

  • максимальный код АЦП

Прошу прощение за неточности в формулировки вопросов, касающихся устройства, так как я скорее программист, нежели электронщик

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#define DEFAULT_LIB_PATH  "/usr/lib/liblcomp.so"
#define INITGUID
#include "guiddef.h"
#include "stubs.h"
#include "ioctl.h"
#include "ifc_ldev.h"
#include "e140cmd.h"

/**
 * Вывод на экран сообщения об ошибки и завершение работы
 * @param txt
 */
void die(const char *txt) {
    fprintf(stderr, "Error: %s\n", txt);
    exit(EXIT_FAILURE);
}

typedef IDaqLDevice* (*CREATEFUNCPTR)(ULONG Slot);

typedef struct Device_t {
    void* handle; // Бибилитека lcomp
    HANDLE ldevice_handle;
    CREATEFUNCPTR create_instance; // Функция инициалищации контекста устройства
    LUnknown *p_instance; // Обобщенный указатель на устройство
    IDaqLDevice *daq_device; // Интерфейс работы с устройством
    PLATA_DESCR_E140 plata; // Описание платы
} Device_t;

/**
 * Инициализация устройства. Завершение выполнения программы если была ошибка
 * @param path_to_lib Путь до библиотеки lcomp
 * @return Структура с указтелями на устройство и библиотеку
 */
Device_t initialize(const char * path_to_lib) {
    Device_t device;
    char *err;
    // Подключение библиотеки
    device.handle = dlopen(path_to_lib, RTLD_LAZY);
    if ((err = dlerror()) != NULL) die(err);

    // Инициализация функции подключения к плате
    device.create_instance = (CREATEFUNCPTR) dlsym(device.handle, "CreateInstance");
    if ((err = dlerror()) != NULL) die(err);

    // Подключение устройство
    device.p_instance = device.create_instance(0);
    if (device.p_instance == NULL) die("call CreateInstance failed");

    // Определение интерфейса устройства
    HRESULT hr = device.p_instance->QueryInterface(IID_ILDEV, (void**) &device.daq_device);
    if (hr != S_OK) die("get IDaqLDevice failed");

    return device;
}

/**
 * Получение одного значения с указанного канала
 * @param device 
 * @param channel Номер канала (индексируется с 0)
 * @param mode Режим. 'd' - дифференциальный, 'c' - с общей землей
 * @return 
 */
double read_channel(Device_t *device, unsigned int channel, char mode) {
    if (mode == 'c') channel += 0x20;
    ASYNC_PAR pp;
    pp.s_Type = L_ASYNC_ADC_INP;
    pp.Chn[0] = channel;
    if (device->daq_device->IoAsync(&pp) != L_SUCCESS)
        die("Failed read from ADC device");
    short sample = pp.Data[0]; // "Сырой" отсчет
    double val = sample / (8000);
    return val;
}

int main(int argc, char** argv) {
    Device_t device = initialize(DEFAULT_LIB_PATH);
    PLATA_DESCR_E140 plata;

    device.daq_device->OpenLDevice();
    device.daq_device->EnableCorrection();
    device.daq_device->ReadPlataDescr(&plata);

    printf("%s Rev. %c (SN: %s)\n", plata.BrdName, plata.Rev, plata.SerNum);

    device.daq_device->InitStartLDevice();
    device.daq_device->StartLDevice();

    // Диф. режим
    printf("Channel 1: %f\n", read_channel(&device, 0, 'd'));
    printf("Channel 11: %f\n", read_channel(&device, 10, 'd'));
    printf("Channel 15: %f\n", read_channel(&device, 14, 'd'));


    // С общей землей
    printf("Channel 1: %f\n", read_channel(&device, 0, 'c'));
    printf("Channel 16: %f\n", read_channel(&device, 15, 'c'));
    printf("Channel 21: %f\n", read_channel(&device, 20, 'c'));

    device.daq_device->CloseLDevice();
    return 0;
}
10.02.2015 14:48:02
#4

Сотрудник "Л Кард"
Откуда: Москва
Здесь с 23.04.2014
Сообщений: 3,727

Re: Пример IoAsync для Linux

InitStart и Start вызывать не нужно. Код АЦП это то что у Вас сырой отсчет. Входной диапазон и максимальный код есть в описании на модуль. На сайте выберите этот модуль - там будут ссылки на документацию.

Александр Александрович
13.02.2015 00:07:46
#5

Гость

Re: Пример IoAsync для Linux

Спасибо за помощь.
Еще такой вопрос: усиление правильно ли так задавать?

uint16_t channel = 9; // 10-ый канал в диф. режиме
channel = channel | 0b0000000000000010; // Хочу поставить усиление в 16 раз

ASYNC_PAR pp;
pp.s_Type = L_ASYNC_ADC_INP;

daq_device_->IoAsync(&pp);
// ....
13.02.2015 14:07:26
#6

Сотрудник "Л Кард"
Откуда: Москва
Здесь с 23.04.2014
Сообщений: 3,727

Re: Пример IoAsync для Linux

Усиление это точно не второй бит. 0b10000000 так скорей. (7 и 6 биты)

Александр Александрович
13.02.2015 16:58:58
#7

Гость

Re: Пример IoAsync для Linux

Огромное Вам спасибо! Работает)