Ladder Debounce

dalporto

Lifetime Supporting Member
Join Date
Jun 2021
Location
Montreal, QC
Posts
258
Hi all.

Is this the simplest way to debounce inputs in Ladder (there are 2 points being debounced here)?

The TOF drives the tag.

I'm expecting a lot of timers doing it this way because I have a lot of those to do.

Building an AOI would result in as much pain as this (tag for each AOI + intermediary tag to write into the AOI input).

Any suggestion on how to make it quicker / cleaner / better?


1713195528873.png
 
At first glance your solution appears to be overly complex. Can you expand on exactly what you are trying to accomplish?
In most cases, for debounce I only use one timer, so not sure we are on the same page in regards to "debounce".

I assume when the pressure is "good" the contact is closed, correct?
So I would have logic that says something like: If system is running and pressure is low for xxx milliseconds, then set alarm. (only one timer)
 
At first glance your solution appears to be overly complex. Can you expand on exactly what you are trying to accomplish?
In most cases, for debounce I only use one timer, so not sure we are on the same page in regards to "debounce".
Hi Ken.

Let say the wired input comes in and I want a 2 seconds confirmation before to pop the alarm. Then the input is not really stable for whatever reason.

Just with a TON I could have an alarm that is coming back many times, popping a "new" alarm each time it stays on for 2 seconds, even if it clears only for 250ms.

This is the reason for the TOF, to make sure that the alarm is really cleared; otherwise, the alarm is still present on the screen (or in the logic) and the operator does not get mad to see the same alarm cycle over and over until he shelves it.

So basically, I just want to make sure that the input is cleared and not just toggling on and off.

We use the term "debouncing" here but maybe it's a misnomer, we're a bunch of people who speak french.
 
Debounce is a common term for this in English too.

There is a canonical* pattern for debounce: see here; of course you will have to decide if that pattern meets your need.

I don't usually think of needing a debounce on the release, but it is included in that pattern and makes sense in the context you describe.

* i.e. known, standard
 
This is nearly equivalent, but uses only 1 timer; the debounced signal would be GRT .ACC 4999. Again you would need to determine if this fits your situation.

I don't know if this is more clear to you, but I generally find cascading timers unnecessarily opaque.

Untitled.png
 
Yeah, that's exactly what I'm talking about.

In my domain, they are not very fond of technology and they are relying mostly on the simplest things like mechanical pressure / level / temperature / Flow switches that are prone to have that kind of behavior when running on the edge of the setpoint, so I'm using debouncing like I would use an hysteresis on an analog input. I sometimes use them on analogs too.

If not, operators sitting in front of alarm pages 40 hrs a week gets mad when one is cycling on and off for no good reason,

In FBD I have a custom block that is quick to use:
1713200016361.png

In ladder, doing it, like a lot of things in LD, is very time-consuming. This is why I was looking at a better solution than what I posted here.
 
This is nearly equivalent, but uses only 1 timer; the debounced signal would be GRT .ACC 4999. Again you would need to determine if this fits your situation.

I don't know if this is more clear to you, but I generally find cascading timers unnecessarily opaque.

View attachment 69391
Yeah, I don't like the pile of parallel timers neither, it's taking a loot of room, it looks leaner your way.

I'm going to try it to see if it's quicker.

Thanks.
 
Yeah, I don't like the pile of parallel timers neither, it's taking a loot of room, it looks leaner your way.

I'm going to try it to see if it's quicker.

Thanks.
You can do array of ints and loop inputs there and use array as timers.

This is 16 bits example for loop.
 

Attachments

  • debounce_inputs_test.pdf
    237.6 KB · Views: 14
  • debounce_inputs_loop.jpg
    debounce_inputs_loop.jpg
    121.9 KB · Views: 16
Can you not create a Function Block or AOI
Here is one I use in Codesys.

FUNCTION_BLOCK DEBOUNCE

VAR_INPUT
IN: BOOL;
tON_DELAY: TIME;
tOFF_DELAY: TIME;
END_VAR

VAR_OUTPUT
Q: BOOL; //Output
END_VAR

VAR
ON_DELAY_TMR: TON; // Timer for On-Delay
OFF_DELAY_TMR: TON; // Timer for Off-Delay
END_VAR

_________________________

//ON AND OFF DELAY.

ON_DELAY_TMR(IN:=IN,PT:=tON_DELAY,); //RUN ON DELAY TIMER

OFF_DELAY_TMR (IN:= NOT IN, PT:=tOFF_DELAY,); //RUN OFF DELAY TIMER

Q:= NOT OFF_DELAY_TMR.Q AND (ON_DELAY_TMR.Q OR Q); //WILL NOT COME ON TILL ON DELAY IS DONE. WILL NOT GO OFF TILL OFF DELAY IS DONE.
 
Yeah, I wrote that a couple posts ago:

"Building an AOI would result in as much pain as this (tag for each AOI + intermediary tag to write into the AOI input)."

Since my dislike comes from creating useless tags for timers (at least with timers I can use arrays that kind of make sense), I'd just be moving my problem somewhere else.

I actually created the AOI wishfully thinking that I could use the EnableIn on the rung as the input. Oh God was I wrong.

So, unless someone knows better, from my understanding if I'd use an AOI:
  • Need to create an intermediary tag before to send it into the debounce block, or a reference that needs to make sense;
  • Need to create an instance of the AOI for each block (even if I probably could use an array, but given they are in different sections it quickly becomes messy);
  • Need to add a rung to send the intermediary tag into the AOI.
Right now I still prefer the TON / TOF scheme with a timer array.
 
I created an AOI for debounce.
Delays for ON (In_OnDebounceTime)
and output remains high until OFF timer expired (In_OffDebounceTime)


1713276969620.png
 
I created an AOI for debounce. [...]
I am pretty sure the In_Sensor XIC and XIO instructions on Rung 3 are redundant: the corresponding .DN values can only be 1 if the XIC/XIO instruction feeding the timer evaluates to True.

And the .TT XIO instructions on Rung 3 are probably also unnecessary:
  • When the I_SensorOnDelayTON.DN bit value is 1,
    • then the I_SensorOnDelayTON.TT bit value must be 0,
    • Also the I_SensorOffDealyTON.TT bit value will be 0 because the In_Sensor bit value will be 1
  • And vice versa for when I_SensorOffDelayTON bit value is 1.
I don't mean to be picky, but clarity is probably the most important aspect of PLC programming, and having unnecessary logic reduces clarity

Also using OTL and OTU for the output is worrisome:
  • if
    • the PLC leaves RUN mode (e.g. power failure) while
      • the In_Sensor is active (value is 1) .
      • and the press debounce has expired (I_SensorDelay.TON.DN value is 1)
  • Then when the PLC returns to RUN mode (e.g. power is restored),
    • the Out_SensorState will be 1.
It could be a Start/Stop Circuit pattern: XIC I_SensorOffDelay.DN is the Start condition; XIO I_SensorOffDelay.DN is the Stop condition; Out_SensorState is the Seal-in/Run bit.
 
Yeah, I wrote that a couple posts ago:

"Building an AOI would result in as much pain as this (tag for each AOI + intermediary tag to write into the AOI input)."

Since my dislike comes from creating useless tags for timers (at least with timers I can use arrays that kind of make sense), I'd just be moving my problem somewhere else.

I actually created the AOI wishfully thinking that I could use the EnableIn on the rung as the input. Oh God was I wrong.

So, unless someone knows better, from my understanding if I'd use an AOI:
  • Need to create an intermediary tag before to send it into the debounce block, or a reference that needs to make sense;
  • Need to create an instance of the AOI for each block (even if I probably could use an array, but given they are in different sections it quickly becomes messy);
  • Need to add a rung to send the intermediary tag into the AOI.
Right now I still prefer the TON / TOF scheme with a timer array.
I would Create a Debounce Function Block/AOI
Then Create a Struct similar to this:
TYPE DEBOUNCE_STRUCT :
STRUCT
DBN: DEBOUNCE;
OnDly: TIME;
OffDly: TIME;
END_STRUCT
END_TYPE

Then Create an array of how many of that same Struct you need and all the Tags are in one handy spot

1713282957093.png
 
Last edited:

Similar Topics

Hello, I´m having a problem trying to program in Ladder. An output should be trigged by two possible contacts. Take a look on the printscreen...
Replies
3
Views
55
I got my PanelView Plus 7 working with a Micrologix 1500. How would I connect my laptop to the PanelView to view the ladder logic while operating...
Replies
6
Views
170
please help me . I have to make this ladder diagram and I can’t figure it out :(
Replies
12
Views
366
Hello, I am trying to replicate a piece of logic on the PLC5 onto an SEL RTAC. I am using ladder on SEL and FBD. I am having issue on the ladder...
Replies
13
Views
248
I have a machine which is undergoing upgradation. As part of the process two SEW drives are being replaced., existing Gen B with new Gen C. The...
Replies
3
Views
209
Back
Top Bottom