I am using Sparkfun's MPR121 breakout board. How can I read the rising and falling values from the proximity sensor(s) as they change in response to the varying distance between a hand and the electrode? Sorry to be such a noob. Sample code can be found at http://www.sparkfun.com/products/9695 I have read through the data sheets here at Freescale. I would like to set up the mpr121 through an arduino UNO and the arduino IDE or the Processing IDE to read proximity via the electrode levels. The distance the hand is from the plate will determine the piece's reaction based on the values read from that electrode. For instance, as a test, the closer the hand is to the plate electrode the brighter an LED will light. I have done some experiments with existing code but all I can get a solid off or on of the LED. When I read from register 0x2a I get only values of about 760 or 761 depending on whether I am touching the electrode or not. Using the code referenced above I can light up individual LEDs attached to each of the electrodes from ele6~11 when a piece of foil is touched. I have tried writing to individual registers setting ele0 ~ 5 to proximity and begun to change touch and release levels but nothing seems to react differently The code I am using the code listed by John Lindblom that can be downloaded from the Sparkfun product page(link above). This level of pushing bytes to registers is entirely new to me as are these levels of data sheet. I am taking code apart and experimenting but am at a loss right now. Thanks for any help.
Disclaimer: I'm new to the MPR121 myself, and actually came here because I can't get the proximity function to even give me a switch response.
Having said that, are you sure you want to be reading 0x2A, the baseline register? If I'm reading the literature correctly, the baseline register is meant to reflect the nominal capacitance of the pad and should (hopefully) only vary slightly in response to environmental changes. A touch is considered to have occurred when the difference between this baseline and the filtered data exceeds some threshold. Have you tried reading the filtered data register at 0x1D and 0x1C combined? (And expect the data to go down during a touch event, not up?)
Let me know how it goes, and if you get a chance, see if you're getting a touch detection in register 0x03, bit 04.
John
Thanks John for your reply.
You are correct I was reading the the baseline just to see what was in there as to values. I had forgotten that while I looked at my last version. Thanks for pointing that out.
I had tried reading 0x1C and got some unreadiable so you are probably correct there as well.
I also just realized that analogue read would not be correct for the register information.... sorry.
Serial.println(analogRead(0x1c)); // SMH*** read eleprox raw data register
Can I concatenate the read from 0x1c and 0x1d to get a meaningful value of 10 bits? perhaps convert later to decimal?
I will try it tonight or tomorrow. I will also let you know what I find in register 0x3.
FWIW I am hacking the code on the Sparkfun site under their product http://www.sparkfun.com/products/9695
Steven
Steven,
Yes, by reading 0x1C alone, you're just getting the lower bits which will be pretty useless by themselves. I'm not familiar with the specifics of your environment, but something along the lines of:
uint16_t result;
result = mpr121Read(0x1D) & 0x0003;
result = (result << 8) | ( (uint16_t ) mpr121Read(0x1C) & 0x00FF);
might work. I'm using the Sparkfun board that includes the touch pads on the PCB, but with a different processor...but I'm not convinced that I even have the proximity function doing it's work, given that I'm not even getting a touch detection out of it. I'm thinking there may be more to the configuration of the function than is outlined in the app note.
John
JohnI am coding in arduino/processing/java with a "hint" of C.
I am getting the feeling that you are right about the data sheet not telling all. The prox function is either not be activated or it's being over ruled.
I looked at the register you asked about and there is no change.
On the other hand, the code you gave me fit right in. Oddly it will jump from 0 to 257 from touch to no touch on the electrode I've attached it to. No gradual change showing any proximity.
Interestingly to me is that if I have multiple electrodes attached to ele0 ~ 5 each value will jump when I touch a particular electrode. BUT not from 0 to 257 as I expected it would. The first will go from 0 to 4, next electrode 0- 8 then 0-16, 0- 32, etc until the last electrode is 0 - 514. If I touch any combination the value reads as the sum of those two wires or three wires or ... etc.
This make logical sense to me but not sure why I can't get it to read prox values.
Unless we are overriding it because of the filters? and touch release?
I have been running tests with Free scales sensor eval kit and software. It will sense proximity as an addition of all the electrodes added together and I can see the values changing on the graph for all and the prox electrode (the mythical #13).
So their software is capable of activating and reading it at any rate. but no code from them that I can find.
I will check the register you asked me about on their eval software when I can get a chance.
Steven
I'll pass on one 'gotcha' that I figured out last night. There's no reset pin on the MPR121, so if you're debugging without cycling power between tests, I think you'll need to put the MPR121 into standby mode (writing a 0 to the electrode configuration register) at the beginning of your initialization. I think some of my previous experiments were invalid because after the first run, all subsequent writes to the configuration registers were getting ignored. See the Quick Start guide, page 53. I think there must be an error in that description, however...I think " Run (when the value of the lower bit is non-zero)" should be "Run (when the value of the lower nibble is non-zero)" given that you could never enable an even number of electrodes otherwise.
I have proximity detection working...that is, I get an IRQ and a bit set in register 1 when my hand gets very close.
No luck with your problem, though, when I read the filtered data it seemed wrong and very binary to me...zero until I got so close that I triggered the interrupt at which point it jumped to 0x1000.
Hi John & Steven,
Sorry to resurrect an old thread, but was curious if either of you were able to get this to work? I'm also connecting the mpr121 to an arduino and no matter what register I try to read I seem to always get 0x00 and 0x01 (trying to read 0x04 and 0x05).
Just wanted to see if you had any luck.
Thanks in advance,
David
Hi guys,
The solution I found was to read the entire column and then use only the bits I need.
The example for the proximity detection:
unsigned int mpr121ReadProximity() {
byte rdata = 0xFF;
byte rdata1c = 0xFF;
byte rdata1d = 0xFF;
uint16_t result;
Wire.beginTransmission(0x5A);
Wire.write(0x1E);
Wire.endTransmission();
Wire.requestFrom(0x5A, 0x1E);
int i = 0;
for ( i = 0; i <= 0x1E; i++ ) {
if (Wire.available()) {
rdata = Wire.read();
if (i == 0x1C) {
rdata1c = rdata;
}
if (i == 0x1D) {
rdata1d = rdata;
}
}
}
result = rdata1d & 0x0003;
result = (result << 8) | ( (uint16_t)rdata1c & 0x00FF);
return result;
}
Cristian,
Thanks for the solution above. am now able to successfully read the electrode filtered data using the following code. I now want to read the baseline info that's in 0x1e-0x2a. I'd liek to do that so I can use them with the filtered data to check the threshold values I should be using. I thought I could just change the read address in this code fragment from 0x1e to 0x2b in order to read the next block of data.. i recognize that the baseline nums are 10 bits.. but only the 8 MSB are available so they need to be shifted.. but that did not work.. i get alternating big and small numbers..
Any idea how youd read the 13 baseline values ? Any ideas ? Thanks !
-jc
void dumpregs() {
byte rdata;
byte rdata1c;
byte rdata1d;
uint16_t result;
uint16_t raw[43];
uint16_t filtered[13];
uint16_t baseline[13];
uint16_t diff[13];
Wire.beginTransmission(0x5A);
Wire.write(0x1E);
Wire.endTransmission();
Wire.requestFrom(0x5A, 0x1E);
int i = 0;
int j=0;
for ( i = 0; i <= 0x1E; i++ ) {
if (Wire.available()) {
rdata = Wire.read();
if ((i >= 0x04) && (i % 2 == 0 )) {
rdata1c = rdata;
}
else if (i >= 0x04) {
rdata1d = rdata;
result = rdata1d & 0x0003;
filtered[j] = (result << 8) | ( (uint16_t)rdata1c & 0x00FF);
Serial.print(filtered[j]);
Serial.print(" ");
}
}
}
Serial.println(" "); } |