avdweb_Switch.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. Switch.cpp
  3. Copyright (C) 2012 Albert van Dalen http://www.avdweb.nl
  4. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
  6. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  7. of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License at http://www.gnu.org/licenses .
  8. AUTHOR: Albert van Dalen
  9. WEBSITE: http://www.avdweb.nl/arduino/hardware-interfacing/simple-switch-debouncer.html
  10. HISTORY:
  11. 1.0.0 20-04-2013 _debouncePeriod=50
  12. 1.0.1 22-05-2013 Added longPress, doubleClick
  13. 1.0.2 01-12-2015 added process(input)
  14. 1.0.3 15-01-2016 added deglitching
  15. 1.0.5 25-01-2017 file renamed to avdweb_Switch
  16. 1.1.0 28-07-2018 added callbacks (code by Sean Lanigan, added by Martin Laclaustra)
  17. 1.2.0-rc 28-07-2017 added singleclick. Reorganize, keeping variables for each event in one function
  18. ..........................................DEGLITCHING..............................
  19. ________________ _
  20. on | | | | _
  21. | | | | | |
  22. | |_| |___| |__
  23. analog off_____|_____________________________|____________________________
  24. ________________ _ _
  25. input _____| |_| |___| |_______________________________
  26. poll ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
  27. equal 0 1 1 0 1 1 1 1 1 1 1 1 0 0 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
  28. deglitchPeriod <--------><-- <-- <- <--------><--------><--------
  29. ___________________________
  30. deglitched _________________| |__________________
  31. deglitchTime ^ ^ ^ ^ ^ ^ ^
  32. ..........................................DEBOUNCING.............................
  33. debouncePeriod <-------------------------------->
  34. _________________________________
  35. debounced _________________| |____________
  36. _ _
  37. _switched _________________| |_______________________________| |__________
  38. switchedTime ^ ^
  39. **********************************************************************************
  40. ........................................DOUBLE CLICK..............................
  41. __________ ______
  42. debounced ________| |_______| |_____________________________
  43. poll ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
  44. _ _
  45. pushed _________| |________________| |__________________________________
  46. pushedTime ^ ^
  47. _ _
  48. released ____________________| |____________| |___________________________
  49. releasedTime ^ ^
  50. doubleClickPeriod <------------------------------------->
  51. _
  52. _doubleClick ___________________________| |__________________________________
  53. ........................................LONG PRESS................................
  54. ___________________________
  55. debounced ________| |___________________________
  56. poll ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
  57. longPressPeriod <--------------->
  58. _ _
  59. _switched _________| |_________________________| |________________________
  60. __________
  61. longPressDisable ___________________________| |_________________________
  62. _
  63. _longPress ___________________________| |__________________________________
  64. ........................................SINGLE CLICK..............................
  65. __________ ______
  66. debounced ________| |_______________________________| |_____
  67. poll ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
  68. longPressPeriod <--------------->
  69. doubleClickPeriod <------------------------------------->
  70. _ _ _ _
  71. _switched _________| |_______| |_____________________________| |____| |___
  72. _____
  73. singleClickDisable______________________________________________| |__________
  74. _
  75. _singleClick _______________________________________________| |______________
  76. */
  77. #include "Arduino.h"
  78. #include "avdweb_Switch.h"
  79. Switch::Switch(byte _pin, byte PinMode, bool polarity, int debouncePeriod, int longPressPeriod, int doubleClickPeriod, int deglitchPeriod):
  80. pin(_pin), polarity(polarity), deglitchPeriod(deglitchPeriod), debouncePeriod(debouncePeriod), longPressPeriod(longPressPeriod), doubleClickPeriod(doubleClickPeriod)
  81. { pinMode(pin, PinMode);
  82. switchedTime = millis();
  83. debounced = digitalRead(pin);
  84. singleClickDisable = true;
  85. }
  86. bool Switch::poll()
  87. { input = digitalRead(pin);
  88. ms = millis();
  89. return process();
  90. }
  91. bool Switch::process()
  92. { deglitch();
  93. debounce();
  94. calcSingleClick();
  95. calcDoubleClick();
  96. calcLongPress();
  97. if(switched())
  98. { switchedTime = ms; //stores last times for future rounds
  99. if(pushed())
  100. { pushedTime = ms;
  101. } else { releasedTime = ms;
  102. }
  103. }
  104. triggerCallbacks();
  105. return _switched;
  106. }
  107. void inline Switch::deglitch()
  108. {
  109. if(input == lastInput) equal = 1;
  110. else
  111. { equal = 0;
  112. deglitchTime = ms;
  113. }
  114. if(equal && ((ms - deglitchTime) > deglitchPeriod)) // max 50ms, disable deglitch: 0ms
  115. { deglitched = input;
  116. deglitchTime = ms;
  117. }
  118. lastInput = input;
  119. }
  120. void inline Switch::debounce()
  121. {
  122. _switched = 0;
  123. if((deglitched != debounced) && ((ms - switchedTime) > debouncePeriod))
  124. { debounced = deglitched;
  125. _switched = 1;
  126. }
  127. }
  128. void inline Switch::calcSingleClick()
  129. { _singleClick = false;
  130. if(pushed())
  131. { if((ms - pushedTime) >= doubleClickPeriod)
  132. { singleClickDisable = false; //resets when pushed not in second click of doubleclick
  133. } else { singleClickDisable = true; //silence single click in second cl. doublecl.
  134. }
  135. }
  136. if(!singleClickDisable)
  137. { _singleClick = !switched() && !on() && ((releasedTime - pushedTime) <= longPressPeriod) && ((ms - pushedTime) >= doubleClickPeriod); // true just one time between polls
  138. singleClickDisable = _singleClick; // will be reset at next push
  139. }
  140. }
  141. void inline Switch::calcDoubleClick()
  142. { _doubleClick = pushed() && ((ms - pushedTime) < doubleClickPeriod);
  143. }
  144. void inline Switch::calcLongPress()
  145. { _longPress = false;
  146. if(released()) longPressDisable = false; //resets when released
  147. if(!longPressDisable)
  148. { _longPress = !switched() && on() && ((ms - pushedTime) > longPressPeriod); // true just one time between polls
  149. longPressDisable = _longPress; // will be reset at next release
  150. }
  151. }
  152. bool Switch::switched()
  153. { return _switched;
  154. }
  155. bool Switch::on()
  156. { return !(debounced^polarity);
  157. }
  158. bool Switch::pushed()
  159. { return _switched && !(debounced^polarity);
  160. }
  161. bool Switch::released()
  162. { return _switched && (debounced^polarity);
  163. }
  164. bool Switch::longPress()
  165. { return _longPress;
  166. }
  167. bool Switch::doubleClick()
  168. { return _doubleClick;
  169. }
  170. bool Switch::singleClick()
  171. { return _singleClick;
  172. }
  173. void Switch::triggerCallbacks()
  174. {
  175. if(_pushedCallback && pushed())
  176. { _pushedCallback(_pushedCallbackParam);
  177. }
  178. else if(_releasedCallback && released())
  179. { _releasedCallback(_releasedCallbackParam);
  180. }
  181. if(_longPressCallback && longPress())
  182. { _longPressCallback(_longPressCallbackParam);
  183. }
  184. if(_doubleClickCallback && doubleClick())
  185. { _doubleClickCallback(_doubleClickCallbackParam);
  186. }
  187. if(_singleClickCallback && singleClick())
  188. { _singleClickCallback(_singleClickCallbackParam);
  189. }
  190. }
  191. void Switch::setPushedCallback(switchCallback_t cb, void* param)
  192. { /// Store the "pushed" callback function
  193. _pushedCallback = cb;
  194. _pushedCallbackParam = param;
  195. }
  196. void Switch::setReleasedCallback(switchCallback_t cb, void* param)
  197. { /// Store the "released" callback function
  198. _releasedCallback = cb;
  199. _releasedCallbackParam = param;
  200. }
  201. void Switch::setLongPressCallback(switchCallback_t cb, void* param)
  202. { /// Store the "long press" callback function
  203. _longPressCallback = cb;
  204. _longPressCallbackParam = param;
  205. }
  206. void Switch::setDoubleClickCallback(switchCallback_t cb, void* param)
  207. { /// Store the "double click" callback function
  208. _doubleClickCallback = cb;
  209. _doubleClickCallbackParam = param;
  210. }
  211. void Switch::setSingleClickCallback(switchCallback_t cb, void* param)
  212. { /// Store the "double click" callback function
  213. _singleClickCallback = cb;
  214. _singleClickCallbackParam = param;
  215. }