Hi all,
I am new to the forum and hope to have made the research well as I found nobody with this issue.
I am using a Pro Micro 5 V clone to control 8 piezo drums.
The circuit is simple. The piezo connects in parallel to a 1 M ohm resistor and a zener diode and then to the analog pin and ground. See picture attached.
The code works fine and it is has been created by Ian Harvey (see below, as it is not the issue I guess).
Problems:
- Out of the 8 pins there is always one that fails. In this breadboard pin A6 failed. When I stopped using it and used A10 instead, then A7 that previously gave signal ceased to work. By not working I mean, there is no signal sent when I do analog read in the serial monitor and obviously does not trigger a drum
- Previous to that A7 was triggering at least three more analog pins. It does not happen with the others.
I had a soldered perfboard version and it was quite worse. Two pins did not work and several triggered other pins. In the A0 to A3 pins.
Is it the Pro Micro clone? or is it that a max number of 7 analog pins can be used at the same time.
Thanks a lot for your help!
Code
// adapted from Ian Harvey
// October 2016.
#include "MIDIUSB.h"
// Needs MIDIUSB library to be installed
static void MIDI_setup();
static void MIDI_noteOn(int ch, int note, int velocity);
static void MIDI_noteOff(int ch, int note);
const int MIDI_CHANNEL=1;
const int NCHANNELS = 8;
const int inPins[NCHANNELS] = { A10, A7, A8, A9, A0, A1, A2, A3 };
const int midiNotes[NCHANNELS] =
{
// Follows General MIDI specs at https://www.midi.org/specifications/item/gm-level-1-sound-set
36, // C1, 1
37, // C#1, 2
38, // D1, 3
39, // D#1, 4
40, // E1, 5
41, // F1, 6
42, // F#1, 7
43, // G1, 8
};
const int thresholdLevel[NCHANNELS] = { 100, 100, 100, 100, 100, 100, 100, 100 }; // ADC reading to trigger; lower => more sensitive
const long int maxLevel[NCHANNELS] = { 600, 600, 600, 600, 600, 600, 600, 600 }; // ADC reading for full velocity; lower => more sensitive
static unsigned int vmax[NCHANNELS] = { 0 };
static unsigned int trigLevel[NCHANNELS];
static unsigned int counter[NCHANNELS] = { 0 };
static unsigned int CTR_NOTEON = 10; // Roughly 5ms sampling peak voltage
static unsigned int CTR_NOTEOFF = CTR_NOTEON + 30; // Duration roughly 15ms
// 0 -> not triggered
// 1..CTR_NOTEON -> sampling note on
// CTR_NOTEON+1 .. CTR_NOTEOFF -> note off
static int statusPin = 2;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
analogReference(DEFAULT);
for (int i = 0; i < NCHANNELS; i++)
{
pinMode(inPins[i], INPUT);
analogRead(inPins[i]);
trigLevel[i] = thresholdLevel[i];
}
MIDI_setup();
}
void loop() {
int ch;
for (ch=0; ch < NCHANNELS; ch++)
{
unsigned int v = analogRead(inPins[ch]);
if ( counter[ch] == 0 )
{
if ( v >= trigLevel[ch] )
{
vmax[ch] = v;
counter[ch] = 1;
}
}
else
{
if ( v > vmax[ch] )
vmax[ch] = v;
counter[ch]++;
if ( counter[ch] == CTR_NOTEON )
{
long int vel = ((long int)vmax[ch]*127)/maxLevel[ch];
Serial.println(v);
if (vel < 5) vel = 5;
if (vel > 127) vel = 127;
MIDI_noteOn(MIDI_CHANNEL, midiNotes[ch], vel);
trigLevel[ch] = vmax[ch];
}
else if ( counter[ch] >= CTR_NOTEOFF )
{
MIDI_noteOff(MIDI_CHANNEL, midiNotes[ch]);
counter[ch] = 0;
}
}
// The signal from the piezo is a damped oscillation decaying with
// time constant 8-10ms. Prevent false retriggering by raising
// trigger level when first triggered, then decaying it to the
// threshold over several future samples.
trigLevel[ch] = ((trigLevel[ch] * 19) + (thresholdLevel[ch] * 1)) / 20;
}
}
// MIDI Code
//
// See https://www.midi.org/specifications/item/table-1-summary-of-midi-message
void MIDI_setup()
{
}
void MIDI_noteOn(int ch, int note, int velocity)
{
midiEventPacket_t noteOn = {0x09, 0x90 | (ch-1), note & 0x7F, velocity & 0x7F};
MidiUSB.sendMIDI(noteOn);
MidiUSB.flush();
}
void MIDI_noteOff(int ch, int note)
{
midiEventPacket_t noteOff = {0x08, 0x80 | (ch-1), note, 1};
MidiUSB.sendMIDI(noteOff);
MidiUSB.flush();
}