Учебный стенд LESO6 и LabVIEW

Шауэрман Александр А. shamrel@yandex.ru

В этой статье постараемся разобраться, как организовать взаимодействие персонального компьютера (ПК) с учебным стендом LESO6 в среде графического программирования LabVIEW (National instruments). Эта информация будет актуальна для учебного стенда LESO1 и для любого другого устройства на микроконтроллере, где для связи с компьютером использован преобразователь USB от Future Technology Devices International (FTDI).

И так, стенд LESO6 (а также и LESO1, и LESO3) подключается к ПК через интерфейс USB. На стендах установлена микросхема преобразователя USB<->UART FT232RL. Таким образом, на стороне микроконтроллера взаимодействие будет происходить через последовательный интерфейс UART. Согласно принципиальной схеме стенда это USART1. На стороне компьютера стенд определится как последовательный порт. Из среды LabVIEW для работы с последовательными портами можно использовать компонент NI-VISA, однако, как показала многолетняя практика нашей лаборатории, удобнее и надежнее использовать непосредственно драйвер D2XX.

Для организации такого взаимодействия нужно решить следующие задачи:
1. Разработать протокол взаимодействия, другими словами определить в каком формате будут передаваться команды и данные с устройства на ПК и обратно, определить формат пакета.
2. Разработать программное обеспечение для микроконтроллера. Оно должно включать в себя драйвер USART, декодер и формирователь команд, и собственно, функции, которые выполняют сами прикладные действия.
3. Разработать ПО для компьютера.

Рассмотрим решение задачи в режиме "от простого к сложному".

Шаг первый. Подключаем стенд

На первом этапе обойдемся без программы для микроконтроллера и какого-либо протокола связи. Научим LabVIEW взаимодействовать со стендом.

Как уже говорилось, работать будем непосредственно с драйвером. Драйвер представляет собой динамическую библиотеку ftd2xx.dll, которая находится в директории с Windows (как правило C:\Windows\System32). Естественно, в системе должен быть установлен драйвер FTDI D2XX. Если это не так, то скачиваем с официального сайта www.ftdichip.com и устанавливаем. В LabVIEW работа с динамическими библиотеками dll осуществляется с помощью узла (Node) Call Library Function (палитра Connectivity -> Libraries & Executables). Этот узел позволяет вызвать определенную функцию из dll, для этого нужно указать путь к библиотеке, выбрать функцию, определить типы входных и выходных переменных, назначит буфера для ввода-вывода... Если вдруг кто-то по какой-то причине не захочет этим заниматься, то можно скачать готовые подприборы (subVI) с сайта FTDI LabVIEW Examples. Так мы и сделаем. Скачиваем и распаковываем архив D2XX_Functions_7.0.zip.

Для создания простейшей программы на LabVIEW для работы со стендом на понадобится всего лишь один subVI из скаченной библиотеки. Создадим новый VI и добавим туда через пункт "Select a VI..." подприбор FT_Get_Number_of_Devices. Этот subVI возвращает количество устройств FTDI, подключенных к компьютеру. Модуль имеет всего два выхода "FT_Status" и "Number of Devices". Легко догадаться, что последний как раз и возвращает число устройств, а первый возвращает статус. Следует отметить, что все subVI из библиотеки возвращают статус устройства, по этому статусу легко отслеживать состояние интерфейса и результат выполнения команды. Создаем для каждого вывода соответствующие индикаторы. Напомню, для того, чтобы создался индикатор требуемого типа, правой кнопкой мыши нажмем на выводе, выберем пункт "Create", а там уже "Indicator". В результате должно получиться как на рисунке ниже.

 

FTDI Get Number of Devices

Для компактности вида я обычно в контекстном меню индикатора или контрола убираю галочку с "View As Icon".

Если в результате запуска число устройств будет больше нуля, а статус – "FT_OK", то можно работать дальше, если иначе, следует разобраться с драйверами и еще раз проверить физическое подключение стенда.

Аналогичную простейшую программу с одним subVI можно создать с помощью некоторых других модулей, например FT_Get_Device_Description_By_Index – возвращает строку с описанием подключенного прибора.

Шаг второй. Открываем и закрываем

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

Устройство может быть открыто по его номеру в системе (если устройство одно, то этот номер 0), по его описанию (прошито в память FTDI, для стендов это "LESO6", "LESO1.1" и т.д.), по серийному номеру или по его положению на шине USB (номер USB порта). Для каждого способа предназначен соответствующий subVIE: FT_Open_Device_By_Index, FT_Open_Device_By_Description, FT_Open_Device_By_Serial_Number, FT_Open_Device_By_Location. На рисунке ниже пример программы, которая открывает устройство по индексу, возвращает статус и закрывает устройство.

 

FTDI Open Device By Index

Такой способ наиболее простой и подходит, если к компьютеру подключено одновременно не более одного преобразователя FTDI, в противном случае, целесообразно использовать открытие по описанию (By Description), как показано ниже:

 

FTDI Open Device By Description

После завершения всех манипуляций с устройством, оно должно быть закрыто. В завершении программы обязательно должен быть использован subVIE FT_Close_Device. В противном случае, при повторном запуске программы драйвер сообщит (вернет FT_Status), что устройство занято и/или уже используется. Хотя переподключение стенда устранит проблему, всегда следует позаботиться о корректном завершении вашей программы.

Шаг третий. Обмен данными

Реpализуем на LabVIEW типовой алгоритм взаимодействия с прибором: открыть устройство -> настроить устройство -> послать данные -> принять данные -> закрыть устройство.

Для начала создадим простейший проект для LESO6, я буду использовать драйвера периферии из проекта leso6_demo (можно взять из git репозитория). Программа инициализирует UART на скорости 11520 кБит/с, в функции обратного вызова uart_rx_cb() принятый байт отправляется обратно. Программа реализует алгоритм "Эхо". Листинг ниже.

#include <avr/io.h>
#include <stdint.h>
 
#include "gpio.h"
#include "uart.h"
//< Функция обратного вызова для приема байта по uart.
void uart_rx_cb(uint8_t ch) 
{
		uart_putchar(ch, NULL);
}
 
int main()
{
	uart_init();		//!< Инициализируем UART.
	// Устанавливаем функцию обратного вызова на прием байта по UART.
	uart_set_input_cb(uart_rx_cb);
	while(1);		//
	return 0;
}

Компилируем и загружаем программу в лабораторный стенд. (Как это сделать?)

Открывать и закрывать устройство мы уже умеем, разберемся как настраивать. Подприбор FT_Set_Baud_Rate устанавливает скорость передачи (для нашего примера 115200), подприбор FT_Set_Data_Characteristics задает режим работы: 8/7-ми битный, количество стоп-бит, наличие/отсутствие/назначение бита паритета (9-ый бит, бит четности).

 

FTDI Set Baud Rate and Data Characteristics

После настройки правилом хорошего тона является очистить входные и выходные буфера, для этого используем subVI FT_Purge.

Отправить данные микроконтроллеру можно с помощью подприборов FT_Write_Byte_Data и FT_Write_String_Data. Оба этих subVI используют одну и туже функцию драйвера FT_Write, отличаются лишь формой представления данных. Первый подприбор на вход принимает массив байт и число байт для отправки, второй – строку, количество байт для отправки соответствует длине строки. Оба подприбора помимо статуса возвращают количество реально отправленных байт.

 

FTDI Write Data and String Characteristics

Для приема данных служат два похожих subVI: FT_Read_Byte_Data и FT_Read_String_Data. Как понятно из названия, первый принимает байтовый массив, второй строку – по сути это одно и тоже. Обоим подприборам помимо handle на вход следует подать количество байт для приема. На выходе собственно сами принятые данные, их количество и, как всегда, статус. Если будет запрошено байт больше, чем в данный момент содержится в приемном буфере, то выполнение программы будет заблокировано, пока в буфере не появятся требуемые байты. Это не всегда удобно, потому рекомендую подприборы чтения использовать совместно с подприбором FT_Get_Queue_Status, который вернет число байт доступных для чтения в настоящий момент. На рисунке ниже показана блок-диаграмма и фронтальная панель программы, работающей по описанному алгоритму.

 

FTDI Open Device By Description

Стоит обратить внимание на одну особенность, в LabVIEW узлы и подприборы выполняются в той очередности, в которой на их входа поступают данные. То-есть, узел выполнится только тогда, когда на всех его входах появятся актуальные данные, причем порядок расположение узлов на блок-диаграмме роли никакой не играет.

Front Panel

Отсюда следует, что если у двух узлов одновременно на входа поступят данные, то очередность их выполнения будет случайной. Так на рисунке выше видно, что на подприборы FT_Purge, FT_Set_Baud_Rate и FT_Set_Data_Characteristics данные приходят одновременно, потому порядок их выполнения предсказать сложно. Однако в этом конкретном примере для нас это не играет никакой роли: не важно, установим ли мы вначале скорость передачи или количество стоп-бит. Совсем другое дело, если поменяется очередь выполнения записи и чтения (FT_Write_Byte_Data и FT_Read_Byte_Data), в этом случае будет нарушен алгоритм работы. В нашей программе для того, чтобы упорядочить очередь выполнения использована Flat Sequence Structure (палитра Programming -> Structures). Рамки в этой структуре выполняются последовательно слева направо. В следующих статьях мы рассмотрим как модифицировать подприборы FTDI таким образом, чтобы жестко упорядочить последовательность выполнения без громоздких структур.

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

9 апреля 2015
Орфографическая ошибка в тексте:
Чтобы сообщить об ошибке автору, нажмите кнопку "Отправить сообщение об ошибке". Вы также можете отправить свой комментарий.