我编写了一个小型 C++ 程序,它可以在 Arduino Uno (atmega328p) 上交叉编译和运行。它是一个基本的 MIDI 补丁更换器,它允许步进通过 32 个插槽,其中包含程序编号(以数组形式组织)。选择一个插槽后,定时器运行,当它达到 400 毫秒时,程序更改将通过串行 MIDI 协议发送到连接的合成器。但这在这种情况下并不重要。
有两个按钮用于增加和减少当前程序。当前节目以二进制形式显示,带有 5 个 LED。有 32 个程序需要单步执行,00000 代表 1,11111 代表 32。
到目前为止一切正常,我做了一个小类,代表一个按钮并处理去抖动。所以我不认为噪音是错误的原因。
错误/错误如下:一段时间后(我无法重现错误发生的那一刻)按钮触发两次更改程序的动作 - 第一次是按下时,第二次是释放时。另外,如果我按下按钮,等待几秒钟然后松开它......这是不需要的,但我看不出我在哪里犯了错误。
midipatcher.cpp - 入口点
#include <Arduino.h>
#include "Button.h"
int timer = 0;
int deltaTime = 0;
int currentSlot = 0;
bool waiting;
int actionDelay = 400;
Button* buttonUp;
Button* buttonDown;
int leds[] = { 9, 10, 11, 12, 13 };
byte nordLeadSlots[32] = {
0, 1, 3, 2,
5, 6, 9, 10,
24, 50, 11, 12,
25, 26, 25, 25
};
byte ms2000Slots[32] = {
5, 6, 9, 10,
24, 50, 11, 12,
25, 26, 25, 25,
0, 1, 3, 2
};
void sendSlotData() {
Serial.write(0xC0);
Serial.write(nordLeadSlots[currentSlot]);
Serial.write(0xC1);
Serial.write(ms2000Slots[currentSlot]);
}
void updateLeds() {
for (int i = 0; i < 5; i++) {
if (bitRead(currentSlot, i) == 1) {
digitalWrite(leds[i], HIGH);
} else {
digitalWrite(leds[i], LOW);
}
}
}
void changeSlot(int slot) {
if (slot > 31) {
currentSlot = 0;
} else if (slot < 0) {
currentSlot = 31;
} else {
currentSlot = slot;
}
waiting = true;
updateLeds();
timer = millis();
}
void setup() {
buttonUp = new Button(2);
buttonDown = new Button(3);
for (int i = 0; i < 5; i++) {
pinMode(leds[i], OUTPUT);
}
Serial.begin(31250);
}
void loop() {
if (buttonUp->isPressed()) {
changeSlot(currentSlot + 1);
}
if (buttonDown->isPressed()) {
changeSlot(currentSlot - 1);
}
deltaTime = millis() - timer;
if (waiting == true && deltaTime > actionDelay) {
sendSlotData();
waiting = false;
}
}
int main(void) {
init();
setup();
while (true) {
loop();
}
}
Button.cpp - 关心按钮去抖动的代码:
#include <Arduino.h>
#include "Button.h"
Button::Button(int pin) {
debounceDelay_ = 10;
pin_ = pin;
state_ = LOW;
lastDebounceTime_ = 0;
pinMode(pin_, INPUT);
}
bool Button::isPressed() {
if (millis() - debounceDelay_ < lastDebounceTime_) return false;
int currentState = digitalRead(pin_);
if (currentState != state_) {
state_ = currentState;
if (currentState == HIGH) {
return true;
}
}
lastDebounceTime_ = millis();
return false;
}
我认为主类中的时间处理不是问题,它只关心在选择插槽后发送程序更改之前必须经过的 400 毫秒。我已经注释掉了该功能,但问题被拒绝了。
编辑:
这是电路的截图,用fritzing制作,抱歉不是真正的电路布局。
再次编辑:不是。
因为我的知名度不够高,所以不能发截图。图片可在此处获得: