The BIG Arduino MIDI controller thread - Page 12
Page 12 of 16 FirstFirst ... 28910111213141516 LastLast
Results 111 to 120 of 155
  1. #111
    Tech Mentor
    Join Date
    Sep 2013
    Posts
    159

    Default

    I've had to deal with this myself recently on a leonardo, the issue here is that the analogue inputs will have noise, so what you have to do is introduce a method for filtering out that noise and only outputting real movement. First things first, make sure that all other unused analog pins are tied to ground, that will get rid of some noise.

    As for the code, I would start by setting up an array containing the pin numbers that you want to read and a couple of variables to store the last reading you took and the current one. so it will look something like this:

    #include <MIDI.h>
    // define the number of pots you want to use here, then all you have to do is change this if you want to add more
    #define NUM_POTS 3 // make sure you change the analogueInputMapping array below
    #define MIDI_CC 1 // use this so that we can set a base CC value and change it later
    byte analogueInputMapping[NUM_POTS] = {A0,A1,A2}; // put the pins you want to use here
    int16_t lastVal[NUM_POTS]; // We use this to store the last value that wasn't noise here
    int16_t tempAnalogueInput; // we use this to take the current reading from each pot

    void setup(){
    MIDI.begin();
    Serial.begin(115200);
    for (i = 0; i < NUM_POTS; i++)
    {
    // Set the pin direction to input.
    pinMode(analogueInputMapping[i], INPUT);
    }

    }

    void loop(){

    for (i = 0; i < NUM_POTS; i++)
    {
    // Read the analogue input pin
    tempAnalogueInput = analogRead(analogueInputMapping[i]);
    if (abs(tempAnalogueInput - lastVal[i]) >= 8) { // check that it's a real reading and not just noise on the 10bit value
    lastVal[i] = tempAnalogueInput; // make sure we keep a record of the last real reading we have taken
    MIDI_TX(176, MIDI_CC + i, tempAnalogueInput >> 3); // shift our 10bit value to 7bits, then output it as a CC
    }
    }

    }



    That's about all you need really :-)

    Essentially, all the magic happens in a couple of lines, this is the first one of note:
    if (abs(tempAnalogueInput - lastVal[i]) >= 8) {

    At that point we've taken a reading from the analog pin, so we compare the reading with the last reading (which will be initialised to something random, it doesn't really matter) essentially, if the new reading and the last reading is +-8 or bigger, then it's a real reading, the code will store the current reading into the last reading variable, output the midi message and continue through the for loop. It should be noted that the value 8 should not really be changed, if you do you'll probably get noise (random midi messages) or you'll thin the data out and won't get 0-128 in single steps.

    the 2nd line of note is the actual MIDI_TX command:
    MIDI_TX(176, MIDI_CC + i, tempAnalogueInput >> 3);

    Specifically this 'tempAnalogueInput >> 3' what that does is converts our 10bit analog value into 7 bits by shifting it 3 bits, which gives us a nice 7bit value without needing to do any maths.

    The code is super simple, doesn't need any delays and as long as you've tied all the unused analogue inputs to ground, it should be super clean, fast, with full 0-128 range from top to bottom and it is easy to expand, just change the NUM_POTS value and add the pin numbers to analogueInputMapping array.

    HTH.

  2. #112
    Newbie
    Join Date
    Feb 2014
    Location
    washington
    Posts
    3

    Default

    That looks good i guess.

  3. #113
    Tech Mentor
    Join Date
    Oct 2012
    Posts
    160

    Default

    Quote Originally Posted by ReggieUK View Post
    I've had to deal with this myself recently on a leonardo, the issue here is that the analogue inputs will have noise, so what you have to do is introduce a method for filtering out that noise and only outputting real movement. First things first, make sure that all other unused analog pins are tied to ground, that will get rid of some noise.
    Yes, but also it's not a bad idea to put 0.1uF cap between AREF pin on your Leonardo and GND.


    int16_t tempAnalogueInput; // we use this to take the current reading from each pot
    There is no need to define this as global variable since you're using it only in loop while checking pots.

    That's about all you need really :-)
    Not really. Imagine this scenario. Your pot values are 10bit. So for instance, they start to jump around these values:

    1019
    1020
    1021
    1023
    1019

    By dividing that with 8, you will get stable 127 MIDI value, so no issue. But, picture this:

    1014
    1015
    1019
    1014
    1020

    What happens here? Your code will start sending a stream of messages - 126,127,126,127. You haven't done anything in your code to prevent that.

    It is also a good idea to delay the reading of analogue pins by 1 or 2ms (but NOT by using delay), to actually make a pause between each reading to allow the pot to stabilize a bit.
    Shantea Controls - Custom MIDI controllers: Official | Youtube | Instagram | Tindie
    DJ Mixes: Psychill, Psydub, Dub | House, Progressive, Techno | Dubstep

  4. #114
    Tech Mentor
    Join Date
    Oct 2012
    Posts
    160

    Default

    Quote Originally Posted by hoogasv View Post
    Though it would be nice if someone posted a new code example with some pots and buttons that works with traktor. It can't just be me who is having trouble with this right? Or, maybe. Anyway, I hope you are willing to help and if not then it's fine.
    Check out my Tannin project:

    https://github.com/paradajz/Tannin
    http://forum.djtechtools.com/showthread.php?t=78521
    Shantea Controls - Custom MIDI controllers: Official | Youtube | Instagram | Tindie
    DJ Mixes: Psychill, Psydub, Dub | House, Progressive, Techno | Dubstep

  5. #115
    Tech Mentor
    Join Date
    Sep 2013
    Posts
    159

    Default

    Not sure what your point is, have you actually tried my code out? It's ROCK SOLID and you clearly haven't understood how it works.

    1014
    1015
    1019
    1014
    1020

    is an irrelevant scenario, since none of those numbers are greater than 8 from each other so the actual 7bit CC VALUE WON'T change!!! Did you read my code? Because I don't divide by 8 anywhere, I don't need to. I have a hysterisis value of 8 which I compare against the result of doing an abs() on lastVal[i] - tempAnalogInput, try the code, check for yourself. I am not arguing with you over this, I'm telling you, it works rock solid.

    This code is actually extracted from my own adaptation on the instructables 'midi arcade controller', I had to rewrite the analog handling section completely, it also tried to use a 'divide by 8 method' which sucked hard, which is entirely why I rewrote it. I also added code for rotary encoders that doesn't need delays or interrupts either.

    A delay in that code might be useful, a cap also might be useful but in the current iteration of code, it doesn't at all.

  6. #116
    Tech Mentor
    Join Date
    Oct 2012
    Posts
    160

    Default

    Quote Originally Posted by ReggieUK View Post
    Did you read my code? Because I don't divide by 8 anywhere, I don't need to. I have a hysterisis value of 8 which I compare against the result of doing an abs() on lastVal[i] - tempAnalogInput, try the code, check for yourself. I am not arguing with you over this, I'm telling you, it works rock solid.
    Ahh, sorry I haven't noticed that. However, you would be surprised how those values can change rapidly, even +- 8, so just because you haven't run into issues yet doesn't mean you won't (I've actually used that same method quite some time ago and it started to give me troubles when I started to add more components to circle). But if it works, all is fine.

    Quote Originally Posted by ReggieUK View Post
    I also added code for rotary encoders that doesn't need delays or interrupts either.
    That is very bad practice. By constantly polling the values from pins on which encoders are connected you waste your CPU cycles for nothing. A couple of years ago I was working on project, also MIDI controller with 2 rotary encoders, 31 potentiometer, 27 LEDs and 48 buttons. Method for reading encoders wasn't using any interrups and my code would "hang", that is, LEDs would start to flicker, pots started changing values etc. Why? Because I wasted so much time on those encoders that code simply couldn't do everything I wanted on time. Using interrupts, you handle encoders only when there is actual change on them, not all the time.
    Shantea Controls - Custom MIDI controllers: Official | Youtube | Instagram | Tindie
    DJ Mixes: Psychill, Psydub, Dub | House, Progressive, Techno | Dubstep

  7. #117
    Newbie
    Join Date
    Feb 2014
    Posts
    2

    Default

    Ok, so this was really helpfull! I tried the code from ReggieUK and it works flawless! Easy to understand commenting as well.

    paradajs, I have seen your project before but didn't find the code I think. Or maybe I found it but thought it was to complex for me at the time. Right now I'm trying to figure out how your leds work. And when I get my own leds to work, I'm pretty much done! After that I will probably post the final code and some pictures!

  8. #118
    Tech Mentor
    Join Date
    Sep 2013
    Posts
    159

    Default

    Hi Paradajz, I actually am not surprised by how much the values fluctuate at all :-) That's why I introduced such a large value in there, it essentially lets the code work itself it by the natural fact that we need a 7bit value from a 10bit value, that's instantly 3bits of noise we can discount

    I should clarify about my code too, whilst I'm not using delays, I'm also not getting any issues at all, I'm using all of the available GPIO, so I'm getting 16buttons, 2 pots and 2 encoders on here atm, I haven't put any delays in the code but there is a small debounce value for the buttons, everything else, the code is just rock solid. I have no problems 'wasting' cpu cycles, it's really not an issue, they're not wasted at all, as they're not being used for anything else, they're free, it just means my code is running efficiently, if I need to thin things out I can easily add a 1-2ms delay in there but it has been entirely unnecessary to do so and if I really need to I can use interrupts. However, the original code that was posted here, the poster is only using 3 pots and nothing else :-) Although having a mega and 54 pins to mess with, I'm guessing he's going to put a lot of stuff on it, in which case, it would be be simple to put the encoder on a couple of interrupt pins.

  9. #119
    Tech Mentor
    Join Date
    Sep 2013
    Posts
    159

    Default

    I made a separate board and firmware for a bunch of RGB LEDs that accepts midi input and makes them light up, I'm going to add it into my existing code for my controller, so that I can essentially make the lights react like a spectra and have a separate unit just for a light show if I want to.

    I've got traktor using the external lights for a vu meter atm, I've got to look at the traktor specs. to see what else I can do with it, clearly I'd like be able to set colours externally and set brightness too. Maybe have it react to the bpm to set delays for effects possibly. The really good thing about these leds is that they only take a single pin to make them work, and once the colour is set, you don't need to keep feeding it any more information, so it's relatively simple to update colours.

  10. #120
    Tech Mentor
    Join Date
    Sep 2013
    Posts
    159

    Default

    Another update, I've expanded the LED code so that it reacts to velocity to change the brightness, I've also added the facility for the user to change colours on each LED via note on messages on channels 2 and 3, I use midi channel 2 for sending 7bit velocity values (0-127) change and I exploit midi channel 3 to tell the system that it's an 8bit colour byte to allow access to the full 8bits per colour channel per led :-)

    I have it laid out so that notes 0-15 are the Red values for each button, 16-31 are the Green values and 32-47 are the Blue values.

    I will probably add a 4th channel for brightness and add an alternate colour for when the button is released, I will also add code to store it all in eeprom too.

    The code is also scalable, so you can put in whatever combination of buttons, pots or encoders that the board will allow, the LED code works via changing a define called NUM_LEDS, simply change the value of NUM_LEDS to suit your application, you can have 0 - 42 leds 128/3 (1 note per colour per button) in the current configuration but it would be simple enough to shift the colour change messages up a channel and then use channel 2 to expand the total number of leds to 84, in fact, it would probably be sensible to use 7 channels in total, channel 1 for turning the lights on/off and 2 lots of 3 channels for handling the 7 and 8bit colour change data, then it would support 128 leds without any messing around. We'll see, it's a fair chunk of program memory to have an array that large, it's about 1KB per colour, so I'd need 2KB for 128 leds, leaving 512bytes for the rest of the code to run in. I can use progmem to store constants, so that's not so bad but it would be tight I think.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •