Ok.
So after a lot of wiring and soldering, i now have a long strip of 64 LEDS, each being controlled by a different midi note, running through 8 shift registers wired up as explained in the 'shiftOut' tutorial.
At slow to moderate speeds this thing is working perfectly. But it's just not running quite fast enough for what I want it to do.
I'm not sure if it is the code, or the speed of the shift registers, or the arduino itself.
During the void (setup) there is a an instruction to blink ALL the LEDS, and then this happens all 64 blink instantaneously. If I try and recreate the same effect by sending 64 midi signals, there is a staggered effect (not long - perhaps 200-300ms) but the effect is very noticeable. In addition to this, odd LEDs will hang, presumably because for whatever reason they miss their 'note off' commands.
If it weren't for the fact that the Blink command deals with all the LEDs instantly I would suspect it was the shift register speed. But as it is... I am confused.
What I am hoping for is that there are some loose ends in the code I can tidy up to get that extra little boost I need.
Richard, previously you said
Furthermore, you don't necessarily have to shift out the chromatic array into the shift registers every time through the loop, either. Maybe only every 100ms would be fast enough(?)
but I am not sure what you mean by that. Do you think this might be something that could help?
Here is the code I am using. As above, except with instructions for 8 shift registers instead of 5...
//variables setup
byte incomingByte = 255; // midi signal #1
byte note = 255; // midi signal #2
byte velocity = 255; // midi signal #3
byte bytenumb; //
byte bitnumb; //
byte chromatic[10]; // declare chromatic scale, 8 x 11 = 88 notes
//Shift Out Pins to 74HC595s
int latchPin = 8;
int clockPin = 12;
int dataPin = 11;
int statusLed = 13; // select the pin for the LED
int startupBeep = 6; // connect to a piezo buzzer. not strictly necessary, but use to know arduino is on & good to receive midi
int action=2; // MIDI rules: 0 =note off ; 1=note on ; 2= nada
//setup: declaring iputs and outputs and begin serial
void setup() {
pinMode(statusLed,OUTPUT); // declare the LED's pin as output
pinMode(latchPin, OUTPUT); // declare latch pin as output
//start serial with midi baudrate 31250 or 38400 for debugging
Serial.begin(31250);
digitalWrite(statusLed,HIGH);
//function that blinks all the LEDs and then switches them off
//gets passed the number of blinks and the pause time
blinkAll_2Bytes(1,750);
killAll_2Bytes(1,500);
for (int i = 0; i < 11; i++){ // (i.e. for i = 0 to 10)
chromatic[i] = 0; // resets the array.
}
}
//loop: wait for serial data, and interpret the message
void loop () {
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// wait for as status-byte, channel 1, note on or off
if (incomingByte== 144){ // note on message starting starting
action=1;
}else if (incomingByte== 128){ // note off message starting
action=0;
}else if (incomingByte > 144){ // message is anything but note message
action=2; //nothing happens
//process second byte
}else if ( (incomingByte<=127) && (action ==1) ){ // IF THE FIRST BYTE WAS A NOTE ON MESSAGE...
bytenumb = (incomingByte / 8); // calculate which array byte 0 ~ 10
bitnumb = (incomingByte % 8); // calculate which bit (0 ~ 7)
chromatic[bytenumb] = bitSet(chromatic[bytenumb], bitnumb);
//ground latchPin and hold low for as long as you are transmitting
digitalWrite(latchPin, 0);
//move 'em out
shiftOut(dataPin, clockPin, chromatic[8]);
shiftOut(dataPin, clockPin, chromatic[7]);
shiftOut(dataPin, clockPin, chromatic[6]);
shiftOut(dataPin, clockPin, chromatic[5]);
shiftOut(dataPin, clockPin, chromatic[4]);
shiftOut(dataPin, clockPin, chromatic[3]);
shiftOut(dataPin, clockPin, chromatic[2]);
shiftOut(dataPin, clockPin, chromatic[1]);
shiftOut(dataPin, clockPin, chromatic[0]);
//return the latch pin high to signal chip that it
//no longer needs to listen for information
digitalWrite(latchPin, 1);
}
else if ( (incomingByte<=127) && (action ==0) ){ //IF THE FIRST BYTE WAS A NOTE OFF MESSAGE...
bytenumb = (incomingByte / 8); // calculate which array byte 0 ~ 10
bitnumb = (incomingByte % 8); // calculate which bit (0 ~ 7)
chromatic[bytenumb] = bitClear(chromatic[bytenumb], bitnumb);
//ground latchPin and hold low for as long as you are transmitting
digitalWrite(latchPin, 0);
//move 'em out
shiftOut(dataPin, clockPin, chromatic[8]);
shiftOut(dataPin, clockPin, chromatic[7]);
shiftOut(dataPin, clockPin, chromatic[6]);
shiftOut(dataPin, clockPin, chromatic[5]);
shiftOut(dataPin, clockPin, chromatic[4]);
shiftOut(dataPin, clockPin, chromatic[3]);
shiftOut(dataPin, clockPin, chromatic[2]);
shiftOut(dataPin, clockPin, chromatic[1]);
shiftOut(dataPin, clockPin, chromatic[0]);
//return the latch pin high to signal chip that it
//no longer needs to listen for information
digitalWrite(latchPin, 1);
}
//process Third byte - the velocity
}else if ( (incomingByte<=127) && (action ==1) ){ // if we received note ON message load this byte in the velocity byte
velocity=incomingByte;
note=255;
}else if ( (incomingByte<=127) && (action ==0) ){ // if we received note message load this byte in the velocity byte
velocity=0;
note=255;
}
}
// the shift out function
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
// This shifts 8 bits out MSB first,
//on the rising edge of the clock,
//clock idles low
//internal function setup
int i=0;
int pinState;
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, OUTPUT);
//clear everything out just in case to
//prepare shift register for bit shifting
digitalWrite(myDataPin, 0);
digitalWrite(myClockPin, 0);
//for each bit in the byte myDataOut?
//NOTICE THAT WE ARE COUNTING DOWN in our for loop
//This means that %00000001 or "1" will go through such
//that it will be pin Q0 that lights.
for (i=7; i>=0; i--) {
digitalWrite(myClockPin, 0);
//if the value passed to myDataOut and a bitmask result
// true then... so if we are at i=6 and our value is
// %11010100 it would the code compares it to %01000000
// and proceeds to set pinState to 1.
if ( myDataOut & (1<<i) ) {
pinState= 1;
}
else {
pinState= 0;
}
//Sets the pin to HIGH or LOW depending on pinState
digitalWrite(myDataPin, pinState);
//register shifts bits on upstroke of clock pin
digitalWrite(myClockPin, 1);
//zero the data pin after shift to prevent bleed through
digitalWrite(myDataPin, 0);
}
//stop shifting
digitalWrite(myClockPin, 0);
}
//blinks the whole register based on the number of times you want to
//blink "n" and the pause between them "d"
//starts with a moment of darkness to make sure the first blink
//has its full visual effect.
void blinkAll_2Bytes(int n, int d) {
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(startupBeep, 0);
digitalWrite(latchPin, 1);
delay(200);
for (int x = 0; x < n; x++) {
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
digitalWrite(startupBeep, 1);
digitalWrite(latchPin, 1);
delay(d);
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(startupBeep, 0);
digitalWrite(latchPin, 1);
delay(d);
}
}
void killAll_2Bytes(int n, int d){
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(latchPin, 1);
delay(200);
}