【Codesys】DINT类型环形计数处理,计数到2的64次方

最近有遇到编码器计数的计数处理,抓取编码器锁存的数值只能在DINT类型范围内,是从-2147483648到2147483647数值,但是现场会有正向多圈的情况。此时需要记录这个数的位置值。就需要记录多圈计数下,圈数的处理。


PROGRAM FB_DintCirAcc
VAR  
    currentCount : DINT; // 当前计数器的值,DINT类型的范围是从-2147483648到2147483647
    circle1 : ULINT := 0; // 经过的极限值圈数  
    circle2 : ULINT := 0; // 经过的一次16位最大值的圈数 
    maxThreshold : DINT := 2147470000; // 接近最大值的阈值  
    minThreshold : DINT := -2147470000; // 接近最小值的阈值  
    ZeroThreshold : DINT := -10000; // 接近零值的阈值  
    approachingMax : BOOL := FALSE; // 标志位,表示是否接近最大值  
    approachingMin : BOOL := FALSE; // 标志位,表示是否接近最小值  
    approachingZero : BOOL := FALSE; // 标志位,表示是否接近零值
    LastCount:DINT;//记录上一周的计数。
    bInit:BOOL:=TRUE;  //初始化
    bCountStrat:BOOL;    //模拟开始周期计数
    EncoderPos:LREAL;//编码器位置
    CalcPos:LREAL;//计数值累加位置
    ulCurrentCount:ULINT;//累加计数值
    DiffData:DINT;//负向累加差值
    UlCirData:ULINT;//负向时圈数值
END_VAR  
  

//模拟先给最大值,跑到第一圈的最大值
IF bInit THEN
    currentCount:=2147400000;
    Encoder.diEncoderPosition:=currentCount;
    bInit:=FALSE;
END_IF
// 假设currentCount在每个周期更新  
IF bCountStrat THEN
    currentCount := currentCount+10000;  
    Encoder.diEncoderPosition:=currentCount;
END_IF
  
// 检测是否接近最大值或最小值  
IF (currentCount > maxThreshold) AND NOT approachingMax THEN  
    // 开始接近最大值  
    approachingMax := TRUE;  
ELSIF currentCount>0 AND  (currentCount <= maxThreshold) AND approachingMax THEN  
    // 不再接近最大值  
    approachingMax := FALSE;  
END_IF  
// 检测是否接近最大值或最小值 
IF (currentCount < minThreshold) AND NOT approachingMin THEN  
    // 开始接近最小值  
    approachingMin := TRUE;  
ELSIF currentCount<0 AND (currentCount >= minThreshold) AND approachingMin THEN  
    // 不再接近最小值  
    approachingMin := FALSE;  
END_IF  
// 检测负值累加是否接近0值。  
IF (currentCount < ZeroThreshold)
    AND (currentCount>(ZeroThreshold*2))
    AND NOT approachingZero THEN  
    // 开始接近最小值  
    approachingZero := TRUE;  
END_IF  

// 检测是否从接近最大值过渡到接近最小值,累加一次计数
IF approachingMax AND approachingMin THEN  
    // 从最大值过渡到最小值,计为一圈  
    circle1 := circle1 + 1;  
    circle2    := circle2 + 1;
    approachingMax := FALSE; // 重置接近最大值的标志  
    approachingMin := FALSE; // 重置接近最小值的标志  
END_IF  
// 检测是否从接近0值,累加一次计数
IF approachingZero AND currentCount>0 THEN
    circle2    := circle2 + 1;
    approachingZero:=FALSE;
END_IF
Encoder.iTurn;
IF  circle1 = 0 THEN
    ulCurrentCount:=(currentCount);
ELSE
    IF currentCount>0 THEN
        ulCurrentCount:=(circle2*2147483647)+DINT_TO_ULINT(currentCount);
    ELSE 
        IF circle1=1 THEN
            DiffData:=ABS((2147483647-currentCount));
            UlCirData:=(circle1*2147483647);
            ulCurrentCount:=DINT_TO_ULINT(DiffData)+UlCirData;
        ELSIF circle1>1 THEN
            DiffData:=ABS((2147483647-currentCount));
            UlCirData:=(((circle1*2)-1)*2147483647);
            ulCurrentCount:=DINT_TO_ULINT(DiffData)+UlCirData;
        END_IF
    END_IF
END_IF
EncoderPos:=Encoder.fActPosition;
CalcPos:=(ulCurrentCount*97.456)/10000;
 

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值