Dear all,
In contrary to many other MPR121 projects where I found information on, I want to use the Freescale MPR121 (placed on a Sparkfun breakout board) to perform a capacity measurement instead of only touch sensing.
The problem is that when I read out the capacity measurment, this doesn't correspond to what's expected based on the equations. Let me try to explain as accurately as possible what I have done:
- According to Freescale's documentation the relation between the measured capacity and the given output ADC is as follows:
C = (I * T * 1024) / (Vdd * ADC)
where
C: capacity to be measured
I: current, Charge Discharge Current (CDC), set in the Analog Front End (AFE) Configuration Register.
T: Charge Discharge Time (CDT), set in the Filter Configuration Register.
Vdd: the breakout board is provided a 3.3V supply
ADC: this is a counter value that represents the voltage inversely proportional to the measured Capacitance (C).
- To verify measurements, I have connected a known capacity to the breakout board sensor 0.
- I want to read the ADC value from the register, as this represents the measured capacity. This is a 10bit number which I read as follows:
void read_capacity( void )
{
short int ADC = 0;
ADC = mpr121.read(EFD0HB); // Read first byte (MSByte)
ADC <<= 8; // Shift byte to MSByte position
ADC |= mpr121.read(EFD0LB); // Past second byte (LSByte) into value
pc.printf("ADC = %i\n", ADC);
pc.printf("\n\n");
}
where EFD0HB and EFD0LB are respectively the high byte and low byte registry addresses for the ADC value of sensor channel 0.
- To make this capacity measurement work, I can configure some settings. Among other filter settings, I can set 'I' (Charge Discharge Current CDC) and 'T' (Charge Discharge Time CDT) to ensure that the measured capacity is within allowed range. This allowed range is calculated as:
C_low = (I*T)/(Vdd-0.7) and C_high=(I*T)/0.7.
The used code to set the CDC and CDT (and some other filter values that make it a more robust measurement via averaging etcetera) is:
void set_capacity_measurement( void )
{ //For more information see Texas Instruments Application Note AN3889
int FFI; // [samples] First Filter Iterations (FFI)
int CDC; // [uA] Charge Discharge Current (CDC)
unsigned char AFE_CFG_value = 0;
int SFI; // [samples] Second Filter Iterations (FFI)
int ESI; // [ms] Electrode Sample Interval
int CDT; // [us] Charge Discharge Time (CDT)
unsigned char FIL_CFG_value = 0;
// Set the electrode config to transition to stop mode
mpr121.write(ELE_CFG,0x00); // write value to register
//Analog Front End (AFE) CONFIGURATION REGISTER
FFI = 3; // value: 0:samples taken 6 (default)| 1:samples taken 10 | 2:samples taken 18 | 3:samples taken 34
CDC = 4; // [uA] range [0 - 63]
FFI <<= 6; // shift to first two bits of register value
AFE_CFG_value = (FFI|CDC); // combine inputs to correct register value
mpr121.write(AFE_CFG,AFE_CFG_value); // write value to register
//Filter CONFIGURATION REGISTER
CDT = 7; // range [1 - 7] = [0.5us - 32us] note: value 0 is invalid
SFI = 0; // range [0 - 3] = [4,6,10,18] samples
ESI = 7; // range [0 - 7] = [1,2, 128ms]
CDT <<= 5; // shift to bits 7:5 of register value
SFI <<= 3; // shift to bits 4:3 of register value
FIL_CFG_value = ((CDT|SFI)|ESI); // combine inputs to correct register value
mpr121.write(FIL_CFG,FIL_CFG_value); // write value to register
// Set the electrode config to transition to active mode
mpr121.write(ELE_CFG,0x0C); // write value to register
pc.printf("Capacity Settings Set\n");
}
- So now I have connected a known Capacity, set 'I' and 'T' to ensure this Capacity value to be within the possible measurement range, calculated with the first equation what ADC value to expect, and read the ADC value.
Unfortunately, the obtained ADC value doesn't correspond to the calculated (expected) ADC value (not even close). I haven't been able to find any relation (multiplication or offset) between the ADC values expected and the ADC values read from the register.
I hope somebody has an idea where to look for the cause of this problem? Or a suggestion what to try?
For completeness I have added two documents regarding the MPR121 and capacity measurement.
Many thanks in advance!
Relevant MPR121 documentation:
/media/uploads/raalst1/an3889_capacitance_sensing_settings.pdf
and
/media/uploads/raalst1/mpr121_data_sheet.pdf
Dear all,
In contrary to many other MPR121 projects where I found information on, I want to use the Freescale MPR121 (placed on a Sparkfun breakout board) to perform a capacity measurement instead of only touch sensing.
The problem is that when I read out the capacity measurment, this doesn't correspond to what's expected based on the equations. Let me try to explain as accurately as possible what I have done:
C = (I * T * 1024) / (Vdd * ADC)
where C: capacity to be measured I: current, Charge Discharge Current (CDC), set in the Analog Front End (AFE) Configuration Register. T: Charge Discharge Time (CDT), set in the Filter Configuration Register. Vdd: the breakout board is provided a 3.3V supply ADC: this is a counter value that represents the voltage inversely proportional to the measured Capacitance (C).
where EFD0HB and EFD0LB are respectively the high byte and low byte registry addresses for the ADC value of sensor channel 0.
C_low = (I*T)/(Vdd-0.7) and C_high=(I*T)/0.7.
The used code to set the CDC and CDT (and some other filter values that make it a more robust measurement via averaging etcetera) is:
Unfortunately, the obtained ADC value doesn't correspond to the calculated (expected) ADC value (not even close). I haven't been able to find any relation (multiplication or offset) between the ADC values expected and the ADC values read from the register.
I hope somebody has an idea where to look for the cause of this problem? Or a suggestion what to try?
For completeness I have added two documents regarding the MPR121 and capacity measurement.
Many thanks in advance!
Relevant MPR121 documentation: /media/uploads/raalst1/an3889_capacitance_sensing_settings.pdf and /media/uploads/raalst1/mpr121_data_sheet.pdf