I'm working on an Arduino code which will interpret a given MIDI note message and output the corresponding note number to a string of LEDs as a binary integer. I have adapted it from existing code found on the site Notes & Volts which features a similar circuit designed to trigger an LED every time a key is pressed.
My circuit takes this further by telling the user exactly which note is being pressed. The note value byte is information is passed to a 74HC595 shift register which displays the note as a binary via a line of LEDs.
In a loose sense the code I have adapted "works". When a key is pressed a series of LEDs light up corresponding to the MIDI note designated to that key. The issue is that this only happens sporadically. Many times a key press won’t be followed by any LEDs but other times it will. Even quick, successive presses tend to result in only a handful of "read" notes.
Why does this happen? To my intuition it would seem that the Arduino is "missing" notes, that is, spending so many clock cycles writing bits to the shift register that it falls out of sync with incoming bytes from the keyboard. Notes & Volts describes almost this exact situation in one of their instructional videos (relevant part at around 6:57). The author cautions against including too many time consuming processes in the code but doesn't mention how many is too many. I can only assume that a ShiftOut command takes a good deal longer than a digitalWrite and that this explains why the example code works but my adaptation does not. Given this information, how long exactly does ShiftOut take and what could be done to speed up my program?
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();
int latchPin = 8;
int clockPin = 12;
int dataPin = 11; //The pins I am using
void note_On(byte channel, byte pitch, byte velocity) { //Runs when note is pressed
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, pitch);
digitalWrite(latchPin, HIGH); //Write 'pitch' to 74HC595. Standard fare
}
void note_Off(byte channel, byte pitch, byte velocity){ //Writes '0' when note is off (all LEDs off)
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, 0x00);
digitalWrite(latchPin, HIGH);
}
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
MIDI.begin(MIDI_CHANNEL_OMNI);
MIDI.setHandleNoteOn(note_On);
MIDI.setHandleNoteOff(note_Off);
}
void loop() {
MIDI.read(); //This function which must be re-run in quick succession
}
UPDATE
@CL @Nick I wrote a code comparing the execution time difference between shiftOut and digitalWrite. While I am not perfectly confident in all of the numbers (1K digitalWrites takes a full 44mS??) one result did not surprise me - shiftOut is slower. By my numbers it is 3.75 times slower. That said, I welcome critiques on my methodology and I will address them as soon as I can. In the meantime I will make a point to research Arduino SPI and welcome any other alternatives to shiftOut.
int latchPin = 8; //Declaration of serial register pins
int clockPin = 12;
int dataPin = 11;
int led = 13; //On-board LED
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
Serial.begin(9600);
pinMode(led, OUTPUT);
}
void loop() {
unsigned long startTime = millis(); //Writes to SR 1K times.
for(int i = 0; i < 1000; i++){ //Prints difference between
digitalWrite(latchPin, LOW); //start and end times.
shiftOut(dataPin, clockPin, MSBFIRST, 0xFF);
digitalWrite(latchPin, HIGH);
}
Serial.print("\nsO:");
Serial.print(millis() - startTime);
delay(1000);
startTime = millis();
for(int i = 0; i < 8000; i++){ //Performs digitalWrite 8K times
digitalWrite(led, HIGH);
}
Serial.print("\t\tdW:"); //
Serial.print(millis() - startTime);
delay(1000);
}
UPDATE While working on a similar issue I discovered that a dramatic change to my code seems to perfectly clear up the issue. I'd still like to know why this particular example does not, however, so I'll keep poking around until I get somewhere.
shiftOut
executes? (Execute it ten thousand times, and runmillis()
before and afterwards.)