Problems sending midi messages - values not the same at arrival

Ok, so I'm doing a project that sends out midi messages when you change some controls (ok, a kind of midi controller). I use some buttons, a potentiometer and 2 ultrasound sensors. Buttons work fine, and corresponding midi messages are sent and received perfectly. Any kind of analog control sends out midi messages ok, but the value sent doesn't correspond to the one calculated in the arduino code...

#define OPCODE 0xB0 // midi CC operation code
#define CTRL01 0x48 // controller number code

const int numReadings = 20;    // number of readings to use in smoothing
int readings[numReadings];     // the read values from the analog input
int index = 0;                 // the index of the current reading
int total=0;                   // the total
unsigned long average=0;       // the average value calculated
unsigned long averageOld=0;    // old value to send midi message on change
const int inputPin = A0;       // potentiometer pin

void setup() {
  Serial.begin(31250);
}

void loop() {

  // subtract the last reading:
  total= total - readings[index];         
  // read from the potentiometer:  
  readings[index] = analogRead(inputPin); 
  // add the reading to the total:
  total= total + readings[index];       
  // advance to the next position in the array:  
  index = index + 1;                    
  // if we're at the end of the array go back to the beginning
  if (index >= numReadings)              
    index = 0;                           
  // calculate the average:
  average = total / numReadings;   

  // re-scale to midi values (0-127)
  unsigned long midiAverage = average * 127 / 1024;

  // if the value has changed, send new midi message
  if (midiAverage != averageOld)
  {
    midiSend(CTRL01, midiAverage);
    averageOld = midiAverage;
  }

}

void midiSend(int control, int message)
{
  String hexMessage = String(message, HEX); // convert int value into hex value for midi
  Serial.write(OPCODE);  // defined in this sketch to CC message
  Serial.write(control); // code for the control to be changed
  Serial.print(hexMessage); // code for the new value to send 
}

This is a simplified sketch I did just to test the potentiometer. If I define the baud rate to 9600 to check values, everything is good. Data stream is correct, value smoothing is working, conversion to midi values too.

When I test it out (connect the midi out to my audio interface's midi in port), and use Midi Ox'smessage monitor to check what is arriving, suddenly the values start at 31 and end at 40 something (it's more like 31-65 at the first quarter of turn of the pot, and then 31 to 40 something).

Connections involved:

Midi Ox list of messages:

I wonder whether the MIDI circuit connection is doing something to the analog side - making an earth float, dragging a supply down, forming a ground loop or similar.

Perhaps you could create a simplified sketch which has no inputs and just outputs some hard-coded values. This would (hopefully) allow you to rule out any peculiar behaviour on the MIDI transmission itself, and imply that the problem is connecting the MIDI port causes the analog readings to change.

On the full sketch I'm working with, I'm using 5 buttons through a 4021 IC, each triggering a midi CC message, and those work fine, so I'm guessing the midi function is ok.
I originally thought that since serial isn't synchronous, there might be some byte sending before previous message was fully sent, but if that was the case, the midi message wouldn't be correctly received by midi ox...

Also, I just tested with the Midi.h library, and messages are passed on ok, so I'm kinda stumped on this one... It's something in my midi message function, but I can't really understand what. Hex conversion is also correct, from 00 to 7f, checking with 9600 baud rate like I said...

void midiSend(int control, int message)
{
  String hexMessage = String(message, HEX); // convert int value into hex value for midi
  Serial.write(OPCODE);  // defined in this sketch to CC message
  Serial.write(control); // code for the control to be changed
  Serial.print(hexMessage); // code for the new value to send 
}

I don't understand this. You shouldn't be sending a string of characters for midi. You don't convert control to a String, so why do it with message? Just Serial.write(message).

The midi messages need to be in hex format, so I have to convert the variable (int or long) to hex.
Opcode and control number (passed as function argument) already are defined as their hex value, so using them around as int does the same. But the value part comes in as int, and needs to be converted to hex.
That conversion method was the only one I found anywhere.

Sorry, but that's not true. An int is an int. Midi doesn't understand what Strings, or hex, or decimal are. It understands binary, just like all computers.

This format

#define OPCODE 0xB0 // midi CC operation code
#define CTRL01 0x48 // controller number code

is for your benefit. The compiler turns them into binary, just as it would regardless of how you define them in the source code.

Change this line

  Serial.print(hexMessage); // code for the new value to send

to

  Serial.write(message); // code for the new value to send

and see if it makes a difference.

That did it, thanks a lot!

That sounds a lot more logical, actually... I must have gotten confused (lol) from always finding the midi CC codes in hex format...

Btw, this might sound really stupid, but my sketch is over 7k with that midi function I used. When I use the midi.h library instead, it goes to around 5k O_o
Nothing else gets changed, just removing my function and changing the calls to midi.h's own midisend function.

Is there a reason for this other than the function being in library being built in C and mine has to be converted?

Try taking

  String hexMessage = String(message, HEX); // convert int value into hex value for midi

out, now that you don't need it.

Once again, right you are haha

I read in the reference that String tends to gobble up a lot of memory, but I thought it was refering to flash memory only...