-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathCapPin.cpp
164 lines (112 loc) · 4.22 KB
/
CapPin.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
CapPin.cpp - Capacitive Sensing Library for 'duino / Wiring
8-8-2011 <paul@moderndevice.com> http://opensource.org/licenses/mit-license.php
This class uses the Atmega's built-in pullup resistors in place of the "send pin" in
CapSlider, and CapTouch.
*/
// include this library's description file
#include "CapPin.h"
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "pins_arduino.h"
#include "WConstants.h"
#endif
// Constructor /////////////////////////////////////////////////////////////////
// Function that handles the creation and setup of instances
CapPin::CapPin(uint8_t sensorPin){
// initialize this instance's variables
// Serial.begin(9600); // for debugging
int error = 1;
// no "send Pin" in this method - the Port register pullup does all the work
// get pin mapping and port for sensorPin - from digital pin functions in Wiring.c
rBit = digitalPinToBitMask(sensorPin); // get receive pin's ports and bitmask
rPort = digitalPinToPort(sensorPin);
rOut = portOutputRegister(rPort);
if (rPort == NOT_A_PORT){ error = -1; // this Arduino function does not appear to work
// Serial.println("bad pin");
}
rReg = portModeRegister(rPort);
rOut = portOutputRegister(rPort);
rIn = portInputRegister(rPort);
calibrateFlag = 0;
}
// calibrate the baseline value for readPin method
void CapPin::calibratePin(unsigned int samples){
uint16_t j, k=0;
total = 0;
*rReg |= rBit; // set Send pin Output
// the idea here is to calibrate for the same number of samples that are specified
// but to make sure that the value is over a certain number of powerline cycles to
// average out powerline errors
unsigned long start = millis();
*rOut &= ~rBit; // set sensorPin output register LOW
while (millis() - start < calibrateTime){ // sample at least 10 power line cycles
for (unsigned int i = 0; i < samples; i++){ // loop for samples parameter
*rReg &= ~rBit; // set sensorPin to INPUT
*rOut |= rBit; // set sensorPin output register HIGH to set pullups
for( j = 0; j < 500; j++)
{ if ( *rIn & rBit )
break; }
total+= j;
*rOut &= ~rBit; // Pin output register LOW
*rReg |= rBit; // OUTPUT & LOW now
}
k++;
}
// if pin is grounded (or connected with resistance lower than the pullup resistors,
// the method will return in about one second.
if (total >= ((unsigned long)samples * 450UL * (unsigned long)k)){
Serial.println("calibratePin method over timeout, check wiring.");
}
else
{
baselineCount = total / k;
Serial.print("Calibrated baselineCount = ");
Serial.println(baselineCount);
}
}
// uses the pullups to sense capacitance without a send pin
long CapPin::readPin(unsigned int samples)
{ uint16_t j;
total = 0;
*rOut |= rBit;
// if (samples < 1) return 0; // defensive programming
// calibrate first time through after reset or cycling power
if (calibrateFlag == 0 || samples != lastSamples){
calibratePin(samples);
lastSamples = samples;
calibrateFlag = 1;
}
// I'm using a for loop here instead of while. It adds a timeout automatically
// the idea is from here http://www.arduino.cc/playground/Code/CapacitiveSensor
for (unsigned int i = 0; i < samples; i++){ // loop for samples parameter
noInterrupts();
*rReg &= ~rBit; // set sensorPin to INPUT
*rOut |= rBit; // set sensorPin output register HIGH to set pullups
interrupts();
for( j = 0; j < 5000; j++)
{ if ( *rIn & rBit ) // bail out when pin goes high
break; }
total+= j;
noInterrupts();
*rOut &= ~rBit; // Pin output register LOW
*rReg |= rBit; // OUTPUT & LOW now
interrupts();
}
// if pin is grounded (or connected to ground with resistance
// lower than the pullup resistors,
// the method will return in about one second.
if (total >= ((unsigned long)samples * 450UL)) {
Serial.println("readPin method over timeout, check wiring.");
return -1;
}
//Serial.println(total);
#ifdef NO_NEGATIVES
if (((long)total - (long)baselineCount) > 0)
return (total - baselineCount);
else return 0;
#else
return (total - baselineCount);
#endif
}