Please check my modified Shift Register sketch

I am modifying the sketch for the Shift Register to receive a MIDI signal through the MIDI to Serial Converter.

The MIDI data is 144, 60, 127

That is going through the converter, and I see the RX LED blinking on the arduino. Here is my sketch, and I am trying to get an LED to light when the data comes through.

I’m not getting the LED itself to light. I’m hoping someone can take a look at this sketch and see what I’m missing. I added the loop in the code to parse through the MIDI signal. Thanks for any help!

/*
  Shift Register Example
 for 74HC595 shift register

 This sketch turns reads serial input and uses it to set the pins
 of a 74HC595 shift register.

 Hardware:
 * 74HC595 shift register attached to pins 2, 3, and 4 of the Arduino,
 as detailed below.
 * LEDs attached to each of the outputs of the shift register

 Created 22 May 2009
 Created 23 Mar 2010
 by Tom Igoe

 */

//Pin connected to latch pin (ST_CP) of 74HC595
const int latchPin = 8;
//Pin connected to clock pin (SH_CP) of 74HC595
const int clockPin = 12;
////Pin connected to Data in (DS) of 74HC595
const int dataPin = 11;

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
  Serial.begin(57600);
  Serial.println("reset");
}

void loop() {
  
  
  if (Serial.available() > 0) { //if serial incoming

    int incomingByte = Serial.read(); //read it
    if (incomingByte==144){ // analyse the first byte (status) : 144 is note on ch1
	incomingByte = Serial.read(); //read the next byte

	if (incomingByte==60){ // analyse the second byte (note) : 60 is middle C

	  incomingByte = Serial.read(); //read the next byte
	  if(incomingByte>0){  //analyse the third byte : velocity >0
            int bitToSet = 1;
            registerWrite(bitToSet, HIGH);
	  }else{ //analyse the third byte : velocity=0
            int bitToSet = 2;
            registerWrite(bitToSet, HIGH);
	  }
	}
	
    }
  }
}

// This method sends bits to the shift register:

void registerWrite(int whichPin, int whichState) {
// the bits you want to send
  byte bitsToSend = 0;

  // turn off the output so the pins don't light up
  // while you're shifting bits:
  digitalWrite(latchPin, LOW);

  // turn on the next highest bit in bitsToSend:
  bitWrite(bitsToSend, whichPin, whichState);

  // shift the bits out:
  shiftOut(dataPin, clockPin, MSBFIRST, bitsToSend);

    // turn on the output so the LEDs can light up:
  digitalWrite(latchPin, HIGH);

}
 if (Serial.available() > 0) { //if serial incoming

int incomingByte = Serial.read(); //read it
    if (incomingByte==144){ // analyse the first byte (status) : 144 is note on ch1
incomingByte = Serial.read(); //read the next byte

This:

if (Serial.available() > 0)

only guarantees you have one byte in the serial buffer. However you are trying to read at least two.

ok. I'm not sure how the serial to midi converter shoots out the data...like is it an array, or what? If it is an array, I am needing to check the first byte in the first if statement, then the second in the second, etc...

I'm not sure how to do this :~

The serial comes as a "stream". If you do not call Serial.read() they pile up in a buffer. Serial.available() tells you how many have arrived. If you know you always receive 3 byte for one "note", then you can wait until there are 3 bytes in the buffer ... Quick&dirty solution that will work in this case.

Hi,
I'm working on something very similar at the moment. I was looking to get midi out from my mac, thru midi to serial converter, into the Arduino, then out into 2 chained 595s. I had some issues reading the multiple bytes from my computer like you're saying. Have you looked into the Midi library?

http://www.arduino.cc/playground/Main/MIDILibrary

The examples it gives show a pretty straight forward way to get Midi being received and understood. :slight_smile:

It sounds like we are doing the exact same thing...

but why do I need the midi library? The Midi to Serial converter is sending serial via USB into the Arduino-I don't need a MIDI shell.

The serial comes as a "stream". If you do not call Serial.read() they pile up in a buffer. Serial.available() tells you how many have arrived. If you know you always receive 3 byte for one "note", then you can wait until there are 3 bytes in the buffer ... Quick&dirty solution that will work in this case.

Can you please briefly show me some code on how to do this? Indeed each message will have three bytes.

I have int incomingByte = Serial.read(); //read it in the next line of code, so I thought it should be reading the byte there?

I feel like I'm so close, but still no luck. Here is what I have so far:

/*
  Shift Register Example
 for 74HC595 shift register

 This sketch turns reads serial input and uses it to set the pins
 of a 74HC595 shift register.

 Hardware:
 * 74HC595 shift register attached to pins 2, 3, and 4 of the Arduino,
 as detailed below.
 * LEDs attached to each of the outputs of the shift register

 Created 22 May 2009
 Created 23 Mar 2010
 by Tom Igoe

 */

//Pin connected to latch pin (ST_CP) of 74HC595
const int latchPin = 8;
//Pin connected to clock pin (SH_CP) of 74HC595
const int clockPin = 12;
////Pin connected to Data in (DS) of 74HC595
const int dataPin = 11;

int incomingByte = 0;


void registerWrite(int whichPin, int whichState) {
// the bits you want to send
  byte bitsToSend = 0;

  // turn off the output so the pins don't light up
  // while you're shifting bits:
  digitalWrite(latchPin, LOW);

  // turn on the next highest bit in bitsToSend:
  bitWrite(bitsToSend, whichPin, whichState);

  // shift the bits out:
  shiftOut(dataPin, clockPin, MSBFIRST, bitsToSend);

    // turn on the output so the LEDs can light up:
  digitalWrite(latchPin, HIGH);
}

void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
  Serial.begin(57600);
  Serial.println("reset");
}

void loop() {
  
  
  if (Serial.available() > 0) { //if serial incoming
	incomingByte = Serial.read(); //read the next byte

    if (incomingByte==144){ // analyse the first byte (status) : 144 is note on ch1


	if (incomingByte==60){ // analyse the second byte (note) : 60 is middle C

	  incomingByte = Serial.read(); //read the next byte
	  if(incomingByte>0){  //analyse the third byte : velocity >0 


            int bitToSet = 1;
            registerWrite(bitToSet, HIGH);
	  }else{ //analyse the third byte : velocity=0
            int bitToSet = 2;
            registerWrite(bitToSet, HIGH);
	  }
	}
	
    }
  }
}

Any help would be humbly appreciated!

Any help would be humbly appreciated!

Why? You’ve ignored the advice you’ve received so far.

but still no luck.

What does this mean? Programming is not a matter of luck. What is that program doing that you don’t want it to do? What is it not doing that you do want?

Hi PaulS,
What are you talking about? What advice? To check the MIDI library? I’m aware of what MIDI signal is feeding the MIDI to Serial converter. I am feeding Serial data to the Arduino. I don’t need the MIDI library-right? Actually-looking at it, I’m seeing that I don’t really understand the library-is it really a “MIDI library” or is it taking midi information that has been converted to serial?? If " if (Serial.available() > 0) only guarantees you have one byte in the serial buffer. However you are trying to read at least two." is advice, well I don’t know the language well enough to know how to interpret that advice.

What I need to know is how to parse the incoming serial data so it sends the needed info to the right pins in the shift register. I tried to be clear, but it sounds like you would like some more information, so I’m happy to provide that:

What is that program doing that you don’t want it to do? What is it not doing that you do want?

Currently all that happens is that I am seeing a TX output from the Converter and I am seeing the RX LED flashing on the arduino when the serial information is coming over.

The signal is Middle “C” note coming out of channel 1 with velocity 100. The MIDI stream therefore looks like this: 144, 60, 100

That goes through the Converter and I’m not exactly sure how it looks coming out because I don’t know how to monitor it, BUT What I want the program to do (in psudo-code) is:

if (byte 1 = 144) {
  if (byte 2 = 60){
     Light LED 1
  }
}

I’m new to physical computing, but I have basic PHP experience, so I’m not a total newbie, but I am still having trouble because I don’t understand the ShiftOut that well.

mbira:

if (byte 1 = 144) {

if (byte 2 = 60){
     Light LED 1
  }
}

You need to basically assemble the message first, and decode it later. Something like this:

byte buf [20];   // allow for up to 20 bytes
byte pos;   // where in buf we are

void loop ()
 {
 if (Serial.available ())
    {
    byte c = Serial.read ();
    if (pos < sizeof buf)
      buf [pos++] = c;
    if (c == '\n')  // if some terminator is hit
      {
      ProcessMessage ();
      pos = 0;  // back to empty buffer
      }
    }
}  // end of loop

That is untested, but the general idea. You now assemble your MIDI message, byte by byte. I forget what MIDI uses to end a message, it will be newline, or something like that. When the newline receives, you call some function that now has the complete message, which it can parse and make sense of.

It depends how efficient you need to be. The library is probably overkill for simply decoding the serial midi. i found it useful in that it gave me usable outputs without having to even open a serial connection directly. It gives useable variables, like ‘pitch’ and ‘velocity’ which you can just… use. The midi-serial converter only converts midi into serial, but it’s still the exact same structure. the library decodes/interprets that structure for you without having to do it yourself.

As you’re using a 595, which takes a serial byte and transmits it parallel to 8 leds.

Using the library, i had a structure like this:

void HandleNoteOn(byte channel, byte pitch, byte velocity) {
  
  //lowers pitch an octave to sync keyboard outputs to the lowest available. c0 -> c-1
  pitch = pitch - 11;

  //This double checks that there's an output for the received input to be sent to.
  if(pitch <= NumOfOutputs)
  {
    //check for note playing status
    if(OutputStatus[pitch-1] != 1)
    {
      //This is the NoteOn.
      if (velocity != 0) {
          OutputStatus[(pitch - 1)] = 1;
          OutputTotal = OutputTotal + Pow(pitch - 1);
          blinkBlue();
      }
      else
      {
        OutputStatus[(pitch - 1)] = 0;
        OutputTotal = OutputTotal - Pow(pitch - 1);
        blinkRed();
      }
    }
  }
}

Then to show the correct output i did this (i’m using 2 595s):

void showOutput()
{
  //OutputTotal split into 2 8 bit bytes (one for each SR)
  int bits_for_SR2 = OutputTotal >> 8;
  int bits_for_SR1 = OutputTotal % 256;

  // Pull latch LOW to send data
  digitalWrite(outLatchPin, LOW);

  //upper 8 bit register (1ST SLAVE 959)
  shiftOut(outDataPin, outClockPin, MSBFIRST, bits_for_SR2);

  //lower 8 bit register (MASTER 959)
  shiftOut(outDataPin, outClockPin, MSBFIRST, bits_for_SR1);

  // Pull latch HIGH to stop sending data
  digitalWrite(outLatchPin, HIGH);
}

Please ignore my shoddy coding skills, i’m so new to this, there’s probably such a better way of doing it :frowning: but it works!

It’s just an idea for you anyway, obviously you can do exactly what the library does for you in your own code, but that’s a bit beyond me at the moment, if im honest.

@BreakBeatKid - Thanks so much man for sharing the code you've got. The "NumOfOutputs" variable isn't declared here, so I'm getting some errors trying to compile this. It sounds like you are doing almost exactly what I'm doing (except I'm taking midi notes from ableton instead of from a keyboard), but I will be feeding this into two 595s.

Would you be at all willing to share your full code with me? It sounds like you, I'm just a musician and trying to get this up off the ground so I can get back to work on music. :slight_smile: I'm not much of a coder as well, and any help would be greatly appreciated.

Sure. I’m certainly paranoid showing my code as this is my first sketch, ha! But as i say, it works :slight_smile:

/////////////////////////////////
//         LIBRARIES           //
/////////////////////////////////
#include <MIDI.h>


/////////////////////////////////
//         CONSTANTS           //
/////////////////////////////////
const int NumOfOutputs = 16;

const int outDataPin = 4;              // The Serial Data Pin to the Shift Register
const int outLatchPin = 3;             // The Latch Pin to the Shift Register
const int outClockPin = 2;             // The Clock Pin to the Shift Register

const int REDLED = 7;
const int BLUELED = 6;


/////////////////////////////////
//         VARIABLES           //
/////////////////////////////////

int OutputStatus[NumOfOutputs];
int OutputValues[NumOfOutputs];

unsigned long OutputTotal;

/////////////////////////////////
//            SETUP            //
/////////////////////////////////
void setup() {  
  pinMode(REDLED, OUTPUT);
  pinMode(BLUELED, OUTPUT);

  pinMode(outDataPin, OUTPUT);    // Configure Digital Pins
  pinMode(outLatchPin, OUTPUT);
  pinMode(outClockPin, OUTPUT);

  //Serial.begin(57600);

  // Initiate MIDI communications, listen to all channels
  MIDI.begin(MIDI_CHANNEL_OMNI);    
  MIDI.turnThruOff();

  // Connect the HandleNoteOn and NoteOff functions to the library, so it is called upon reception of a NoteOn or NoteOff.
  MIDI.setHandleNoteOn(HandleNoteOn);
  MIDI.setHandleNoteOff(HandleNoteOff);
}  


/////////////////////////////////
//            LOOP             //
/////////////////////////////////
void loop() {

  MIDI.read();
  showOutput();

}


/////////////////////////////////
//          CALLBACKS          //
/////////////////////////////////
//NoteOn callback
void HandleNoteOn(byte channel, byte pitch, byte velocity) {
  
  //lowers pitch an octave to sync keyboard outputs to the lowest available. c0 -> c-1
  pitch = pitch - 11;

  //This double checks that there's an output for the received input to be sent to.
  if(pitch <= NumOfOutputs)
  {
    //check for note playing status
    if(OutputStatus[pitch-1] != 1)
    {
      //This is the NoteOn.
      if (velocity != 0) {
          OutputStatus[(pitch - 1)] = 1;
          OutputTotal = OutputTotal + Pow(pitch - 1);
          blinkBlue();
      }
      else
      {
        OutputStatus[(pitch - 1)] = 0;
        OutputTotal = OutputTotal - Pow(pitch - 1);
        blinkRed();
      }
    } else {}
  } else {}
}


//NoteOff callback
void HandleNoteOff(byte channel, byte pitch, byte velocity) { 
  
  //lowers pitch an octave to sync keyboard outputs to the lowest available. c0 -> c-1
  pitch = pitch - 11;
  //check for note playing status
  if(OutputStatus[pitch-1] != 0)
  {
    if(pitch <= NumOfOutputs)
    {
      //This is the NoteOn.
      OutputStatus[(pitch - 1)] = 0;
      OutputTotal = OutputTotal - Pow(pitch - 1);
      blinkRed();
    }
  }
}


/////////////////////////////////
//          FUNCTIONS          //
/////////////////////////////////
void showOutput()
{
  //OutputTotal split into 2 8 bit bytes
  int bits_for_SR2 = OutputTotal >> 8;
  int bits_for_SR1 = OutputTotal % 256;

  // Pull latch LOW to send data
  digitalWrite(outLatchPin, LOW);

  //upper 8 bit register (1ST SLAVE 959)
  shiftOut(outDataPin, outClockPin, MSBFIRST, bits_for_SR2);

  //lower 8 bit register (MASTER 959)
  shiftOut(outDataPin, outClockPin, MSBFIRST, bits_for_SR1);

  // Pull latch HIGH to stop sending data
  digitalWrite(outLatchPin, HIGH);
}


void blinkRed()
{
  digitalWrite(REDLED,HIGH);     // Blink the LED
  delay(20);
  digitalWrite(REDLED,LOW);      // Blink the LED
}

void blinkBlue()
{
  digitalWrite(BLUELED,HIGH);     // Blink the LED
  delay(20);
  digitalWrite(BLUELED,LOW);      // Blink the LED
}

/////////////////
//    MATHS    //
/////////////////

//2^i
unsigned int Pow(byte ex)
{
    return 1 << ex;
}

Hope it helps at least.

(Just for the record, this works with serial-midi converter, but NOT with Moco for LUFA. If anyone has any idea as to why, i’d greatly appreciate it!!)

Back to the 3 byte input question.

if (Serial.available()>=3) {
  // now at least 3 bytes are in the buffer.
  First = Serial.read() ; Secnd = Serial.read() ; Third = Serial.read() ; 
  :  // code to do your thing with all three bytes
  }

midi isnt strictly speaking always 3 byes, some messages have 2, some have as many bytes as it takes to say whats needed. but i wish id realised it was that simple about a week ago :smiley: