MIDI: Std Serial works, but not SoftSerial

Hi,

I'm trying to build my own computer <-> MIDI interface using an Arduino UNO R3 and an old but working Joystick port to MIDI interface
(My goal is to reflash the 16u2 with a MIDI HID firmware (LUFA?) and use SoftwareSerial for the MIDI side communication.)

My problem is that I just cant get the SoftwareSerial to work!
If I connect the joystick port to the standard pins 0 & 1 for Rx & Tx and use the builtin UART to send notes to my synth, it works just fine, but if I move the MIDI output pins to 2 & 3, and try the SoftwareSerial library (Arduino 1.0.1) my synth doesn't play anything.
my test code:

#include <SoftwareSerial.h>

#define rxMIDIpin 2
#define txMIDIpin 3

SoftwareSerial mySerial(rxMIDIpin, txMIDIpin);

void setup()  
{
  pinMode(rxMIDIpin, INPUT);
  pinMode(txMIDIpin, OUTPUT);
  mySerial.begin(31250);
  //Serial.begin(31250);
}

void loop() {
  // play notes
  for (int note = 0x1E; note < 0x5A; note ++) {
    noteOn(0x90, note, 0x45);
    delay(1000);
    noteOn(0x90, note, 0x00);
     delay(1000);
  }
}

void noteOn(int cmd, int pitch, int velocity) {
  mySerial.write(cmd);
  mySerial.write(pitch);
  mySerial.write(velocity);
  //Serial.write(cmd);
  //Serial.write(pitch);
  //Serial.write(velocity);
}

I can see from many other posts that others have successfully used SoftwareSerial for MIDI, so I can't figure out what I'm doing wrong.
Please help...

/Leifson

Hi, I can't see anything wrong in your code, except that there may be problems in the implicit conversion from signed integer (the three arguments to noteOn() are ints) to byte (the type expected by write()). Although I don't think it should make much difference I would redefine the arguments to noteOn() as byte or uint8_t (and the loop variable "int note" as well).

Thanks for your answer. I understand what you mean about the implicit cast, and I tried again with those changes, but as you suspected there was no improvement.
(That part of the code is taken straight from the Arduino MIDI tutorial, and it does indeed work using the standard serial library.)

One thing I have thought about is that some sources in the internet says that the inverters shown in the Send Line of the MIDI specification schematic could be omitted for some processors, because the processor can invert the signal on its own.
I don't quite understand the purpose of the inverters, since there is two of them the signal isn't inverted, is it? It feels more like some current feed / line driver purpose to me.
Anyway, could it have something to do with this? I mean, is there any difference in how the signal is handled for pin 0&1 (UART) compared with the SoftwareSerial on pins 2&3?

Well, I don't see why SoftwareSerial should behave differently from HardwareSerial as far as logic inversion is concerned, but you may try to initialize mySerial with a third argument, a flag indicating inverted logic. So you may try:

SoftwareSerial mySerial(rxMIDIpin, txMIDIpin, true);

(assuming this option was already implemented in version 1.0.1).

I would also remove the pinMode statements in setup(), which are managed by SoftwareSerial itself. Then I would try different pairs of digital pins, and would also measure their voltage, just rule out the possibility of different levels between pins 0, 1 and the rest.

Ok, I've now tried all your suggestions, but with no improvement.
The inverted logic flag worked as it supposed to, but it should be left as default (not inverted) to work the same as the UART signal.
I've also tried most of the pins available but the problem remains.
Then I hooked up a oscilloscope to check the waveform and I could see the correct voltage levels, but:

One difference that I notice is that the timing is different between software serial and UART!
I modified the program to write the same byte (0xAA) to get a nice and steady pulse train, and I can see that the total time until all bits are sent is longer for the SoftwareSerial than the UART at the same baudrate!
I haven't calculated exactly how much longer, but I guess maybe 10% difference in total time.

#include <SoftwareSerial.h>

#define rxMIDIpin 10
#define txMIDIpin 11

SoftwareSerial mySerial = SoftwareSerial(rxMIDIpin, txMIDIpin);

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

void loop() {
  for (int note = 0x1E; note < 0x5A; note ++) {
    noteOn(0xAA, note, 0x45);
    delay(2000);
  }
}

void noteOn(int cmd, int pitch, int velocity) {
  mySerial.write(cmd);
  Serial.write(cmd);
}

Any ideas?

Power supply? If the processor doesn't get at least 4.5V it may run at a clock speed lower than 16MHz. You may probably measure what comes out of the 5V pin and see. There are also fuses that affect the clock speed, they are usually changed through avrdude.