CapacitiveSensor.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. CapacitiveSense.h v.04 - Capacitive Sensing Library for 'duino / Wiring
  3. Copyright (c) 2009 Paul Bagder All right reserved.
  4. Version 04 by Paul Stoffregen - Arduino 1.0 compatibility, issue 146 fix
  5. vim: set ts=4:
  6. */
  7. #if ARDUINO >= 100
  8. #include "Arduino.h"
  9. #else
  10. #include "WProgram.h"
  11. #include "pins_arduino.h"
  12. #include "WConstants.h"
  13. #endif
  14. #include "CapacitiveSensor.h"
  15. // Constructor /////////////////////////////////////////////////////////////////
  16. // Function that handles the creation and setup of instances
  17. CapacitiveSensor::CapacitiveSensor(uint8_t sendPin, uint8_t receivePin)
  18. {
  19. uint8_t sPort, rPort;
  20. // initialize this instance's variables
  21. // Serial.begin(9600); // for debugging
  22. error = 1;
  23. loopTimingFactor = 310; // determined empirically - a hack
  24. CS_Timeout_Millis = (2000 * (float)loopTimingFactor * (float)F_CPU) / 16000000;
  25. CS_AutocaL_Millis = 20000;
  26. // Serial.print("timwOut = ");
  27. // Serial.println(CS_Timeout_Millis);
  28. // get pin mapping and port for send Pin - from PinMode function in core
  29. #ifdef NUM_DIGITAL_PINS
  30. if (sendPin >= NUM_DIGITAL_PINS) error = -1;
  31. if (receivePin >= NUM_DIGITAL_PINS) error = -1;
  32. #endif
  33. sBit = digitalPinToBitMask(sendPin); // get send pin's ports and bitmask
  34. sPort = digitalPinToPort(sendPin);
  35. sReg = portModeRegister(sPort);
  36. sOut = portOutputRegister(sPort); // get pointer to output register
  37. rBit = digitalPinToBitMask(receivePin); // get receive pin's ports and bitmask
  38. rPort = digitalPinToPort(receivePin);
  39. rReg = portModeRegister(rPort);
  40. rIn = portInputRegister(rPort);
  41. rOut = portOutputRegister(rPort);
  42. // get pin mapping and port for receive Pin - from digital pin functions in Wiring.c
  43. noInterrupts();
  44. *sReg |= sBit; // set sendpin to OUTPUT
  45. interrupts();
  46. leastTotal = 0x0FFFFFFFL; // input large value for autocalibrate begin
  47. lastCal = millis(); // set millis for start
  48. }
  49. // Public Methods //////////////////////////////////////////////////////////////
  50. // Functions available in Wiring sketches, this library, and other libraries
  51. long CapacitiveSensor::capacitiveSensor(uint8_t samples)
  52. {
  53. total = 0;
  54. if (samples == 0) return 0;
  55. if (error < 0) return -1; // bad pin
  56. for (uint8_t i = 0; i < samples; i++) { // loop for samples parameter - simple lowpass filter
  57. if (SenseOneCycle() < 0) return -2; // variable over timeout
  58. }
  59. // only calibrate if time is greater than CS_AutocaL_Millis and total is less than 10% of baseline
  60. // this is an attempt to keep from calibrating when the sensor is seeing a "touched" signal
  61. if ( (millis() - lastCal > CS_AutocaL_Millis) && abs(total - leastTotal) < (int)(.10 * (float)leastTotal) ) {
  62. // Serial.println(); // debugging
  63. // Serial.println("auto-calibrate");
  64. // Serial.println();
  65. // delay(2000); */
  66. leastTotal = 0x0FFFFFFFL; // reset for "autocalibrate"
  67. lastCal = millis();
  68. }
  69. /*else{ // debugging
  70. Serial.print(" total = ");
  71. Serial.print(total);
  72. Serial.print(" leastTotal = ");
  73. Serial.println(leastTotal);
  74. Serial.print("total - leastTotal = ");
  75. x = total - leastTotal ;
  76. Serial.print(x);
  77. Serial.print(" .1 * leastTotal = ");
  78. x = (int)(.1 * (float)leastTotal);
  79. Serial.println(x);
  80. } */
  81. // routine to subtract baseline (non-sensed capacitance) from sensor return
  82. if (total < leastTotal) leastTotal = total; // set floor value to subtract from sensed value
  83. return(total - leastTotal);
  84. }
  85. long CapacitiveSensor::capacitiveSensorRaw(uint8_t samples)
  86. {
  87. total = 0;
  88. if (samples == 0) return 0;
  89. if (error < 0) return -1; // bad pin - this appears not to work
  90. for (uint8_t i = 0; i < samples; i++) { // loop for samples parameter - simple lowpass filter
  91. if (SenseOneCycle() < 0) return -2; // variable over timeout
  92. }
  93. return total;
  94. }
  95. void CapacitiveSensor::reset_CS_AutoCal(void){
  96. leastTotal = 0x0FFFFFFFL;
  97. }
  98. void CapacitiveSensor::set_CS_AutocaL_Millis(unsigned long autoCal_millis){
  99. CS_AutocaL_Millis = autoCal_millis;
  100. }
  101. void CapacitiveSensor::set_CS_Timeout_Millis(unsigned long timeout_millis){
  102. CS_Timeout_Millis = (timeout_millis * (float)loopTimingFactor * (float)F_CPU) / 16000000; // floats to deal with large numbers
  103. }
  104. // Private Methods /////////////////////////////////////////////////////////////
  105. // Functions only available to other functions in this library
  106. int CapacitiveSensor::SenseOneCycle(void)
  107. {
  108. noInterrupts();
  109. *sOut &= ~sBit; // set Send Pin Register low
  110. *rReg &= ~rBit; // set receivePin to input
  111. *rOut &= ~rBit; // set receivePin Register low to make sure pullups are off
  112. *rReg |= rBit; // set pin to OUTPUT - pin is now LOW AND OUTPUT
  113. *rReg &= ~rBit; // set pin to INPUT
  114. *sOut |= sBit; // set send Pin High
  115. interrupts();
  116. while ( !(*rIn & rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is LOW AND total is positive value
  117. total++;
  118. }
  119. if (total > CS_Timeout_Millis) {
  120. return -2; // total variable over timeout
  121. }
  122. // set receive pin HIGH briefly to charge up fully - because the while loop above will exit when pin is ~ 2.5V
  123. noInterrupts();
  124. *rOut |= rBit; // set receive pin HIGH - turns on pullup
  125. *rReg |= rBit; // set pin to OUTPUT - pin is now HIGH AND OUTPUT
  126. *rReg &= ~rBit; // set pin to INPUT
  127. *rOut &= ~rBit; // turn off pullup
  128. *sOut &= ~sBit; // set send Pin LOW
  129. interrupts();
  130. while ( (*rIn & rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is HIGH AND total is less than timeout
  131. total++;
  132. }
  133. // Serial.println(total);
  134. if (total >= CS_Timeout_Millis) {
  135. return -2; // total variable over timeout
  136. } else {
  137. return 1;
  138. }
  139. }