I've thoroughly looked around and a lot of people are trying to do the same thing as I am: make a 48-key capacitive touch MIDI device (I'm using an Arduino Nano 3.0). Saving all the MIDI stuffs for later, I'm just trying to get the touch working. I already cut the presoldered ADDR-GND connection on all four breakouts and reassigned them with jumpers; the full wiring can be seen in the picture. However, I'm pretty sure the problem is in my code.
I could get two of them working just fine on addresses 0x5A and 0x5B, but when I tried connecting four, only 0x5B and 0x5C worked correctly. 0x5A didn't give any response at all, and 0x5D would act normally until any one of its pins were touched, and then it would say all of them were touched at once and stay on forever even when I release it. Surely I'm just doing some math wrong or some other stupid error, but I can't seem to find it; perhaps someone here will have better luck. It's just a modified version of the example that comes with the library:
#include "mpr121.h"
#include <Wire.h>
#define numBoards 4 // Number of MPR121s used
int irqpin [] = {2, 3, 4, 5};
int ADD [] = {0x5A, 0x5B, 0x5C, 0x5D}; // Corresponding addresses of each board
boolean touchStates [12 * numBoards]; // To keep track of the previous touch states
void setup(){
for (int i = 0; i < numBoards; i++) {
pinMode(irqpin [i], INPUT_PULLUP);
//digitalWrite(irqpin [i], HIGH); //enable pullup resistor
}
Serial.begin(9600);
Wire.begin();
for (int i = 0; i < numBoards; i++) {
mpr121_setup(ADD [i]);
}
}
void loop(){
for (int i = 0; i < numBoards; i++) {
readTouchInputs(i);
}
for (int t = 0; t < numBoards * 12; t++) {
Serial.print (touchStates [t]);
}
Serial.println ();
}
void readTouchInputs(int boardNum){
if(!checkInterrupt(boardNum)){
//read the touch state from the MPR121
Wire.requestFrom(ADD [boardNum],2);
byte LSB = Wire.read();
byte MSB = Wire.read();
uint16_t touched = ((MSB << 8) | LSB); //16bits that make up the touch states
for (int i=0; i < 12; i++){ // Check what electrodes were pressed
if (touched & (1<<i)) {
if (touchStates [i + boardNum * 12] == 0) {
//pin i was just touched
// Serial.print ("pin ");
// Serial.print (i + boardNum * 12);
// Serial.println (" was just touched");
} else if (touchStates[i + boardNum * 12] == 1) {
//pin i is still being touched
}
touchStates [i + boardNum * 12] = 1;
} else {
if (touchStates [i + boardNum * 12] == 1) {
// Serial.print ("pin ");
// Serial.print (i + boardNum * 12);
// Serial.println (" is no longer being touched");
//pin i is no longer being touched
}
touchStates [i + boardNum * 12] = 0;
}
}
}
}
void mpr121_setup(int address){
set_register(address, ELE_CFG, 0x00);
// Section A - Controls filtering when data is > baseline.
set_register(address, MHD_R, 0x01);
set_register(address, NHD_R, 0x01);
set_register(address, NCL_R, 0x00);
set_register(address, FDL_R, 0x00);
// Section B - Controls filtering when data is < baseline.
set_register(address, MHD_F, 0x01);
set_register(address, NHD_F, 0x01);
set_register(address, NCL_F, 0xFF);
set_register(address, FDL_F, 0x02);
// Section C - Sets touch and release thresholds for each electrode
set_register(address, ELE0_T, TOU_THRESH);
set_register(address, ELE0_R, REL_THRESH);
set_register(address, ELE1_T, TOU_THRESH);
set_register(address, ELE1_R, REL_THRESH);
set_register(address, ELE2_T, TOU_THRESH);
set_register(address, ELE2_R, REL_THRESH);
set_register(address, ELE3_T, TOU_THRESH);
set_register(address, ELE3_R, REL_THRESH);
set_register(address, ELE4_T, TOU_THRESH);
set_register(address, ELE4_R, REL_THRESH);
set_register(address, ELE5_T, TOU_THRESH);
set_register(address, ELE5_R, REL_THRESH);
set_register(address, ELE6_T, TOU_THRESH);
set_register(address, ELE6_R, REL_THRESH);
set_register(address, ELE7_T, TOU_THRESH);
set_register(address, ELE7_R, REL_THRESH);
set_register(address, ELE8_T, TOU_THRESH);
set_register(address, ELE8_R, REL_THRESH);
set_register(address, ELE9_T, TOU_THRESH);
set_register(address, ELE9_R, REL_THRESH);
set_register(address, ELE10_T, TOU_THRESH);
set_register(address, ELE10_R, REL_THRESH);
set_register(address, ELE11_T, TOU_THRESH);
set_register(address, ELE11_R, REL_THRESH);
// Section D
// Set the Filter Configuration
// Set ESI2
set_register(address, FIL_CFG, 0x04);
// Section E
// Electrode Configuration
// Set ELE_CFG to 0x00 to return to standby mode
set_register(address, ELE_CFG, 0x0C); // Enables all 12 Electrodes
// Section F
// Enable Auto Config and auto Reconfig
/*set_register(0x5A, ATO_CFG0, 0x0B);
set_register(0x5A, ATO_CFGU, 0xC9); // USL = (Vdd-0.7)/vdd*256 = 0xC9 @3.3V set_register(0x5A, ATO_CFGL, 0x82); // LSL = 0.65*USL = 0x82 @3.3V
set_register(0x5A, ATO_CFGT, 0xB5);*/ // Target = 0.9*USL = 0xB5 @3.3V
set_register(address, ELE_CFG, 0x0C);
}
boolean checkInterrupt(int boardNum){
return digitalRead(irqpin [boardNum]);
}
void set_register(int address, unsigned char r, unsigned char v){
Wire.beginTransmission(address);
Wire.write(r);
Wire.write(v);
Wire.endTransmission();
}