Cannot convert type 'UDINT' to type 'POINTER TO BOOL' Error in Beckhoff. FB Used to work in Codesys (IFM) for years

I am trying to reuse a FB in Beckhoff that I used in Codesys for years. Beckhoff is based on Codesys, therefore I did not expect any problems. I think the error has something to do with a type conversion that is possible in Codesys but not in Beckhoff. Error: Cannot convert type 'UDINT' to type 'POINTER TO BOOL'.

Underneath my code can be found. This FB has worked for 5+ years in multiple projects already with PLC's from IFM.

 FUNCTION_BLOCK FC_AlarmsHandler VAR_INPUT LI_bIN: BOOL; /// Reset Alarms bits - only Alarms that are acknowledged LI_bReset: BOOL; /// Acknowledge all active Alarms bits at once LI_bAckAll: BOOL; /// Hold time of new alarm LI_rHoldTimeNewAlarms: REAL; /// Base address of Alarms group struct LI_adrAlarmsGroup: DWORD; /// Number of Alarms group elements LI_sizeofAlarmsGroup: UINT; /// Base address of Alarms struct LI_adrAlarms: DWORD; /// Base address of Alarms old array of bool LI_adrAlarmsOld: DWORD; /// Base address of Alarms hold array of bool LI_adrAlarmsHold: DWORD; /// Base address of Alarms acknowledge array of bool LI_adrAlarmsAck: DWORD; LI_adrAlarmsText: POINTER TO STRING(64); END_VAR VAR_OUTPUT LQ_bOUT: BOOL; /// New Alarm -> this output is one cycle high LQ_bNewAlarm: BOOL; /// When an alarm is active, this output is high LQ_bAlarmActive: BOOL; /// Alarm gone -> this output is one cycle high LQ_bAlarmGone: BOOL; END_VAR VAR LT_bInit: BOOL; /// offset for group address LT_adrOffsetGroup: DWORD; LT_iNumberOfAlarmGroupElements: UINT; /// Number of lines for alarm visualization table in Hmi LT_iNumberOfHmiLines: INT; /// Number of lines for alarm history visualization table in Hmi LT_iNumberOfHmiHistoryLines: INT; LT_ptAlarms: POINTER TO BOOL; LT_ptAlarmsOld: POINTER TO BOOL; LT_ptAlarmsHold: POINTER TO BOOL; LT_ptAlarmsAck: POINTER TO BOOL; LT_ptAlarmsText: POINTER TO STRING(64); LT_iCounterAlarmsElements: INT; /// Timer for holding new alarm fbTofNewAlarm: TOF; END_VAR 
LQ_bOUT:=LI_bIN; // Init IF LT_bInit = FALSE THEN LT_adrOffsetGroup := LI_adrAlarmsGroup - LI_adrAlarms; LT_iNumberOfAlarmGroupElements := LI_sizeofAlarmsGroup / SIZEOF(LT_ptAlarms^); // Alarm array for HMI LT_iNumberOfHmiLines := GDI_Alarms.iNumberOfHmiLines; // Alarm history array for HMI LT_iNumberOfHmiHistoryLines := GDI_Alarms.iNumberOfHmiHistoryLines; LT_bInit := TRUE; END_IF (***************************************************************************) (* Alarm handling *) (***************************************************************************) [HERE I AM HAVING MY PROBLEMS] // Init new scan cycle LT_ptAlarms := LI_adrAlarms + (LT_adrOffsetGroup * SIZEOF(LT_ptAlarms^)); LT_ptAlarmsText := LI_adrAlarmsText + (LT_adrOffsetGroup * SIZEOF(LT_ptAlarmsText^)); LT_ptAlarmsOld := LI_adrAlarmsOld + (LT_adrOffsetGroup * SIZEOF(LT_ptAlarmsOld^)); LT_ptAlarmsHold := LI_adrAlarmsHold + (LT_adrOffsetGroup * SIZEOF(LT_ptAlarmsHold^)); LT_ptAlarmsAck := LI_adrAlarmsAck + (LT_adrOffsetGroup * SIZEOF(LT_ptAlarmsAck^)); LQ_bNewAlarm:= FALSE; LQ_bAlarmActive := FALSE; LQ_bAlarmGone := FALSE; FOR LT_iCounterAlarmsElements := 1 TO LT_iNumberOfAlarmGroupElements DO // Scan all data of group // Check for new alarms IF LT_ptAlarms^ AND NOT LT_ptAlarmsOld^ THEN LQ_bNewAlarm:= TRUE; END_IF // Reset current alarms IF LI_bReset AND LT_ptAlarmsAck^ AND NOT LT_ptAlarms^ THEN LT_ptAlarms^ := FALSE; ELSE LT_ptAlarms^ := LT_ptAlarms^ OR LT_ptAlarmsOld^; (* keep alarms true *) END_IF // Hold new alarms IF fbTofNewAlarm.Q = TRUE THEN LT_ptAlarmsHold^ := LT_ptAlarms^ OR LT_ptAlarmsHold^; ELSE LT_ptAlarmsHold^ := LT_ptAlarms^; END_IF // Acknowlegde current alarms IF LI_bAckAll THEN LT_ptAlarmsAck^ := LT_ptAlarms^; END_IF // check if alarm is gone IF NOT LT_ptAlarms^ AND LT_ptAlarmsOld^ THEN LQ_bAlarmGone := TRUE; END_IF // Alarms active IF LT_ptAlarms^ THEN LQ_bAlarmActive:= TRUE; END_IF // Save old value LT_ptAlarmsOld^ := LT_ptAlarms^; // Next element LT_ptAlarms := LT_ptAlarms + SIZEOF(LT_ptAlarms^); // Pointer to next element LT_ptAlarmsText := LT_ptAlarmsText + SIZEOF(LT_ptAlarmsText^); // Pointer to next element LT_ptAlarmsOld := LT_ptAlarmsOld + SIZEOF(LT_ptAlarmsOld^); // Pointer to next element LT_ptAlarmsHold := LT_ptAlarmsHold + SIZEOF(LT_ptAlarmsHold^); // Pointer to next element LT_ptAlarmsAck := LT_ptAlarmsAck + SIZEOF(LT_ptAlarmsAck^); // Pointer to next element END_FOR fbTofNewAlarm(in:= LQ_bNewAlarm, PT:= REAL_TO_TIME(LI_rHoldTimeNewAlarms), Q=> , ET=> ); 

I already tried to add a conversion UDINT_TOPBOOL, UDINT_TODWORD (because of standard pointer datatype) but this did not work.

1

1 Answer

I strongly suspect you have been using a 32-bit version of CODESYS for all these years, and are now moving to a 64-bit Beckhoff PLC.

If so, your problem is not caused by moving from CODESYS to TwinCAT, but moving from 32 bits to 64 bits. Try it for yourself : go back to CODESYS, and choose any 64-bit runtime. You will get the same error as in TwinCAT when you compile.

  • You probably should not use DWORD variables to pass addresses around. Use "POINTER TO". Better yet, use "REFERENCE TO". This will compile and work across different CPU architectures.

  • You seem to be calculating the addresses of many variables that are found in a single structure using offsets, rather than having one single pointer (or reference) to the structure and using "." to access its fields. I have not fully analyzed your code, but it seems to me it would greatly simplify it as you would get rid of all pointer calculations and offload this work to the compiler.

3

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like