how to add 2 more pot to this code

Status
Not open for further replies.

edrummer

Well-known member
This is for a midi controller that has 3 buttons and 1 pot. I simply want to add 2 more pots and keep the rest of the code intact. I want to add more later but to learn and understand, if someone could just show me how I could add 2 more pots. I'd be grateful. I have 3 pots connected to A0, A1 and A2. The buttons and 1 pot work, I just need to adjust the code for 2 more pots.
HTML:
#include <Bounce.h>

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

Bounce button0 = Bounce(0, 5);
Bounce button1 = Bounce(1, 5);
Bounce button2 = Bounce(2, 5); 

byte current_value_1; 
byte previous_value_1; 

void setup() {
  analogReadResolution(7); // set the analog read resolution to 7 bits (a range of 0 - 127)
  analogReadAveraging(32); // average the analog value by averaging 16 readings
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  
 }

void loop() {
  button0.update();
  button1.update();
  button2.update();
  
  current_value_1 = analogRead(0); 
  
  if (button0.fallingEdge()) {
    usbMIDI.sendNoteOn(60, 99, channel);  // 60 = C4
  }
  if (button1.fallingEdge()) {
    usbMIDI.sendNoteOn(61, 99, channel);  // 61 = C#4
  }
  if (button2.fallingEdge()) {
    usbMIDI.sendNoteOn(62, 99, channel);  // 61 = C#4
  }
  
  if (button0.risingEdge()) {
    usbMIDI.sendNoteOff(60, 0, channel);  // 60 = C4
  }
  if (button1.risingEdge()) {
    usbMIDI.sendNoteOff(61, 0, channel);  // 61 = C#4
  }
  if (button2.risingEdge()) {
    usbMIDI.sendNoteOff(62, 0, channel);  // 61 = C#4
  }
  if(current_value_1 != previous_value_1) {
    previous_value_1 = current_value_1;
    usbMIDI.sendControlChange(1, current_value_1, 1); // send continuous controller message
  }

 
}
 
Code:
#include <Bounce.h>

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

Bounce button0 = Bounce(0, 5);
Bounce button1 = Bounce(1, 5);
Bounce button2 = Bounce(2, 5); 

byte current_value_1; 
byte previous_value_1;
[COLOR="#FF0000"]byte current_value_2; 
byte previous_value_2; 
byte current_value_3; 
byte previous_value_3; [/COLOR]

void setup() {
  analogReadResolution(7); // set the analog read resolution to 7 bits (a range of 0 - 127)
  analogReadAveraging(32); // average the analog value by averaging 16 readings
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  
 }

void loop() {
  button0.update();
  button1.update();
  button2.update();
  
  current_value_1 = analogRead([COLOR="#FF0000"]A[/COLOR]0); 
[COLOR="#FF0000"]  current_value_2 = analogRead(A1); 
  current_value_3 = analogRead(A2);  
  [/COLOR]
  if (button0.fallingEdge()) {
    usbMIDI.sendNoteOn(60, 99, channel);  // 60 = C4
  }
  if (button1.fallingEdge()) {
    usbMIDI.sendNoteOn(61, 99, channel);  // 61 = C#4
  }
  if (button2.fallingEdge()) {
    usbMIDI.sendNoteOn(62, 99, channel);  // 61 = C#4
  }
  
  if (button0.risingEdge()) {
    usbMIDI.sendNoteOff(60, 0, channel);  // 60 = C4
  }
  if (button1.risingEdge()) {
    usbMIDI.sendNoteOff(61, 0, channel);  // 61 = C#4
  }
  if (button2.risingEdge()) {
    usbMIDI.sendNoteOff(62, 0, channel);  // 62 = D4
  }
  if(current_value_1 != previous_value_1) {
    previous_value_1 = current_value_1;
    usbMIDI.sendControlChange(1, current_value_1, 1); // send continuous controller message
  }
  [COLOR="#FF0000"]if(current_value_2 != previous_value_2) {
    previous_value_2 = current_value_2;
    usbMIDI.sendControlChange(2, current_value_1, 1); // send continuous controller message
  }
  if(current_value_3 != previous_value_3) {
    previous_value_3 = current_value_3;
    usbMIDI.sendControlChange(3, current_value_1, 1); // send continuous controller message
  }[/COLOR]

 
}
warning -
untested... not even compiled.... might have a typo or minor error yet.


This extends the code to cover pins from A0 to A2 and the CC numbers from 1 to 3. But you don't need to use those PINs or (especially) those CC numbers. You can put any value between 0 and 127 in the first value of the .sendControlChange() call.

(It's arguably clearer to put A0 rather than 0 as some think that will point a digital pin 0 even though it knows to use the analog pin sequence instead)

I've not tried to manage analog signals with just analogReadAveraging() so I don't know how good the output will be but it should work fairly well.

You will still get MIDI junk if you try this code with A0, A1 or A2 not connected to your circuit.
 
Well it compiles but still no work. when I map to the controls they all have the same cc note and 1 knob turns all 3 controls. I cannot find a code with 3 working pots that I could add the buttons to. I thought that one would be the easiest but maybe not. Anyway this one works but also only 1 pot if you know how to adapt for multiple pots.


Code:
[code]

#include <Bounce.h>

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

Bounce button0 = Bounce(0, 5);
Bounce button1 = Bounce(1, 5);
Bounce button2 = Bounce(2, 5); 

byte current_value_1; 
byte previous_value_1;
byte current_value_2; 
byte previous_value_2; 
byte current_value_3; 
byte previous_value_3; 

void setup() {
  analogReadResolution(7); // set the analog read resolution to 7 bits (a range of 0 - 127)
  analogReadAveraging(32); // average the analog value by averaging 16 readings
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  
 }

void loop() {
  button0.update();
  button1.update();
  button2.update();
  
  current_value_1 = analogRead(A0); 
  current_value_2 = analogRead(A1); 
  current_value_3 = analogRead(A2);  
  
  if (button0.fallingEdge()) {
    usbMIDI.sendNoteOn(60, 99, channel);  // 60 = C4
  }
  if (button1.fallingEdge()) {
    usbMIDI.sendNoteOn(61, 99, channel);  // 61 = C#4
  }
  if (button2.fallingEdge()) {
    usbMIDI.sendNoteOn(62, 99, channel);  // 61 = C#4
  }
  
  if (button0.risingEdge()) {
    usbMIDI.sendNoteOff(60, 0, channel);  // 60 = C4
  }
  if (button1.risingEdge()) {
    usbMIDI.sendNoteOff(61, 0, channel);  // 61 = C#4
  }
  if (button2.risingEdge()) {
    usbMIDI.sendNoteOff(62, 0, channel);  // 62 = D4
  }
  if(current_value_1 != previous_value_1) {
    previous_value_1 = current_value_1;
    usbMIDI.sendControlChange(1, current_value_1, 1); // send continuous controller message
  }
  if(current_value_2 != previous_value_2) {
    previous_value_2 = current_value_2;
    usbMIDI.sendControlChange(2, current_value_1, 1); // send continuous controller message
  }
  if(current_value_3 != previous_value_3) {
    previous_value_3 = current_value_3;
    usbMIDI.sendControlChange(3, current_value_1, 1); // send continuous controller message
  }

 
}
[/CODE] Capture.PNG 1.PNG
 
Didn't you copy and paste?

Maybe that's good. But you missed altering these:

current_value_1

in the .sendControlChange message calls.
 
I copied and pasted your code from #2. I didn't alter anything oh I clicked on copy for forum, it didn't do it right

Code:
#include <Bounce.h>
// the MIDI channel number to send messages
const int channel = 1;
// define how many pots are active up to number of available analog inputs
#define analogInputs 1
// make arrays for input values and lagged input values
int inputAnalog[analogInputs];
int iAlag[analogInputs];
// make array of cc values
int ccValue[analogInputs];
// index variable for loop
int i;

// cc values for buttons
int cc_off = 0;
int cc_on = 65;
int cc_super = 127;

// map buttons to cc for button
int cc0 = 51;
int cc1 = 52;
int cc2 = 53;


Bounce button0 = Bounce(0, 3);
Bounce button1 = Bounce(1, 3);
Bounce button2 = Bounce(2, 3);



void setup() {
  // MIDI rate
  Serial.begin(31250);
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
 

}

void loop() {
  // loop trough active inputs for knobs
  for (i=0;i<analogInputs;i++){
    // read current value at i-th input
    inputAnalog[i] = analogRead(i);
    // if magnitude of difference is 8 or more...
    if (abs(inputAnalog[i] - iAlag[i]) > 7){
      // calc the CC value based on the raw value
      ccValue[i] = inputAnalog[i]/8;
      // send the MIDI
      usbMIDI.sendControlChange(i, ccValue[i], 3);
      // set raw reading to lagged array for next comparison
      iAlag[i] = inputAnalog[i];
    }
  delay(5); // limits MIDI messages to reasonable number
  }
  
  // Push Button code
  button0.update();
  button1.update();
  button2.update();


 
  if (button0.fallingEdge()) {
    usbMIDI.sendNoteOn(60, 99, channel);  // 60 = C4
  }
  if (button1.fallingEdge()) {
    usbMIDI.sendNoteOn(61, 99, channel);  // 61 = C#4
  }
  if (button2.fallingEdge()) {
    usbMIDI.sendNoteOn(62, 99, channel);  // 62 = D4
  }


  if (button0.risingEdge()) {
    usbMIDI.sendNoteOff(60, 0, channel);  // 60 = C4
  }
  if (button1.risingEdge()) {
    usbMIDI.sendNoteOff(61, 0, channel);  // 61 = C#4
  }
  if (button2.risingEdge()) {
    usbMIDI.sendNoteOff(62, 0, channel);  // 62 = D4
  }
 
  
}
 
Code:
#include <Bounce.h>

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

Bounce button0 = Bounce(0, 5);
Bounce button1 = Bounce(1, 5);
Bounce button2 = Bounce(2, 5); 

byte current_value_1; 
byte previous_value_1;
byte current_value_2; 
byte previous_value_2; 
byte current_value_3; 
byte previous_value_3; 

void setup() {
  analogReadResolution(7); // set the analog read resolution to 7 bits (a range of 0 - 127)
  analogReadAveraging(32); // average the analog value by averaging 16 readings
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  
 }

void loop() {
  button0.update();
  button1.update();
  button2.update();
  
  current_value_1 = analogRead(A0); 
  current_value_2 = analogRead(A1); 
  current_value_3 = analogRead(A2);  
  
  if (button0.fallingEdge()) {
    usbMIDI.sendNoteOn(60, 99, channel);  // 60 = C4
  }
  if (button1.fallingEdge()) {
    usbMIDI.sendNoteOn(61, 99, channel);  // 61 = C#4
  }
  if (button2.fallingEdge()) {
    usbMIDI.sendNoteOn(62, 99, channel);  // 61 = C#4
  }
  
  if (button0.risingEdge()) {
    usbMIDI.sendNoteOff(60, 0, channel);  // 60 = C4
  }
  if (button1.risingEdge()) {
    usbMIDI.sendNoteOff(61, 0, channel);  // 61 = C#4
  }
  if (button2.risingEdge()) {
    usbMIDI.sendNoteOff(62, 0, channel);  // 62 = D4
  }
  if(current_value_1 != previous_value_1) {
    previous_value_1 = current_value_1;
    usbMIDI.sendControlChange(1, current_value_1, 1); // send continuous controller message
  }
  if(current_value_2 != previous_value_2) {
    previous_value_2 = current_value_2;
    usbMIDI.sendControlChange(2, current_value_2, 1); // send continuous controller message
  }
  if(current_value_3 != previous_value_3) {
    previous_value_3 = current_value_3;
    usbMIDI.sendControlChange(3, current_value_3, 1); // send continuous controller message
  }

 
}

It was me but in all honesty you need to have some understanding of what you are doing.
 
It worked ant then quit, It seams very unstable. I had the same problem with another sketch. I fried my 3.6 now I'm using a 3.2 Ill reboot and try again. I just have 3 pots and 3 buttons on the breadboard but all 6 worked once and then quit. could be shaky connections.
 
This is my unit, I'd like to try to connect as many pot's as I can and see if it works. Since I fried the 3.6 I may have to use some muxes. I'm going to try to get the lights working while there's only 3 if you have any suggestions. Finally some hope and something to work with, Thank you!

DSCN128.jpg

DS.jpg
 
You shouldn't really start a new thread in a different category, presumably because you weren't happy with the previous thread. This definitely belongs in the project guidance section (and is very welcome there), and "bumping" the thread with your first post here would have been perfectly fine.

A couple of notes:

I note you posted a video of the Adafruit trellis, is there a reason you don't use that? It made the hardware and software of my project a lot simpler, the response is good enough for a MIDI trigger. The same library also handles the trellis lights pretty well.

For the lights in your current setup, it depends on what function you want out of them. A "lit, when pressed" function, is pretty easy, and I'd be inclined (personally) to do it in hardware so as to not waste digital pins that could be used for more buttons. You should be able to connect the (what I assume is a) diode to the switch so that it pulls current through it when closed, as well as pulling the digital input low. Anything fancier than that might need to be shelved for a while.

When I did this I put a threshold on my Knobs, that they had to register a minimum change before I sent a new message. You've done a similar thing by using the averaging, but I wouldn't promise that you're not sending an excess of messages that will clog the system, particularly as you increase knob count. That would explain the working then quitting behaviour. Equally a rogue bit of wire, casually shorting a power rail out would explain that too.

While that's by no means bad soldering, for a project like this you really should consider a PCB. If you can't do that yet, this is a great place to start as it's just routing and long term the reliability is a massive plus. You should 100% be drawing this project out, and probably for the level of support you're asking for include pictures of the hardware, as is setup.

If you've fried a board, I'd strongly encourage you to hunt down the error properly so you don't burn another. When you've cracked whatever the issue is, I'd just buy another T3.5 when you're ready to expand. Honestly, the faff of adding in muxes into the code vs the cost is not going to pay off at all. Especially considering you'd need both analogue and digital Muxes.

This is a great project, similar to one I did and I fully encourage you to pursue it to completion. My custom MIDI controller is 100% the crown of my DJ setup, and the cheapest item there. It took me (a professional electronic engineer) a hella long time, and about two versions to really get something good, and I'm considering revising the current version after two years of use. So while it looks like you've got a lot of learning points, ploug through.
Equally, really consider breaking this problem up into smaller chunks, because if you're handling it all at once you're making it really difficult. Start at the hardware, get yourself something that reads all the buttons, all the knobs and prints the values to Serial monitor (or equivalent)
The add the USB midi, get something that sends unique and sensible messages for each button/knob, first on the monitor, then check it with Ableton or another USB MIDI watcher
Then start mapping. It might seem like this step is redundant, but I spent a long time sending the wrong message type to Serato, then an even longer time trying to get messages back.

Scale each step as well, which you've been doing to some extent already. Get yourself 4 pots, then 8, then 24 (on PCB if you can), and follow these through the rest. You may find hardware/code that works for 4 and 8 starts to fail at 24, but if you don't step through you might not realise the knob count is the problem.

Doing all four steps in one makes it near impossible to know
- Is the knob broken/Disconnected, or is there a code problem, or am I sending the wrong message, or am I sending too many messages, or is it the wrong kind of message for ableton, or is it mapped properly?
I'm not patronising you, this is exactly how I approached the problem. I'm sure you can do this, but I can't promise you'll do it real quick!

Ed
 
You shouldn't really start a new thread in a different category...

I disagree. If a thread goes too far off course from the initial enquiry the work you do on it becomes too specific to be useful to anyone but the OP.

Here, someone might reasonably stumble upon this thread not knowing how to add another element to a non-array coded MIDI controller, it would show the types of things to look for to extend controls with repeated commands.
 
Has the many knobs and buttons sketch been tested with software? if have something I can test my hardware that would help.
 
I stumbled upon this, it sounds like he was trying to do exactly what i am. Do you know if it ever worked?

[QUOTE D-One
D-One is offline
Junior Member

Join Date
Jan 2019
Posts
3

Hello! Thanks for sharing this @oddson, it's the best example I have found for my needs.
I have made a few mofications to suit my needs however I think the way I coded things is a bit inneficient and I was wondering if i could get some help.


My objective is to have an LED per Button, every time a button is pressed its corresponding LED turns On and stays On until another button is pressed and the rest turns Off, basically a Ableton Live Scene trigger where LED's On is just a visual indicatior of what Scene is active.

Adding the LED info
Code:

const int D_LEDS = 2; // How many Pins for LEDS
const int DIGITAL_LEDS[D_LEDS] = {11,12}; // Numbers of the LED Pins

Digital Section:
Code:

//************DIGITAL SECTION**************
//Modificaions : Changed the order of fallingEdge and risingEdge because note off was trigeering the note instead of note on.
void getDigitalData(){
for (int i=0;i<D_PINS;i++){
digital.update();
if (digital.risingEdge()) {
usbMIDI.sendNoteOn(note, ON_VELOCITY, channel);
digitalWrite(DIGITAL_LEDS[0], LOW); // TURNS OFF DIGITAL_LEDS 1 - PIN 11
digitalWrite(DIGITAL_LEDS[1], LOW); // TURNS OFF DIGITAL_LEDS 2 - PIN 12
}
// Note Off messages when each button is released
if (digital.fallingEdge()) {
usbMIDI.sendNoteOff(note, 0, channel);
digitalWrite(DIGITAL_LEDS, HIGH); // TURN ON THE PRESSED BUTTON EQUIVALENT LED WHEN BUTTON IS RELEASED.
Serial.print(" Note OFF ");
}
}
}

It works fine but as i add more LED's using "DIGITAL_LEDS[number], LOW" a bunch of times seems inneficint, is there a better way to go about this?

][/QUOTE]

I'm still trying to get the pots working, I adjusted the code in #5 for 8 pots connected, I tested everything but still no work. The blue line with the cc no. is not supposed to show up until a parameter is selected and a knob is turned, as if it's reading something it shouldn't Any suggestions?
Capture.PNG2.PNG
 
If you want to interface physical rotary knobs to your software....

Not sure if I've got the wrong end of what you are trying to solve -

If you want to have manual pots as per your picture, you could implement them with rotary encoders and capture the digital output to tweak/control whatever you want downstream.


I have code in python running on a pi that reads ~37 of these encoders via an ISR to read multiple MCP23S17's and thence control some PWM modules sitting on the I2C bus.
Am currently porting this to C++ on a teansy 4.0.
Both the rotary encoders and the required chips are only ~ 1$ each and connect to the teansy via the SPI bus, and currently I am seeing the ISR return data from any switch rotation in around 3 microseconds so plenty fast enough for my purposes, under Debian and Python3 I see more like 5 milliseconds which is still acceptable for my needs.
Happy to share code - it's work in progress at present but coming along quite well. I used the excellent library that Sumotoy posted on GitHub to simplify talking to the GPIO expanders
Cheers
Ed



Hello! Thanks for sharing this @oddson, it's the best example I have found for my needs.
I have made a few mofications to suit my needs however I think the way I coded things is a bit inneficient and I was wondering if i could get some help.


My objective is to have an LED per Button, every time a button is pressed its corresponding LED turns On and stays On until another button is pressed and the rest turns Off, basically a Ableton Live Scene trigger where LED's On is just a visual indicatior of what Scene is active.

Adding the LED info
Code:

const int D_LEDS = 2; // How many Pins for LEDS
const int DIGITAL_LEDS[D_LEDS] = {11,12}; // Numbers of the LED Pins

Digital Section:
Code:

//************DIGITAL SECTION**************
//Modificaions : Changed the order of fallingEdge and risingEdge because note off was trigeering the note instead of note on.
void getDigitalData(){
for (int i=0;i<D_PINS;i++){
digital.update();
if (digital.risingEdge()) {
usbMIDI.sendNoteOn(note, ON_VELOCITY, channel);
digitalWrite(DIGITAL_LEDS[0], LOW); // TURNS OFF DIGITAL_LEDS 1 - PIN 11
digitalWrite(DIGITAL_LEDS[1], LOW); // TURNS OFF DIGITAL_LEDS 2 - PIN 12
}
// Note Off messages when each button is released
if (digital.fallingEdge()) {
usbMIDI.sendNoteOff(note, 0, channel);
digitalWrite(DIGITAL_LEDS, HIGH); // TURN ON THE PRESSED BUTTON EQUIVALENT LED WHEN BUTTON IS RELEASED.
Serial.print(" Note OFF ");
}
}
}

It works fine but as i add more LED's using "DIGITAL_LEDS[number], LOW" a bunch of times seems inneficint, is there a better way to go about this?

][/QUOTE]

I'm still trying to get the pots working, I adjusted the code in #5 for 8 pots connected, I tested everything but still no work. The blue line with the cc no. is not supposed to show up until a parameter is selected and a knob is turned, as if it's reading something it shouldn't Any suggestions?
View attachment 17175[/QUOTE]
 
Thanks, I think I found a code that works with the pots. I was only able to test 8 at a time, but they all worked. I'm still trying to get the lights to work with the buttons. I will try your code
 
I get these errors

test_1:12: error: 'note' was not declared in this scope

usbMIDI.sendNoteOff(note, 0, channel);

^

test_1:12: error: 'channel' was not declared in this scope
usbMIDI.sendNoteOff(note, 0, channel);

^

test_1:13: error: 'DIGITAL_LEDS' was not declared in this scope
digitalWrite(DIGITAL_LEDS, HIGH); // TURN ON THE PRESSED BUTTON EQUIVALENT LED WHEN BUTTON IS RELEASED.

^

'D_PINS' was not declared in this scope
 
sample code to simply read GPIO expander chip with interrupt

Hi I've attached some test code that reads up to 8 rotary encoders sitting on SPI-0 at address 0 and using interrupt pin 9 - this has been tested and works on a Due and Teensy 4.
It merely writes out to the serial port the encoder # and rotation direction so you'd need to add the appropriate code into the loop to allow each pot to address the function you want to control.
Whilst in theory this could allow expansion to multiple MCP23S17 chips it looks like the attachInterrupt function does not support arguments so a lower level routine will have to be used to identify which interrupt occurred and hence which chip to read.
I know others have done this since this is what folks writing code to control e.g. quad-copters use to manage pitch/yaw/roll to feedback/control the individual motor speeds.
zip contains the ino and the MCP library from Sumotoy's Github repository.
/Ed
View attachment bare-read-with-interrupt.zip
 
Status
Not open for further replies.
Back
Top