MIDI control of LED strips

Status
Not open for further replies.

fff54

Member
Hi, I'm looking for some code help. I plan to control 8x LED strips with MIDI, via Teensy LC. I have so far managed to write the code so that each LED strip is individually controlled via a MIDI note on / note off, and that the velocity of the note is related to the brightness of the LED.
But, ideally what I would like to achieve is that the LED trigger is controlled via note on/off, but the brightness is controlled by a separate MIDI cc, such as the mod wheel or an expression pedal. Could someone point me in the right direction to achieve this?
This is what I have so far:
Code:
int DSLLPin = 16;
int DSLCPin = 17;
int DSRCPin = 20;
int DSRRPin = 22;

int USLLPin = 23;
int USLCPin = 3;
int USRCPin = 4;
int USRRPin = 6;



void myNoteOn(byte channel, byte note, byte velocity) {
  velocity = velocity * 2;

  if (note == 60) {
    analogWrite(DSLLPin, velocity);
  }
  if (note == 62) {
    analogWrite(DSLCPin, velocity);
  }
  if (note == 64) {
    analogWrite(DSRCPin, velocity);
  }
  if (note == 65) {
    analogWrite(DSRRPin, velocity);
  }

  if (note == 67) {
    analogWrite(USLLPin, velocity);
  }
  if (note == 69) {
    analogWrite(USLCPin, velocity);
  }
  if (note == 71) {
    analogWrite(USRCPin, velocity);
  }
  if (note == 72) {
    analogWrite(USRRPin, velocity);
  }
}


void myNoteOff(byte channel, byte note, byte velocity) {
  velocity = velocity * 2;
  
  if (note == 60) {
    analogWrite(DSLLPin, 0);
  }
  if (note == 62) {
    analogWrite(DSLCPin, 0);
  }
  if (note == 64) {
    analogWrite(DSRCPin, 0);
  }
  if (note == 65) {
    analogWrite(DSRRPin, 0);
  }

  if (note == 67) {
    analogWrite(USLLPin, 0);
  }
  if (note == 69) {
    analogWrite(USLCPin, 0);
  }
  if (note == 71) {
    analogWrite(USRCPin, 0);
  }
  if (note == 72) {
    analogWrite(USRRPin, 0);
  }


}

void setup() {

  pinMode(DSLLPin, OUTPUT);
  usbMIDI.setHandleNoteOff(myNoteOff) ;
  usbMIDI.setHandleNoteOn(myNoteOn) ;
  analogWrite(DSLLPin, 256);
  delay(400);             
  analogWrite(DSLLPin, 0);

  pinMode(DSLCPin, OUTPUT);
  usbMIDI.setHandleNoteOff(myNoteOff) ;
  usbMIDI.setHandleNoteOn(myNoteOn) ;
  analogWrite(DSLCPin, 256);
  delay(400);            
  analogWrite(DSLCPin, 0);

  pinMode(DSRCPin, OUTPUT);
  usbMIDI.setHandleNoteOff(myNoteOff) ;
  usbMIDI.setHandleNoteOn(myNoteOn) ;
  analogWrite(DSRCPin, 256);
  delay(400);               
  analogWrite(DSRCPin, 0);

  pinMode(DSRRPin, OUTPUT);
  usbMIDI.setHandleNoteOff(myNoteOff) ;
  usbMIDI.setHandleNoteOn(myNoteOn) ;
  analogWrite(DSRRPin, 256);
  delay(400);              
  analogWrite(DSRRPin, 0);

  pinMode(USLLPin, OUTPUT);
  usbMIDI.setHandleNoteOff(myNoteOff) ;
  usbMIDI.setHandleNoteOn(myNoteOn) ;
  analogWrite(USLLPin, 256);
  delay(400);             
  analogWrite(USLLPin, 0);

  pinMode(USLCPin, OUTPUT);
  usbMIDI.setHandleNoteOff(myNoteOff) ;
  usbMIDI.setHandleNoteOn(myNoteOn) ;
  analogWrite(USLCPin, 256);
  delay(400);             
  analogWrite(USLCPin, 0);

  pinMode(USRCPin, OUTPUT);
  usbMIDI.setHandleNoteOff(myNoteOff) ;
  usbMIDI.setHandleNoteOn(myNoteOn) ;
  analogWrite(USRCPin, 256);
  delay(400);    
  analogWrite(USRCPin, 0);

  pinMode(USRRPin, OUTPUT);
  usbMIDI.setHandleNoteOff(myNoteOff) ;
  usbMIDI.setHandleNoteOn(myNoteOn) ;
  analogWrite(USRRPin, 256);
  delay(400);      
  analogWrite(USRRPin, 0);

}
void loop() {
  usbMIDI.read(16);
}
 
You can use usbMIDI.setHandleControlChange(myControlChange);, similar to setHandleNoteOn.
I guess you have seen this page?

Paul
 
I looked a bit further into your code.
There is no need to set the NoteON and NoteOff handler several times, once in setup() is OK, like this:
Code:
void setup() {
  usbMIDI.setHandleNoteOff(myNoteOff);
  usbMIDI.setHandleNoteOn(myNoteOn);

  pinMode(DSLLPin, OUTPUT);
  analogWrite(DSLLPin, 256);
  delay(400);
  analogWrite(DSLLPin, 0);

  pinMode(DSLCPin, OUTPUT);
  analogWrite(DSLCPin, 256);
  delay(400);
  analogWrite(DSLCPin, 0);

  pinMode(DSRCPin, OUTPUT);
  analogWrite(DSRCPin, 256);
  delay(400);
  analogWrite(DSRCPin, 0);

  pinMode(DSRRPin, OUTPUT);
  analogWrite(DSRRPin, 256);
  delay(400);
  analogWrite(DSRRPin, 0);

  pinMode(USLLPin, OUTPUT);
  analogWrite(USLLPin, 256);
  delay(400);
  analogWrite(USLLPin, 0);

  pinMode(USLCPin, OUTPUT);
  analogWrite(USLCPin, 256);
  delay(400);
  analogWrite(USLCPin, 0);

  pinMode(USRCPin, OUTPUT);
  analogWrite(USRCPin, 256);
  delay(400);
  analogWrite(USRCPin, 0);

  pinMode(USRRPin, OUTPUT);
  analogWrite(USRRPin, 256);
  delay(400);
  analogWrite(USRRPin, 0);
}

And there is a code sample at File > Examples > Teensy > USB_MIDI > InputFunctionsComplete that may help you.
Plus a post on this forum.

Paul
 
Last edited:
You can use usbMIDI.setHandleControlChange(myControlChange);, similar to setHandleNoteOn.
I guess you have seen this page?

Paul

Hi Paul, yes I have seen that, but I don't want to use Control Change to trigger the LED strips, just to effect the brightness, while using note on/off to activate the strips... and I can't get my head around how to do that.
 
I looked a bit further into your code.
There is no need to set the NoteON and NoteOff handler several times, once in setup() is OK, like this:
Code:
void setup() {
  usbMIDI.setHandleNoteOff(myNoteOff);
  usbMIDI.setHandleNoteOn(myNoteOn);

  pinMode(DSLLPin, OUTPUT);
  analogWrite(DSLLPin, 256);
  delay(400);
  analogWrite(DSLLPin, 0);

  pinMode(DSLCPin, OUTPUT);
  analogWrite(DSLCPin, 256);
  delay(400);
  analogWrite(DSLCPin, 0);

  pinMode(DSRCPin, OUTPUT);
  analogWrite(DSRCPin, 256);
  delay(400);
  analogWrite(DSRCPin, 0);

  pinMode(DSRRPin, OUTPUT);
  analogWrite(DSRRPin, 256);
  delay(400);
  analogWrite(DSRRPin, 0);

  pinMode(USLLPin, OUTPUT);
  analogWrite(USLLPin, 256);
  delay(400);
  analogWrite(USLLPin, 0);

  pinMode(USLCPin, OUTPUT);
  analogWrite(USLCPin, 256);
  delay(400);
  analogWrite(USLCPin, 0);

  pinMode(USRCPin, OUTPUT);
  analogWrite(USRCPin, 256);
  delay(400);
  analogWrite(USRCPin, 0);

  pinMode(USRRPin, OUTPUT);
  analogWrite(USRRPin, 256);
  delay(400);
  analogWrite(USRRPin, 0);
}

And there is a code sample at File > Examples > Teensy > USB_MIDI > InputFunctionsComplete that may help you.
Plus a post on this forum.

Paul

Thanks for streamlining this, that makes sense and I'll incorporate it. As for the InputFunctionsComplete example, I'll have a look again and see if i can get my head around how to use both note on/off and control change with analogWrite.
 
Hi again, bumping this up as I'm sadly no further on in my quest to trigger an LED strip on/off using MIDI note on/off, and then control the brightness with a MIDI cc after it has been triggered...
Any advice would be much appreciated.
 
@fff54:

I'm not where I can get to my Teensy, so all of this will be off the top of my head:

In your original post, you make the following call to activate a particular LED strip & the brightness is set by the note's velocity:

Code:
  if (note == 60) {
    analogWrite(DSLLPin, velocity);
  }

So if I understand correctly, you want to use a value that is set by a CC message to control the brightness instead of using the "velocity" of the note. As PaulS suggested, include the usbMIDI.setHandleControlChange(handleControlChange); call in your setup(), then create a "handleControlChange()" function that will take the value reported by your selected CC & store it into a variable called "brightness". Your previous code then becomes as follows:

Code:
  if (note == 60) {
    analogWrite(DSLLPin, brightness);
  }

Your "handleControlChange()" function will need to parse the control number reported to only look at the CC for your selected device (e.g. the MODwheel typically reports as device #1) as follows:

Code:
// one-time setup
setup()
{
   usbMIDI.setHandleControlChange(handleControlChange);
}


// MIDI message callback - control change
void handleControlChange(byte channel, byte number, byte value)
{
   // MOD wheel
   if (number == 1)
   {
      brightness = value;  // scale this if/as needed
   }
}

Hopefully this gives you some ideas on how to proceed . . . feel free to ask more questions !!

Mark J Culross
KD5RXT
 
Hi Mark, thanks for this, it's starting to make a bit more sense to me! (I'm very new to this as I'm sure you can tell!)
Could I then also have a different MIDI CC for each of the different LED strips? So, for example...

Code:
if (note == 60) {
    analogWrite(DSLLPin, DSLLbrightness);
  }
if (note == 62) {
    analogWrite(DSLCPin, DSLCbrightness);

etc etc.. and then
Code:
// MIDI message callback - control change
void handleControlChange(byte channel, byte number, byte value)
{
   // MOD wheel
   if (number == 1)
   {
      DSLLbrightness = value*2;  // scale this if/as needed
   }
  {
   // EXPRESSION
   if (number == 7)
   {
      DSLCbrightness = value*2;  // scale this if/as needed
   }
}

Or could it only be 1 MIDI cc to control the brightness of all the different LED strips?

Thanks!
Mickey
 
Could I then also have a different MIDI CC for each of the different LED strips? So, for example...

Code:
// MIDI message callback - control change
void handleControlChange(byte channel, byte number, byte value)
{
   // MOD wheel
   if (number == 1)
   {
      DSLLbrightness = value*2;  // scale this if/as needed
   }
  {
   // EXPRESSION
   if (number == 7)
   {
      DSLCbrightness = value*2;  // scale this if/as needed
   }
}

Thanks!
Mickey

Mickey (fff54):

Yes, you can do exactly what you have shown & use a different MIDI CC input to set the brightness individually for each strip.

Good luck & have fun !! (And again, feel free to ask more questions)

Mark J Culross
KD5RXT
 
Hi again Mark!

So in trying this out with a different value for each LEDs brightness name, I then get the error that, for example, 'DSLLBright' was not declared in this scope... (the same error for all of them)

This is the code I tried to verify..

Code:
int DSLLPin = 16;
int DSLCPin = 17;
int DSRCPin = 20;
int DSRRPin = 22;

int USLLPin = 23;
int USLCPin = 3;
int USRCPin = 4;
int USRRPin = 6;



void myNoteOn(byte channel, byte note, byte velocity) {
  velocity = velocity * 2;

  // downstage lights left to right - notes C3 D3 E3 F3

  if (note == 60) {
    analogWrite(DSLLPin, DSLLBright);
  }
  if (note == 62) {
    analogWrite(DSLCPin, DSLCBright);
  }
  if (note == 64) {
    analogWrite(DSRCPin, DSRCBright);
  }
  if (note == 65) {
    analogWrite(DSRRPin, DSRRBright);
  }

  // upstage lights left to right - notes G3 A3 B3 C4

  if (note == 67) {
    analogWrite(USLLPin, USLLBright);
  }
  if (note == 69) {
    analogWrite(USLCPin, USLCBright);
  }
  if (note == 71) {
    analogWrite(USRCPin, USRCBright);
  }
  if (note == 72) {
    analogWrite(USRRPin, USRRBright);
  }
}


void myNoteOff(byte channel, byte note, byte velocity) {
  velocity = velocity * 2;
  
  // downstage lights left to right - notes C3 D3 E3 F3

  if (note == 60) {
    analogWrite(DSLLPin, 0);
  }
  if (note == 62) {
    analogWrite(DSLCPin, 0);
  }
  if (note == 64) {
    analogWrite(DSRCPin, 0);
  }
  if (note == 65) {
    analogWrite(DSRRPin, 0);
  }

  // upstage lights left to right - notes G3 A3 B3 C4

  if (note == 67) {
    analogWrite(USLLPin, 0);
  }
  if (note == 69) {
    analogWrite(USLCPin, 0);
  }
  if (note == 71) {
    analogWrite(USRCPin, 0);
  }
  if (note == 72) {
    analogWrite(USRRPin, 0);
  }


void handleControlChange(byte channel, byte number, byte value)
{
   // downstage 
   
   if (number == 111)
   {
      DSLLBright = value*2;  
   }
   if (number == 112)
   {
      DSLCBright = value*2;  
   }
   if (number == 113)
   {
      DSRCBright = value*2;  
   }
   if (number == 114)
   {
      DSRRBright = value*2;  
   }
   
   // upstage 
   
   if (number == 115)
   {
      USLLBright = value*2;  
   }
   if (number == 116)
   {
      USLCBright = value*2;  
   }
   if (number == 117)
   {
      USRCBright = value*2;  
   }
   if (number == 118)
   {
      USRRBright = value*2;  
   }
}



void setup() {
  usbMIDI.setHandleNoteOff(myNoteOff);
  usbMIDI.setHandleNoteOn(myNoteOn);
  usbMIDI.setHandleControlChange(myControlChange);
  
  // downstage

  pinMode(DSLLPin, OUTPUT);
  analogWrite(DSLLPin, 256);
  delay(400);                 
  analogWrite(DSLLPin, 0);

  pinMode(DSLCPin, OUTPUT);
  analogWrite(DSLCPin, 256);
  delay(400);                
  analogWrite(DSLCPin, 0);

  pinMode(DSRCPin, OUTPUT);
  analogWrite(DSRCPin, 256);
  delay(400);               
  analogWrite(DSRCPin, 0);

  pinMode(DSRRPin, OUTPUT);
  analogWrite(DSRRPin, 256);
  delay(400);                 
  analogWrite(DSRRPin, 0);

  // upstage

  pinMode(USLLPin, OUTPUT);
  analogWrite(USLLPin, 256);
  delay(400);               
  analogWrite(USLLPin, 0);

  pinMode(USLCPin, OUTPUT);
  analogWrite(USLCPin, 256);
  delay(400);                
  analogWrite(USLCPin, 0);

  pinMode(USRCPin, OUTPUT);
  analogWrite(USRCPin, 256);
  delay(400);                
  analogWrite(USRCPin, 0);

  pinMode(USRRPin, OUTPUT);
  analogWrite(USRRPin, 256);
  delay(400);                 
  analogWrite(USRRPin, 0);

}
void loop() {
  usbMIDI.read(16); 
}

Do I need to somehow "declare" each of these brightness names somehow at the beginning of the code in the same way as the pin names are linked to actual pin numbers....?
 
Making good progress

Mickey (fff54):

Yup, you are correct again !! I am guessing that you are in the process of learning C, and that's not a bad thing at all !! You are doing well !!

As you correctly discerned, you will need to declare your DSxxBright variables at the top of your INO file just like you did for the pin variables.

Code:
int DSLLBright;
int DSLCBright;
int DSRCBright;
int DSRRBright;
Here are a couple of things to note:

1) when you declare them at the top of the file like this, they are known as "global variables" & can be used within any function (contrast that with variables that are defined within a function, which are known as "local variables" & can only be used within that specific function. This concept is referred to as "variable scope".)

2) Since you will be using these variables to pass values to the analogWrite() function, which is expecting an "int" for the "value", it's easiest to define your variables as "int" as well. Just be aware that the compiler will do you a favor by comparing the variable type you pass (your "DSxxBright" is defined as type "int") with the variable type expected (analogWrite() is expecting an "value" to be type "int"). With both of these being defined as type "int", the compiler will have no complaints.

3) Notice that the "value" received in the handleControlChange() function is of type "byte". When you use one variable (the "value" of type "byte" received by your handleControlChange() function) & assign it to another variable (your "DSxxBright" defined as type "int"), the compiler will also compare the types in this case as well. Unless you do something "extra", the compiler will issue a warning about the types not matching. Here's the "extra" required in this specific case (highlighted in RED font):

Code:
// MIDI message callback - control change
void handleControlChange(byte channel, byte number, byte value)
{
   // MOD wheel
   if (number == 1)
   {
      DSLLbrightness = [COLOR="#FF0000"](int)[/COLOR]value*2;  // scale this if/as needed
   }
   // EXPRESSION
   if (number == 7)
   {
      DSLCbrightness = [COLOR="#FF0000"](int)[/COLOR]value*2;  // scale this if/as needed
   }
}

This is known as a "type cast" . . . in this case, we are taking a "byte" value & "casting" it to an "int". Type casting must be used carefully to make sure that information is not lost. For example, if you try type casting an "int" (which can hold values from -32768 to +32767) to a "byte" (which can hold values from 0 to 255), you can see that the resulting "byte" will contain *much less* information, & the original value will almost certainly not be properly represented !!

Keep up the good work (& as before, ask more if/as needed) !!

Mark J Culross
KD5RXT
 
Last edited:
Many thanks Mark, you have been incredibly helpful! I admit that I don't understand everything perfectly, but I'm definitely learning a lot... I managed to get the following code to compile successfully. I'm not physically with the teensy and the LEDs right now, but I will be again next week and I look forward to testing this out! Will report back...
Thank you for your help.
Code:
int DSLLBrightness;
int DSLCBrightness;
int DSRCBrightness;
int DSRRBrightness;

int USLLBrightness;
int USLCBrightness;
int USRCBrightness;
int USRRBrightness;

int DSLLPin = 16;
int DSLCPin = 17;
int DSRCPin = 20;
int DSRRPin = 22;

int USLLPin = 23;
int USLCPin = 3;
int USRCPin = 4;
int USRRPin = 6;


void myNoteOn(byte channel, byte note, byte velocity) {
  velocity = velocity * 2;

  // downstage lights left to right - notes C3 D3 E3 F3

  if (note == 60) {
    analogWrite(DSLLPin, DSLLBrightness);
  }
  if (note == 62) {
    analogWrite(DSLCPin, DSLCBrightness);
  }
  if (note == 64) {
    analogWrite(DSRCPin, DSRCBrightness);
  }
  if (note == 65) {
    analogWrite(DSRRPin, DSRRBrightness);
  }

  // upstage lights left to right - notes G3 A3 B3 C4

  if (note == 67) {
    analogWrite(USLLPin, USLLBrightness);
  }
  if (note == 69) {
    analogWrite(USLCPin, USLCBrightness);
  }
  if (note == 71) {
    analogWrite(USRCPin, USRCBrightness);
  }
  if (note == 72) {
    analogWrite(USRRPin, USRRBrightness);
  }
}


void myNoteOff(byte channel, byte note, byte velocity) {
  velocity = velocity * 2;

  // downstage lights left to right - notes C3 D3 E3 F3

  if (note == 60) {
    analogWrite(DSLLPin, 0);
  }
  if (note == 62) {
    analogWrite(DSLCPin, 0);
  }
  if (note == 64) {
    analogWrite(DSRCPin, 0);
  }
  if (note == 65) {
    analogWrite(DSRRPin, 0);
  }

  // upstage lights left to right - notes G3 A3 B3 C4

  if (note == 67) {
    analogWrite(USLLPin, 0);
  }
  if (note == 69) {
    analogWrite(USLCPin, 0);
  }
  if (note == 71) {
    analogWrite(USRCPin, 0);
  }
  if (note == 72) {
    analogWrite(USRRPin, 0);
  }
}

void myControlChange(byte channel, byte number, byte value) {

  // downstage lights

  if (number == 111)
  {
    DSLLBrightness = (int)value * 2;
  }
  if (number == 112)
  {
    DSLCBrightness = (int)value * 2;
  }
  if (number == 113)
  {
    DSRCBrightness = (int)value * 2;
  }
  if (number == 114)
  {
    DSRRBrightness = (int)value * 2;
  }

  // upstage lights

  if (number == 115)
  {
    USLLBrightness = (int)value * 2;
  }
  if (number == 116)
  {
    USLCBrightness = (int)value * 2;
  }
  if (number == 117)
  {
    USRCBrightness = (int)value * 2;
  }
  if (number == 118)
  {
    USRRBrightness = (int)value * 2;
  }

}

void setup() {
  usbMIDI.setHandleNoteOff(myNoteOff);
  usbMIDI.setHandleNoteOn(myNoteOn);
  usbMIDI.setHandleControlChange(myControlChange);


// downstage

  pinMode(DSLLPin, OUTPUT);
  analogWrite(DSLLPin, 256);
  delay(400);                 
  analogWrite(DSLLPin, 0);

  pinMode(DSLCPin, OUTPUT);
  analogWrite(DSLCPin, 256);
  delay(400);                 
  analogWrite(DSLCPin, 0);

  pinMode(DSRCPin, OUTPUT);
  analogWrite(DSRCPin, 256);
  delay(400);                
  analogWrite(DSRCPin, 0);

  pinMode(DSRRPin, OUTPUT);
  analogWrite(DSRRPin, 256);
  delay(400);                 
  analogWrite(DSRRPin, 0);

  // upstage

  pinMode(USLLPin, OUTPUT);
  analogWrite(USLLPin, 256);
  delay(400);               
  analogWrite(USLLPin, 0);

  pinMode(USLCPin, OUTPUT);
  analogWrite(USLCPin, 256);
  delay(400);                 
  analogWrite(USLCPin, 0);

  pinMode(USRCPin, OUTPUT);
  analogWrite(USRCPin, 256);
  delay(400);              
  analogWrite(USRCPin, 0);

  pinMode(USRRPin, OUTPUT);
  analogWrite(USRRPin, 256);
  delay(400);                
  analogWrite(USRRPin, 0);

}
void loop() {
  usbMIDI.read(16); 
}
 
You're welcome !! Glad to help !!

Mickey (fff54):

You are very welcome & glad that I could be of some help. I received lots of excellent help on this forum when I first got started using the Teensy, so I'm doing my best to carry on that tradition !!

I thought of one more thing that you might find beneficial to add: you might want to set a default brightness level for the strips. Consider the following: if a noteOn message comes thru for a particular LED strip, but the CC that controls the brightness of that strip has not yet been received, the default brightness would be "0", thus you wouldn't be able to tell that the noteOn message was received by viewing any changes in the LED strip(s). Let's say you want the default brightness of each LED strip to be half the maximum value (assume max=255, so half would be 127), then you'd change the definition line to make use of the ability to "set an initial value in the definition line" as follows:

Code:
int DSLLBrightness = 127;
int DSLCBrightness = 127;
int DSRCBrightness = 127;
int DSRRBrightness = 127;

int USLLBrightness = 127;
int USLCBrightness = 127;
int USRCBrightness = 127;
int USRRBrightness = 127;

Anytime a CC message is received, it will overwrite the default brightness value in the corresponding variable.

You could also initialize each LED strip to a different default brightness value if you'd like.

Good luck & have fun !! Looking forward to hearing how it goes . . .

Mark J Culross
KD5RXT
 
Hi Mark, thanks for this, that's definitely a very helpful addition!
So my next thought is that it must be relatively straight forward to convert this code to control an RGB strip too, right? Create an int for each of the 3 R/G/B pins for each LED strip, and for 3x brightness pins each too (which is how you 'mix' the desired colour?) and then I could have a noteOn message trigger an RGB LED strip and three midi CC faders to control the colour balance... Does this sound correct, or am I missing something else fundamental?
 
I just tried to knock this up and it compiles OK, replacing the 8x single colour LED strips for 2x RGB LED strips.... What do you think?


Code:
int LeftRedBrightness = 255;
int LeftGreenBrightness = 255;
int LeftBlueBrightness = 255;

int RightRedBrightness = 255;
int RightGreenBrightness = 255;
int RightBlueBrightness = 255;

int LeftRedPin = 16;
int LeftGreenPin = 17;
int LeftBluePin = 20;

int RightRedPin = 22;
int RightGreenPin = 23;
int RightBluePin = 3;


void myNoteOn(byte channel, byte note, byte velocity) {
  velocity = velocity * 2;

  // left - note C3

  if (note == 60) {
    analogWrite(LeftRedPin, LeftRedBrightness);
    analogWrite(LeftGreenPin, LeftGreenBrightness);
    analogWrite(LeftBluePin, LeftBlueBrightness);
  }

  // right - note G3

  if (note == 67) {
    analogWrite(RightRedPin, RightRedBrightness);
    analogWrite(RightGreenPin, RightGreenBrightness);
    analogWrite(RightBluePin, RightBlueBrightness);
  }
}


void myNoteOff(byte channel, byte note, byte velocity) {
  velocity = velocity * 2;

  // left - note C3

  if (note == 60) {
    analogWrite(LeftRedPin, 0);
    analogWrite(LeftGreenPin, 0);
    analogWrite(LeftBluePin, 0);
  }

  // right - note G3

  if (note == 67) {
    analogWrite(RightRedPin, 0);
    analogWrite(RightGreenPin, 0);
    analogWrite(RightBluePin, 0);
  }
}

void myControlChange(byte channel, byte number, byte value) {

  // left

  if (number == 111)
  {
    LeftRedBrightness = (int)value * 2;
  }
  if (number == 112)
  {
    LeftGreenBrightness = (int)value * 2;
  }
  if (number == 113)
  {
    LeftBlueBrightness = (int)value * 2;
  }

  // right

  if (number == 115)
  {
    RightRedBrightness = (int)value * 2;
  }
  if (number == 116)
  {
    RightGreenBrightness = (int)value * 2;
  }
  if (number == 117)
  {
    RightBlueBrightness = (int)value * 2;
  }
}

void setup() {
  usbMIDI.setHandleNoteOff(myNoteOff);
  usbMIDI.setHandleNoteOn(myNoteOn);
  usbMIDI.setHandleControlChange(myControlChange);


  // left
  pinMode(LeftRedPin, OUTPUT);
  pinMode(LeftGreenPin, OUTPUT);
  pinMode(LeftBluePin, OUTPUT);

  // right
  pinMode(RightRedPin, OUTPUT);
  pinMode(RightGreenPin, OUTPUT);
  pinMode(RightBluePin, OUTPUT);
}

void loop() {
  usbMIDI.read(16); // Only listens to MIDI Channel 16
}
 
Hi Mark and everyone,
I am back with the Teensy and the LED strips now and testing this code out:

Code:
int allBrightness = 255;

int DSLLPin = 16;
int DSLCPin = 17;
int DSRCPin = 20;
int DSRRPin = 22;

int USLLPin = 23;
int USLCPin = 3;
int USRCPin = 4;
int USRRPin = 6;


void myNoteOn(byte channel, byte note, byte velocity) {
  velocity = velocity * 2;

  // downstage lights left to right - notes C3 D3 E3 F3

  if (note == 60) {
    analogWrite(DSLLPin, allBrightness);
  }
  if (note == 62) {
    analogWrite(DSLCPin, allBrightness);
  }
  if (note == 64) {
    analogWrite(DSRCPin, allBrightness);
  }
  if (note == 65) {
    analogWrite(DSRRPin, allBrightness);
  }

  // upstage lights left to right - notes G3 A3 B3 C4

  if (note == 67) {
    analogWrite(USLLPin, allBrightness);
  }
  if (note == 69) {
    analogWrite(USLCPin, allBrightness);
  }
  if (note == 71) {
    analogWrite(USRCPin, allBrightness);
  }
  if (note == 72) {
    analogWrite(USRRPin, allBrightness);
  }
}


void myNoteOff(byte channel, byte note, byte velocity) {
  velocity = velocity * 2;

  // downstage lights left to right - notes C3 D3 E3 F3

  if (note == 60) {
    analogWrite(DSLLPin, 0);
  }
  if (note == 62) {
    analogWrite(DSLCPin, 0);
  }
  if (note == 64) {
    analogWrite(DSRCPin, 0);
  }
  if (note == 65) {
    analogWrite(DSRRPin, 0);
  }

  // upstage lights left to right - notes G3 A3 B3 C4

  if (note == 67) {
    analogWrite(USLLPin, 0);
  }
  if (note == 69) {
    analogWrite(USLCPin, 0);
  }
  if (note == 71) {
    analogWrite(USRCPin, 0);
  }
  if (note == 72) {
    analogWrite(USRRPin, 0);
  }
}

void myControlChange(byte channel, byte number, byte value) {

 // all lights brightness control

  if (number == 18)
  {
    allBrightness = (int)value * 2;
  }
}

void setup() {
  usbMIDI.setHandleNoteOff(myNoteOff);
  usbMIDI.setHandleNoteOn(myNoteOn);
  usbMIDI.setHandleControlChange(myControlChange);

  pinMode(DSLLPin, OUTPUT);
  pinMode(DSLCPin, OUTPUT);
  pinMode(DSRCPin, OUTPUT);
  pinMode(DSRRPin, OUTPUT);
  pinMode(USLLPin, OUTPUT);
  pinMode(USLCPin, OUTPUT);
  pinMode(USRCPin, OUTPUT);
  pinMode(USRRPin, OUTPUT);

}
void loop() {
  usbMIDI.read(16); 
}

This is working OK in the sense that MIDI CC#18 will now effect the brightness level of the LED when it turns on, but once it's lit the brightness level is fixed at that value and CC#18 has no more effect on the LEDs, and as such I can't, for example, fade the light out.

What I'm trying to achieve is that the noteOn activates the LED, then while the LED is on the CC #18 will actively control the brightness level, so for example I can fade the LED strip brightness up and down with CC#18.

If anyone has any advice about how to achieve this (or, if it's even possible?) it would be much appreciated.
Many thanks
 
You need to keep track of the currently active notes in a datastructure so that when you get #18 CC you can call
analogWrite again on all the active notes.
 
Hi MarkT, thank you for the reply, it's good to know it's possible at least!
Would you be able to give any more advice or instructions about how to achieve what you've suggested?
Many thanks!
 
Well the simplest approach is an array of bool, one for each note. Maintain its state with the noteOn/noteOff
events, scan it when you get a #18 CC event.
 
Thanks MarkT. I'm not a coder, I'm a total beginner to this world so I have no idea how to implement what you've said! Do you know if there is a tutorial somewhere that might help me?
 
Try search terms to find relevant tutorials, perhaps "using arrays in C" - there will be a whole shed-load
of tutorials out there, finding one suited to you will take some creative use of a search engine. There are
probably some good introductions to programming for MIDI as well out there.
 
Thank you for the advice MarkT, I've done a lot of googling and watching tutorials but I'm well out of my depth and not getting any closer to understanding how to do this! Which is extra frustrating as from what you've said seems like it should be simplistic enough!

If there is anyone who has done something like this before and could show me an example of a code, or would would be willing to walk me through it (for a fee perhaps?) I would be very grateful.
 
This: "This is working OK in the sense that MIDI CC#18 will now effect the brightness level of the LED when it turns on, but once it's lit the brightness level is fixed at that value and CC#18 has no more effect on the LEDs, and as such I can't, for example, fade the light out."

is probably linked to the allbrightness only being used to set led values within the myNoteOn() function. perhaps it brightness of leds will therefore only change when a new note on is triggered. If the control change function included an update outside of the mynoteon function, that might be away to update the led brightness.

so perhaps something along the lines of
Code:
void myControlChange(byte channel, byte number, byte value) {

 // all lights brightness control

  if (number == 18)
  {
    allBrightness = (int)value * 2;
//psuedo code
//add lines to go an update all leds that are currently on. 
if{led is currently on
analogWrite this led with new brightness
}

  }
}
 
Hi mortonkopf, thank you for this! I'm making progress...!

So, I've converted this code to operate 2x RGB LED strips (instead of 8x single colour strips)... I compiled the following code and it works, in that I can trigger an LED with noteOn and then adjust the brightness of each R,G & B individually with midi CC numbers, fantastic!

Code:
int RedBrightness = 0;
int GreenBrightness = 0;
int BlueBrightness = 0;


int LeftRedPin = 16;
int LeftGreenPin = 17;
int LeftBluePin = 20;

int RightRedPin = 22;
int RightGreenPin = 23;
int RightBluePin = 3;


void myNoteOn(byte channel, byte note, byte velocity) {
  velocity = velocity * 2;

  // left - note C3

  if (note == 60) {
    analogWrite(LeftRedPin, RedBrightness);
    analogWrite(LeftGreenPin, GreenBrightness);
    analogWrite(LeftBluePin, BlueBrightness);
  }

  // right - note D3

  if (note == 62) {
    analogWrite(RightRedPin, RedBrightness);
    analogWrite(RightGreenPin, GreenBrightness);
    analogWrite(RightBluePin, BlueBrightness);
  }
}


void myNoteOff(byte channel, byte note, byte velocity) {
  velocity = velocity * 2;

  // left - note C3

  if (note == 60) {
    analogWrite(LeftRedPin, 0);
    analogWrite(LeftGreenPin, 0);
    analogWrite(LeftBluePin, 0);
  }

  // right - note D3

  if (note == 62) {
    analogWrite(RightRedPin, 0);
    analogWrite(RightGreenPin, 0);
    analogWrite(RightBluePin, 0);
  }
}

void myControlChange(byte channel, byte number, byte value) {

  // RGB brightness - MIDI CC 22/23/24

  //red

  if (number == 22)
  {
    RedBrightness = (int)value * 2;
    if (LeftRedPin > 0)
      analogWrite(LeftRedPin, RedBrightness);
    if (RightRedPin > 0)
      analogWrite(RightRedPin, RedBrightness);
  }

  //green

  if (number == 24)
  {
    GreenBrightness = (int)value * 2;
    if (LeftGreenPin > 0)
      analogWrite(LeftGreenPin, GreenBrightness);
    if (RightRedPin > 0)
      analogWrite(RightGreenPin, GreenBrightness);
  }

  //blue

  if (number == 23)
  {
    BlueBrightness = (int)value * 2;
    if (LeftBluePin > 0)
      analogWrite(LeftBluePin, BlueBrightness);
    if (RightRedPin > 0)
      analogWrite(RightBluePin, BlueBrightness);
  }
}

void setup() {
  usbMIDI.setHandleNoteOff(myNoteOff);
  usbMIDI.setHandleNoteOn(myNoteOn);
  usbMIDI.setHandleControlChange(myControlChange);

  // left
  pinMode(LeftRedPin, OUTPUT);
  pinMode(LeftGreenPin, OUTPUT);
  pinMode(LeftBluePin, OUTPUT);

  // right
  pinMode(RightRedPin, OUTPUT);
  pinMode(RightGreenPin, OUTPUT);
  pinMode(RightBluePin, OUTPUT);
}

void loop() {
  usbMIDI.read(16); // Only listens to MIDI Channel 16
}

However, my new problem is that the noteOn messages are now effectively redundant - the midi CC brightness controllers trigger the LED strips regardless of the noteOn message... For example if I tweak a CC the LED strip will turn on to that value, regardless of the fact that there has not been a noteOn message.

I tried to edit the 'if' statement to include myNoteOn=60 etc (see code snippet below) but it didn't make a difference. Do you know how I would translate this into a correct piece of code, so that the LEDs will only activate if there has been a relevant noteOn message?

Code:
  if (number == 22)
  {
    RedBrightness = (int)value * 2;
    if (myNoteOn==60, LeftRedPin > 0)
      analogWrite(LeftRedPin, RedBrightness);
    if (myNoteOn==62, RightRedPin > 0)
      analogWrite(RightRedPin, RedBrightness);
  }
 
HI, this "For example if I tweak a CC the LED strip will turn on to that value, regardless of the fact that there has not been a noteOn message." relates to my suggestion in the pseudo code with the line //add lines to go an update all leds that are currently on.

So, what you could do is add code that that says if there is a cc18 AND if the note is on. We do this by using the && term. One way to do this is to follow up on MarkT suggestion of maintaining an array of states of the LEDs. This is done using a State Machine. you keep a variable that you say is either 1 or zero for on or off, and you change this variable when the note goes on or off. you can then reference this to check what state the led is in, and so only allow the cc18 to work if the note is on.

For state variable example code, have a quick read here: https://www.instructables.com/Finite-State-Machine-on-an-Arduino/
and, for example, if you applied the state machine for note 60, and called it boolean note60,
for the application using this way of doing it, you would have:
if( ( received the cc18 message) && (note60 == 1)) {now change brightness of the on leds;}

its just one way of doing it.
 
Status
Not open for further replies.
Back
Top