I have a 600 pulse per revolution optical encoder (and some other stuff) connected to an Arduino Uno (tried it on r2 and r3) through the interrupt pins 2 and 3.
While waiting for a my MIDI jack to arrive in the mail, I tried connecting my setup to my computer through the USB-serial port, along with hairless-midi and loopMidi. Loopmidi is a virtual MIDI port, and hairless-midi bridges serial ports with MIDI ports - virtual or otherwise. I used a baud rate of 115200, because I figured it couldn't hurt to go too high. Everything seemed to work pretty well in Mixxx. Really well, actually. It seemed very responsive and accurate. The encoder didn't miss a beat, no matter how fast I span that thing.
So I was pretty excited when the MIDI jack arrived. I put it in my breadboard and changed
Serial.begin(115200);
to
Serial.begin(31250);
and tested it out in Mixxx. Now, if I spin the encoder moderately quickly in one direction, the virtual record will move in that direction and then suddenly spin the other way and then back again. I assume that the encoder is missing pulses?
I tried it in two different $6 usb-midi cables as well as in my M-Audio Fast Track Ultra.
Then I thought that maybe it had something to do with the lower baud rate (115200 vs 31250). I changed the rate to 38400 and went through USB serial. It worked great. I even tried 19200. Perfect. Even at 9600, it worked.
Why is this happening? Is the usb-serial circuitry in the Arduino, along with some free software, really more reliable than a midi cable and a $300 audio interface, even when the arduino is set to very low baud rates? Or is there something about the weird 31250 baud rate that causes problems in the Arduino?
I haven't had a chance to try to use the 31250 rate through the usb-serial, because hairless midi doesn't allow that rate.
EDIT: Here's the relevant part of the code, and the relevant part of the circuit. There are a few other components, which might be making the problem worse, but even without those components, the optical encoder does not work at 31250.
enum PinAssignments {
encoderPinA = 2, // rigth
encoderPinB = 3, // left
};
volatile int encoderPos = 0; // a counter for the dial
unsigned int lastReportedPos = 0; // change management
boolean A_set = false;
boolean B_set = false;
void setup() {
pinMode(encoderPinA, INPUT_PULLUP);
pinMode(encoderPinB, INPUT_PULLUP);
// encoder pin on interrupt 0 (pin 2)
attachInterrupt(0, doEncoderA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
attachInterrupt(1, doEncoderB, CHANGE);
Serial.begin(31250);
}
void loop() {
if (encoderPos != lastReportedPos){
Serial.write(0xB0);
Serial.write(0x27);
Serial.write(64 + encoderPos - lastReportedPos);
encoderPos = 0;
lastReportedPos = encoderPos;
}
}
// Interrupt on A changing state
void doEncoderA(){
A_set = !A_set;
// adjust counter + if A leads B
if ( A_set && !B_set )
encoderPos += 1;
}
// Interrupt on B changing state, same as A above
void doEncoderB(){
B_set = !B_set;
if( B_set && !A_set )
encoderPos -= 1;
}
It's weird. Another possibility: does the weird baud rate somehow mess with the hardware interrupts?