Posted 4 Aug 2020 Hi all i've been trying to make a simple timer in structured text which is turned on and off by a single input, all instances of flip flops i have found seem to be 2 input. any help or examples would be appreciated example of programs; Pulse signal received, start timer Pulse signal received stop timer Share this post Link to post Share on other sites
Posted 4 Aug 2020 What happens when the timer times out? A simple flip flop to toggle a bit in ST pulse:=input AND NOT temp temp:=input IF pulse THEN output:= NOT output; END_IF Share this post Link to post Share on other sites
Posted 4 Aug 2020 ah great, at the end of the timer it it subtracts from the total time to display time it takes for a cycle Share this post Link to post Share on other sites
Posted 5 Aug 2020 (edited) does this look right? im gonna go test with it now but i find it really hard to monitor ST and see the problem head_go_pls = input pulse timer_start = start timer timer_snap = move the current time so that its stored pulse:= Head_go_pls AND NOT flip_flop_bit; flip_flop_bit:= Head_go_pls; IF pulse THEN Timer_snap:= Cycle_timer.PV; Timer_start:= NOT Timer_start; END_IF; TIMHX(Timer_start, Cycle_timer,500); Cycle_time_bin:= (500-Timer_snap); Cycle_time_real:= one_minute/Cycle_time_bin; Cans_per_min:= Cycle_time_real*Index_amount; Edited 5 Aug 2020 by Bobodopalus Share this post Link to post Share on other sites
Posted 5 Aug 2020 hmm i think ive made an error there in stopping the timer, not sure of the best solution Share this post Link to post Share on other sites
Posted 5 Aug 2020 Do you want the cycle time between every input pulse or every second input pulse? Starting and stopping the timer using a flip flop will only be able to capture every second pulse. Share this post Link to post Share on other sites
Posted 5 Aug 2020 every second pulse is fine, our machines complete a cycle in around 2 seconds, we only need to know roughly how fast its operating and it doesnt need immediate updates Share this post Link to post Share on other sites
Posted 5 Aug 2020 Cycle time between pulses in seconds. Timer_SP:= 2000; (* Timer setpoint *) pulse:= input AND NOT oneshot; (*generate pulse on rising edge of input*) oneshot:=input; IF pulse THEN IF Timer_Start AND NOT timer1.CF THEN (*Calculate cycle time only if timer has not timed out*) inst_cycle_time_sec:= UINT_TO_REAL(Timer_SP-timer1.PV)/100.0; (*instantaneous cycle time in seconds*) END_IF; Timer_Start:= NOT Timer_Start; (* toggle timer every pulse*) END_IF; TIMHX(Timer_Start,timer1,Timer_SP); Share this post Link to post Share on other sites
Posted 5 Aug 2020 If you want every cycle you can change the code to this: Timer_SP:= 200; (* Timer setpoint *) TIMHX(TRUE,timer1,Timer_SP); pulse:= input AND NOT oneshot; (*generate pulse on rising edge of input*) oneshot:=input; IF pulse THEN IF NOT timer1.CF THEN (*Calculate cycle time only if timer has not timed out*) inst_cycle_time_sec:= UINT_TO_REAL(Timer_SP-timer1.PV)/100.0; (*instantaneous cycle time in seconds*) ELSE inst_cycle_time_sec:=0.0; END_IF; timer1.PV:= Timer_SP; END_IF; Share this post Link to post Share on other sites
Posted 6 Aug 2020 thanks alot, i'll have a go with this a bit later Share this post Link to post Share on other sites
Posted 15 Sep 2020 i've just tried this and had some errors Share this post Link to post Share on other sites
Posted 15 Sep 2020 (edited) im having issues with the site today. here are the errors im having timer 1 being timer type is incorrect? invalid instruction i have no idea what this refers to (i cant seem to upload or add a link for the screenshot) Edited 15 Sep 2020 by Bobodopalus Share this post Link to post Share on other sites
Posted 15 Sep 2020 the site was down, maybe not everything is working as it should. i noticed the same issue. detecting edge is basically the same regardless of programming language. you create another variable of same type and create copy input is a boolean so any other boolean would be fine to keep copy of the value then we use the fact that copy is always slightly delayed. if we compare copy with original before value is saved to a copy, we can detect change... for boolean signal that would be either rising or falling edge. key is that copy need to be retained... so pseudo code to detect rising edge is: ; first do a comparison... IF (X0==TRUE) AND (M0==FALSE) THEN ; rising edge detected ENDIF ; then update copy to be like original M0 = X0 pseudo code to detect falling edge is: ; first do a comparison... IF (X0==FALSE) AND (M0==TRUE) THEN ; falling edge detected ENDIF ; then update copy to be like original M0 = X0 pseudo code to detect both edges is: ; first do a comparison... IF X0<>M0 THEN ; some edge is detected ENDIF ; then update copy to be like original M0 = X0 you can use one of the edges (either rising or falling) to toggle some other bit (internal memory or an output) ; first do a comparison... IF (X0==TRUE) AND (M0==FALSE) THEN Y0 = NOT Y0 ; toggle output ENDIF ; then update copy to be like original M0 = X0 that other bit can be used to enable timer... Share this post Link to post Share on other sites
Posted 21 Sep 2020 (edited) sorry this is where my knowledge of plc's really falls apart, in the comment above what does M0 and X0 actually refer to? i really only know the basics of plc's finished uni with very little knowledge and have picked up everything i know since starting this job near the start of the year largely from this website. and i assume chelton's example should work? im trying Timer_SP:= 200; (* Timer setpoint *) TIMHX(TRUE,timer1,Timer_SP); pulse:= input AND NOT oneshot; (*generate pulse on rising edge of input*) oneshot:=input; IF pulse THEN IF NOT timer1.CF THEN (*Calculate cycle time only if timer has not timed out*) inst_cycle_time_sec:= UINT_TO_REAL(Timer_SP-timer1.PV)/100.0; (*instantaneous cycle time in seconds*) ELSE inst_cycle_time_sec:=0.0; END_IF; timer1.PV:= Timer_SP; END_IF; internals: pulse = bool oneshot = bool timer = timer timer_sp = uint inst cycle time sec = real but when i compile i get ERROR: Symbol 'timer1' is the invalid data type(TIMER or COUNTER) in the SFC/ST program. ERROR: Invalid Instruction whats causing these errors? thanks for all the help both of you also i see images are still not uploadable :( Edited 21 Sep 2020 by Bobodopalus Share this post Link to post Share on other sites
Posted 21 Sep 2020 timer1 = timer not timer = timer sorry about the formatting. Share this post Link to post Share on other sites
Posted 21 Sep 2020 sorry it is timer1 = timer, i typo'd, can you email it to me if you have made it? or i can send you what i've made if you pm me your email. really missing being able to upload images Share this post Link to post Share on other sites
Posted 21 Sep 2020 X0 is some boolean variable such as PLC input. this can be read only variable (such as PLC input) M0 is another boolean variable that stores last known value of of X0. this need to be a global or at least static variable so it can retain value even after instruction pointer is no longer in the subprogram where the one-shot logic is. this variable needs both read and write access. it you look at M0 over time, it is the same thing like X... just slightly delayed (in case of PLC, that would be one scan or whatever interval is used to execute mentioned code). Y0 is another boolean variable, much like M0 and if needed it could be a PLC output too. this is all pretty much the same as posted by chelton. if yo ulook closer you will see that: X0 = "input" M0 = "pulse" Share this post Link to post Share on other sites
Posted 22 Sep 2020 (edited) realised my mistake, the error was caused by me putting the FB onto a test plc i have which is cp1l and not cj2m, cp1l does not use timer type in FB. so now its working but it seems to be quite inaccurate, but it does seems to be scaled so this can probable be fixed with maths. im using a TIM block to trigger this now with #40 on the input, the block is activating correctly but for #40 im getting a result of 6 seconds, and for #10 i was getting a result of 1.5 so it seems to be 50% out, im not sure why this is the case. yes after some testing it does seems to be 50% out, i changed the dividing value to 1500 from 1000 and now its accurate, whats causing this difference though? Edited 22 Sep 2020 by Bobodopalus added testing Share this post Link to post Share on other sites
Posted 22 Sep 2020 (edited) anyway for this to work on a cp1l? i am very happy with the program though, thank you very much. i work with CJ2M around 80% of the time and CP1L the rest of the time, im fine with doing the CP1L version differently if needed Edited 22 Sep 2020 by Bobodopalus Share this post Link to post Share on other sites
Posted 22 Sep 2020 i found a work around for timers here posted by roze on this forum, still cant link sadly but that will only work for timers completing i think Share this post Link to post Share on other sites