Programming novice here.
I’ve built a working version of Mike Cook’s Midi Glockenspiel, except mine plays drums (with different mechanics). MIDI Glockenspiel
I’m now attempting to use an analogWrite method instead of digital HIGH/LOW so I can utilize the MIDI velocity data. Each time I fire a solenoid, I want to produce a 50 millisecond long PWM (of varying duty cycles).
Since I am controlling six independent solenoids, I figured I couldn’t use “delay” to control the PWM duration as it would conflict with the data listening and firing of the other solenoids/drums. I’ve studied the BlinkWithoutDelay example to help wrap my mind around using “millis()” as a way to time the PWM duration.
What I’m having a hard time imagining is what the code would look like to keep track of the analogWrite for 6 different pins simultaneously.
This is the code I have now. It is lacking code to control the analogWrite duration. Any help on getting me going in the right direction would be greatly appreciated.
//variables setup
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 -- 48 for octiave 3 -- 60 for octiave 4 -- 72 for octiave 5
// 84 for octiave 6 -- 96 for octiave 7
// 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
//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 () {
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 != 0) {
analogWrite(myPin, velocity*2); // play it if it is one of our notes. Also, does this multiplier work?
if(down == HIGH) digitalWrite(strobe, HIGH); // strobe high to data indicator led
}
}
}