Для реализации определенных задач потребовалась генерация случайных чисел.

Перечитав форумы, нашлось достаточно решений и мнений, но все они сводились к одному из трех решений:

  1. Использовать функцию случайного числа из библиотек.
  2. Генерировать случайное число от времени.
  3. Использовать непонятные длинные формулы.

Но каждое из решений не устроило, по той или иной причине.

Требуется быстрая генерация случайного числа, да еще с хорошей не повторяемостью чисел.

Мне попалась статья американского математика Джорджа Марсаглии (George Marsaglia) о генерации случайного числа путем простых действий. Данный метод называется Xorshift RNGs.

Со статьей в оригинале можно ознакомиться по ссылке: Xorshift RNGs. George Marsaglia. The Florida State University

На основе статьи написал функциональный блок, который отлично удовлетворяет всем требованиям, простой в реализации и работает во всех ПЛК, которые я использую в своих проектах.

Заголовок функционального блока:

FUNCTION_BLOCK xorshift
VAR_INPUT
In1: DWORD;
In2: DWORD;
END_VAR
VAR_OUTPUT
Out1: DWORD:=1;
Out2: DWORD:=2;
Random: REAL;
END_VAR
VAR
END_VAR

Код функционального блока:

in1 := in1 XOR SHL(in1,23);
in1 := in1 XOR SHR(in1,17);
in1 := in1 XOR in2;
in1 := in1 XOR SHR(in2,26);
random := (1.0/4294967295.0*(in1+in2))+0.5;
out1 := in1;
out2 := in1+in2;

Пример использования функционального блока:

VAR
RND:xorshift; (*Инициализация FB*)
END_VAR
RND(in1:=RND.out1,in2:=RND.out2); (*Генерация случайного числа*)
RND.Random; (*Случайное число*)

В каждом цикле ПЛК получаете сгенерированное случайное число с большим периодом повторения.

В переменной RND.Random содержится значение от 0 до 1.