为什么在 Arduino MIDI 项目上使用 31250 的波特率会导致问题?

电器工程 Arduino 波特率 迷笛
2022-01-20 10:08:03

我有一个每转 600 个脉冲的光学编码器(和其他一些东西)通过中断引脚 2 和 3 连接到 Arduino Uno(在 r2 和 r3 上尝试过)。

在等待我的 MIDI 插孔收到邮件时,我尝试通过 USB 串行端口将我的设置连接到我的计算机,以及 hairless-midi 和 loopMidi。Loopmidi 是一个虚拟 MIDI 端口,hairless-midi 将串行端口与 MIDI 端口(虚拟或其他)桥接。我使用了 115200 的波特率,因为我认为太高不会有什么坏处。在 Mixxx 中,一切似乎都运行良好。真的很好,其实。它似乎非常敏感和准确。无论我跨越那个东西的速度有多快,编码器都不会错过任何一个节拍。

所以当 MIDI 插孔到来时,我非常兴奋。我把它放在我的面包板上并改变了

Serial.begin(115200);

Serial.begin(31250);

并在 Mixxx 中进行了测试。现在,如果我在一个方向上适度快速地旋转编码器,虚拟唱片将朝那个方向移动,然后突然向另一个方向旋转,然后又返回。我假设编码器缺少脉冲?

我在两条不同的 6 美元 usb-midi 电缆以及我的 M-Audio Fast Track Ultra 中进行了尝试。

然后我认为这可能与较低的波特率有关(115200 vs 31250)。我将速率更改为 38400 并通过 USB 串行。效果很好。我什至试过19200。完美。即使在9600,它也有效。

为什么会这样?Arduino 中的 USB 串行电路以及一些免费软件是否真的比 midi 电缆和 300 美元的音频接口更可靠,即使 arduino 设置为非常低的波特率?还是有什么奇怪的 31250 波特率会导致 Arduino 出现问题?

我没有机会尝试通过 USB 串行使用 31250 速率,因为无毛 MIDI 不允许该速率。

编辑:这是代码的相关部分,以及电路的相关部分。还有一些其他组件可能会使问题变得更糟,但即使没有这些组件,光学编码器也无法在 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;

  }

基本电路

有点奇怪。另一种可能性:奇怪的波特率是否会以某种方式干扰硬件中断?

再次编辑:我在 mididebug 模式下运行 mixxx 并在一个方向上跨越记录。这是在日志中:

Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3E"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"
... for a while and then ...
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41"
...
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x41" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F" 
Debug [Controller]: "MIDI status 0xB0 (ch 1, opcode 0xB), ctrl 0x27, val 0x3F"

所以它从偶尔重复 63 到偶尔重复 66 到突然重复 65。速度为 64 意味着轮子没有移动。63 表示逆时针移动一个脉冲。65是顺时针一个脉冲。反之亦然,具体取决于事物的接线方式。

这是否意味着问题出在 arduino 而不是 midi 适配器?

2个回答

您的波特率不是 MCU 时钟的整数除数。波特率由 MCU 的时钟分频。用时钟的整数除数很容易得到9600、19200等速率。例如,如果您有一个 6.144MHz 晶振,要获得 19200,您需要除以 3200。

对于各种应用(音频、模拟视频和许多其他应用)中的奇数数据速率,使用特定晶体以获得整数除数,例如,NTSC 电路可能具有用于生成各种同步信号的 5.034963MHz 晶体,请参阅

晶体振荡器频率 - 维基百科

如果您的 MCU 有内部时钟发生器,请尝试将其调整为不同的值以获得整数除数,否则会导致误码过高。

一种确定的测试方法是将您的 MIDI 输出连接到您的 MIDI 输入,并像以前一样使用 USB 串行设置系统,但将它(通过您的“虚拟 MIDI 电缆”软件)路由到计算机上的 MIDI 输出端口. 这将测试您的 USB MIDI 硬件是否实际上以设备工作的数据速率可靠地工作。根据我的经验,许多 USB MIDI 设备基本上是为键盘设计的(当按下或释放一个键时只发送 3 个字节左右),并且当您以 31.25 Kbit 的全速率传输时会出现奇怪的溢出问题。这也非常依赖于操作系统/驱动程序。

我想您还想确保发送器/线路驱动程序正常工作。请张贴您的 Arduino MIDI 输出电路的示意图。您使用什么作为输出驱动程序?

我做了很多假设,但假设 Arduino Uno 在 16 MHz,31250 bps 完全支持(0% 错误),UBBR 寄存器值为 31,根据此:AVR UART 速率计算器这表明 MIDI 的比特率应该不是问题(事实上,我的理解是 31250 在很大程度上被选择为易于使用 1MHz 时钟,这与电传打字机衍生的 RS-232 速率不同)。

此外,PC 通过 MIDI 嗅探器或监视器接收到的消息转储在调试中非常有用。