I'm working on a MIDI controlled drum set player. I have an arduino reading midi data on one channel from a sequencer to trigger short pulses on the 6 pwm pins. Each pwm pin drives a different solenoid to activate a drumstick on each drum of a drum set.
The one pin (or midi note) that behaves differently is G#1 (expressed through pwm10). This note controls a solenoid that (when charged) lifts the hi-hat to the open position. A G#1 note with a volume > 1 lifts the hi-hat. It stays lifted (charged) until a G#1 with a volume of 1 is played. That closes the hi-hat.
My problem (and I think it's a code problem) is that once the pwm10 gets charged (by a G#1 w/Volume of over 1), none of the other notes (for the 5 other PWM pins) are responded to until the pwm10 turns off (by a G#1 w/Volume equal to 1).
I'm rather new to programming, so any insight into what might be causing my problem would be greatly appreciated.
byte incomingByte;
byte note;
byte velocity;
int noteDown = LOW;
int state=0; // state machine variable 0 = command waiting : 1 = note waitin : 2 = velocity waiting
int baseNote = 36; // lowest note
// use different values of baseNote to select the MIDI octiave
// 24 for octiave 1 -- 36 for octiave 2 --
// play only notes for our drums define pin numbers:-
byte playArray[] = { 3, 0, 5, 0, 0, 0, 6, 9, 10, 11 };
// corresponding to note 24, 25, 26, 27, 28, 29, 30, 31, 32, 33 - for base note = 24 or C1
int strobe = 13; // select the pin for the monostable
int channel = 15; // MIDI channel to respond to (in this case channel 16) change this to change the channel number
// MIDI channel = the value in 'channel' + 1
int onTime3 = 0; // pwm duration depending on velocity - for each pin
int onTime5 = 0; // pwm duration depending on velocity - for each pin
int onTime6 = 0; // pwm duration depending on velocity - for each pin
int onTime9 = 0; // pwm duration depending on velocity - for each pin
int onTime11 = 0; // pwm duration depending on velocity - for each pin
int liftForce = 255; // duty cycle for the hi-hat lifter - 255 max
int hitForce = 0;
unsigned long pwmStart3 = 0;
unsigned long pwmStart5 = 0;
unsigned long pwmStart6 = 0;
unsigned long pwmStart9 = 0;
unsigned long pwmStart11 = 0;
//setup: declaring inputs and outputs and begin serial
void setup() {
pinMode(strobe,OUTPUT); // declare the strobe pin as output
state = 0; // initialize state machine variable
//start serial with MIDI baudrate 31250 or 38400 for debugging
Serial.begin(31250);
digitalWrite(strobe,LOW);
}
//loop: wait for serial data, and interpret the message
void loop () {
unsigned long now = millis(); // Get current time
if(pwmStart3 > 0 && now - pwmStart3 >= onTime3) // Check how long the pin has been firing
{
analogWrite(3, 0); // Turn the PWM off if it has been long enough - onTime
}
if(pwmStart5 > 0 && now - pwmStart5 >= onTime5) // Check how long the pin has been firing
{
analogWrite(5, 0); // Turn the PWM off if it has been long enough - onTime
}
if(pwmStart6 > 0 && now - pwmStart6 >= onTime6) // Check how long the pin has been firing
{
analogWrite(6, 0); // Turn the PWM off if it has been long enough - onTime
}
if(pwmStart9 > 0 && now - pwmStart9 >= onTime9) // Check how long the pin has been firing
{
analogWrite(9, 0); // Turn the PWM off if it has been long enough - onTime
}
if(pwmStart11 > 0 && now - pwmStart11 >= onTime11) // Check how long the pin has been firing
{
analogWrite(11, 0); // Turn the PWM off if it has been long enough - onTime
}
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
digitalWrite(strobe,LOW); // clear any previous strobe
switch (state) {
case 0:
// look for as status-byte, our channel, note on
if (incomingByte== (144 | channel)) {
noteDown = HIGH;
state=1;
}
// look for as status-byte, our channel, note off
if (incomingByte== (128 | channel)) {
noteDown = LOW;
state=1;
}
case 1:
// get the note to play or stop
if(incomingByte < 128) {
note=incomingByte;
state=2;
}
else {
state = 0; // reset state machine as this should be a note number
}
break;
case 2:
// get the velocity
if(incomingByte < 128) {
playNote(note, incomingByte, noteDown); // fire off the solenoid
}
state = 0; // reset state machine to start
}
}
}
void playNote(byte note, byte velocity, int down) {
// if velocity = 0 on a 'Note ON' command, treat it as a note off
if ((down == HIGH) && (velocity == 0)) {
down = LOW;
}
//since we can't play all notes we only action notes between 24 & 33
if(note>=baseNote && note<(baseNote + 10)) {
byte myPin=playArray[note-baseNote]; // to get our pwm pin number
if(myPin == 10 && velocity > 1) { // if it's the high-hat lifter on switch - added less than
analogWrite(myPin, liftForce); // power lifter on
}
if(myPin == 10 && velocity == 1) { // if it's the high-hat lifter off switch
analogWrite(myPin, 0); // turn lifter off
}
hitForce = (velocity * 2);
if(myPin != 0 && myPin != 10) { // if it's not zero or ten
analogWrite(myPin, hitForce); // play it if it is one of our notes.
if(myPin == 3) {
pwmStart3 = millis(); // store the pwm start time for whichever pin the note belongs to
onTime3 = ((25475 / 127) - ((75 * hitForce) / 127)); // this accounts for 50ms onTime at velocity 127 and 200ms at velocity 1
}
if(myPin == 5) {
pwmStart5 = millis();
onTime5 = ((25475 / 127) - ((75 * hitForce) / 127));
}
if(myPin == 6) {
pwmStart6 = millis();
onTime6 = ((25475 / 127) - ((75 * hitForce) / 127));
}
if(myPin == 9) {
pwmStart9 = millis();
onTime9 = ((25475 / 127) - ((75 * hitForce) / 127));
}
if(myPin == 11) {
pwmStart11 = millis();
onTime11 = ((25475 / 127) - ((75 * hitForce) / 127));
}
if(down == HIGH) digitalWrite(strobe, HIGH); // strobe high to data indicator led
}
}
}