Help with CapSense Piano!

Hi, I’m pretty new to using Arduino IDE and was wondering whether I could get some help with the coding of this project. Using an Adafruit Flora, I have made an e-textile piano with seven capacitive touchpads made from conductive fabric connected to the Flora pins (0, 1, 2, 3, 9, 10, 12) with conductive thread, and a Piezo buzzer is attached to 6 and the ground/GND. I have lifted this code from a tutorial which I have attempted to modify:

/*
  Capacitive-Touch Arduino Keyboard Piano
  
  Plays piano tones through a buzzer when the user taps touch-sensitive piano "keys"
  
  Created  18 May 2013
  Modified 23 May 2013
  by Tyler Crumpton and Nicholas Jones
  
  This code is released to the public domain. For information about the circuit,
  visit the Instructable tutorial at http://www.instructables.com/id/Capacitive-Touch-Arduino-Keyboard-Piano/
*/

#include <CapacitiveSensor.h>
#include "pitches.h"

#define BUZZER_PIN      6   // The output pin for the piezo buzzer
#define NUM_OF_SAMPLES  10   // Higher number whens more delay but more consistent readings
#define CAP_THRESHOLD   150  // Capactive reading that triggers a note (adjust to fit your needs)
#define NUM_OF_KEYS     7    // Number of keys that are on the keyboard

// This macro creates a capacitance "key" sensor object for each key on the piano keyboard:
#define CS(Y) CapacitiveSensor(2, Y)

// Each key corresponds to a note, which are defined here. Uncomment the scale that you want to use:
int notes[]={NOTE_C4,NOTE_D4,NOTE_E4,NOTE_F4,NOTE_G4,NOTE_A4,NOTE_B4}; // C-Major scale
//int notes[]={NOTE_A4,NOTE_B4,NOTE_C5,NOTE_D5,NOTE_E5,NOTE_F5,NOTE_G5}; // A-Minor scale
//int notes[]={NOTE_C4,NOTE_DS4,NOTE_F4,NOTE_FS4,NOTE_G4,NOTE_AS4,NOTE_C5}; // C Blues scale

// Defines the pins that the keys are connected to:
CapacitiveSensor keys[] = {CS(3), CS(2), CS(0), CS(1), CS(12), CS(9), CS(10)};

void setup() { 
  // Turn off autocalibrate on all channels:
  for(int i=0; i<8; ++i) {
    keys[i].set_CS_AutocaL_Millis(0xFFFFFFFF);
  }
  // Set the buzzer as an output:
  pinMode(BUZZER_PIN, OUTPUT); 
}

void loop() {    
  // Loop through each key:
  for (int i = 0; i < 8; ++i) {
    // If the capacitance reading is greater than the threshold, play a note:
    if(keys[i].capacitiveSensor(NUM_OF_SAMPLES) > CAP_THRESHOLD) {
      tone(BUZZER_PIN, notes[i]); // Plays the note corresponding to the key pressed
    }
  }
}

I have pitches.h on the other tab and I installed the CapacitiveSensor library with the IDE manager, and I’m sure it’s not the hardware itself, but nothing is happening when the pads are touched. I don’t know half of what this code does aside from guesswork and what I’ve picked up from similar tutorials, etc.

Basically, if someone can help me pick this apart and work out what needs changing, that would be great. I can add images of the piece so far etc. if need be. Thanks!

EDIT: Forgot to say, I assume the issue stems from not having a “common pin” as the original code/tutorial did, or something going on in the setup/loop part. Maybe.

For narrowing down where the problem is you should flash a small program that does nothing more than detecting a single capacitive sensor to check if your basic wiring works.

The more things you add the more possabilities where the bug can be.
Trying to be fast through throwing it all together with guessings turns out to slow you down because now you have to test hundreds or thousands of guessing by varying this varying that.

This seems to be a lesson almost any newbee has to make before believing it.

For a detailed analysis you have to provide a handrawn picture of how you wired the sensors to your microcontroller.

best regards Stefan

For narrowing down where the problem is you should flash a small program that does nothing more than detecting a single capacitive sensor to check if your basic wiring works.

Where would I be able to learn to make that? I’ve seen various videos where upon touching the capacitive component it shows a higher number, etc.

I can do a basic diagram of the circuitry as a whole but it’s literally just Flora pin -thread-> fabric

I have no idea what you mean by "thread" and "fabric" in your case.
are you sure that "thread" and "fabric" are the common words for what you mean?

Can you upload a picture of your microcontroller and the things you have connected to them?

best regards Stefan

Sorry, here’s a picture of the piece so far, this is only a test to see if I can get it to function:


The small squares are the conductive fabric, with conductive thread acting as a wire to the board.

EDIT: The buzzer isn’t pictured here, but will be attached to #6 and GND.

The wires look like just wrapped around the wholes and wrapped around the whites pieces.

This are bad conditions for conducting.

If you take a look into the documentation at Arduino.cc
https://playground.arduino.cc/Main/CapacitiveSensor/

you can see that there are used two pins with a resistor between them.
The code uses the internal pullup-resistor as the resistor. How good this will work depends on the resistance-value of this internal pullup-resistor.
I guess they vary from microcontroller-type to microcontroller-type.

The docs mention a value of 1 MegaOhm. Which is pretty high and much higher than the internal pullup-resistor (which migh have only 0,02 to 0,5 MegaOhm)

Can you provide the links to where got the code from and the design of the wiring and the "metal" pieces?

also one of the basic democodes states
#include <CapPin.h>

/* CapPin

  • Capacitive Library CapPin Demo Sketch
  • Paul Badger 2011
  • This class uses the bullt-in pullup resistors read the capacitance on a pin
  • The pin is set to input and then the pullup is set,
  • A loop times how long the pin takes to go HIGH.
  • The readPin method is fast and can be read 1000 times in under 10 mS.
  • By reading the pin repeated you can sense "hand pressure"
  • at close range with a small sensor. A larger sensor (piece of foil/metal) will yield
  • larger return values and be able to sense at more distance. For
  • a more senstive method of sensing pins see CapTouch
  • Hook up a wire with or without a piece of foil attached to the pin.
  • I suggest covering the sensor with mylar, packing tape, paper or other insulator
  • to avoid having users directly touch the pin.
    */
    best regards Stefan

Code was lifted from here, I honestly wasn’t expecting it to work the first time but I don’t have the know-how to write it on my own so I was hoping I could butcher someone else’s.
The wiring was basically this but the idea was instead of a gamepad each ‘button’ would play a note. Strong resistors were used in similar projects, but for a test piece, I was hoping for similar results to the Adafruit project.

Here is a capacitive sensor that is pre-built for reliable function.
Though I haven't them tested myself

best regards Stefan

That’s really useful for the future, for this project however it is intended to be predominately etextiles, so I’m hoping I can do something with this code:

/*
Example code for a Flora game controller with capacitive touch sensing! Full tutorial and video:
http://learn.adafruit.com/plush-game-controller/
Uses Modern Device's Capacitive Sensing library: https://github.com/moderndevice/CapSense
  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!
  Written by Limor Fried & Becky Stern for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
  
*/
#include <CapPin.h>
#include <Keyboard.h>

CapPin cPin_10 = CapPin(10);    // read pin 10 (D10 on Flora) - connect to NES B
CapPin cPin_9  = CapPin(9);     // read pin 9 (D9 on Flora)   - connect to NES A
CapPin cPin_6  = CapPin(6);     // read pin 6 (D6 on Flora)   - connect to NES Start
CapPin cPin_12 = CapPin(12);    // read pin 12 (D12 on Flora) - connect to NES Select
CapPin cPin_1  = CapPin(1);     // read pin 1 (TX on Flora)   - connect to NES right
CapPin cPin_0  = CapPin(0);     // read pin 0 (RX on Flora)   - connect to NES up
CapPin cPin_2  = CapPin(2);     // read pin 2 (SDA on Flora)  - connect to NES left
CapPin cPin_3  = CapPin(3);     // read pin 3 (SCL on Flora)  - connect to NES down

CapPin pins[] = {cPin_10, cPin_9, cPin_6, cPin_12, cPin_1, cPin_0, cPin_2, cPin_3};
// check http://arduino.cc/en/Reference/KeyboardModifiers for more info on unique keys

// WASD D-pad, select = Return, start = Space, LeftButton = z, RightButton = x
//char Keys[] =   {  'x',    'z',    ' ',     KEY_RETURN,    'd',     'w',    'a',    's'};

// arrow D-pad, select = Return, start = Space, LeftButton = b, RightButton = a
char Keys[] =   {  'a',    'b',    ' ',     KEY_RETURN, KEY_RIGHT_ARROW, KEY_UP_ARROW, KEY_LEFT_ARROW, KEY_DOWN_ARROW};

boolean currentPressed[] = {false, false, false, false, false, false, false, false};

// Capactive touch threashhold, you might want to mess with this if you find its too
// sensitive or not sensitive enough
#define THRESH 500

float smoothed[8] = {0,0,0,0,0,0,0,0};

void setup()
{
  //while (!Serial)
  Serial.begin(115200);
  Serial.println("start");
  Keyboard.begin();
}


void loop()                    
{ 
  for (int i=0;i<8;i++) {
    delay(1);
    long total1 = 0;
    long start = millis();
    long total =  pins[i].readPin(2000);

    // check if we are sensing that a finger is touching the pad 
    // and that it wasnt already pressed
    if ((total > THRESH) && (! currentPressed[i])) {
      Serial.print("Key pressed #"); Serial.print(i);
      Serial.print(" ("); Serial.print(Keys[i]); Serial.println(")");
      currentPressed[i] = true;

      Keyboard.press(Keys[i]);
    } 
    else if ((total <= THRESH) && (currentPressed[i])) {
      // key was released (no touch, and it was pressed before)
      Serial.print("Key released #"); Serial.print(i);
      Serial.print(" ("); Serial.print(Keys[i]); Serial.println(")");
      currentPressed[i] = false;
      
      Keyboard.release(Keys[i]);
    }
    
/*
    // simple lowpass filter to take out some of the jitter
    // change parameter (0 is min, .99 is max) or eliminate to suit
    smoothed[i] = smooth(total, .8, smoothed[i]);   
    Serial.print(i); Serial.print(": ");
    Serial.print( millis() - start);      // time to execute in mS
    Serial.print("ms \t");
    Serial.print(total);                  // raw total
    Serial.print("\t->\t");
    Serial.println((int) smoothed[i]);       // smoothed
*/
    delay(5);
  }
}

// simple lowpass filter
// requires recycling the output in the "smoothedVal" param
int smooth(int data, float filterVal, float smoothedVal){

  if (filterVal > 1){      // check to make sure param's are within range
    filterVal = .999999;
  }
  else if (filterVal <= 0){
    filterVal = 0;
  }

  smoothedVal = (data * (1 - filterVal)) + (smoothedVal  *  filterVal);

  return (int)smoothedVal;
}

I hope I can somehow use this as a base and turn it in to something that can play notes from pitches.h like I was attempting in the original post. I’m sure the circuit itself probably needs more work but what is confusing me is how the Adafruit plush controller works without resistors etc. perfectly fine, and how I can take that concept and turn it into a plush piano.

did you try this code? Which seems to be the original code

or this one?

it mentions a threshold value with which you have to experiment to get results.
Anyway befor using the piano-code you should do some experimental analysis by a simpler code that prints the measured values to the serial-monitor

The microcontroller-world is not super-standardizes like USB-devices. And in case of capacitive sensing it is even more sensible to different parameters.

best regards Stefan

Yeah, that’s the code I am attempting to edit so instead of going A, B, Start, Select, etc., it plays C, D, E, F, etc.

I will have a look at adjusting the threshold for the sensors, I’m currently trying to work out how to tell it to play notes instead of simulating keyboard presses.

So I’m having a play with the actual gamepad code from the Adafruit tutorial, and everything is identical aside from the THRESH value I keep changing, and nothing is happening? My feet are on the floor (which apparently matters) but no output onto Notepad whatsoever. I don’t think there’s an extra step to have it ‘type’ anywhere, so if anyone has advice here it would help me work out what is happening!

Sorry to bump a thread but I’ve gone over the code and the wiring for this a dozen times now with no problems coming up. If anyone can at least suggest somewhere to better understand what I’m trying to do that would be great, or even just an “oh your ___ is ___”. Thanks again!

Do you have digital multimeter to test if you really have a connection from your conductive fabric all the way towards the yellow connection-hole?

If you add serial output what do the measured values show?

If the adafruit-game-controller-sketch does not react at all

it is time for a much much smaller testcode to test if a single input connected to
your e-textile produce any kind of result at all.

best regards Stefan

Are there examples of some smaller test codes to look for responses? No multimeter but I’m sure I could get one, I just wanted to say you’ve been a massive help so far so thank you :+1:

The basic route to do so is looking through the given sourcecode if online-ressources are mentioned:

https://raw.githubusercontent.com/moderndevice/CapSense/master/Examples/CapPin/CapPin3.pde

if you have anyquestions how to proceed give a short description of what you have done so far on your own and then ask a question.

If you just ask "what's the next step?" "what's the next step?" "what's the next step?"
without describing your own effort you will erode the will of other users to help

best regards Stefan

Okay, I didn’t realise there were example sketches in the library. I will test some and look for results as well as looking into whether I can test the circuit. Sorry for asking so many questions, I will edit this post with some results later hopefully.

It is okay to ask a lot of questions as long as you add a description of your own effort or at least what your thoughts are
best regards Stefan

Okay, got a multimeter, tested each connection. According to this thing, set to 200Ω, I’m getting readings between 10 and 40, typically, so does that mean the circuit has a resistance of up to 40, and I should set the THRESH (threshold value) at like 10?

UPDATE: Set THRESH to 9. No input, but realised whenever a stray tail (excess thread at the back on the design) crossed into another section, it did display input in a text editor! So I think it’s something to do with the wiring? But As far as I can tell, I’ve mimicked the tutorial, down to the thickness of the thread. Will keep looking in to why it only works intermittently, but can confirm it’s not the code (except maybe the THRESH value).

EDIT: Stefan, seen your post below but I can’t reply yet, I can give that a go with some foil and crocodile clips I suppose. I didn’t know about the monitor so that will help too. I’ll try that now!

The restsitance is OK. It is a thin wire so it has quite some resistance. If you would take a three-socket 230V extender with a 3 to 5m cable and measure resistance it would be 0,2 to 0,8 Ohm. Because the wire is much thicker.

Did you read the comment in the sourcecode?

This class uses the built-in pullup resistors read the capacitance on a pin

  • The pin is set to input and then the pullup is set,
  • A loop times how long the pin takes to go HIGH.
  • The readPin method is fast and can be read 1000 times in under 10 mS.
  • By reading the pin repeated you can sense "hand pressure"
  • at close range with a small sensor. A larger sensor (piece of foil/metal) will yield
    ** * larger return values and be able to sense at more distance**. For
  • a more senstive method of sensing pins see CapTouch
  • Hook up a wire with or without a piece of foil attached to the pin.
  • I suggest covering the sensor with mylar, packing tape, paper or other insulator
    ** * to avoid having users directly touch the pin**.

Just to do another test if you have a wire 1m long and a metal plate of 5 x 5 cm or even bigger. Test it with this.

You are writing about an text-editor. Do you know that the Arduino-IDE has a serial monitor ? it is NOT a texteditor it is live monitoring what rushes in from the code whenever a command Serial.print gets executed

best regards Stefan