All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
255 lines
12 KiB
HTML
255 lines
12 KiB
HTML
<!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>
|