FUNCTION_BLOCK "PSE_DIAG"
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : ICSLSSSC
FAMILY : SITOP
VERSION : 2.1
VAR_INPUT
IMPULSE : Bool;
COM_RST : Bool;
END_VAR
VAR_OUTPUT
DONE : Bool;
BUSY : Bool;
CHANNEL_STATE : Byte;
STATUS : Word;
ERROR : Bool;
END_VAR
VAR
tmp_STATUS : Word;
n_state : Int;
last_state : Int;
flag_state : Int;
pos_impulse : Bool;
neg_impulse : Bool;
com_rst_impulse : Bool;
IMPULSE_pos_old : Bool;
IMPULSE_neg_old : Bool;
COM_RST_old : Bool;
count_pos_impulse : Int;
count_neg_impulse : Int;
count_channel_impulse : Int;
count_channel_position : Int;
count_error : Int;
var_impulse : Bool;
startbit_detected : Bool;
channel1_active : Bool;
channel2_active : Bool;
channel3_active : Bool;
channel4_active : Bool;
evaluation : Bool;
duration : Bool;
STATE_START_IMPULSE : Bool;
STATE_IMPULSE : Bool;
frame_ok : Bool;
time_to_impulse_ok : Bool;
error_bit : Bool;
cycle_time_nok : Bool;
time_impulse_nok : Bool;
time_pause_nok : Bool;
time_1 {OriginalPartName := 'DTL'; LibVersion := '1.0'} : DTL;
time_pos {OriginalPartName := 'DTL'; LibVersion := '1.0'} : DTL;
time_neg {OriginalPartName := 'DTL'; LibVersion := '1.0'} : DTL;
time_impulse : Time;
time_pause : Time;
time_neg_start {OriginalPartName := 'DTL'; LibVersion := '1.0'} : DTL;
time_neg_start_old {OriginalPartName := 'DTL'; LibVersion := '1.0'} : DTL;
time_neg_impulse {OriginalPartName := 'DTL'; LibVersion := '1.0'} : DTL;
time_to_impulse : Time;
time_of_frame : Time;
time_2 {OriginalPartName := 'DTL'; LibVersion := '1.0'} : DTL;
time_sys {OriginalPartName := 'DTL'; LibVersion := '1.0'} : DTL;
time_sys_old {OriginalPartName := 'DTL'; LibVersion := '1.0'} : DTL;
time_zyklus : Time;
status_byte : Byte;
error_byte : Byte;
WATCH_DOG_TIME {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
CYCLE_TIME {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
WATCH_IN : Bool;
CYCLE_IN : Bool;
TIMER_SEND : Time;
TIMER_SEND2 : Time;
Time_Send : Time;
Time_Send2 : Time;
zaehler : Int;
zaehler2 : Int;
time_impulse_save0 : Time;
time_impulse_save1 : Time;
time_impulse_save2 : Time;
time_impulse_save3 : Time;
time_impulse_save4 : Time;
time_of_frame_save : Time;
time_nok : Bool;
IDLE : Int := 0;
read_clock : Int := 1;
STATE_ERROR : Int := 2;
CYCLE_TIME_ERROR : Int;
t_start_min : Time;
t_start_max : Time;
t_channel_min : Time;
t_channel_max : Time;
t_frame_min : Time;
t_frame_max : Time;
t_impulse_min1 : Time;
t_impulse_min2 : Time;
t_impulse_min3 : Time;
t_impulse_min4 : Time;
t_impulse_max1 : Time;
t_impulse_max2 : Time;
t_impulse_max3 : Time;
t_impulse_max4 : Time;
time_zyklus_save : Time;
Cache_Busy : Bool;
END_VAR
VAR_TEMP
tmp_time : Int;
tmp_time2 : Int;
END_VAR
BEGIN
//define constant variables
#IDLE:=0;
#read_clock:=1;
#STATE_ERROR:=2;
#CYCLE_TIME_ERROR:=3;
#t_start_min:=T#375ms;
#t_start_max:=T#625ms;
#t_channel_min:=T#138ms;
#t_channel_max:=T#363ms;
#t_frame_min:=T#2513ms;
#t_frame_max:=t#2988ms;
#t_impulse_min1:=t#376ms;
#t_impulse_min2:=t#852ms;
#t_impulse_min3:=t#1328ms;
#t_impulse_min4:=t#1804ms;
#t_impulse_max1:=t#626ms;
#t_impulse_max2:=t#1152ms;
#t_impulse_max3:=t#1678ms;
#t_impulse_max4:=t#2204ms;
#TIMER_SEND:=T#6s;
#TIMER_SEND2:=T#4s;
//begin
#ERROR:= false;
#time_nok:=false;
#var_impulse:=#IMPULSE; //read IMPULSE
//Zykluszeit berechnen
#tmp_time2:=RD_SYS_T(#time_2); //Systemzeit auslesen
#time_sys:=#time_2;
IF #time_sys > #time_sys_old THEN
#time_zyklus:=T_DIFF(IN1:=#time_sys, IN2:=#time_sys_old);
#cycle_time_nok:=false;
ELSE
#cycle_time_nok:=true;
#time_sys_old:=#time_sys;
RETURN;
END_IF;
//Überprüfung der Zykluszeit, wenn Zykluszeit > 100ms dann Fehler
IF #time_zyklus>T#102ms THEN
#CYCLE_IN:=true;
#cycle_time_nok:=true;
ELSE
#CYCLE_IN:=false;
#cycle_time_nok:=FALSE;
END_IF;
// pos. Flanke am Eingang COM_RST auswerten
IF #COM_RST AND #COM_RST<>#COM_RST_old THEN
#n_state:=#IDLE;
#com_rst_impulse:=true;
#WATCH_IN:=false;
#CYCLE_IN:=false;
END_IF;
#COM_RST_old:=#COM_RST;
//pos Flanke
IF #IMPULSE AND #IMPULSE<>#IMPULSE_pos_old THEN
#n_state:=#read_clock;
#flag_state:=15;
#pos_impulse:=true;
#count_pos_impulse:=#count_pos_impulse+1;
#WATCH_IN:=false;
IF #Cache_Busy=false THEN
#Cache_Busy:=true;
#ERROR:=false;
#DONE:=false;
#STATUS:=w#16#0000;
END_IF;
END_IF;
#IMPULSE_pos_old:=#IMPULSE;
//neg Flanke
IF NOT #IMPULSE AND #IMPULSE<>#IMPULSE_neg_old THEN
#n_state:=#read_clock;
#flag_state:=16;
#neg_impulse:=true;
#count_neg_impulse:=#count_neg_impulse+1;
IF #Cache_Busy=false THEN
#Cache_Busy:=true;
#ERROR:=false;
#DONE:=false;
#STATUS:=w#16#0000;
END_IF;
END_IF;
#IMPULSE_neg_old:=#IMPULSE;
//TIMER starten
IF #neg_impulse=false OR #pos_impulse=false THEN
#WATCH_IN:=true;
END_IF;
//Zustand "IDLE"
IF #n_state=#IDLE THEN
IF #com_rst_impulse=true THEN
#DONE:=false;
#ERROR:=false;
#Cache_Busy:=false;
#CHANNEL_STATE:=b#16#00;
#STATUS:=w#16#0000;
#count_channel_impulse:=0;
#count_channel_position:=0;
#neg_impulse:=false;
#pos_impulse:=false;
#com_rst_impulse:=false;
#startbit_detected:=false;
#error_bit:=false;
#cycle_time_nok:=false;
#time_impulse_nok:=false;
#time_pause_nok:=FALSE;
//#flag_state:=0;
#channel1_active:=true;
#channel2_active:=true;
#channel3_active:=true;
#channel4_active:=true;
#status_byte:=b#16#00;
#error_byte:=b#16#00;
#tmp_STATUS:=w#16#00;
#duration:=false;
#evaluation:=false;
#STATE_START_IMPULSE:=false;
#STATE_IMPULSE:=false;
#frame_ok:=false;
END_IF;
IF #last_state=#read_clock THEN
#error_bit:=false;
END_IF;
#last_state:=#IDLE; //IDLE als letzten Zustand speichern
//Zustand "Uhrzeit lesen"
ELSIF #n_state=#read_clock THEN
//Uhrzeit lesen bei neg. oder pos. Flanke
#tmp_time:=RD_SYS_T(#time_1); //Systemzeit lesen
//Zeit der pos. und neg. Flanke speichern
IF #flag_state=15 AND #pos_impulse=true THEN
#time_pos:=#time_1;
END_IF;
IF #flag_state=16 AND #neg_impulse=true THEN
#time_neg:=#time_1;
END_IF;
//Berechnung starten
IF #pos_impulse=true AND #neg_impulse=true THEN
#duration:=true;
ELSE
#n_state:=#IDLE;
END_IF;
//Berechnung der Impulse- und Pausenzeit
IF #duration=true THEN
IF #flag_state=16 THEN //wenn neg. Flanke erkannt, dann Zeit des Impulses berechnen
#time_impulse:=T_DIFF(IN1:=#time_neg, IN2:=#time_pos); //Zeitdifferenz berechnen
IF #time_impulse < t#0ms OR #time_impulse > #t_start_max THEN
#n_state:=#IDLE;
#last_state:=#read_clock;
#pos_impulse:=false;
RETURN;
END_IF;
#pos_impulse:=false;
END_IF;
IF #flag_state=15 THEN //wenn pos. Flanke erkannt, dann Zeit der Pause berechnen
#time_pause:=T_DIFF(IN1:=#time_pos, IN2:=#time_neg); //Zeitfifferenz berechnen
IF #time_pause < t#0ms OR #time_pause > #t_frame_max THEN
#n_state:=#IDLE;
#last_state:=#read_clock;
#neg_impulse:=false;
RETURN;
END_IF;
#neg_impulse:=false;
END_IF;
#duration:=false;
#evaluation:=true;
END_IF;
//Auswertung des Telegramms
IF #evaluation=true THEN
#evaluation:=false;
//Länge der Impulse speichern
IF #count_channel_impulse=0 THEN
#time_impulse_save0:=#time_impulse;
END_IF;
IF #count_channel_impulse=1 THEN
#time_impulse_save1:=#time_impulse;
END_IF;
IF #count_channel_impulse=2 THEN
#time_impulse_save2:=#time_impulse;
END_IF;
IF #count_channel_impulse=3 THEN
#time_impulse_save3:=#time_impulse;
END_IF;
IF #count_channel_impulse=4 THEN
#time_impulse_save4:=#time_impulse;
END_IF;
IF #count_channel_impulse>4 THEN
#zaehler:=#zaehler+1;
END_IF;
IF #time_impulse>#t_start_min AND #time_impulse<#t_start_max AND #flag_state=15 THEN
#STATE_START_IMPULSE:=true;
END_IF;
IF #time_impulse>#t_channel_min AND #time_impulse<#t_channel_max AND #startbit_detected=true AND #flag_state=15 THEN
#STATE_IMPULSE:=true;
END_IF;
IF #STATE_START_IMPULSE=true THEN
#startbit_detected:=true;
#count_channel_impulse:=0; //Testvariable
#count_channel_position:=0;
//Startimpulse merken
#time_neg_start_old:=#time_neg_start;
#time_neg_start:=#time_neg;
#time_of_frame:=T_DIFF(IN1:=#time_neg_start, IN2:=#time_neg_start_old);
IF #time_of_frame>#t_frame_min AND #time_of_frame<#t_frame_max AND #time_to_impulse<#t_frame_max THEN
#frame_ok:=true;
ELSE
#zaehler2:=#zaehler2+1;
#time_of_frame_save:=#time_of_frame;
#frame_ok:=false;
END_IF;
IF #time_pause>t#2s THEN
#channel1_active:=false;
#channel2_active:=false;
#channel3_active:=false;
#channel4_active:=false;
END_IF;
IF #frame_ok=true AND #error_bit=false AND #cycle_time_nok=FALSE THEN
#frame_ok:=false;
#DONE:=true;
#Cache_Busy:=false;
//Daten übernehmen
IF #channel1_active=true THEN
#status_byte.%X0:=true;
#error_byte.%X0:= false;
ELSE
#status_byte.%X0:=false;
#error_byte.%X0:= true;
END_IF;
IF #channel2_active=true THEN
#status_byte.%X1:=true;
#error_byte.%X1:= false;
ELSE
#status_byte.%X1:=false;
#error_byte.%X1:= true;
END_IF;
IF #channel3_active=true THEN
#status_byte.%X2:=true;
#error_byte.%X2:= false;
ELSE
#status_byte.%X2:=false;
#error_byte.%X2:= true;
END_IF;
IF #channel4_active=true THEN
#status_byte.%X3:=true;
#error_byte.%X3:= false;
ELSE
#status_byte.%X3:=false;
#error_byte.%X3:= true;
END_IF;
#CHANNEL_STATE:=#error_byte;
END_IF;
#STATE_START_IMPULSE:=false;
END_IF;
IF #STATE_IMPULSE=true THEN
#STATE_IMPULSE:=false;
//neg Flanke merken
#time_neg_impulse:=#time_neg;
#time_to_impulse:=T_DIFF(IN1:=#time_neg_impulse, IN2:=#time_neg_start);
IF #time_to_impulse < t#0ms OR #time_to_impulse > #t_frame_max THEN
#n_state:=#IDLE;
#last_state:=#read_clock;
RETURN;
END_IF;
#count_channel_impulse:=#count_channel_impulse+1;
IF #count_channel_position = 0 THEN
IF #time_to_impulse>#t_impulse_min1 AND #time_to_impulse<#t_impulse_max1 THEN
#channel1_active:=true;
#count_channel_position:=1;
ELSE
#channel1_active:=false;
END_IF;
IF #time_to_impulse>#t_impulse_min2 AND #time_to_impulse<#t_impulse_max2 THEN
#channel2_active:=true;
#count_channel_position:=2;
ELSE
#channel2_active:=false;
END_IF;
IF #time_to_impulse>#t_impulse_min3 AND #time_to_impulse<#t_impulse_max3 THEN
#channel3_active:=true;
#count_channel_position:=3;
ELSE
#channel3_active:=false;
END_IF;
IF #time_to_impulse>#t_impulse_min4 AND #time_to_impulse<#t_impulse_max4 THEN
#channel4_active:=true;
#count_channel_position:=0;
ELSE
#channel4_active:=false;
END_IF;
END_IF;
IF #count_channel_position=1 THEN
IF #time_to_impulse>#t_impulse_min2 AND #time_to_impulse<#t_impulse_max2 THEN
#channel2_active:=true;
#count_channel_position:=2;
ELSE
#channel2_active:=false;
END_IF;
IF #time_to_impulse>#t_impulse_min3 AND #time_to_impulse<#t_impulse_max3 THEN
#channel3_active:=true;
#count_channel_position:=3;
ELSE
#channel3_active:=false;
END_IF;
IF #time_to_impulse>#t_impulse_min4 AND #time_to_impulse<#t_impulse_max4 THEN
#channel4_active:=true;
#count_channel_position:=0;
ELSE
#channel4_active:=false;
END_IF;
END_IF;
IF #count_channel_position = 2 THEN
IF #time_to_impulse>#t_impulse_min3 AND #time_to_impulse<#t_impulse_max3 THEN
#channel3_active:=true;
#count_channel_position:=3;
ELSE
#channel3_active:=false;
END_IF;
IF #time_to_impulse>#t_impulse_min4 AND #time_to_impulse<#t_impulse_max4 THEN
#channel4_active:=true;
#count_channel_position:=0;
ELSE
#channel4_active:=false;
END_IF;
END_IF;
IF #count_channel_position = 3 THEN
IF #time_to_impulse>#t_impulse_min4 AND #time_to_impulse<#t_impulse_max4 THEN
#channel4_active:=true;
#count_channel_position:=0;
ELSE
#channel4_active:=false;
END_IF;
END_IF;
END_IF;
END_IF;
#n_state:=#IDLE;
#last_state:=#read_clock;
ELSIF #n_state=#STATE_ERROR THEN
#count_error:=#count_error+1; //Testvariable
#ERROR:=true;
#Cache_Busy:=false;
#DONE:=false;
#STATUS:=#tmp_STATUS;
#tmp_STATUS:=w#16#0000;
#WATCH_IN:=false;
#CYCLE_IN:=false;
#error_bit:=false;
#n_state:=#IDLE;
#last_state:=#STATE_ERROR;
END_IF;
#BUSY := #Cache_Busy;
//TIMER
#WATCH_DOG_TIME (IN:=#WATCH_IN,
PT:=#TIMER_SEND);
#Time_Send:=#WATCH_DOG_TIME.ET;
IF #WATCH_DOG_TIME.Q = True THEN
#n_state:=#STATE_ERROR;
#tmp_STATUS:=w#16#8002;
#error_bit:=true;
#com_rst_impulse:=true;
END_IF;
#CYCLE_TIME (IN:=#CYCLE_IN,
PT:=#TIMER_SEND2 );
#Time_Send2:=#CYCLE_TIME.ET;
IF #CYCLE_TIME.Q = true THEN
#n_state:=#STATE_ERROR;
#tmp_STATUS:=w#16#8001;
#error_bit:=true;
#com_rst_impulse:=true;
#time_zyklus_save:=#time_zyklus;
END_IF;
#time_sys_old:=#time_sys;
END_FUNCTION_BLOCK