CapacitiveSensor.cpp 6.1 KB

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