Go Down

Topic: capsense help (Read 1 time) previous topic - next topic


hey guys

so im building an instrument with capacitive touch sensors for keys.
i have the amazing MPR121 capacitance breakout board and it works wonderfully.

however, it only enables me to get input from 12 electrodes. i need 13 for a full octave (c to c').

i downloaded capsense, and tried to implement the code into my pre-existing MPR sketch, and well - i do get input from the capsense button on the arduino - but the latency is around 1 second!

if you could help me out, and tell me why my code slows down like that - i would be a very happy person.

here is my messy code - capsense is //commented. MPR121 code is taken from bildr.org


Code: [Select]
//#include <CapSense.h>
#include "mpr121.h"
#include <Wire.h>
#include <SimpleMessageSystem.h>

//CapSense   cs_19_15 = CapSense(2,3);

int irqpin = 12;  // Digital 12
boolean touchStates[12]; //to keep track of the previous touch states

void setup(){
  pinMode(irqpin, INPUT);
  digitalWrite(irqpin, HIGH); //enable pullup resistor


void loop(){
//    long tot = cs_19_15.capSense(30);
//  Serial.print(tot);
//  Serial.println("\t");
//  if(tot < 5000){
//    digitalWrite(13, LOW);
//  }
//  if(tot > 5000){
//    digitalWrite(13, HIGH);
//  }
//  delay(10);

  if (messageBuild() > 0) { // Checks to see if the message is complete and erases any previous messages
    switch (messageGetChar()) { // Gets the first word as a character
    case 'r': // Read pins (analog or digital)
      readpins(); // Call the readpins function
      break; // Break from the switch
    case 'w': // Write pin
      writepin(); // Call the writepin function



void readTouchInputs(){
    //read the touch state from the MPR121
    byte LSB = Wire.receive();
    byte MSB = Wire.receive();
    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] == 0){
          //pin i was just touched
          Serial.print("pin ");
          Serial.println(" was just touched");
            digitalWrite(i+2, HIGH);
            digitalWrite(13, HIGH);
        }else if(touchStates[i] == 1){
          //pin i is still being touched
        touchStates[i] = 1;     
        if(touchStates[i] == 1){

          Serial.print("pin ");
          Serial.println(" is no longer being touched");
            digitalWrite(i+2, LOW);
            digitalWrite(13, LOW);
          //pin i is no longer being touched
        touchStates[i] = 0;

void mpr121_setup(void){
  // Section A - Controls filtering when data is > baseline.
  set_register(0x5A, MHD_R, 0x01);
  set_register(0x5A, NHD_R, 0x01);
  set_register(0x5A, NCL_R, 0x00);
  set_register(0x5A, FDL_R, 0x00);

  // Section B - Controls filtering when data is < baseline.
  set_register(0x5A, MHD_F, 0x01);
  set_register(0x5A, NHD_F, 0x01);
  set_register(0x5A, NCL_F, 0xFF);
  set_register(0x5A, FDL_F, 0x02);
  // Section C - Sets touch and release thresholds for each electrode
  set_register(0x5A, ELE0_T, TOU_THRESH);
  set_register(0x5A, ELE0_R, REL_THRESH);

  set_register(0x5A, ELE1_T, TOU_THRESH);
  set_register(0x5A, ELE1_R, REL_THRESH);
  set_register(0x5A, ELE2_T, TOU_THRESH);
  set_register(0x5A, ELE2_R, REL_THRESH);
  set_register(0x5A, ELE3_T, TOU_THRESH);
  set_register(0x5A, ELE3_R, REL_THRESH);
  set_register(0x5A, ELE4_T, TOU_THRESH);
  set_register(0x5A, ELE4_R, REL_THRESH);
  set_register(0x5A, ELE5_T, TOU_THRESH);
  set_register(0x5A, ELE5_R, REL_THRESH);
  set_register(0x5A, ELE6_T, TOU_THRESH);
  set_register(0x5A, ELE6_R, REL_THRESH);
  set_register(0x5A, ELE7_T, TOU_THRESH);
  set_register(0x5A, ELE7_R, REL_THRESH);
  set_register(0x5A, ELE8_T, TOU_THRESH);
  set_register(0x5A, ELE8_R, REL_THRESH);
  set_register(0x5A, ELE9_T, TOU_THRESH);
  set_register(0x5A, ELE9_R, REL_THRESH);
  set_register(0x5A, ELE10_T, TOU_THRESH);
  set_register(0x5A, ELE10_R, REL_THRESH);
  set_register(0x5A, ELE11_T, TOU_THRESH);
  set_register(0x5A, ELE11_R, REL_THRESH);
  // Section D
  // Set the Filter Configuration
  // Set ESI2
  set_register(0x5A, FIL_CFG, 0x04);
  // Section E
  // Electrode Configuration
  // Set ELE_CFG to 0x00 to return to standby mode
  set_register(0x5A, 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

boolean checkInterrupt(void){
  return digitalRead(irqpin);

void set_register(int address, unsigned char r, unsigned char v){

//commence max communication!

void readpins(){ // Read pins (analog or digital)

  switch (messageGetChar()) { // Gets the next word as a character

    case 'd': // READ digital pins

    messageSendChar('d');  // Echo what is being read
    for (char i=2;i<14;i++) {
      messageSendInt(digitalRead(i)); // Read pins 2 to 13
    messageEnd(); // Terminate the message being sent
    break; // Break from the switch

  case 'a': // READ analog pins

    messageSendChar('a');  // Echo what is being read
    for (char i=0;i<6;i++) {
      messageSendInt(analogRead(i)); // Read pins 0 to 5
    messageEnd(); // Terminate the message being sent



void writepin() { // Write pin

  int pin;
  int state;

  switch (messageGetChar()) { // Gets the next word as a character

    case 'a' : // WRITE an analog pin

    pin = messageGetInt(); // Gets the next word as an integer
    state = messageGetInt(); // Gets the next word as an integer
    pinMode(pin, OUTPUT); //Sets the state of the pin to an output
    analogWrite(pin, state); //Sets the PWM of the pin
    break;  // Break from the switch

    // WRITE a digital pin
  case 'd' :

    pin = messageGetInt();  // Gets the next word as an integer
    state = messageGetInt();  // Gets the next word as an integer
    pinMode(pin,OUTPUT);  //Sets the state of the pin to an output
    digitalWrite(pin,state);  //Sets the state of the pin HIGH (1) or LOW (0)




So far I get mixed results when playing with cap sense but I can tell you that how long it takes to sense is a matter of how long it takes to bleed the cap through the resistor, the higher the value of those two the longer it takes to bleed. You have with resistor-capacitor setup what is called the time constant, R x C (resistance times capacitance) which I find a little funny with cap sense since changing C is how it works and yet time 'constant'... oh well, it's probably a geek thing.

Here is the most minimal cap sense I know of. It works but I wouldn't use it as is outside of test.

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.


hey smoke

well, the code i implemented is copy/pasted from the tutorial you posted. when i run the tutorial by itself, the response is fine.

maybe the two libraries are having a conflict?

could anyone possibly point out some errors i've made?



Just saying that between the resistors and capacitive elements you might likely be able to change values of those and the same code be sensing quicker. The smaller the resistor the faster the capacitor will bleed, the smaller the capacitor the faster it will reach low value.

I haven't dug into the example, I've done and played with two playground cap sense sketches and evolved setups from there but as I say, I got mixed results. A couple were good as far as making cheap buttons.

I have to go out now but I'll be back.

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.


any thoughts on how i could fix my code?


Go Up