Using the debounce switch component macro - Flow:3

For Flowcode users to discuss projects, flowcharts, and any other issues related to Flowcode 2 and 3.

Moderators: Benj, Mods

Post Reply
canipus
Posts: 31
Joined: Sun Nov 12, 2006 7:33 am
Contact:

Using the debounce switch component macro - Flow:3

Post by canipus »

Can anyone PLEASE give (or point me to), a quick tutorial illustrating the use of the component macro to debounce a switch on an input port?
Currently I have a triangle decision box that is quizzing a variable that is an input port pin true or false (Y or N). Effectively the decision box is testing the switch on the input which is either in a high or low state. I want to debounce the switch by adding the switch component macro.
The question is, where does the macro box go on the flowchart? Immediately after the decision triangle in the Y branch? ...or does the macro box somehow replace the decision box, meaning I should be using the macro in place of the decision box?

PS Flowcode is a great product but just wish there were more basic tutorial examples for novices.

TIA

Canipus

User avatar
Steve
Matrix Staff
Posts: 3427
Joined: Tue Jan 03, 2006 3:59 pm
Has thanked: 114 times
Been thanked: 422 times
Contact:

Post by Steve »

Using the new Switch component with v3, you can use the macros "WaitUntilHigh" and "WaitUntilLow" to wait for a particular switch to be pressed/released. In the Switch component properties you will find an option to add a debounce to these functions.

There are a series of tutorial programs that get installed when you install Flowcode - these are in the "Examples" subfolder of Flowcode V3. I know these are not ideal, and we have talked about releaseing a proper course for Flowcode. This may yet happen.

canipus
Posts: 31
Joined: Sun Nov 12, 2006 7:33 am
Contact:

Post by canipus »

steve wrote:Using the new Switch component with v3, you can use the macros "WaitUntilHigh" and "WaitUntilLow" to wait for a particular switch to be pressed/released. In the Switch component properties you will find an option to add a debounce to these functions.

There are a series of tutorial programs that get installed when you install Flowcode - these are in the "Examples" subfolder of Flowcode V3. I know these are not ideal, and we have talked about releaseing a proper course for Flowcode. This may yet happen.
Steve,

At the risk of appearing dense, my question is how do you use them? Are you saying that the program flow reaches the macro and then stops and waits for the key press or is the "wait" referring to the debounce time wait period set in the new switch options?
I assume it must be the latter, but then I don't understand how you split the program flow into the key is not pressed direction or the key has been pressed direction. With the decision box that was easy to do so my original question remains, can you combine the macro with the decision box and if so where does the macro go in relation to the decision box?

thanks for the response

Canipus

User avatar
goldwingers
Posts: 118
Joined: Wed Sep 06, 2006 1:22 pm
Location: London
Been thanked: 1 time
Contact:

Maybe this will help

Post by goldwingers »

If you have an input component, in your program, if you click on the switch properties box you can set your delay there.

If you use the macro, this halts the programme until a switch is pressed.. hope this helps you out

Any delay you put on a switch should be directly after the input block and before the decision box

Ian

canipus
Posts: 31
Joined: Sun Nov 12, 2006 7:33 am
Contact:

Re: Maybe this will help

Post by canipus »

goldwingers wrote:If you have an input component, in your program, if you click on the switch properties box you can set your delay there.

If you use the macro, this halts the programme until a switch is pressed.. hope this helps you out

Any delay you put on a switch should be directly after the input block and before the decision box

Ian
Ohh! so the macro does halt the program? Then it's not the function I'm looking for. Your later suggestion is on the lines of what I am currently doing. I have my input box component set up followed by my decision box and then after my decision box I have inserted a delay box. On some of my important switches I have also put the delay box into an elaborate loop that circles round to the front of the decision box, to recheck the switch state after the delay (after the contact bounce should have finished). It is all working - at least on simulation - BUT if I follow what you're suggesting, I can simply set the delay in the switch properties and not bother with my delay box? I wasn't sure if the delay in the switch properties was only applicable if it was accompanied by the use of the switch macros. Hence my confusion. So the delay in the switch properties can be set and gets compiled with my input and decision box and I don't need to worry about the macros (unless I want to halt the program while it waits for a change in the switch condition - which is not what I want to do).
OK this make a lot more sense now. I guess I'm now wondering exactly how the switch properties delay setting works on the code. Does it add an auto loop based delay and recheck the switch input function, or is it just a simply humble in line delay to save adding the delay component box manually?

Thanks for the feedback.

User avatar
Steve
Matrix Staff
Posts: 3427
Joined: Tue Jan 03, 2006 3:59 pm
Has thanked: 114 times
Been thanked: 422 times
Contact:

Post by Steve »

The debounce delay in the switch component properties only works for the "WaitUntilHigh" and "WaitUntilLow" macros.

One thing you may be able to do is read the switch input as normal and then if it is pressed (i.e. after the decision icon that checks if it has been pressed) add a "WaitUntilLow" macro - this will provide the debouncing.

I will look into allowing proper debouncing of inputs for a future release. Does anyone have any ideas on this? E.g. should it be done via the switch component macros or should it be accessible in the "input" icon itself?

Mark
Posts: 209
Joined: Thu Oct 19, 2006 11:46 am
Location: Bakewell, UK
Has thanked: 20 times
Been thanked: 16 times
Contact:

Post by Mark »

Steve,

I would suggest the debounce is integrated into the input icon. This is on the basis that like the old thermometer ADC component, the input may well be used for other purposes where an assesment of signal stablity is required.

However, the keypad component could usefully have its own in-built debounce as a seperate feature.

As a general comment related to this series of posts, the forum seems to get a lot of questions of the 'what exactly does this feature do?' type. My preference will be that, when you find the time, to release a formal manual spelling out in a terse way (bullet points?) what flowcode features and their options actually do, rather than adding to the excellent (in their own way) classroom type tutorials approach.

Thanks
Go with the Flow.

User avatar
Steve
Matrix Staff
Posts: 3427
Joined: Tue Jan 03, 2006 3:59 pm
Has thanked: 114 times
Been thanked: 422 times
Contact:

Post by Steve »

Thanks for the suggestions, Mark.
As a general comment related to this series of posts, the forum seems to get a lot of questions of the 'what exactly does this feature do?' type. My preference will be that, when you find the time, to release a formal manual spelling out in a terse way (bullet points?) what flowcode features and their options actually do, rather than adding to the excellent (in their own way) classroom type tutorials approach.
Another good suggestion. The only problem being the words "when you find the time"!!

canipus
Posts: 31
Joined: Sun Nov 12, 2006 7:33 am
Contact:

Post by canipus »

steve wrote: One thing you may be able to do is read the switch input as normal and then if it is pressed (i.e. after the decision icon that checks if it has been pressed) add a "WaitUntilLow" macro - this will provide the debouncing.
Hmmm. Not sure about that. If you examine the nature of a mechanical contact bounce the switch will open and shut many times during a period of 30ms but sometimes up to 100ms in poor cases. The problem is with most simple debounce delays implemented in software is that they take no account of the fact that the debounce gets worse, the time period increases, as the switch ages in use. A simple brute force delay of 30ms may work for the first few years of the product, but if the swicth is used heavily, after 3 years the contact bounce may exceed the 30ms delay set within the software.

I agree with the previous post that such a function should be built into the INPUT block, but I would also add that unless Matrix Multimedia were willing to produce a new, separate input block with a proper input sampling function macro to accomplish the debounce function, then it would be completely useless and a total waste of your time. You would be giving users nothing that they can't already do for themselves.

The contact bounce "problem" is one of the most underated, most misunderstood (even by senior software developers of numerous years experience), that I have come across. Having spent over 30 years in electronics analog and digital design for the semiconductor industry I have yet to meet a software developer that incorporates even a half reasonable algorithm for dealing with this issue in embedded software design. Frankly the level of education on this topic is appalling, and in many cases we have a world full of embedded software with a built in failure mechanism just waiting to happen - and when the glitch occurrs then it's passed off as an irritating bug somehwere else in the system.

The facts are simple. Many developers are solving the problem with the so called "brute force delay" mechanism. Unfortunately there is no such guarantee that the amount of brute force applied within the design is ever enough to conquer the problem. In short, the problem is NOT static its dynamic. Contact bounce is a variable and WILL get worse as the switch ages (REGARDLESS OF THE COST OF THE SWITCH). So the question then becomes, how much delay are you going to insert in your software flow based on the fact that the delay required is dynamically shifting? And that is the root of the problem!

If you're going to give us a really nice Macro that is at least half useful, then you MUST make the algorithm sampling and loop based with the input being examined over a specific number of samples and a clock or variable that is incremented to control the number of loops. In addition, should the sample mechanism fail during one of the loop passes (because the bounce occurs and changes the logic state), then you need to reset the variable to start the sample periods again (or at least reduce the variable value to cause the sample process to be extended in time). When, and only when, the input logic condition is static for the complete period of THE ENTIRE COMBINED samples (the cumulative sample window), can you assume with some measure of certainty, (but still no absolute guarantee), that the contacts have finished bouncing and the program can continue to execute the next stage.

I really hope you do this because apart from the value it brings to the product it would be a smack in the eye for all the other IDEs on the market, (Delphi, PIC Basic, Proton Basic, Visual xxx, ANSI C), that claim to offer this function as part of the compiler process, but in reality are nothing more than half hearted attempts to solve the issue.

The fact that companies like MAXIM are happily selling debouncer silicon to sit in front of the ports on RISC processors is testament to the fact that no one has really come up with a perfect software solution - at least not one that is being offered in the public domain that is simple to incorporate as a TRANSPARENT "plug-in" software solution.

Just my 2 c for what it's worth.

Canip

User avatar
Steve
Matrix Staff
Posts: 3427
Joined: Tue Jan 03, 2006 3:59 pm
Has thanked: 114 times
Been thanked: 422 times
Contact:

Post by Steve »

Canipus:

Thanks for the info in your post (but the way, you've just won the longest post competition by a country mile :) ). When I revisit the debounce problem, I will bear what you've said in mind and look into it more carefully.

What I think I will do is add to the Decision icon (and maybe to the Loop icon as well) the facility to check a particular input pin state and add the debouncing there - e.g. "if [B2 is high]". This has the added benefit that a variable does not need to be used when reacting to digital inputs.

Although I may have a misunderstanding regarding debouncing:

I presume switch bounce happens when the switch is changing state (i.e. being pressed or released). When you are reading an input, you are not reading a change in state; instead, you are reading a logic level at that particular time.

Thus when you use the input icon followed by a decision, the decision is not based on a change in input state - the decision is based on the input level.

This is why I put a debounce option into the "WaitUntilHigh" and "WaitUntilLow" macros only.

Anyone have thoughts on this?

canipus
Posts: 31
Joined: Sun Nov 12, 2006 7:33 am
Contact:

Post by canipus »

steve wrote:Canipus:


I presume switch bounce happens when the switch is changing state (i.e. being pressed or released). When you are reading an input, you are not reading a change in state; instead, you are reading a logic level at that particular time.

Thus when you use the input icon followed by a decision, the decision is not based on a change in input state - the decision is based on the input level.

This is why I put a debounce option into the "WaitUntilHigh" and "WaitUntilLow" macros only.

Anyone have thoughts on this?
Yes that is correct, but there is a flaw based on your assumption of the way embedded programming based on emulating hardware logic design works.
Let's take an example of logic flow at a purely systems level to illustrate the fallacy.
We have 3 or more sequential synchronised logic blocks, but to keep things simple lets keep it to 3 and let's call them functional blocks A, B and C and let the first block A be the inputting and measurement of a switch on a port.
Let us decide that the initiation and processing of block B depends on A and let's also make the initiation and function of C dependent on B so we have a serial logic functional chain. In this case, all we need to do is initiate the chain sequence to register a level transition at the input to A, and it really doesn't matter what the input on A is doing after the first transition has been registered because the chain of serial processing has been triggered and the input to A is no longer responsible for the sequence. In reality the logic has been passed on down to B and then onto C. In this scenario it really doesn't matter whether we debounce the switch on A or not. The first transition has been registered and the system logic carries on down the line.

BUT:- what if logic C doesn't depend on B to start doing it's thing? Supposing C also depends on the input on A as part of it's processing. In other words, A has said to B, "OK we have a transition off you go" and then B says to C "OK, wake up and start doing your thing on the input of A - everything is OK and input to A is at logic X and stable".
Well unfortunately, B has just lied to C. Everything isn't alright on the input to logic A because the damned level is still bouncing up and down like a see-saw and C is not going to know what the hell do do with it (without building in some safety factor into C to cope with it).

What we are effectively dealing with in our design is where something has been triggered that then tells some logic further on to look at the very thing that has done the triggering. For this to be functionally accurate, the "thing" that created the first trigger response MUST be 100% stable at the point of triggering so that when C looks back at it, there is no possible confusion about the input condition.

To reiterate, the criterion for switch debouncing is NOT so the logic immediately after the switch has a clear understanding, but because something else later in the system that will become "functional" due to A, is also dependent on the condition on A being the SAME as when A got triggered. Unfortunately, there is no way to cater for this UNLESS you make the judgement call to only work on inputs where the logic conditions are static for within pre-determined time windows dictated by the functional needs of what the program is attempting to accomplish. Hence the need to debounce the input in a way that says to the program "the input is now at a constant logic level, do what ever you want, all further processing will be valid for this particular time slot we are working in."

I hope this makes sense. Your logic is true, only, if all events subsequent to A are no longer dependent on what the input to A is doing.

I trust this explanation serves to illustrate the problem a little better.

Unfortunately, I cannot claim to be able to provide you with the perfect algorithm - my expertise is hardware not software - but I do know and recognise that good debouncing solutions with a software algorithm are hard to come across. If you use hardware to solve the problem, the solution is a piece of cake; the most effection solution being a cross-coupled nand gate that acts as a latch/unlatch function. Surprisingly few engineers working on embedded systems are aware of this very simple elegant solution, and those that are aware, believe they can emulate a solution in software such as using a digital delay to take the place of an analog RC time-constant placed on the switch network.

However, if you do a web search on something like "switch debouncing" or "PIC debouncing" you will find some very good articles and application notes on the subject that will add more information to a very thorny subject.

Apologies for probably the second most log post. :wink:

User avatar
Steve
Matrix Staff
Posts: 3427
Joined: Tue Jan 03, 2006 3:59 pm
Has thanked: 114 times
Been thanked: 422 times
Contact:

Post by Steve »

How about this:

Add an option so that when reading an input, the program wait until the signal is stable. Let's say this is done using a call to "ReadState" macro of the switch component. With the debouncing option enabled, this call will wait until the signal has been stable for a certain time before returning a valid value of the input.

Would this approach be ok? And what would be an appropriate value for the "certain time"?

The only problem with this is that the signal could be oscillating anyway (i.e. it's connected to an astable rather than a switch), which may cause the program to lock at this point.

Should there be a timeout (500ms?) to avoid this lock-up?

canipus
Posts: 31
Joined: Sun Nov 12, 2006 7:33 am
Contact:

Post by canipus »

steve wrote:How about this:

Add an option so that when reading an input, the program wait until the signal is stable. Let's say this is done using a call to "ReadState" macro of the switch component. With the debouncing option enabled, this call will wait until the signal has been stable for a certain time before returning a valid value of the input.

Would this approach be ok? And what would be an appropriate value for the "certain time"?

The only problem with this is that the signal could be oscillating anyway (i.e. it's connected to an astable rather than a switch), which may cause the program to lock at this point.

Should there be a timeout (500ms?) to avoid this lock-up?
Steve,

Well that certainly works, functionally speaking, but is really another twist in the "brute force" methodology that we can implement already. It helps but apart from a little time saving I question the usefulness relative to a sampling based solution. The problem with any "brute force" delay solution is that one always has to guestimate the time delay - you even asked that very question above. A really valuabale sution is one that takes away some of the guesswork and a sampling/loop based approach does that.

Although I said I am no software expert regarding algorithms, I have been working on some Flowcode (on paper) for the last 24 hours and I think I have something of value that may be of interest, but obviously I want to put the sequence into Flowcode 3 and prove that it works before wasting your time. I'm right in the middle of sorting out my daughters laptop (spywhere etc.) before she returns to college this evening, but I will attempt to test my design over the weekend. If it works I will email you the file so you can look at it. It's certainly not something I would have to do manually everytime I have a switch that needs debouncing but if the entire thing could be put into 'special" macro block with it's own icon, then it would be a superb time saver. I say 'special" macro icon because currently a macro is a simple input output, with a line in at the top of the box and a line out at the bottom. What will be needed is a macro icon with a line in at the top and two lines out at the bottom because there is a branch at the end of the macro like the decision triangle. (1 valid output and 1 non valid output).
Let me work on it over the weekend and I'll get back to you next week.

With your C programming experience (I have zero experience on C), you may be able to make the entire thing more concise and elegant.

To answer your specific question about the delays, 30ms is a fairly common delay but I use 50ms as a more conservative approach. Unfortunately, there is NO utopian value for ALL switches. There are too many mechanical switching technologies on the market to come up with a single figure that fits all. Remember also what I wrote earlier about the dynamic nature of the bounce. It gets worse/longer as the switch ages. That makes it a real ..ugger to solve!
Nevertheless, the flowchart I've got on my scratchpad at the moment compensates for the dynamic nature of the bounce but at the penalty of adding extra delay steps when they may not be required. I'm pretty confident that the logic is correct I just need attempt to flowcode it on the PC.

With regard the comment on the input maybe oscillating and creating lockup I will need to think about that. That's a good thought. I must admit I have been looking at this in terms of digital logic rather than an oscillating analog signal, and I guess my first comment is could/would that sort of input not be handled by a proper A/D input - or perhaps more along the lines of setting up timer based interrupts? Not sure. Anyone else care to comment?
I'll keep you posted....

canipus

User avatar
goldwingers
Posts: 118
Joined: Wed Sep 06, 2006 1:22 pm
Location: London
Been thanked: 1 time
Contact:

Lost

Post by goldwingers »

I think that you should all look at the initial posting, me thinks your in a wind up Steve, I see the word "NOVICE" in there and now think this is an experienced programmer No offence Canipus but im a novice at flowcode and an electrical engineer So here is my theory on switch debounce;

Any metal which is put under strain as in a switch to maintain contact will flex when released, the contacts of the switch force the moving part to Bounce.... between the two positions. This happens quicker than the eye can see or for a lamp to light up hence we do not see it...... So when you have programs running at 20Mhz they do see it for the switch is passed quicker than the debounce time... has had time to stop. So to put it in Novice terms Can we just live with Debounce, however we get to overcome it.

Steve, I think if you put a time delay in the input icon that would maybe serve better as we can then drive normal switches with debounce or digital signals with no mentionable debounce. ie an external timer - What do you think ?

Guys this really has made interesting reading.

Ian

canipus
Posts: 31
Joined: Sun Nov 12, 2006 7:33 am
Contact:

Re: Lost

Post by canipus »

goldwingers wrote:I think that you should all look at the initial posting, me thinks your in a wind up Steve, I see the word "NOVICE" in there and now think this is an experienced programmer No offence Canipus
Ian
Ian

No offence taken, but for heavens sake

a) why on earth would I want to waste anybody's time pretending to be something I am not

b) what specifically in my post leads you to think I am an experienced programmer?

I wrote my first small program for a PIC micro precisely 4 weeks ago and it is the first program I have ever written. I have a very strong grounding in hi-speed CMOS design, digital conversion theory, logic design and most of all plain old analog (transistor and not ICs at that) plus RF. I have never needed to write any software because all my design was done with mathematics (my main degree) and pencil and paper. I only moved to using CAD and and simulation models 4 years ago ( probably 15 years after the rest of the world).

I really can't understand why you think I am winding Steve up or for that matter anyone else in this group. My participation here is simply because Flowcode is an excellent teaching tool, (I'm trying to teach myself - so far with a fair amount of success that I believe belongs to Flowcode and the vision of Matrix in producing the product), and besides if I was an experience programmer would I really be playing with flowcharts or just diving straight into C or even assembler?

regards, puzzled
canipus :?

User avatar
goldwingers
Posts: 118
Joined: Wed Sep 06, 2006 1:22 pm
Location: London
Been thanked: 1 time
Contact:

Post by goldwingers »

Canipus,
I refer you to your original posting on this subject and quote, "PS Flowcode is a great product but just wish there were more basic tutorial examples for novices." This led me to think that you were in fact a novice. Trying to help you with your problem, to which you replied also seemingly to me as a novice.

Just like me - I started on flowcode 1 - missed Ver 2 and went back for more in Ver 3. I dont write C,ASM, Basic, I rely on flowcode to get done what i need to.

Then all of a sudden your writing very interesting stuff about algorithms, and stuff, so please dont take any offence, to me it looked a little like a wind up.

Have fun learning Flowcode, I know i have thats all its about really.

User avatar
Steve
Matrix Staff
Posts: 3427
Joined: Tue Jan 03, 2006 3:59 pm
Has thanked: 114 times
Been thanked: 422 times
Contact:

Post by Steve »

canipus wrote: Although I said I am no software expert regarding algorithms, I have been working on some Flowcode (on paper) for the last 24 hours and I think I have something of value that may be of interest, but obviously I want to put the sequence into Flowcode 3 and prove that it works before wasting your time.
I've now received the file from Canipus - thank you very much for that.

It looks relatively simple, and I can look at implementing code similar to this in future.

GJB
Posts: 11
Joined: Tue Jan 09, 2007 9:37 pm
Contact:

Post by GJB »

Hey guys, I also wrote my first Pic code just 3 days ago, but I have been a radio comms engineer for 42 years. I really enjoyed reading through this particular item.

The bouncy switch question should also take into account the fact that most switches on micro system pass very little or no current.
Although a well designed switch or relay contact should
operate with a wiping motion to keep the contacts clean, when little or no current is being passed, then oxidisation sets in early and dirty oxidised contacts behave exactly like bouncy switches.

The input marco should distinguish between switches versus logic inputs. Logic inputs will not need de-bouncing, and any inbuilt delay will adversely effect the frequency performance of that input.

I would suggest having switch input and logic input macros.

If your designing a commercial product and don't wish it to fail frequently, then do use good quality switches, preferably gold plated. I would also be tempted in non battery applications to add pull ups on the ports (where switches pull down to ground) to make the switch pass a few milliamps. Don’t forget the RFI decoupling !

The first item I programmed using a keypad did suffer from bounce, but simply waiting for the port to return to 255 before moving on cured it. Now I note that interrupts will fire twice once on key down and again on key up, perhaps the second firing could be flaged as such and the port/pin masked for a short time ??

Cheers Joe

canipus
Posts: 31
Joined: Sun Nov 12, 2006 7:33 am
Contact:

Post by canipus »

GJB wrote: I would suggest having switch input and logic input macros.


The first item I programmed using a keypad did suffer from bounce, but simply waiting for the port to return to 255 before moving on cured it. Now I note that interrupts will fire twice once on key down and again on key up, perhaps the second firing could be flaged as such and the port/pin masked for a short time ??

Cheers Joe
Joe

Good inputs. I'm guessing the current switch input in Flowcode works more like a logic input so long as you don't set the bounce delay and use the switch macros. What is really needed is a second type of input for switches with a correct debounce utility built in.

I've not got as far as using interupts but I have been reading some of the PICBasic tutorial books and it looks like you can set the PIC interupt to work either on the positive or negative going edge of the signal. Not sure if you can do this in Flowcode as I haven't even looked at its interupt capability.

User avatar
Steve
Matrix Staff
Posts: 3427
Joined: Tue Jan 03, 2006 3:59 pm
Has thanked: 114 times
Been thanked: 422 times
Contact:

Post by Steve »

On the interrupt issue, there is an "INT" interrupt (typically on B0) and a "PORTB" interrupt.

The "INT" interrupt is fired when B0 performs a transition from low to high OR high to low.

The "PORTB" interrupt is fired when the high nibble of port B changes. So, this will fire when a button is pressed AND AGAIN when it is released.

daveb0360
Posts: 139
Joined: Mon Sep 21, 2009 10:17 am
Location: Leicester
Has thanked: 35 times
Been thanked: 12 times
Contact:

Re: Using the debounce switch component macro - Flow:3

Post by daveb0360 »

Hi All,
As a NOVICE programmer (but a time served electronics engineer), I would like an explanation as to the use of the 'waituntilhigh/low' statements. As I click the button to view (edit) the code for this macro. I notice that the end statement uses 'wdt' to enact the wait time.....at least, that's how I see it as a novice. However, my design, at the hardware level does not need to use the watchdog function within the chip so I have set it to 'disabled' in the config bits section.

Could this be why my 'real world' switch on the breadboard does not seem to perform debounce? In other words, to use the switch debounce function within the switch component, do I need to enable the internal watchdog function in the bit config and would this then have any undesired effect on the rest of the program? The switch (which, in the final design is not a switch, it's a trigger input) might sit all day without a trigger event so would some section of the chip be upset?

Cheers
Dave

Post Reply