August 4, 2016

Доступ к портам ввода/вывода

TwinCAT позволяет превратить обычный ПК в PC-based Control System, то есть в итоге мы получим обычный ПК, который сможет управлять промышленными объектами. В общем, так и есть, но сам ПК по прежнему с нами и все его "плюшки" по прежнему готовы к употреблению.

Начнем с простого — графическая система. ПК позволяет запускать "тяжелые" графические системы: вы можете взять Unity3D, нарисовать "тяжелую", трехмерную, интерактивную визуализацию, а затем через TwinCAT.Ads API связать ее с ПЛК-программой реального времени. Ну, или просто запустить игру и убедиться, что она работает как на обычном десктопе:



Убедившись, что это работает, спустимся ниже — куда-нибудь ближе к железу ПК. Здесь TwinCAT предлагает нам, как специалистам умелым и разумным, прямой путь к железу ПК через порты/ввода.
Выдержка из справочной системы: прямой доступ к железу — не проблема, пока вы только читаете из портов. Проблемы начнутся, когда вы начнете писать в порты ввода/вывода железа.


Порты ввода/вывода


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

В справочной системе, для примера, приводится работа с "пищалкой" pc-speaker'ом; для работы которого сначала нужно записать значение делителя для системного таймера, а затем установить бит включения спикера (или сбросить его, когда он надоест своим пронзительным верещанием).

Для работы с портами используются две функции F_IOPortRead и F_IOPortWrite. Описывать их смысла мало, поэтому возьмем пример из справочной системы и заставим спикер исполнять простые мелодии. Полный проект доступен на GitHub'е в виде исходных кодов плеера и готовой к установке библиотеки.


Готовая библиотека


Чтобы было проще, я обернул функцию спикера в библиотечную функцию FB_PcSpeaker. Саму библиотеку Tc3_PcSpeaker (с единственной функцией) можно скачать и установить в систему.
Как устанавливать библиотеки расписано в нюансах библиотек в TwinCAT 3.

Единственная функция проста до приличия:

Speaker : FB_PcSpeaker;
F, L, D : REAL;
M       : REAL := 1; // duration multiplier

[...]

Speaker(
    Freq    := REAL_TO_DWORD( F ),
    Length  := REAL_TO_TIME ( L * M ),
    Delay   := REAL_TO_TIME ( D ),
    Execute := TRUE );

IF NOT Speaker.Busy THEN
    Speaker(Execute:= FALSE);
    // Next beep, please...
END_IF


Исполняем мелодии


Для исполнения мелодий нам нужны ноты. Вычленим их из миди-файлов и запишем в глобальную переменную в виде массива троек чисел: частота, длительность, пауза после ноты (стандартная последовательность для утилиты beep из мира Linux). Так как все мелодии разные и было бы странным ожидать от них одинаковой длины, то сигналом стоп будет служить тройка нулей.

VAR_GLOBAL CONSTANT
(* Star Wars Imperial March *) 
    Beeps : ARRAY[0..201] OF REAL := [392, 350, 100, 392, 350, 100, (* [...] *), 0, 0, 0];
END_VAR


Для извлечения нот из массива произвольной длины, будем извлекать ноты через... указатели, копируя значения до тех пор, пока не встретится набор из трех нулей. Почти как тип STRING, оканчивающийся нулем /0, только три нуля.
Можно было бы воспользоваться функцией UPPER_BOUND для получения размера массива, но использовать мощный, промышленный контроллер для воспроизведения мелодий уже не оптимально, так что продолжаем развлекаться...

pNotes : PVOID;
szR    : UDINT := SIZEOF(REAL);

[...]

MEMCPY(ADR(F), pNotes, szR);
pNotes := pNotes + szR;
MEMCPY(ADR(L), pNotes, szR);
pNotes := pNotes + szR;
MEMCPY(ADR(D), pNotes, szR);
pNotes := pNotes + szR;


Вот и все, разве что выключить спикер напоследок. Воспользуемся экшеном:

Speaker.SwitchOff();

No comments

Post a Comment

Note: Only a member of this blog may post a comment.