Hi,
I’m currently building a small extension for my Grand Orgue vpo system, which will be a small set of real organ pipes. I’m planning to control the pipe’s valve magnets using an Arduino Nano with midiIn and 4 shift registers with 25 transistors on their outputs to control solenoids.
The circuit is working fine, but the programming is the problem for me. I only use 25 pipes, so two octaves. I want to start at the G right under middle C (so Midinote 55) , so thats what has to be the shift register’s first pin. At the moment it’s working, but very unstable. The LED that I attached between the base and emitter of the transistor for testing purposes often stays on or off until I reset the board. What am I doing wrong or what can I improve to solve the problem? Btw: It’s a code I copied from another thread that I modified a bit. And yes, my way may be completely wrong, I’m not a pro at all.)
Here’s my code:
/* /* Controlling up to 88 LEDs independently with Midi notes from a Midi in.
//
// This code has been cobbled together from existing material found on the internet and help from the Arduino forums.
// The midi stuff in particular was gleaned from this thread: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1187962258/
// The shift register stuff is pulled straight from the arduino tutorials.
// I have not fine tuned it yet and there are still probably fragments of code in here that are either unnecessary or
// perhaps even detrimental to the performance.
// However, it DOES work, so if you happen to need to be able to control LEDS via midi notes, then this will be
// a useful place to start.
*/
// A midi signal comes in 3 bits. The first is Midi On (144), or Midi off(128). It can be a bunch of other things too,
// but for this situation I'm not interested in them.
// The second bit is the note number (e.g 36 = C1, 37 = C#1, 38 = D1, etc.)
// The third bit is velocity (0-127).
// Finally - at the moment this code only deals with 5 shift registers, giving control over 40 leds,
// although the array caters for all 88 notes.
//
//variables setup
byte byteCount;
byte incomingByte = 255; // midi signal #1
byte note = 255; // midi signal #2
byte velocity = 255; // midi signal #3
byte incomingBytea;
byte bytenumb; //
byte bitnumb; //
byte chromatic[4]; // declare chromatic scale, 8 x 11 = 88 notes
//Shift Out Pins to 74HC595s
int latchPin = 11;
int clockPin = 12;
int dataPin = 8;
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);
//function that blinks all the LEDs and then switches them off
//gets passed the number of blinks and the pause time
blinkAll_2Bytes(1,100);
killAll_2Bytes(1,100);
delay(200);
blinkAll_2Bytes(1,100);
killAll_2Bytes(1,100);
for (int i = 0; i < 4; 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...
if(byteCount == 1) {
incomingBytea = incomingByte;
incomingBytea += -55;
}
bytenumb = (incomingBytea / 8); // calculate which array byte 0 ~ 10
bitnumb = (incomingBytea % 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[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);
digitalWrite(statusLed,HIGH);
}
else if ( (incomingByte<=127) && (action ==0) ){ //IF THE FIRST BYTE WAS A NOTE OFF MESSAGE...
if(byteCount == 1) {
incomingBytea = incomingByte;
incomingBytea += -55;
}
bytenumb = (incomingBytea / 8); // calculate which array byte 0 ~ 10
bitnumb = (incomingBytea % 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[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);
digitalWrite(statusLed,LOW);
}
//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);
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);
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);
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);
digitalWrite(latchPin, 1);
delay(200);
}