![](upload/erji2.jpg)
英文原文地址https://learn.sparkfun.com/tutorials/mpr121-hookup-guide
MPR121QR2 是一款电容式触摸传感器控制器,可以非常轻松地将电容式触摸感应集成到您的项目中。它通过I 2 C 进行通信,并通过测量十二个电极点的电容来工作。当物体靠近电极连接器时,测得的电容会发生变化。这向 MPR121 发出信号,表明某物触及了“按钮”。该 IC 还能够驱动电极引脚 4 到 11 上的 LED 或基本 GPIO 功能,为您设置项目提供了很大的自由。传感器的工作电压为 1.6V 至 3.3V。该传感器不是很耗电,每 16 毫秒采样时仅消耗约 29 µA。
材料
要完成本教程,您将需要 MPR121 传感器的三个版本之一:
您还需要一个烙铁、一些连接线和一个能够进行 I 2 C 通信的微控制器。对于我们的示例,我们将使用 Arduino Uno。您还需要某种材料来充当电容感应表面(也称为电极,不要与字符Electrode混淆。通常,铝箔效果很好。但是,您也可以使用硬币、导电涂料,或铜带。
推荐阅读
MPR121 非常容易上手,尤其是示例代码。但是,如果您以前没有使用过 Arduino 或不熟悉 I 2 C 通信,您应该查看下面的教程。
电容式触摸传感器分线板
该SparkFun电容式触摸传感器接口板是最通用的三个MPR121产品的选择。您可以将它连接到您想要的任何类型的电极上,而且由于它是一个简单的分线板,没有它喜欢的特定微控制器占用空间。
SparkFun 电容式触摸传感器突破 - MPR121
SEN-09695
退休
分线板有 4 个引脚,至少需要连接到您的微控制器才能进行通信:电源线和 I 2 C 线。但是,对于我们的示例,我们还将连接 IRQ 引脚以更轻松地检测其中一个电极的变化。
连接
MPR121 Breakout → Arduino Uno
3.3V → 3.3V
SCL → A5
SDA → A4
GND→GND
IRQ → D2
您还需要将电极/LED 引脚连接到您之前选择的电极材料。您需要确保材料和电路板之间有良好、牢固的连接,因此请确保彻底焊接连接。
查看下面的弗里茨图,了解您的连接应该是什么样子。黄色方块代表您决定用于电极的任何材料。
与分线板沟通
要与您的分线板通信,您需要在此处以 zip 文件形式提供 Arduino 草图。或者,您还可以在GitHub上找到用于使用分线板的最新固件。让我们看一看,看看代码到底在做什么。
复制代码 #include "mpr121.h" #include <Wire.h> int irqpin = 2; // Digital 2 boolean touchStates[12]; //to keep track of the previous touch states
在代码的第一部分中,初始化了 MPR121 库和 Wire 库。Wire 库使 I 2 C 通信易于在 Arduino 上使用。该草图还将数字引脚 2 定义为 IRQ 引脚连接,并创建布尔变量 touchStates 的 12 个实例。
对于代码的第二部分,我们将 定义irqpin
为 INPUT,告诉 Arduino 监视通过该引脚传入的数字信号。串行通信也以 9600 bps 以及 Wire 和 mpr121 库开始。
复制代码 void setup(){ pinMode(irqpin, INPUT); digitalWrite(irqpin, HIGH); //enable pullup resistor Serial.begin(9600); Wire.begin(); mpr121_setup(); }
代码的主循环非常简单,因为它只调用了一个函数。
复制代码 void loop(){ readTouchInputs(); }
该功能实际上在代码的下一部分中描述。Arduino 在第一部分向传感器请求电极状态,并为传感器定义了最低有效位和最高有效位。
复制代码void readTouchInputs(){ if(!checkInterrupt()){ //read the touch state from the MPR121 Wire.requestFrom(0x5A,2); byte LSB = Wire.read(); byte MSB = Wire.read(); uint16_t touched = ((MSB << 8) | LSB); //16bits that make up the touch states for (int i=0; i < 12; i++){ // Check what electrodes were pressed if(touched & (1<<i)){ if(touchStates[i] == 0){ //pin i was just touched Serial.print("pin "); Serial.print(i); Serial.println(" was just touched"); }else if(touchStates[i] == 1){ //pin i is still being touched } touchStates[i] = 1; }else{ if(touchStates[i] == 1){ Serial.print("pin "); Serial.print(i); Serial.println(" is no longer being touched"); //pin i is no longer being touched } touchStates[i] = 0; } } }}
Arduino 扫描每个电极并在电极被触发时通过串行打印出一条消息。一旦不再接触电极,Arduino 就会打印出一条消息。
代码的最后一个主要部分定义了每个电极的阈值。每个电极必须有一个触摸阈值和一个释放阈值,以便 Arduino 比较电极的当前状态。
复制代码void mpr121_setup(void){ set_register(0x5A, ELE_CFG, 0x00); // Section A - Controls filtering when data is > baseline. set_register(0x5A, MHD_R, 0x01); set_register(0x5A, NHD_R, 0x01); set_register(0x5A, NCL_R, 0x00); set_register(0x5A, FDL_R, 0x00); // Section B - Controls filtering when data is < baseline. set_register(0x5A, MHD_F, 0x01); set_register(0x5A, NHD_F, 0x01); set_register(0x5A, NCL_F, 0xFF); set_register(0x5A, FDL_F, 0x02); // Section C - Sets touch and release thresholds for each electrode set_register(0x5A, ELE0_T, TOU_THRESH); set_register(0x5A, ELE0_R, REL_THRESH); set_register(0x5A, ELE1_T, TOU_THRESH); set_register(0x5A, ELE1_R, REL_THRESH); set_register(0x5A, ELE2_T, TOU_THRESH); set_register(0x5A, ELE2_R, REL_THRESH); set_register(0x5A, ELE3_T, TOU_THRESH); set_register(0x5A, ELE3_R, REL_THRESH); set_register(0x5A, ELE4_T, TOU_THRESH); set_register(0x5A, ELE4_R, REL_THRESH); set_register(0x5A, ELE5_T, TOU_THRESH); set_register(0x5A, ELE5_R, REL_THRESH); set_register(0x5A, ELE6_T, TOU_THRESH); set_register(0x5A, ELE6_R, REL_THRESH); set_register(0x5A, ELE7_T, TOU_THRESH); set_register(0x5A, ELE7_R, REL_THRESH); set_register(0x5A, ELE8_T, TOU_THRESH); set_register(0x5A, ELE8_R, REL_THRESH); set_register(0x5A, ELE9_T, TOU_THRESH); set_register(0x5A, ELE9_R, REL_THRESH); set_register(0x5A, ELE10_T, TOU_THRESH); set_register(0x5A, ELE10_R, REL_THRESH); set_register(0x5A, ELE11_T, TOU_THRESH); set_register(0x5A, ELE11_R, REL_THRESH); // Section D // Set the Filter Configuration // Set ESI2 set_register(0x5A, FIL_CFG, 0x04); // Section E // Electrode Configuration // Set ELE_CFG to 0x00 to return to standby mode set_register(0x5A, ELE_CFG, 0x0C); // Enables all 12 Electrodes // Section F // Enable Auto Config and auto Reconfig /*set_register(0x5A, ATO_CFG0, 0x0B); set_register(0x5A, ATO_CFGU, 0xC9); // USL = (Vdd-0.7)/vdd*256 = 0xC9 @3.3V set_register(0x5A, ATO_CFGL, 0x82); // LSL = 0.65*USL = 0x82 @3.3V set_register(0x5A, ATO_CFGT, 0xB5);*/ // Target = 0.9*USL = 0xB5 @3.3V set_register(0x5A, ELE_CFG, 0x0C);}
它看起来像很多代码,但它只是重复为每个电极引脚设置阈值的过程。
示例草图中的最后两个函数只是检查 的状态irqpin
以确定 IC 是否发出电极已被触摸的信号。最后一个函数set_register
只是通过 Wire 库中的标准步骤运行 Arduino,将寄存器写入 IC。
复制代码boolean checkInterrupt(void){ return digitalRead(irqpin);}void set_register(int address, unsigned char r, unsigned char v){ Wire.beginTransmission(address); Wire.write(r); Wire.write(v); Wire.endTransmission();}
现在您对代码有了基本的了解,让我们开始阅读数据。从您之前下载的文件中打开草图,并将其上传到您的 Arduino。上传后,在 Arduino IDE 中打开串行监视器。如果您按下任何电极或释放任何电极,您应该开始看到 Arduino 打印出句子。
其他代码参考:
#include "mpr121.h"
#include <Wire.h>
#define SENSORS 13
#define TOU_THRESH 0x1F
#define REL_THRESH 0x1A
#define PROX_THRESH 0x3f
#define PREL_THRESH 0x3c
// variables: capacitive sensing
bool touchStates[SENSORS]; // holds the current touch/prox state of all sensors
bool activeSensors[SENSORS] = {1,1,1,1,1,1,1,1,1,1,1,1,1}; // holds which sensors are active (0=inactive, 1=active)
bool newData = false; // flag that is set to true when new data is available from capacitive sensor
int irqpin = 2; // pin that connects to notifies when data is available from capacitive sensor
void setup(){
// attach interrupt to pin - interrupt 1 is on pin 2 of the arduino (confusing I know)
attachInterrupt(0, dataAvailable, FALLING);
// set-up the Serial and I2C/Wire connections
Serial.begin(9600);
Wire.begin();
// set the registers on the capacitive sensing IC
setupCapacitiveRegisters();
}
void loop(){
readCapacitiveSensor();
}
/**
* dataAvailable Callback method that runs whenever new data becomes available on from the capacitive sensor.
* This method was attached to the interrupt on pin 2, and is called whenever that pins goes low.
*/
void dataAvailable() {
newData = true;
}
/**
* readCapacitiveSensor Reads the capacitive sensor values from the MP121 IC. It makes a request to
* the sensor chip via the I2C/Wire connection, and then parses the sensor values which are stored on
* the first 13 bits of the 16-bit response msg.
*/
void readCapacitiveSensor(){
if(newData){
Serial.println("yes");
//read the touch state from the MPR121
Wire.requestFrom(0x5A,2);
byte tLSB = Wire.read();
byte tMSB = Wire.read();
uint16_t touched = ((tMSB << 8) | tLSB); //16bits that make up the touch states
for (int i = 0; i < SENSORS; i++){ // Check what electrodes were pressed
if (activeSensors[i] == 0) continue;
char sensor_id [] = {'\0','\0','\0'};
switch (i) {
case 12:
sensor_id[0] = 'P';
break;
default:
if (i < 10) {
sensor_id[0] = char( i+48 );
}
else if (i < 12) {
sensor_id[0] = char('1');
sensor_id[1] = char( ( i % 10 ) + 48 );
}
}
if (sensor_id != '\0') {
// read the humidity level
// if current sensor was touched (check appropriate bit on touched var)
if(touched & (1<<i)){
// if current pin was not previously touched send a serial message
if(touchStates[i] == 0){
Serial.print(sensor_id);
Serial.print(":");
Serial.println("1");
}
touchStates[i] = 1;
} else {
// if current pin was just touched send serial message
if(touchStates[i] == 1){
Serial.print(sensor_id);
Serial.print(":");
Serial.println("0");
}
touchStates[i] = 0;
}
}
}
newData = false;
}
}
/**
* setupCapacitiveRegisters Updates all of configurations on the MP121 capacitive sensing IC. This includes
* setting levels for all filters, touch and proximity sensing activation and release thresholds, debounce,
* and auto-configurations options. At the end it activates all of the electrodes.
*/
void setupCapacitiveRegisters(){
set_register(0x5A, ELE_CFG, 0x00);
// Section A - filtering when data is > baseline.
// touch sensing
set_register(0x5A, MHD_R, 0x01);
set_register(0x5A, NHD_R, 0x01);
set_register(0x5A, NCL_R, 0x00);
set_register(0x5A, FDL_R, 0x00);
// prox sensing
set_register(0x5A, PROX_MHDR, 0xFF);
set_register(0x5A, PROX_NHDAR, 0xFF);
set_register(0x5A, PROX_NCLR, 0x00);
set_register(0x5A, PROX_FDLR, 0x00);
// Section B - filtering when data is < baseline.
// touch sensing
set_register(0x5A, MHD_F, 0x01);
set_register(0x5A, NHD_F, 0x01);
set_register(0x5A, NCL_F, 0xFF);
set_register(0x5A, FDL_F, 0x02);
// prox sensing
set_register(0x5A, PROX_MHDF, 0x01);
set_register(0x5A, PROX_NHDAF, 0x01);
set_register(0x5A, PROX_NCLF, 0xFF);
set_register(0x5A, PROX_NDLF, 0xFF);
// Section C - Sets touch and release thresholds for each electrode
set_register(0x5A, ELE0_T, TOU_THRESH);
set_register(0x5A, ELE0_R, REL_THRESH);
set_register(0x5A, ELE1_T, TOU_THRESH);
set_register(0x5A, ELE1_R, REL_THRESH);
set_register(0x5A, ELE2_T, TOU_THRESH);
set_register(0x5A, ELE2_R, REL_THRESH);
set_register(0x5A, ELE3_T, TOU_THRESH);
set_register(0x5A, ELE3_R, REL_THRESH);
set_register(0x5A, ELE4_T, TOU_THRESH);
set_register(0x5A, ELE4_R, REL_THRESH);
set_register(0x5A, ELE5_T, TOU_THRESH);
set_register(0x5A, ELE5_R, REL_THRESH);
set_register(0x5A, ELE6_T, TOU_THRESH);
set_register(0x5A, ELE6_R, REL_THRESH);
set_register(0x5A, ELE7_T, TOU_THRESH);
set_register(0x5A, ELE7_R, REL_THRESH);
set_register(0x5A, ELE8_T, TOU_THRESH);
set_register(0x5A, ELE8_R, REL_THRESH);
set_register(0x5A, ELE9_T, TOU_THRESH);
set_register(0x5A, ELE9_R, REL_THRESH);
set_register(0x5A, ELE10_T, TOU_THRESH);
set_register(0x5A, ELE10_R, REL_THRESH);
set_register(0x5A, ELE11_T, TOU_THRESH);
set_register(0x5A, ELE11_R, REL_THRESH);
// Section D - Set the touch filter Configuration
set_register(0x5A, FIL_CFG, 0x04);
// Section E - Set proximity sensing threshold and release
set_register(0x5A, PRO_T, PROX_THRESH); // sets the proximity sensor threshold
set_register(0x5A, PRO_R, PREL_THRESH); // sets the proximity sensor release
// Section F - Set proximity sensor debounce
set_register(0x59, PROX_DEB, 0x50); // PROX debounce
// Section G - Set Auto Config and Auto Reconfig for prox sensing
set_register(0x5A, ATO_CFGU, 0xC9); // USL = (Vdd-0.7)/vdd*256 = 0xC9 @3.3V
set_register(0x5A, ATO_CFGL, 0x82); // LSL = 0.65*USL = 0x82 @3.3V
set_register(0x5A, ATO_CFGT, 0xB5); // Target = 0.9*USL = 0xB5 @3.3V
set_register(0x5A, ATO_CFG0, 0x0B);
// Section H - Start listening to all electrodes and the proximity sensor
set_register(0x5A, ELE_CFG, 0x3C);
}
/**
* set_register Sets a register on a device connected via I2C. It accepts the device's address,
* register location, and the register value.
* @param address The address of the I2C device
* @param r The register's address on the I2C device
* @param v The new value for the register
*/
void set_register(int address, unsigned char r, unsigned char v){
Wire.beginTransmission(address);
Wire.write(r);
Wire.write(v);
Wire.endTransmission();
}