CapacitiveSensor.cpp 5.9 KB

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