reading piezo for midi note velocity

Hi all, I’ve been working on a midi drum controller for some time now. At the moment I am able to trigger note on/pff messages using 16 piezos, however the notes all have a fixed velocity of max 127 or 0. How can I get velocity based on how hard or soft I hit the sensor? I’ve read a lot of posts on the topic including this one http://www.workinprogress.ca/projects/edubeat/source/ see original post http://lists.puredata.info/pipermail/pd-list/2011-06/089407.html these deal with shaping the signal by adding a capacitor , which I intend to do. I also read this post http://arduino.cc/forum/index.php?topic=65113.0 which deal with velocity like this

So what happens is, as soon as I strike the piezo, I hear a piano note
from my PC speakers…
I also modified the sketch so that instead of ‘127’ as the midi
velocity, I send the analog read value divided by 8 (max value from
analog read is 1023, and max midi velocity value is 127) to the
software
So now I’ve got the basic idea working with ‘velocity’ sensing

Can anyone help me implement velocity sensing like mentioned above or other in the sketch below

/* Midi Footsteps - Mike Cook Feb 2010
 *
 * -----------------
 * send MIDI serial data, for multiplexed pressure pad sensors
 *
 *
###############################################################################################

HARDWARE NOTE:
The MIDI Socket is connected to arduino TX through a PNP transistor to
invert the MIDI signal.

 *  Arduino analog input 5 - I2C SCL
 *  Arduino analog input 4 - I2C SDA
 *  Using 1 MCP23016 I2C expanders at addresses 0 to drive indicator LEDs
 *  Two 8 to 1 multiplexers feeding A0 and A1 controlled by Pins 4, 5 & 6

 *  Output MIDI CC values from 16 to 32 (depending on what sensor is triggered)
   with a value of 0 or 127 depending if the sansor returns
   a number greater than or less than that held in the threshold variable.

################################################################################################
*/
// Includes
#include <Wire.h>
#include <avr/pgmspace.h>
#include "Defines.h"
#include "pitches.h"
 //#define MIDI_TEST   // un comment for a test to format the data for
the seril monitor
// notes to play, corresponding to the 12+ sensors:
int notes[] = { NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6,
NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6,
NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5 };//soprano

// Start of code
void setup() {
 //  set the states of the I/O pins to drive the sensor multiplexer:
  pinMode(s0Pin, OUTPUT);
  pinMode(s1Pin, OUTPUT);
  pinMode(s2Pin, OUTPUT);
  lastLedVal = 0;

 // Setup I2C devices
  Wire.begin();                      // start the I2C interface
  
  doSensorScan();                                        // get initial states
  saveCurrentState();

 //  Setup serial / MIDI
#ifdef MIDI_TEST
    Serial.begin(9600);    // Debug speed
#else
    Serial.begin(31250);       // MIDI speed
#endif
}

//********************* MAIN LOOP ***********************************

void loop() {
   doSensorScan();
   lookForChange();
   saveCurrentState();
 //   delay(400);
   } // end loop function

//********************* Functions ***********************************

void doSensorScan() {  // look at all the sensors
 for(int i=0; i<8; i++){
  // select multiplexer channel
  digitalWrite(s0Pin, i & 0x1);
  digitalWrite(s1Pin, (i>>1) & 0x1);
  digitalWrite(s2Pin, (i>>2) & 0x1);
  delay(1);            // delay to allow sample & hold capictor to charge
  currentState[i] = analogRead(mux1); // read mux1 in first 8 array locations
  delay(1);            // delay to allow sample & hold capictor to charge
  currentState[i+8] = analogRead(mux2); // read mux2 in last 8 array locations
 }
}

void saveCurrentState(){  // save the current state for next time
 for(int i=0; i<16; i++){
   lastState[i] = currentState[i];
 }
}

void printCurrentSatae(){   // for debugging use
 Serial.print(" one ");
  for(int i=0; i<3; i++){
   Serial.print(currentState[i], HEX);
  Serial.print(" ");
  }
  Serial.println(" ");
    Serial.print(" two ");
     for(int i=0; i<3; i++){
   Serial.print(currentState[i+8], HEX);
  Serial.print(" ");
  }
}

// the value of threshold determins the on / off point
void lookForChange(){
 int ledVal = 0;
 int ledMask = 1;
 for(int i=0; i<16; i++){
   if(currentState[i] < threshold) ledVal |= ledMask;   // add a 1 in
the position of sensors under threshold
    ledMask = ledMask << 1;
  }
  if(lastLedVal != ledVal) {   // something has changed
  ledMask = 1;
    for(int i=0; i<16; i++){
      if((ledMask & ledVal) != (ledMask & lastLedVal)){
        if((ledMask & ledVal) == 0) {
          // note off
          controlSend(0x80, control[i], 0x00);   // turn off control message
noTone(8);
digitalWrite(ledPin,LOW);
          }
        else{
          // note on
          controlSend(0x90, control[i], 0x7f);  // turn on control message
tone(8, notes[i], 20);
digitalWrite (ledPin,HIGH);
          }
      }
      ledMask = ledMask << 1;
    }
    // Update the trigger LEDs
      gpio_writeByteInverse(ledAddress, ledVal, I2CregisterInput);
  }
  lastLedVal = ledVal;        // record current state of LEDs and
MIDI notes / messages
  digitalWrite(ledPin,LOW);
}

//  plays a MIDI note

#ifdef MIDI_TEST
// This is a test so format data for viewing in the serial monitor
 void controlSend(char cmd, char data1, char data2) {
 cmd = cmd | char(midiChannel);  // merge channel number
 Serial.print(((cmd >> 4) & 0xf), HEX);  // to prevent leading Fs
being displayed
 Serial.print((cmd & 0xf), HEX);
 Serial.print(" ");
 Serial.print(data1, HEX);
 Serial.print(" ");
 Serial.println(data2, HEX);

}

#else
 // no test so send the stuff out to MIDI
 void controlSend(char cmd, char data1, char data2) {
 cmd = cmd | char(midiChannel);  // merge channel number
 Serial.print(cmd, BYTE);
 Serial.print(data1, BYTE);
 Serial.print(data2, BYTE);
}
==========
new Tab
========
defines.h

// Defines
// I2C registers
#define I2CregisterInput 0
#define I2CregisterOutput 2
#define I2CregisterPolarity 4
#define I2CregisterConfig 6
#define I2CregisterInterrupt 8
#define I2CregisterExpander 10
// I2C device addresses
#define ledAddress   (0x20 | 0x0)     // address of trigger LED
indicators output
// Control Switch device bit masks
#define ddrTrigger 0x00000     // data direction register for trigger
indictor LEDs

// Arduino pin assignments

#define midiChannel (byte)0

// Define constants
const int s0Pin = 2;  // multiplexer select pins
const int s1Pin = 3;
const int s2Pin = 4;
const int mux1 = 0;   // analogue port multiplexer 1 is read on
const int mux2 = 1;   // analogue port multiplexer 2 is read on
#define ledPin     13  // for midi out status
// Variable definations
int currentState[16]; // current state of sensors
int lastState[16];    // the last state of the sensors
int threshold = 0x90;  // sets the threshold value in deciding if a
sensor is pressd.
int lastLedVal;
char control[16] = { 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75};
// notes to play, corresponding to the 16 sensors:

Thank you in advance,
Caesar

Replace this line:-

controlSend(0x90, control[i], 0x7f);  // turn on control message

with

controlSend(0x90, control[i], currentState[i]>>3);  // turn on control message

Thanks Mike!

from looking at the serial monitor I can see that I'm now getting varying velocity values. sweet. I had to double check bu the tone library docs says to control volume use a resistor. Again that would control all audio output at once. Can the tone command have a similar velocity variable? MY next post will be one adding a 12bit DAC for audio synth. but for now now my finale question has to do with polyphony. How many notes can I play simultaneously, as in chords, using an arduino board and multiplexers?

Can the tone command have a similar velocity variable?

No, there is no hardware to alter the amplitude is is just a digital output.