无心飞扬 发表于 2024-11-5 21:34:24

伪随机数-codesys的ST实现两种方法

ST实现伪随机数的两种方法
使用codesys的FUN函数块实现

方法一:LCG算法,Seed= (Seed *259 + 147) MOD 27200
(**********************************************变量区一**********************************************)
VAR_IN_OUT
      Seed:dINT;
      Range_MinValue:REAL;
      Range_MaxValue:REAL;
end_var
var_output
      RandReal:REAL;
END_VAR
VAR
      SCALE_X:REAL;
      RandInt:dINT;
END_VAR

(*********************************************程序区一**********************************************)
//算出的seed
      RandInt := (Seed *259 + 147) MOD 27200;
      Seed := RandInt;
//把数据压缩到在0至1.0之间      
      RandReal := DINT_TO_REAL(RandInt)/ 27200.0;
//设置区间后,输出区间值缩放:OUT = + MIN
IF          Range_MinValue < Range_MaxValueTHEN
      SCALE_X :=RandReal*(Range_MaxValue-Range_Minvalue)+Range_Minvalue;
      RandReal := SCALE_X;
END_IF


方法二:使用系统时间纳秒
(**********************************************变量区二**********************************************)
FUNCTION NS_Random_R : real
VAR_INPUT
      Range_MinValue:REAL;
      Range_MaxValue:REAL;
end_var

VAR CONSTANT
      udiMinUdint:UDINT:=0;//无符号双整数的最小值
      udiMaxUdint:UDINT:=16#ffffffff;//无符号双整数的最大值4294967295
END_VAR

VAR
      uliGetRtcNs: ULINT;      //获取系统时间纳秒变量,Alias SYSTIME: ULINT
      //udiGetRtcNsStatus: UDINT;//获取纳秒时间结果*)
      
(*数据转换变量*)
      uliConvertValue0: UDINT;
      uliConvertValue1: UDINT;
      uliConvertValue2: UDINT;
      uliConvertValue3: UDINT;
      uliConvertValue4: UDINT;
      uliConvertValue:UDINT;
      
      rNORM_X:REAL;
      SCALE_X:REAL;

END_VAR

(**********************************************程序区二**********************************************)
(*//读取PLC的系统时间纳秒读数,
//然后取系统时间纳秒后四字节,并交换字节顺序:1234转为4321
//再标准化之后压缩到0.0到1.0之间,
//最后线性转化到设定范围内
//未设置缩放范围,输出结果是在0到1.0之间*)

(*读系统时间纳秒,纳秒是64位无符号长整型数*)
      //udiGetRtcNsStatus:=SysTimeGetNs(uliGetRtcNs);
      SysTimeGetNs(uliGetRtcNs);
(*读出来的纳秒是8个字节无符号长整型数,取后四个字节,并交换字节顺序:1234转为4321*)
      uliConvertValue0:=ULINT_TO_UDINT(uliGetRtcNs);//把8字节无符号长整数转换成4字节无符号整数
      uliConvertValue1 := ROL(uliConvertValue0,24);//交换第1字节和第3字节
      uliConvertValue2 := ROL(uliConvertValue0,8);//交换第0字节和第2字节
      uliConvertValue3 := uliConvertValue1 AND 16#FF00FF00;
      uliConvertValue4 := uliConvertValue2 AND 16#00FF00FF;
      uliConvertValue := uliConvertValue3 OR uliConvertValue4;
      
(*把变量的值映射到0.0~1.0之间,对其进行标准化*)
//标准化公式:OUT = (VALUE – MIN) / (MAX – MIN)
      rNORM_X := UDINT_TO_REAL(uliConvertValue-udiMinUdint) /UDINT_TO_REAL(udiMaxUdint-udiMinUdint);
      NS_Random_R := rNORM_X;

(*把标准化结果缩放到指定的取值范围(最小值和最大值之间)*)
//先判断是否使用缩放区间
//缩放公式:OUT = + MIN
IF         Range_MinValue < Range_MaxValueTHEN
      SCALE_X :=rNORM_X*(Range_MaxValue-Range_Minvalue)+Range_Minvalue;
      NS_Random_R := SCALE_X;
END_IF

(**********************************************效果**********************************************)



页: [1]
查看完整版本: 伪随机数-codesys的ST实现两种方法