Piezo MIDI Drums

Hi I could use some help.
I have simple MIDI drums based on piezo sensors. I use this code:

int piezo1 = A0;
int piezo2 = A2;
int piezo3 = A4;
int piezo4 = A6;
int piezo5 = A8;
int threshold = 500;
int sensorReading = 0;
int val,oldcas;

void setup() {

pinMode(piezo1, INPUT);
pinMode(piezo2, INPUT);
pinMode(piezo3, INPUT);
pinMode(piezo4, INPUT);
pinMode(piezo5, INPUT);
Serial.begin(57600);

}

void loop() {

//////////////////CRASH////////////////

sensorReading = analogRead(piezo5);

if( sensorReading > threshold ) {
oldcas = millis()+5;
while(analogRead(piezo5) > threshold)
{
if(millis()==oldcas)
{
val = analogRead(piezo5) / 8;
}
}

MidiTX(144, 1, val);
MidiTX(128, 1, val);
}

//////////R-TOM////////////////////

sensorReading = analogRead(piezo4);

if( sensorReading > threshold ) {
oldcas = millis()+5;
while(analogRead(piezo4) > threshold)
{
if(millis()==oldcas)
{
val = analogRead(piezo4) / 8;
}
}

MidiTX(144, 2, val);
MidiTX(128, 2, val);
}

///////////////SNARE////////////////

sensorReading = analogRead(piezo3);

if( sensorReading > threshold ) {
oldcas = millis()+5;
while(analogRead(piezo3) > threshold)
{
if(millis()==oldcas)
{
val = analogRead(piezo3) / 8;
}
}

MidiTX(144, 3, val);
MidiTX(128, 3, val);
}

///////////////L-TOM/////////////

sensorReading = analogRead(piezo2);

if( sensorReading > threshold ) {
oldcas = millis()+5;
while(analogRead(piezo2) > threshold)
{
if(millis()==oldcas)
{
val = analogRead(piezo2) / 8;
}
}

MidiTX(144, 4, val);
MidiTX(128, 4, val);
}

//////////////HI-HIT/////////////////

sensorReading = analogRead(piezo1);

if( sensorReading > threshold ) {
oldcas = millis()+5;
while(analogRead(piezo1) > threshold)
{
if(millis()==oldcas)
{
val = analogRead(piezo1) / 8;
}
}

MidiTX(144, 5, val);
MidiTX(128, 5, val);
}
}

void MidiTX(unsigned char StatusByte, unsigned char Note, unsigned char Val)
{
Serial.write(StatusByte);
Serial.write(Note);
Serial.write(Val);
}

with virtual MIDI port loopbe1 , Serial - MIDI converter V2D (by Mark Demers - Spikenzielab.com) and Battery 3 as sample player. but audio from battery is delayed. I tryed another SW with Battery 3 ( Maple Virtual Midi Cable as virtual midi port and Hairless MIDI<->Serial Bridge as converter ) but ther is still delay.

where is problem??

I have tried to simplify the code to make it easier to debug. I have created a function that does everything your code was repeating once to avoid cut an paste and make things more consistent.

#define  MAX_PIEZO  5

uint8_t piezo[MAX_PIEZO] = { A0, A2, A4, A6, A8 };
uint8_t drumType[MAX_PIEZO] = { 5, 4, 3, 2, 1 };

const int threshold = 500;  

void setup() 
{
  for (uint8_t i=0; i<MAX_PIEZO; i++)
    pinMode(piezo[i], INPUT);

  Serial.begin(57600);      
}

void MidiTX(unsigned char StatusByte, unsigned char Note, unsigned char Val)
{
  Serial.write(StatusByte);
  Serial.write(Note);
  Serial.write(Val);
}

void ProcessPiezo(uint8_t p)
{
  uint16_t sensorReading = analogRead(piezo[p]);
  uint16_t  val;

  if (sensorReading > threshold) 
  {
    uint32_t oldcas = millis() + 5;
    
    // this part of the code looks complex
    // explain what you are trying to do?
    while (analogRead(piezo[p]) > threshold)
    {
      if (millis() >= oldcas)
      {
        val = analogRead(piezo[p]) / 8;
      }
    }
    
    MidiTX(144, drumType[p], val);
    MidiTX(128, drumType[p], val);
  }
}

void loop()
{
  for (uint8_t i=0; i<MAX_PIEZO; i++)
    ProcessPiezo(i);
}

So the question is what do you mean by delay? How long? milliseconds, seconds, minutes?

There is a 5ms delay built into you code when you detect a value > threshold, but I imagine that you don't mean that.
Your code also used int for a millis() value instead of unsigned long, so I changed that. In some cases that could have caused delays until the counter wrapped around again.

Try what is there now, verify that you still have a problem and then give us more details.

You can also try to capture the output using the serial monitor on the computer (avoid all the MIDI) and if the message is there instantaneously, you knoew the delay is after that in the MIDI software chain on the PC.

by delay I mean time between hitting the drum pad and sound from PC.
yep, I tryed serial monitor and problem seems to be in MIDI chain in PC
and it cannot be fixed easy i think :smiley: I tryed combinaton of more SW but nothig worked :confused:

thanks anyway :slight_smile:

and one more problem, why it doesnt work with two midi msg at the same time? when i hit 2 pads simultaneously, plays only one or none.

why it doesnt work with two midi msg at the same time?

Probably because of the 5ms delay waiting for the signal. If you hit both at the same time one will be registered and the other has probably disappeared by the time you have finished checking and sent the message out the port.

To fix this you would have to rewrite the functions without delay statements. One approach may be to just remove the delay you have now and just see if that works better.

Hey, i've created an alternative to MIDI, using only USB connection for a Homemade electronic drums. Check it out:

Dude, just change the vst you're using. For example i'm using FL Studio with ezdrummer (superior drummer, and others) and i solve the delay issue just by using ASIOALL. In the options menu > audio settings change it to ASIO and problem solved.

rikardo:
and one more problem, why it doesnt work with two midi msg at the same time? when i hit 2 pads simultaneously, plays only one or none.

As said above, maybe the second is being missed while processing the first. Would it be possible for you to read entire port (portValue = PINA), then send out the messages from select switch/case statements?

why not read all the analog values in a loop (as above) and if the value is above a threshold set an EVENT flag, then after all the readings have been done, check what EVENTS have been set and send the midi command, clearing the EVENTS as you go

Do the transmitting of the midi commands block all other processing ?
The right way to do this would be to pop your midi command onto a stack and let an interrupt driven transmitter handle all the midi transmissions by pulling commands off the stack until the stack is empty, thus giving all unused time back to the main program

Hi all, I wonder if anyone has the code to send the data via MIDI, I have already DIN5 connector with 220 ohms resistance on pin 4 to +5, ground to pin 2 and pin 5 tx to meI would like to know as I do work

thank you for your answer