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
16 #include "pins_arduino.h"
17 #include "WConstants.h"
20 #include "CapacitiveSensor.h"
22 // Constructor /////////////////////////////////////////////////////////////////
23 // Function that handles the creation and setup of instances
25 CapacitiveSensor::CapacitiveSensor(uint8_t sendPin, uint8_t receivePin)
27 // initialize this instance's variables
28 // Serial.begin(9600); // for debugging
30 loopTimingFactor = 310; // determined empirically - a hack
32 CS_Timeout_Millis = (2000 * (float)loopTimingFactor * (float)F_CPU) / 16000000;
33 CS_AutocaL_Millis = 20000;
35 // Serial.print("timwOut = ");
36 // Serial.println(CS_Timeout_Millis);
38 // get pin mapping and port for send Pin - from PinMode function in core
40 #ifdef NUM_DIGITAL_PINS
41 if (sendPin >= NUM_DIGITAL_PINS) error = -1;
42 if (receivePin >= NUM_DIGITAL_PINS) error = -1;
45 pinMode(sendPin, OUTPUT); // sendpin to OUTPUT
46 pinMode(receivePin, INPUT); // receivePin to INPUT
47 digitalWrite(sendPin, LOW);
49 sBit = PIN_TO_BITMASK(sendPin); // get send pin's ports and bitmask
50 sReg = PIN_TO_BASEREG(sendPin); // get pointer to output register
52 rBit = PIN_TO_BITMASK(receivePin); // get receive pin's ports and bitmask
53 rReg = PIN_TO_BASEREG(receivePin);
55 // get pin mapping and port for receive Pin - from digital pin functions in Wiring.c
56 leastTotal = 0x0FFFFFFFL; // input large value for autocalibrate begin
57 lastCal = millis(); // set millis for start
60 // Public Methods //////////////////////////////////////////////////////////////
61 // Functions available in Wiring sketches, this library, and other libraries
63 long CapacitiveSensor::capacitiveSensor(uint8_t samples)
66 if (samples == 0) return 0;
67 if (error < 0) return -1; // bad pin
70 for (uint8_t i = 0; i < samples; i++) { // loop for samples parameter - simple lowpass filter
71 if (SenseOneCycle() < 0) return -2; // variable over timeout
74 // only calibrate if time is greater than CS_AutocaL_Millis and total is less than 10% of baseline
75 // this is an attempt to keep from calibrating when the sensor is seeing a "touched" signal
77 if ( (millis() - lastCal > CS_AutocaL_Millis) && abs(total - leastTotal) < (int)(.10 * (float)leastTotal) ) {
79 // Serial.println(); // debugging
80 // Serial.println("auto-calibrate");
84 leastTotal = 0x0FFFFFFFL; // reset for "autocalibrate"
88 Serial.print(" total = ");
91 Serial.print(" leastTotal = ");
92 Serial.println(leastTotal);
94 Serial.print("total - leastTotal = ");
95 x = total - leastTotal ;
97 Serial.print(" .1 * leastTotal = ");
98 x = (int)(.1 * (float)leastTotal);
102 // routine to subtract baseline (non-sensed capacitance) from sensor return
103 if (total < leastTotal) leastTotal = total; // set floor value to subtract from sensed value
104 return(total - leastTotal);
108 long CapacitiveSensor::capacitiveSensorRaw(uint8_t samples)
111 if (samples == 0) return 0;
112 if (error < 0) return -1; // bad pin - this appears not to work
114 for (uint8_t i = 0; i < samples; i++) { // loop for samples parameter - simple lowpass filter
115 if (SenseOneCycle() < 0) return -2; // variable over timeout
122 void CapacitiveSensor::reset_CS_AutoCal(void){
123 leastTotal = 0x0FFFFFFFL;
126 void CapacitiveSensor::set_CS_AutocaL_Millis(unsigned long autoCal_millis){
127 CS_AutocaL_Millis = autoCal_millis;
130 void CapacitiveSensor::set_CS_Timeout_Millis(unsigned long timeout_millis){
131 CS_Timeout_Millis = (timeout_millis * (float)loopTimingFactor * (float)F_CPU) / 16000000; // floats to deal with large numbers
134 // Private Methods /////////////////////////////////////////////////////////////
135 // Functions only available to other functions in this library
137 int CapacitiveSensor::SenseOneCycle(void)
140 DIRECT_WRITE_LOW(sReg, sBit); // sendPin Register low
141 DIRECT_MODE_INPUT(rReg, rBit); // receivePin to input (pullups are off)
142 DIRECT_MODE_OUTPUT(rReg, rBit); // receivePin to OUTPUT
143 DIRECT_WRITE_LOW(rReg, rBit); // pin is now LOW AND OUTPUT
144 delayMicroseconds(10);
145 DIRECT_MODE_INPUT(rReg, rBit); // receivePin to input (pullups are off)
146 DIRECT_WRITE_HIGH(sReg, sBit); // sendPin High
149 while ( !DIRECT_READ(rReg, rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is LOW AND total is positive value
152 //Serial.print("SenseOneCycle(1): ");
153 //Serial.println(total);
155 if (total > CS_Timeout_Millis) {
156 return -2; // total variable over timeout
159 // set receive pin HIGH briefly to charge up fully - because the while loop above will exit when pin is ~ 2.5V
161 DIRECT_WRITE_HIGH(rReg, rBit);
162 DIRECT_MODE_OUTPUT(rReg, rBit); // receivePin to OUTPUT - pin is now HIGH AND OUTPUT
163 DIRECT_WRITE_HIGH(rReg, rBit);
164 DIRECT_MODE_INPUT(rReg, rBit); // receivePin to INPUT (pullup is off)
165 DIRECT_WRITE_LOW(sReg, sBit); // sendPin LOW
168 #ifdef FIVE_VOLT_TOLERANCE_WORKAROUND
169 DIRECT_MODE_OUTPUT(rReg, rBit);
170 DIRECT_WRITE_LOW(rReg, rBit);
171 delayMicroseconds(10);
172 DIRECT_MODE_INPUT(rReg, rBit); // receivePin to INPUT (pullup is off)
174 while ( DIRECT_READ(rReg, rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is HIGH AND total is less than timeout
178 //Serial.print("SenseOneCycle(2): ");
179 //Serial.println(total);
181 if (total >= CS_Timeout_Millis) {
182 return -2; // total variable over timeout