Hey,
Ive been trying to make this MIDI percussion thing with ChatGPT as i dont know how to code but i think we have reached stalemate and require some actual brains to move on.
Here is the circuit im currently working with: (the round black thing is supposed to be a piezo sensor)
Im using Arduino UNO R4 Minima connected to my laptop via USB.
On the laptop ive been using Arduino IDE (obviously), loopMIDI and Hairless MIDI to make a virtual MIDI cable.
I have tried using 2 somewhat different codes.
This is what we were initially working on starting from scratch.
#include <MIDI.h>
// Define constants and variables
const int thresholdBase = 100; // Base threshold for detecting a hit
const int debounceDelay = 50; // Delay in milliseconds to debounce the hit
const int analogPin = A0; // Analog pin connected to the sensor
const float alpha = 0.1; // Low-pass filter constant
int threshold = thresholdBase; // Dynamic threshold
float filteredValue = 0; // Low-pass filter output
unsigned long lastHitTime = 0; // Timestamp of the last hit
// Create a MIDI object
MIDI_CREATE_DEFAULT_INSTANCE();
void setup() {
Serial.begin(115200);
MIDI.begin(MIDI_CHANNEL_OMNI); // Initialize MIDI communication
}
void loop() {
int sensorValue = analogRead(analogPin);
// Apply low-pass filter
filteredValue = alpha * sensorValue + (1 - alpha) * filteredValue;
// Log the filtered sensor value
Serial.print("Filtered sensor value: ");
Serial.println(filteredValue);
if (filteredValue > threshold) {
unsigned long currentTime = millis();
if (currentTime - lastHitTime > debounceDelay) {
Serial.println("Hit detected!");
int velocity = map(filteredValue, threshold, 1023, 1, 127); // Map sensor value to MIDI velocity
// Log the mapped velocity
Serial.print("Mapped velocity: ");
Serial.println(velocity);
sendMIDI(60, velocity); // Send MIDI note with velocity
// Dynamic threshold adjustment
threshold = thresholdBase + (filteredValue - thresholdBase) / 2;
lastHitTime = currentTime;
}
} else {
// Gradually reset threshold to base value
threshold = max(thresholdBase, threshold - 1);
}
delay(10); // Short delay to prevent overwhelming the serial buffer
}
void sendMIDI(byte note, byte velocity) {
Serial.print("Sending MIDI note: ");
Serial.print(note);
Serial.print(", Velocity: ");
Serial.println(velocity);
MIDI.sendNoteOn(note, velocity, 1); // Send Note On message
MIDI.sendNoteOff(note, 0, 1); // Send Note Off message
Serial.println("MIDI note off sent");
delay(10); // Short delay to ensure message is sent completely
}
Serial Monitor is constantly spamming low filtered sensor values and when i tap on the piezo its detecting multiple hits (like 4-5) with varying velocities over 350ms or so.
Hairless MIDI is spamming "Error: got unexpected data byte 0x(followed by a random number and/or letter)" when i turn on the Serial <-> MIDI Bridge and after the initial tap it keeps spamming random midi notes with random velocities.
I couldnt get it better than this so i asked it to adapt the code i previously had success with on Arduino NANO to Arduino UNO and this was the best we could do with it. (before more problems got introduced)
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
#define LED 2
#define PIEZO_PIN A0
#define MIDI_CHANNEL 10
#define NOTE_NUMBER 10
#define THRESHOLD 50
#define DEBOUNCE_TIME 200 // Debounce time in milliseconds
int lastValue = 0;
unsigned long lastHitTime = 0;
void setup() {
Serial.begin(115200);
MIDI.begin(MIDI_CHANNEL_OMNI);
pinMode(LED, OUTPUT);
pinMode(PIEZO_PIN, INPUT);
Serial.println("Setup complete");
}
void noteOn(byte pitch, byte velocity) {
MIDI.sendNoteOn(pitch, velocity, MIDI_CHANNEL);
Serial.print("MIDI note on, Note: ");
Serial.print(pitch);
Serial.print(", Velocity: ");
Serial.println(velocity);
}
void noteOff(byte pitch) {
MIDI.sendNoteOff(pitch, 0, MIDI_CHANNEL);
}
void loop() {
int sensorValue = analogRead(PIEZO_PIN);
if (sensorValue > THRESHOLD && (millis() - lastHitTime) > DEBOUNCE_TIME) {
int velocity = map(sensorValue, THRESHOLD, 1023, 1, 127);
if (velocity > 127) velocity = 127;
noteOn(NOTE_NUMBER, velocity);
digitalWrite(LED, HIGH);
delay(10); // Light up LED for visual feedback
digitalWrite(LED, LOW);
lastHitTime = millis();
}
delay(10); // Short delay to prevent overwhelming the loop
}
On Serial Monitor i was getting pretty accurate readings though it seemed to register each tap on the piezo twice with varying velocities.
On Hairless MIDI i got a bunch of seemingly random unintended notes with random velocities after each tap (though they followed the same pattern and velocities were mostly the same also).
I dont know if this is relevant but may be worth mentioning that i currently have the piezo loose (but stable) on a wooden table and sometimes between fairly firm foam pads.
I appreciate if anyone bothers to take a look and share their thoughts.
Thank you!








