原文链接:http://www.geek-workshop.com/thread-3335-1-1.html
Arduino除了接受数字端口的数字信号,唯一能检测的模拟物理量就是电压。任何模拟传感器的检测值几乎都要通过相关电路转化成电压值,再输入 arduino的模拟端口进行模数转换。电容值就需要相对更复杂和昂贵的电路转化为电压值,才能被Arduino检测,而对很多物理过程的检测,都可以很 方便可靠地通过来检测电容值来实现,其中最常用的地方就是触摸传感器。风靡一时的MaKey MaKey就是个例子。这里介绍一个除了一段导线和一个端口,不需要任何元器件的电容检测方法。 这个方法的思路是,首先把一个数字端口设成低电位,并打开arduino的内部上拉电阻,开始计算这个端口到达高电位所需要的时间。而这个时间与此端口的 对地电容值有关,电容越大,时间越长。在硬件上只需要在一个端口上连一根导线即可。用手指触摸这段导线的裸露端,就会导致电容变化,arduino可以通 过上述方法检测这个变化。如果要增加灵敏度,可以在导线上连一片锡箔。为防止你手上有强静电击穿芯片,可以在锡箔上盖一薄层绝缘纸。
使用的代码如下。你可以方便地把它用到你的项目里。程序下载运行后,用手指触摸接在8号口的导线,就可以点亮9号口的led,手指离开,led熄灭。这个图上用的是板子上的13号灯。
1 int ledPin = 9; 2 int capval; 3 void setup() 4 { 5 pinMode(ledPin, OUTPUT); 6 Serial.begin(9600); 7 Serial.println("Touch senser"); 8 } 9 10 void loop () 11 { 12 digitalWrite(ledPin,LOW); 13 capval = readCapacitivePin(8); 14 Serial.println(capval, DEC); 15 if (capval > 2) { 16 // turn LED on: 17 digitalWrite(ledPin, HIGH); 18 delay(10); 19 } 20 } 21 22 uint8_t readCapacitivePin(int pinToMeasure) { 23 // Variables used to translate from Arduino to AVR pin naming 24 volatile uint8_t* port; 25 volatile uint8_t* ddr; 26 volatile uint8_t* pin; 27 // Here we translate the input pin number from 28 // Arduino pin number to the AVR PORT, PIN, DDR, 29 // and which bit of those registers we care about. 30 byte bitmask; 31 port = portOutputRegister(digitalPinToPort(pinToMeasure)); 32 ddr = portModeRegister(digitalPinToPort(pinToMeasure)); 33 bitmask = digitalPinToBitMask(pinToMeasure); 34 pin = portInputRegister(digitalPinToPort(pinToMeasure)); 35 // Discharge the pin first by setting it low and output 36 *port &= ~(bitmask); 37 *ddr |= bitmask; 38 delay(1); 39 // Make the pin an input with the internal pull-up on 40 *ddr &= ~(bitmask); 41 *port |= bitmask; 42 43 // Now see how long the pin to get pulled up. This manual unrolling of the loop 44 // decreases the number of hardware cycles between each read of the pin, 45 // thus increasing sensitivity. 46 uint8_t cycles = 17; 47 if (*pin & bitmask) { cycles = 0;} 48 else if (*pin & bitmask) { cycles = 1;} 49 else if (*pin & bitmask) { cycles = 2;} 50 else if (*pin & bitmask) { cycles = 3;} 51 else if (*pin & bitmask) { cycles = 4;} 52 else if (*pin & bitmask) { cycles = 5;} 53 else if (*pin & bitmask) { cycles = 6;} 54 else if (*pin & bitmask) { cycles = 7;} 55 else if (*pin & bitmask) { cycles = 8;} 56 else if (*pin & bitmask) { cycles = 9;} 57 else if (*pin & bitmask) { cycles = 10;} 58 else if (*pin & bitmask) { cycles = 11;} 59 else if (*pin & bitmask) { cycles = 12;} 60 else if (*pin & bitmask) { cycles = 13;} 61 else if (*pin & bitmask) { cycles = 14;} 62 else if (*pin & bitmask) { cycles = 15;} 63 else if (*pin & bitmask) { cycles = 16;} 64 65 // Discharge the pin again by setting it low and output 66 // It's important to leave the pins low if you want to 67 // be able to touch more than 1 sensor at a time - if 68 // the sensor is left pulled high, when you touch 69 // two sensors, your body will transfer the charge between 70 // sensors. 71 *port &= ~(bitmask); 72 *ddr |= bitmask; 73 74 return cycles; 75 }
这个主意不是我的原创,readCapacitivePin函数来自官网playground,我写了setup和loop来示范它的用法。