MIDI controller (Arduino UNO) multiple paramenters

Hello. I am working on a project for a MIDI controller and ran into an issue.
I need to assign multiple potentiometer ranges and I am not able to adjust the code accordingly.
I used a code, which worked well for all my needs so far. I am using multiple Multiplexers and now I need to adjust the parameter ranges for multiple potis.
I will have about 5 different ranges to define and I can’t figure out how to change the code.
I will add the parts of the code I think are relevant.

  1. Definition of the Potentiometers on Multiplexers:
    (I belive the comments are the key to my problem)
    //DEFINE POTENTIOMETERS CONNECTED TO MULTIPLEXER****************
    //Pot::Pot(Mux mux, byte muxpin, byte command, byte control, byte channel)
    //Command parameter is for future use

  2. The function for the multiplexer/potentiometers:

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);
    
  }
}

How to change the function, so I can add multiple parameter ranges?

Here some of the defined potis on the multiplexer and I added comments on the ones which have different ranges:

//MULTIPLEXER 2 (1-15)
//LFO
Pot MPO1(M2, 3, 0, 25, 1); //Shape 1 (0-7)
Pot MPO2(M2, 2, 0, 24, 1); //Speed 1
Pot MPO3(M2, 1, 0, 27, 1); //Delay 2
Pot MPO4(M2, 0, 0, 26, 1); //Speed 2
//OSC 1
Pot MPO5(M2, 7, 0, 34, 1); //Shape 1 (0-2)
Pot MPO6(M2, 6, 0, 32, 1); //Semitone 1 (16-112)
Pot MPO7(M2, 5, 0, 33, 1); //Tune 1
Pot MPO8(M2, 4, 0, 35, 1); //Pulse Width 1
//OSC 2
Pot MPO9(M2, 11, 0, 38, 1); //Shape 2 (0-3)
Pot MPO10(M2, 10, 0, 36, 1); //Semitone 2 (16-112)
Pot MPO11(M2, 9, 0, 37, 1); //Tune 2
Pot MPO12(M2, 8, 0, 39, 1); //Pulse Width 2
//OSC 3
Pot MPO13(M2, 14, 0, 44, 1); //Shape 3 (0-2)
Pot MPO14(M2, 13, 0, 42, 1); //Semitone 3 (16-112)
Pot MPO15(M2, 12, 0, 43, 1); //Tune 3

Could you post code using code tags by selecting the code in the IDE, right-click and select “Copy for forum” and paste it here.
hitting the </> code-tags button here on the forum is also starting to work properly,
but omitting them here makes the forum respond to the indentation in your sketch.

byte potmessage = MUXPOTS[i]->getValue();

Depending a little on what you want to do with that value, , you could create an array of struct that holds the information that you think you are going to need.
btw, isn’t the 2nd argument of the sendControlChange() expecting a 7-bit value ?

Thanks @Deva_Rishi for pointing out how to add the code.
It was my first forum post.
Before I am making a mess here, I would like to ask, if It would be appropriate to actually post the entire code here.
The code consists of 3 files, which are ‘Controller.h’, ‘Controller.cpp’ and 'than the file where I fill in the details for my buttons and pots.

If it is ok, to post the entire thing here, I will do that.
I am not fit enough in programming to answer your questions.

So far the code was easy to handle for me, original source ‘Notes & Volts’, but the guy didn’t respond to my questions how to adjust his code for multiple pot parameters.
Right now all pots go from 0 to 127. Some pots need only value 0 - 2, 0 - 3, 0 - 7 or 16 - 112…
As you can see above I only created the list of pots, give them numbers, relate them to the multiplexer and add the CC address. I am making a MIDI controller for the Waldorf Pulse synth and I have the CC documentation, so I know all needed addresses and parameters. Just need to fill them in. So, now I got stuck with the potis which don’t have a 0 - 127 range.
It would be great, if you could provide an example for one additional poti, so I could go ahead and fill in the the other missing ones.
I am able to read most of the code and find my way through, but I am only a musician with some basic programming skills. Your suggestion about adding an array makes sense, but I don’t know how and where in the code.

Of course it is, that is the easiest for us. then we can see the whole thing, and advise you one where to put what. What you want is not hugely complicated (or a lot of work) But guiding you through it without the whole code is. (that’s near impossible really)
Basically what i think you need is the use of the map function.

https://www.arduino.cc/reference/en/language/functions/math/map/
Where the arguments are different for each pot.
we can create a struct with a field for each of the arguments, and create an array with that.

https://playground.arduino.cc/Code/Struct/
Just post your code.

You could try something like this:

#include <Control_Surface.h> // https://github.com/tttapa/Control-Surface

HardwareSerialMIDI_Interface midi = Serial;

CD74HC4067 mux = {
    A0,       // Analog input pin
    {2, 3, 4, 5} // Address pins S0, S1, S2
};

CCPotentiometer lfo_shape_1 { mux.pin(3), {25, CHANNEL_1} }, // (pin, (CC#, channel))
                osc1_shape_1 { mux.pin(7), {34, CHANNEL_1} },
                osc2_shape_1 { mux.pin(11), {38, CHANNEL_1} };

void setup() {
    // Change the ranges of the potentiometers
    lfo_shape_1.map([](analog_t raw)  -> analog_t { return (7 + 1ul) * raw / 128; }); // [0, 7]
    osc1_shape_1.map([](analog_t raw) -> analog_t { return (2 + 1ul) * raw / 128; }); // [0, 2]
    osc2_shape_1.map([](analog_t raw) -> analog_t { return (3 + 1ul) * raw / 128; }); // [0, 3]
    // If you don't explicitly map a potentiometer, the default range is [0, 127]
    Control_Surface.begin();
}

void loop() {
    Control_Surface.loop();
}

It uses the Control Surface library I maintain. See the Getting Started guide for more information.

Edit: change from 8-bit mux to 16-bit mux.

OK. @Deva_Rishi here we go.
And for the motivation a little picture of the beautiful customized Waldorf Pulse.

First the main file:

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

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

  by Notes and Volts
  www.notesandvolts.com

  Version 1.2 
 *************************************************************
  WALDORF PULSE Controller edition by Konstantin Jagoulis 2021
 *************************************************************/

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 = 9;
//---How many potentiometers are connected to a multiplexer?--
byte NUMBER_MUX_POTS = 47;
//************************************************************

//***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(A0, 16, true); //Analog multiplexer on Arduino analog pin A0
Mux M3(A1, 16, true); //Analog multiplexer on Arduino analog pin A1
Mux M4(A2, 16, true); //Analog multiplexer on Arduino analog pin A2
//*******************************************************************


//***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  5=Toggle CC **

Button MBU4(M1, 3, 4, 32, 1, 5);    //2"                        yes
Button MBU3(M1, 2, 3, 32, 1, 5);    //4"                        yes
Button MBU2(M1, 1, 2, 32, 1, 5);    //8"                        yes
Button MBU1(M1, 0, 6, 32, 1, 5);    //16"                       yes

Button MBU8(M1, 7, 5, 40, 1, 5);    //Key Track                 yes
Button MBU7(M1, 6, 3, 36, 1, 5);    //4"                        yes
Button MBU6(M1, 5, 2, 36, 1, 5);    //8"                        yes
Button MBU5(M1, 4, 6, 36, 1, 5);    //16"                       yes

Button MBU9(M1, 8, 5, 41, 1, 5);    //Sync On/Off               yes

//*******************************************************************
////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, &MBU7, &MBU8, &MBU9};
//*******************************************************************


//***DEFINE POTENTIOMETERS CONNECTED TO MULTIPLEXER*******************
//Pot::Pot(Mux mux, byte muxpin, byte command, byte control, byte channel)
//**Command parameter is for future use**
//MULTIPLEXER 2 (1-15)
//LFO
Pot MPO1(M2, 3, 0, 25, 1);       //Shape 1       (0-7)         
Pot MPO2(M2, 2, 0, 24, 1);       //Speed 1                     
Pot MPO3(M2, 1, 0, 27, 1);       //Delay 2                     
Pot MPO4(M2, 0, 0, 26, 1);       //Speed 2                           
//OSC 1
Pot MPO5(M2, 7, 0, 34, 1);       //Shape 1       (0-2)         
Pot MPO6(M2, 6, 0, 32, 1);       //Semitone 1    (16-112)      
Pot MPO7(M2, 5, 0, 33, 1);       //Tune 1                      
Pot MPO8(M2, 4, 0, 35, 1);       //Pulse Width 1               
//OSC 2
Pot MPO9(M2, 11, 0, 38, 1);      //Shape 2       (0-3)         
Pot MPO10(M2, 10, 0, 36, 1);     //Semitone 2    (16-112)      
Pot MPO11(M2, 9, 0, 37, 1);      //Tune 2                      
Pot MPO12(M2, 8, 0, 39, 1);      //Pulse Width 2                     
//OSC 3
Pot MPO13(M2, 14, 0, 44, 1);     //Shape 3       (0-2)         
Pot MPO14(M2, 13, 0, 42, 1);     //Semitone 3    (16-112)      
Pot MPO15(M2, 12, 0, 43, 1);     //Tune 3                      

//MULTIPLEXER 3 (1-16)
//MIX
Pot MPO16(M3, 3, 0, 45, 1);      //OSC 1                       
Pot MPO17(M3, 2, 0, 46, 1);      //OSC 2                       
Pot MPO18(M3, 1, 0, 47, 1);      //OSC 3                       
Pot MPO19(M3, 0, 0, 48, 1);      //NOISE                       
//FILTER
Pot MPO20(M3, 7, 0, 52, 1);      //Envelope 1                  
Pot MPO21(M3, 6, 0, 53, 1);      //Velocity                    
Pot MPO22(M3, 5, 0, 56, 1);      //Resonance                   
Pot MPO23(M3, 4, 0, 50, 107);    //Cutoff                            
//ADSR 1
Pot MPO24(M3, 11, 0, 14, 1);     //A 1                         
Pot MPO25(M3, 10, 0, 15, 1);     //D 1                         
Pot MPO26(M3, 9, 0, 16, 1);      //S 1                         
Pot MPO27(M3, 8, 0, 17, 1);      //R 1                               
//ADSR 2
Pot MPO28(M3, 15, 0, 18, 1);     //A 2                         
Pot MPO29(M3, 14, 0, 19, 1);     //D 2                         
Pot MPO30(M3, 13, 0, 20, 1);     //S 2                               
Pot MPO31(M3, 12, 0, 21, 1);     //R 2                         

//MULTIPLEXER 4 (1-16)
//MOD
Pot MPO32(M4, 3, 0, 54, 1);      //Cutoff Source  (0-15)       
Pot MPO33(M4, 2, 0, 55, 1);      //Cutoff Amount               
Pot MPO34(M4, 1, 0, 60, 108);    //Pitch Source   (0-15)             
Pot MPO35(M4, 0, 0, 61, 1);      //Pitch Amount                
//MATRIX MOD AMMOUNT
Pot MPO36(M4, 7, 0, 109, 1);     //1                           
Pot MPO37(M4, 6, 0, 112, 1);     //2                           
Pot MPO38(M4, 5, 0, 115, 1);     //3                           
Pot MPO39(M4, 4, 0, 118, 1);     //4                           
//ARPEGGIO
Pot MPO40(M4, 11, 0, 102, 1);    //ON, OFF, HOLD  (0-2)        
Pot MPO41(M4, 10, 0, 105, 1);    //Tempo                       
Pot MPO42(M4, 9, 0, 103, 1);     //Range          (0-9)        
Pot MPO43(M4, 8, 0, 106, 1);     //Mode           (0-6)        
//VOLUME
Pot MPO44(M4, 15, 0, 57, 1);     //Volume                      
Pot MPO45(M4, 14, 0, 58, 1);     //Velocity                    
Pot MPO46(M4, 13, 0, 5, 1);      //Portamento Time             
Pot MPO47(M4, 12, 0, 63, 1);     //Bend Range     (0-24)       
//*******************************************************************
//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, &MPO13, &MPO14, &MPO15, &MPO16, &MPO17, &MPO18, &MPO19, &MPO20, &MPO21, &MPO22, &MPO23, &MPO24, &MPO25, &MPO26, &MPO27, &MPO28, &MPO29, &MPO30, &MPO31, &MPO32, &MPO33, &MPO34, &MPO35, &MPO36, &MPO37, &MPO38, &MPO39, &MPO40, &MPO41, &MPO42, &MPO43, &MPO44, &MPO45, &MPO46, &MPO47};
//*******************************************************************


void setup() {
  Serial.begin(9600); //9600 bits per second serial data output
  MIDI.begin(MIDI_CHANNEL_OMNI);
}

void loop() {
  MIDI.read();
  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 6: //CC 16"
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 36, MUXBUTTONS[i]->Bchannel);
          break;
        case 2: //CC 8"
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 48, MUXBUTTONS[i]->Bchannel);
          break;
        case 3: //CC 4"
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 60, MUXBUTTONS[i]->Bchannel);
          break;
        case 4: //CC 2"
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 72, MUXBUTTONS[i]->Bchannel);
          break;          
        case 5: //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);
    
  }
}

Now the Controller.cpp file:


#include "Controller.h"

//****************************************************************************************
Mux::Mux(byte outpin_, byte numPins_, bool analog_)
{
  outpin = outpin_;
  //enablepin = enablepin_;
  numPins = numPins_;
  analog = analog_;
  if (analog == false) pinMode(outpin, INPUT_PULLUP);
  //pinMode(enablepin, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  if (numPins > 8) pinMode(5, OUTPUT);
}
//****************************************************************************************
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
Button::Button(byte pin, byte command, byte value, byte channel, byte debounce)
{
  _pin = pin;
  pinMode(_pin, INPUT_PULLUP);
  _value = value;
  _command = command;
  _debounce = debounce;
  _time = 0;
  _busy = false;
  _status = 0b00000010;
  _last = 1;
  Bcommand = command;
  Bvalue = value;
  Bchannel = channel;
  Btoggle = 0;
}

Button::Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce)
{
  _pin = mux.outpin;
  _numMuxPins = mux.numPins;
  _muxpin = muxpin;
  _value = value;
  _command = command;
  _debounce = debounce;
  _time = 0;
  _busy = false;
  _status = 0b00000010;
  _last = 1;
  Bcommand = command;
  Bvalue = value;
  Bchannel = channel;
  Btoggle = 0;
}

void Button::muxUpdate()
{
  byte temp = _muxpin;
  temp = temp << 2;
  if (_numMuxPins > 8) PORTD = PORTD & B11000011;
  else PORTD = PORTD & B11100011;
  PORTD = PORTD | temp;
}

byte Button::getValue()
{
  // If BUSY bit not set - read button
  if (bitRead(_status, 0) == false) { // If busy false
    if (digitalRead(_pin) == _last) return 2; // If same as last state - exit
  }

  // If NEW Bit set - Key just pressed, record time
  if (bitRead(_status, 1) == true) { // If new is true
    bitSet(_status, 0); // Set busy TRUE
    bitClear(_status, 1); // Set New FALSE
    _time = millis();
    return 255;
  }

  // Check if debounce time has passed - If no, exit
  if (millis() - _time < _debounce) return 255;

  // Debounce time has passed. Read pin to see if still set the same
  // If it has changed back - assume false alarm
  if (digitalRead(_pin) == _last) {
    bitClear(_status, 0); // Set busy false
    bitSet(_status, 1); // Set new true
    return 255;
  }

  // If this point is reached, event is valid. return event type
  else {
    bitClear(_status, 0); // Set busy false
    bitSet(_status, 1); // Set new true
    _last = ((~_last) & 0b00000001); // invert _last
    return _last;
  }
}

void Button::newValue(byte command, byte value, byte channel)
{
  Bvalue = value;
  Bcommand = command;
  Bchannel = channel;
}

//********************************************************************
Pot::Pot(byte pin, byte command, byte control, byte channel)
{
  _pin = pin;
  _control = control;
  _value = analogRead(_pin);
  _value = _value >> 3;
  _oldValue = _value << 3;
  _value = _value << 3;
  Pcommand = command;
  Pcontrol = control;
  Pchannel = channel;
}

void Pot::muxUpdate()
{
  byte temp = _muxpin;
  temp = temp << 2;
  if (_numMuxPins > 8) PORTD = PORTD & B11000011;
  else PORTD = PORTD & B11100011;
  //PORTD = PORTD & B11000011;
  PORTD = PORTD | temp;
}

Pot::Pot(Mux mux, byte muxpin, byte command, byte control, byte channel)
{
  _pin = mux.outpin;
  _numMuxPins = mux.numPins;
  _muxpin = muxpin;
  _control = control;
  muxUpdate();
  _value = analogRead(_pin);
  _value = _value >> 3;
  _oldValue = _value << 3;
  _value = _value << 3;
  Pcommand = command;
  Pcontrol = control;
  Pchannel = channel;
}

byte Pot::getValue()
{
  _value = analogRead(_pin);
  int tmp = (_oldValue - _value);
  if (tmp >= 8 || tmp <= -8) {
    _oldValue = _value >> 3;
    _oldValue = _oldValue << 3;
    return _value >> 3;
  }
  return 255;
}

void Pot::newValue(byte command, byte value, byte channel) {
  Pcommand = command;
  Pcontrol = value;
  Pchannel = channel;
}

And finally the Controller.h file:

#ifndef Controller_h
#define Controller_h

#include <Arduino.h>

//***********************************************************************
class Mux
{
  public:
    Mux(byte outpin_, byte numPins_, bool analog_);
    byte outpin;
    byte numPins;
    bool analog;
};
//************************************************************************
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
class Button
{
  public:
    Button(byte pin, byte command, byte value, byte channel, byte debounce);
    Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce);
    byte getValue();
    void muxUpdate();
    void newValue(byte command, byte value, byte channel);
    byte Bcommand;
    byte Bvalue;
    byte Bchannel;
    byte Btoggle;

  private:
    byte _previous;
    byte _current;
    unsigned long _time;
    int _debounce;
    byte _pin;
    byte _muxpin;
    byte _numMuxPins;
    byte _value;
    byte _command;
    bool _busy;
    byte _status;
    byte _last;
    byte _enablepin;
};
//*************************************************************************
class Pot
{
  public:
    Pot(byte pin, byte command, byte control, byte channel);
    Pot(Mux mux, byte muxpin ,byte command, byte control, byte channel);
    void muxUpdate();
    void newValue(byte command, byte value, byte channel);
    byte getValue();
    byte Pcommand;
    byte Pcontrol;
    byte Pchannel;

  private:
    byte _pin;
    byte _muxpin;
    byte _numMuxPins;
    byte _control;
    int _value;
    int _oldValue;
    bool _changed;
    byte _enablepin;
};
//*************************************************************************
#endif

Thanks @PieterP

I will also wait for the reply of @Deva_Rishi and see how I am getting through this.

I do understand the code snippet you sent and I will need to figure out how to implement such a code example in the existing code without causing total code chaos.

Hopefully you guys are patient with me :wink:

As you can see on the photo, the beauty is just waiting to play.
All the rest is working already fine. The parameter variations for the potis is the last thing left to do.

Add a range member variable to the Pot class (and add initializers for it in the constructors). In the Pot::getValue() method, multiply the value by (range + 1) and divide the result by (127 + 1).

What Pieter is suggesting is the most appropriate way, though i would simply use the map() function for that.
in controller.h

class Pot
{
  public:
    Pot(byte pin, byte command, byte control, byte channel, byte min, byte max);
    Pot(Mux mux, byte muxpin ,byte command, byte control, byte channel, byte min, byte max);

(....)

  private:
    byte _min;
    byte _max;
    byte _pin;
    byte _muxpin;
(....

then in the controller.cpp

Pot::Pot(byte pin, byte command, byte control, byte channel, byte min, byte max)
{
  _min = min;
  _max = max;
  _pin = pin;
  _control = control;
(....)
Pot::Pot(Mux mux, byte muxpin, byte command, byte control, byte channel, byte min, byte max)
{
  _min = min;
  _max = max;
  _pin = mux.outpin;
  _numMuxPins = mux.numPins;
(....)
byte Pot::getValue()
{
  _value = analogRead(_pin);
  int tmp = (_oldValue - _value);
  if (tmp >= 8 || tmp <= -8) {
    _oldValue = _value >> 3;
    _oldValue = _oldValue << 3;
    return map( _value >> 3, 0, 127, _min, _max);
  }
  return 255;
}

should do the trick, that is you will have to add the min and max values to all you pot definitions in your main file

Pot MPO1(M2, 3, 0, 25, 1, 0, 127);       //Shape 1       (0-7)         
Pot MPO2(M2, 2, 0, 24, 1, 127, 0);       //Speed 1     this should invert it's function.

A way of doing it which is much more of a patch-fix is to do it here in the main file with the returned value

void updatePots() {
  for (int i = 0; i < NUMBER_POTS; i = i + 1) {
    byte potmessage = POTS[i]->getValue();
(....)
void updateMuxPots() {
  for (int i = 0; i < NUMBER_MUX_POTS; i = i + 1) {
    MUXPOTS[i]->muxUpdate();
    byte potmessage = MUXPOTS[i]->getValue();

Create separate arrays to hold the min & max values for each pot, and simply use

byte message = map(message, 0, 127, muxmin[i], muxmax[i]);

not as pretty, but works the same way and easier to get right.
I may have made some typos (and other mistakes), and i have only indicated where the new lines should come, but i think you get the gist.

I have done all the edits in the .cpp and .h file and updated all pots with the new parameters.
The very last bit is what I don’t get.
Is that an alternative way of doing it or do I need to add some code at the code at these places?

I clicked on ‘Verify’ in the Arduino programming environment and received the following Error Message and only one line was marked red:
Screenshot 2021-04-22 at 15.15.12

Arduino: 1.8.13 (Mac OS X), Board: "Arduino Mega or Mega 2560, ATmega2560 (Mega 2560)"

sketch/Controller.cpp: In constructor ‘Pot::Pot(byte, byte, byte, byte, byte, byte)’:
Controller.cpp:109:3: error: ‘_min’ was not declared in this scope
** _min = min;**
** ^~**
sketch/Controller.cpp:109:3: note: suggested alternative: '_pin’
** _min = min;**
** ^
~**
** _pin**
Controller.cpp:110:3: error: ‘_max’ was not declared in this scope
** _max = max;**
** ^~**
sketch/Controller.cpp:110:3: note: suggested alternative: 'fmax’
** _max = max;**
** ^
~**
** fmax**
sketch/Controller.cpp: In constructor ‘Pot::Pot(Mux, byte, byte, byte, byte, byte, byte)’:
Controller.cpp:134:3: error: ‘_min’ was not declared in this scope
** _min = min;**
** ^~**
sketch/Controller.cpp:134:3: note: suggested alternative: '_pin’
** _min = min;**
** ^
~**
** _pin**
Controller.cpp:135:3: error: ‘_max’ was not declared in this scope
** _max = max;**
** ^~**
sketch/Controller.cpp:135:3: note: suggested alternative: 'fmax’
** _max = max;**
** ^
~**
** fmax**
sketch/Controller.cpp: In member function ‘byte Pot::getValue()’:
Controller.cpp:157:38: error: ‘_min’ was not declared in this scope
** return map( _value >> 3, 0, 127, _min, _max);**
** ^~**
sketch/Controller.cpp:157:38: note: suggested alternative: '_pin’
** return map( _value >> 3, 0, 127, _min, _max);**
** ^
~**
** _pin**
Controller.cpp:157:44: error: ‘_max’ was not declared in this scope
** return map( _value >> 3, 0, 127, _min, _max);**
** ^~**
sketch/Controller.cpp:157:44: note: suggested alternative: 'fmax’
** return map( _value >> 3, 0, 127, _min, _max);**
** ^
~**
** fmax**
sketch/Controller.cpp: At global scope:
Controller.cpp:162:6: error: prototype for ‘void Pot::newValue(byte, byte, byte, byte, byte)’ does not match any in class 'Pot’
** void Pot::newValue(byte command, byte value, byte channel, byte min, byte max) {**
** ^**
In file included from sketch/Controller.cpp:2:0:
Controller.h:54:10: error: candidate is: void Pot::newValue(byte, byte, byte)
** void newValue(byte command, byte value, byte channel);**
** ^
~~~~~**
Multiple libraries were found for "MIDI.h"
** Used: /Users/eule/Documents/Arduino/libraries/MIDI_Library-5.0.2**
** Not used: /Users/eule/Documents/Arduino/libraries/arduino_midi_library-master**
exit status 1
’_min’ was not declared in this scope

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

Yes that would be an alternative way of doing it. Don’t combine them !

As for at least 1 of the error messages i can show that you made a mistake

 void Pot::newValue(byte command, byte value, byte channel, byte min, byte max) {

i didn’t tell you to add them there, still that was the downside to not creating the full sketch for myself within the IDE. Hang on while i do that.

No it compiles for me, you’ve made mistakes. My files now look like this :

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

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

  by Notes and Volts
  www.notesandvolts.com

  Version 1.2 
 *************************************************************
  WALDORF PULSE Controller edition by Konstantin Jagoulis 2021
 *************************************************************/

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 = 9;
//---How many potentiometers are connected to a multiplexer?--
byte NUMBER_MUX_POTS = 47;
//************************************************************

//***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(A0, 16, true); //Analog multiplexer on Arduino analog pin A0
Mux M3(A1, 16, true); //Analog multiplexer on Arduino analog pin A1
Mux M4(A2, 16, true); //Analog multiplexer on Arduino analog pin A2
//*******************************************************************


//***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  5=Toggle CC **

Button MBU4(M1, 3, 4, 32, 1, 5);    //2"                        yes
Button MBU3(M1, 2, 3, 32, 1, 5);    //4"                        yes
Button MBU2(M1, 1, 2, 32, 1, 5);    //8"                        yes
Button MBU1(M1, 0, 6, 32, 1, 5);    //16"                       yes

Button MBU8(M1, 7, 5, 40, 1, 5);    //Key Track                 yes
Button MBU7(M1, 6, 3, 36, 1, 5);    //4"                        yes
Button MBU6(M1, 5, 2, 36, 1, 5);    //8"                        yes
Button MBU5(M1, 4, 6, 36, 1, 5);    //16"                       yes

Button MBU9(M1, 8, 5, 41, 1, 5);    //Sync On/Off               yes

//*******************************************************************
////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, &MBU7, &MBU8, &MBU9};
//*******************************************************************


//***DEFINE POTENTIOMETERS CONNECTED TO MULTIPLEXER*******************
//Pot::Pot(Mux mux, byte muxpin, byte command, byte control, byte channel)
//**Command parameter is for future use**
//MULTIPLEXER 2 (1-15)
//LFO
Pot MPO1(M2, 3, 0, 25, 1, 0, 127);       //Shape 1       (0-7)         
Pot MPO2(M2, 2, 0, 24, 1, 0, 127);       //Speed 1                     
Pot MPO3(M2, 1, 0, 27, 1, 0, 127);       //Delay 2                     
Pot MPO4(M2, 0, 0, 26, 1, 0, 127);       //Speed 2                           
//OSC 1
Pot MPO5(M2, 7, 0, 34, 1, 0, 127);       //Shape 1       (0-2)         
Pot MPO6(M2, 6, 0, 32, 1, 0, 127);       //Semitone 1    (16-112)      
Pot MPO7(M2, 5, 0, 33, 1, 0, 127);       //Tune 1                      
Pot MPO8(M2, 4, 0, 35, 1, 0, 127);       //Pulse Width 1               
//OSC 2
Pot MPO9(M2, 11, 0, 38, 1, 0, 127);      //Shape 2       (0-3)         
Pot MPO10(M2, 10, 0, 36, 1, 0, 127);     //Semitone 2    (16-112)      
Pot MPO11(M2, 9, 0, 37, 1, 0, 127);      //Tune 2                      
Pot MPO12(M2, 8, 0, 39, 1, 0, 127);      //Pulse Width 2                     
//OSC 3
Pot MPO13(M2, 14, 0, 44, 1, 0, 127);     //Shape 3       (0-2)         
Pot MPO14(M2, 13, 0, 42, 1, 0, 127);     //Semitone 3    (16-112)      
Pot MPO15(M2, 12, 0, 43, 1, 0, 127);     //Tune 3                      

//MULTIPLEXER 3 (1-16)
//MIX
Pot MPO16(M3, 3, 0, 45, 1, 0, 127);      //OSC 1                       
Pot MPO17(M3, 2, 0, 46, 1, 0, 127);      //OSC 2                       
Pot MPO18(M3, 1, 0, 47, 1, 0, 127);      //OSC 3                       
Pot MPO19(M3, 0, 0, 48, 1, 0, 127);      //NOISE                       
//FILTER
Pot MPO20(M3, 7, 0, 52, 1, 0, 127);      //Envelope 1                  
Pot MPO21(M3, 6, 0, 53, 1, 0, 127);      //Velocity                    
Pot MPO22(M3, 5, 0, 56, 1, 0, 127);      //Resonance                   
Pot MPO23(M3, 4, 0, 50, 107, 0, 127);    //Cutoff                            
//ADSR 1
Pot MPO24(M3, 11, 0, 14, 1, 0, 127);     //A 1                         
Pot MPO25(M3, 10, 0, 15, 1, 0, 127);     //D 1                         
Pot MPO26(M3, 9, 0, 16, 1, 0, 127);      //S 1                         
Pot MPO27(M3, 8, 0, 17, 1, 0, 127);      //R 1                               
//ADSR 2
Pot MPO28(M3, 15, 0, 18, 1, 0, 127);     //A 2                         
Pot MPO29(M3, 14, 0, 19, 1, 0, 127);     //D 2                         
Pot MPO30(M3, 13, 0, 20, 1, 0, 127);     //S 2                               
Pot MPO31(M3, 12, 0, 21, 1, 0, 127);     //R 2                         

//MULTIPLEXER 4 (1-16)
//MOD
Pot MPO32(M4, 3, 0, 54, 1, 0, 127);      //Cutoff Source  (0-15)       
Pot MPO33(M4, 2, 0, 55, 1, 0, 127);      //Cutoff Amount               
Pot MPO34(M4, 1, 0, 60, 108, 0, 127);    //Pitch Source   (0-15)             
Pot MPO35(M4, 0, 0, 61, 1, 0, 127);      //Pitch Amount                
//MATRIX MOD AMMOUNT
Pot MPO36(M4, 7, 0, 109, 1, 0, 127);     //1                           
Pot MPO37(M4, 6, 0, 112, 1, 0, 127);     //2                           
Pot MPO38(M4, 5, 0, 115, 1, 0, 127);     //3                           
Pot MPO39(M4, 4, 0, 118, 1, 0, 127);     //4                           
//ARPEGGIO
Pot MPO40(M4, 11, 0, 102, 1, 0, 127);    //ON, OFF, HOLD  (0-2)        
Pot MPO41(M4, 10, 0, 105, 1, 0, 127);    //Tempo                       
Pot MPO42(M4, 9, 0, 103, 1, 0, 127);     //Range          (0-9)        
Pot MPO43(M4, 8, 0, 106, 1, 0, 127);     //Mode           (0-6)        
//VOLUME
Pot MPO44(M4, 15, 0, 57, 1, 0, 127);     //Volume                      
Pot MPO45(M4, 14, 0, 58, 1, 0, 127);     //Velocity                    
Pot MPO46(M4, 13, 0, 5, 1, 0, 127);      //Portamento Time             
Pot MPO47(M4, 12, 0, 63, 1, 0, 127);     //Bend Range     (0-24)       
//*******************************************************************
//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, &MPO13, &MPO14, &MPO15, &MPO16, &MPO17, &MPO18, &MPO19, &MPO20, &MPO21, &MPO22, &MPO23, &MPO24, &MPO25, &MPO26, &MPO27, &MPO28, &MPO29, &MPO30, &MPO31, &MPO32, &MPO33, &MPO34, &MPO35, &MPO36, &MPO37, &MPO38, &MPO39, &MPO40, &MPO41, &MPO42, &MPO43, &MPO44, &MPO45, &MPO46, &MPO47};
//*******************************************************************


void setup() {
  Serial.begin(9600); //9600 bits per second serial data output
  MIDI.begin(MIDI_CHANNEL_OMNI);
}

void loop() {
  MIDI.read();
  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 6: //CC 16"
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 36, MUXBUTTONS[i]->Bchannel);
          break;
        case 2: //CC 8"
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 48, MUXBUTTONS[i]->Bchannel);
          break;
        case 3: //CC 4"
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 60, MUXBUTTONS[i]->Bchannel);
          break;
        case 4: //CC 2"
          MIDI.sendControlChange(MUXBUTTONS[i]->Bvalue, 72, MUXBUTTONS[i]->Bchannel);
          break;          
        case 5: //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);
    
  }
}

Controller.cpp :

#include "Controller.h"

//****************************************************************************************
Mux::Mux(byte outpin_, byte numPins_, bool analog_)
{
  outpin = outpin_;
  //enablepin = enablepin_;
  numPins = numPins_;
  analog = analog_;
  if (analog == false) pinMode(outpin, INPUT_PULLUP);
  //pinMode(enablepin, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  if (numPins > 8) pinMode(5, OUTPUT);
}
//****************************************************************************************
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
Button::Button(byte pin, byte command, byte value, byte channel, byte debounce)
{
  _pin = pin;
  pinMode(_pin, INPUT_PULLUP);
  _value = value;
  _command = command;
  _debounce = debounce;
  _time = 0;
  _busy = false;
  _status = 0b00000010;
  _last = 1;
  Bcommand = command;
  Bvalue = value;
  Bchannel = channel;
  Btoggle = 0;
}

Button::Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce)
{
  _pin = mux.outpin;
  _numMuxPins = mux.numPins;
  _muxpin = muxpin;
  _value = value;
  _command = command;
  _debounce = debounce;
  _time = 0;
  _busy = false;
  _status = 0b00000010;
  _last = 1;
  Bcommand = command;
  Bvalue = value;
  Bchannel = channel;
  Btoggle = 0;
}

void Button::muxUpdate()
{
  byte temp = _muxpin;
  temp = temp << 2;
  if (_numMuxPins > 8) PORTD = PORTD & B11000011;
  else PORTD = PORTD & B11100011;
  PORTD = PORTD | temp;
}

byte Button::getValue()
{
  // If BUSY bit not set - read button
  if (bitRead(_status, 0) == false) { // If busy false
    if (digitalRead(_pin) == _last) return 2; // If same as last state - exit
  }

  // If NEW Bit set - Key just pressed, record time
  if (bitRead(_status, 1) == true) { // If new is true
    bitSet(_status, 0); // Set busy TRUE
    bitClear(_status, 1); // Set New FALSE
    _time = millis();
    return 255;
  }

  // Check if debounce time has passed - If no, exit
  if (millis() - _time < _debounce) return 255;

  // Debounce time has passed. Read pin to see if still set the same
  // If it has changed back - assume false alarm
  if (digitalRead(_pin) == _last) {
    bitClear(_status, 0); // Set busy false
    bitSet(_status, 1); // Set new true
    return 255;
  }

  // If this point is reached, event is valid. return event type
  else {
    bitClear(_status, 0); // Set busy false
    bitSet(_status, 1); // Set new true
    _last = ((~_last) & 0b00000001); // invert _last
    return _last;
  }
}

void Button::newValue(byte command, byte value, byte channel)
{
  Bvalue = value;
  Bcommand = command;
  Bchannel = channel;
}

//********************************************************************
Pot::Pot(byte pin, byte command, byte control, byte channel, byte min, byte max)
{
  _min = min;
  _max = max;
  _pin = pin;
  _control = control;
  _value = analogRead(_pin);
  _value = _value >> 3;
  _oldValue = _value << 3;
  _value = _value << 3;
  Pcommand = command;
  Pcontrol = control;
  Pchannel = channel;
}

void Pot::muxUpdate()
{
  byte temp = _muxpin;
  temp = temp << 2;
  if (_numMuxPins > 8) PORTD = PORTD & B11000011;
  else PORTD = PORTD & B11100011;
  //PORTD = PORTD & B11000011;
  PORTD = PORTD | temp;
}

Pot::Pot(Mux mux, byte muxpin, byte command, byte control, byte channel, byte min, byte max)
{
  _min = min;
  _max = max;
  _pin = mux.outpin;
  _numMuxPins = mux.numPins;
  _muxpin = muxpin;
  _control = control;
  muxUpdate();
  _value = analogRead(_pin);
  _value = _value >> 3;
  _oldValue = _value << 3;
  _value = _value << 3;
  Pcommand = command;
  Pcontrol = control;
  Pchannel = channel;
}

byte Pot::getValue()
{
  _value = analogRead(_pin);
  int tmp = (_oldValue - _value);
  if (tmp >= 8 || tmp <= -8) {
    _oldValue = _value >> 3;
    _oldValue = _oldValue << 3;
    return map( _value >> 3, 0, 127, _min, _max);;
  }
  return 255;
}

void Pot::newValue(byte command, byte value, byte channel) {
  Pcommand = command;
  Pcontrol = value;
  Pchannel = channel;
}

Controller.h :

#ifndef Controller_h
#define Controller_h

#include <Arduino.h>

//***********************************************************************
class Mux
{
  public:
    Mux(byte outpin_, byte numPins_, bool analog_);
    byte outpin;
    byte numPins;
    bool analog;
};
//************************************************************************
//Button (Pin Number, Command, Note Number, Channel, Debounce Time)
class Button
{
  public:
    Button(byte pin, byte command, byte value, byte channel, byte debounce);
    Button(Mux mux, byte muxpin, byte command, byte value, byte channel, byte debounce);
    byte getValue();
    void muxUpdate();
    void newValue(byte command, byte value, byte channel);
    byte Bcommand;
    byte Bvalue;
    byte Bchannel;
    byte Btoggle;

  private:
    byte _previous;
    byte _current;
    unsigned long _time;
    int _debounce;
    byte _pin;
    byte _muxpin;
    byte _numMuxPins;
    byte _value;
    byte _command;
    bool _busy;
    byte _status;
    byte _last;
    byte _enablepin;
};
//*************************************************************************
class Pot
{
  public:
    Pot(byte pin, byte command, byte control, byte channel, byte min, byte max);
    Pot(Mux mux, byte muxpin ,byte command, byte control, byte channel, byte min, byte max);
    void muxUpdate();
    void newValue(byte command, byte value, byte channel);
    byte getValue();
    byte Pcommand;
    byte Pcontrol;
    byte Pchannel;

  private:
    byte _min;
    byte _max;
    byte _pin;
    byte _muxpin;
    byte _numMuxPins;
    byte _control;
    int _value;
    int _oldValue;
    bool _changed;
    byte _enablepin;
};
//*************************************************************************
#endif
1 Like

You guys are awesome !!!

It works perfectly now. I will do some finishing work and will post a little video of the Waldorf in action. :wink:
You made my day guys. What a great asset to have such a forum with programmers helping each other. I would have had a lot of try and error till solving this issue.

Thank You!

1 Like

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