zoukankan      html  css  js  c++  java
  • 用arduino直接检测电容值:一个不用外围电路的简易触摸传感器

    原文链接:http://www.geek-workshop.com/thread-3335-1-1.html


    Arduino除了接受数字端口的数字信号,唯一能检测的模拟物理量就是电压。任何模拟传感器的检测值几乎都要通过相关电路转化成电压值,再输入 arduino的模拟端口进行模数转换。电容值就需要相对更复杂和昂贵的电路转化为电压值,才能被Arduino检测,而对很多物理过程的检测,都可以很 方便可靠地通过来检测电容值来实现,其中最常用的地方就是触摸传感器。风靡一时的MaKey MaKey就是个例子。这里介绍一个除了一段导线和一个端口,不需要任何元器件的电容检测方法。 这个方法的思路是,首先把一个数字端口设成低电位,并打开arduino的内部上拉电阻,开始计算这个端口到达高电位所需要的时间。而这个时间与此端口的 对地电容值有关,电容越大,时间越长。在硬件上只需要在一个端口上连一根导线即可。用手指触摸这段导线的裸露端,就会导致电容变化,arduino可以通 过上述方法检测这个变化。如果要增加灵敏度,可以在导线上连一片锡箔。为防止你手上有强静电击穿芯片,可以在锡箔上盖一薄层绝缘纸。
    使用的代码如下。你可以方便地把它用到你的项目里。程序下载运行后,用手指触摸接在8号口的导线,就可以点亮9号口的led,手指离开,led熄灭。这个图上用的是板子上的13号灯。

    View Code
     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来示范它的用法。

  • 相关阅读:
    一天摄入多少蛋白质比较合理?
    给函数添加元数据(python)
    反转链表(C++实现)
    删除链表的中间节点(C++实现)
    在双向链表中删除倒数第K个链表节点(C++实现)
    在单链表中删除倒数第K个节点(C++实现)
    二叉树的创建及遍历(递归和非递归C++实现)
    删除排序数组中的重复项(C++实现)
    打印两个有序链表的公共部分(C++实现)
    用一个栈实现另一个栈的排序(C++实现)
  • 原文地址:https://www.cnblogs.com/catmelo/p/2913576.html
Copyright © 2011-2022 走看看