Pages: [1]   Go Down
Author Topic: Capacitive touch keyboard, repeating notes problem.  (Read 989 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi there....

Apologies for the general n00biness, only 3 days into Arduino....

I'm trying to adapt some code for a touch capacitive keyboard by Bas van Straaten, using  Amanda Ghassaei's tutorials and I am having some problems. At the moment when triggered, the MIDI note will repeat until a finger is taken off. I believe the problem is within the 'if' part of the sketch, however I do not know what I should replace it with. I have tried some digital.Write commands and these are invalid.



Can anyone help?

Many thanks.

The sketch is as follows

#include <CapacitiveSensor.h>
#define cal 400

CapacitiveSensor cs_2_3 = CapacitiveSensor(2,3); // 1m Ohm capacitor
CapacitiveSensor cs_2_4 = CapacitiveSensor(2,4);
CapacitiveSensor cs_2_5 = CapacitiveSensor(2,5);
CapacitiveSensor cs_2_6 = CapacitiveSensor(2,6);

int potPin = A0;
int noteON = 144;

void setup() {
// Set MIDI baud rate:
Serial.begin(9600);

}

void loop() {
 
int potVal = analogRead(potPin);
byte velocity = map(potVal, 0, 1023, 0, 127);

long total1 = cs_2_3.capacitiveSensor(30);
long total2 = cs_2_4.capacitiveSensor(30);
long total3 = cs_2_5.capacitiveSensor(30);
long total4 = cs_2_6.capacitiveSensor(30);


if (total1 > cal) {

for (int note=48;note<49;note++) {//from note 50 (D3) to note 69 (A4)
MIDImessage(noteON, note, velocity);//turn note on
delay(60);
MIDImessage(noteON, note, 0);}}//turn note off

if (total2 > cal) {
 
for (int note=49;note<50;note++) {//from note 50 (D3) to note 69 (A4)
MIDImessage(noteON, note, velocity);//turn note on
delay(60);//hold note for 300ms
MIDImessage(noteON, note, 0);}}//turn note off

if (total3 > cal) {
 
for (int note=50;note<51;note++) {//from note 50 (D3) to note 69 (A4)
MIDImessage(noteON, note, velocity);//turn note on
delay(60);//hold note for 300ms
MIDImessage(noteON, note, 0);}}//turn note off

if (total4 > cal) {
 
for (int note=51;note<52;note++) {//from note 50 (D3) to note 69 (A4)
MIDImessage(noteON, note, velocity);//turn note on
delay(60);//hold note for 300ms
MIDImessage(noteON, note, 0);}}//turn note off




}
//send MIDI message
void MIDImessage(int command, int MIDInote, int MIDIvelocity) {
Serial.write(command);//send note on or note off command
Serial.write(MIDInote);//send pitch data
Serial.write(MIDIvelocity);//send velocity data
}
« Last Edit: July 03, 2014, 03:28:56 pm by assemblyworker » Logged

Melbourne. Australia
Offline Offline
God Member
*****
Karma: 24
Posts: 742
Freelance software and hardware development based in Melbourne Australia
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Please read this http://forum.arduino.cc/index.php/topic,148850.0.html
 Specifically point 7

And then use code tags and reformat you code so that its readable

I'd recommend indenting the code properly as well. as even with code tags, your code is very hard to read.
« Last Edit: July 04, 2014, 02:23:35 am by rogerClark » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for replying and apologies for the messy code and ignorance towards the forum rules!

Code:
#include <CapacitiveSensor.h>
#define cal 400

CapacitiveSensor cs_2_3 = CapacitiveSensor(2,3); // 1m Ohm capacitor
CapacitiveSensor cs_2_4 = CapacitiveSensor(2,4);
CapacitiveSensor cs_2_5 = CapacitiveSensor(2,5);
CapacitiveSensor cs_2_6 = CapacitiveSensor(2,6);

int potPin = A0;
int noteON = 144;

void setup() {
  // Set MIDI baud rate:
  Serial.begin(9600);

}

void loop() {

  int potVal = analogRead(potPin);
  byte velocity = map(potVal, 0, 1023, 0, 127);

  long total1 = cs_2_3.capacitiveSensor(30);
  long total2 = cs_2_4.capacitiveSensor(30);
  long total3 = cs_2_5.capacitiveSensor(30);
  long total4 = cs_2_6.capacitiveSensor(30);


  if (total1 > cal) {

    for (int note=48;note<49;note++) {//from note 50 (D3) to note 69 (A4)
      MIDImessage(noteON, note, velocity);//turn note on
      delay(60);
      MIDImessage(noteON, note, 0);
    }
  }//turn note off

  if (total2 > cal) {

    for (int note=49;note<50;note++) {//from note 50 (D3) to note 69 (A4)
      MIDImessage(noteON, note, velocity);//turn note on
      delay(60);//hold note for 300ms
      MIDImessage(noteON, note, 0);
    }
  }//turn note off

  if (total3 > cal) {

    for (int note=50;note<51;note++) {//from note 50 (D3) to note 69 (A4)
      MIDImessage(noteON, note, velocity);//turn note on
      delay(60);//hold note for 300ms
      MIDImessage(noteON, note, 0);
    }
  }//turn note off

  if (total4 > cal) {

    for (int note=51;note<52;note++) {//from note 50 (D3) to note 69 (A4)
      MIDImessage(noteON, note, velocity);//turn note on
      delay(60);//hold note for 300ms
      MIDImessage(noteON, note, 0);
    }
  }//turn note off




}
//send MIDI message
void MIDImessage(int command, int MIDInote, int MIDIvelocity) {
  Serial.write(command);//send note on or note off command
  Serial.write(MIDInote);//send pitch data
  Serial.write(MIDIvelocity);//send velocity data
}


I think my problems lies in this specific part of the code, which is causing a short MIDI message to retrigger.

Code:
  if (total1 > cal) {

    for (int note=48;note<49;note++) {//from note 50 (D3) to note 69 (A4)
      MIDImessage(noteON, note, velocity);//turn note on
      delay(60);
      MIDImessage(noteON, note, 0);

I would really like to know what commands I should type so that when the sensor is touched, one MIDI message is triggered and is stopped when the trigger is released.

I have been trying to do this with the Amanda Ghassaei tutorials but the digital.Write commands don't seem to work with capacitive touch (or at least not how I'm implementing them).

I have tried various implementations of this code.....

Code:
  currentState = digitalRead(buttonPin);
  if (currentState == HIGH && lastState == LOW){
    MIDImessage(noteON, 60, 127);
    delay(2);
  } else if(currentState == LOW && lastState == HIGH){
    MIDImessage(noteON, 60, 0);
    delay(2);
  }
  lastState = currentState;

... but end up with numerous errors.

It's all a little bewildering at the moment as there is so much information online, trying to find parts that are most relevant is proving a little difficult.

Hopefully that's a little clearly and less of a ball ache to read!

Thanks...
Logged

Melbourne. Australia
Offline Offline
God Member
*****
Karma: 24
Posts: 742
Freelance software and hardware development based in Melbourne Australia
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm not an expert in Midi, but I don't know why you are sending the

Code:
      MIDImessage(noteON, note, 0);

when you've already sent noteOn for the same note with a non zero velocity value

Your comments in places seem to suggest that you think that sending this turns off the note, AFIK it doesn't do that

e.g. an example to turn off a not is

Code:
MIDImessage(noteOFF, note, velocity);//turn note off

i.e the noteOFF command


I think you need to get one note on one pad working before you attempt to program all the pads

Also rather than continuously sending noteOn commands, you need to store the last state of each note e.g. playing or not playing and if its already playing and you enter the loop()n function again and need it to continue, then you don't need to resend the noteON command (as its already on)

Probably the best method is to use an array to store the last state of each of your pads

e.g.

Code:
boolean pads[NUMBER_OF_PADS]={false,false,false etc etc etc};

Then in your loop()

check each capacitive input to determine the state of each pad to give you an ON or OFF e.g. newPadState = ON
then
Code:
if (pads[0]!=newPadState)
{
pads[0]=newPadState;
if (newPadState==ON)
{
// TURN NOTE ON
}
else
{
// TURN NOTE OFF
}

}

Note this isnt real code its just an indication of a possible way to code this

You can use a for loop to iterate all your pads etc rather than using pads[0] and pads[1] as long as you can access the data from the correct sensor at the same time  (if you see what I mean)

BTW, I'm sure someone else will post a more elegant solution, but its something to think about before then ;-)

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Many thanks for the response....

The reason for the MIDI velocity 0 command was that I had read that this is quite a common implementation instead of the MIDI off command. However, I have changed that now (I had tried before but since realised I didn't add an int command at the top.)


I will try the additional loop part over the next day or so, thanks again for the help.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#include <CapacitiveSensor.h>

CapacitiveSensor cs_2_3 = CapacitiveSensor(2,3); // 1m Ohm capacitor


byte noteON = 144;
byte noteOFF = 128;
boolean total1 > 500 = true;
boolean total1 < 500 = false;

void setup() {
  Serial.begin(9600);
}

void loop() {

  long total1 = cs_2_3.capacitiveSensor(30);



  if (total1>500 == true && total1<500 == false) {
    MIDImessage(noteON, 60, 127);
    delay(2);

  }
  else if (total1>500 == false && total1<500 == true){

    MIDImessage(noteOFF, 60, 0);
    delay(2);
  }
}

void MIDImessage(byte command, byte data1, byte data2) {
  Serial.write(command);
  Serial.write(data1);
  Serial.write(data2);
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For the record I now have this working with the following code based on work by Bas van Straaten and Amanda Ghassaei if it helps anyone.

Although I'm curious to know why the 'for' section is needed

for (int note=60;note<61;note++) {


As this to me suggests that it is meant for running a sequence when just a single not is required. If anyone can clear that up it would be really cool.


The working code...

Code:
#include <CapacitiveSensor.h>
#define cal 400

CapacitiveSensor cs_2_3 = CapacitiveSensor(2,3);

int ledPin1 = 11;

byte noteON = 144;
byte noteOFF = 128;

void setup(){
  pinMode(ledPin1, OUTPUT);

}
void loop(){

  long total1 = cs_2_3.capacitiveSensor(30);
  static int lastInput1 = 0;
  int newInput1 = total1;

  if (total1 > cal) {
    digitalWrite(11, HIGH);
  }
  else{
    digitalWrite (11, LOW);
  }

  if((lastInput1 < cal) && (newInput1 > cal)) {
    for (int note=60;note<61;note++) {
      MIDImessage(noteON, 60, 127);
    }
  };
  if((lastInput1 > cal) && (newInput1 < cal)) {
    for (int note=60;note<61;note++) {
      MIDImessage(noteOFF, 60, 0);
    }
  };
  lastInput1 = newInput1;

}
void MIDImessage(byte command, byte data1, byte data2){
  Serial.write(command);
  Serial.write(data1);
  Serial.write(data2);


}





 
Logged

Pages: [1]   Go Up
Jump to: