Midi controller octave changer

Hi,

Im a newbie here and I have a problem with my code. I have crated a 24 button midi keyboard usin 2 multiplexer. I used a MIDI_Controller.h library and as a basic keyboard it works just as intended. BUT

I want to have and octave changer (3 way switch) to select between octaves (+ or - 12) to the value that the code puts out as any of the buttons on my keyboard is pressed.

I have failed many times trying to get a simple switch ( on pin 15) to activate a midi note that is 12 notes higher than if not pressed. Is the .refresh on the library somehow preventing the variables to be changed by the "if and else" function that I have tried to create inside the void loop function before MIDI_Controller.refresh (); ?

Any help would be aprecciated

Hajaxo from Finland

It will be very difficult to help without seeing your code. Please post your sketch.

What Arduino are you using?

You can't detect the position of a 3-position switch with one input pin.

You should end up with code sort of like this added to your existing sketch.

int OctaveShift = 0;
const byte OctaveUpPin = 15;
const byte OctaveDownPin = 16;

void loop()
{
  if (digitalRead(OctaveUpPin) == LOW)
    OctaveShift = 12;
  else if (digitalRead(OctaveDownPin) == LOW)
    OctaveShift = -12;
  else
    OctaveShift = 0;
...
   MIDI.sendNote(pitch + OctaveShift);
}

Im trying to use int saato as the variable witch the "if else"-function changes
The library can be found from github: GitHub - tttapa/MIDI_controller: This is a library for creating a MIDI controller using an Arduino or Teensy board.

heres my code:


int saato ;



void setup() {
  pinMode (15, INPUT);
digitalWrite(15, HIGH);
  pinMode (14, INPUT);
digitalWrite(14, HIGH);
}

//Written for use with Pro Micro Arduino (M.S.)

#include <MIDI_Controller.h>
AnalogMultiplex mux1(A1, {2,3,4,5});
AnalogMultiplex mux2(A2, {2,3,4,5});
  


int velocity = 0b1111111; // Maximum velocity (0b1111111 = 0x7F = 127)
 int a1F2 = 41; // Name Desired pitches and define with MIDI value note1 normisti 41...yritä saada -12 ja +12 oktaavinapin paineettua
 int a2F2x = 42;
 int a3G2 = 43;
 int a4G2x = 44;
 int a5A2 = 45;
 int a6A2x = 46;
 int a7B2 = 47;
 int a8C3 = 48;
 int a9C3x = 49;
 int a10D3 = 50;
 int a11D3x = 51;
 int a12E3 = 52;
 int a13F3 = 53;
 int a14F3x = 54;
 int a15G3 = 55;
 int a16G3x = 56;
 int a17A3 = 57;
 int a18A3x = 58;
 int a19B3 = 59;
 int a20C4 = 60;
 int a21C4x = 61;
 int a22D4 = 62;
 int a23D4x = 63;
 int a24E4 = 64;




Digital Buttonslarge[] = {
    


  {mux1.pin(0), saato, 1, velocity},
  {mux1.pin(1), a3G2 + saato, 1, velocity},
  {mux1.pin(2), (a5A2 + saato), 1, velocity},
  {mux1.pin(3), a7B2 + saato, 1, velocity},
  {mux1.pin(4), a8C3 + saato, 1, velocity},
  {mux1.pin(5), a10D3 + saato, 1, velocity},
  {mux1.pin(6), a12E3 + saato, 1, velocity},
  {mux1.pin(7), a13F3 + saato, 1, velocity},
  {mux1.pin(8), a15G3 + saato, 1, velocity},
  {mux1.pin(9), a17A3 + saato, 1, velocity},
  {mux1.pin(10), a19B3 + saato, 1, velocity},
  {mux1.pin(11), a20C4 + saato, 1, velocity},
  {mux1.pin(12), a22D4 + saato, 1, velocity},
  {mux1.pin(13), a24E4 + saato, 1, velocity},



};

Digital Buttonssmall[] = {
  {mux2.pin(0), a2F2x, 1, velocity},
  {mux2.pin(1), a4G2x, 1, velocity},
  {mux2.pin(2), a6A2x, 1, velocity},
  {mux2.pin(3), a9C3x, 1, velocity},
  {mux2.pin(6), a11D3x, 1, velocity},
  {mux2.pin(4), a14F3x, 1, velocity},
  {mux2.pin(5), a16G3x, 1, velocity},
  {mux2.pin(8), a18A3x, 1, velocity},
  {mux2.pin(7), a21C4x, 1, velocity},
  {mux2.pin(9), a23D4x, 1, velocity},
  /* {mux2.pin(9), G2, 4, velocity},
    {mux2.pin(10), E2, 4, velocity},
    {mux2.pin(11), B2, 4, velocity},
    {mux2.pin(12), D2, 4, velocity},
    {mux2.pin(13), a2, 4, velocity},
    {mux2.pin(14), f2, 4, velocity},
    {mux2.pin(15), C3, 4, velocity},
  */
};


  
void loop() {

if (digitalRead ( 15 == HIGH)) {
  saato = 12 ;
};

MIDI_Controller.refresh();

  
}

Thanks for the answer. I think my problem is the way that the library has been built. The code that I am trying to access is outside the void loop function.

Incorrect syntax. If you want to check the pin is high then this is the correct way:

if (digitalRead (15) == HIGH) {
  saato = 12 ;
};

I notice that you are enabling the internal pull-up resistor so shouldn't you be checking for LOW?

So I changed it like this. Also tried HIGH. Didnt work. If I bring all the "Int" and "Digital" rows inside the loop function... the octave change works, but the codes pushes midi notes as fast as the code runs. It is supposed to work in a way that when you press a button, it gives an output, and it gives an "off" input when you release.

void loop() {

if (digitalRead (15) == LOW) 
  saato = 12 ;
else
  saato = 0;


MIDI_Controller.refresh();

  
}

When you use 'saato' to initialize your array it won't matter if the value of 'saato' changes in the future. Once the result of the expression is calculated and stored it will not be calculated again. You have to add 'saato' AFTER you look up the button and are about to send the note.

1 Like

Here are several coding suggestions:

  1. Instead of using digitalWrite to enable the internal pullup the following is preferred for readability:

pinMode (15, INPUT_PULLUP);

  1. It is customary to put includes at the beginning of the file, followed by constants, followed by gloabl variables, followed by functions.

  2. For integers that will not change you should use the 'const' keyword. That way if your code attempts to overwrite the value the compiler will show an error. For example:

int velocity = 0b1111111; // Maximum velocity (0b1111111 = 0x7F = 127)

should be:

const int velocity = 0b1111111; // Maximum velocity (0b1111111 = 0x7F = 127)

  1. The following is a static initialization happening only once and there fore when saato is updated the array will not be:
Digital Buttonslarge[] = {
  {mux1.pin(0), saato, 1, velocity},
  {mux1.pin(1), a3G2 + saato, 1, velocity},
  {mux1.pin(2), (a5A2 + saato), 1, velocity},
  {mux1.pin(3), a7B2 + saato, 1, velocity},
  {mux1.pin(4), a8C3 + saato, 1, velocity},
  {mux1.pin(5), a10D3 + saato, 1, velocity},
  {mux1.pin(6), a12E3 + saato, 1, velocity},
  {mux1.pin(7), a13F3 + saato, 1, velocity},
  {mux1.pin(8), a15G3 + saato, 1, velocity},
  {mux1.pin(9), a17A3 + saato, 1, velocity},
  {mux1.pin(10), a19B3 + saato, 1, velocity},
  {mux1.pin(11), a20C4 + saato, 1, velocity},
  {mux1.pin(12), a22D4 + saato, 1, velocity},
  {mux1.pin(13), a24E4 + saato, 1, velocity},
};

You will have to record the note number that was sent for that button and use the same note number even if the octave has changed since then.

1 Like

I hear you. It seems like it is not solvable so easily after all.

I've replied to your issue comment here: Octave change for multiplexer buttons · Issue #113 · tttapa/MIDI_controller · GitHub

As mentioned in the readme, the MIDI_Controller library is no longer supported and has been obsoleted by the Control Surface library.

Control Surface supports transposition out of the box:

// Transposer that transposes one octave (12 semitones) at a time,
// from 0 to +1 octave.
Transposer<0, +1> transposer(12);
// change the transposition depending on the state of the switch
// on pin 15
SwitchSelector selector {transposer, 15}; 

CD74HC4067 mux1 {
  A1,          // Analog input pin
  {2, 3, 4, 5} // Address pins S0, S1, S2, S3
};

using namespace MIDI_Notes;
Bankable::NoteButton buttons[] {
  {transposer, mux1.pin(0), note(F, 2)},
  {transposer, mux1.pin(1), note(G, 2)},
  {transposer, mux1.pin(2), note(A, 2)},
  {transposer, mux1.pin(3), note(B, 2)},
  {transposer, mux1.pin(4), note(C, 3)},
  {transposer, mux1.pin(5), note(D, 3)},
  {transposer, mux1.pin(6), note(E, 3)},
  {transposer, mux1.pin(7), note(F, 3)},
  {transposer, mux1.pin(8), note(G, 3)},
  {transposer, mux1.pin(9), note(A, 3)},
  {transposer, mux1.pin(10), note(B, 3)},
  {transposer, mux1.pin(11), note(C, 4)},
  {transposer, mux1.pin(12), note(D, 4)},
  {transposer, mux1.pin(13), note(E, 4)},
};

https://tttapa.github.io/Control-Surface-doc/Doxygen/da/d2d/Transposer_8ino-example.html

I changed to Control Surface and my keyboard works now as intented!!! IM SO HAPPY!!! Thanks for all the responses. Learning little by little about arduino.

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