// Siemens TIA Portal teaching reference: stateful motor function block
// Reviewed 2026-08-30. Adapt and verify syntax, timer type, optimized access,
// startup, retentivity and call behavior for the exact CPU, firmware and STEP 7 version.
// Standard control example only: not a safety function or commissioning authorization.

FUNCTION_BLOCK "FB_MotorEvidence"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 1.0
   VAR_INPUT
      Enable       : Bool;
      StartReq     : Bool;
      StopReq      : Bool;
      Permit       : Bool;
      RunFeedback  : Bool;
      ResetReq     : Bool;
      StartTimeout : Time := T#3s;
   END_VAR

   VAR_OUTPUT
      RunCommand : Bool;
      Ready      : Bool;
      Running    : Bool;
      Faulted    : Bool;
      State      : USInt;
      ErrorId    : UInt;
   END_VAR

   VAR
      StartOld      : Bool;
      ResetOld      : Bool;
      RequestLatched: Bool;
      StartTimer    : IEC_Timer;
   END_VAR

   VAR_TEMP
      StartEdge : Bool;
      ResetEdge : Bool;
   END_VAR

BEGIN
   // State convention: 0 disabled, 10 ready, 20 starting,
   // 30 running, 90 fault. Inputs are ordinary control signals.
   #StartEdge := #StartReq AND NOT #StartOld;
   #ResetEdge := #ResetReq AND NOT #ResetOld;
   #StartOld := #StartReq;
   #ResetOld := #ResetReq;

   // Stop, disable and lost permit dominate a start request.
   IF #StopReq OR NOT #Enable OR NOT #Permit OR #Faulted THEN
      #RequestLatched := FALSE;
   ELSIF #StartEdge THEN
      #RequestLatched := TRUE;
   END_IF;

   #RunCommand := #RequestLatched
                  AND #Enable
                  AND #Permit
                  AND NOT #Faulted;

   #StartTimer(IN := #RunCommand AND NOT #RunFeedback,
               PT := #StartTimeout);

   IF #StartTimer.Q THEN
      #Faulted := TRUE;
      #ErrorId := 16#0101;
      #RequestLatched := FALSE;
      #RunCommand := FALSE;
   END_IF;

   // Reset is accepted only while disabled, stopped, cause-free and feedback off.
   IF #ResetEdge AND NOT #Enable AND NOT #RunFeedback THEN
      #Faulted := FALSE;
      #ErrorId := 16#0000;
   END_IF;

   #Running := #RunCommand AND #RunFeedback AND NOT #Faulted;
   #Ready := #Enable AND #Permit AND NOT #Faulted AND NOT #Running;

   IF #Faulted THEN
      #State := 90;
   ELSIF NOT #Enable THEN
      #State := 0;
   ELSIF #Running THEN
      #State := 30;
   ELSIF #RunCommand THEN
      #State := 20;
   ELSE
      #State := 10;
   END_IF;
END_FUNCTION_BLOCK

// Example cyclic call after TIA Portal creates an instance DB named Motor_A_DB:
//
// "Motor_A_DB"(
//     Enable       := "Cmd".Enable,
//     StartReq     := "Cmd".Start,
//     StopReq      := "Cmd".Stop,
//     Permit       := "Status".Permit,
//     RunFeedback  := "Status".MotorRunning,
//     ResetReq     := "Cmd".Reset,
//     StartTimeout := T#3s,
//     RunCommand   => "Outputs".MotorRun,
//     Ready        => "Status".Ready,
//     Running      => "Status".Running,
//     Faulted      => "Status".Faulted,
//     State        => "Status".State,
//     ErrorId      => "Status".ErrorId
// );
