This commit is contained in:
254
attic/public/blog/debouncing/index.html
Normal file
254
attic/public/blog/debouncing/index.html
Normal file
@ -0,0 +1,254 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-us">
|
||||
<head><script src="/livereload.js?mindelay=10&v=2&port=1313&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:<
|
||||
void count() { static uint32_t lastEvent = 0; uint32_t currentEvent = micros(); if (currentEvent &gt; (lastEvent + configBlock.debounce)) { lastEvent = currentEvent; cnt++; } } 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:<
|
||||
void count() { static uint32_t lastEvent = 0; uint32_t currentEvent = micros(); if (currentEvent &gt; (lastEvent + configBlock.debounce)) { lastEvent = currentEvent; cnt++; } } 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:<
|
||||
void count() { static uint32_t lastEvent = 0; uint32_t currentEvent = micros(); if (currentEvent &gt; (lastEvent + configBlock.debounce)) { lastEvent = currentEvent; cnt++; } } 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:<</p>
|
||||
<pre tabindex="0"><code>void count() {
|
||||
static uint32_t lastEvent = 0;
|
||||
uint32_t currentEvent = micros();
|
||||
if (currentEvent &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’t work anymore.</p>
|
||||
<p>Since I couldn’t remember the approaches I read about earlier I’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’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-&gt;buttonPin);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (button-&gt;oldPressedState != button-&gt;pressedState) {
|
||||
Serial.print("Index ");
|
||||
Serial.print(button-&gt;index);
|
||||
Serial.print(", state changed from ");
|
||||
Serial.print(button-&gt;oldPressedState);
|
||||
Serial.print(" to ");
|
||||
Serial.print(button-&gt;pressedState);
|
||||
Serial.println();
|
||||
button-&gt;oldPressedState = button-&gt;pressedState;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (button-&gt;pressedState) {
|
||||
case psHIGH:
|
||||
if (buttonState == LOW) {
|
||||
button-&gt;pressedState = psLOW;
|
||||
button-&gt;lastStateChange = currentMicros;
|
||||
}
|
||||
break;
|
||||
case psLOW:
|
||||
if (buttonState == HIGH) {
|
||||
button-&gt;pressedState = psHIGH;
|
||||
button-&gt;lastStateChange = currentMicros;
|
||||
} else {
|
||||
if (currentMicros &gt; (button-&gt;lastStateChange + configBlock.debounce)) {
|
||||
button-&gt;pressedState = psACCEPTED_LOW;
|
||||
button-&gt;lastStateChange = currentMicros;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case psACCEPTED_LOW:
|
||||
if (buttonState == HIGH) {
|
||||
button-&gt;pressedState = psSHORT;
|
||||
button-&gt;lastStateChange = currentMicros;
|
||||
}
|
||||
if (currentMicros &gt; (button-&gt;lastStateChange + (configBlock.longPress * 1000))) {
|
||||
button-&gt;pressedState = psLONG_START;
|
||||
button-&gt;lastStateChange = currentMicros;
|
||||
}
|
||||
break;
|
||||
case psSHORT:
|
||||
sendMsg(button-&gt;index, "PRESS_SHORT");
|
||||
button-&gt;pressedState = psHIGH;
|
||||
button-&gt;lastStateChange = currentMicros;
|
||||
break;
|
||||
case psLONG_START:
|
||||
sendMsg(button-&gt;index, "PRESS_LONG_START");
|
||||
button-&gt;pressedState = psLONG_CONT;
|
||||
button-&gt;lastStateChange = currentMicros;
|
||||
break;
|
||||
case psLONG_CONT:
|
||||
if (buttonState == HIGH) {
|
||||
button-&gt;pressedState = psLONG_END;
|
||||
button-&gt;lastStateChange = currentMicros;
|
||||
}
|
||||
if (currentMicros &gt; (button-&gt;lastStateChange + (configBlock.longPressRepeat * 1000))) {
|
||||
button-&gt;pressedState = psLONG_CONT_SEND;
|
||||
button-&gt;lastStateChange = currentMicros;
|
||||
}
|
||||
break;
|
||||
case psLONG_CONT_SEND:
|
||||
sendMsg(button-&gt;index, "PRESS_LONG_CONT");
|
||||
button-&gt;pressedState = psLONG_CONT;
|
||||
button-&gt;lastStateChange = currentMicros;
|
||||
break;
|
||||
case psLONG_END:
|
||||
sendMsg(button-&gt;index, "PRESS_LONG_END");
|
||||
button-&gt;pressedState = psHIGH;
|
||||
button-&gt;lastStateChange = currentMicros;
|
||||
break;
|
||||
default:
|
||||
button-&gt;pressedState = psHIGH;
|
||||
button-&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>
|
Reference in New Issue
Block a user