Go Down

Topic: MIDI CC sensitivity (Read 989 times) previous topic - next topic

yarsrev

Thanks Mike
OK almost there but now it says..


'pin' was not declared in this scope

yarsrev

Here's what the code looks like now...

Code: [Select]

#define CC              0xB0

#define NUMBER_OF_ANALOG_INPUTS  16 // NOTE: if you change this value, also change the controllers array, to match the number of inputs and the number of controllers.

#define CHANNEL 1 // Send all messages on channel 1.

/* The list with the corresponding controller numbers: for example, the values of the potentiometer on A0 will be sent as the first controller number in this list, A1 as the second, etc. */
int controllers[] = {
  0x7, 0x5, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0xE, 0x4A, 0x47, 0x58, 0x49, 0x4B, 0x4C, 0x48, 0x59, 0x54, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0xF, 0x55, 0x56, 0x57, 0x4D, 0x4E, 0x4F, 0x10
};  

int analogVal[NUMBER_OF_ANALOG_INPUTS];  // We declare an array for the values from the analog inputs

int analogOld[NUMBER_OF_ANALOG_INPUTS]; // We declare an array for the previous analog values.

int shift = 0;

/* The format of the message to send via serial. We create a new data type, that can store 3 bytes at once.  This will be easier to send as MIDI. */
typedef struct {
  uint8_t status;   // first  byte   : status message (NOTE_ON, NOTE_OFF or CC (controlchange) and midi channel (0-15)
  uint8_t data1;    // second byte   : first value (0-127), controller number or note number
  uint8_t data2;    // third  byte   : second value (0-127), controller value or velocity
}
t_midiMsg;          // We call this data type 't_midiMsg'

void setup() // The setup runs only once, at startup.
{
  pinMode(13, OUTPUT);   // Set pin 13 (the one with the LED) to output
  digitalWrite(13, LOW); // Turn off the LED
  pinMode(11,INPUT_PULLUP);
  for(int i = 0; i < NUMBER_OF_ANALOG_INPUTS; i++){  // We make all values of analogOld -1, so it will always be different from any possible analog reading.
    analogOld[i]=-1;
  }
  Serial.begin(31250);  // Start a serial connection @31250 baud or bits per second on digital pin 0 and 1, this is the connection to the ATmega16U2, which runs the HIDuino MIDI firmware. (31250 baud is the original MIDI speed.)
  delay(1000);           // Wait a second before sending messages, to be sure everything is set up
  digitalWrite(13, HIGH);// Turn on the LED, when the loop is about to start.
}

void loop() // The loop keeps on repeating forever.
{
  if(digitalRead(11) == LOW){
       shift = 16;
        }
      else {
        shift = 0;
        }
        int newReading = analogRead(pin);
if( abs(newReading - oldReading) >=2) {
// send new reading
oldReading = newReading;
}
  t_midiMsg msg;                                     // create a variable 'msg' of data type 't_midiMsg' we just created
  for(int i = 0; i < NUMBER_OF_ANALOG_INPUTS; i++){  // Repeat this procedure for every analog input.

    analogVal[i] = analogRead(i+A0)/8;               // The resolution of the Arduino's ADC is 10 bit, and the MIDI message has only 7 bits, 10 - 7 = 3, so we divide by 2^3, or 8.
    if(analogVal[i] != analogOld[i]){                // Only send the value, if it is a different value than last time.
      msg.status = CC;                               // Controll Change
      msg.status = msg.status | CHANNEL-1;           // Channels are zero based (0 = ch1, and F = ch16). Bitwise or to add the status message and channel together:
                                                    /* status     = 0bssss0000
                                                     * channel    = 0b0000cccc
                                                     * | ------------------ (bitwise or)
                                                     * msg.status = 0bsssscccc      
                                                     */
      msg.data1   = controllers[i+shift];            // Get the controller number from the array above.
      msg.data2   = analogVal[i];                    // Get the value of the analog input from the analogVal array.
      Serial.write((uint8_t *)&msg, sizeof(msg));    // Send the MIDI message.
      analogOld[i] = analogVal[i];                   // Put the analog values in the array for old analog values, so we can compare the new values with the previous ones.
      delay(10);                                     // Wait for 10ms, so it doesn't flood the computer with MIDI-messages
    }
  }

}

Grumpy_Mike

You have not defined what you want the value of pin to be, it is not mentioned anywhere else in the code.
So you need to define it and put and set it to a value, or just replace the word "pin" with the number of the analogue input you want to use.

In the mean time please read:-
https://www.arduino.cc/reference/en/language/variables/variable-scope--qualifiers/scope/

yarsrev

Thanks Mike, OK I understand what's in scope.

I'm still deciphering the code I have hacked together.

I want (pin) to be all analog inputs not just one.

Can I make use of these commands earlier in the code...?

int analogVal[NUMBER_OF_ANALOG_INPUTS]; 

int analogOld[NUMBER_OF_ANALOG_INPUTS];


Grumpy_Mike

Quote
Can I make use of these commands earlier in the code...?
No.
You need to specify what number analogue input you want to use. I don't understand why that particular analogue read is needed.

The code assumes that you have 16 analogue inputs, do you?
If so then you just need a number from 0 to 15 depending on which one you need to use at the time. The place you use the variable pin is not in a loop so I think that is wrong. Later on you use
Code: [Select]
analogVal[i] = analogRead(i+A0)/8;
This is much closer to what you want although even that line contains two mistakes.
First off as A0 is zero anyway you can just use i and you should not do the divide by 8 until you have decided if you want to send the value or not. So you need to use
Code: [Select]
analogVal[i] = analogRead(i);
    if(abs(analogVal[i] - analogOld[i]) > 2){

Don't forget to divide it by 8 before you send it.

yarsrev

Thanks Mike. Yes I have 16 analog inputs and a switch on pin 11 (arduino mega rev3). I'll try your suggestion

yarsrev

Hi Mike
Would you check I have inserted your suggestion correctly? It compiles ok but I am still getting jitter from the pots.

Code: [Select]

#define CC              0xB0

#define NUMBER_OF_ANALOG_INPUTS  16 // NOTE: if you change this value, also change the controllers array, to match the number of inputs and the number of controllers.

#define CHANNEL 1 // Send all messages on channel 1.

/* The list with the corresponding controller numbers: for example, the values of the potentiometer on A0 will be sent as the first controller number in this list, A1 as the second, etc. */
int controllers[] = {
  0x7, 0x5, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0xE, 0x4A, 0x47, 0x58, 0x49, 0x4B, 0x4C, 0x48, 0x59, 0x54, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0xF, 0x55, 0x56, 0x57, 0x4D, 0x4E, 0x4F, 0x10
}; 

int analogVal[NUMBER_OF_ANALOG_INPUTS];  // We declare an array for the values from the analog inputs

int analogOld[NUMBER_OF_ANALOG_INPUTS]; // We declare an array for the previous analog values.

int shift = 0;

/* The format of the message to send via serial. We create a new data type, that can store 3 bytes at once.  This will be easier to send as MIDI. */
typedef struct {
  uint8_t status;   // first  byte   : status message (NOTE_ON, NOTE_OFF or CC (controlchange) and midi channel (0-15)
  uint8_t data1;    // second byte   : first value (0-127), controller number or note number
  uint8_t data2;    // third  byte   : second value (0-127), controller value or velocity
}
t_midiMsg;          // We call this data type 't_midiMsg'

void setup() // The setup runs only once, at startup.
{
  pinMode(13, OUTPUT);   // Set pin 13 (the one with the LED) to output
  digitalWrite(13, LOW); // Turn off the LED
  pinMode(11,INPUT_PULLUP);
  for(int i = 0; i < NUMBER_OF_ANALOG_INPUTS; i++){  // We make all values of analogOld -1, so it will always be different from any possible analog reading.
    analogOld[i]=-1;
  }
  Serial.begin(31250);  // Start a serial connection @31250 baud or bits per second on digital pin 0 and 1, this is the connection to the ATmega16U2, which runs the HIDuino MIDI firmware. (31250 baud is the original MIDI speed.)
  delay(1000);           // Wait a second before sending messages, to be sure everything is set up
  digitalWrite(13, HIGH);// Turn on the LED, when the loop is about to start.
}

void loop() // The loop keeps on repeating forever.
{
  if(digitalRead(11) == LOW){
       shift = 16;
        }
      else {
        shift = 0;
        }
        int i;
        int pin;
        int newReading = analogRead(pin);
        analogVal[i] = analogRead(i);
    if(abs(analogVal[i] - analogOld[i]) > 2) {
// send new reading
int oldReading = newReading;
}
  t_midiMsg msg;                                     // create a variable 'msg' of data type 't_midiMsg' we just created
  for(int i = 0; i < NUMBER_OF_ANALOG_INPUTS; i++){  // Repeat this procedure for every analog input.

    analogVal[i] = analogRead(i+A0)/8;               // The resolution of the Arduino's ADC is 10 bit, and the MIDI message has only 7 bits, 10 - 7 = 3, so we divide by 2^3, or 8.
    if(analogVal[i] != analogOld[i]){                // Only send the value, if it is a different value than last time.
      msg.status = CC;                               // Controll Change
      msg.status = msg.status | CHANNEL-1;           // Channels are zero based (0 = ch1, and F = ch16). Bitwise or to add the status message and channel together:
                                                    /* status     = 0bssss0000
                                                     * channel    = 0b0000cccc
                                                     * | ------------------ (bitwise or)
                                                     * msg.status = 0bsssscccc       
                                                     */
      msg.data1   = controllers[i+shift];            // Get the controller number from the array above.
      msg.data2   = analogVal[i];                    // Get the value of the analog input from the analogVal array.
      Serial.write((uint8_t *)&msg, sizeof(msg));    // Send the MIDI message.
      analogOld[i] = analogVal[i];                   // Put the analog values in the array for old analog values, so we can compare the new values with the previous ones.
      delay(10);                                     // Wait for 10ms, so it doesn't flood the computer with MIDI-messages
    }
  }

}

Grumpy_Mike

Quote
Would you check I have inserted your suggestion correctly?
Sorry you have not.
The bit that does the actual reading of the pots has not been changed at all.
It is still
Code: [Select]
for(int i = 0; i < NUMBER_OF_ANALOG_INPUTS; i++){  // Repeat this procedure for every analog input.

    analogVal[i] = analogRead(i+A0)/8;               // The resolution of the Arduino's ADC is 10 bit, and the MIDI message has only 7 bits, 10 - 7 = 3, so we divide by 2^3, or 8.
    if(analogVal[i] != analogOld[i]){

So yes it will still jitter.

What you have done is:-
Code: [Select]
        int i;
        int pin;
        int newReading = analogRead(pin);
        analogVal[i] = analogRead(i);
    if(abs(analogVal[i] - analogOld[i]) > 2) {
// send new reading
int oldReading = newReading;

What is this supposed to be doing?
You define a variable called i which you never assign a value to and never use.
You define a variable called pin which you never assign a value to and do use but why you use it is anyone's guess.
Finally you define a variable called oldReading and set it to the value of newReading which is your reading from an undefined analogue channel but you never use the variable newReadng so why define it. In short I have no idea why you have that section of code in your sketch, it does nothing.
What do you think it does?

yarsrev

I am trying to integrate this: if(abs(analogVal - analogOld) > 2) as you say it will stop the jitter.

Here is the code again without any modification. How should I integrate: if(abs(analogVal - analogOld) > 2)


Code: [Select]


#define CC              0xB0

#define NUMBER_OF_ANALOG_INPUTS  16 // NOTE: if you change this value, also change the controllers array, to match the number of inputs and the number of controllers.

#define CHANNEL 1 // Send all messages on channel 1.

/* The list with the corresponding controller numbers: for example, the values of the potentiometer on A0 will be sent as the first controller number in this list, A1 as the second, etc. */
int controllers[] = {
  0x7, 0x5, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0xE, 0x4A, 0x47, 0x58, 0x49, 0x4B, 0x4C, 0x48, 0x59, 0x54, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0xF, 0x55, 0x56, 0x57, 0x4D, 0x4E, 0x4F, 0x10
};  

int analogVal[NUMBER_OF_ANALOG_INPUTS];  // We declare an array for the values from the analog inputs

int analogOld[NUMBER_OF_ANALOG_INPUTS]; // We declare an array for the previous analog values.

int shift = 0;

/* The format of the message to send via serial. We create a new data type, that can store 3 bytes at once.  This will be easier to send as MIDI. */
typedef struct {
  uint8_t status;   // first  byte   : status message (NOTE_ON, NOTE_OFF or CC (controlchange) and midi channel (0-15)
  uint8_t data1;    // second byte   : first value (0-127), controller number or note number
  uint8_t data2;    // third  byte   : second value (0-127), controller value or velocity
}
t_midiMsg;          // We call this data type 't_midiMsg'

void setup() // The setup runs only once, at startup.
{
  pinMode(13, OUTPUT);   // Set pin 13 (the one with the LED) to output
  digitalWrite(13, LOW); // Turn off the LED
  pinMode(11,INPUT_PULLUP);
  for(int i = 0; i < NUMBER_OF_ANALOG_INPUTS; i++){  // We make all values of analogOld -1, so it will always be different from any possible analog reading.
    analogOld[i]=-1;
  }
  Serial.begin(31250);  // Start a serial connection @31250 baud or bits per second on digital pin 0 and 1, this is the connection to the ATmega16U2, which runs the HIDuino MIDI firmware. (31250 baud is the original MIDI speed.)
  delay(1000);           // Wait a second before sending messages, to be sure everything is set up
  digitalWrite(13, HIGH);// Turn on the LED, when the loop is about to start.
}

void loop() // The loop keeps on repeating forever.
{
  if(digitalRead(11) == LOW){
       shift = 16;
        }
      else {
        shift = 0;
        }
  t_midiMsg msg;                                     // create a variable 'msg' of data type 't_midiMsg' we just created
  for(int i = 0; i < NUMBER_OF_ANALOG_INPUTS; i++){  // Repeat this procedure for every analog input.

    analogVal[i] = analogRead(i+A0)/8;               // The resolution of the Arduino's ADC is 10 bit, and the MIDI message has only 7 bits, 10 - 7 = 3, so we divide by 2^3, or 8.
    if(analogVal[i] != analogOld[i]){                // Only send the value, if it is a different value than last time.
      msg.status = CC;                               // Controll Change
      msg.status = msg.status | CHANNEL-1;           // Channels are zero based (0 = ch1, and F = ch16). Bitwise or to add the status message and channel together:
                                                    /* status     = 0bssss0000
                                                     * channel    = 0b0000cccc
                                                     * | ------------------ (bitwise or)
                                                     * msg.status = 0bsssscccc      
                                                     */
      msg.data1   = controllers[i+shift];            // Get the controller number from the array above.
      msg.data2   = analogVal[i];                    // Get the value of the analog input from the analogVal array.
      Serial.write((uint8_t *)&msg, sizeof(msg));    // Send the MIDI message.
      analogOld[i] = analogVal[i];                   // Put the analog values in the array for old analog values, so we can compare the new values with the previous ones.
      delay(10);                                     // Wait for 10ms, so it doesn't flood the computer with MIDI-messages
    }
  }

}


Grumpy_Mike

OK just this time but I am wondering why you are having to be shown this, I told you what to do in reply #22

Code: [Select]
#define CC              0xB0

#define NUMBER_OF_ANALOG_INPUTS  16 // NOTE: if you change this value, also change the controllers array, to match the number of inputs and the number of controllers.

#define CHANNEL 1 // Send all messages on channel 1.

/* The list with the corresponding controller numbers: for example, the values of the potentiometer on A0 will be sent as the first controller number in this list, A1 as the second, etc. */
int controllers[] = {
  0x7, 0x5, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, 0xE, 0x4A, 0x47, 0x58, 0x49, 0x4B, 0x4C, 0x48, 0x59, 0x54, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F, 0xF, 0x55, 0x56, 0x57, 0x4D, 0x4E, 0x4F, 0x10
}; 

int analogVal[NUMBER_OF_ANALOG_INPUTS];  // We declare an array for the values from the analog inputs

int analogOld[NUMBER_OF_ANALOG_INPUTS]; // We declare an array for the previous analog values.

int shift = 0;

/* The format of the message to send via serial. We create a new data type, that can store 3 bytes at once.  This will be easier to send as MIDI. */
typedef struct {
  uint8_t status;   // first  byte   : status message (NOTE_ON, NOTE_OFF or CC (controlchange) and midi channel (0-15)
  uint8_t data1;    // second byte   : first value (0-127), controller number or note number
  uint8_t data2;    // third  byte   : second value (0-127), controller value or velocity
}
t_midiMsg;          // We call this data type 't_midiMsg'

void setup() // The setup runs only once, at startup.
{
  pinMode(13, OUTPUT);   // Set pin 13 (the one with the LED) to output
  digitalWrite(13, LOW); // Turn off the LED
  pinMode(11,INPUT_PULLUP);
  for(int i = 0; i < NUMBER_OF_ANALOG_INPUTS; i++){  // We make all values of analogOld -1, so it will always be different from any possible analog reading.
    analogOld[i]=-1;
  }
  Serial.begin(31250);  // Start a serial connection @31250 baud or bits per second on digital pin 0 and 1, this is the connection to the ATmega16U2, which runs the HIDuino MIDI firmware. (31250 baud is the original MIDI speed.)
  delay(1000);           // Wait a second before sending messages, to be sure everything is set up
  digitalWrite(13, HIGH);// Turn on the LED, when the loop is about to start.
}

void loop() // The loop keeps on repeating forever.
{
  if(digitalRead(11) == LOW){
       shift = 16;
        }
      else {
        shift = 0;
        }
  t_midiMsg msg;                                     // create a variable 'msg' of data type 't_midiMsg' we just created
  for(int i = 0; i < NUMBER_OF_ANALOG_INPUTS; i++){  // Repeat this procedure for every analog input.

    //analogVal[i] = analogRead(i+A0)/8;               // The resolution of the Arduino's ADC is 10 bit, and the MIDI message has only 7 bits, 10 - 7 = 3, so we divide by 2^3, or 8.
    //if(analogVal[i] != analogOld[i]){                // Only send the value, if it is a different value than last time.
    analogVal[i] = analogRead(i);
    if(abs(analogVal[i] - analogOld[i]) > 2){
       
      msg.status = CC;                               // Controll Change
      msg.status = msg.status | CHANNEL-1;           // Channels are zero based (0 = ch1, and F = ch16). Bitwise or to add the status message and channel together:
                                                    /* status     = 0bssss0000
                                                     * channel    = 0b0000cccc
                                                     * | ------------------ (bitwise or)
                                                     * msg.status = 0bsssscccc     
                                                     */
      msg.data1   = controllers[i+shift];            // Get the controller number from the array above.
      msg.data2   = analogVal[i] >> 3;               // Get the value of the analog input from the analogVal array and convert it to a 7 bit MIDI value.
                                                     // note the shift right three times " >> 3" does the same as divide by 8 but a bit faster.
      Serial.write((uint8_t *)&msg, sizeof(msg));    // Send the MIDI message.
      analogOld[i] = analogVal[i];                   // Put the analog values in the array for old analog values, so we can compare the new values with the previous ones.
      delay(10);                                     // Wait for 10ms, so it doesn't flood the computer with MIDI-messages
    }
  }

}



yarsrev

You are a star Mike. Thanks for being patient with me, it is slowly starting to sink in!

I will install and do a full test in the studio this weekend but it already looks very stable inside MIDI monitor.


yarsrev

Quick question about the divide by 8 code, you have commented it and I can't see where it now happens in the code? Is it no longer needed?

Grumpy_Mike

#27
Mar 17, 2019, 11:11 pm Last Edit: Mar 17, 2019, 11:13 pm by Grumpy_Mike
You need the divide by 8 in the data 2 statement. I used the better shift right method in place of the divide by 8.

As I said you need the full 10 bits to do the "only send it if it has changed" bit.

I left it in that code but commented out so you could see the place it used to be.

MarkT

Hi all
Still having trouble with this. Mike, wont your suggestion effectively halve the resolution?

No, it doesn't reduce resolution, it just adds hysteresis.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

dannyrichardson

#29
Mar 18, 2019, 08:50 pm Last Edit: Mar 18, 2019, 08:53 pm by dannyrichardson
Thanks for the advice! I had a similar question about my MIDI controller. Learning all of this coding is confusing!  I run a mini MIDI controller that is a little bit older, but when I was able to easily get it going.

Go Up