Inverting midi range with analog read expression pedal

Status
Not open for further replies.

Aussie_CrocHunter

Well-known member
Hi, I'm adding an expression pedal port to me midistomp pedal so I've done a little test sketch based on an analog pot example sketch. I know some expression pedals are inverted, some have a polarity switch, and some don't.

Two questions:
1. Is there are better way to write this code? (don't want it to be too messy)
2. Can you show me how to make a user-editable 'virtual polarity switch' which will invert the midi range so it would read 127 to 0 OR 0 to 127 ?

Thank you :)

Code:
#include <Bounce.h>

// the MIDI channel number to send messages
const int channel = 1;

// the MIDI continuous controller for each analog input
const int controllerA10 = 98;


void setup() {
}
// store previously sent values, to detect changes
int previousA0 = -1;

elapsedMillis msec = 0;

void loop() {
  // only check the analog inputs 50 times per second,
  // to prevent a flood of MIDI messages
  if (msec >= 20) {
    msec = 0;
    int n0 = analogRead(A10) / 8;
    // only transmit MIDI messages if analog input changed
    if (n0 != previousA0) {
      usbMIDI.sendControlChange(controllerA10, n0, channel);
      previousA0 = n0;
    }
  }
  
  while (usbMIDI.read()) {
    // ignore incoming messages
  }
}
 
Your variable names puzzle me, is it on A10 or A1? Do you care in the code?

Other than that it's passable MIDI code well written by my amature standards. You may occasionally find your code still chattering at your max rare between two adjacent values due to noise and rounding but as you do have it time limited it should be fine.
 
I did notice some chattering. I thought maybe it was my cheap pot, but it is brand new.
How would I fix that? And can I invert the range?
 
How to invert the pedal polarity:

analogRead returns 0-1023 , right?

uninverted = analogRead(A10) / 8;
inverted = (1023- analogRead(A10)) / 8;
 
If you leave the pot near a threshold between two rounding points in the 12 bit data then even modest noise will cause alternation between two midi values.

A better approach is to write the raw value to your lagged varable and compare that with the current raw reading and if the (absolute value of the) difference is greater than some threshold then reduce to seven bit and update the CC value. You can likely use a shorter, or even no ellapsed minimum.

Search 'hysteresis'

The ResponsiveAnalogRead library does a great job of taming pot signals without needing to handle all the details. It's used extensively in midi projects here.

Invert as last step:

ccInv = 127 - cc

...but only to save dividing by 8 twice.
 
The analog section of my original midi project uses a mostly usable moving deadband hysteresis system
Code:
//************ANALOG SECTION**************
void getAnalogData(){
  v0 = analogRead(0);
  if (v0D > thrshld) // if delta variable from last pass shows change past threshold - recalulate
  {
    usbMIDI.sendControlChange(cc0, v0/8, chnl); // calculate D2 and send
    v0L = v0; // lag only on update
  }
  v0D = abs(v0L-v0);
}

The last line is key... the size of the change between the raw value and its lagged reading (from when the last midi was sent) is stored on one pass to test on the next.

The limits are set at update but changes are tracked at every pass (there is no time based limits on midi updates which can allow flooding midi queues with data.

Search for ResponsiveAnalogRead library if you don't want to roll your own hysteresis method.

To allow the for toggled directionality you can use a linear equation. In one setting the x intercept is zero and the slope 1 and in the other the intercept is 127 and the slope is minus one. In both the output can be calculated:

CCOut = m * CC + b .

So you just set the m and b parameters based on the selected polarity.

Increasing

m=1 b=0

Decreasing

m=-1 b=127
 
Re ResponsiveAnalogRead

Hello all, thanks oddson for much useful code.

Its weird how often you find other working on the same coding problem at the same time.

Anyway I am interfacing a couple of expression pedals (M-audio Ex-P ) and

a)still had some chattering.
b)contending with the usual pot problems of them not quite getting to zero or maximum value.

As I just needed a workable solution so I can concentrate on another project this worked for me.

Code:
ResponsiveAnalogRead analogZero(A0, true);


//in setup
    analogZero.setActivityThreshold(25);  //tried various values but this worked ok for me
//in the update
    analogZero.update();
    adcValue = analogZero.getValue();
    valX = (map(adcValue, 60, 980, 0, 127));
    valX = constrain(valX, 0, 127);
The map values were 60 for pedal at its lowest and 980 for pedal at maximum.

Though sometimes the pedal managed to get down to 50.

Hence map sometimes would return -ve numbers, constrain makes sure we dont go below zero.

Yes its (very) clunky but its giving me sensible non jittery values.

Hope this helps someone.

regards
 
Thanks for your help. The mapping 0-127 and constraining would be very helpful for my project as I'm expecting people to use different types/brands of expression pedals which all respond slightly differently and show different CC ranges with just a simple analogread > CC arrangement.

I've tried combining these myself with the code I'm using but it's no use. I don't really know what I'm doing.

Here's the main code I'm using for testing:
Code:
/* 
Many Buttons and Knobs with CC toggle buttons

   You must select MIDI from the "Tools > USB Type" menu

   This example code is in the public domain.
*/


//************LIBRARIES USED**************
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
// include the Bounce library for 'de-bouncing' switches -- removing electrical chatter as contacts settle
#include <Bounce.h> 
//usbMIDI.h library is added automatically when code is compiled as a MIDI device

// ******CONSTANT VALUES******** 
// customize code behaviour here!
const int channel = 1; // MIDI channel
const int A_PINS = 1; // number of Analog PINS

// define the pins you want to use and the CC ID numbers on which to send them..
const int ANALOG_PINS[A_PINS] = {A10};
const int CCID[A_PINS] = {98};

//******VARIABLES***********
// a data array and a lagged copy to tell when MIDI changes are required
byte data[A_PINS];
byte dataLag[A_PINS]; // when lag and new are not the same then update MIDI CC value

// initialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead analog[]{
  {ANALOG_PINS[0],true},
}; 

//************SETUP**************
void setup() {
  
}

//************LOOP**************
void loop() {
  getAnalogData();
 // getDigitalData();
  while (usbMIDI.read()) {
     // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}

//************ANALOG SECTION**************
void getAnalogData(){  
  for (int i=0;i<A_PINS;i++){
    // update the ResponsiveAnalogRead object every loop
    analog[i].update(); 
    // if the repsonsive value has change, print out 'changed'
    if(analog[i].hasChanged()) {
      data[i] = analog[i].getValue()>>3;
      if (data[i] != dataLag[i]){
        dataLag[i] = data[i];
        usbMIDI.sendControlChange(CCID[i], data[i], channel);
      }
    }
  }
}

The code works, but it's too jittery and doesn't work with full 0-127 range for my pedal. If

Code:
//in setup
    analogZero.setActivityThreshold(25);  //tried various values but this worked ok for me
//in the update
    analogZero.update();
    adcValue = analogZero.getValue();
    valX = (map(adcValue, 60, 980, 0, 127));
    valX = constrain(valX, 0, 127);
these parts could be added it would help greatly! I tested the threshold thing and it works really well to keep the values less jittery, but then the mapping and constraing needs to be added.

Can someone please help me combine the two?
cheers
 
Last edited:
A few tips:-

Ground any pot metalwork. Fairly straightforward in a non-conductive housing. In a metal housing you need to be mindful of any potential ground loops in your grounding strategy.

A 10 nF cap from respective Analog pin to ground. Then 4.7k resistor from A pin to wiper of 10k pot with said resistor and Cap physically as close as possible to the A pin.

If using a multiplexer, the 10nF cap and 4.7k need to be on the input of the mux. Don't put caps on it's output.

Some pot supply rail bypass can be helpful. Say 150 Ohm resistor from board V+ to pot V+. Then 100nF bypass from pot V+ to ground. In thinking on it, possibly the best place to ground both of these caps is the AnalogGND pin if your board has one.

If your project has noisy digital stuff like displays, Midi in optocoupler or whatever then try to keep analog and digital wiring separate and at 90 degrees.

Hope there's something useful to play with.
 
Thanks for your help. The mapping 0-127 and constraining would be very helpful for my project as I'm expecting people to use different types/brands of expression pedals which all respond slightly differently and show different CC ranges with just a simple analogread > CC arrangement.

I've tried combining these myself with the code I'm using but it's no use. I don't really know what I'm doing.

Here's the main code I'm using for testing:
Code:
/* 
Many Buttons and Knobs with CC toggle buttons

   You must select MIDI from the "Tools > USB Type" menu

   This example code is in the public domain.
*/


//************LIBRARIES USED**************
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
// include the Bounce library for 'de-bouncing' switches -- removing electrical chatter as contacts settle
#include <Bounce.h> 
//usbMIDI.h library is added automatically when code is compiled as a MIDI device

// ******CONSTANT VALUES******** 
// customize code behaviour here!
const int channel = 1; // MIDI channel
const int A_PINS = 1; // number of Analog PINS

// define the pins you want to use and the CC ID numbers on which to send them..
const int ANALOG_PINS[A_PINS] = {A10};
const int CCID[A_PINS] = {98};

//******VARIABLES***********
// a data array and a lagged copy to tell when MIDI changes are required
byte data[A_PINS];
byte dataLag[A_PINS]; // when lag and new are not the same then update MIDI CC value

// initialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead analog[]{
  {ANALOG_PINS[0],true},
}; 

//************SETUP**************
void setup() {
  
}

//************LOOP**************
void loop() {
  getAnalogData();
 // getDigitalData();
  while (usbMIDI.read()) {
     // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}

//************ANALOG SECTION**************
void getAnalogData(){  
  for (int i=0;i<A_PINS;i++){
    // update the ResponsiveAnalogRead object every loop
    analog[i].update(); 
    // if the repsonsive value has change, print out 'changed'
    if(analog[i].hasChanged()) {
      data[i] = analog[i].getValue()>>3;
      if (data[i] != dataLag[i]){
        dataLag[i] = data[i];
        usbMIDI.sendControlChange(CCID[i], data[i], channel);
      }
    }
  }
}

The code works, but it's too jittery and doesn't work with full 0-127 range for my pedal. If

Code:
//in setup
    analogZero.setActivityThreshold(25);  //tried various values but this worked ok for me
//in the update
    analogZero.update();
    adcValue = analogZero.getValue();
    valX = (map(adcValue, 60, 980, 0, 127));
    valX = constrain(valX, 0, 127);
these parts could be added it would help greatly! I tested the threshold thing and it works really well to keep the values less jittery, but then the mapping and constraing needs to be added.

Can someone please help me combine the two?
cheers


Does this help, Ive changed a couple of things I use a0 rather than 10, put the responsiveness hack I used in and tried it here and it seems to work.

I was getting confused by some of the variable naming so there may be a glaring error in here but no-doubt if there is someone will spot it.

let me know how you get on or if what I did doesnt make sense :)




Code:
*
  Many Buttons and Knobs with CC toggle buttons

   You must select MIDI from the "Tools > USB Type" menu

   This example code is in the public domain.

   hacky mods to help  Aussie_CrocHunter jont<at>ninelocks.com January 2020

*/


//************LIBRARIES USED**************
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
// include the Bounce library for 'de-bouncing' switches -- removing electrical chatter as contacts settle
#include <Bounce.h>
//usbMIDI.h library is added automatically when code is compiled as a MIDI device

// ******CONSTANT VALUES********
// customize code behaviour here!
const int channel = 1; // MIDI channel
const int NUM_SLIDERS = 1; // number of Analog PINS

// define the pins you want to use and the CC ID numbers on which to send them..
const int ANALOG_PINS[NUM_SLIDERS] = {A0};  //for my test module
const int CCID[NUM_SLIDERS] = {98};

//******VARIABLES***********
// a data array and a lagged copy to tell when MIDI changes are required
byte data[NUM_SLIDERS];
byte dataLag[NUM_SLIDERS]; // when lag and new are not the same then update MIDI CC value

// initialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead analog[NUM_SLIDERS] {
  ResponsiveAnalogRead(ANALOG_PINS[0], true),
};

//************SETUP**************
void setup() {
  // init the thresholds for the ResponsiveAnalogeRead objects
  for (int n = 0; n < NUM_SLIDERS; n++) {
    analog[n].setActivityThreshold(25);
  }

}

//************LOOP**************
void loop() {
  getAnalogData();
  // getDigitalData();
  while (usbMIDI.read()) {
    // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}

//************ANALOG SECTION**************

void getAnalogData() {
  int valX;
  int adcValue = 0;
  for (int i = 0; i < NUM_SLIDERS; i++) {
    // update the ResponsiveAnalogRead object every loop
    analog[i].update();
    // if the repsonsive value has change, print out 'changed'
    if (analog[i].hasChanged()) {

      //jons hacky mod start
      adcValue = analog[i].getValue();
      valX = (map(adcValue, 60, 980, 0, 127));
      valX = constrain(valX, 0, 127);

      data[i] = valX;
//jons hacky mod end
      
      if (data[i] != dataLag[i]) {
        dataLag[i] = data[i];
        usbMIDI.sendControlChange(CCID[i], data[i], channel);
      }
    }
  }
}
 
Hey @AussieCrochunter from another Aussie. Here's the code from my Pedalboard. Note that each pedal has individual map.

Code:
// MatrixRat's Teensy LC USB Midi 5-Pedal board.
// Board type = Teensy LC, USB Type Serial+Midi.
// Four pedals were hacked out of discarded organs and use a light source and LDR.
// Incandescent lamps were removed and replaced with ultra bright yellow LEDs.
// The fifth also came out of an organ, had a well worn out 90 Degree large pot.
// The guts out of an old Waa Waa pedal was transplanted into that one.
#include <ResponsiveAnalogRead.h>
const int channel = 1;                              // MIDI channel
const int A_PINS = 5;                               // number of Analog PINS
const int ANALOG_PINS[A_PINS] = {A2,A3,A6, A8, A9}; //Analog Pins used
const int CCID[A_PINS] =                {1,     2,    4,   11,    7  };  // CC numbers for respective pedals.
const uint16_t INPUT_MINIMUM[A_PINS]  = {90,    8,    8,   44,    50 };  // These four arrays contain
const uint16_t INPUT_MAXIMUM[A_PINS]  = {1022,  1018, 940, 956,   650};  // parameters used in map() function
const uint16_t OUTPUT_MINIMUM[A_PINS] = {0,     0,    0,   0,     0  };  // per Pedal element. 
const uint16_t OUTPUT_MAXIMUM[A_PINS] = {127,   127,  127, 127,   127};  //
//******VARIABLES***********
//uint16_t readValue[A_PINS];
uint16_t data[A_PINS];
uint16_t dataLag[A_PINS]; // when lag and new are not the same then update MIDI CC value

ResponsiveAnalogRead analog[]{
  {ANALOG_PINS[0],true},
  {ANALOG_PINS[1],true},
  {ANALOG_PINS[2],true},
  {ANALOG_PINS[3],true},
  {ANALOG_PINS[4],true},
}; 


//************SETUP**************
void setup() {
 // Serial.begin (38400);
}

//************LOOP**************
void loop() {
  getAnalogData();
  while (usbMIDI.read()) {
     // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}


//************ANALOG SECTION**************
void getAnalogData(){  
  for (int i=0;i<A_PINS;i++){
    // update the ResponsiveAnalogRead object every loop
    analog[i].update(); 
          
          // if the repsonsive value has change, print out 'changed'
          if(analog[i].hasChanged()) {
              
              data[i]=(analog[i].getValue());
              uint16_t temp=data[i];
              data[i]=constrain(data[i],INPUT_MINIMUM[i],INPUT_MAXIMUM[i]);
              data[i] = map(data[i],INPUT_MINIMUM[i],INPUT_MAXIMUM[i],OUTPUT_MINIMUM[i],OUTPUT_MAXIMUM[i]);
                    
                    if (data[i] != dataLag[i]){
                    dataLag[i] = data[i];

                          usbMIDI.sendControlChange(CCID[i], data[i], channel);
                         // Serial.print data[i];
                          //Serial.println();

                                              }
                                     }
                            }
                      }
To reverse the action, Swap the values like so for CCID 1
Code:
const int CCID[A_PINS] =                {1,     2,    4,   11,    7  };  // CC numbers for respective pedals.
const uint16_t INPUT_MINIMUM[A_PINS]  = {1022,    8,    8,   44,    50 };  // These four arrays contain
const uint16_t INPUT_MAXIMUM[A_PINS]  = {90,  1018, 940, 956,   650};  // parameters used in map() function
const uint16_t OUTPUT_MINIMUM[A_PINS] = {0,     0,    0,   0,     0  };  // per Pedal element. 
const uint16_t OUTPUT_MAXIMUM[A_PINS] = {127,   127,  127, 127,   127};  //

Hope this is useful.
 
Sundry observations... not an EE and prone to blunders so I may have any number of things wrong here.

The m audio issue is likely due to the wiring not being a simple cross of Vcc and GND. I believe it's the wiper and upper leg that are crossed by the polarity switch. If the polarity switch is in the correct position and the floor knob is zeroed then you should be able to sweep near enough rail to rail.

Attention to detail in the wiring is likely more benificial than adding filtering.

Adding a resistor in series on either side of a mux would make it much slower to read correctly.

If you are going to filter in analog you'd best make it with a very low cutoff if your intent us to remove signal other than the nearly static voltage level since it will largely be mains hum and its harmonics.

The ResponsiveAnalogRead library is usually sufficient to remove noise for 7 bit midi just with stock settings but with custom settings it should be able to tame any reasonable signal.
 
Last edited:
Sundry observations... not an EE and prone to blunders so I may have any number of things wrong here.

The m audio issue is likely due to the wiring not being a simple cross of Vcc and GND. I believe it's the wiper and upper leg that are crossed by the polarity switch. If the polarity switch is in the correct position and the floor knob is zeroed then you should be able to sweep near enough rail to rail.

.
Thats interesting,

I'd done most of the dev work using a normal pot and havent put the maudios into full time use. But I did notice that the polarity switch was doing something odd, when I metered the plug.
Sadly no sign of a circuit online anywhere so far , I shall dismantle/document/report back later.
 
re: the M-Audio EX-P

The article linked below mentions:
Note that some manufacturers choose TIP for the measurement and RING for the reference voltage, and others do the exact opposite. You can measure the resistance with a multi-meter between RING/SLEEVE and TIP/SLEEVE while moving the pedal to figure it out. Only one of those two will measure a resistance that changes as the pedal moves.


Anyway, for this application, just leave the switch in the OTHER position, and set the limit knob to the full anti-clockwise position to yield the full range. The resistance ring-to-sleeve varies from about 1K to about 11k as the pedal is moved.

If you need the resistance to get all the way to 0, rewire the pedal with the limit pot removed.

http://blackaddr.com/expression-pedal-repair-and-mod/
 
I could not find a semantic for it online and mine is elsewhere but I recall the ground is the sleave in both.

An ohm reading across the tip and sleave while you move the pedal will tell you if ts the wiper or not. Flip the polarity switch and you should be able to see which is which.

If hot and ground were reversed the polarity switch would leave the reading at the total resistance of the pot (/ resistor network).

I think there is a resistor in series on the wiper that is forming part of the bottom leg of a voltage divider so the polarity can't cause the pot to fully short the hot and ground. I think this would produce the observed behaviour.
 
To me (with my engineers hat on), the only sensible place for a ground is the sleeve. Thats mostly why I want to take a double check inside :)

A bit of me thinks best place for the top of the pot (and the connection to the supply rail) is on the tip, so that if someone decides to plug a mono jack in your dont short down the supply.
(though on mine I do the feed to the pot via a small resistor to protect from that).

These may be of use/interest to someone

https://www.soundonsound.com/forum/viewtopic.php?f=35&t=800
https://missionengineering.com/understanding-expression-pedals/
 
Update: I examined my EX-P a bit more closely, and found a schematic online (which only shows the circuit in the OTHER position).
4129065822_4afb4d41ba_o.png

So - with the limit pot at minimum, it's effectively out of circuit.
It's the 1K resistor on the wiper which causes the values to never reach 0.
 
Update: I examined my EX-P a bit more closely, and found a schematic online (which only shows the circuit in the OTHER position).
View attachment 18665

So - with the limit pot at minimum, it's effectively out of circuit.
It's the 1K resistor on the wiper which causes the values to never reach 0.

much appreciated , had taken mine to bits to have a quick look as well :)
 
To me (with my engineers hat on), the only sensible place for a ground is the sleeve. ...
My engineer's hat is blue and white striped and has a brim and a puffy top.. choo woooo…

But even I know the ground belongs on the sleeve (even if I don't know how to spell it).

...Re: on one of the original topics... I did make a MIDI guitar pick that needed to be configured as the slide-thumb-joystick I used is limited in its range. So I made it self-configuring:
https://forum.pjrc.com/threads/43143-Self-calibrating-scaled-output-MIDI-Guitar-Pick-project
 
Does this help, Ive changed a couple of things I use a0 rather than 10, put the responsiveness hack I used in and tried it here and it seems to work.

I was getting confused by some of the variable naming so there may be a glaring error in here but no-doubt if there is someone will spot it.

let me know how you get on or if what I did doesnt make sense :)




Code:
*
  Many Buttons and Knobs with CC toggle buttons

   You must select MIDI from the "Tools > USB Type" menu

   This example code is in the public domain.

   hacky mods to help  Aussie_CrocHunter jont<at>ninelocks.com January 2020

*/


//************LIBRARIES USED**************
// include the ResponsiveAnalogRead library for analog smoothing
#include <ResponsiveAnalogRead.h>
// include the Bounce library for 'de-bouncing' switches -- removing electrical chatter as contacts settle
#include <Bounce.h>
//usbMIDI.h library is added automatically when code is compiled as a MIDI device

// ******CONSTANT VALUES********
// customize code behaviour here!
const int channel = 1; // MIDI channel
const int NUM_SLIDERS = 1; // number of Analog PINS

// define the pins you want to use and the CC ID numbers on which to send them..
const int ANALOG_PINS[NUM_SLIDERS] = {A0};  //for my test module
const int CCID[NUM_SLIDERS] = {98};

//******VARIABLES***********
// a data array and a lagged copy to tell when MIDI changes are required
byte data[NUM_SLIDERS];
byte dataLag[NUM_SLIDERS]; // when lag and new are not the same then update MIDI CC value

// initialize the ReponsiveAnalogRead objects
ResponsiveAnalogRead analog[NUM_SLIDERS] {
  ResponsiveAnalogRead(ANALOG_PINS[0], true),
};

//************SETUP**************
void setup() {
  // init the thresholds for the ResponsiveAnalogeRead objects
  for (int n = 0; n < NUM_SLIDERS; n++) {
    analog[n].setActivityThreshold(25);
  }

}

//************LOOP**************
void loop() {
  getAnalogData();
  // getDigitalData();
  while (usbMIDI.read()) {
    // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}

//************ANALOG SECTION**************

void getAnalogData() {
  int valX;
  int adcValue = 0;
  for (int i = 0; i < NUM_SLIDERS; i++) {
    // update the ResponsiveAnalogRead object every loop
    analog[i].update();
    // if the repsonsive value has change, print out 'changed'
    if (analog[i].hasChanged()) {

      //jons hacky mod start
      adcValue = analog[i].getValue();
      valX = (map(adcValue, 60, 980, 0, 127));
      valX = constrain(valX, 0, 127);

      data[i] = valX;
//jons hacky mod end
      
      if (data[i] != dataLag[i]) {
        dataLag[i] = data[i];
        usbMIDI.sendControlChange(CCID[i], data[i], channel);
      }
    }
  }
}
Perfect! Works beautifully thank you! No chatter and I can change the parameters to get full range :) fantastic
 
Hey @AussieCrochunter from another Aussie. Here's the code from my Pedalboard. Note that each pedal has individual map.

Code:
// MatrixRat's Teensy LC USB Midi 5-Pedal board.
// Board type = Teensy LC, USB Type Serial+Midi.
// Four pedals were hacked out of discarded organs and use a light source and LDR.
// Incandescent lamps were removed and replaced with ultra bright yellow LEDs.
// The fifth also came out of an organ, had a well worn out 90 Degree large pot.
// The guts out of an old Waa Waa pedal was transplanted into that one.
#include <ResponsiveAnalogRead.h>
const int channel = 1;                              // MIDI channel
const int A_PINS = 5;                               // number of Analog PINS
const int ANALOG_PINS[A_PINS] = {A2,A3,A6, A8, A9}; //Analog Pins used
const int CCID[A_PINS] =                {1,     2,    4,   11,    7  };  // CC numbers for respective pedals.
const uint16_t INPUT_MINIMUM[A_PINS]  = {90,    8,    8,   44,    50 };  // These four arrays contain
const uint16_t INPUT_MAXIMUM[A_PINS]  = {1022,  1018, 940, 956,   650};  // parameters used in map() function
const uint16_t OUTPUT_MINIMUM[A_PINS] = {0,     0,    0,   0,     0  };  // per Pedal element. 
const uint16_t OUTPUT_MAXIMUM[A_PINS] = {127,   127,  127, 127,   127};  //
//******VARIABLES***********
//uint16_t readValue[A_PINS];
uint16_t data[A_PINS];
uint16_t dataLag[A_PINS]; // when lag and new are not the same then update MIDI CC value

ResponsiveAnalogRead analog[]{
  {ANALOG_PINS[0],true},
  {ANALOG_PINS[1],true},
  {ANALOG_PINS[2],true},
  {ANALOG_PINS[3],true},
  {ANALOG_PINS[4],true},
}; 


//************SETUP**************
void setup() {
 // Serial.begin (38400);
}

//************LOOP**************
void loop() {
  getAnalogData();
  while (usbMIDI.read()) {
     // controllers must call .read() to keep the queue clear even if they are not responding to MIDI
  }
}


//************ANALOG SECTION**************
void getAnalogData(){  
  for (int i=0;i<A_PINS;i++){
    // update the ResponsiveAnalogRead object every loop
    analog[i].update(); 
          
          // if the repsonsive value has change, print out 'changed'
          if(analog[i].hasChanged()) {
              
              data[i]=(analog[i].getValue());
              uint16_t temp=data[i];
              data[i]=constrain(data[i],INPUT_MINIMUM[i],INPUT_MAXIMUM[i]);
              data[i] = map(data[i],INPUT_MINIMUM[i],INPUT_MAXIMUM[i],OUTPUT_MINIMUM[i],OUTPUT_MAXIMUM[i]);
                    
                    if (data[i] != dataLag[i]){
                    dataLag[i] = data[i];

                          usbMIDI.sendControlChange(CCID[i], data[i], channel);
                         // Serial.print data[i];
                          //Serial.println();

                                              }
                                     }
                            }
                      }
To reverse the action, Swap the values like so for CCID 1
Code:
const int CCID[A_PINS] =                {1,     2,    4,   11,    7  };  // CC numbers for respective pedals.
const uint16_t INPUT_MINIMUM[A_PINS]  = {1022,    8,    8,   44,    50 };  // These four arrays contain
const uint16_t INPUT_MAXIMUM[A_PINS]  = {90,  1018, 940, 956,   650};  // parameters used in map() function
const uint16_t OUTPUT_MINIMUM[A_PINS] = {0,     0,    0,   0,     0  };  // per Pedal element. 
const uint16_t OUTPUT_MAXIMUM[A_PINS] = {127,   127,  127, 127,   127};  //

Hope this is useful.

Thanks heaps! I'll be trying this out too :)
 
Status
Not open for further replies.
Back
Top