﻿Hi there, 
This video is about an interesting chip, the MPR121 which sports
the impressive title of a Proximity 
Capacitive Touch Sensor Controller. I am investigating this
chip to provide a button interface for the 
Pimoroni Enviro+ board for the Raspberry Pi. 
If you recall from my previous videos – links in the description-
the Enviro+ board covers the complete 
IO connector of the Raspberry PI, you can’t access spare GPIO
pins but the I2C bus is still accessible. 
The Enviro+ board has lots of environmental sensors but the only
one that is really suitable for use 
to trigger an action like a button is the proximity detector,
which uses reflected infrared light. 
One button would make a pretty horrible user experience, so can
the MPR121 come to the rescue? 
I got the idea to try out the MPR121 when browsing through the Adafruit
website while searching for a 
solution for my problem. 
As you can see the board has an I2c interface on one side and 12 sensor
connections on the other. The 
price on the Adafruit website was 7.95 US$ which was pretty much
the same in British Pounds, plus shipping 
when you buy from one of the Adafruit distributors. 
And what do you get for that money? 
The MPR121 chip on a breakout board of course but since that chip
is for max. 3.3V supply voltages, Adafruit 
made their board 5V compatible by adding a 5V to 3.3V regulator
and 2 IO converters for the SDA and SCL 
signals. 
Oh, and the board has proper holes for mounting. 
I mention all this because this is the board I actually bought
from Ebay for 2.89 delivered within 3 
days of ordering. You get the breakout board with MPR121 but that
is it. No 5V compatibility or mounting 
holes. Well, for the Enviro+, 3.3V are available so 5V compatibility
is not an issue and I decided I’ll 
figure something out for mounting it eventually, if I even decide
to use it. 
Like the Adafruit board, this one comes with pin-headers to be
soldered in. Everything is clearly labelled 
and pretty self-explanatory. The black solder mask makes it
a bit tricky to check traces, because I am 
looking where I can drill the missing mounting holes 
It looks as if there is space on the left side, above and below the
6 pins for the I2C interface. On 
the top you can just make out one via which may only a redundant
one for the ground plane but with careful 
drilling it is just possible to avoid the via. 
The header accessible on the Enviro+ only has 3.3V, GND, SCL and
SDA so the IRQ pin on the MPR121 will 
not be used. The ADD pin allows to select 4 different I2C addresses
depending on whether it is open or 
tied to ground or to SDA or SCL. 
I will leave it open which selects hex 0x5a as address for the MPR121.
So what is the MPR121. For this and the next couple of images, I
raided a nice presentation by Freescale, 
the link to it and other documents are in the description. 
So, in a nutshell, this chip has12 electrodes interfaces each
of which can be a capacitive sensor but 
can also be configured as standard GPIO or to drive a LED but of
course not at the same time. 
There is a 13th virtual electrode which is based selectably on
on the effects of the first 2, first 4 
or all 12 of the individual electrodes together. The idea is that
this large virtual electrode can be 
used to trigger something if you just get into the proximity of
the touch sensor area 
Each of the 12 sensors forms a capacitor, one plate being the electrode
and the other whatever is in 
the proximity, for example air or your finger. It is important
to note that you don’t need to make physical 
contact with the sensor. It is designed to works just by proximity
and through isolating material, for 
example a printed circuit board. 
For each sensor, the chip goes through these 4 steps. Ensure the
electrode is discharged by grounding 
it, then charge it for a selectable time, then measure the voltage
and the discharge it back to 0. By 
default, it repeats this cycle every 16 ms. 
Without touch, the voltage, and therefore the capacity measured
for each sensor depends on a lot of things, 
like the size of the electrodes, the di-electric material used
to isolate them from each other and the 
user, wiring, and so on. So with differently shaped electrodes,
the “at rest” value will be somewhat 
different for each sensor. This at-rest value is referred to
as the electrode’s baseline. In addition 
there are changes in capacitance based on static, humitity,
temperature, and so on, so the baseline changes 
all the time. 
The MPR121 implements a rather complex and fully configurable
mechanism to automatically adjust each 
electrode baseline for these effects, while suppressing changes
caused by noise. This is shown in the 
upper graph and there are several application notes available
explaining the method and the effect of 
the adjustable parameters, like NCL, MHD, and so on 
Touches are detected as drops in the baseline that exceed configurable
thresholds. This is shown in the 
second graph. 
But the binary touched/not touched data is not the only thing
an application can read from the MPR121. 
The filtered ADC values for each electrode are accessible as
10 bit values on the I2C. This allows, for 
example, calculating a 2D position as shown here. 
The red E0 to E3 represents 4 electrodes arranged in a square.
If your finger would be at the location 
of the green, yellow or orange circle, the effects on the ADC values
would allow you to approximate these 
positions. 
Note that I had to redraw the bars in this diagram because for whatever
reason the original presentation 
shows the effect of touch on the ADC count reversed from what I
observed in my experiments. 
I would also like to point out that this is still highly idealized.
It doesn’t take into account that 
the baseline no-touch value is likely slightly different for
each sensor and all baselines drift, potentially 
slightly differently over time. Further the actual effect is
much smaller, I my experiments, for example, 
the baseline was around 730 and in the yellow E2 case dropped to
only around 550. 
So, yes interpolation is possible to program but not that easy,
accurate and reliable 
Some ideas on shapes of electrodes for different purposes. I
was particularly intrigued by the linear 
slider, 
especially the one on the left and gave that a try. 
The white sheet is normal printer paper laminated because that
is what I would use for a front plate. 
The electrodes on the back are kitchen foil. Unfortunately I
did not think of making a video of the underside 
but you can just make out that the two upper electrodes form a slider
and the two lower ones go to simple 
rectangular buttons. 
Vou see that rhe two squares on the Enviro+ display show the button
status 
While the colour of the circle is interpolated from the ADC values
of the two slider electrodes 
- 
It does sort of work. 
Of course, like with the slider, nothing stops you from touching
multiple sensors simultaneously and 
the MPR121 responds as expected. By the way, the white numbers
on the display indicate which electrode 
was touched. 
The electrodes are hard to see so I drew their outlines on a piece
of paper. It should be possible to 
sense touch even through the additional layer of paper. 
Yes buttons .. 
and the slider work as before. 
You can touch electrodes directly like here where I touch the
pins of the board and it is still recognized. 
When you start writing software for the MPR121 and look at the
data sheet, you get a shock by the massive 
register footprint: No less that 128 registers are accessible
from the I2C bus and about half of them 
need to be configured is some way. The reason for that explosion
is that everything, from thresholds, 
to noise counts and filters needs to be setup and configured for
each of the 12 actual sensors and for 
the virtual 13th sensor as well. 
There is a MPR121 driver available from Adafruit but I did not
like it because it seems to be more like 
a proof of concept and is very limited in what it allows the user
to configure. So, I rolled my own driver 
which you can download from my Github page. 
I also want to quickly mention that the MPR121 data sheet is definitely
not enough to program the chip. 
While it contains the register map and bit definitions it does
not explain why what values need to be 
set and how they all depend on each other. 
It turns out that this essential information is sprinkled over
at least 7 separate application notes 
you need to first find and then download in addition to the data
sheet. 
As a public service, here is a list and links of the important ones.
Especially the last one in this list is absolutely crucial for
configuration. Amongst other things it 
explains how to do some kind of auto configuration that relieves
you from manually calculating and setting 
some of the most fundamental configuration values. 
You find this list in the description of the video 
Here is a quick view of the program on the Enviro+ for the squares
and the circle. I am just commenting 
on the MPR121 specifics, and not on how to draw things on the LCD.
The driver is instantiated with the chips operating voltage
of 3.3V and the I2C bus address. The voltage 
is needed for the autoconfig operation.. 
and the next line is to check the out-of-range register which
should be all zeros if autoconfig succeeded. 
I have never seen it fail. 
The next line turns off proximity mode which is the virtual 13th
electrode since I am not using it in 
this test. 
In the while loop.. 
I am reading the touch status and all capacitance values in one
go by calling mpr121.Filtered. There 
are other functions in the driver that just report whether electrodes
are pressed or not, or to return 
capacitance values, but this one gives everything in one go,
as a snapshot so to say, which ensures that 
the values are consistent with each other. 
For convenience, I then convert the bits of the touch status into
an array of booleans and do the same 
with the electrode capacitance values. At the same time, I create
the string 
showing which electrode was touched. 
This bit here used the ratio of the capacitance of electrodes
0 and 1 to calculate a colour. 
The rest is very straight forward. 
Depending on the touch status, the program draws the circle and
rectangles and either filled or not. 
An that is basically all there is. Autoconfig and sensible defaults
make using the MPR121 very easy, 
but if you really need to, you can change the default configuration.
For future use in the enviro+ project, I used LibreOffice Draw
to design a front panel that looks like 
this. 
The blue part is the enviro+ board, with the dark blue showing
the locations of the LCD and other sensors. 
The brownish rectangles are the touch sensors. I am planning
to use copper foil instead of kitchen foil 
because that allows you to solder wires to it. 
You see that I am using all 12 electrodes of the MPR121. 
Electrodes 2 to 11 are simple buttons while electrodes 
0 and 1 are long bars. 
If I enable the button overlay … 
you can see that this creates 20 buttons. The idea is that touching
some buttons will straddle two electrodes 
and therefore cause two touches to be registered. 
For example, button 11 is recognized when button 1 
and 0 are both touched, 
button 2 and 0 gives 12, and so on. 
Theoretically I could have combined the both bars and gained
an extra button but I thought 20 will be 
probably enough. 
But how reliably is this method? I decided to do a mock-up test
first. 
My rather crude but to-scale mock-up of the drawing you just saw.
It is using self-adhesive copper foil 
and soldering the wires was no problem. What I did not think about
is that since this is the underside 
of the front panel, everything should have been mirrored but
for function testing that does not matter. 
I changed the program to just display the button number and I indicated
the centre of the buttons with 
a blue felt tip marker. In real life, the panel would of course
show printed buttons with labels instead. 
As you can see, the results are disappointing. Of course the direct
buttons are no problem, but the ones 
formed my the combination of 2 buttons are very hit and miss. 
The detection is very sensitive to minute differences in the
way and exact location of the touch. 
I think, as it stands, this is not suitable as a user interface.
Interestingly, the upper block worked slightly better, 
and since this has a shorter bar, it got me thinking that on the
relative large bar area below, 
the partial overlap of my finger causes only a relative minute
capacitance change. So, maybe those bars 
should be much thinner than the standard buttons? 
Alternatively, maybe I could improve the behaviour by reducing
the detection thresholds for the bars, 
to make them much more sensitive. 
Changing sensitivity is easy to try. I just added these 2 lines
to overwrite the standard configuration for all buttons. By
default the touch threshold is 12 and release 
6, but for the two bar-shaped electrodes 
I changed it to 6 and 3. 
This means a deviation of just 6 from the baseline value for the
bar electrodes is already sufficient 
to register as touch. 
- 
I think you’ll agree that with this simple configuration change
the behaviour is much better now but 
.. 
still not perfect. 
Depending on what functions these buttons will eventually have,
misinterpreted buttons could be an immensely 
frustrating user experience. Just imagine one does for example
SAVE and the other DELETE. 
So back to the drawing board. 
I decided to forgo the idea of the overlapping button as it is too
error prone and try this layout instead. 
If I enable the button overlay … 
you see that this creates 22 buttons. 
The idea here is that the big bar at the bottom is a shift key. Each
of the other 11 buttons has two 
functions. 
One that is reached by just touching it, and the other by first
touching shift and then the button. 
Lets see how that works in a test. 
I de-soldered all wires from the previous mock-up .. 
and onto the new layout in another corner. 
This time I did remember to mirror the button layout so that it
matches the design. 
One slight problem with the new mock-up is that the wires preventing
the panel from lying flat when reversed. 
In the real front panel, there will be holes drilled under each
button for the wires to pass through 
- 
As you would expect, touching the individual buttons works exactly
as it should. 
- 
To get to the 2nd function, the shift key needs to be pressed first
and of course this works just as 
well 
I think this method may be less elegant but is far less error prone
and I will probably use it for the 
actual Enviro+ project. But that is for a future video. 
For now, that’s it for this video. 
Thanks for watching. 
