Skip to content

Commit cdf3e7f

Browse files
committed
IO: Add MPR121 capacitive touch example
1 parent 5e2a636 commit cdf3e7f

File tree

3 files changed

+138
-0
lines changed

3 files changed

+138
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import processing.io.I2C;
2+
3+
// MPR121 is a capacitive-touch sensor controller with 12 channels
4+
// datasheet: https://www.nxp.com/docs/en/data-sheet/MPR121.pdf
5+
6+
class MPR121 extends I2C {
7+
int address;
8+
int touched;
9+
10+
// registers used (there are more)
11+
static final int EFD0LB = 0x04; // ELE0 Electrode Filtered Data LSB
12+
static final int E0TTH = 0x41; // ELE0 Touch Threshold
13+
static final int E0RTH = 0x42; // ELE0 Release Threshold
14+
static final int E0BV = 0x1e; // ELE0 Baseline Value
15+
static final int MHDR = 0x2b; // MHD Rising
16+
static final int NHDR = 0x2c; // NHD Amount Rising
17+
static final int NCLR = 0x2d; // NCL Rising
18+
static final int MHDF = 0x2f; // MHD Falling
19+
static final int NHDF = 0x30; // NHD Amount Falling
20+
static final int NCLF = 0x31; // NCL Falling
21+
static final int CDT = 0x5d; // Filter/Global CDT Configuration
22+
static final int ECR = 0x5e; // Electrode Configuration
23+
static final int SRST = 0x80; // Soft Reset
24+
25+
// there can be more than one device connected to the bus
26+
// as long as they have different addresses
27+
// possible addresses: 0x5a (default) - 0x5d
28+
MPR121(String dev, int address) {
29+
super(dev);
30+
this.address = address;
31+
reset();
32+
}
33+
34+
void update() {
35+
beginTransmission(address);
36+
write(0x00);
37+
byte[] in = read(2);
38+
// & 0xff makes sure the byte is not interpreted as a negative value
39+
touched = (in[1] & 0xff) << 8 | (in[0] & 0xff);
40+
}
41+
42+
boolean touched(int channel) {
43+
if (channel < 0 || 11 < channel) {
44+
return false;
45+
}
46+
if ((touched & (1 << channel)) != 0) {
47+
return true;
48+
} else {
49+
return false;
50+
}
51+
}
52+
53+
void threshold(int touch, int release) {
54+
for (int i=0; i < 12; i++) {
55+
threshold(touch, release, i);
56+
}
57+
}
58+
59+
void threshold(int touch, int release, int channel) {
60+
if (channel < 0 || 11 < channel) {
61+
return;
62+
}
63+
touch = constrain(touch, 0, 255);
64+
release = constrain(release, 0, 255);
65+
writeRegister(E0TTH + 2*channel, touch);
66+
writeRegister(E0RTH + 2*channel, release);
67+
}
68+
69+
int analogRead(int channel) {
70+
if (channel < 0 || 11 < channel) {
71+
return 0;
72+
}
73+
beginTransmission(address);
74+
write(EFD0LB + 2*channel);
75+
byte[] in = read(2);
76+
return (in[1] & 0xff) << 8 | (in[0] & 0xff);
77+
}
78+
79+
int analogReadBaseline(int channel) {
80+
if (channel < 0 || 11 < channel) {
81+
return 0;
82+
}
83+
beginTransmission(address);
84+
write(E0BV + channel);
85+
byte[] in = read(1);
86+
return (in[0] & 0xff) << 2;
87+
}
88+
89+
void reset() {
90+
writeRegister(SRST, 0x63);
91+
delay(1);
92+
threshold(12, 6);
93+
// set baseline filtering control registers (see p. 12)
94+
writeRegister(MHDR, 0x01);
95+
writeRegister(NHDR, 0x01);
96+
writeRegister(NCLR, 0x0e);
97+
writeRegister(MHDF, 0x01);
98+
writeRegister(NHDF, 0x05);
99+
writeRegister(NCLF, 0x01);
100+
// change sample interval to 1ms period from default 16ms
101+
writeRegister(CDT, 0x20);
102+
// start sampling
103+
writeRegister(ECR, 0x8f);
104+
}
105+
106+
void writeRegister(int register, int value) {
107+
beginTransmission(address);
108+
write(register);
109+
write(value);
110+
endTransmission();
111+
}
112+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import processing.io.*;
2+
MPR121 touch;
3+
4+
// see setup.png in the sketch folder for wiring details
5+
6+
void setup() {
7+
size(600, 200);
8+
//printArray(I2C.list());
9+
touch = new MPR121("i2c-1", 0x5a);
10+
}
11+
12+
void draw() {
13+
background(204);
14+
noStroke();
15+
16+
touch.update();
17+
18+
for (int i=0; i < 12; i++) {
19+
if (touch.touched(i)) {
20+
fill(255, 0, 0);
21+
} else {
22+
fill(255, 255, 255);
23+
}
24+
ellipse((width/12) * (i+0.5), height/2, 20, 20);
25+
}
26+
}
178 KB
Loading

0 commit comments

Comments
 (0)