Teensy usbMIDI.read to dual 595 and leds, need guidance..

I’m currently trying to use the usbMIDI.read function for Teensy and want to convert the midi data to light up 16 leds, through 2 daisychained 595 shift registers.

The hardware is debugged and works perfectly with a running light sketch. But I can’t grasp how I should think with midi feedback and shiftOut.

I would appreciate if someone could give me a hint about how to approach this in a text description rather than code. Can’t seem to find any similar projects or get my mind around it.

Do I need to make an array to store the midi notes in after the reading and before the shiftOut?

ShiftOut is the “program” for how to convert the midi data to bits and bytes right? If I need an array, should it be inside the shiftOut or outside?

The “write command”, should I place it in the loop or do it via an extra void? I guess it needs to be linked to the loop to actually write out the notes when they are read?

Thanks in advance!

Some reading:
https://www.pjrc.com/teensy/td_midi.html

The Control Surface library I'm working on should support this.

Here's an example that reads MIDI note inputs and turns on / off LEDs connected to 74HC595 shift registers: https://tttapa.github.io/Control-Surface/Doc/Doxygen/dd/dcc/md_Getting-Started.html#first-input

Pieter

PieterP:
The Control Surface library I'm working on should support this.

Here's an example that reads MIDI note inputs and turns on / off LEDs connected to 74HC595 shift registers: https://tttapa.github.io/Control-Surface/Doc/Doxygen/dd/dcc/md_Getting-Started.html#first-input

Pieter

Thanks for your advice, I tried it out but it didn't compile so I'm going further with my own code that I'm a bit curious about. Any idéas how to get this puzzle together?

First of all, do my shiftOut look ok? Second of all, how do I get my shiftOut to talk to my other two functions? Feeling kind of stupid...

Variables

//SHIFT REGISTER FOR LEDS, OUTPUT PINS_____________________
int latchPin = 10; // ST_CP, SS (Storage register clock pin)
int clockPin = 14; // SH_CP, SCK (Shift register clock pin) Set to alternative pin 14, since internal led using 13!
int dataPin = 11;  // DS, MOSI (data out from Teensy, into 595)

Setup

  //USB MIDI_____________________
  usbMIDI.setHandleNoteOff(OnNoteOff);
  usbMIDI.setHandleNoteOn(OnNoteOn);
  digitalWrite (latchPin, HIGH);
  delay(400);
  digitalWrite(latchPin, LOW);


  //SHIFT REGISTER FOR LEDS, OUTPUT PINS_____________________
  //set shift register pins to output
  pinMode(latchPin, OUTPUT);

Loop

 usbMIDI.read();

Functions

void OnNoteOn(byte channel, byte note, byte velocity) {
  digitalWrite(latchPin, HIGH); // Any Note-On turns on LED
}

void OnNoteOff(byte channel, byte note, byte velocity) {
  digitalWrite(latchPin, LOW);  // Any Note-Off turns off LED
}


void shiftOut(int dataPin, int clockPin, byte note) {
  // 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(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

//clear everything out just in case to
//prepare shift register for bit shifting
  digitalWrite(dataPin, 0);
  digitalWrite(clockPin, 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(clockPin, 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 ( note & (1<<i) ) {
      pinState= 1;
    }
    else {  
      pinState= 0;
    }

    //Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(dataPin, pinState);
    //register shifts bits on upstroke of clock pin  
    digitalWrite(clockPin, 1);
    //zero the data pin after shift to prevent bleed through
    digitalWrite(dataPin, 0);
  }

  //stop shifting
  digitalWrite(clockPin, 0);
}

Imbecillen:
Thanks for your advice, I tried it out but it didn't compile

What board are you using? Could you send me the error message you got?
I try to support as many boards as I can, and all examples are compiled for multiple boards as part of my continuous integration pipeline.

Imbecillen:
First of all, do my shiftOut look ok? Second of all, how do I get my shiftOut to talk to my other two functions? Feeling kind of stupid...

Why are you creating your own shiftOut function? The Arduino core has this function built in.

You'll have to create some kind of buffer that keeps track of which LEDs are turned on, and which LEDs are turned off. Then you can use shiftOut to send that buffer to the shift registers, byte by byte.

You can program this yourself, it could be a good learning experience, or you could use a library that allows you to use the usual digitalWrite functions on the 74HC595 pins:
This is what I'm using: Arduino Helpers: 1.SPI-Blink.ino

PieterP:
What board are you using? Could you send me the error message you got?
I try to support as many boards as I can, and all examples are compiled for multiple boards as part of my continuous integration pipeline.
Why are you creating your own shiftOut function? The Arduino core has this function built in.

You'll have to create some kind of buffer that keeps track of which LEDs are turned on, and which LEDs are turned off. Then you can use shiftOut to send that buffer to the shift registers, byte by byte.

You can program this yourself, it could be a good learning experience, or you could use a library that allows you to use the usual digitalWrite functions on the 74HC595 pins:
This is what I'm using: Arduino Helpers: 1.SPI-Blink.ino

Teensy LC (for prototyping, will go for another later), about two years old so it may be an older version if they differ. I will try to replicate the problem tomorrow and send it to you as a thanks for the help :wink: I think it was something with a lib file.

Well, I thought the shiftOut function had to be written to be able to use shift registers, and it all makes a lot more sense now when you explained this! I was following some tutorials and they where building their own shift function. Nice to get rid of it..

The buffer should be an array, something like this right? With temporary readings and comparisons.

for (int i = 0; i < 16; i++) { //loop through 16 mux channels
    if (toReadDigitalMux1[i] == 1) { //we read the choosen mux channel input
      tempDigitalRead1 = digitalReadMux1(i);
      if (pushbuttonMode[i] == 1 && tempDigitalRead1 != buttonState[i]) { //___NORMAL MODE (1)
        delay(20); //just a delay for noise to ensure push button was actually hit
        if (digitalReadMux1(i) == tempDigitalRead1) { //check if pushbutton is still the same
          if (tempDigitalRead1 == LOW) { //button pressed, turn note on
            midiSend('p', 1, i); //call note on/off function
          } else { //button released
            midiSend('p', 0, i);
          }
        }
      }
    }
  }

The library looks nice, but I got one concern. How do I set my SR pins?

Imbecillen:
Teensy LC (for prototyping, will go for another later), about two years old so it may be an older version if they differ. I will try to replicate the problem tomorrow and send it to you as a thanks for the help :wink: I think it was something with a lib file.

Thanks! Teensy LC requires some specific changes to the library. It's not that popular, so I didn't add it yet. I might find some time next week. Now that I know what board it is, I can probably generate the error messages myself, so you don't really have to send it.

Edit: I haven't been able to reproduce the error, it compiles fine for me. Did you select the "MIDI" USB option in the Tools menu?

Imbecillen:
The buffer should be an array, something like this right? With temporary readings and comparisons.

Yes, an array is the best choice here.

Imbecillen:

for (int i = 0; i < 16; i++) { //loop through 16 mux channels

if (toReadDigitalMux1[i] == 1) { //we read the choosen mux channel input
      tempDigitalRead1 = digitalReadMux1(i);
      if (pushbuttonMode[i] == 1 && tempDigitalRead1 != buttonState[i]) { //___NORMAL MODE (1)
        delay(20); //just a delay for noise to ensure push button was actually hit
        if (digitalReadMux1(i) == tempDigitalRead1) { //check if pushbutton is still the same
          if (tempDigitalRead1 == LOW) { //button pressed, turn note on
            midiSend('p', 1, i); //call note on/off function
          } else { //button released
            midiSend('p', 0, i);
          }
        }
      }
    }
  }

It's not entirely clear to me how this code relates to the shift registers?
You can save 8 bits of data in each byte of the array, with the added benefit that it can be shifted out directly.
Here's the implementation of the BitArray class of the library I linked previously: Arduino-Helpers/src/AH/Containers/BitArray.hpp at master · tttapa/Arduino-Helpers · GitHub

Imbecillen:
The library looks nice, but I got one concern. How do I set my SR pins?

The example I linked to uses the SPI pins. I strongly recommend using SPI to drive the shift registers, because it's much faster and more efficient, since everything is done in hardware rather than in software (shiftOut).
You can use many different devices on the same SPI bus, so it doesn't matter if it's already in use.

If SPI is really not an option, you can use the shiftOut version of the library that allows you to use any pair of pins: Arduino Helpers: 2.BitBang-Blink.ino