|
As a more reliable alternative to mechanical keypads, this pcb with an integrated touch sensor controller provides a numeric keypad and requires only the two i2c signal lines (plus optionally an interrupt line to the microprocessor to signal a keystroke) and runs on 3.3V. Depending on the polling interval, current consumption is 70µA to 1 or 2 mA.
Connections:
•
GND • 3.3V
• SDA - i2c data
• SCL - i2c clock
• INT - interrupt signal to mcu
• LED - for user feedback since there is no mechanical click
It can be mounted behind a transparent plexiglass panel as long as it is glued without air bubbles (for example with silicon compound or two-sided adhesive tape).
70 x 53 mm pcb with gold-finished contact pads for connections, 0.1" pitch.
Circuit consists of the AD7147 controller and supply decoupling capacitors. i2c pull-up resistors not included: SDA and SCL require ca 4.7 kOhm pull-ups on mcu side.
This version uses the Analog Devices AD7147 with i2c.
The pcb can also be fitted with the SPI version on request.
An alternative with the Freescale MPR121 is coming soon.
/****************************************************************************/
/* MPR121 sample code - www.flashgenie.net */
/* any feedback is welcome at genie < at > flashgenie.net */
/****************************************************************************/
byte resA,MPR_OK; //global
#define MPR_i2cAddress 0x5a //0x4D
#define TouchedOK 13 //code for Ok key of touch pad
#define TouchedESC 8 //code of ESC key of touch pad
#define NoTouch 0
#define ADmsg 60
#define NUM_TOUCH_KEYS 13 //including eleProx
#define DATA_BLOCK_SIZE 43 //include baseline values
#define ADC_TouchRegister 0
#define ADC_ResultRegister 4
#define BaselineRegister 30
void initMPR(void);
byte DecodeButtons(void);
byte ReadFromMPR( byte RegAdr, byte NumberOfRegistersToRead, byte *DataBuffer);
void MPR121_WriteRegister(byte adr, byte val);
void initMPR(void)
{
#define InitBlockSize 27 //send sequential registers as one long block: address then vals
byte Thresholds[InitBlockSize] = {0x41,15,10,15,10,15,10,15,10,15,10,15,
10,15,10,15,10,15,10,15,10,15,10,15,10,15,10};
word sent;
IIC1_Init();//lo-level init
I2C1_Init();
I2C1_SelectSlave(MPR_i2cAddress);
MPR_OK = 1;
MPR121_WriteRegister(0x2B,1); // MAX HALF DELTA Rising
MPR121_WriteRegister(0x2C,1); // NOISE HALF DELTA Rising
MPR121_WriteRegister(0x2D,0); // NOISE COUNT LIMIT Rising
MPR121_WriteRegister(0x2E,0); // DELAY LIMIT Rising
MPR121_WriteRegister(0x2F,1); // MAX HALF DELTA Falling
MPR121_WriteRegister(0x30,1); // NOISE HALF DELTA Falling
MPR121_WriteRegister(0x31,0xFF); // NOISE COUNT LIMIT Falling
MPR121_WriteRegister(0x32,2); // DELAY LIMIT Falling
resA = I2C1_SendBlock(&Thresholds, (word)InitBlockSize, &sent); // send block, with address
if (resA)
ErrorMsg(resA, "i2cSendBlockErr");
if (sent < InitBlockSize)//sending failed
{
MPR_OK=0;//set global error flag to indicate that touch pad is not available
return;
}
MPR121_WriteRegister(0x5C,0x0B); // AFE CONFIG FFI CDC %1011 AN3889
MPR121_WriteRegister(0x5D,0x04); //TOUCH DETECTION CONFIG last 3 bits=sample interval; 4:5ms
MPR121_WriteRegister(0x7B,0x0B); // %1011 AUTOCONFIG enable
MPR121_WriteRegister(0x7D,156); //196 was 156 AUTOCONFIG upper limit USL 196 for 3V
MPR121_WriteRegister(0x7E,101); //127 was 101 AUTOCONFIG lower limit LSL 65% of USL
MPR121_WriteRegister(0x7F,140); //176 was 140 AUTOCONFIG target level 90% of USL
MPR121_WriteRegister(0x5E,0x0c); // START PESCE (number of electrodes )
}
void MPR121_WriteRegister(byte adr, byte val)
{ byte blk[2];
word sent;
blk[0]=adr;// copy register address and value into a two-byte block and send it
blk[1]=val;
resA = I2C1_SendBlock(&blk, 2, &sent); // send 1 byte to set read address
if (resA)
ErrorMsg(resA, "i2cSendBlockErr");
}
//return true if success
byte ReadFromMPR( byte RegAdr, byte NumberOfRegistersToRead, byte *DataBuffer){ word sent;
resA = I2C1_SendBlock(&RegAdr, (word)1, &sent); // send 1 byte to set read address
if (resA)
{
ErrorMsg(resA, "i2cSendBlockErr");
return 0;//fail
}
resA = I2C1_RecvBlock(DataBuffer, NumberOfRegistersToRead, &sent); // number of bytes
if (resA)
{
ErrorMsg(resA, "i2cReadBlockErr");
}
return (resA==ERR_OK);// success
}
//call this routine when the interrupt line from the MPR121 signals a touch event
byte DecodeButtons(void) //decode bitmap of MPR touch register and return ascii code of key
{ word mask = 0x0001;
byte i;
if (ReadFromMPR(ADC_TouchRegister, 2, (byte *)(&TouchBits)))
{
for (i=0;i<10;i++)// test for 10 digits:
{
if (TouchBits == mask)
return '0'+i;//return character value of digit: '0', '1' etc
mask <<=1;//shift left 1 to test next bit
}
if (TouchBits == 0x0400)
return TouchedESC;
else if (TouchBits == 0x0800)
return TouchedOK;
else
return NoTouch;
}
else return NoTouch;
}
//end mpr121
|