Arduino Forum

Topics => Interactive Art => Topic started by: AeonSair on May 28, 2014, 05:13 am

Title: Changing DrumKit Sketch to Only Read One Hit at a Time
Post by: AeonSair on May 28, 2014, 05:13 am
Hi, I'm running a version of SpikenzieLab's DrumKitAI Sketch on an Arduino Duemilanove w/ATmega 328. The drum kit sketch is meant to be used with multiple piezo sensors that are mounted on separate pads/drums. However, for my project I am mounting all of my piezo sensors on a single piece of thin wood. I need to the sketch to only register one hit at a time so that there wont be any crosstalk between sensors. I was hoping someone could describe/show me how to change the sketch to only read the sensor with the highest vibration for each hit. Here is the code I am using:
[font=Verdana]
Code: [Select]
//  BY: MARK DEMERS Copywrite 2009
//  April. 2009
//  VERSION: 1.b
//
//  DESCRIPTION:
//  Arduino analog input used to sense piezo drum hits then sent serialy to processing.

//*******************************************************************************************************************
// User settable variables
//*******************************************************************************************************************

unsigned char PadNote[6] = {40,36,50,63,40,65};         // MIDI notes from 0 to 127 (Mid C = 60)

int PadCutOff[6] = {580,700,280,600,600,600};           // Minimum Analog value to cause a drum hit

int MaxPlayTime[6] = {90,120,70,90,90,90};               // Cycles before a 2nd hit is allowed

#define  midichannel 0;                              // MIDI channel from 0 to 15 (+1 in "real world")

boolean VelocityFlag  = true;                           // Velocity ON (true) or OFF (false)





//*******************************************************************************************************************
// Internal Use Variables
//*******************************************************************************************************************

boolean activePad[6] = {0,0,0,0,0,0};                   // Array of flags of pad currently playing
int PinPlayTime[6] = {0,0,0,0,0,0};                     // Counter since pad started to play

unsigned char status;

int pin = 0;     
int hitavg = 0;

//*******************************************************************************************************************
// Setup
//*******************************************************************************************************************

void setup()
{
  Serial.begin(57600);                                  // connect to the serial port 115200
}

//*******************************************************************************************************************
// Main Program
//*******************************************************************************************************************

void loop()
{
  for(int pin=0; pin < 6; pin++)
  {
    hitavg = analogRead(pin);                              // read the input pin

    if((hitavg > PadCutOff[pin]))
    {
      if((activePad[pin] == false))
      {
        if(VelocityFlag == true)
        {
  //        hitavg = 127 / ((1023 - PadCutOff[pin]) / (hitavg - PadCutOff[pin]));    // With full range (Too sensitive ?)
          hitavg = (hitavg / 8) -1 ;                                                 // Upper range
        }
        else
        {
          hitavg = 127;
        }

        MIDI_TX(144,PadNote[pin],hitavg);
        PinPlayTime[pin] = 0;
        activePad[pin] = true;
      }
      else
      {
        PinPlayTime[pin] = PinPlayTime[pin] + 1;
      }
    }
    else if((activePad[pin] == true))
    {
      PinPlayTime[pin] = PinPlayTime[pin] + 1;
     
      if(PinPlayTime[pin] > MaxPlayTime[pin])
      {
        activePad[pin] = false;
        MIDI_TX(128,PadNote[pin],127);
      }
    }
  }
}


//*******************************************************************************************************************
// Transmit MIDI Message
//*******************************************************************************************************************
void MIDI_TX(unsigned char MESSAGE, unsigned char PITCH, unsigned char VELOCITY)
{
  status = MESSAGE + midichannel;
  Serial.write(status);
  Serial.write(PITCH);
  Serial.write(VELOCITY);
}
[/size][/size][/size][/font]
/code]

Thank you for any help/suggestions![size=10pt][size=10pt][font=Verdana][size=10pt][/size][/font][/size][/size]
Title: Re: Changing DrumKit Sketch to Only Read One Hit at a Time
Post by: Grumpy_Mike on May 28, 2014, 06:32 am
I don't think you can. If they are all on the same piece of wood they will all get the same hit and there is nothing you can do to distinguish between them as all the signals will look the same.
Title: Re: Changing DrumKit Sketch to Only Read One Hit at a Time
Post by: AeonSair on May 28, 2014, 08:01 am
The Piezos are able to measure the velocity of each hit based on the amount of vibration. The sketch even allows me to create a minimum velocity needed to send a MIDI signal. It seems like the code should be able to be altered to only allow a single MIDI note to be registered at a time (the note from the piezo with the strongest signal/vibration). Or am I missing something?

I should also note that currently, using the filter already built into the code, hitting the piece of wood only sends a signal from the nearest coupled of piezos. I used the Arduino Serial Monitor and recorded the data from various hits. It appears to be constant that the piezo nearest the point of contact for each hit sends the greatest value for the Velocity variable.
Title: Re: Changing DrumKit Sketch to Only Read One Hit at a Time
Post by: Grumpy_Mike on May 28, 2014, 03:26 pm
Try this then:-
Code: [Select]

void loop()
{
  int pin = 0;
  boolean noHit = true;
  while(pin < 6 && noHit){
    hitavg = analogRead(pin);                              // read the input pin
    if((hitavg > PadCutOff[pin]))
    {
       MIDI_TX(144,PadNote[pin],hitavg);
        noHit = false;
      }
    }   
    delay(100); // adjust for length of time to play note
        MIDI_TX(128,PadNote[pin],127);
        noHit = true;
      }


Note:- completely untested because only you have the hardware. It does compile however.
Title: Re: Changing DrumKit Sketch to Only Read One Hit at a Time
Post by: AeonSair on May 28, 2014, 07:57 pm
I just tried it and only the signals from the first sensor are coming through. I tried changing the PadCutOff to the lowest value for all the other sensors while increasing the PadCutOff for the first one, but I still can't get any of the other pads to register a hit.
Title: Re: Changing DrumKit Sketch to Only Read One Hit at a Time
Post by: Grumpy_Mike on May 28, 2014, 08:23 pm
Sorry I missed out a
Code: [Select]
pin++;
From that.
It goes just before the closing brace of the while statement.
Title: Re: Changing DrumKit Sketch to Only Read One Hit at a Time
Post by: AeonSair on May 28, 2014, 11:21 pm
I'm having trouble understanding where to insert that. I don't know very much about programming, just what I've learned in the past week.
Title: Re: Changing DrumKit Sketch to Only Read One Hit at a Time
Post by: Grumpy_Mike on May 28, 2014, 11:36 pm
I could believe you are not trying. I said:-
Quote
It goes just before the closing brace of the while statement.


If you click on the opening brace the closing brace gets highlighted. Remember that, in the mean time:-
Code: [Select]

void loop()
{
  int pin = 0;
  boolean noHit = true;
  while(pin < 6 && noHit){
    hitavg = analogRead(pin);                              // read the input pin
    if((hitavg > PadCutOff[pin]))
    {
       MIDI_TX(144,PadNote[pin],hitavg);
        noHit = false;
      }
      pin++;
    }   
    delay(100); // adjust for length of time to play note
        MIDI_TX(128,PadNote[pin],127);
        noHit = true;
      }
Title: Re: Changing DrumKit Sketch to Only Read One Hit at a Time
Post by: AeonSair on May 29, 2014, 02:08 am
Thank you. I just uploaded the new sketch but the readings are going crazy. It appears that after the first piezo is triggered, a loop is occurring and sending a "note off" MIDI message. I've attached a screenshot of my MIDI monitor. I also tried running the sketch with all the user variables set to the default value but the same thing is happening. After the loop starts it appears that none of the Piezos can be triggered.
Title: Re: Changing DrumKit Sketch to Only Read One Hit at a Time
Post by: Grumpy_Mike on May 29, 2014, 06:53 am
Try this then
Code: [Select]

void loop()
{
  int pin = 0;
  boolean noHit = true;
  while(pin < 6 && noHit){
    hitavg = analogRead(pin);                              // read the input pin
    if((hitavg > PadCutOff[pin]))
    {
       MIDI_TX(144,PadNote[pin],hitavg);
        noHit = false;
      }
      pin++;
    }
   if(!noHit){   
    delay(100); // adjust for length of time to play note
        MIDI_TX(128,PadNote[pin],127);
        noHit = true;
      }
}