0

我编写了一个小型 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制作,抱歉不是真正的电路布局。

再次编辑:不是。

因为我的知名度不够高,所以不能发截图。图片可在此处获得:

在此处输入图像描述

4

2 回答 2

0

您好,您可以使用低通滤波器解决该问题。

噪声是来自周围环境的高频信号,可能是交流线路中存在无功负载时产生的电噪声。

您可以做的是在每个输入引脚中放置一个旁路电容器接地。

或者

创建一个只允许长按状态的低通滤波器程序。长按按钮的概念。

于 2021-02-05T08:16:19.803 回答
-1

您不需要下拉电阻器,而是要将开关接地并启用输入引脚上的内部上拉电阻。你可以看看我在这里整理的一个小演示系统的照片:

https://kentindell.files.wordpress.com/2015/02/2015-02-18-15-02-16.jpg

该演示在这里讨论:

https://kentindell.wordpress.com/2015/02/18/micrcontroller-interconnect-network-min-version-1-0/

初始化 I/O 端口的 C 在这里:

https://github.com/min-protocol/min/blob/master/firmware/main.c#L64

读取输入的 C 代码在这里:

https://github.com/min-protocol/min/blob/master/firmware/main.c#L85

于 2015-05-07T22:36:59.857 回答