Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 2 of 2

Thread: How to make a midi controller with 16 analog inputs using Teensy LC!

  1. #1

    How to make a midi controller with 16 analog inputs using Teensy LC!

    Hi everyone!
    Here's how to make a USB midi controller for dirt cheap!
    This controller has 16 analog inputs.

    what you'll need:

    1 Teensy LC ---> buy from pjrc ($11.65)
    1 CD74HC4067 breakout board ---> buy from sparkfun ($4.95)
    1 to 16 10k linear B potentiometers. ---> buy from ebay (5pc for $1.25)
    1 Breadboard -----> buy from ebay ($1.50)
    Wire....pennies per ft! buy lots because its always handy to have lots of.

    Step 1:
    Once you have all these items wire them up together like this...for simplicity sake only 3 potentiometers are shown but you can connect 16, just remember to connect any additional pots to +/- and the center pins of the potentiometers go to the "C" pins on the red breakout board.
    Click image for larger version. 

Name:	i63aWzf.jpg 
Views:	66 
Size:	97.6 KB 
ID:	11852


    Step 2:
    Install Arduino 1.8.4 (newer versions don't support teensy LC yet )
    Get it here ---> https://www.arduino.cc/en/Main/OldSoftwareReleases

    Step 3:
    Install the Teensy loader application
    Get it here ---> https://www.pjrc.com/teensy/loader.html

    Step 4:
    Plug your Teensy into your computer via usb...

    Step 5:
    Open Arduino 1.8.4 and click "tools" and then set the board type to Teensy LC
    Click image for larger version. 

Name:	mBqmiNm.png 
Views:	47 
Size:	34.3 KB 
ID:	11857


    Step 6:
    Click tools and also set the USB type to MIDI
    Click image for larger version. 

Name:	qLzFDnu.png 
Views:	40 
Size:	30.0 KB 
ID:	11853


    Step 7:
    Delete the "void setup" and "loop setup" code so you have a nice blank page in arduino.
    Click image for larger version. 

Name:	ViDcOmL.png 
Views:	37 
Size:	10.7 KB 
ID:	11854

    Step 8:
    Paste this code into the blank page
    //************LIBRARIES USED**************
    // include the ResponsiveAnalogRead library for analog smoothing
    #include <ResponsiveAnalogRead.h>
    //usbMIDI.h library is added automatically when code is compiled as a MIDI device

    // ******CONSTANT VALUES********
    // customize code behaviour here!
    const int muxTimeMin = 500; // minimum micro-seconds between MUX reads
    const int channel = 1; // MIDI channel
    const int MUX_PINS = 16; // number of MUX Channnels

    // define the CC ID numbers on which to send them..

    const int CCID[MUX_PINS] = {70,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36};


    //******VARIABLES***********
    // a data array and a lagged copy to tell when MIDI changes are required
    byte data[MUX_PINS];
    byte dataLag[MUX_PINS]; // when lag and new are not the same then update MIDI CC value
    byte i=0; // global index for MUX channel reads

    //mapping of mux to teensy digital pins
    int pin_Out_S0 = 4;
    int pin_Out_S1 = 3;
    int pin_Out_S2 = 2;
    int pin_Out_S3 = 1;
    int pin_In_Mux1 = A0;


    //****** TIMER VARIABLE *** change scale here!
    elapsedMicros mux1Updated; // switch to micros to run at speed and tune with muxTimeMin setting above
    //elapsedMillis mux1Updated; // switch to millis to troubleshoot

    //************INITIALIZE LIBRARY OBJECTS**************
    // initialize the ReponsiveAnalogRead objects
    ResponsiveAnalogRead analog[]{
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true},
    {pin_In_Mux1 ,true}
    };



    //************SETUP**************
    void setup() {
    //! don't forget to set for output!
    pinMode(pin_Out_S0, OUTPUT);
    pinMode(pin_Out_S1, OUTPUT);
    pinMode(pin_Out_S2, OUTPUT);
    pinMode(pin_Out_S3, OUTPUT);
    }

    //************LOOP**************
    void loop() {
    nextMUXpin();
    while (usbMIDI.read()) {
    // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
    }
    }


    //************MUX SECTION**************
    void nextMUXpin(){
    if (mux1Updated>muxTimeMin) {
    // 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);
    serialPringMIDIdata(); // use to troublshoot
    }
    }

    //reset timer
    mux1Updated = 0;
    //increment index
    i++;
    if (i>15) {i=0;}
    // set mux control pins for next pass
    digitalWrite(pin_Out_S0, HIGH && (i & B00000001));
    digitalWrite(pin_Out_S1, HIGH && (i & B00000010));
    digitalWrite(pin_Out_S2, HIGH && (i & B00000100));
    digitalWrite(pin_Out_S3, HIGH && (i & B00001000));
    }
    }

    // **useful for debugging, comment out function call to run full speed
    void serialPringMIDIdata(){
    Serial.print(i,DEC);
    Serial.print(" :");
    Serial.print(HIGH && (i & B00000001),BIN);
    Serial.print(HIGH && (i & B00000010),BIN);
    Serial.print(HIGH && (i & B00000100),BIN);
    Serial.print(HIGH && (i & B00001000),BIN);
    Serial.print(" MUX_PIN: ");
    Serial.print(i,DEC);
    Serial.print(" CC: ");
    Serial.print(CCID[i],DEC);
    Serial.print(" DATA HEX: ");
    Serial.println(data[i],HEX);
    }
    This code was made by the user oddson here at the Teensy forum (https://forum.pjrc.com) ...HERE is a link to the full thread if you're bored and wanna see how he developed it. I made some very small changes to the code he posted in order to make this code work with the wiring in my diagram above. He has mentioned that there is another verson of this code in the thread but I havn't had a chance to try it out yet.

    To set the CC values of the C0 pins on the red breakoutboard, change the values in the "const int CCID[MUX_PINS] = {70,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36}; " to whatever you want! left to right (70 to 36) are c0 to c15

    Step 9:
    Click "verify"
    Click image for larger version. 

Name:	UCf5PQJ.png 
Views:	42 
Size:	53.6 KB 
ID:	11855

    Wait a little while and allow the arduino software to verify and compile the code.

    Step 10:
    Once its done compiling, click "upload"
    Click image for larger version. 

Name:	twCl2Hg.png 
Views:	42 
Size:	58.0 KB 
ID:	11856


    Step 11:
    Plug your fancy new DIY midi controller into whatevers you want and play around with it!

    Note: I made this project to increase the number of analog inputs for a cool synth creation board called "Axoloti" you can check it out here: http://www.axoloti.com/ its awesome!

  2. #2
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Vancouver Canada
    Posts
    619
    I believe it's preferable to power the MUX from Vin (5v) and ground it to the GND pin.

    The device is supposed to work better (lower on resistance, more linear output) with the higher supply voltage and it's return should not be to the analog ground (as it may introduce additional noise).

    FYI - the other version doesn't use the (excellent!) ResponsiveAnalogRead(RAR) library to keep the voltages stable enough to use for MIDI CC values, relying instead on simple 'dead-band' control where changes less than some threshold are ignored.

Posting Permissions

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