Обмен данными с PRU

Для обмена данными с PRU используется программы BlinkningLeds_Pru0MemoryRead и BlinkningLeds_Pru0MemoryWrite. Их текст генерируется в зависимости от того, какие переменные отмечены на обмен между PRU и основным циклом.

Обмен данными занимает ресурсы (регистры, память) PRU, поэтому чтобы увеличить набор синхронизируемых переменных нужно пересобирать (перекомпилировать) PRU программу и после этого переимпортировать результирующий .exp.

Следует понимать, что:

  • При обмене происходит обновление всех переменных (либо читаются все, либо пишутся все). Нет смысла вызывать обмен несколько раз только для того, чтобы по-очереди передать каждую отдельную переменную.
  • Во время обмена данными PRU ядро не выполняет пользовательскую программу и не опрашивает входы. Получаемые значения целостны и согласованы между собой.
  • Для отладки PRU в режиме online, можно отмечать некоторые переменные на обмен, и тогда их значения будет видно в CoDeSys online
  • Сначала происходит передача данных в PRU, а затем чтение данных из PRU. Между этими двумя операциями PRU может успеть выполнить свой цикл.
  • Не стоит делать input output переменные для обмена. Они будут работать как input.

Есть несколько направлений, где могут передаваться данные:

  • Основная программа → PRU
  • PRU → основная программа
  • PRU0 ↔ PRU1

Общий подход

При составлении основной программы PLC_PRG стоит придерживаться следующего подхода:

PROGRAM PLC_PRG
...

(* В начале программы читаем состояние PRU *)
BlinkningLeds_Pru0MemoryRead()

(* К значениям из PRU можно обращаться через точку *)
BlinkningLeds_Pru0MemoryWrite.

(* В конце программы записываем новые значения в PRU *)
BlinkningLeds_Pru0MemoryWrite()

END_PROGRAM

Передача данных в PRU

Если PRU управляет шаговым двигателем, то передача данных в PRU позволит настроить PRU программу на нужное количество импульсов, скорость подачи импульсов.

Если же необходимо задействовать “быстрый” выход как обычный (т.е. управлять им из основной программы), то это тоже делается через передачу данных из основного цикла в PRU программу. PRU программа управляет выходом, а команда на включение-выключение передаётся между основным циклом и PRU программой.

Рассмотрим PRU программу

PROGRAM OUT_CONTROL 
  variables: 
    <no variables> 
   
  body: 
    FAST_OUTPUTS(out3 := FALSE); 
END_PROGRAM

Добавим в неё возможность управления быстрым выходом по сигналу “основного цикла”. Для этого нужно объявить переменную.

Объявили переменную для обмена

Если сейчас запутить программу, то ничего не изменится. Выход по-прежнему будет неактивен, а всё потому, что переменная active не обозначена к обмену между основным циклом и PRU программой.

Для того, чтобы управлять этой переменной из основного цикла – нужно установить курсор на строку с объявлением переменной и нажать alt+enter (или на возникшую лампочку слева).

Объявили переменную для обмена

И в появившемся меню выбрать пункт “Exchange this variable with HOST”

Включаем обмен с основным циклом

Код станет выглядеть вот так:

Передача данных в PRU настроена

При компиляции этой PRU программы, в результирующей программе OutControlPruConfig_Pru0MemoryWrite будет переменная с именем OUT_CONTROL_active (название складывается из названия блока в котором находится переменная и названия самой переменной).

PROGRAM OutControlPruConfig_Pru0MemoryWrite
VAR_INPUT
  OUT_CONTROL_active : BOOL;
END_VAR
VAR_OUTPUT
  running : BOOL;
  writeFails : DWORD;
  readFails : DWORD;
END_VAR

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

OutControlPruConfig_Pru0MemoryWrite(
  OUT_CONTROL_active := ...
);

Сам обмен происходит в момент вызова MemoryWrite.

Чтение данных из PRU

В целом, чтение ничем не отличается от записи, за исключением того, что используется программа MemoryRead вместо MemoryWrite. Точно так же нужно объявить переменную (на этот раз output, а не input), и настроить для неё Exchange with HOST.

Например, если в основном цикле нужно значение “быстрого входа”, то это можно реализовать следующим образом:

Передача данных из PRU в основной цикл

Обмен в случае функциональных блоков

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

Например:

  • Блок чтения быстрых входов FAST_INPUTS возвращает 4 значения, а кому-то может требоваться только одно-два
  • Блок энкодера может возвращать как само положение, так и счётчик обработанных импульсов

Если включать в обмен все-все переменные, то ресурсы закончатся.

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

Например, рассмотрим программу, обработки значения с энкодера

Обработка энкодера и передача данных в основной цикл

Здесь в параметрах @Export перечислены те переменные блока энкодера, которые нужно синхронизировать с основным циклом.

После компиляции и импорта .exp файла, на стороне КДС возникнет три VAR_OUTPUT переменных:

PROCESS_ENCODER_encoder_counter : WORD; 
PROCESS_ENCODER_encoder_position : WORD; 
PROCESS_ENCODER_encoder_zeroDetected : BOOL;

Updated:

Leave a Comment