Files
Wolfgang Hottgenroth b2249c06e9
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
mdwiki test starts
2025-04-14 22:22:45 +02:00

255 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="en-us">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Yet Another Debouncing Method - Minimal Setups</title>
<meta name="generator" content="Hugo 0.140.2">
<link href="http://172.16.3.33:1313//index.xml" rel="alternate" type="application/rss+xml">
<link rel="canonical" href="http://172.16.3.33:1313/blog/debouncing/">
<link rel="stylesheet" href="http://172.16.3.33:1313/css/theme.min.css">
<link rel="stylesheet" href="http://172.16.3.33:1313/css/chroma.min.css">
<script defer src="http://172.16.3.33:1313//js/fontawesome6/all.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery.easing@1.4.1/jquery.easing.min.js" integrity="sha256-H3cjtrm/ztDeuhCN9I4yh4iN2Ybx/y1RM7rMmAesA0k=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js" integrity="sha256-4XodgW4TwIJuDtf+v6vDJ39FVxI0veC/kSCCmnFp7ck=" crossorigin="anonymous"></script>
<script src="http://172.16.3.33:1313/js/bundle.js"></script><style>
:root {}
</style>
<meta property="og:url" content="http://172.16.3.33:1313/blog/debouncing/">
<meta property="og:site_name" content="Minimal Setups">
<meta property="og:title" content="Yet Another Debouncing Method">
<meta property="og:description" content="You can find several approaches for debouncing mechanical switches on the Internet, some work better, some not so good.
One common approach is to ignore events in an ISR when they come too fast:&lt;
void count() { static uint32_t lastEvent = 0; uint32_t currentEvent = micros(); if (currentEvent &amp;gt; (lastEvent &#43; configBlock.debounce)) { lastEvent = currentEvent; cnt&#43;&#43;; } } void setup() { pinMode(REED_PIN, INPUT_PULLUP); attachInterrupt(REED_PIN, count, FALLING); } This works very good when only the tipping of a switch is relevant.">
<meta property="og:locale" content="en_us">
<meta property="og:type" content="article">
<meta property="article:section" content="blog">
<meta property="article:published_time" content="2018-04-30T00:00:00+00:00">
<meta property="article:modified_time" content="2018-04-30T00:00:00+00:00">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Yet Another Debouncing Method">
<meta name="twitter:description" content="You can find several approaches for debouncing mechanical switches on the Internet, some work better, some not so good.
One common approach is to ignore events in an ISR when they come too fast:&lt;
void count() { static uint32_t lastEvent = 0; uint32_t currentEvent = micros(); if (currentEvent &amp;gt; (lastEvent &#43; configBlock.debounce)) { lastEvent = currentEvent; cnt&#43;&#43;; } } void setup() { pinMode(REED_PIN, INPUT_PULLUP); attachInterrupt(REED_PIN, count, FALLING); } This works very good when only the tipping of a switch is relevant.">
<meta itemprop="name" content="Yet Another Debouncing Method">
<meta itemprop="description" content="You can find several approaches for debouncing mechanical switches on the Internet, some work better, some not so good.
One common approach is to ignore events in an ISR when they come too fast:&lt;
void count() { static uint32_t lastEvent = 0; uint32_t currentEvent = micros(); if (currentEvent &amp;gt; (lastEvent &#43; configBlock.debounce)) { lastEvent = currentEvent; cnt&#43;&#43;; } } void setup() { pinMode(REED_PIN, INPUT_PULLUP); attachInterrupt(REED_PIN, count, FALLING); } This works very good when only the tipping of a switch is relevant.">
<meta itemprop="datePublished" content="2018-04-30T00:00:00+00:00">
<meta itemprop="dateModified" content="2018-04-30T00:00:00+00:00">
<meta itemprop="wordCount" content="422"><script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">
</script>
</head>
<body>
<div class="container"><header>
<h1>Minimal Setups</h1>
</header>
<div class="global-menu">
<nav>
<ul>
<li class=""><a href="/keys/">Keys</a></li>
<li class=""><a href="/about/">About</a></li></ul>
</nav>
</div>
<div class="content-container">
<main><h1>Yet Another Debouncing Method</h1>
<time>Mon, Apr 30, 2018</time><p>You can find several approaches for debouncing mechanical switches on the Internet, some work better, some not so good.</p>
<p>One common approach is to ignore events in an ISR when they come too fast:&lt;</p>
<pre tabindex="0"><code>void count() {
static uint32_t lastEvent = 0;
uint32_t currentEvent = micros();
if (currentEvent &amp;gt; (lastEvent + configBlock.debounce)) {
lastEvent = currentEvent;
cnt++;
}
}
void setup() {
pinMode(REED_PIN, INPUT_PULLUP);
attachInterrupt(REED_PIN, count, FALLING);
}
</code></pre><p>This works very good when only the tipping of a switch is relevant.</p>
<p>When also the time the button was pressed is relevant and when it is especially necessary to distinguish between a short and a long press this approach doesn&rsquo;t work anymore.</p>
<p>Since I couldn&rsquo;t remember the approaches I read about earlier I&rsquo;ve sketched this state machine:</p>
<p><img src="/20180430110848869_0001.jpg" alt=""></p>
<p>(The double-lined states are action-states which send out the related information.)</p>
<p>At least for me, this approach is working very reliable so far, I&rsquo;m quite happy with it.</p>
<pre tabindex="0"><code>enum tPressedState { psHIGH, psLOW, psACCEPTED_LOW, psLONG_START, psLONG_CONT, psLONG_CONT_SEND, psLONG_END, psSHORT, psINVALID };
typedef struct {
uint8_t index;
uint8_t buttonPin;
tPressedState pressedState;
tPressedState oldPressedState;
uint32_t lastStateChange;
} tButton;
tButton buttons[] = {
{ 1, SWITCH_1, psHIGH, psINVALID, 0 },
{ 2, SWITCH_2, psHIGH, psINVALID, 0 },
{ 3, SWITCH_3, psHIGH, psINVALID, 0 },
{ 0, 0, psINVALID, psINVALID, 0 } // END MARKER
};
static void buttonHandler(tButton *button) {
uint32_t currentMicros = micros();
uint8_t buttonState = digitalRead(button-&amp;gt;buttonPin);
#ifdef DEBUG
if (button-&amp;gt;oldPressedState != button-&amp;gt;pressedState) {
Serial.print(&#34;Index &#34;);
Serial.print(button-&amp;gt;index);
Serial.print(&#34;, state changed from &#34;);
Serial.print(button-&amp;gt;oldPressedState);
Serial.print(&#34; to &#34;);
Serial.print(button-&amp;gt;pressedState);
Serial.println();
button-&amp;gt;oldPressedState = button-&amp;gt;pressedState;
}
#endif
switch (button-&amp;gt;pressedState) {
case psHIGH:
if (buttonState == LOW) {
button-&amp;gt;pressedState = psLOW;
button-&amp;gt;lastStateChange = currentMicros;
}
break;
case psLOW:
if (buttonState == HIGH) {
button-&amp;gt;pressedState = psHIGH;
button-&amp;gt;lastStateChange = currentMicros;
} else {
if (currentMicros &amp;gt; (button-&amp;gt;lastStateChange + configBlock.debounce)) {
button-&amp;gt;pressedState = psACCEPTED_LOW;
button-&amp;gt;lastStateChange = currentMicros;
}
}
break;
case psACCEPTED_LOW:
if (buttonState == HIGH) {
button-&amp;gt;pressedState = psSHORT;
button-&amp;gt;lastStateChange = currentMicros;
}
if (currentMicros &amp;gt; (button-&amp;gt;lastStateChange + (configBlock.longPress * 1000))) {
button-&amp;gt;pressedState = psLONG_START;
button-&amp;gt;lastStateChange = currentMicros;
}
break;
case psSHORT:
sendMsg(button-&amp;gt;index, &#34;PRESS_SHORT&#34;);
button-&amp;gt;pressedState = psHIGH;
button-&amp;gt;lastStateChange = currentMicros;
break;
case psLONG_START:
sendMsg(button-&amp;gt;index, &#34;PRESS_LONG_START&#34;);
button-&amp;gt;pressedState = psLONG_CONT;
button-&amp;gt;lastStateChange = currentMicros;
break;
case psLONG_CONT:
if (buttonState == HIGH) {
button-&amp;gt;pressedState = psLONG_END;
button-&amp;gt;lastStateChange = currentMicros;
}
if (currentMicros &amp;gt; (button-&amp;gt;lastStateChange + (configBlock.longPressRepeat * 1000))) {
button-&amp;gt;pressedState = psLONG_CONT_SEND;
button-&amp;gt;lastStateChange = currentMicros;
}
break;
case psLONG_CONT_SEND:
sendMsg(button-&amp;gt;index, &#34;PRESS_LONG_CONT&#34;);
button-&amp;gt;pressedState = psLONG_CONT;
button-&amp;gt;lastStateChange = currentMicros;
break;
case psLONG_END:
sendMsg(button-&amp;gt;index, &#34;PRESS_LONG_END&#34;);
button-&amp;gt;pressedState = psHIGH;
button-&amp;gt;lastStateChange = currentMicros;
break;
default:
button-&amp;gt;pressedState = psHIGH;
button-&amp;gt;lastStateChange = currentMicros;
}
}
</code></pre><footer>
</footer>
</main>
<div class="sidebar">
<nav class="slide-menu">
<ul>
<li class=""><a href="http://172.16.3.33:1313/">Home</a></li>
<li class="parent has-sub-menu"><a href="http://172.16.3.33:1313/blog/">Blogs<span class="mark opened">-</span></a>
<ul class="sub-menu">
<li class=""><a href="http://172.16.3.33:1313/blog/tetris/">2024-05-27<br/> Tetris </a></li>
<li class=""><a href="http://172.16.3.33:1313/blog/rgb-driver/">2024-05-25<br/> PL 9823 meets MSP430 </a></li>
<li class=""><a href="http://172.16.3.33:1313/blog/timeserver2/">2025-03-13<br/> Stratum 1 NTP Server participating in ntppool.org </a></li>
<li class=""><a href="http://172.16.3.33:1313/blog/timeserver/">2025-02-11<br/> Just another Stratum 1 Timeserver </a></li>
<li class="active"><a href="http://172.16.3.33:1313/blog/debouncing/">2018-04-30<br/> Yet Another Debouncing Method </a></li>
<li class=""><a href="http://172.16.3.33:1313/blog/three-phase-inverter-ng/">2016-12-19<br/> Three Phase Inverter - Second Service </a></li>
<li class=""><a href="http://172.16.3.33:1313/blog/three-phase-inverter/">2016-10-14<br/> Three Phase Inverter </a></li>
<li class=""><a href="http://172.16.3.33:1313/blog/theremin/">2013-07-01<br/> Theremin </a></li>
<li class=""><a href="http://172.16.3.33:1313/blog/email-childprot/">2013-06-27<br/> Children Protection for Postfix-based EMail-Server </a></li>
</ul>
</li>
<li class=" has-sub-menu"><a href="http://172.16.3.33:1313/articles/">Articles<span class="mark closed">+</span></a>
<ul class="sub-menu">
<li class=""><a href="http://172.16.3.33:1313/articles/quotes/"> Quotes </a></li>
</ul>
</li>
<li class=" has-sub-menu"><a href="http://172.16.3.33:1313/howtos/">HowTos<span class="mark closed">+</span></a>
<ul class="sub-menu">
<li class=""><a href="http://172.16.3.33:1313/howtos/colors-in-minicom/"> Colors in Minicom </a></li>
<li class=""><a href="http://172.16.3.33:1313/howtos/engel-des-herrn/"> Engel des Herrn </a></li>
<li class=""><a href="http://172.16.3.33:1313/howtos/occ-in-nextcloud-pod/"> Execute occ in Nextcloud pod </a></li>
<li class=""><a href="http://172.16.3.33:1313/howtos/gitlab-backup/"> Gitlab Backup and Restore </a></li>
<li class=""><a href="http://172.16.3.33:1313/howtos/gitlab-change-baseurl/"> Gitlab Change BaseURL in Database </a></li>
<li class=""><a href="http://172.16.3.33:1313/howtos/gitlab-upgrades/"> Gitlab Upgrades </a></li>
<li class=""><a href="http://172.16.3.33:1313/howtos/ca-certificate-in-debian/"> How to add a CA certificate in Debian </a></li>
<li class=""><a href="http://172.16.3.33:1313/howtos/iscsi-on-linux/"> iSCSI on Linux </a></li>
<li class=""><a href="http://172.16.3.33:1313/howtos/magnifikat/"> Magnifikat </a></li>
<li class=""><a href="http://172.16.3.33:1313/howtos/neovim/"> Neovim Setup </a></li>
<li class=""><a href="http://172.16.3.33:1313/howtos/putty-and-hardware-keys/"> PuTTY and OPENGPG hardware keys </a></li>
<li class=""><a href="http://172.16.3.33:1313/howtos/resize-hdd-on-running-system/"> Resize HDD on running system </a></li>
<li class=""><a href="http://172.16.3.33:1313/howtos/snmpwalk-with-numeric-and-text-output/"> snmpwalk with numeric and text output of oid </a></li>
<li class=""><a href="http://172.16.3.33:1313/howtos/prince-of-persia-1/"> Solution for Prince of Persia 1 </a></li>
</ul>
</li>
</ul>
</nav>
<div class="sidebar-footer"></div>
</div>
</div><a href="#" id="backtothetop-fixed" class="backtothetop"
data-backtothetop-duration="600"
data-backtothetop-easing="easeOutQuart"
data-backtothetop-fixed-fadeIn="1000"
data-backtothetop-fixed-fadeOut="1000"
data-backtothetop-fixed-bottom="10"
data-backtothetop-fixed-right="20">
<span class="fa-layers fa-fw">
<i class="fas fa-circle"></i>
<i class="fas fa-arrow-circle-up"></i>
</span></a>
</div>
</body>
</html>