Using analoge capacitive touch sensors with 16-channel MUX

Dear community,

I'm new to Arduino and considering this I'm working on quite an ambitious project. I would like to turn a harp sculpture into an instrument with capacitive touch sensors.

I found a code by Esperienze Elettroniche for Arduino UNO with which you can turn any metal object into a capacitive sensor with just one analog pin. It works perfectly fine! As you need A0 as a pull-up resistor there's 5 pins left to turn into sensors. I would like to have more touch sensors though, so I built a 16-channel Multiplexor similar to the CD74HC4067.
I found out how to connect the MUX to the Arduino by connecting S0-S4 to digital pins 8-11, GND to GND, VCC to 5V and SIG to A1 and an according code. I don't know how to combine those two codes though in order to let the touch sensor code run through the MUX so to say..

Here's Esperienze Elettroniche's touch sensor code combined with a code I found on hooking up a MUX with Arduino. It gives me many errors :wink: I thought I could assign A1 to all of the touch sensors as this is where the MUX's SIG connects with the Arduino, does that make sense or does that confuse the program?

#define THRES 200
#define SAMPLES 20

//Mux control pins
int s0 = 8;
int s1 = 9;
int s2 = 10;
int s3 = 11;

//Mux in "SIG" pin
int SIG_pin = A1;



struct touchPad {
  int pin;
  int unpValue;
  int value;
  char state = 0, prevState = 0;
  char toggleState = 0;
};

touchPad touchPad1, touchPad2, touchPad3, touchPad4, touchPad5;

void setup() {


  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT);

  digitalWrite(s0, HIGH);
  digitalWrite(s1, HIGH);
  digitalWrite(s2, HIGH);
  digitalWrite(s3, HIGH);

  Serial.begin(57600);



/* Set A0 pull-up resistor, used to charge internal capacitor */
pinMode(A0, INPUT_PULLUP);
analogRead(A0);


/* Initialize sensors */
touchPadInit(&touchPad1, A1);
touchPadInit(&touchPad2, A1);
touchPadInit(&touchPad3, A1);
touchPadInit(&touchPad4, A1);
touchPadInit(&touchPad5, A1);


Serial.begin(57600);


}

void loop() {

  //Loop through and read all 16 values
  for (int i = 0; i < 16; i ++) {
    //  Serial.print("Value at channel ");
    //Serial.print(i);
    //Serial.print("is : ");
    Serial.println(readMux(i));
    delay(1000);
  }




float readMux(int channel) {
  int controlPin[] = {s0, s1, s2, s3};

  int muxChannel[16][4] = {
    {0, 0, 0, 0}, //channel 0
    {1, 0, 0, 0}, //channel 1
    {0, 1, 0, 0}, //channel 2
    {1, 1, 0, 0}, //channel 3
    {0, 0, 1, 0}, //channel 4
    {1, 0, 1, 0}, //channel 5
    {0, 1, 1, 0}, //channel 6
    {1, 1, 1, 0}, //channel 7
    {0, 0, 0, 1}, //channel 8
    {1, 0, 0, 1}, //channel 9
    {0, 1, 0, 1}, //channel 10
    {1, 1, 0, 1}, //channel 11
    {0, 0, 1, 1}, //channel 12
    {1, 0, 1, 1}, //channel 13
    {0, 1, 1, 1}, //channel 14
    {1, 1, 1, 1} //channel 15
  };

  //loop through the 4 sig
  for (int i = 0; i < 4; i ++) {
    digitalWrite(controlPin[i], muxChannel[channel][i]);
  }

  //read the value at the SIG pin
  int val = analogRead(SIG_pin);

  //return the value
  // float voltage = (val * 5.0) / 1024.0;
  // return voltage;



/* setMuxChannel (1);
  int val = analogRead (muxSIG);
  Serial.println(val);


  /* Scan sensors */
touchPadScan(&touchPad1);
  touchPadScan(&touchPad2);
  touchPadScan(&touchPad3);
  touchPadScan(&touchPad4);
  touchPadScan(&touchPad5);






  Serial.print(touchPad1.value);
  Serial.print("\t");
  Serial.print(touchPad2.value);
  Serial.print("\t");
  Serial.print(touchPad3.value);
  Serial.print("\t");
  Serial.print(touchPad4.value);
  Serial.print("\t");
  Serial.println(touchPad5.value);
  Serial.print(" ");


  delay (100);

}


void touchPadInit(touchPad *pad, int pin) {
  pad->pin = pin;
  pad->unpValue = (sampleB(pin) - sampleA(pin));
  DIDR0 |= 1;
  DIDR0 |= 1 << (pin - A0);
}

int sampleA(int sensePin) {
  /* Sample capacitor is charged to VCC
     via A0 pull-up resistor, touch pad
     is discharged by pulling pin low
  */
  ADMUX = 0b01000000;
  pinMode(sensePin, OUTPUT);
  digitalWrite(sensePin, 0);

  pinMode(sensePin, INPUT);
  ADMUX = 0b01000000 | sensePin - A0;

  ADCSRA |= 1 << ADSC;
  while ((ADCSRA & (1 << ADSC)) != 0);

  return ADC;
}

int sampleB(int sensePin) {
  /* Sample capacitor is discharged by selecting
     GND as ADC input, touch pad is charged to VCC
     via pin pull-up resistor
  */
  ADMUX = 0b01001111;
  pinMode(sensePin, INPUT_PULLUP);

  pinMode(sensePin, INPUT);
  ADMUX = 0b01000000 | sensePin - A0;

  ADCSRA |= 1 << ADSC;
  while ((ADCSRA & (1 << ADSC)) != 0);

  return ADC;
}

void touchPadScan(touchPad *pad) {
  static float A, B;

  A = 0;
  B = 0;

  /* Get some readings from sensor and calculate average */
  for (int i = 0; i < SAMPLES; i++) {
    A += sampleA(pad->pin);
    B += sampleB(pad->pin);
  }

  A /= SAMPLES;
  B /= SAMPLES;

  pad->value = (B - A);

  /* Member unpValue is a running average of the unpressed readings.
     A sudden change in sensor reading is interpreted as a touch
  */
  if (pad->value > (pad->unpValue + THRES))
    pad->state = 1;
  else {
    pad->state = 0;
    pad->unpValue = ((float)pad->unpValue * 0.9) + ((float)pad->value * 0.1);
  }

  if (pad->state == 1 && pad->prevState == 0)
    pad->toggleState = !pad->toggleState;

  pad->prevState = pad->state;
}

Attached you'll also find a picture of MUX setup. I put 5 black wires for sensors in I1, I2, I3, I4 and I5 (pins 4-8 on the MUX). Thanks a lot for any hint!
Best wishes, Elena

Why?
Why not get some experience first it will make your design decisions so much better.

And do you understand it and more precisely its limitations? There is a library that does the same thing supported by Arduino called cap sense.

How many?
It makes a big difference, the more you need the harder it gets.
These simple methods of touch sensing are fine for a few sensors but do not scale well for many sensors. Scaling up in electronics often brings up problems that you don't see at smaller scales.

My advice to you would be to get a touch sensor board and let that do the touch sensing for you, like the MPR212 chip / board. With this one you get 12 sensors and you can use two boards on the one I2C bus without difficulty, even more with a small trick.

There are other boards as well, search for Adafruit touch sensors for a good choice.

1 Like

I also recommend you to use a library - for example ADC touch. Thus, your program will become simpler and more understandable.

1 Like

Hey, thanks for your advice!

You're right about that, but you must know these kind of ideas that you don't get out of your mind :wink: Though I understand I should get experience by playing with fewer touch sensors first and fully understand both the hardware and software setup.

My harp has 22 strings in total. For now I would be very happy with the possible 16 due to the MUX. It's good to know that it will get more and more difficult with more cap sensors added..

Thank you, I will look into this!

I think if you use 2 x 16 multiplexers with 2 analog inputs it would work fine. So you will have 32 capacitive sensors.

Hi, @flashko

If you are going to multiplex the capacitive pickups, I doubt if you will have much success.
The added capacitance of the multiplexers and the length of the wiring will effect your results.

Also the function of the Arduino involves pulses being sent out the capacitor sense line and a response time being observed, not as simple as multiplexing switches.

This is how it works.
How to Add Capacitive Sensing to Any Arduino Project.

Summary
Capacitive proximity and touch sensors represent great for adding engaging and intuitive input options to DIY projects. As the name suggests, a capacitive sensor is nothing more at its core than a simple capacitor. One plate of the capacitor consists of a fixed conductive object, such as a metal strip. A target object, such as a user’s finger, forms the other plate. An Arduino sends out pulses and measures how long it takes until the software reports a response. The Arduino can then translate this delay to a proximity value. In its simplest form, a home-made sensor can deliver good results when tweaked appropriately for some applications. A dedicated proximity sensor board can achieve better results. Choosing to add an additional board, however, also increases the overall size, complexity, and cost of a project.

Tom.. :smiley: :+1: :coffee: :australia:
PS. If you are going to try, can I suggest you try 16 channels first with basic code to see if it will work?

thanks for this advice. For now I combined three digital cap sensors with the 5 analog ones mentioned above, so 8 sensors in total. This worked pretty well (with some shaky, unforeseeable results in between, like numbers going down instead of up when touching -> I just added two thresholds so in any case of touch my sound would be triggered). I also have the feeling that adding a MUX complicates capacitive sensing. I will look into the different options and keep you updated.

When doing any sort of capacitive sensing I always use grounded copper foil either underneath or to one side as close as possible to the sensor part the user will touch. This gives a more repeatable result especially if you go on and have it battery powered or stand alone where you don't get the solid ground that connecting it to a computer can give.

Hi,

Schematic and code, would help.

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.