simple midi contoller

Status
Not open for further replies.
...had trouble with my rotary style pots( Not sure what size they where. do they have to be a certain ohm?) ...
If your potentiometer's resistance is too large it won't work reliably, too small and you can burn something out (hopefully just the pot!) but anything in the 1-50 KOhm range seems to work fine.

Any potentiometer will work as long as the pin can sense the voltage coming from the voltage divider (which is what a potentiometer is when wired between a voltage and ground - the wiper gives a voltage proportional to its position regardless of the overall resistance). For it to work accurately and reliably the current moving into the Teensy instead of flowing to the ground should be insignificant to avoid having the process of measuring the voltage causing the voltage to drop. I would guess that anything above 100K would be dodgy.

The pictured trimmers were 50K and they work fine on the on the T3.0... I'm pretty sure I've used 100K too which is 10-times the Arduino board recommendation of 10K or smaller but I suspect Paul's boards are better than that.

If your pots have a three-digit number on them you can find their values -- 102 = 1KOhm, 502 = 5KOhm, 103 = 10KOhm, 503 = 50KOhm are standard pot values that seem to work. The smallest implies a current of 3.3 mA which doesn't sound like much but some people talk about 64 pots powered off the 3.3 volt supply on the Teensy which is >200mA on its own.

If your pots are small enough and there is still a problem you may have crappy pots (they may just be old and there is oxidization where the wiper contacts the resistive surface) or some other source of noise like poor solder joints or loose breadboard connections.

But the great thing about the ResponsiveAnalgoRead algorithm is that you can adjust parameters and change its responsiveness... more forgiving of noise vs. quicker response is the major trade-off but it's more complex than just that.... (see 'other methods' on the gitHUB page: https://github.com/dxinteractive/ResponsiveAnalogRead )

Given these problems are far-and-away the biggest hurdle for those making analog MIDI controllers I think Paul is hoping an example sketch with some of these advanced features exposed will help noobs resolve with these difficulties when they arise.

But this 'simple' version is a nice first step as it seems to tame run-of-then-mill pot-noise quite nicely with stock settings.... but especially when then dropping to 7-bit afterwards.

I do want to check to see if bit reduction is something the algorithm already handles as it may simplify the sketch further.

Adding thee simple buttons with hard-coded behaviour would be trivial but I'd like to do it correctly so that changing the number of buttons is handled simply (if not elegantly).

In the final version I'd also like to make various behaviours possible such as a latched mode (toggle) as well as making both CC and note-on/off messages user configurable.
 
Last edited:
I have been thinking about it all day at work, and i think i may have hooked the wires up wrong. i'm going to try later tonight and see if that is what i did.
I really appreciate the help, and love teensy boards. so far they have been working out great for making a midi controller. I will post photos of the finished controller when it is finished. But if you want to send people my way that are new to teensy, and want to make a simple midi controller. I can give them My thoughts on the process, and explain how my stumbling though it went. I'm here to help.
Also, please let me know how to add those buttons with hard coded information. I am totally ok with that, as long as each button is hard coded to a different number. my Audio Program Abelton live has a midi learn function. so i just put it in learn mode, and turn a pot, it senses it moving and it's ready to go. please let me know how to do this. thanks again
 
Oh and one other thing I was thinking of. is there a way to make a Led connected to each pot that gets brighter as the pot turn up? just curious
 
I should be able to paste Paul's example code in tonight for a functional sketch that meets your requirements.

You wanted note on when pressed and off when released -correct?
(Rather than CC messages and with no latching.)

Re hooking up pots... wiper is almost always in the middle of the contacts. If you get the other two wrong it will work backwards...

If you are using a T3.x make sure you power your pots with 3.3 volt supply pin.

If you power the pots with 5 volt supply it will either max out the readings too early (if your lucky and your Teensy model has 5 volt tolerant input) or it may fry your Teensy.

Apparently you should ground the pots to the AGND instead of GND as it's isolated somewhat from the noisy digital circuitry on the board.

I didn't in the test rig, however, and it was working fine... (I'd like to say I wanted a noisy signal to test the smoothing but really it's because I forgot.)

You may find some references to using AREF as the supply voltage for reading analog signals... Paul says 'no' to this for reading pots.
 
Maybe the example code in File > Examples > Teensy > USB_MIDI > Buttons can help you with the 3 buttons generating note on/off codes?
 
Oh and one other thing I was thinking of. is there a way to make a Led connected to each pot that gets brighter as the pot turn up? just curious
Yes but it either takes another pin each (where you analog-write a value and the duty cycle of the pulse-width-modulation signal makes the LED seem more and less bright) our you'd need to buffer the voltage level from the pot and use that to control brightness (I assume this is possible but I don't know how).

Unless you have run out of pins the former would be better... should be as simple as scaling the current MIDI value an sending it with analogWrite() and the hardware is basically an LED in series with a resister to ground with the PIN on the anode (hot) side.

https://www.pjrc.com/teensy/tutorial2.html

(edit - or is there a way to build a pot controlled LED and read the voltage from that to control MIDI without any op amps?):confused:
 
Last edited:
tried to get the buttons going from your suggestion. but it didn't make much sense to me. i tried to set something up but got tons of errors. i'm still pretty fresh at this coding stuff. I am just vagly understanding the layout, but the syntax is still comfusing to me.
 
i tried to set something up but got tons of errors.

Ok, we can try to help you, but the way things work here is you post the code. The complete code, so anyone can copy the whole thing into Arduino and get the same error. It's ok to be new. It's ok to make mistakes. But the expectation is you show us what you're trying.
 
Code:
// include the ResponsiveAnalogRead library
#include <ResponsiveAnalogRead.h>
#include <Bounce.h>  // Bounce library makes button change detection easy
const int channel = 1;

Bounce button1 = Bounce(1, 5);  // 5 = 5 ms debounce time
Bounce button2 = Bounce(2, 5);  // which is appropriate for good
Bounce button3 = Bounce(3, 5);  // quality mechanical pushbuttons
const int A_PINS = 6; // number of Analog PINS
// define the pins you want to use and the CC ID numbers on which to send them..
const int ANALOG_PINS[A_PINS] = {A0,A1,A2,A3,A4,A5};
const int CCID[A_PINS] = {21,22,23,24,25,26};

// a data array and a lagged copy to tell when MIDI changes are required
byte data[A_PINS];
byte dataLag[A_PINS];
// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead analog[]{
  {ANALOG_PINS[0],true},
  {ANALOG_PINS[1],true},
  {ANALOG_PINS[2],true},
  {ANALOG_PINS[3],true},
  {ANALOG_PINS[4],true},
  {ANALOG_PINS[5],true},
  {ANALOG_PINS[6],true}//,
  //{ANALOG_PINS[7],true},
  //{ANALOG_PINS[8],true},
}; // not sure if there is a better way... some way run a setup loop on global array??
void setup() {
  // begin serial so we can see analog read values through the serial monitor
  //Serial.begin(9600); 
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
}

void loop() {
  // update the ResponsiveAnalogRead object every loop
  for (int i=0;i<A_PINS;i++){
    analog[i].update(); 
    // if the repsonsive value has change, print out 'changed'
    if(analog[i].hasChanged()) {
      data[i] = analog[i].getValue()>>3;
      if (data[i] != dataLag[i]){
        dataLag[i] = data[i];
        usbMIDI.sendControlChange(CCID[i], data[i], channel);
      }
    }
  }
    button1.update();
  button2.update();
  button3.update();
  // Note On messages when each button is pressed
  if (button1.fallingEdge()) {
    usbMIDI.sendNoteOn(60, 99, channel);  // 60 = C4
  }
  if (button2.fallingEdge()) {
    usbMIDI.sendNoteOn(61, 99, channel);  // 61 = C#4
  }
  if (button3.fallingEdge()) {
    usbMIDI.sendNoteOn(62, 99, channel);  // 62 = D4
  }
  // Note Off messages when each button is released
  if (button1.risingEdge()) {
    usbMIDI.sendNoteOff(60, 0, channel);  // 60 = C4
  }
  if (button2.risingEdge()) {
    usbMIDI.sendNoteOff(61, 0, channel);  // 61 = C#4
  }
  if (button3.risingEdge()) {
    usbMIDI.sendNoteOff(62, 0, channel);  // 62 = D4
  }


  // MIDI Controllers should discard incoming MIDI messages.
  while (usbMIDI.read()) {
  }
}
This is Paul's example code merged into mine in the three places it needs to go to work...

The initialization lines -- top of the file
The setup lines -- inside void setup()
The loop lines -- inside void loop()

You cannot have two setup calls or two loop calls ... I suspect that might be the source of some of your errors.

no other real changes from above (except to make the channel constant the same in the analog section...

It's not elegant but I believe it works (but I cannot test properly because my breadboard test rig fell apart so I commented out the 'analog.update' to test just the digital part with a wire from the pin to ground on each of three pins).

Note Paul's pin use skips 0 so it's pins 1,2,3 not 0,1,2 but you can change that if you fix each of the two places it's hard coded.

@Paul.... there is an extra brace-end in your example code right before the 'ignore read' section... the code will not compile as is.

If this still isn't working for you don't worry... it's very close but my lack of a test rig and the lateness of the hour means this was all I could do tonight.
 
Last edited:
ok great,oh i did not know i was supposed to post my code. sure I will get it posted next time I am at my computer. you guys are great, I feel like I'm learning a lot, but still feel kinda lost. I can look at code and sort of break it down, and modify the numbers of pots and switches being used but a lot of the code doesn't make sense. so a few quick questions.
is there a checklist of what i need to have in a code like this to make it function. like for example( for a car
to drive, it needs a motor in front, a transmission in the middle, a driveshaft after that, and wheels. in that order. if not you can have all the parts sitting there but it will do nothing)
does it have to be in a specific order?
does the computer read it from top to bottom left to right.
is there some sort of roadmap that shows1. the bare minimum need to make the code even work? where do variables go. where do if-then statements go? etc.
Trying to wrap my brain around it. it's slowly sinking in lol
 
I can look at code and sort of break it down, and modify the numbers of pots and switches being used but a lot of the code doesn't make sense...
Some things will be over your head for a while... but my code will be better commented when it's complete so you'll have a better chance of understanding more of it.
...is there a checklist of what i need to have in a code like this to make it function.
No check list... there are references:
https://www.arduino.cc/en/tutorial/sketch
https://www.arduino.cc/en/Tutorial/Blink
https://www.pjrc.com/teensy/td_usage.html

I recall in my early days playing getting the on-board LED to blink different patterns by adjusting the code from the Digital IO page. You really need to keep it simple to start learning.

The basic parts of a sketch are:

  • outside all functions Global variables are declared outside any function and then are accessible in all function calls. It's also where pre-compiler instructions are typically placed. The one you need to know to start is #include which is needed to use libraries (like ResponsiveAnalogRead). The file to be inserted into the code by the pre-compiler is in the form: <fileNameHear.h> like an HTML tag. These files may themselves include other #include statements so your compiled code can be very much larger than the handful of lines you typically have to use to access a library.
  • Setup: void setup(){...} Code run once at startup - used to calculate starting values or otherwise run code needed to make things work that isn't static (needs to be executed by the Teensy board). Even if you are not using this section you seem to need it to get the code to compile.
  • Loop: void loop(){...} - Arduino's main loop. This is the heart of any sketch as it will execute indefinitely. There must be a function with this name too. No other functions will run unless called by one of these (directly or indirectly).
  • custom functions: byte myFunction(){...} Anything you write that you want to call under specific circumstances - from inside some particular 'if' condition in your main loop for example. The keyword before the function determines whether and what type of value is returned to the calling function. The keyword 'void' means there is no value. Byte returns an eight-bit packet of data to the calling function (maybe the MIDI data byte you are sending through usbMIDI.)


The code itself uses the C language syntax etc. which is not very forgiving. If you've coded VBA for Excel or other high-level scripting languages you may be used to not worrying about text-case matching on variable names. You need to become proficient at figuring out what compile errors are telling you... if you're really stuck you can post your full code and explain what you're trying to do.

If your program compiles it's free of syntax errors but it doesn't mean it actually does anything. That's when inserting serial.print() statements can help debugging the actual logic of your sketch.

The code is also based on the object-oriented extensions to the C language known as C++.
Where you see code with object.method() syntax that's object oriented speak for a code function (called a method) associated with an object.

Any of the details above might not be 100% true as I am no programmer... You sometimes need to understand this stuff to follow library documentation but I struggle with all but the simplest stuff (even though I've programmed in many high-level languages for decades - microcontroller code in a C-based language is very different).

Maybe someone can point to a more concise learning plan... but hopefully this helps clear up some of the fog around how this stuff works.

Trying to wrap my brain around it. it's slowly sinking in lol
Yeah... that's how it goes but if you really want to learn the coding (rather than just adjust other peoples code to run on your hardware) then you need to step back a bit and work through very simple sketches first...

You may want a second Teensy if you do... personally I'd get an LC for your current MIDI project as the T3.5 is overkill for a MIDI controller... but it's a pretty good platform for audio projects with Paul's awesome audio library and audio design tool. It's also good for other more demanding libraries like those for some graphical displays and LED matrixes.

I have nine Teensys now... including five T3.0s I picked up from PJRC's closeout on the model... they are similar to the LC with a bit more power but either is more than ample for MIDI projects (which is what I got them for).
 
i don't know where to start adding the code, or even what code to add. so this is all i have so far. everything works accept for obviously the switches. please help


// include the ResponsiveAnalogRead library
#include <ResponsiveAnalogRead.h>

const int A_PINS = 6; // number of Analog PINS
// define the pins you want to use and the CC ID numbers on which to send them..
const int ANALOG_PINS[A_PINS] = {A0,A1,A2,A3,A4,A5};
const int CCID[A_PINS] = {21,22,23,24,25,26};

// a data array and a lagged copy to tell when MIDI changes are required
byte data[A_PINS];
byte dataLag[A_PINS];
// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead analog[]{
{ANALOG_PINS[0],true},
{ANALOG_PINS[1],true},
{ANALOG_PINS[2],true},
{ANALOG_PINS[3],true},
{ANALOG_PINS[4],true},
{ANALOG_PINS[5],true},
{ANALOG_PINS[6],true}//,
//{ANALOG_PINS[7],true},
//{ANALOG_PINS[8],true},
}; // not sure if there is a better way... some way run a setup loop on global array??
void setup() {
// begin serial so we can see analog read values through the serial monitor
//Serial.begin(9600);
}

void loop() {
// update the ResponsiveAnalogRead object every loop
for (int i=0;i<A_PINS;i++){
analog.update();
// if the repsonsive value has change, print out 'changed'
if(analog.hasChanged()) {
data = analog.getValue()>>3;
if (data != dataLag){
dataLag = data;
usbMIDI.sendControlChange(CCID, data, 1);
}
}
}
}
 
Have you tried my code in post #35 yet?

... or here's the update with arrays for both analog and digital
Code:
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
// include the Bounce library for debouncing switches for clean messages
#include <Bounce.h> 
// ******CONSTANT VALUES******** - customize code behaviour here!
const int channel = 1; // MIDI channel
const int A_PINS = 6; // number of Analog PINS
const int D_PINS = 3; // number of Digital PINS
const int ON_VELOCITY = 99; // note-one velocity from buttons <=127
// define the pins you want to use and the CC ID numbers on which to send them..
const int ANALOG_PINS[A_PINS] = {A0,A1,A2,A3,A4,A5};
const int CCID[A_PINS] = {21,22,23,24,25,26};
// define the pins and notes for digital events
const int DIGITAL_PINS[D_PINS] = {0,1,2};
const int note[D_PINS] = {60,61,62};
const int BOUNCE_TIME = 7; // 5 ms is usually sufficient
const boolean toggled = true;
//******VARIABLES***********
// a data array and a lagged copy to tell when MIDI changes are required
byte data[A_PINS];
byte dataLag[A_PINS]; // when lag and new are not the same then update MIDI CC value

// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead analog[]{
  {ANALOG_PINS[0],true},
  {ANALOG_PINS[1],true},
  {ANALOG_PINS[2],true},
  {ANALOG_PINS[3],true},
  {ANALOG_PINS[4],true},
  {ANALOG_PINS[5],true},
  {ANALOG_PINS[6],true}/*,
  {ANALOG_PINS[7],true},
  {ANALOG_PINS[8],true},*/
}; // not sure if there is a better way... some way run a setup loop on global array??
// initialize the bounce objects
Bounce digital[] =   {
  Bounce(DIGITAL_PINS[0],BOUNCE_TIME),
  Bounce(DIGITAL_PINS[1], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[2], BOUNCE_TIME)/*,
  Bounce(DIGITAL_PINS[3], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[4], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[5], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[6], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[7], BOUNCE_TIME),*/
}; 


void setup() {
  // begin serial so we can see analog read values through the serial monitor
  for (int i=0;i<D_PINS;i++){
    pinMode(DIGITAL_PINS[i], INPUT_PULLUP);
  }
}

void loop() {
  getAnalogData();
  getDigitalData();
  while (usbMIDI.read()) {
  }
}


//************ANALOG SECTION**************
void getAnalogData(){  
  for (int i=0;i<A_PINS;i++){
    // update the ResponsiveAnalogRead object every loop
    analog[i].update(); 
    // if the repsonsive value has change, print out 'changed'
    if(analog[i].hasChanged()) {
      data[i] = analog[i].getValue()>>3;
      if (data[i] != dataLag[i]){
        dataLag[i] = data[i];
        usbMIDI.sendControlChange(CCID[i], data[i], channel);
      }
    }
  }
}



//************DIGITAL SECTION**************
void getDigitalData(){
  for (int i=0;i<D_PINS;i++){
  digital[i].update();
    if (digital[i].fallingEdge()) {
      usbMIDI.sendNoteOn(note[i], ON_VELOCITY, channel);  
    }
    // Note Off messages when each button is released
    if (digital[i].risingEdge()) {
      usbMIDI.sendNoteOff(note[i], 0, channel);  
    }
  }
}
 
Last edited:
sorry, for some reason my browser did not refresh, I missed a few of the replies. now i'm up to date. I will try that code out tonight. thanks
 
ResponsiveAnalogRead analog[]{

If you're new to all this, simply making 8 copies of the code with different names is much simpler. Sure, it's large and looks messy, but it gets the job done. I highly recommend going with the simplest way first. Get things working first, even if not the efficient way. Optimize later, after it's already working.
 
If you're new to all this, simply making 8 copies of the code with different names is much simpler. Sure, it's large and looks messy, but it gets the job done. I highly recommend going with the simplest way first. Get things working first, even if not the efficient way. Optimize later, after it's already working.

Better yet... build a single pot version on a breadboard first... my code should work for you to replicate the results of the hardware-build tutorial that brought you here but to learn to program Teensy for yourself you need to start simple... which was what I was saying above:
if you really want to learn the coding (rather than just adjust other peoples code to run on your hardware) then you need to step back a bit and work through very simple sketches first...

...but this thread did start with
...is there a code sketch floating around here i can copy and paste, and just modify the input numbers?

Well there is now. :)
 
you guys are awesome. i really appreciate all your help. i feel like i have just dipped my toe in to the world of using code with hardware. and it's fun. this is just the start....
 
I notice just about all modern synth schematics show a 0.1uF cap across every 10k pot used as a controller.
Seems to help quiet down jitters.
Cheap ceramic caps is used. Placed across the pot's Gnd and wiper.

I'm sure some software method is also used too.
But I thought it might be worth mentioning the caps.
Both Roland and Korg do this in their designs.
 
I notice just about all modern synth schematics show a 0.1uF cap across every 10k pot used as a controller...
Really? I've always assumed that it got included in DIY design because isolation caps are so ubiquitous in DIY guitar effects.

I looks to me like the cap and the upper leg (wiper to hot) of the potentiometer form a low-pass filter whose corner frequency will move with the pot... but I'm not and EE and I don't know whether/how the lower leg of the pot might counteract what looks to me would be a variable low-pass filter.

If it does, the corner frequency that might get very very small (when your at the top of the pot) allowing even low frequency noise into the signal you're following... [edit - this sentence is just all wrong!]


On the other hand the ResponsiveAnalogRead uses some form of hysteresis/filtering and a sleep function that allows a wider dead-band when the output is sleeping before it's awaked by a major change... which is more-or-less perfect behaviour for MIDI CC controller. And if you're only doing 7-bit MIDI then this should be super solid.

And if it's not there you can go under the hood a bit and change parameters. I'm excited to try the advanced features on an old M-Audio expression pedal with a very scratchy section at about 30% that sends HIGH spikes to the ADC. If this algo can make that thing usable again then I'll be mighty impressed...

About my code above... it should still have a time-limter on the MIDI as if a live data pin is allowed to drift or if noise that breaks the sleep mode of ResponsiveAnalogRead the code can pump loads of data into the usb link... my MIDI monitor showed streams of data when I left an alalog pin float... so it may misbehave if your electrical connections are compromised.
 
Last edited:
I believe the cap across Gnd and wiper makes a "decoupling network" and it's purpose is to eliminate AC signals on the DC line.
Basically quiet down ripple, jitter which would appear as AC
 
Yeah... wouldn't that make more sense on the other size of the pot if it's for noisy power?

I've got my logic backwards in the statement above anyway... if it is acting as variable low-pass it would be most effective at higher settings where the corner is lower...

And at low setting the lower leg becomes an effective path to ground and so it looks less like a low pass???

I'm not an EE so I don't know and it's kinda off-topic... I was just surprised to hear the technic is used in commercial examples...

but ResponsiveAnalogRead makes even a noisy signal usable -- especially for low-rez MIDI messages. I should have just said that! :eek:
 
Have you tried my code in post #35 yet?

... or here's the update with arrays for both analog and digital
Code:
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
// include the Bounce library for debouncing switches for clean messages
#include <Bounce.h> 
// ******CONSTANT VALUES******** - customize code behaviour here!
const int channel = 1; // MIDI channel
const int A_PINS = 6; // number of Analog PINS
const int D_PINS = 3; // number of Digital PINS
const int ON_VELOCITY = 99; // note-one velocity from buttons <=127
// define the pins you want to use and the CC ID numbers on which to send them..
const int ANALOG_PINS[A_PINS] = {A0,A1,A2,A3,A4,A5};
const int CCID[A_PINS] = {21,22,23,24,25,26};
// define the pins and notes for digital events
const int DIGITAL_PINS[D_PINS] = {0,1,2};
const int note[D_PINS] = {60,61,62};
const int BOUNCE_TIME = 7; // 5 ms is usually sufficient
const boolean toggled = true;
//******VARIABLES***********
// a data array and a lagged copy to tell when MIDI changes are required
byte data[A_PINS];
byte dataLag[A_PINS]; // when lag and new are not the same then update MIDI CC value

// ititialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead analog[]{
  {ANALOG_PINS[0],true},
  {ANALOG_PINS[1],true},
  {ANALOG_PINS[2],true},
  {ANALOG_PINS[3],true},
  {ANALOG_PINS[4],true},
  {ANALOG_PINS[5],true},
  {ANALOG_PINS[6],true}/*,
  {ANALOG_PINS[7],true},
  {ANALOG_PINS[8],true},*/
}; // not sure if there is a better way... some way run a setup loop on global array??
// initialize the bounce objects
Bounce digital[] =   {
  Bounce(DIGITAL_PINS[0],BOUNCE_TIME),
  Bounce(DIGITAL_PINS[1], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[2], BOUNCE_TIME)/*,
  Bounce(DIGITAL_PINS[3], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[4], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[5], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[6], BOUNCE_TIME),
  Bounce(DIGITAL_PINS[7], BOUNCE_TIME),*/
}; 


void setup() {
  // begin serial so we can see analog read values through the serial monitor
  for (int i=0;i<D_PINS;i++){
    pinMode(DIGITAL_PINS[i], INPUT_PULLUP);
  }
}

void loop() {
  getAnalogData();
  getDigitalData();
  while (usbMIDI.read()) {
  }
}


//************ANALOG SECTION**************
void getAnalogData(){  
  for (int i=0;i<A_PINS;i++){
    // update the ResponsiveAnalogRead object every loop
    analog[i].update(); 
    // if the repsonsive value has change, print out 'changed'
    if(analog[i].hasChanged()) {
      data[i] = analog[i].getValue()>>3;
      if (data[i] != dataLag[i]){
        dataLag[i] = data[i];
        usbMIDI.sendControlChange(CCID[i], data[i], channel);
      }
    }
  }
}



//************DIGITAL SECTION**************
void getDigitalData(){
  for (int i=0;i<D_PINS;i++){
  digital[i].update();
    if (digital[i].fallingEdge()) {
      usbMIDI.sendNoteOn(note[i], ON_VELOCITY, channel);  
    }
    // Note Off messages when each button is released
    if (digital[i].risingEdge()) {
      usbMIDI.sendNoteOff(note[i], 0, channel);  
    }
  }
}


Is there a way to keep this from spitting out a massive stream of midi data? I notice some code for midi controllers has a way to keep the midi data from being sent if its not a new value
 
It should only send cc if the value implied by the smoothed analog is different... but on faster T3.x boards it can still pump a lot of MIDI (if the knob is fast swept or if a pin is allowed to float)... should add a minimum time lapse between a send and the next... regardless of whether it will skip intermediary values.

Add an elapsed milliseconds condition to the following line:
if (data != dataLag)

Edit - I hope to try this in the next day or so and will post the results here. It should only take a few lines of code to configure an array of elapsed counters and a threshold value and then a new test line:

if (data != dataLag && CCsentElapsed > midiDelay )
 
Last edited:
Ya because I can't use the previously linked code on my PC because it crashes my midi driver+overloads the midi inputs on my DAW Causing it to lock up. The sketch looks pretty nice despite this problem.

I was hoping to use someone elses sketch with very little customization of my own since I'm very bad at writing code and was hoping to lift someone's sketch for a cheap midi controller with my own high quality faders and encoders. Hell I'd even be willing to give a few bucks to someone who's willing to throw together a super smooth functioning midi controller sketch.

I'll keep an eye on this thread.
 
Status
Not open for further replies.
Back
Top