Midi Controller not working

Hi, I followed below image to made a Midi Controller, use Arduino micro and CD4067, uploaded the code then use the loopMIDI and hairless-midi, but it no any response when press any button or potentiometer. What is the problem?

#include "MIDIUSB.h"
 
#include <Multiplexer4067.h> 
#include <Thread.h> 
#include <ThreadController.h> 

/////////////////////////////////////////////
// buttons
const byte muxNButtons = 5; 
const byte NButtons = 11; 
const byte totalButtons = muxNButtons + NButtons;
const byte muxButtonPin[muxNButtons] = {12, 13, 14, 15, 11}; 
const byte buttonPin[NButtons] = {18, 19, 20, 10, 16, 14, 15, 6, 7, 8, 9}; 
int buttonCState[totalButtons] = {0}; 
int buttonPState[totalButtons] = {0}; 

/////////////////////////////////////////////
// debounce
unsigned long lastDebounceTime = 0;  
unsigned long debounceDelay = 5;    

/////////////////////////////////////////////
// potentiometers
const byte NPots = 4; 
const byte muxPotPin[NPots] = {0, 1, 2, 3}; 
int potCState[NPots] = {0}; 
int potPState[NPots] = {0}; 
int potVar = 0; 
int lastCcValue[NPots] = {0};

/////////////////////////////////////////////
// pot reading
int TIMEOUT = 50; 
byte varThreshold = 4; 
boolean potMoving = true; 
unsigned long pTime[NPots] = {0}; 
unsigned long timer[NPots] = {0}; 

/////////////////////////////////////////////
// midi
byte midiCh = 0; // * midi channel to be used
byte note = 36; // * The lowest note that will be used
byte cc = 1; // *Lowest CC that will be used

/////////////////////////////////////////////
// Multiplexer
Multiplexer4067 mplex = Multiplexer4067(2, 3, 4, 5, A3);

/////////////////////////////////////////////
// threads - program each Arduino activity to happen at a certain time
ThreadController cpu; // master thread, where others will be added
Thread threadReadPots; // thread to control pots

/////////////////////////////////////////////

void setup() {

  mplex.begin(); 

  for (int i = 0; i < NButtons; i++) { 
    pinMode(buttonPin[i], INPUT_PULLUP);
  }

  pinMode(A3, INPUT_PULLUP);

  /////////////////////////////////////////////
  // threads
  threadReadPots.setInterval(10);
  threadReadPots.onRun(readPots);
  cpu.add(&threadReadPots);
  /////////////////////////////////////////////

}

void loop() {

  cpu.run();
  readButtons();

}


/////////////////////////////////////////////
// read buttons

void readButtons() {

  for (int i = 0; i < muxNButtons; i++) { 
    int buttonReading = mplex.readChannel(muxButtonPin[i]);
    if (buttonReading > 1000) {
      buttonCState[i] = HIGH;
    }
    else {
      buttonCState[i] = LOW;
    }
  }

  for (int i = 0; i < NButtons; i++) { 
    buttonCState[i + muxNButtons] = digitalRead(buttonPin[i]); 
  }

  for (int i = 0; i < totalButtons; i++) {

    if ((millis() - lastDebounceTime) > debounceDelay) {

      if (buttonCState[i] != buttonPState[i]) {
        lastDebounceTime = millis();

        if (buttonCState[i] == LOW) {
          noteOn(potMidiCh(), note + i, 127);  
          MidiUSB.flush();
          buttonPState[i] = buttonCState[i];
        }
        else {
          noteOn(potMidiCh(), note + i, 0);  
          MidiUSB.flush();
          buttonPState[i] = buttonCState[i];
        }
      }
    }

  }

}


/////////////////////////////////////////////
//read potentiometers

void readPots() {

  for (int i = 0; i < NPots - 1; i++) { 
    potCState[i] = mplex.readChannel(muxPotPin[i]);
  }

  for (int i = 0; i < NPots; i++) {

    potVar = abs(potCState[i] - potPState[i]); 

    if (potVar >= varThreshold) { 
      pTime[i] = millis(); 
    }
    timer[i] = millis() - pTime[i]; 
    if (timer[i] < TIMEOUT) { 
      potMoving = true;
    }
    else {
      potMoving = false;
    }

    if (potMoving == true) { 
      int ccValue = map(potCState[i], 22, 1022, 0, 127);
      if (lastCcValue[i] != ccValue) {
        controlChange(11, cc + i, ccValue); 
        MidiUSB.flush();
        potPState[i] = potCState[i]; 
        lastCcValue[i] = ccValue;
      }
    }
  }

}

/////////////////////////////////////////////
// calculates midi channel based on pot position
int potMidiCh () {
  int potCh =  map(mplex.readChannel(muxPotPin[9]), 22, 1023, 0, 4);

  if (potCh == 4) {
    potCh = 3;
  }
  
  return potCh + midiCh;
}



/////////////////////////////////////////////
// Arduino (pro)micro midi functions MIDIUSB Library
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);
}

is multiplexer allowing analog signals?
do midi need some initiating in setup?
is Atmega32u4 support multi-threading?

Use a logic analyzer to see what happens.

Insert Serial.println()´s at points of interrest.

Have a nice day and enjoy coding in C++.

Sorry, I’m beginner to Arduino, how to use logic analyser?

Is multiplexer allowing analog signals?
MUX allow both analog and digital signals
do midi need some initiating in setup?
No
is Atmega32u4 support multi-threading?
I found that Arduino doesn’t support multi-threading but some say still can multi-threading.

There should be no need to use either loopMidi or hairless midi. Your Arduino Micro should just show up as a USB-midi device that you can select within any MIDI capable software (being a DAW or a standalone instrument/effect)
I suggest your simplify your setup first to exclude parts of the code.
try

#include "MIDIUSB.h"

#define LED 3  // that pin is PWM capable and has no extra function
#define POT A2
#define CHANNEL (7 - 1)  // midi channel 6 equals 5 in this system.

// First parameter is the event type (0x09 = note on, 0x08 = note off).
// Second parameter is note-on/note-off, combined with the channel.
// Channel can be anything between 0-15. Typically reported to the user as 1-16.
// Third parameter is the note number (48 = middle C).
// Fourth parameter is the velocity (64 = normal, 127 = fastest).

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, (uint8_t) (0x90 | channel), pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
  MidiUSB.flush();
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, (uint8_t) (0x80B | channel), pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
  MidiUSB.flush();
}

void setup() {
  pinMode(LED, OUTPUT);
  analogWrite(LED, 120);
  delay(1000);
  analogWrite(LED, 0);
}

// First parameter is the event type (0x0B = control change).
// Second parameter is the event type, combined with the channel.
// Third parameter is the control number number (0-119).
// Fourth parameter is the control value (0-127).

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, (uint8_t) (0xB0 | channel), control, value};
  MidiUSB.sendMIDI(event);
  MidiUSB.flush();
}


void loop() {
  static uint32_t moment = millis();
  //static bool noteon = true;
  static uint8_t volume = 0;
  uint8_t analog = analogRead(POT) >> 3;
  if ((volume != analog) && (millis() - moment > 20)) {
    moment = millis();
    volume = analog;
    controlChange(CHANNEL, 7, volume);
  }

  /*if (millis() - moment > 2000) {
    moment = millis();
    if (noteon) noteOn(0, 48, 100);  // pin C2
    else noteOff(0, 48, 64);
    noteon = !noteon;
    }*/

  midiEventPacket_t rx = MidiUSB.read();
  while (rx.header != 0) {    
    uint8_t type = rx.byte1 >> 4;
    uint8_t channel = rx.byte1 & 0xF;
    uint8_t value1 = rx.byte2;
    uint8_t value2 = rx.byte3;
    if (type == 0x9) analogWrite(LED, value2 * 2);
    if (type == 0x8) analogWrite(LED, 0);
    rx = MidiUSB.read();
  }

  //controlChange(0, 10, 65); // Set the value of controller 10 on channel 0 to 65
}

with just a single pot meter without multiplexer, and a led responding to note on/off.
to just confirm that midi transmission is working the way you want it to.
Something similar can be don to test the multiplexing, but once MiDi is working, the main program can also be used for testing that i guess.

I tried to just 16 buttons without multiplexer and upload other code, not as USB-midi device, use loopMIDI and hairless midi, but it still no response~~ is the pro micro broken ??

probably not.

if that is the download link, you should post it within </> code tags. I don't want to download it.

did you change the baudrate ?

do you have other midi device? do you receive response from it?

I have changed the baudrate to 115200 in hairless-midi.

Here is the code:

#define ATMEGA32U4 1

/////////////////////////////////////////////
#ifdef ATMEGA328
#include <MIDI.h>
 //MIDI_CREATE_DEFAULT_INSTANCE();

#elif ATMEGA32U4
#include "MIDIUSB.h"

#endif
// ---- //

/////////////////////////////////////////////
const int N_BUTTONS = 16; 
const int BUTTON_ARDUINO_PIN[N_BUTTONS] = {10, 16, 14, 15, 6, 7, 8, 9, 2, 3, 4, 5, A3, A2, A1, A0}; 


byte pin13index = 12; 

int buttonCState[N_BUTTONS] = {};       
int buttonPState[N_BUTTONS] = {};        

// debounce
unsigned long lastDebounceTime[N_BUTTONS] = {0};  
unsigned long debounceDelay = 20;  


/////////////////////////////////////////////
// midi
byte midiCh = 2; 
byte note = 36; 
byte cc = 11;

/////////////////////////////////////////////
// SETUP
void setup() {

 
  Serial.begin(115200); 

#ifdef DEBUG
Serial.println("Debug mode");
Serial.println();
#endif

  // Buttons
  for (int i = 0; i < N_BUTTONS; i++) {
    pinMode(BUTTON_ARDUINO_PIN[i], INPUT_PULLUP);
  }

#ifdef pin13
pinMode(BUTTON_ARDUINO_PIN[pin13index], INPUT);
#endif


}

/////////////////////////////////////////////
// LOOP
void loop() {

  buttons();

}

/////////////////////////////////////////////
// BOTOES
void buttons() {

  for (int i = 0; i < N_BUTTONS; i++) {

    buttonCState[i] = digitalRead(BUTTON_ARDUINO_PIN[i]);  

#ifdef pin13
if (i == pin13index) {
buttonCState[i] = !buttonCState[i]; 
}
#endif

    if ((millis() - lastDebounceTime[i]) > debounceDelay) {

      if (buttonPState[i] != buttonCState[i]) {
        lastDebounceTime[i] = millis();

        if (buttonCState[i] == LOW) {

         
#ifdef ATMEGA328
MIDI.sendNoteOn(note + i, 127, midiCh); // note, velocity, channel

#elif ATMEGA32U4
noteOn(midiCh, note + i, 127);  // channel, note, velocity
MidiUSB.flush();


#elif DEBUG
Serial.print(i);
Serial.println(": button on");
#endif

        }
        else {

        
#ifdef ATMEGA328
MIDI.sendNoteOn(note + i, 0, midiCh); // note, velocity, channel

#elif ATMEGA32U4
noteOn(midiCh, note + i, 0);  // channel, note, velocity
MidiUSB.flush();

#elif DEBUG
Serial.print(i);
Serial.println(": button off");
#endif

        }
        buttonPState[i] = buttonCState[i];
      }
    }
  }
}

/////////////////////////////////////////////

/////////////////////////////////////////////
#ifdef ATMEGA32U4

// Arduino (pro)micro midi functions MIDIUSB Library
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);
}

#endif

I have other midi device with Arduino pro micro, it's working.
I made a MIDI controller with second Arduino pro micro, checked their COM were different port.

if you are using midi.h then you need to modify the baudrate in serialMIDI.h

struct DefaultSerialSettings
{
    /*! Override the default MIDI baudrate to transmit over USB serial, to
    a decoding program such as Hairless MIDI (set baudrate to 115200)\n
    http://projectgus.github.io/hairless-midiserial/
    */
    static const long BaudRate = 31250;
};

For 16 buttons, I changed the baudrate to 115200 in serialMIDI.h and uploaded the code again, but still not work when press any button.
I use pro micro it should be use MIDIUSB.h not MIDI.h

Also got some message after uploaded code. Is it mean some error?

Connecting to programmer: .
Found programmer: Id = "CATERIN"; type = S
    Software Version = 1.0; No Hardware Version given.
Programmer supports auto addr increment.
Programmer supports buffered memory access with buffersize=128 bytes.

Programmer supports the following devices:
    Device code: 0x44

yes, but if you use MIDIUSB.h your device should just show up as a midi device, and you won't need hairless midi

OK, I just open LoopMIDI and use Ableton, it's can't any MIDI mapping, do I miss something?


By the way orange light on the top right-hand corner of Ableton is not blink when press any button on MIDI controller (keyboard is working).
InkedAbleton

so you don't need loopMIDI !!!
you micro is showing up correctly Now if you go back to my reply#6 you see the code i used, which is really simple, no multiplexer, just a button and a pot. I made this code for testing (and to develop a simple midi controller)
Midi output channel is set to '7' (-1 will correct the -1 offset.)

if ((volume != analog) && (millis() - moment > 20)) {
    moment = millis();
    volume = analog;
    controlChange(CHANNEL, 7, volume);
  }

this sends CC#7 on channel 7 (volume on channel 7) for the result of the analog input (to which i have a pot connected)

and if you uncomment this

/*if (millis() - moment > 2000) {
    moment = millis();
    if (noteon) noteOn(0, 48, 100);  // pin C2
    else noteOff(0, 48, 64);
    noteon = !noteon;
    }*/

it will send a noteOn or noteOff every 2 seconds for note C2 (mide 42) on channel 1.

You should be able to receive those in ableton (i can without issue) You have selected Track (which deals with all noteOn & noteOff) and Remote which deals with all CC#

Oh I'm sorry to all, finally checked the some pin weren’t soldering , now I soldering all pin and it's working~

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.