Adding octave buttons for piano?

Hi,

I want to make a touch sensor piano using the capsense library. I have found a project on instructables and will use that code. I understand what the sketch is doing but I am having a hard time understanding how to go about adding some octave buttons to the code. I want 8 keys and two keys left for octaveUp and octaveDown (I know this sketch is set for just 8, I’ll add those later).

Here’s the code:

#include <CapacitiveSensor.h>

#define numberOfInputs 8      //choose the number of inputs
#define Thresshold 700          //define the thresshold 

long total[numberOfInputs];
long lastTotal[numberOfInputs];
boolean midi_on[numberOfInputs];
boolean midiMode = true;       // if midiMode is false, the Arduino is in Debug mode. Make sure to put the midiMode to true if you want the Arduino to act as a Midi device

int octave;


CapacitiveSensor   cs_2_3 = CapacitiveSensor(2,3);        //you may have to comment some of these out..
CapacitiveSensor   cs_2_4 = CapacitiveSensor(2,4);
CapacitiveSensor   cs_2_5 = CapacitiveSensor(2,5);
CapacitiveSensor   cs_2_6 = CapacitiveSensor(2,6);
CapacitiveSensor   cs_2_7 = CapacitiveSensor(2,7);
CapacitiveSensor   cs_2_8 = CapacitiveSensor(2,8);
CapacitiveSensor   cs_2_9 = CapacitiveSensor(2,9);
CapacitiveSensor   cs_2_10 = CapacitiveSensor(2,10);




void setup() {

    Serial.begin(9600);
  }

void loop() {
  for( int i = 1; i < numberOfInputs; i++) {             //Semd a MIDI message for the corresponding input
    if (total[i] > Thresshold && !midi_on[i]) {
      sendMidi(0x90, 60 + i + octave * 12, 127);                      
      midi_on[i] = true;
    }
    if (total[i] < Thresshold && midi_on[i]) {
      sendMidi(0x90, 60 + i, 0);//turn note off
      midi_on[i] = false;
    }
   
  
  total[1] =   cs_2_3.capacitiveSensor(30);              //you may have to comment some of these out..
  total[2] =   cs_2_4.capacitiveSensor(30);
  total[3] =   cs_2_5.capacitiveSensor(30);
  total[4] =   cs_2_6.capacitiveSensor(30);
  total[5] =   cs_2_7.capacitiveSensor(30);
  total[6] =   cs_2_8.capacitiveSensor(30);
  total[7] =   cs_2_9.capacitiveSensor(30);
  total[8] =  cs_2_10.capacitiveSensor(30);
  }
}

//send MIDI message
void sendMidi(int Statusbyte, int Databyte1, int Databyte2) {
  if (midiMode) {
    Serial.write(Statusbyte);//send note on or note off command 
    Serial.write(Databyte1);//send pitch data
    Serial.write(Databyte2);//send velocity data
  }
  else { 
    if (Databyte2 == 127) {
      Serial.println("Note On");
    }
    else {
      Serial.println("Note Off");
    }
  }
}

I have addedint octave and + octave * 12 to the loop with no success (I kind of knew that wasn’t going to do the job. My question is, am I on the right track by doing this? Do I need to initiate pinMode in ‘void setup’ or something similar?

I’m a tad lost but with a little help I know I’ll be able to figure it out so any help would be super appreciated!

First a bug: total[8] is outside the array, use 0 to 7 for the array index. The for loop also should start at i=0; while i<numberOfInputs.

Then define the additional octave sensors, read their values when filling the total array and set octave accordingly.

I’d move the code for reading the sensors into a subroutine, and call it at the begin of loop(), not at the end.

Hi DrDiettrich,

Thanks for your respone.

The bug pointing to the total[8] makes sense now as in my test sketch I was having to define an extra input to use all the keys and it was using C# as the base note which was confusing me.

Could you clarify a few things for me that you have said to do:

By defining the octave sensors do you me something like:

#define octaveUp 12
#define octaveDown -12

As for reading the values, how would I dod that?

Sorry if this should be crystal clear, i'm just starting out on the world of Arduino :slight_smile:

Many thanks!

For the octave sensors you have to declare variables (CapacitiveSensor cs... = ...), then get their states (cs...capacitiveSensor(30);). When one is pressed, put the according value into octave, zero when none is pressed, and consider what should happen when both are pressed at the same time.

Ahh, Ok so you are just declaring the variable, I get that now - thanks :slight_smile:

Ok, so the values has to be put into octave through #define at the top of the sketch, or the int octave?

Thanks for your patience with this. I will get there if I keep asking questions :wink:

If someone could just show me an example to fill in the gaps that would be great. I'm not asking so it's just done for me so I don't learn anything but so I can see how these things are implemented properly and then can ask how or why these things work the way they do.

C++ is like a foreign language to me at the moment. I have looked at some tutorials online and understand some basic terms but just don't quite get how to expand on certain things.

Many thanks :wink:

Still not managing to figure this out?? :confused:

Anybody care to help me with this?

Thanks!

I'm not sure what you want the extra buttons to do. Do you want the user to hold the button down to maintain the octave change?

If you just want a single press to do it, how long should the button be pressed to count as a real press? If the button is pressed twice, how long between presses does it need to be to count as a separate press?

Did you tell us how many octaves up or down you want?

Ah, OK sorry if I have not explained properly. I'd like to have 8 buttons to play a scale. For instance: C D E F G A B (C). I'd like to have 2 octave buttons, one to increase the octave and one to decrease the octave ie: if I increased the octave the keys would then represent D E F G A B C (D) and so on.

The octave buttons will act as a normal button presses and with one press increase, or decrease with a range of 3-4 octave each way. I'd like the buttons to be pressed and they change instantly if that makes sense.

I hope that explains a little better in what I'm trying to achieve?

Thanks!

NB: There will be a total of 10 buttons. 8 for the piano keys, and two for the octave buttons!

PolyKrome:
For instance: C D E F G A B (C). I'd like to have 2 octave buttons, one to increase the octave and one to decrease the octave ie: if I increased the octave the keys would then represent D E F G A B C (D) and so on.

While it would certainly be possible to change the keys this way, it seems a very odd way to shift octaves. I'd think if your initial keys started with C, you'd want all the octaves to start with C.

If no one beats me to it, I'll take a close look at your code to see if I can offer some suggestions.

Yes you're quite right. I was thinking in a whole tone shift for some reason. While thinking about it, I think semitone shifts would be the best option.

If you can tweak the code so I can see what is going on then I'll be able to adjust that myself I think.

I have been looking up on tutorials and getting more familiar with terms and what basic functions do etc. I understand what is going on in a basic demo sketch I'm just having trouble expanding on sketches so seeing how this can be implemented will help me greatly.

Many thanks for the help!!

You should not multiply the octave variable by anything but just add it into the sum to get the midi number. This variable should be set initially to zero, you don't do this but luckily for you it gets set to zero anyway.
If you see the octave up button pressed you make this variable equal to 12, plus what ever value it is currently with

octiave = octiave + 12

There are more subnet ways of writing this.
Similarly the down button should subtract 12.

Now to stop the value in going beyond these limits of +12 and -12 you use an if statement to test if octiave is already at the end of its travel limits. You also need to wait after you see the up or down button pressed until it becomes unpressed.

Thanks for the reply, Mike.

This variable should be set initially to zero

So I should do this?:

int octave = 0;

You should not multiply the octave variable by anything but just add it into the sum to get the midi number

So if I just add add ‘octave’ without the multiplier like so?

 for( int i = 1; i < numberOfInputs; i++) {             //Semd a MIDI message for the corresponding input
    if (total[i] > Thresshold && !midi_on[i]) {
      sendMidi(0x90, 60 + i + octave, 127);                      
      midi_on[i] = true;

One of my biggest drawbacks so far is how do I assign the ‘octave buttons’ to say: total[10] = cs_2_10.capacitiveSensor(30); for an example (I know this isn’t in the sketch just yet, I’ll add it later). Do I do this via pinMode and digitalWrite?

I appreciate the feedback and apologise if this is glaringly obvious!

So I should do this?:

Yes.

So if I just add add ‘octave’ without the multiplier like so?

Yes.

how do I assign the ‘octave buttons’ to say: total[10] = cs_2_10.capacitiveSensor(30);

Why would you want to do that?

In the first post you said:-

I want 8 keys and two keys left for octaveUp and octaveDown (I know this sketch is set for just 8, I’ll add those later).

Better add them now so we know what you are thinking. For example do you want this octave up and down button to be cap sense buttons? The problem will be that the cap sense example used here is not very robust and you will have trouble extending it to an unlimited number of buttons.

This sort of thing ( octave up / down not cap sense ) is covered in my new book:-

Hi Mike,

Yes I would like them to be capsense buttons because I need the room for this project I want to build. The keys need to be as thin as possible. I will only ever need 8 buttons for this project so I will not need to expand this to an unlimited number of buttons - is this still do-able to use capsense buttons? If the sketch is not robust enough, maybe I could squeeze and pot for the octave up and down, but it would be a last resort.

Here is the updated sketch with the above revisions for reference:

#include <CapacitiveSensor.h>

#define numberOfInputs 10       //8 inputs for 'keys' buttons and two for octave up and down.
#define Thresshold 700          //Define the thresshold. 


long total[numberOfInputs];
long lastTotal[numberOfInputs];
boolean midi_on[numberOfInputs];
boolean midiMode = true;       // If midiMode is false, the Arduino is in Debug mode. Make sure to put the midiMode to true if you want the Arduino to act as a Midi device.

int octave = 0;

CapacitiveSensor   cs_2_3 = CapacitiveSensor(2,3);       
CapacitiveSensor   cs_2_4 = CapacitiveSensor(2,4);
CapacitiveSensor   cs_2_5 = CapacitiveSensor(2,5);
CapacitiveSensor   cs_2_6 = CapacitiveSensor(2,6);
CapacitiveSensor   cs_2_7 = CapacitiveSensor(2,7);
CapacitiveSensor   cs_2_8 = CapacitiveSensor(2,8);
CapacitiveSensor   cs_2_9 = CapacitiveSensor(2,9);
CapacitiveSensor   cs_2_10 = CapacitiveSensor(2,10);
CapacitiveSensor   cs_2_11 = CapacitiveSensor(2,11);
CapacitiveSensor   cs_2_12 = CapacitiveSensor(2,12);

////////////////////////////////////////////////////////////


void setup() {

    Serial.begin(31250); //Begin MIDI.
  }

////////////////////////////////////////////////////////////

void loop() {
   
  total[0] =   cs_2_3.capacitiveSensor(30);            
  total[1] =   cs_2_4.capacitiveSensor(30);
  total[2] =   cs_2_5.capacitiveSensor(30);
  total[3] =   cs_2_3.capacitiveSensor(30);              
  total[4] =   cs_2_4.capacitiveSensor(30);
  total[5] =   cs_2_5.capacitiveSensor(30);
  total[6] =   cs_2_3.capacitiveSensor(30);             
  total[7] =   cs_2_4.capacitiveSensor(30);
  // Set capacitive sensor for octave buttons.
  total[8] =   cs_2_6.capacitiveSensor(30);
  total[9] =   cs_2_6.capacitiveSensor(30);

////////////////////////////////////////////////////////////

  for( int i = 0; i < numberOfInputs; i++) {             //Send a MIDI message for the corresponding input.
    if (total[i] > Thresshold && !midi_on[i]) {
      sendMidi(0x90, 60 + i + octave, 127);                      
      midi_on[i] = true;
    }
    if (total[i] < Thresshold && midi_on[i]) {
      sendMidi(0x90, 60 + i, 0);                         //Turn note off.
      midi_on[i] = false;
    }
  }
}

/////////////////////Send MIDI Message//////////////////////

void sendMidi(int Statusbyte, int Databyte1, int Databyte2) {
  if (midiMode) {
    Serial.write(Statusbyte);//send note on or note off command 
    Serial.write(Databyte1);//send pitch data
    Serial.write(Databyte2);//send velocity data
  }
  else { 
    if (Databyte2 == 127) {
      Serial.println("Note On");
    }
    else {
      Serial.println("Note Off");
    }
  }
}

is this still do-able to use capsense buttons?

I have not used this library myself so I can't tell, a lot will depend on your physical system. However cramming in all into a small space is the opposite of what is desirable with capacitive sensing.

As to the code, you need to treat the up and down buttons separately and not as part of the keyboard scan. So they should not be included in the sending MIDI loop like you have them.

Ah, OK I'll experiment a little and see what I can do. Thanks for the help, Mike!

In regards to your book, I can't buy anything just yet as Christmas has slapped me around the face, financially speaking, but it could be a good investment in a couple of months!

Cheers!

Ok, I have tweaked the code to be able to use a capsense button as an octave up button…to a point.

The only problem is that it is going up by an octave and two semitones ie: C3 to D4 - which is weird. I guess that must be a problem with the sum, or I’m not adding enough math into my new octave up button so to speak.

Also, once I have pressed the octave up button and then press a ‘key’ button the midi not just ‘hangs’. I guess this is because somewhere I need to turn midi off if the octave button is pressed?

Here is the code, shortened down for just four buttons so I can debug more easily:

#include <CapacitiveSensor.h>

#define numberOfInputs 4       //8 inputs for 'keys' buttons and two for octave up and down.
#define Thresshold 700         //Define the thresshold 
#define octave_buttons 1        //Define octave buttons

long total_octave[octave_buttons];
long total[numberOfInputs];
long lastTotal[numberOfInputs];
boolean midi_on[numberOfInputs];
boolean midiMode = true;       // if midiMode is false, the Arduino is in Debug mode. Make sure to put the midiMode to true if you want the Arduino to act as a Midi device

int octave = 0;

CapacitiveSensor   cs_2_3 = CapacitiveSensor(2,3);       
CapacitiveSensor   cs_2_4 = CapacitiveSensor(2,4);
CapacitiveSensor   cs_2_5 = CapacitiveSensor(2,5);
CapacitiveSensor   cs_2_6 = CapacitiveSensor(2,6);


////////////////////////////////////////////////////////////


void setup() {
  if (midiMode) {
    Serial.begin(31250);
  }
  else {
    Serial.begin(9600);
  }
  
}

////////////////////////////////////////////////////////////

void loop() {
   
  total[0] =   cs_2_3.capacitiveSensor(30);            
  total[1] =   cs_2_4.capacitiveSensor(30);
  total[2] =   cs_2_5.capacitiveSensor(30);
  // Set capacitive sensor for octave buttons.
  total_octave[0] =   cs_2_6.capacitiveSensor(30);


////////////////////////////////////////////////////////////

  for( int i = 0; i < numberOfInputs; i++) {             //Send a MIDI message for the corresponding input
    if (total[i] > Thresshold && !midi_on[i]) {
      sendMidi(0x90, 60 + i + octave, 127);                      
      midi_on[i] = true;
    }
    if (total[i] < Thresshold && midi_on[i]) {
      sendMidi(0x90, 60 + i, 0);                         //turn note off
      midi_on[i] = false;
    }
  }
////////////////////Set octave up button //////////////////

  if (total_octave[0] > Thresshold) {
      octave = octave + 12;                     
    }         

}
/////////////////////send MIDI message//////////////////////

void sendMidi(int Statusbyte, int Databyte1, int Databyte2) {
  if (midiMode) {
    Serial.write(Statusbyte);//send note on or note off command 
    Serial.write(Databyte1);//send pitch data
    Serial.write(Databyte2);//send velocity data
  }
  else { 
    if (Databyte2 == 127) {
      Serial.println("Note On");
    }
    else {
      Serial.println("Note Off");
    }
  }
}

I have stopped the midi note from hanging. I had forgotten to add 'octave' to the midi 'note off' sum.

I'm still having trouble with the the octave up shifting from C3 to D4 and so on. I am having to use:

octave = octave + 1

in order to shift just one octave (with the bug still happening - C3 to D4). If I am to use +12 it will shift 12 octaves.

Anyone shed any light on this? (Mike)

Cheers!