Midi controller values incorrect when starting up axoloti


#1

Hello, I've connected a midi controller to my axoloti using the 5pin midi input pins but when I start up the axoloti the values of each knob on the controller are all incorrect....

If I fiddle with each knob (there are 12) they immediately correct themselves right away but it's a huge pain in the butt...especially annoying if the settings were recently set to something I liked..

Is there any way to configure the axoloti to read the values of the midi controller on startup automatically?


#2

Hey,
What midi controller is it you are using?


#3

A diy arduino one
here's a link to the code if you think it might be at fault...
https://drive.google.com/file/d/0BwnVMB_6yujwR1dydVJ6MHJib2M/view


#4

I can't tell you what is wrong with your code. Your first initialization could b triggered from your midi device. A loadbang first shoots a message to Midi telling it to send all cc values at once.
Another way would be looking into presets.
I'm sure there are better solutions.


#5

There's no way for Axoloti to know the position of a controller plugged into DIN5 unless you send the current state from the controller to the Axoloti.


#6

Ahh so I need to change the code of my midi controller so it sends the values of each potentiometers when it starts up...hmm


#7

How do I do a loadbang?


#8

@rbrt has a loadbang in his repository. It works just like it works in pure data.
It emits a pulse/ trigger as soon as the patch starts. You take that to initialize all values that your midi controller currently has. You can send the trigger to a cc and your midi script execute a block of code (send all current cc values). With that you initialise the midi cc to to the board every time you restart the patch. Anyone could correct me if I'm wrong.

Good luck.


#9

i looked at the arduino code briefly, can you post your actual code? i think you posted the sketch you started with. there are no buttons or pots defined in this code (everything is set to zero)

however it should be a simple matter of moving those lines:


if (NUMBER_BUTTONS != 0) updateButtons();
if (NUMBER_POTS != 0) updatePots();
if (NUMBER_MUX_BUTTONS != 0) updateMuxButtons();
if (NUMBER_MUX_POTS != 0) updateMuxPots();

into the setup function like so:


void setup() {
MIDI.begin(MIDI_CHANNEL_OFF);
if (NUMBER_BUTTONS != 0) updateButtons();
if (NUMBER_POTS != 0) updatePots();
if (NUMBER_MUX_BUTTONS != 0) updateMuxButtons();
if (NUMBER_MUX_POTS != 0) updateMuxPots();
}


#10

Here's what my code ended up looking like in the end

#include <MIDI.h>
#include "Controller.h"

/*************************************************************
  MIDI CONTROLLER

  by Notes and Volts
  www.notesandvolts.com

  Version 1.2 **Arduino UNO ONLY!**
 *************************************************************/

MIDI_CREATE_DEFAULT_INSTANCE();

//************************************************************
//***SET THE NUMBER OF CONTROLS USED**************************
//************************************************************
//---How many buttons are connected directly to pins?---------
byte NUMBER_BUTTONS = 0;
//---How many potentiometers are connected directly to pins?--
byte NUMBER_POTS = 0;
//---How many buttons are connected to a multiplexer?---------
byte NUMBER_MUX_BUTTONS = 6;
//---How many potentiometers are connected to a multiplexer?--
byte NUMBER_MUX_POTS = 12;
//************************************************************

//***ANY MULTIPLEXERS? (74HC4067)************************************
//MUX address pins must be connected to Arduino UNO pins 2,3,4,5
//A0 = PIN2, A1 = PIN3, A2 = PIN4, A3 = PIN5
//*******************************************************************
//Mux NAME (OUTPUT PIN, , How Many Mux Pins?(8 or 16) , Is It Analog?);


Mux M1(10, 16, false); //Digital multiplexer on Arduino pin 10
Mux M2(A5, 16, true); //Analog multiplexer on Arduino analog pin A0
//*******************************************************************


//***DEFINE DIRECTLY CONNECTED POTENTIOMETERS************************
//Pot (Pin Number, Command, CC Control, Channel Number)
//**Command parameter is for future use**

//Pot PO1(A0, 0, 1, 1);
//Pot PO2(A1, 0, 10, 1);
//Pot PO3(A2, 0, 22, 1);
//Pot PO4(A3, 0, 118, 1);
//Pot PO5(A4, 0, 30, 1);
//Pot PO6(A5, 0, 31, 1);
//*******************************************************************
//Add pots used to array below like this->  Pot *POTS[] {&PO1, &PO2, &PO3, &PO4, &PO5, &PO6};
Pot *POTS[] {};
//*******************************************************************


//***DEFINE DIRECTLY CONNECTED BUTTONS*******************************
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

//Button BU1(2, 0, 60, 1, 5 );
//Button BU2(3, 0, 61, 1, 5 );
//Button BU3(4, 0, 62, 1, 5 );
//Button BU4(5, 0, 63, 1, 5 );
//Button BU5(6, 0, 64, 1, 5 );
//Button BU6(7, 0, 65, 1, 5 );
//Button BU7(8, 1, 64, 1, 5 );
//Button BU8(9, 2, 64, 1, 5 );
//*******************************************************************
//Add buttons used to array below like this->  Button *BUTTONS[] {&BU1, &BU2, &BU3, &BU4, &BU5, &BU6, &BU7, &BU8};
Button *BUTTONS[] {};
//*******************************************************************


//***DEFINE BUTTONS CONNECTED TO MULTIPLEXER*************************
//Button::Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce)
//** Command parameter 0=NOTE  1=CC  2=Toggle CC **

Button MBU1(M1, 0, 0, 70, 1, 5);
Button MBU2(M1, 1, 1, 71, 1, 5);
Button MBU3(M1, 2, 2, 72, 1, 5);
Button MBU4(M1, 3, 0, 73, 1, 5);
Button MBU5(M1, 4, 0, 74, 1, 5);
Button MBU6(M1, 5, 0, 75, 1, 5);
//Button MBU7(M1, 6, 0, 76, 1, 5);
//Button MBU8(M1, 7, 0, 77, 1, 5);
//Button MBU9(M1, 8, 0, 78, 1, 5);
//Button MBU10(M1, 9, 0, 79, 1, 5);
//Button MBU11(M1, 10, 0, 80, 1, 5);
//Button MBU12(M1, 11, 0, 81, 1, 5);
//Button MBU13(M1, 12, 0, 82, 1, 5);
//Button MBU14(M1, 13, 0, 83, 1, 5);
//Button MBU15(M1, 14, 0, 84, 1, 5);
//Button MBU16(M1, 15, 0, 85, 1, 5);
//*******************************************************************
////Add multiplexed buttons used to array below like this->  Button *MUXBUTTONS[] {&MBU1, &MBU2, &MBU3, &MBU4, &MBU5, &MBU6.....};
Button *MUXBUTTONS[] {&MBU1, &MBU2, &MBU3, &MBU4, &MBU5, &MBU6};

//*******************************************************************


//***DEFINE POTENTIOMETERS CONNECTED TO MULTIPLEXER*******************
//Pot::Pot(Mux mux, byte muxpin, byte command, byte control, byte channel)
//**Command parameter is for future use**

Pot MPO1(M2, 0, 0, 100, 1);
Pot MPO2(M2, 1, 0, 101, 1);
Pot MPO3(M2, 2, 0, 102, 1);
Pot MPO4(M2, 3, 0, 103, 1);
Pot MPO5(M2, 4, 0, 104, 1);
Pot MPO6(M2, 5, 0, 105, 1);
Pot MPO7(M2, 6, 0, 106, 1);
Pot MPO8(M2, 7, 0, 107, 1);
Pot MPO9(M2, 8, 0, 108, 1);
Pot MPO10(M2, 9, 0, 109, 1);
Pot MPO11(M2, 10, 0, 110, 1);
Pot MPO12(M2, 11, 0, 111, 1);
//Pot MPO13(M2, 12, 0, 50, 1);
//Pot MPO14(M2, 13, 0, 55, 2);
//Pot MPO15(M2, 14, 0, 50, 1);
//Pot MPO16(M2, 15, 0, 55, 2);
//*******************************************************************
//Add multiplexed pots used to array below like this->  Pot *MUXPOTS[] {&MPO1, &MPO2, &MPO3, &MPO4, &MPO5, &MPO6.....};
Pot *MUXPOTS[] {&MPO1, &MPO2, &MPO3, &MPO4, &MPO5, &MPO6, &MPO7, &MPO8, &MPO9, &MPO10, &MPO11, &MPO12};
//*******************************************************************


void setup() {
  MIDI.begin(MIDI_CHANNEL_OFF);
}

void loop() {
  if (NUMBER_BUTTONS != 0) updateButtons();
  if (NUMBER_POTS != 0) updatePots();
  if (NUMBER_MUX_BUTTONS != 0) updateMuxButtons();
  if (NUMBER_MUX_POTS != 0) updateMuxPots();
}


//*****************************************************************
void updateButtons() {

  // Cycle through Button array
  for (int i = 0; i < NUMBER_BUTTONS; i = i + 1) {
    byte message = BUTTONS[i]->getValue();

    //  Button is pressed
    if (message == 0) {
      switch (BUTTONS[i]->Bcommand) {
        case 0: //Note
          MIDI.sendNoteOn(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
          break;
        case 1: //CC
          MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
          break;
        case 2: //Toggle
          if (BUTTONS[i]->Btoggle == 0) {
            MIDI.sendControlChange(BUTTONS[i]->Bvalue, 127, BUTTONS[i]->Bchannel);
            BUTTONS[i]->Btoggle = 1;
          }
          else if (BUTTONS[i]->Btoggle == 1) {
            MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
            BUTTONS[i]->Btoggle = 0;
          }
          break;
      }
    }

    //  Button is not pressed
    if (message == 1) {
      switch (BUTTONS[i]->Bcommand) {
        case 0:
          MIDI.sendNoteOff(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
          break;
        case 1:
          MIDI.sendControlChange(BUTTONS[i]->Bvalue, 0, BUTTONS[i]->Bchannel);
          break;
      }
    }
  }
}
//*******************************************************************
void updateMuxButtons() {

  // Cycle through Mux Button array
  for (int i = 0; i < NUMBER_MUX_BUTTONS; i = i + 1) {

    MUXBUTTONS[i]->muxUpdate();
    byte message = MUXBUTTONS[i]->getValue();

    //  Button is pressed
    if (message == 0) {
      switch (MUXBUTTONS[i]->Bcommand) {
        case 0: //Note
          MIDI.sendNoteOn(MUXBUTTONS[i]->Bvalue, 127, MUXBUTTONS[i]->Bchannel);
          break;
        case 1: //CC
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 127, MUXBUTTONS[i]->Bchannel);
          break;
        case 2: //Toggle
          if (MUXBUTTONS[i]->Btoggle == 0) {
            MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 127, MUXBUTTONS[i]->Bchannel);
            MUXBUTTONS[i]->Btoggle = 1;
          }
          else if (MUXBUTTONS[i]->Btoggle == 1) {
            MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 0, MUXBUTTONS[i]->Bchannel);
            MUXBUTTONS[i]->Btoggle = 0;
          }
          break;
      }
    }
    //  Button is not pressed
    if (message == 1) {
      switch (MUXBUTTONS[i]->Bcommand) {
        case 0:
          MIDI.sendNoteOff(MUXBUTTONS[i]->Bvalue, 0, MUXBUTTONS[i]->Bchannel);
          break;
        case 1:
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 0, MUXBUTTONS[i]->Bchannel);
          break;
      }
    }
  }
}
//***********************************************************************
void updatePots() {
  for (int i = 0; i < NUMBER_POTS; i = i + 1) {
    byte potmessage = POTS[i]->getValue();
    if (potmessage != 255) MIDI.sendControlChange(POTS[i]->Pcontrol, potmessage, POTS[i]->Pchannel);
  }
}
//***********************************************************************
void updateMuxPots() {
  for (int i = 0; i < NUMBER_MUX_POTS; i = i + 1) {
    MUXPOTS[i]->muxUpdate();
    byte potmessage = MUXPOTS[i]->getValue();
    if (potmessage != 255) MIDI.sendControlChange(MUXPOTS[i]->Pcontrol, potmessage, MUXPOTS[i]->Pchannel);
  }
}

#11

ok, have you tried my suggestion of copying the code into the setup part? (but leave the code in the loop untouched)


#12

Just tried it now. First I tried moving the lines by cutting the "if" lines of code and pasting them into the setup function but doing that resulted in the controller not working at all...I then tried copying and pasting the "if" lines into the setup function instead and the controller worked but did not send the values on start up...I also tried both of these options with and without the loadbang object but had the same results either way. Blarrg :frowning:


#13

ok, well definitely leave it in the loop, or it will not run after setup (as you found out)

had another look at the code, the problem is, that it only sends midi out, when the pots are turned (otherwise it would send midi messages all the time)

you basically have to write additional functions that make sure the pots are read on init (even though they did not move)

what about the switches? are those toggles or momentary switches? what do you change with them?

but let's first take care of the pots:

add these lines to the very end of the arduino sketch:

void updateMuxPotsInit() {
  for (int i = 0; i < NUMBER_MUX_POTS; i = i + 1) {
    MUXPOTS[i]->muxUpdate();
    byte potmessage = MUXPOTS[i]->getValueInit();
    if (potmessage != 255) MIDI.sendControlChange(MUXPOTS[i]->Pcontrol, potmessage, MUXPOTS[i]->Pchannel);
  }

}

the void setup() should look like this:

void setup() {
  MIDI.begin(MIDI_CHANNEL_OFF);
  if (NUMBER_MUX_POTS != 0) updateMuxPotsInit();
}

then also add this function to the Controller.cpp file (after line 156):

byte Pot::getValueInit()
{
  _value = analogRead(_pin);
    return _value >> 3;
}

and add to Controller.h, after line 53:

byte getValueInit();

that should/could do it.

unfortunately i cannot test this, but let me know if it works :slight_smile:


#14

Sweeeeet, I'll give this a shot asap. Hopefully tomorrow morning!

I have a bunch of switches I'm using right now. I'll be using them to turn various things on/off as well as switching between thing (like choosing between trip,saw,square waveforms) ......I'm guessing they need to be toggle switches that turn on midi cc notes...when those notes are active/inactive I can set up my patch to toggle things on/off

Edit for clarification: the switches I'm using are all toggle switches.


#15

how are you planing on switching more then two states with a toggle switch? or more precisely, how do you expect to sync the controller and the axoloti in that regard on startup? because the switch has only two states, there is no way for the arduino to know which waveform should be choosen on the axoloti on startup. unless you move the whole switching logic to the arduino and send a different value of the same cc message for each waveform:

sine: cc20 value 1
tri: cc20 value 2 etc.

but then you will have to save the state of the switch in eeprom on the arduino, and recall it on boot up. you will also need some kind of display for the buttons (leds or similar) otherwise you will not be able to see which waveform you have selected.

all in all, maybe it would be easier to use a rotary switch for the waveform choosing, you will need additional digital ins, but i think you have them available on the uno or your multiplexer.


#16

I'm using a rotary switch but in the Arduino code the mode would be set to toggle...or would that have to be set to momentary?


#17

And for the other switches to switch between say two different options I'm just using spdt switches with the + in on the middle pole and the others go to resistors going to ground/a digital multiplexer that sends it's signals to the Arduino pin number 10... also for things that are on/off, rather than using resistors im using leds.


#18

alrighty, tried it out, didnt work but on start up but the controller still functions. I wish I knew how to code, I seem to understand the problem, that the controlleris waiting for the value for the pot to change before it would send the first value to the controller axoloti. I guess the solution would be to have it get current values of the pots on startup and send them to the controller, then begin its loop where it sends midi notes when changed...


#19

ok, well the problem is at least twofold:

1) the controller has to send all the pot positions on startup (of the controller) so that the axoloti patch matches the pot positions
2) the controller has to be powered on after the axoloti (and the patch is loaded) so that the axoloti is ready to receive all this midi info and adjust the patch accordingly.

since midi is a one way protocol, there is no way for your controller to know when the axoloti is ready...

for 1)

at this point please check if the arduino sends midi on startup by connecting it to a pc and a midi monitoring program.

for 2)

i don't know about this in your setup, so leave that uncommented


#20

you would need multiple inputs for one rotary switch (or one analog input and some resistors)