Кабели USB Bridge и LabVIEW

VISA, TCP/IP, USB, CAN, GPIB и подобные протоколы
Ответить
Аватара пользователя
dadreamer

Activity Professionalism Автор
professor
professor
Сообщения: 3926
Зарегистрирован: 17 фев 2013, 16:33
Награды: 4
Версия LabVIEW: 2.5 — 2022
Благодарил (а): 11 раз
Поблагодарили: 126 раз
Контактная информация:

Кабели USB Bridge и LabVIEW

Сообщение dadreamer »

В этой теме я хотел бы рассказать о таком способе связи двух компьютеров между собой как использование кабеля USB Bridge, об особенностях этого способа и о специфике его работы в :labview: . Сам способ может вполне служить альтернативой методу связи с помощью сетевых карт и куска патч-корда, конечно, с некоторыми ограничениями, о которых чуть позже. Вкратце, кабель USB Bridge представляет собой стандартный USB кабель типа А-А с находящимся обычно посредине устройством, обеспечивающим оптронную развязку обоих концов. Устройство представляет собой микросхему-контроллер, выполняющую функции моста (bridge). Эти контроллеры отличаются друг от друга фирмой-производителем и протоколом коммуникации. Исходя из этого я могу разделить все подобные кабели на две группы:

1. Кабели, поддерживающие стандарт Microsoft Windows Easy Transfer - с протоколом можно работать с помощью функций пакета WinUSB (чип кабеля - Prolific);
2. Кабели с собственным протоколом, заданным на этапе производства - стандарт Windows Easy Transfer не поддерживается и с протоколом можно работать только с помощью SDK разработчика (чип кабеля - OTi, других не встречал).

С первой группой всё более-менее понятно, в сети есть рекомендации, с которых можно начать программирование, поэтому эти кабели я оставил на потом. Собираюсь рассказать о них позже. А пока что опишу в общих чертах кабели на OTi-чипе. Один из примеров - кабель UANC22V7 фирмы Gembird с контроллером OTi-2208NF. Вот как он выглядит:
uanc22v7.jpg
uanc22v7.jpg (8.34 КБ) 14180 просмотров
Довольно распространены также кабели на чипе OTi-2108, небольшие обзоры таких кабелей можно увидеть тут или вот тут.
TU2-PCLINK (фирма TRENDnet):
TU2-PCLINK_d01_2.jpg
TU2-PCLINK_d01_2.jpg (25.53 КБ) 14180 просмотров
DL-USB015:
USB_Data_Link_Cable_for_Computer_data_sharing.jpg
У меня имеются в наличии кабели на обоих чипах. Отличие 2208NF от 2108, кроме собственно маркировки и внешнего вида кабеля - при подключении кабеля на чипе 2208NF в системе появляется съемный диск (как при вставке флэшки) размером 1 МБ и виртуальный CD-ROM с файловым менеджером, тогда как контроллер 2108 создаёт только виртуальный CD-ROM с программой. Идентифицировать чип кабеля визуально невозможно (к сожалению), но при подключении к ПК это сделать очень легко - нужно лишь зайти в Диспетчер устройств Windows, найти съемный диск, появившийся при подключении кабеля, и посмотреть VID и PID его родителя (т.е., контроллера моста). Для чипов OTi VID равен 0EA0, а PID соответствует маркировке чипа: 2108, 2208 и т.д.
oti_vid_pid.jpg
Взаимодействие с контроллером кабеля выполняется с помощью стандартных функций WinAPI CreateFile, DeviceIoControl, CloseHandle, применяемых к съемному диску (2208NF) или виртуальному CD-ROM'у (2108). Функция CreateFile открывает физический диск, создаваемый контроллером моста, возвращая дескриптор (хэндл) для дальнейшей работы с устройством. Функция DeviceIoControl используется для передачи управляющих команд драйверу контроллера, выполняя таким образом функции приёма-передачи данных и ряд служебных операций. Функция CloseHandle закрывает диск по его дескриптору (хэндлу). Как видим, практически вся работа с контроллером кабеля выполняется через DeviceIoControl. Подробное описание этой функции приведено в MSDN.
Функция имеет следующие параметры:
  • hDevice — дескриптор (хэндл) устройства, получаемый с помощью CreateFile
  • IoControlCode — управляющий код для драйвера устройства, в нашем случае это 4D004 (IOCTL_SCSI_PASS_THROUGH) или 4D014 (IOCTL_SCSI_PASS_THROUGH_DIRECT)
  • InBuffer — указатель на буфер с входными данными
  • InSize — размер входного буфера
  • OutBuffer — указатель на буфер с выходными данными
  • OutSize — размер выходного буфера
  • BytesReturned — указатель на переменную, куда сохраняется число байт, записанных в выходной буфер
  • pOverlapped — указатель на структуру OVERLAPPED, в нашем случае не используется (NULL)
В свою очередь входной-выходной буфер имеет определённый формат, задаваемый управляющим кодом IoControlCode. В данном случае это структура SCSI_PASS_THROUGH, либо структура SCSI_PASS_THROUGH_DIRECT.
Таким образом, буфер должен содержать следующие поля:
  • Length (U16) — размер всей структуры (sizeof)
  • ScsiStatus (U8) — статус выполнения команды устройством, возвращаемый хост-адаптером USB-шины
  • PathId (U8) — SCSI-порт или шина, где размещено устройство
  • TargetId (U8) — контроллер/устройство на шине, которому посылается команда
  • Lun (U8) — логический номер устройства внутри контроллера
  • CdbLength (U8) — длина CDB-пакета (CDB - Command Descriptor Block, блок дескриптора команды)
  • SenseInfoLength (U8) — длина Sense-буфера для возврата ошибки
  • DataIn (U8) — направление передачи данных: 00 - SCSI_IOCTL_DATA_OUT или 01 - SCSI_IOCTL_DATA_IN
  • DataTransferLength (I32) — размер буфера для приёма/передачи данных
  • TimeOutValue (U32) — максимальное время выполнения команды, сек.
  • DataBufferOffset / DataBuffer (U32) — смещение от начала структуры до буфера для приёма/передачи данных (SCSI_PASS_THROUGH) или указатель на буфер (SCSI_PASS_THROUGH_DIRECT)
  • SenseInfoOffset (U32) — смещение от начала структуры до Sense-буфера для возврата ошибки
  • Cdb (16 x U8) — CDB-блок с управляющим кодом
  • ucSenseBuf (24 x U8) — Sense-буфер для возврата ошибки
Ниже приведён список основных команд для работы с девайсом через функцию DeviceIoControl.

1. Отправка данных
Эта команда осуществляет передачу данных на удалённый ПК.
IoControlCode = 4D014 (IOCTL_SCSI_PASS_THROUGH_DIRECT), InBuffer заполняется следующим образом:

Length = 00 2C (44d)
ScsiStatus = 0
PathId = FF (255d)
TargetId = FF (255d)
Lun = FF (255d)
CdbLength = 10 (16d)
SenseInfoLength = 18 (24d)
DataIn = 00
Filler1 (1 байт) = 00
Filler2 (1 байт) = 00
Filler3 (1 байт) = 00
DataTransferLength = 00 01 00 00 (65536d)
TimeOutValue = 00 00 00 0A (10d)
DataBuffer = [указатель на заранее выделенный в памяти буфер]
SenseInfoOffset = 00 00 00 30 (48d)
Cdb[16] = D9 2A FF 00|00 00 00 00|00 00 00 00|00 00 4F 54

2. Приём данных
Эта команда осуществляет получение данных с удалённого ПК.
IoControlCode = 4D014 (IOCTL_SCSI_PASS_THROUGH_DIRECT), InBuffer заполняется следующим образом:

Length = 00 2C (44d)
ScsiStatus = 0
PathId = FF (255d)
TargetId = FF (255d)
Lun = FF (255d)
CdbLength = 10 (16d)
SenseInfoLength = 18 (24d)
DataIn = 01
Filler1 (1 байт) = 00
Filler2 (1 байт) = 00
Filler3 (1 байт) = 00
DataTransferLength = 00 01 00 00 (65536d)
TimeOutValue = 00 00 00 0A (10d)
DataBuffer = [указатель на заранее выделенный в памяти буфер]
SenseInfoOffset = 00 00 00 30 (48d)
Cdb[16] = D9 28 64 00|00 00 00 00|00 00 00 00|00 00 4F 54
После выполнения команды буфер DataBuffer будет содержать полученные данные.

3. Запрос статуса удалённого ПК + Установка/получение числа пакетов на передачу/приём
Эта команда возвращает состояние второго компьютера, к которому подключен дальний конец кабеля. Кроме того, этой же командой задаётся количество пакетов, которое требуется передать с текущего ПК, а также возвращается количество пакетов, которые будут переданы с удалённого ПК на текущий.
IoControlCode = 4D004 (IOCTL_SCSI_PASS_THROUGH), InBuffer заполняется следующим образом:

Length = 00 2C (44d)
ScsiStatus = 0
PathId = 0
TargetId = 0
Lun = 0
CdbLength = 10 (16d)
SenseInfoLength = 18 (24d)
DataIn = 01
Filler1 (1 байт) = 00
Filler2 (1 байт) = 00
Filler3 (1 байт) = 00
DataTransferLength = 00 00 00 08 (8d)
TimeOutValue = 00 00 00 05 (5d)
DataBufferOffset = [смещение от начала структуры до заранее выделенного в памяти буфера, например sizeof(SCSI_PASS_THROUGH) + Fillers (8 байт)]
SenseInfoOffset = 00 00 00 30 (48d)
Cdb[16] = D8 00 03 00|00 00 00 00|00 00 00 00|00 00 4F 54
Приведённый CDB используется для обычного запроса статуса. После выполнения команды буфер по смещению DataBufferOffset будет содержать полученный статус. Список возможных статусов приведён ниже:
0, 1, 8 — компьютер офф-лайн (пауза 200 мс):
0 — отключение на текущей стороне
1 — программа на удалённом ПК не запущена
8 — отключение на удалённой стороне
2, 3, 4 — значения по умолчанию, на практике не используются (пауза 50 мс)
5 — пришли новые данные (требуется чтение) (без задержки)
6 — удалённый ПК выполняет чтение данных, но данных для отправки нет (пауза 5 мс)
7 — компьютер он-лайн (пауза 1 мс)
9 — нужна повторная отправка данных / ошибка при получении данных /сбой подключения (без задержки)
A — ?, на практике не встречалось (пауза 5 мс)
B — полное переподключение, на практике не встречалось (пауза 5 мс)

Два байта в CDB, идущие за D8 00 03 (выделены оранжевым), обозначают число пакетов, которое нужно считать удалённому компьютеру. Если эти два байта не равны 0, то удаленный ПК получает при запросе статуса не 07 00 00 00|00 00 00 00|, а 05 00 00 00|00 00 00 00|, т.е. 05 и два отправленных байта.

4. Установка статуса ошибки при передаче (статус плохого соединения)
Эта команда используется для уведомления удалённой стороны об ошибке при передаче данных. Вызывается сразу после чтения (статус=5), признанного ошибочным. В результате выполнения команды удалённый ПК считывает статус=9. Если статус=9, то следует переслать предыдущее сообщение.
IoControlCode = 4D004 (IOCTL_SCSI_PASS_THROUGH), InBuffer заполняется следующим образом:

Length = 00 2C (44d)
ScsiStatus = 0
PathId = 0
TargetId = 0
Lun = 0
CdbLength = 10 (16d)
SenseInfoLength = 0
DataIn = 01
Filler1 (1 байт) = 00
Filler2 (1 байт) = 00
Filler3 (1 байт) = 00
DataTransferLength = 00 00 00 00 (0d)
TimeOutValue = 00 00 00 05 (5d)
DataBufferOffset = sizeof(SCSI_PASS_THROUGH) (в данном случае ничего не принимаем и буфер не создаём)
SenseInfoOffset = 00 00 00 30 (48d)
Cdb[16] = D8 01 0B 00|00 00 00 00|00 00 00 00|00 00 4F 54

5. Получение идентификатора чипа/контроллера
Эта команда возвращает заводскую версию контроллера, заданную при прошивке.
IoControlCode = 4D004 (IOCTL_SCSI_PASS_THROUGH), InBuffer заполняется следующим образом:

Length = 00 2C (44d)
ScsiStatus = 0
PathId = 0
TargetId = 0
Lun = 0
CdbLength = 10 (16d)
SenseInfoLength = 0
DataIn = 01
Filler1 (1 байт) = 00
Filler2 (1 байт) = 00
Filler3 (1 байт) = 00
DataTransferLength = 00 00 00 0C (12d)
TimeOutValue = 00 00 00 05 (5d)
DataBufferOffset = [смещение от начала структуры до заранее выделенного в памяти буфера, например sizeof(SCSI_PASS_THROUGH) + Fillers (8 байт)]
SenseInfoOffset = 00 00 00 30 (48d)
Cdb[16] = F0 00 00 00|00 00 00 00|00 00 00 00|00 00 4F 54
После выполнения команды буфер DataBuffer будет содержать идентификатор контроллера, например:
для 2108: 52 64 22 08|00 01 30 39|30 33 30 31
для 2208NF: 00 00 22 08|00 01 30 38|30 38 32 32

6. Установка величины таймаута для приложения
Эта команда задаёт время, в течение которого контроллер считает приложение активным (т.е. онлайн). Время начинает отсчитываться при каждом запросе статуса удалённой стороны. Иными словами, пока программа проверяет статус удалённого ПК не реже, чем значение таймаута, она считается "живой" (статус=7). В противном случае статус=1.
IoControlCode = 4D004 (IOCTL_SCSI_PASS_THROUGH), InBuffer заполняется следующим образом:

Length = 00 2C (44d)
ScsiStatus = 0
PathId = 0
TargetId = 0
Lun = 0
CdbLength = 10 (16d)
SenseInfoLength = 18 (24d)
DataIn = 01
Filler1 (1 байт) = 00
Filler2 (1 байт) = 00
Filler3 (1 байт) = 00
DataTransferLength = 00 00 00 00 (0d)
TimeOutValue = 00 00 00 05 (5d)
DataBufferOffset = sizeof(SCSI_PASS_THROUGH) (в данном случае ничего не принимаем и буфер не создаём)
SenseInfoOffset = 00 00 00 30 (48d)
Cdb[16] = D8 01 04 00|00 00 00 00|00 00 00 00|00 00 4F 54
Байты, выделенные оранжевым, должны содержать значение таймаута. Принимаются значения от 1000 мс до 10 000 мс. Само значение должно быть приведено к числу, кратному 1000 и уменьшенному в 5 раз. Далее это число в формате U16 делится на старший и младший байты. Старший байт записывается в Cdb[3], младший - в Cdb[4].

7. Получение типа USB-шины удалённой стороны
Эта команда представляет собой более расширенную версию команды 5 (получение идентификатора чипа/контроллера). Она возвращает не только заводскую версию контроллера, заданную при прошивке, но также и тип USB-интерфейса на удалённом ПК: Full Speed (USB 1.1) или High Speed (USB 2.0).
IoControlCode = 4D004 (IOCTL_SCSI_PASS_THROUGH), InBuffer заполняется следующим образом:

Length = 00 2C (44d)
ScsiStatus = 0
PathId = 0
TargetId = 0
Lun = 0
CdbLength = 10 (16d)
SenseInfoLength = 0
DataIn = 01
Filler1 (1 байт) = 00
Filler2 (1 байт) = 00
Filler3 (1 байт) = 00
DataTransferLength = 00 00 00 40 (64d)
TimeOutValue = 00 00 00 05 (5d)
DataBufferOffset = [смещение от начала структуры до заранее выделенного в памяти буфера, например sizeof(SCSI_PASS_THROUGH) + Fillers (8 байт)]
SenseInfoOffset = 00 00 00 30 (48d)
Cdb[16] = F0 00 00 00|00 00 00 00|00 00 00 00|00 00 4F 54
После выполнения команды буфер DataBuffer будет содержать идентификатор контроллера (см. описание команды 5), а также тип USB-шины удалённого компьютера.

Например, выходной буфер DataBuffer после вызова команды содержит следующие данные (64 байта):
00 00 22 08|00 01 30 38|30 38 32 32|01 00 01 00
00 02 00 00|00 20 20 01|00 00 00 00|00 00 00 00
00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00
00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00

Тип USB-шины определяется следующим образом:

Код: Выделить всё

AL = Byte(14-й байт, выделенный оранжевым)
if (AL<>0) then begin
  if (Byte(21-й байт, выделенный голубым)<>20) then
    status:=9 //Full Speed
  else
    status:=8 //High Speed
end
else begin
  if (Byte(22-й байт, выделенный розовым)<>20) then
    status:=9 //Full Speed
  else
    status:=8 //High Speed
end
Ну вот, теперь плавно можем перейти к описанию работы с кабелем в :labview: . В прикреплённом архиве лежат два варианта программы: простая программа для пересылки текстовых сообщений между двумя компами и программа посложнее, способная переслать файл с одного ПК на другой. Для работы программ требуется подключить кабель в USB-порты обоих компьютеров.
USB_Bridge_2108_2208NF.rar
lv2011
(540.99 КБ) 286 скачиваний
Более простая программа Send Write Simple.vi содержит следующие SubVI:
- USB Bridge Find.vi — выполняет поиск USB-девайса в системе по его VID и PID. Если устройство есть в системе, то SubVI выдаст букву виртуального диска, принадлежащего контроллеру, а также символическое имя устройства. За основу USB Bridge Find.vi взят :vi: Get USB Info.vi отсюда.
- USB Bridge Open.vi — открывает сеанс работы с устройством. Используется функция CreateFile из WinAPI, возвращающая хэндл для дальнейших операций чтения/записи.
- USB Bridge Set Timeout.vi — устанавливает величину таймаута для программы (см. описание команды 6).
- USB Bridge Get Status.vi — получает статус удалённого ПК (см. описание команды 3).
- USB Bridge Send Data.vi — отправляет данные на удалённый ПК (см. описание команды 1).
- USB Bridge Receive Data.vi — принимает данные с удалённого ПК (см. описание команды 2).
- USB Bridge Set Bad Status.vi — устанавливает статус ошибки при передаче данных, если принятый пакет "битый" (см. описание команды 4).
- USB Bridge Close.vi — закрывает сеанс работы с устройством. Используется функция CloseHandle из WinAPI.

Логика программы довольно проста: в цикле While непрерывно запрашивается статус удалённой стороны (USB Bridge Get Status.vi). В зависимости от значения статуса выбирается тот или иной кадр Case-структуры согласно описанию команды 3. Программа работает по принципу "аськи": отправленные с одного компа данные сразу же отображаются на другом.

Программа посложнее Send Write - Queue+FileTransfer.vi кроме передачи текстовых сообщений способна передать отдельный файл. Она содержит внутри себя несколько параллельных циклов: цикл коммуникации с удалённой стороной, цикл обработки UI-событий (нажатия кнопок), цикл записи в файл (когда удалённый комп передаёт файл) и цикл чтения из файла (когда удалённый комп принимает файл). Связь между циклами организована через очереди и уведомители. Очереди Data Out и Data In используются для отправки данных на удалённый ПК и приёма данных с него. Уведомитель Stop используется для остановки всех циклов. Уведомитель FilePath используется для передачи пути файла из цикла обработки UI в цикл чтения из файла.

Следует отметить, что в полную силу используется функционал обнаружения и коррекции ошибок в цикле коммуникации. При ошибке приёма данных устанавливается статус ошибки (USB Bridge Set Bad Status.vi), в результате чего удалённая сторона получает статус=9. Это приводит к тому, что последнее отправленное сообщение пересылается удалённым ПК ещё раз. В процессе отправки (USB Bridge Send Data.vi) и приёма (USB Bridge Receive Data.vi) данных используется следующий механизм контроля целостности пакета: в буфере на отправку/приём первые 4 байта - это номер пакета (U32), вторые 4 байта - это номер пакета + 1. Эти два числа также размещены в самом конце буфера (байты, начиная с FFF8 (65528d)). Такой механизм позволяет обнаружить потерю пакета или элементарные повреждения пакета (отсутствие начала/конца, замену полезных данных посторонними). При передаче/приёме файла также проверяется его целостность по алгоритму CRC-64. Конечно, до полноценного файлового менеджера этой программе очень далеко, но с задачей передачи и приёма отдельного файла она неплохо справляется.

Теперь то, что касается собственно кабелей USB Bridge. Данные передаются вполне себе неплохо в обе стороны. Скорость приёма/передачи данных где-то 15-16 МБ/с для кабеля на чипе 2208NF и около 17-18 МБ/с для кабеля на чипе 2108. Использовалась пара ПК с W7 Ultimate x64 и W8.1 Professional x64. В качестве иллюстрации могу приложить вот такие картинки.

Кабель DL-USB015 на чипе 2108:
Компьютер 1:
PC1_2.jpg
Компьютер 2:
PC2_2.jpg
Кабель UANC22V7 на чипе 2208NF:
Компьютер 1:
PC1_1.jpg
Компьютер 2:
PC2_1.jpg
Однако, стоит заметить, что кабель UANC22V7 показал себя хуже в работе, нежели его предшественник на 2108. Выражается это в том, что время от времени возникают "провалы" в передаче данных (см. картинки): контроллер по какой-то причине не воспринимает команду передачи пакета и встаёт как вкопанный. Через несколько секунд возникает таймаут, пакет теряется. Происходит пересылка пакета и возобновление передачи данных. На файл весом в 1-1.5 ГБ такое может произойти 2-3 раза. Событие нечастое, кроме того, не страшное, т.к. программно предусмотрен механизм коррекции потерянных пакетов. Это влияет лишь на время передачи - оно увеличивается на число тайм-аутов в процессе передачи файла. Скорее всего, это аппаратная проблема (или особенность), т.к. на кабелях с другими чипами такого я не наблюдал.
Второй недостаток кабеля на 2208NF - если воткнуть оба конца кабеля в оба компа и включить компы почти одновременно, то на одном из них девайс может никак вообще не определиться или определиться как неизвестное устройство. Похоже, это тоже аппаратная "фича". Лечится только извлечением конца кабеля и включением обратно. Для рядового юзера это мелочи, в принципе, но для того, кто собирается закладывать такой кабель в систему автоматизации, это довольно неприятно, так как там иной раз нет возможности переткнуть кабель. В таком случае можно взять пару USB-реле с обоих концов кабеля и управлять ими программно (пример подобного реле - Cleware USB Connect). Опять же, у кабелей на 2108 или на Prolific такого поведения не замечал.
Помимо прочего, на кабелях с чипами 2108 есть светодиод, моргающий при передаче данных (в отличие от кабеля на базе 2208NF). Мелочь, а приятно. Изображение
В этом плане не совсем понятно, почему чип 2208NF позиционируется производителем как более новый по сравнению с 2108. Казалось бы, более современное устройство должно быть более совершенным. Видимо, это не всегда так. Или же здесь задействован какой-то третий фактор...

В качестве заключения могу сказать, что кабели USB Bridge вполне могут служить альтернативой связи через обычные сетевые карты. Конечно, не без ограничений: максимальная длина кабеля USB - 5 метров, скорость ниже на порядок по сравнению с Gigabit-картами, топология "точка-точка" и только. Зато есть и плюс: простота организации связи - не нужно прописывать никакие настройки, воткнул кабель в оба порта и всё работает. Вывод таков: с задачей обмена файлами или текстовыми данными на небольшом расстоянии кабель USB Bridge справляется на 100%.

P.S.: Тему, в идеале, хотел бы дополнить описанием работы с кабелями стандарта Windows Easy Transfer, а также аналогичным небольшим обзором. Будет зависеть от времени, сил и желания. :rtfm:
Аватара пользователя
Vitekkz88

Activity Silver Автор
expert
expert
Сообщения: 1100
Зарегистрирован: 21 янв 2014, 15:45
Награды: 3
Версия LabVIEW: 12,13,14
Откуда: Томск
Контактная информация:

Re: Кабели USB Bridge и LabVIEW

Сообщение Vitekkz88 »

dadreamer, молодец! Очень интересный и НУЖНЫЙ материал! Спасибо! :super:
Инженер - это открыто светящийся интеллект, свободный и не обидный юмор, это легкость и широта мысли...Это воспитанность, тонкость вкусов, хорошая речь, плавно согласованная и без сорных словечек...
-А. И. Солженицын
Аватара пользователя
Pavel Krivozubov

Activity Bronze
professor
professor
Сообщения: 4421
Зарегистрирован: 07 фев 2008, 16:39
Награды: 3
Версия LabVIEW: 7.0 - 2013
Откуда: г. Электросталь
Благодарил (а): 24 раза
Поблагодарили: 9 раз
Контактная информация:

Re: Кабели USB Bridge и LabVIEW

Сообщение Pavel Krivozubov »

dadreamer, действительно классное и полезное во всех аспектах исследование! В мемориз как говорится :1stplace: :super:
Borjomy_1

Activity Professionalism Silver
doctor
doctor
Сообщения: 2207
Зарегистрирован: 28 июн 2012, 09:32
Награды: 3
Версия LabVIEW: 2009..2020
Откуда: город семи холмов
Благодарил (а): 27 раз
Поблагодарили: 26 раз

Re: Кабели USB Bridge и LabVIEW

Сообщение Borjomy_1 »

Ну не знаю даже...
это и специальный кабель (Не в промышленном исполнении, выполненный китайскими конторами. Сегодня есть, завтра - нет), и соединение точка-точка и специальное программное обеспечение на обоих концах, работающее ненадежно и с нюансами, характерными для каждого чипа/изделия... Единственная необходимость в данном решении - это поставить раком заказчика, максимально усложнив и ограничив технологию обмена данными.
Аватара пользователя
dadreamer

Activity Professionalism Автор
professor
professor
Сообщения: 3926
Зарегистрирован: 17 фев 2013, 16:33
Награды: 4
Версия LabVIEW: 2.5 — 2022
Благодарил (а): 11 раз
Поблагодарили: 126 раз
Контактная информация:

Re: Кабели USB Bridge и LabVIEW

Сообщение dadreamer »

Следует понимать, что предложенный способ - это не замена стандартным механизмам обмена данными. Это альтернатива. Из того, что мы имеем на сегодняшний день, способы связи двух ПК такие:
- локальная сеть: две сетевухи + витая пара;
- соединение через COM/LPT: два порта COM/LPT + нуль-модемный кабель;
- беспроводная связь (Wi-Fi / Bluetooth): два адаптера Wi-Fi / Bluetooth (встроенные или внешние).
Атавизмы типа IrDA и модемов не рассматриваем. Получается не слишком-то широкий выбор. Способ связи по COM/LPT можно тоже выкинуть, в наше время для передачи файлов он вовсе не годится, с его-то скоростями. Остаётся либо беспроводная связь, либо Ethernet.

Предложенный мной способ хоть и специфичен (а точнее, малоизвестен), но имеет кое какие плюсы. Как я писал уже, это и простота установки и подключения (сторонние драйвера не нужны, настройки интерфейса не нужны), универсальность (шина USB есть на любом современном компе) и дешевизна. По последнему параметру: например, две Gigabit-карты + патч-корд обойдутся в (2 х 750 р. - 950 р. + 15 р. за метр + 2 х 30 р. за коннекторы RJ-45) = 1575 - 1975 р. Грубо говоря, полторы - две тысячи рублей. Кабель UANC22V7 стоит около 1 т.р., можно и дешевле найти, рублей за 600. Да, выигрыш в стоимости не очень большой, но всё же есть.
Borjomy_1 писал(а):Не в промышленном исполнении
Для стандартных лабораторных условий вполне подойдёт. Для промышленности совсем другие решения. Используйте то, что там наиболее подходит по параметрам и по требованиям.
Borjomy_1 писал(а):выполненный китайскими конторами
Сейчас практически каждая плата, датчик, преобразователь выпущены китайцами. Тут ничего не поделать.
Borjomy_1 писал(а):Сегодня есть, завтра - нет
Насколько я знаю, чип 2108 перестал поддерживаться OTi несколько лет назад. Но до сих пор продаются кабели на его основе. Не знаю, когда истечёт срок жизни 2208NF, но судя по простом поиску, кабели на его основе также вовсю продаются в интернете.
Borjomy_1 писал(а):соединение точка-точка
С этим мало что можно сделать. Если только брать ещё таких кабелей и замыкать компы в кольцо. Тогда можно попробовать сделать общий буфер и т.п. Но это отдельная задача для того, кто решит выбрать этот путь.
Borjomy_1 писал(а):специальное программное обеспечение на обоих концах
Ну, для Ethernet или Wi-Fi тоже нужно специальное ПО, само собой ничего не заработает. Не бывает такого, что воткнул, и данные передались с компа на комп. Другое дело, что ПО может быть уже написано и для Ethernet, и для Wi-Fi. Для USB Bridge такого ПО не было или оно было проприетарным. Я сделал базовое открытое ПО, которое можно уже допиливать, как угодно.
Borjomy_1 писал(а):работающее ненадежно и с нюансами
С нюансами, да, но, как я писал, нюансами подвержен только UANC22V7. Да и то, такие нюансы обходятся довольно просто. Насчёт ненадёжности не согласен. Я провёл очень много тестов, перед тем, как написать статью и выложить :vi: в доступ. Когда-то давно действительно были сбои. Но в представленной программе все возможные сбои и глюки устранены. Программа наиболее близка с оригиналу (файловому менеджеру от OTi), и работает она аналогично. Специально не искал, но вот пара отзывов: http://www.dns-shop.ru/product/d6c41c41 ... j-gembird/ Я перегонял многогиговые файлы туда-сюда и всё работало замечательно.
Borjomy_1 писал(а):максимально усложнив и ограничив технологию обмена данными
Я как программист не вижу ничего сложного в технологии и представленных программах. Любой нормальный программист так же сможет разобраться. Все команды для работы с девайсом описаны. Все VI описаны. Структура программы описана. Данные передаются в открытой форме. Не вижу сложностей. Может, чуть допилить, сформировав из цикла коммуникации отдельный SubVI. Ну, это уж кому как захочется.

Повторюсь, вовсе не призываю брать этот кабель и сразу же внедрять его на производстве. Но никто не мешает взять пару подобных кабелей и испытать в лабораторных условиях или дома, чтобы расставить все точки над i. Да, и во многих случаях Ethernet на самом деле уместнее.
Аватара пользователя
nae
user
user
Сообщения: 79
Зарегистрирован: 20 мар 2014, 14:21
Версия LabVIEW: 15
Откуда: Новосибирск
Благодарил (а): 5 раз
Контактная информация:

Re: Кабели USB Bridge и LabVIEW

Сообщение nae »

В свежем комплекте sbRIO eval kit шел такой кабель - воткнул его в плату и комп - чуда не произошло. Поискал дрова в интернете - ничего не нашел. Настроил витую пару и задвинул кабель подальше...
Аватара пользователя
dadreamer

Activity Professionalism Автор
professor
professor
Сообщения: 3926
Зарегистрирован: 17 фев 2013, 16:33
Награды: 4
Версия LabVIEW: 2.5 — 2022
Благодарил (а): 11 раз
Поблагодарили: 126 раз
Контактная информация:

Re: Кабели USB Bridge и LabVIEW

Сообщение dadreamer »

nae писал(а):В свежем комплекте sbRIO eval kit шел такой кабель - воткнул его в плату и комп - чуда не произошло. Поискал дрова в интернете - ничего не нашел. Настроил витую пару и задвинул кабель подальше...
Похоже, что не совсем такой же.
NI LabVIEW RIO Evaluation Kit FAQ писал(а):1. Using the Included USB Host-to-Host Cable

The easiest and recommended way to connect to the LabVIEW RIO evaluation target to your host computer is with the included USB host-to-host cable. The central node on the cable should light up when a connection has been established. This USB connection is emulated as an Ethernet device. An automatic network connection is created over the USB device port, which is handy for initial configuration and allows for system updates apart from the physical Ethernet connection. By default the target’s IP address should be hard coded 172.22.11.2. Choose Static IP when using the Setup Utility and leave the address as-is.
Хотя я не нашёл на сайте NI ни фоток кабеля, ни имени фирмы-изготовителя, ни каких-то других тех. данных.

nae, можете скинуть фото кабеля, VID/PID чипа и/или модель (маркировку)? Если кабель поддерживает Windows Easy Transfer, то его можно использовать для обмена данными между двумя ПК. Отдельно драйвера ставить не надо, под Виндой подхватывается стандартный winusb.sys. (Хотя, не знаю, как с этим дела обстоят на RIO-платформе)
Аватара пользователя
dadreamer

Activity Professionalism Автор
professor
professor
Сообщения: 3926
Зарегистрирован: 17 фев 2013, 16:33
Награды: 4
Версия LabVIEW: 2.5 — 2022
Благодарил (а): 11 раз
Поблагодарили: 126 раз
Контактная информация:

Re: Кабели USB Bridge и LabVIEW

Сообщение dadreamer »

Настала наконец пора рассказать о кабелях на стандарте Microsoft Windows Easy Transfer, т.к. нашлось время проверить их работу в :labview: и оценить результаты. Изначально, на момент написания исходного обзора, у меня был в наличии кабель U-441 Windows Easy Transfer Cable от фирмы ST-Lab (USB 2.0) (чип кабеля PL-25A1).
u-441.jpg
Однако прогресс не стоит на месте и в продаже появились аналогичные кабели на базе USB 3.0. Для дополнения статьи и из собственного интереса я прикупил парочку таких кабелей. Первый — это USB 3.0 Active USB Data Link Cable (IUSB-LINK-770) от фирмы Goobay (чип кабеля PL-27A1).
IUSB-LINK-770.jpg
Второй кабель — Delock Cable Data Link + KM Switch USB 3.0 (чип кабеля OT-7300). Поддержка Windows Easy Transfer в этом чипе стала для меня некоторой неожиданностью, т.к. OTi по какой-то причине отказались от собственного протокола и решили использовать стандарт Microsoft (впрочем, оно и к лучшему).
delock_usb_3_0_cable.jpg
Поскольку все три кабеля работают по стандарту Microsoft, то вся коммуникационная часть сводится к использованию арсенала функций WinUSB, то есть библиотеки winusb.dll, которая в свою очередь управляет драйвером winusb.sys. Пакет WinUSB поддерживается с Windows XP SP2. Для инициализации и финализации устройства используются несколько функций из setupapi.dll и kernel32.dll.

MSDN содержит обобщённый пример работы с любым WinUSB-устройством: открытие, чтение/запись, закрытие. Взяв этот пример за основу, я сделал ряд базовых :vi: для работы с WET кабелями в :labview: , а также пример их использования. Пример достаточно прост и работает по принципу "аськи": подключаем кабель в оба компьютера, запускаем программу и можем отправлять текстовые данные с одного компьютера на другой. Вот все исходники:
WinUSB_LV.rar
lv2013
Main VI - First WinUsb Test.vi
(286.29 КБ) 210 скачиваний
Далее кратко опишу назначение каждого :vi: в примере.

Основные :vi: :

- OpenDevice.vi — производит открытие WinUSB-устройства. Входным параметром является тип чипсета кабеля: Prolific (PL-серия) или OTi (чип OT-7300). Тип чипсета определяется идентификатором класса устройства, прописанным в драйвере (GUID). Для кабелей на чипе Prolific используется GUID {1eb7cb03-60a9-4d28-934f-4abeeebd0019}, для кабелей на OT-7300 GUID соответствует {bc103702-dd72-406f-9b28-95c868337b59}. По этому GUID возможен поиск устройства в системе с помощью функционала WinAPI (см. описание GetDevicePath.vi). В процессе поиска определяется путь к экземпляру устройства. Этот путь передаётся в стандартную функцию WinAPI CreateFile, которая возвращает дескриптор (хэндл) для дальнейшей работы с устройством. Хэндл является выходным параметром инструмента OpenDevice.vi.
- GetDevicePath.vi — выполняет поиск устройства в системе по заданному GUID. Принцип работы: строка с GUID конвертируется в кластер (String To GUID Cluster.vi) и передаётся в функцию SetupDiGetClassDevs из setupapi.dll, которая возвращает набор (массив) информации о присутствующих в системе устройствах с таким GUID. С помощью SetupDiEnumDeviceInterfaces из набора извлекается самый первый интерфейс устройства. Двойной вызов SetupDiGetDeviceInterfaceDetail возвращает необходимую информацию об этом интерфейсе - путь к устройству, передаваемый в дальнейшем в CreateFile. Функция SetupDiDestroyDeviceInfoList освобождает память, занимаемую информационным набором.
- InitDevice.vi — инициализирует девайс и возвращает основную информацию (скорость передачи, число входных/выходных каналов, характеристики канала: ID канала, макс. размер пакета). Функция WinUsb_Initialize из winusb.dll выполняет инициализацию по хэндлу устройства, возвращая хэндл интерфейса, с которым работают все остальные функции из WinUSB. Функция WinUsb_QueryDeviceInformation запрашивает информацию об устройстве (в данном случае это скорость передачи: Low Speed (USB 1.0), Full Speed (USB 1.0), High Speed (USB 2.0 и выше)). С помощью функции WinUsb_QueryInterfaceSettings получаем структуру USB_INTERFACE_DESCRIPTOR, в которой нас интересует только число каналов. Далее в цикле For перебираем эти каналы, запрашивая через WinUsb_QueryPipe у каждого канала структуру WINUSB_PIPE_INFORMATION. Из неё получаем тип канала. Нас интересуют только Bulk-каналы, т.к. именно через них производится стандартный обмен данными (бинарными или текстовыми). Направление канала (вход или выход) определяется по его ID: если 7-й бит ID равен 1, то это входной канал, в противном случае канал выходной. Теоретически устройство может иметь несколько входных и выходных каналов. В данной программе (и для данных кабелей) полагаем, что наш девайс имеет по одному каналу каждого вида.
- Write Pipe Sync.vi — выполняет синхронную запись данных в выходной канал (WinUsb_WritePipe). Проще говоря, программа будет ждать, пока все данные не будут записаны в канал. Операция может быть и асинхронной, при необходимости. В данном примере полагаем, что данные будут посланы в канал достаточно быстро и их размер будет небольшим, так что это никак не скажется на быстродействии программы. При передаче плотного потока данных на больших скоростях рекомендуется делать передачу данных асинхронной.
- Read Pipe Async.vi — выполняет асинхронное чтение данных из канала (WinUsb_ReadPipe). При таком способе чтения программа не будет дожидаться, пока в канале окажутся все запрашиваемые данные, а сразу же возвращается из функции. В дальнейшем мы можем организовать собственный цикл ожидания данных. В цикле While вызываем WaitForSingleObject с заданным таймаутом. При получении всех запрашиваемых данных, при таймауте или при какой-либо ошибке функция возвращает соответствующий результат, который анализируется. В случае, когда данные набраны, вызывается WinUsb_GetOverlappedResult для перемещения данных в пользовательский буфер. В том случае, когда данные всё ещё не набраны, а пользователь решил остановить программу, цикл прекращает работу по уведомителю и вызывается WinUsb_AbortPipe для отмены асинхронной операции. Важную роль в асинхронных операциях играет структура OVERLAPPED, содержащая хэндл эвента, который переходит в сигнальное состояние при наступлении события (например, получен весь пакет данных). Более подробно об этом можно почитать на MSDN или в примерах по WinAPI. См. также описание Create Event For Async.vi.
- Flush Pipe.vi — очищает закэшированные в канале данные, вызывая функцию WinUsb_FlushPipe. В данном примере :vi: представлен как концепт. Обычно не требуется использовать этот :vi: при нормальной работе. Для входного канала имеет смысл, когда число принятых байт не равно нулю (т.к. гипотетически данные из канала могут быть не считаны целиком). Для выходного канала смысла не имеет, т.к. данные не кэшируются.
- Free Device.vi — финализирует интерфейс устройства с помощью WinUsb_Free.
- Close Device.vi — закрывает девайс по его хэндлу (вызывается CloseHandle).

Вспомогательные :vi: :

- Create Event For Async.vi — создаёт новый эвент с помощью CreateEvent и помещает его хэндл в структуру OVERLAPPED. Используется для асинхронных операций (в данном случае, это чтение из канала). Для того, чтобы WinAPI мог работать со структурой, пока протекает асинхронная операция, а :labview: не уничтожил её, структура передаётся в виде указателя, а не в виде кластера. Это также позволяет использовать одну и ту же структуру после отмены асинхронной операции.
- Free Event For Async.vi — уничтожает эвент по его хэндлу (вызывается CloseHandle).
- Get Pipe Policy.vi — возвращает текущую политику (т.е., настройку поведения) заданного канала. Доступен ряд политик, которые при желании могут быть изменены на пользовательские. В числе таких политик таймаут передачи данных, игнор коротких пакетов, частичное чтение пакетов, авто-очистка канала и другие.
- Set Pipe Policy.vi — устанавливает текущую политику заданного канала.
- Get Win32 Error Message.vi — возвращает текст ошибки Windows по её числовому коду. Используется FormatMessage из kernel32.dll.

Теперь, после знакомства с функциями WinUSB можем перейти к бенчмаркам. Скажу сразу, файловый менеджер на WinUSB я не стал делать и пока что не вижу в этом нужды. Дело в том, что для кабелей по стандарту Windows Easy Transfer уже существует замечательный менеджер — Total Commander. В нём и будем проводить все тесты. Все три кабеля прекрасно поддерживаются в TC, правда поддержка кабеля Delock Cable Data Link + KM Switch USB 3.0 на чипе OT-7300 появилась лишь с версии 9.0 RC2. Вообще, на сайте TC есть список проверенных кабелей на WET стандарте, которые гарантированно будут там работать: Supported cables for USB cable connection. Как видим, два кабеля из статьи там уже прописаны. Также Ghisler (автор TC) выложил утилиту winusbtest, с помощью которой можно проверить, есть ли связь между компами и поддерживает ли ваш кабель стандарт WET: http://ghisler.fileburst.com/addons/winusbtest.zip Для кабеля на OT-7300 я эту тулзу подправил, прописав новый GUID:
winusbtest_ot.zip
проверка кабеля на OT-7300
(16.36 КБ) 216 скачиваний
Первый тестируемый кабель я проверял на двух компах с W7 64-bit. Остальные два кабеля проверялись на компьютерах с Windows 8.1 64-bit (ноутбук) и Windows 10 64-bit (стационарный ПК). Термины "приём" и "отправка" при таком подключении достаточно условны (что для одного ПК "приём", для другого - "отправка"), поэтому я не стал их использовать.

Кабель U-441 Windows Easy Transfer Cable:
U-441 USB 2.0 - с ПК1 на ПК2
U-441 USB 2.0 - с ПК1 на ПК2
U-441 USB 2.0 - с ПК2 на ПК1
U-441 USB 2.0 - с ПК2 на ПК1
USB 3.0 Active USB Data Link Cable (IUSB-LINK-770):
Goobay USB 3.0 - с ПК1 (W10) на ПК2 (W8.1)
Goobay USB 3.0 - с ПК1 (W10) на ПК2 (W8.1)
Goobay USB 3.0 - с ПК2 (W8.1) на ПК1 (W10)
Goobay USB 3.0 - с ПК2 (W8.1) на ПК1 (W10)
Delock Cable Data Link + KM Switch USB 3.0:
Delock USB 3.0 - с ПК1 (W10) на ПК2 (W8.1)
Delock USB 3.0 - с ПК1 (W10) на ПК2 (W8.1)
Delock USB 3.0 - с ПК2 (W8.1) на ПК1 (W10)
Delock USB 3.0 - с ПК2 (W8.1) на ПК1 (W10)
Получается следующий расклад по скоростям:
- U-441 Windows Easy Transfer Cable — 19-20 МБ/с;
- USB 3.0 Active USB Data Link Cable (IUSB-LINK-770) — 44,5-63 МБ/с;
- Delock Cable Data Link + KM Switch USB 3.0 — 31-39 МБ/с.

Понятно, что USB 3.0 кабели перегоняют данные быстрее кабелей 2.0 из-за более продвинутого стандарта. Однако они и более чувствительны к железу (хост-контроллер шины USB и, скорее всего, остальная периферия, такая как материнка, процессор и т.д.), отсюда такой разброс по скоростям. Отсюда и недостижимость теоретического "потолка" в 5 Гбит/с. Другое дело, что при большой скорости "провалы" становятся менее критичными, т.к. общее время на передачу всё равно заметно меньше, чем при использовании кабелей старого стандарта.
В целом, WET кабели показали себя в работе весьма неплохо. Так что я даже не смог выделить особых нюансов и каких-то "подводных камней". Если стандарт USB продолжит так гармонично развиваться, то в будущем возможно появление аналогичных кабелей на 3.1 и 4.0.

P.S.: Внимательный читатель мог заметить, что в этой статье не был описан кое какой функционал кабелей помимо собственно файлового трансфера. Это, например, создание локальной сети, шаринг интернета с компа на комп и некоторые другие "фишки". Я не стал заострять на этом внимание, т.к. не для всех кабелей эти вещи доступны, и кроме того этот функционал недоступен вовсе для программиста (на которого сделан упор). Конечно, всё это довольно любопытно. К примеру, сетка на Delock Cable Data Link + KM Switch USB 3.0 делается в несколько действий. Интересная штука — и софтовый KVM, когда одной мышью и клавой можно управлять двумя компами одновременно. Оставляю эти "примочки" на разбор интересующимся. Изображение
Ответить
  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Коммуникация с приборами»