Looking for simple MIDI CC code

Status
Not open for further replies.

Synchrony

Active member
Hi! Newbie coder, but pretty good with MIDI. I've written code that sends MIDI notes to my computer using sensors and it's working great. Now I need to do kind of the opposite and I'm at a loss. I need to send MIDI CC to a Tensy 3.2 to alter stuff in the code.

Basically like this:

1. Send MIDI CC #40 from my MIDI controller (like this one) to Teensy
2. If MIDI CC #40 = 127, do something
3. Else if MIDI CC #40 = 0, do something else

I've looked at the tutorials and just don't understand it. I know basic if/else code, but not how to get the MIDI CC data to manipulate. I'm up against a deadline and could use some help. If I could get the basic setup and loop code required I would greatly appreciate it.

TIA!
 
If your MIDI controller is only USB midi you’ll be much better off using either a T3.6 or T4.0 which have a second USB port that can be used as a host for other USB devices like the one you linked. If you want it to work with DIN based MIDI then any Teensy can be used rather simply and there are examples already available for this using the MIDI library included with the Teensyduino install, for USB based MIDI there are some examples in the USBHost_t36 library included as well.
 
The good thing is you can use the same control change callback function between all the libraries so without even having all the hardware you aer able to test this while only being connected to a computer and use a program such as MIDI Tools which I use to test MIDI hardware as I build it.

So something like this should work on the T3.6/T4.0 for all forms of midi whether USB device or USB host or DIN.
Code:
#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

#include <USBHost_t36.h>

USBHost myusb;
USBHub hub1(myusb);
USBHub hub2(myusb);
MIDIDevice midi1(myusb);

void setup() {
  myusb.begin();
  MIDI.begin();
  MIDI.setHandleControlChange(onControlChange);
  usbMIDI.setHandleControlChange(onControlChange);
  midi1.setHandleControlChange(onControlChange);
}

void loop() {
  myusb.Task();
  while(usbMIDI.read() || MIDI.read() || midi1.read()){
  }
}

void onControlChange(uint8_t channel, uint8_t control, uint8_t value){
  if(control == 40){
    if(value == 127){
      //Do something
    }
    else if(value == 0){
      //Do something else
    }
  }
}

If you want to just test it at this point and still use the T3.2 with only a computer program and no external hardware you can just do something like this.
Code:
void setup() {
  usbMIDI.setHandleControlChange(onControlChange);
}

void loop() {
  while(usbMIDI.read()){
  }
}

void onControlChange(uint8_t channel, uint8_t control, uint8_t value){
  if(control == 40){
    if(value == 127){
      //Do something
    }
    else if(value == 0){
      //Do something else
    }
  }
}
 
I don't need a second port because I'm running everything through a computer with MIDI routing software. I'm using in and out through one USB cable. I've got that stuff covered.

I looked at the MIDI InputFunctionsBasics and MIDI InputRead examples. I'm sorry, I'm just so basic a coder. I need to get CC# 40 from MIDI Channel one (no virtual cables, not using MIDIx4 or MIDIx16). Then {if CC #40 = 127} do {this code} else do {this code}. I feel dumb about it, but the example code still isn't making sense to me. I'll paypal $5 to someone who can spell it out for me. :)
 
Run the InputFunctionsComplete example on your Teensy, and then open the Arduino Serial Monitor. As your PC sends MIDI messages, you should see info about each message Teensy receives printed to the serial monitor.

Step 1: Just run it and make sure the Control Change lines it prints have the correct info.

Step 2: Delete code for all the messages you don't care to see. That example is long. If the basic version prints the right info, it might save you a little time with less code to delete. As you delete stuff, keep uploading the code to your Teensy to make sure it still works for the Control Change printing you care about.

Step 3: Change the myControlChange() function to do whatever you want with the CC message.
 
If you want to just test it at this point and still use the T3.2 with only a computer program and no external hardware you can just do something like this.
Code:
void setup() {
  usbMIDI.setHandleControlChange(onControlChange);
}

void loop() {
  while(usbMIDI.read()){
  }
}

void onControlChange(uint8_t channel, uint8_t control, uint8_t value){
  if(control == 40){
    if(value == 127){
      //Do something
    }
    else if(value == 0){
      //Do something else
    }
  }
}

Question: I'm using the Adafruit library to drive lights with my MIDI code (it's working fine), so this line:

void onControlChange(uint8_t channel, uint8_t control, uint8_t value)

is giving me this error:

Arduino: 1.8.10 (Windows 10), TD: 1.48, Board: "Teensy 3.2 / 3.1, Serial + MIDI, 96 MHz (overclock), Faster, US English"

Sabre_code_final_002:198: error: 'void onControlChange(uint8_t, uint8_t, uint8_t)' redeclared as different kind of symbol
void onControlChange(uint8_t channel, uint8_t control, uint8_t value){

^

C:\Users\timea\Documents\Arduino\Sabre_code_final_002\Sabre_code_final_002.ino:38:5: note: previous declaration 'int onControlChange'

int onControlChange;

^

Sabre_code_final_002: In function 'void setup()':
C:\Users\timea\Documents\Arduino\Sabre_code_final_002\Sabre_code_final_002.ino:58:49: warning: invalid conversion from 'int' to 'void (*)(uint8_t, uint8_t, uint8_t) {aka void (*)(unsigned char, unsigned char, unsigned char)}' [-fpermissive]

usbMIDI.setHandleControlChange(onControlChange);

^

In file included from C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy3/WProgram.h:59:0,

from C:\Users\timea\AppData\Local\Temp\arduino_build_407726\pch\Arduino.h:6:

C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy3/usb_midi.h:305:14: note: initializing argument 1 of 'void usb_midi_class::setHandleControlChange(void (*)(uint8_t, uint8_t, uint8_t))'

void setHandleControlChange(void (*fptr)(uint8_t channel, uint8_t control, uint8_t value)) {

^

Sabre_code_final_002: In function 'void onControlChange(uint8_t, uint8_t, uint8_t)':
Sabre_code_final_002:198: error: 'void onControlChange(uint8_t, uint8_t, uint8_t)' redeclared as different kind of symbol
void onControlChange(uint8_t channel, uint8_t control, uint8_t value){

^

C:\Users\timea\Documents\Arduino\Sabre_code_final_002\Sabre_code_final_002.ino:38:5: note: previous declaration 'int onControlChange'

int onControlChange;

^

Sabre_code_final_002:205: error: expected '}' at end of input
}

^

Sabre_code_final_002:205: error: expected '}' at end of input
Multiple libraries were found for "Adafruit_TLC5947.h"
Used: C:\Users\timea\Documents\Arduino\libraries\Adafruit_TLC5947-master
'void onControlChange(uint8_t, uint8_t, uint8_t)' redeclared as different kind of symbol

I'm lost on that.
 
Looks like you have a variable with the same name as the function “onControlChange” so one or other needs to be changed to a different name.
 
Okay, I'm finally at the stage where I can try to get this working. I'm going to post my full code. The sensor to MIDI section and the lights are working perfectly. I *know* my code isn't elegant. I'm having difficulty making 'for' loops work right with this application, so it's a lot of replication -- and I'm fine with that for now because I'm up against a deadline. After this Sunday, I'll work on slimlining the code.

Right now I need to to this: I need to send a CC # to turn off all of the light channels and another CC # to turn them back on. It will be send via USB MIDI, the same MIDI that's transmitting the MIDI notes back to my software synth. I don't really understand functions or how to incorporate the CC code into my existing code. Here is where I'm at. Thanks in advance!

Code:
// LED
#include "Adafruit_TLC5947.h"
#define NUM_TLC5974 1
#define data   11
#define clock   13
#define latch   10
#define oe  -1  // set to -1 to not use the enable pin (its optional)
Adafruit_TLC5947 tlc = Adafruit_TLC5947(NUM_TLC5974, clock, data, latch);
// END LED

int noteIsOn0;
int noteIsOn1;
int noteIsOn2;
int noteIsOn3;
int noteIsOn4;
int noteIsOn5;
int noteIsOn6;
int noteIsOn7;
int thresh;



void setup() {

// LED Setup
  Serial.begin(9600);
  
  Serial.println("TLC5974 test");
  tlc.begin();
  if (oe >= 0) {
    pinMode(oe, OUTPUT);
    digitalWrite(oe, LOW);
  }
// END LED  

// Harp Setup
thresh = 480;
// End Harp

 usbMIDI.setHandleControlChange(onControlChange);
}

void onControlChange(uint8_t channel, uint8_t control, uint8_t value){
  if(control == 40){
    if(value == 127){
        tlc.setLED(0, 0, 0, 0);
    delay (500);
        tlc.setLED(1, 0, 0, 0);
    delay (500);
        tlc.setLED(2, 0, 0, 0);
    delay (500);
        tlc.setLED(3, 0, 0, 0);
    delay (500);
        tlc.setLED(4, 0, 0, 0);
    delay (500);
        tlc.setLED(5, 0, 0, 0);
    delay (500);
        tlc.setLED(6, 0, 0, 0);
    delay (500);
        tlc.setLED(7, 0, 0, 0);
    delay (500);
    }
  }
 if(control == 41){
    if(value == 127){
        tlc.setLED (0, 4095, 4095, 1);
    delay (500);
        tlc.setLED (1, 4095, 4095, 1);
    delay (500);
        tlc.setLED (2, 4095, 4095, 1);
    delay (500);
        tlc.setLED (3, 4095, 4095, 1);
    delay (500);
        tlc.setLED (4, 4095, 4095, 1);
    delay (500);
        tlc.setLED (5, 4095, 4095, 1);
    delay (500);
        tlc.setLED (6, 4095, 4095, 1);
    delay (500);
        tlc.setLED (7, 4095, 4095, 1);
    delay (500);
    }
  }
}

void loop() {

// Sensor Start 0 
  
  if (noteIsOn0 == false) {
    if (analogRead(0) > (thresh)) {
      usbMIDI.sendNoteOn(60, (random(115,127)), 1);
      tlc.setLED(0, 0, 4095, 0); 
      noteIsOn0 = true;
    }
  } else {
    if (analogRead(0) < thresh) {
      usbMIDI.sendNoteOff (60, 0, 1);
      noteIsOn0 = false;
      tlc.setLED (0, 4095, 4095, 1);     
    }
  }

// Sensor Start 1
  if (noteIsOn1 == false) {  
    if (analogRead(1) > thresh+30) {
      usbMIDI.sendNoteOn(62, (random(115,127)), 1);
      tlc.setLED(1, 0, 4095, 0); 
      noteIsOn1 = true;
    }
  } else {
    if (analogRead(1) < thresh) {
      usbMIDI.sendNoteOff (62, 0, 1);
      noteIsOn1 = false;
      tlc.setLED (1, 4095, 4095, 1); 
      }
  }

// Sensor Start 2
  if (noteIsOn2 == false) {  
    if (analogRead(2) > thresh) {
      usbMIDI.sendNoteOn(64, (random(115,127)), 1);
      tlc.setLED(2, 0, 4095, 0); 
      noteIsOn2 = true;
    }
  } else {
    if (analogRead(2) < thresh) {
      usbMIDI.sendNoteOff (64, 0, 1);
      noteIsOn2 = false;
      tlc.setLED (2, 4095, 4095, 1);      
    }
  }

  
// Sensor Start 3
  if (noteIsOn3 == false) {
    if (analogRead(3) > thresh) {
      usbMIDI.sendNoteOn(65, (random(115,127)), 1);
      tlc.setLED(3, 0, 4095, 0); 
      noteIsOn3 = true;
    }
  } else {
    if (analogRead(3) < thresh) {
      usbMIDI.sendNoteOff (65, 0, 1);
      noteIsOn3 = false;
      tlc.setLED (3, 4095, 4095, 1);     
    }
  }


// Sensor Start 4
  if (noteIsOn4 == false) {
    if (analogRead(4) > thresh + 25) {
      usbMIDI.sendNoteOn(67, (random(115,127)), 1);
      tlc.setLED(4, 0, 4095, 0); 
      noteIsOn4 = true;
    }
  } else {
    if (analogRead(4) < thresh) {
      usbMIDI.sendNoteOff (67, 0, 1);
      noteIsOn4 = false;
       tlc.setLED (4, 4095, 4095, 1);     
    }
  }

// Sensor Start 5
  if (noteIsOn5 == false) {
    if (analogRead(5) > thresh) {
      usbMIDI.sendNoteOn(69, (random(115,127)), 1);
      tlc.setLED(5, 0, 4095, 0); 
      noteIsOn5 = true;
    }
  } else {
    if (analogRead(5) < thresh) {
      usbMIDI.sendNoteOff (69, 0, 1);
      noteIsOn5 = false;
      tlc.setLED (5, 4095, 4095, 1);      
    }
  }

// Sensor Start 6
  if (noteIsOn6 == false) {
    if (analogRead(6) > thresh) {
      usbMIDI.sendNoteOn(71, (random(115,127)), 1);
      tlc.setLED(6, 0, 4095, 0); 
      noteIsOn6 = true;
    }
  } else {
    if (analogRead(6) < thresh) {
      usbMIDI.sendNoteOff (71, 0, 1);
      noteIsOn6 = false;
      tlc.setLED (6, 4095, 4095, 1);      
    }
  }

// Sensor Start 7
  if (noteIsOn7 == false) {
    if (analogRead(7) > thresh) {
      usbMIDI.sendNoteOn(72, (random(115,127)), 1);
      tlc.setLED(7, 0, 4095, 0); 
      noteIsOn7 = true;
    }
  } else {
    if (analogRead(7) < thresh) {
      usbMIDI.sendNoteOff (72, 0, 1);
      noteIsOn7 = false;
      tlc.setLED (7, 4095, 4095, 1);     
    }
  }


// END Sensors 

  while (usbMIDI.read()) {}

  tlc.write();
  delay(5);
   
}
 
How about just letting onControlChange() set a boolean that uses or doesn't use the lights?

Code:
// LED
#include "Adafruit_TLC5947.h"
#define NUM_TLC5974 1
#define data   11
#define clock   13
#define latch   10
#define oe  -1  // set to -1 to not use the enable pin (its optional)
Adafruit_TLC5947 tlc = Adafruit_TLC5947(NUM_TLC5974, clock, data, latch);
// END LED

bool usingLights = true;
int noteIsOn0;
int noteIsOn1;
int noteIsOn2;
int noteIsOn3;
int noteIsOn4;
int noteIsOn5;
int noteIsOn6;
int noteIsOn7;
int thresh;



void setup() {

// LED Setup
  Serial.begin(9600);
  
  Serial.println("TLC5974 test");
  tlc.begin();
  if (oe >= 0) {
    pinMode(oe, OUTPUT);
    digitalWrite(oe, LOW);
  }
// END LED  

// Harp Setup
thresh = 480;
// End Harp

 usbMIDI.setHandleControlChange(onControlChange);
}

void onControlChange(uint8_t channel, uint8_t control, uint8_t value){
  if(control == 40 && value == 127){
    usingLights = true;
  }
  else if(control == 41 && value == 127){
    usingLights = false;
    tlc.setLED(0, 0, 0, 0);
    delay (500);
    tlc.setLED(1, 0, 0, 0);
    delay (500);
    tlc.setLED(2, 0, 0, 0);
    delay (500);
    tlc.setLED(3, 0, 0, 0);
    delay (500);
    tlc.setLED(4, 0, 0, 0);
    delay (500);
    tlc.setLED(5, 0, 0, 0);
    delay (500);
    tlc.setLED(6, 0, 0, 0);
    delay (500);
    tlc.setLED(7, 0, 0, 0);
    delay (500);
  }
}

void loop() {

// Sensor Start 0 
  
  if (noteIsOn0 == false) {
    if (analogRead(0) > (thresh)) {
      usbMIDI.sendNoteOn(60, (random(115,127)), 1);
      if (usingLights) tlc.setLED(0, 0, 4095, 0); 
      noteIsOn0 = true;
    }
  } else {
    if (analogRead(0) < thresh) {
      usbMIDI.sendNoteOff (60, 0, 1);
      noteIsOn0 = false;
      if (usingLights) tlc.setLED (0, 4095, 4095, 1);     
    }
  }

// Sensor Start 1
  if (noteIsOn1 == false) {  
    if (analogRead(1) > thresh+30) {
      usbMIDI.sendNoteOn(62, (random(115,127)), 1);
      if (usingLights) tlc.setLED(1, 0, 4095, 0); 
      noteIsOn1 = true;
    }
  } else {
    if (analogRead(1) < thresh) {
      usbMIDI.sendNoteOff (62, 0, 1);
      noteIsOn1 = false;
      if (usingLights) tlc.setLED (1, 4095, 4095, 1); 
      }
  }

// Sensor Start 2
  if (noteIsOn2 == false) {  
    if (analogRead(2) > thresh) {
      usbMIDI.sendNoteOn(64, (random(115,127)), 1);
      if (usingLights) tlc.setLED(2, 0, 4095, 0); 
      noteIsOn2 = true;
    }
  } else {
    if (analogRead(2) < thresh) {
      usbMIDI.sendNoteOff (64, 0, 1);
      noteIsOn2 = false;
      if (usingLights) tlc.setLED (2, 4095, 4095, 1);      
    }
  }

  
// Sensor Start 3
  if (noteIsOn3 == false) {
    if (analogRead(3) > thresh) {
      usbMIDI.sendNoteOn(65, (random(115,127)), 1);
      if (usingLights) tlc.setLED(3, 0, 4095, 0); 
      noteIsOn3 = true;
    }
  } else {
    if (analogRead(3) < thresh) {
      usbMIDI.sendNoteOff (65, 0, 1);
      noteIsOn3 = false;
      if (usingLights) tlc.setLED (3, 4095, 4095, 1);     
    }
  }


// Sensor Start 4
  if (noteIsOn4 == false) {
    if (analogRead(4) > thresh + 25) {
      usbMIDI.sendNoteOn(67, (random(115,127)), 1);
      if (usingLights) tlc.setLED(4, 0, 4095, 0); 
      noteIsOn4 = true;
    }
  } else {
    if (analogRead(4) < thresh) {
      usbMIDI.sendNoteOff (67, 0, 1);
      noteIsOn4 = false;
       if (usingLights) tlc.setLED (4, 4095, 4095, 1);     
    }
  }

// Sensor Start 5
  if (noteIsOn5 == false) {
    if (analogRead(5) > thresh) {
      usbMIDI.sendNoteOn(69, (random(115,127)), 1);
      if (usingLights) tlc.setLED(5, 0, 4095, 0); 
      noteIsOn5 = true;
    }
  } else {
    if (analogRead(5) < thresh) {
      usbMIDI.sendNoteOff (69, 0, 1);
      noteIsOn5 = false;
      if (usingLights) tlc.setLED (5, 4095, 4095, 1);      
    }
  }

// Sensor Start 6
  if (noteIsOn6 == false) {
    if (analogRead(6) > thresh) {
      usbMIDI.sendNoteOn(71, (random(115,127)), 1);
      if (usingLights) tlc.setLED(6, 0, 4095, 0); 
      noteIsOn6 = true;
    }
  } else {
    if (analogRead(6) < thresh) {
      usbMIDI.sendNoteOff (71, 0, 1);
      noteIsOn6 = false;
      if (usingLights) tlc.setLED (6, 4095, 4095, 1);      
    }
  }

// Sensor Start 7
  if (noteIsOn7 == false) {
    if (analogRead(7) > thresh) {
      usbMIDI.sendNoteOn(72, (random(115,127)), 1);
      if (usingLights) tlc.setLED(7, 0, 4095, 0); 
      noteIsOn7 = true;
    }
  } else {
    if (analogRead(7) < thresh) {
      usbMIDI.sendNoteOff (72, 0, 1);
      noteIsOn7 = false;
      if (usingLights) tlc.setLED (7, 4095, 4095, 1);     
    }
  }


// END Sensors 

  while (usbMIDI.read()) {}

  tlc.write();
  delay(5);
   
}

I'll let you worry about making this look good ;)
By the way, I think the maximum value for those last three parameters of setLED() should be 255, not 4095.
Also, do you really need those 500 millisecond delays in there? Just wondering.
 
I'll give this a try! The delays aren't necessary, just for effect. I'm not sure if I'll keep them. I'll double-check the parameter values. I thought the maximum 4095 had something to do with the LED driver board. Thanks!!
 
Status
Not open for further replies.
Back
Top