MPR121 是一款触摸传感器芯片,原理是通过检测电容变化来判断当前是否有触摸(接近)。
主要电器特性如下【参考1】:
1. 工作电压1.71-3.6v(芯片工作电压)
2. 通讯接口为 I2C
3. 12个检测端口
4. 带有1个 IRQ端口
我是在Taobao购买的模块,价格是16元【参考3】。经过搜索,这是仿sparkfun的,更多资料可以在【参考2】看到。
模块长得下面这样,有一个降压芯片,看起来可以直接使用 5V 供电。上面有12个口,可以接12个触摸按钮。IRQ 的作用是发出中断通知上面有触摸。ADD是芯片的I2C地址选择,接GND VDD SDA或者 SCL 地址分别是 0x5A 0x5B 0x5C 和 0x5D【来自参考4】。
图片来自【参考2】
下面的代码可以正常工作(卖家的例程,有一些修改可以在 1.6.0 上编译通过)
#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(); }
运行结果:
完整的代码下载
参考:
1. http://wenku.baidu.com/link?url=77EtEpflHOBF9LmqwOvIwe5ONZ6I548h4BcBk4Ep1XWVO_RVDj9fycwoku44RENseV48lzvnrnDasY3UAMHsBuuU7yVdxFsAfxq-zbDiEhy MPR121中文数据手册
2. https://learn.sparkfun.com/tutorials/mpr121-hookup-guide
3. https://item.taobao.com/item.htm?spm=a1z09.2.0.0.kpoNRc&id=19968128319&_u=pkf8s90f4c
4. MPR121 DataSheet
===============================================================================
额外说一下这个传感器在 Pro Micro 上的连接方法:
1. Pro Micro 的中断:“The Pro Micro has five external interrupts, which allow you to instantly trigger a function when a pin goes either high or low (or both). If you attach an interrupt to an interrupt-enabled pin, you’ll need to know the specific interrupt that pin triggers: pin 3 maps to interrupt 0, pin 2 is interrupt 1, pin 0 is interrupt 2, pin 1 is interrupt 3, and pin 7 is interrupt 4.”
推荐 使用 Pin7-Interrupt 4
2. Pro Micro Pin2- SDA Pin3-SCL