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

Thread: Beginner advice on midi controller

  1. #1

    Beginner advice on midi controller

    Hi, I'm looking to build what should be a pretty simple midi controller for MAX MSP. The controller would consist of several joysticks that would transmit CC messages. I plan on using these... https://www.adafruit.com/product/3102

    I'd also like to have a keypad matrix switch that I can use to type in commands. For instance if I typed in '127' it would then send a message (what kind I don't know, I'm currently thinking program change) that would trigger some sort of event in Max like 'start playing this file' or 'load this preset' etc etc

    And lastly I'd like some sort of LCD display that told me what I was doing. IE if I moved a joystick it would display what two CC values I was transmitting.

    I've downloaded and installed the MIDIcontroller-master library. To get started I opened up the MIDIpot example file in arduino IDE, but I am unable to verify and compile the sketch.

    This is the error message.

    Arduino: 1.8.9 (Mac OS X), TD: 1.46, Board: "Teensy 2.0, MIDI, 16 MHz, US English"

    /Users/nate/Documents/Arduino/libraries/MIDIcontroller-master/MIDIcapSens.cpp: In member function 'int MIDIcapSens::read()':
    /Users/nate/Documents/Arduino/libraries/MIDIcontroller-master/MIDIcapSens.cpp:47:31: error: 'touchRead' was not declared in this scope
    int newValue = touchRead(pin);
    ^
    Error compiling for board Teensy 2.0.

    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.



    I am very new to arduino/teensy and have no idea what this means. Any help with this specific problem or general advice on my project would be greatly appreciated.

    Thanks!

    The code is simply the MIDIpot exmaple, but here it is anyways,


    #include "MIDIcontroller.h"

    byte MIDIchannel = 5;
    const int potPin = A0; // Change this to the ANALOG pin you want to use

    // Pot parameters are: pin, CC number, KILL switch enabled
    // When KILL is enabled, separate CC messages (with a different number) will be sent
    // when you turn the pot all the way down and when you start turning it up again.
    // Simply omit the "KILL" argument if you don't want that.
    MIDIpot myPot(potPin, 22, KILL);

    // OPTIONAL: use outputRange() to limit the min/max MIDI output values
    // mysensor.outputRange(12, 90);

    void setup(){
    }

    void loop(){
    myPot.send();
    }

  2. #2
    I'm just building my first controller too, but I *think* that appears to be an error message from the MIDIcapSens.cpp sketch rather than the MIDIpot one, so maybe you opened the wrong one first go?

    I think it's saying that in line 47 of "MIDIcapSens.cpp"

    "int newValue = touchRead(pin);"

    you haven't defined a value for "pin"

    but I'm pretty sure that's irrelevant as it's wrong sketch!
    In the "MIDIpot" sketch you posted you should not have the same issue as it defines "Potpin" as "A0" in the third line.
    Maybe try this again?

    I am building a controller using this libary instead, which I found very simple:

    https://github.com/tttapa/MIDI_controller

    but it is designed for Teensy 3.1/3.2 - although this suggests there is an amended code for 2.0

    https://github.com/tttapa/MIDI_controller/issues/20

  3. #3
    Thanks, duckchild

    I just ran the sketch again and got this error message, which is completely different...

    Code:
    Arduino: 1.8.9 (Mac OS X), TD: 1.46, Board: "Teensy 2.0, MIDI, 16 MHz, US English"
    
    /Users/nate/Documents/Arduino/libraries/MIDIcontroller-master/MIDIpot.cpp: In member function 'int MIDIpot::read()':
    /Users/nate/Documents/Arduino/libraries/MIDIcontroller-master/MIDIpot.cpp:82:16: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
       if (newValue >= inHi && value != outHi){ // Assign hi analog to hi MIDI
                    ^
    /Users/nate/Documents/Arduino/libraries/MIDIcontroller-master/MIDIpot.cpp:86:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
       else if (newValue <= inLo && value != outLo){ // Assign low analog to low MIDI
                         ^
    /Users/nate/Documents/Arduino/libraries/MIDIcontroller-master/MIDIdrum.cpp: In member function 'int MIDIdrum::send(int)':
    /Users/nate/Documents/Arduino/libraries/MIDIcontroller-master/MIDIdrum.cpp:69:27: warning: third operand of conditional expression has no effect [-Wunused-value]
         constrain(vel, 1, 127);
                               ^
    /Users/nate/Documents/Arduino/libraries/MIDIcontroller-master/MIDIcapSens.cpp: In member function 'int MIDIcapSens::read()':
    /Users/nate/Documents/Arduino/libraries/MIDIcontroller-master/MIDIcapSens.cpp:47:31: error: 'touchRead' was not declared in this scope
       int newValue = touchRead(pin);
                                   ^
    Error compiling for board Teensy 2.0.
    
    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.
    I don't know, I've been working with some other examples from a few of the instructables out there that are so far working ok. I'll check out the library you posted too.

    This has been my favorite so far...
    https://forum.pjrc.com/threads/45376...ts-and-Buttons

  4. #4
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,138
    Quote Originally Posted by nateflanigan View Post
    ...I just ran the sketch again and got this error message, which is completely different...
    That's actually the same fatal error plus some new warnings.

    You don't need an external MIDI controller library (and you won't really find support for them here as none of the regulars use them).

    The joysticks should be fairly simple as they are just two potentiometers each so you need two analog pins for each. The 'many knobs and buttons' example code's analog section can handle this.

    Reading a keypad should be not too hard by following this
    https://www.pjrc.com/teensy/td_libs_Keypad.html

    ...but interpreting codes and performing actions will be up to you to work out.

    I'm not expert at displays but there are plenty of people here who are.

    I strongly recommend you try the tutorials to get some basics first.
    https://www.pjrc.com/teensy/tutorial.html

    It's possible to cobble code together from examples without understanding all the gory details but you need to have some understanding of the basics to have any chance of succeeding. And you have specific plans that will require you to work out the logic so you will need to learn to code these yourself.

  5. #5
    Sound advice oddson, so far I like the example code that you posted on another thread best.

  6. #6
    Hi, I've made some great progress but could use some advice for taking the next step.

    I've got the matrix keypad working and sending midi note on/off and velocity values for each of the 16 keys (0-9,#,*, A,B,C,D). What I'd like to do is have the 0-9 keys send the midi note messages but A,B,C,D keys act as octave change buttons when held. For instance say I have it set so that when I press 1 it sends note# 40, I'd like to be able to hold the A key press 1 and have it transmit note# 52.

    Any advice on how to proceed?

    here is the code so far...

    Code:
    #include "MIDIUSB.h"
    
    /* Settings for Keypad */
    const byte ROWS = 4; //four rows
    const byte COLS = 4; //four columns
    const int NB_BUTTONS = ROWS * COLS;
    
    
    int notes[NB_BUTTONS] = {37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52};
    
    int keymodifier;
    /* Keypad Init */
    //https://github.com/Nullkraft/Keypad
    #include <Keypad.h>
    char keys[ROWS][COLS] = {
      {'1', '2', '3', 'A'},
      {'4', '5', '6', 'B'},
      {'7', '8', '9', 'C'},
      {'*', '0', '#', 'D'}
    };
    
    //Keypad pins
    byte rowPins[ROWS] = {0, 1, 2, 3}; //connect to the row pinouts of the kpd
    byte colPins[COLS] = {4, 5, 6, 7}; //connect to the column pinouts of the kpd
    Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
    
    //Keypad state : 1 = DOWN 3 = UP (there are other state which are unused here)
    unsigned int buttons_state[NB_BUTTONS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
    
    void setup() {
      Serial.begin(115200);
      kpd.setHoldTime(250); // THIS IS WHERE I SET HOLD TIME NPF
    }
    
    
    
    void loop() {
      if (kpd.getKeys()) {
        for (int i = 0; i < LIST_MAX; i++) // Scan the whole key list.
        {
          if ( kpd.key[i].stateChanged )   // Only find keys that have changed state.
          {
            buttons_state[kpd.key[i].kcode] = kpd.key[i].kstate;
    
            if (kpd.key[i].kstate == 1) { //DOWN
              Serial.print(kpd.key[i].kcode);
              Serial.print(":");
              Serial.println("1");
    
            
               
                key_down(kpd.key[i].kcode);
    
              
            }
                  
                  
            if (kpd.key[i].kstate == 3) { //UP
              Serial.print(kpd.key[i].kcode);
              Serial.print(":");
              Serial.println("0");
              // If key is up we send a midi note off
              key_up(kpd.key[i].kcode);
            }
          }
        }
      }
    }
    
    //Key down (pressed)
    void key_down(int key) {
      //Serial.print(buttons_state[velocity_button]);
      noteOn(0, (notes[key] + keymodifier), 127);
    
      //Display note and velocity on screen
      MidiUSB.flush();
    }
    
    //Key up (unpressed)
    void key_up(int key) {
    
        noteOff(0, notes[key], 127);
        
      MidiUSB.flush();
    }
    
    void noteOn(byte channel, byte pitch, byte velocity) {
      midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
      MidiUSB.sendMIDI(noteOn);
    }
    
    void noteOff(byte channel, byte pitch, byte velocity) {
      midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
      MidiUSB.sendMIDI(noteOff);
    }
    
    void controlChange(byte channel, byte control, byte value) {
      midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
      MidiUSB.sendMIDI(event);
    }

  7. #7
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,138
    Do you mean an option selector that is only active while held... like a shift key?

    Search MIDI and BANK together for examples. Thay mostly use a variable to store the selected bank states but using the actual pad button state should be simple enough.

    The main trick is to go to a two dimensional array (matrix) for notes where the additional dimension is the bank number.

    The other complication is having some keys represent modifiers and some events. It might be easier to have an intermediary step pass the matrix states into separate data structures for event and modifier buttons to allow indicator varables work in a loop that scans through the event key states on an outer loop and the modifiers on an inner loop.

    BTW: What is that Library? I don't know if you're even calling it in your code as I've only scanned it so far but I don't think you want to use it if you are compilingTeensy for USB MIDI as the appropriate library is included automatically.


    ....knocked this off quickly on my tablet.... excuse spelling and typos....

  8. #8
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,138
    You can retain the single loop structure if you have two paths within the loop, one if 'i' represents an event button and another if it is a modifier.

    Then set modifier variables when not an event.

    When it is an event, send with the note based on current modifier state from the most recent pass.

    As long as the modifier is set first this will work but longer debounce times MIGHT start to make it feel sluggish....

  9. #9
    Thanks, it'll take me a while to parse all this.

    Do you mean an option selector that is only active while held... like a shift key?
    Yes, exactly

    I'm not sure if this is what you're getting at but I was thinking that maybe the matrix should just be for notes and incorporate additional buttons to act as the modifiers. I mean, I don't need to trigger that many events, even 16 is probably fine for most performances.

  10. #10
    Also, about the library, that code is adapted from this example I found

    https://create.arduino.cc/projecthub...-keypad-c68fd2

    What is to be gained from using the default library? I'm starting to work on altering the sketch to use the default library. It's pretty confusing to me, one problem I'm having is it seems there's no flush command in the default library.

  11. #11
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,138
    What is to be gained from using the default library?
    it works, and doesn't need a flush or prepacked variables.

    Separete bank selectors would be slightly easier but you should be able to use the pad if you want.

  12. #12
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,138
    ....I should mention that, years ago, Teensy was the only way to do USB MIDI without fairly onerous kludges needed to get around how the device appears to the host for programing vs in operation. Teensy's bootloader made a much nicer experience possible for both the programmer and the user (by providing a MIDI compliant device to the USB interface).

    I honestly don't know where Aurdiuno is now as I only do Teensy.
    Last edited by oddson; 07-05-2019 at 04:51 PM.

Posting Permissions

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