CapacitiveSensor.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. pinMode(sendPin, OUTPUT); // sendpin to OUTPUT
  34. pinMode(receivePin, INPUT); // receivePin to INPUT
  35. sBit = digitalPinToBitMask(sendPin); // get send pin's ports and bitmask
  36. sPort = digitalPinToPort(sendPin);
  37. sReg = portModeRegister(sPort);
  38. sOut = portOutputRegister(sPort); // get pointer to output register
  39. rBit = digitalPinToBitMask(receivePin); // get receive pin's ports and bitmask
  40. rPort = digitalPinToPort(receivePin);
  41. rReg = portModeRegister(rPort);
  42. rIn = portInputRegister(rPort);
  43. rOut = portOutputRegister(rPort);
  44. // get pin mapping and port for receive Pin - from digital pin functions in Wiring.c
  45. leastTotal = 0x0FFFFFFFL; // input large value for autocalibrate begin
  46. lastCal = millis(); // set millis for start
  47. }
  48. // Public Methods //////////////////////////////////////////////////////////////
  49. // Functions available in Wiring sketches, this library, and other libraries
  50. long CapacitiveSensor::capacitiveSensor(uint8_t samples)
  51. {
  52. total = 0;
  53. if (samples == 0) return 0;
  54. if (error < 0) return -1; // bad pin
  55. for (uint8_t i = 0; i < samples; i++) { // loop for samples parameter - simple lowpass filter
  56. if (SenseOneCycle() < 0) return -2; // variable over timeout
  57. }
  58. // only calibrate if time is greater than CS_AutocaL_Millis and total is less than 10% of baseline
  59. // this is an attempt to keep from calibrating when the sensor is seeing a "touched" signal
  60. if ( (millis() - lastCal > CS_AutocaL_Millis) && abs(total - leastTotal) < (int)(.10 * (float)leastTotal) ) {
  61. // Serial.println(); // debugging
  62. // Serial.println("auto-calibrate");
  63. // Serial.println();
  64. // delay(2000); */
  65. leastTotal = 0x0FFFFFFFL; // reset for "autocalibrate"
  66. lastCal = millis();
  67. }
  68. /*else{ // debugging
  69. Serial.print(" total = ");
  70. Serial.print(total);
  71. Serial.print(" leastTotal = ");
  72. Serial.println(leastTotal);
  73. Serial.print("total - leastTotal = ");
  74. x = total - leastTotal ;
  75. Serial.print(x);
  76. Serial.print(" .1 * leastTotal = ");
  77. x = (int)(.1 * (float)leastTotal);
  78. Serial.println(x);
  79. } */
  80. // routine to subtract baseline (non-sensed capacitance) from sensor return
  81. if (total < leastTotal) leastTotal = total; // set floor value to subtract from sensed value
  82. return(total - leastTotal);
  83. }
  84. long CapacitiveSensor::capacitiveSensorRaw(uint8_t samples)
  85. {
  86. total = 0;
  87. if (samples == 0) return 0;
  88. if (error < 0) return -1; // bad pin - this appears not to work
  89. for (uint8_t i = 0; i < samples; i++) { // loop for samples parameter - simple lowpass filter
  90. if (SenseOneCycle() < 0) return -2; // variable over timeout
  91. }
  92. return total;
  93. }
  94. void CapacitiveSensor::reset_CS_AutoCal(void){
  95. leastTotal = 0x0FFFFFFFL;
  96. }
  97. void CapacitiveSensor::set_CS_AutocaL_Millis(unsigned long autoCal_millis){
  98. CS_AutocaL_Millis = autoCal_millis;
  99. }
  100. void CapacitiveSensor::set_CS_Timeout_Millis(unsigned long timeout_millis){
  101. CS_Timeout_Millis = (timeout_millis * (float)loopTimingFactor * (float)F_CPU) / 16000000; // floats to deal with large numbers
  102. }
  103. // Private Methods /////////////////////////////////////////////////////////////
  104. // Functions only available to other functions in this library
  105. int CapacitiveSensor::SenseOneCycle(void)
  106. {
  107. noInterrupts();
  108. *sOut &= ~sBit; // sendPin Register low
  109. *rReg &= ~rBit; // receivePin to input
  110. *rOut &= ~rBit; // receivePin Register low to make sure pullups are off
  111. *rReg |= rBit; // receivePin to OUTPUT - pin is now LOW AND OUTPUT
  112. *rReg &= ~rBit; // receivePin to INPUT
  113. *sOut |= sBit; // sendPin High
  114. interrupts();
  115. while ( !(*rIn & rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is LOW AND total is positive value
  116. total++;
  117. }
  118. Serial.print("SenseOneCycle(1): ");
  119. Serial.println(total);
  120. if (total > CS_Timeout_Millis) {
  121. return -2; // total variable over timeout
  122. }
  123. // set receive pin HIGH briefly to charge up fully - because the while loop above will exit when pin is ~ 2.5V
  124. noInterrupts();
  125. *rOut |= rBit; // receivePin - turns on pullup
  126. *rReg |= rBit; // receivePin to OUTPUT - pin is now HIGH AND OUTPUT
  127. *rReg &= ~rBit; // receivePin to INPUT
  128. *rOut &= ~rBit; // receivePin turn off pullup
  129. *sOut &= ~sBit; // sendPin LOW
  130. interrupts();
  131. while ( (*rIn & rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is HIGH AND total is less than timeout
  132. total++;
  133. }
  134. Serial.print("SenseOneCycle(2): ");
  135. Serial.println(total);
  136. if (total >= CS_Timeout_Millis) {
  137. return -2; // total variable over timeout
  138. } else {
  139. return 1;
  140. }
  141. }