极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 36134|回复: 4

用arduino直接检测电容值:一个不用外围电路的简易触摸传感器

[复制链接]
发表于 2013-2-2 13:24:10 | 显示全部楼层 |阅读模式
Arduino除了接受数字端口的数字信号,唯一能检测的模拟物理量就是电压。任何模拟传感器的检测值几乎都要通过相关电路转化成电压值,再输入arduino的模拟端口进行模数转换。电容值就需要相对更复杂和昂贵的电路转化为电压值,才能被Arduino检测,而对很多物理过程的检测,都可以很方便可靠地通过来检测电容值来实现,其中最常用的地方就是触摸传感器。风靡一时的MaKey MaKey就是个例子。这里介绍一个除了一段导线和一个端口,不需要任何元器件的电容检测方法。

这个方法的思路是,首先把一个数字端口设成低电位,并打开arduino的内部上拉电阻,开始计算这个端口到达高电位所需要的时间。而这个时间与此端口的对地电容值有关,电容越大,时间越长。在硬件上只需要在一个端口上连一根导线即可。用手指触摸这段导线的裸露端,就会导致电容变化,arduino可以通过上述方法检测这个变化。如果要增加灵敏度,可以在导线上连一片锡箔。为防止你手上有强静电击穿芯片,可以在锡箔上盖一薄层绝缘纸。

使用的代码如下。你可以方便地把它用到你的项目里。程序下载运行后,用手指触摸接在8号口的导线,就可以点亮9号口的led,手指离开,led熄灭。这个图上用的是板子上的13号灯。



[pre lang="arduino" line="1" file="touch_sensor.ino"]int ledPin = 9;
int capval;
void setup()
{
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Serial.println("Touch senser");
}

void loop ()
{
digitalWrite(ledPin,LOW);
capval = readCapacitivePin(8);
Serial.println(capval, DEC);
if (capval > 2) {
// turn LED on:
digitalWrite(ledPin, HIGH);
delay(10);
}
}

uint8_t readCapacitivePin(int pinToMeasure) {
// Variables used to translate from Arduino to AVR pin naming
volatile uint8_t* port;
volatile uint8_t* ddr;
volatile uint8_t* pin;
// Here we translate the input pin number from
// Arduino pin number to the AVR PORT, PIN, DDR,
// and which bit of those registers we care about.
byte bitmask;
port = portOutputRegister(digitalPinToPort(pinToMeasure));
ddr = portModeRegister(digitalPinToPort(pinToMeasure));
bitmask = digitalPinToBitMask(pinToMeasure);
pin = portInputRegister(digitalPinToPort(pinToMeasure));
// Discharge the pin first by setting it low and output
*port &= ~(bitmask);
*ddr |= bitmask;
delay(1);
// Make the pin an input with the internal pull-up on
*ddr &= ~(bitmask);
*port |= bitmask;

// Now see how long the pin to get pulled up. This manual unrolling of the loop
// decreases the number of hardware cycles between each read of the pin,
// thus increasing sensitivity.
uint8_t cycles = 17;
if (*pin & bitmask) { cycles = 0;}
else if (*pin & bitmask) { cycles = 1;}
else if (*pin & bitmask) { cycles = 2;}
else if (*pin & bitmask) { cycles = 3;}
else if (*pin & bitmask) { cycles = 4;}
else if (*pin & bitmask) { cycles = 5;}
else if (*pin & bitmask) { cycles = 6;}
else if (*pin & bitmask) { cycles = 7;}
else if (*pin & bitmask) { cycles = 8;}
else if (*pin & bitmask) { cycles = 9;}
else if (*pin & bitmask) { cycles = 10;}
else if (*pin & bitmask) { cycles = 11;}
else if (*pin & bitmask) { cycles = 12;}
else if (*pin & bitmask) { cycles = 13;}
else if (*pin & bitmask) { cycles = 14;}
else if (*pin & bitmask) { cycles = 15;}
else if (*pin & bitmask) { cycles = 16;}

// Discharge the pin again by setting it low and output
// It's important to leave the pins low if you want to
// be able to touch more than 1 sensor at a time - if
// the sensor is left pulled high, when you touch
// two sensors, your body will transfer the charge between
// sensors.
*port &= ~(bitmask);
*ddr |= bitmask;

return cycles;
}
[/code]

这个主意不是我的原创,readCapacitivePin函数来自官网playground,我写了setup和loop来示范它的用法。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

 楼主| 发表于 2013-2-2 13:46:12 | 显示全部楼层
本帖最后由 春泥蛋炒饭 于 2013-2-2 13:51 编辑

刚刚看到Ansifa老大的贴:http://www.geek-workshop.com/for ... thread&tid=1192 用了电阻检测。
本帖目的很相似,可以作为arduino自己的输入来使用,只是检测原理是电容变化,可以不接触手指。
回复 支持 反对

使用道具 举报

发表于 2013-2-3 13:50:38 | 显示全部楼层
看到立即测试了一下好像触摸灵敏度并不是很高,和电阻式的差不多。不过好处是不用AD转换就能用。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-2-3 16:32:25 | 显示全部楼层
Ansifa 发表于 2013-2-3 13:50
看到立即测试了一下好像触摸灵敏度并不是很高,和电阻式的差不多。不过好处是不用AD转换就能用。

如果需要更灵敏,可以提高cycles 数值,还有个有效的办法是把导线接到一个面积大的导体(比如一张锡箔)上,这样可以明显增加灵敏度,还可以覆盖绝缘层防止手指静电击穿芯片。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-10 02:22 , Processed in 0.053675 second(s), 21 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表