tttapa / MIDI_controller

This is a library for creating a MIDI controller using an Arduino or Teensy board.
GNU General Public License v3.0
404 stars 69 forks source link

Multiplexing 4067 (16channel mux) with arduino leonardo micro pro #77

Closed WORRYL3SS closed 5 years ago

WORRYL3SS commented 5 years ago

I have a issue trying to make a MIDI Controller device with an arduino leonardo micro pro and a HP4067 multiplexer. I have 12 potensionmeters connected on the mux . I can read the pot values throught the multiplexer on the serial monitor . I can't convert these to midi-usb , i have tried a lot of codes online but none worked here is the one i've been trying now :

//Total num of MIDI controls
#define NUM_CONROLS 15

//Num of channels to read directly through analog pins
#define ANALOG_NUM_CHANNELS 0

//Num of channels read through 74HC4051 mux chip
#define MUX_NUM_CHANNELS 15

//Mux output to Arduino analog pin
#define MUX_COM A1

//Mux address select digital pins
#define MUX_ADDRESS_SEL_0 4
#define MUX_ADDRESS_SEL_1 5
#define MUX_ADDRESS_SEL_2 6
#define MUX_ADDRESS_SEL_3 7

//Debug baud rate
#define SERIAL_RATE 9600

//MIDI channel to use
#define MIDI_CHANNEL 0
//CC slots 14-31 are recognized as assignable controls by MIDI standard
#define MIDI_CC_START 14

//maps to map log taper slider pots to linear readings
int sliderFromMap[] = {0, 1023};
int sliderToMap[] = {0, 127};
byte sliderFromMapSize;
byte sliderToMapSize;

//maps to map log taper rotary pots to linear readings
int knobFromMap[] = {0, 55, 130, 516, 1023};
int knobToMap[] = {0, 127};
byte knobFromMapSize;
byte knobToMapSize;

//Holds current MIDI control values
int ccValue[NUM_CONROLS];

//Stores pin numbers of analog channels
byte analogChannelPin[ANALOG_NUM_CHANNELS];

void setup()
{
  Serial.begin(SERIAL_RATE);

  pinMode(MUX_ADDRESS_SEL_0, OUTPUT);
  pinMode(MUX_ADDRESS_SEL_1, OUTPUT);
  pinMode(MUX_ADDRESS_SEL_2, OUTPUT);
  pinMode(MUX_ADDRESS_SEL_3, OUTPUT);

  sliderFromMapSize = sizeof(sliderFromMap) / sizeof(int);
  sliderToMapSize = sizeof(sliderToMap) / sizeof(int);

  knobFromMapSize = sizeof(knobFromMap) / sizeof(int);
  knobToMapSize = sizeof(knobToMap) / sizeof(int);

 /* analogChannelPin[0] = A0;
  analogChannelPin[1] = A1;
  analogChannelPin[2] = A2;
  analogChannelPin[3] = A3;*/
}

void loop()
{
  //Loop through all mux channels
  for (byte muxChannel = 0; muxChannel < MUX_NUM_CHANNELS; ++muxChannel)
  {
    int midiValue = multiMap(readMuxChannel(muxChannel), sliderFromMap, sliderFromMapSize, sliderToMap, sliderToMapSize);

    if (ccValue[muxChannel] != midiValue)
    {
      ccValue[muxChannel] = midiValue;
      midiControlChange(MIDI_CHANNEL, MIDI_CC_START + muxChannel, midiValue);
    }
  }

  /*
  //Loop through all analog channels
  for (byte analogChannel = 0; analogChannel < ANALOG_NUM_CHANNELS; ++analogChannel)
  {
    int analogValue = analogRead(analogChannelPin[analogChannel]);
    int midiValue = 0;

    if (analogChannel == 0)
    {
      //read single remaining slider
      midiValue = multiMap(analogValue, sliderFromMap, sliderFromMapSize, sliderToMap, sliderToMapSize);
    }
    else
    {
      //the rest are rotary pots
      midiValue = multiMap(analogValue, knobFromMap, knobFromMapSize, knobToMap, knobToMapSize);
    }

    if (ccValue[MUX_NUM_CHANNELS + analogChannel] != midiValue)
    {
      ccValue[MUX_NUM_CHANNELS + analogChannel] = midiValue;
      midiControlChange(MIDI_CHANNEL, MIDI_CC_START + MUX_NUM_CHANNELS + analogChannel, midiValue);
    }
  }*/
}

//Reads analog value of mux chips at selected channel
int readMuxChannel(byte channel)
{
  // Select which mux: 0 (on A0) or 1 (on A10)
  bool whichPin = (channel >> 3) & 1;

  //Select mux channel: 0:7
  digitalWrite(MUX_ADDRESS_SEL_0, channel & 1);
  digitalWrite(MUX_ADDRESS_SEL_1, (channel >> 1) & 1);
  digitalWrite(MUX_ADDRESS_SEL_2, (channel >> 2) & 1);
  digitalWrite(MUX_ADDRESS_SEL_2, (channel >> 3) & 1);

  //Read mux output
//  return analogRead(MUX_COM);  // 0 through 7 on A0, 8 through 15 on A10.
}

//Linear interpolates a value in fromMap to toMap
int multiMap(int value, int fromMap[], int fromMapSize, int toMap[], int toMapSize)
{
  //Boundary cases
  if (value <= fromMap[0]) return toMap[0];
  if (value >= fromMap[fromMapSize - 1]) return toMap[toMapSize - 1];

  //Find the fromMap interval that value lies in
  byte fromInterval = 0;
  while (value > fromMap[fromInterval + 1])
    fromInterval++;

  //Find the percentage of the interval that value lies in
  float fromIntervalPercentage = (float)(value - fromMap[fromInterval]) / (fromMap[fromInterval + 1] - fromMap[fromInterval]);

  //Map it to the toMap interval and percentage of that interval
  float toIntervalPercentage = ((fromInterval + fromIntervalPercentage) / (fromMapSize - 1)) * (toMapSize - 1);
  byte toInterval = (byte)toIntervalPercentage;
  toIntervalPercentage = toIntervalPercentage - toInterval;

  //Linear interpolate
  return toMap[toInterval] + toIntervalPercentage * (toMap[toInterval + 1] - toMap[toInterval]);
}

//Sends MIDI CC signal
void midiControlChange(byte channel, byte ccNum, byte value)
{
  //Send a MIDI control change event through USB
  MIDIEvent event = {0x0B, 0xB0 | channel, ccNum, value};
  MIDIUSB.write(event);
  MIDIUSB.flush();
}

The problem with this one is that when i move the sliders , instead of seeing the value being changed , i see the control channel being changed ! Can you help with this one or suggest me another code so i can make it work ?

tttapa commented 5 years ago

Please see this example: https://github.com/tttapa/MIDI_controller/blob/master/examples/Ex.12.AnalogMultiplex/Ex.12.AnalogMultiplex.ino

WORRYL3SS commented 5 years ago

Thank you so much for this one . I still have and issue though , my device is being recognized as a midi device , from the midi monitor but when i move the sliders around nothing happens ,values don't change. Here is the code that you send me to check , changed a bit accordingly to my schematic .

include

// Create an instance of 'AnalogMultiplex' with the output pin of the multiplexer connected to // analog input pin A1 and the address pins connected to pins 4, 5 ,6 and 7 (because my mux is 16 channel). AnalogMultiplex multiplexer(A1, { 4, 5, 6, 7 } );

// Create 12 new instances of the class 'Analog', on the 12 pins of the multiplexer, // that send MIDI messages with controller 7 (channel volume) on channels 1 - 12 Analog potentiometers[] = { {multiplexer.pin(0), MIDI_CC::Channel_Volume, 1}, {multiplexer.pin(1), MIDI_CC::Channel_Volume, 2}, {multiplexer.pin(2), MIDI_CC::Channel_Volume, 3}, {multiplexer.pin(3), MIDI_CC::Channel_Volume, 4}, {multiplexer.pin(4), MIDI_CC::Channel_Volume, 5}, {multiplexer.pin(5), MIDI_CC::Channel_Volume, 6}, {multiplexer.pin(6), MIDI_CC::Channel_Volume, 7}, {multiplexer.pin(7), MIDI_CC::Channel_Volume, 8}, {multiplexer.pin(8), MIDI_CC::Channel_Volume, 9}, {multiplexer.pin(9), MIDI_CC::Channel_Volume, 10}, {multiplexer.pin(10), MIDI_CC::Channel_Volume, 11}, {multiplexer.pin(11), MIDI_CC::Channel_Volume, 12} };

void setup() {}

void loop() { // Refresh the MIDI controller (check whether the potentiometer's input has changed since last time, if so, send the new value over MIDI) MIDI_Controller.refresh(); }

Should I add something more in order to be able to see the values changing ?

tttapa commented 5 years ago

Do you get constant values or no values at all? Is the multiplexer enabled?

llumemergent commented 2 years ago

Hello I need help with the multiplexers, ttapa can you contact me with private please ??