Querying the fan state (generic)
This sample illustrates access to the fan speed data via the generic function block FB_MDP_ReadElement. It can be used to diagnose a fan failure (fan speed = 0).
A prerequisite is the presence of a fan. If no fan is available in the IPC, the IPC does not support the addressed module type, and the access attempt results in the error message 16#EC800002.
The contents of the FAN module are described in the Configuration Area of the IPC diagnostics. The generic function block FB_MDP_ReadElement is used for the access.
A description of the structure of this sample program can be found in the sample: Querying CPU data (generic).
Sample: access via the generic function block FB_MDP_ReadElement
Enumeration definition
//** = simply adjust these lines if modifying code for own purposes
// central definition of state machine states
// (supports easy program modification)
{attribute 'qualified_only'}
TYPE E_State :
(
Idle, // idle state
ReadFanSpeedInit, //** initiate reading fan speed
ReadFanSpeedProcess //** process reading fan speed
);
END_TYPE
PROGRAM MAIN
VAR
// internal use
sAmsNetId : STRING := ''; //** ADS Net ID (local = '')
eState : E_State; // Enum with index for state machine
bStart : BOOL := TRUE; // flag to trigger restart of statemachine
nData : UINT; // data storage for unsigned integer
stMDP_Addr : ST_MDP_Addr; // structure will include all address parameters
nModuleIndex : USINT := 0; //** Fan index (no. of fan)
// FB instances
fbReadMDPElement : FB_MDP_ReadElement; // instance of FB for reading MDP element
// results of execution
bError : BOOL; // error flag (indicator: error occured)
nErrID : UDINT; // last error ID
aFanSpeed : ARRAY[0..1] OF UINT; //** buffer for speed of fans
END_VAR
Program code
// For an easy re-use of the following code for own purposes, parts of this sample program use
// "general" data names (and copy the results in specific variables after processing the code).
// Remark: Error 16#EC800002 means module type not supported (IPC does not provide this type of information, e.g. does not have fans)
CASE eState OF
E_State.Idle:
IF bStart THEN
bStart := FALSE;
eState := E_State.ReadFanSpeedInit; //** initiate first state
END_IF
E_State.ReadFanSpeedInit: //**
stMDP_Addr.nArea := INT_TO_BYTE(eMDP_Area_ConfigArea); //** set area address to "Config Area"
stMDP_Addr.nTableId := 1; //** table ID in module for "Fan properties"
stMDP_Addr.nSubIdx := 1; //** subindex in table ID for "Fan speed"
fbReadMDPElement(
bExecute := TRUE, // Flag: trigger execution of FB
eModuleType := eMDP_ModT_Fan, //** desired module type = Fan
stMDP_Addr := stMDP_Addr, // MDP address structure. Dynamic module ID added internally.
iModIdx := nModuleIndex, //** instance of desired module type (0 = first instance)
pDstBuf := ADR(nData), // buffer for storing data
cbDstBufLen := SIZEOF(nData), // length of buffer
sAmsNetId := sAmsNetId, // AMS Net ID
); //** Note: fbReadMDPElement.tTimeOut must be > cycle time!
eState := E_State.ReadFanSpeedProcess;//** next state: process FB
E_State.ReadFanSpeedProcess: //** process FB: request fan data
fbReadMDPElement(bExecute := FALSE); // Flag: Get execution state of FB
//** Note: fbReadMDPElement.tTimeOut must be > cycle time!
IF NOT fbReadMDPElement.bBusy THEN // FB executed?
IF fbReadMDPElement.bError THEN // Error?
bError := TRUE; // set error flag
nErrID := fbReadMDPElement.nErrID; // store error id (16#ECA60105 = BIOS or HW does
// not support this data (here: mainboard data))
eState := E_State.Idle; // finish state machine
ELSE // set parameters for next steps
bError := FALSE; // turn off error flag
aFanSpeed[nModuleIndex] := nData; //** store fan speed in dedicated array
IF nModuleIndex = 0 THEN //** Current fan = fan 1?
nModuleIndex := 1; //** Read fan 2 (= second module instance) in next loop
ELSE //**
nModuleIndex := 0; //** Read fan 1 (= first module instance) in next loop
END_IF //**
eState := E_State.ReadFanSpeedInit; //** next state
END_IF
END_IF
END_CASE