[英]How to make encoder work with two libraries?
首先,我想说我对 C++ 非常陌生,这就是我在 ESP32 上使用 Arduino 核心和库的原因,我想为您即将在下面看到的垃圾箱火灾道歉。
只需制作带有按钮和编码器的自定义键盘。 启动时,选择两种模式之一:blekeyboard 或 ble midi 控制界面。
该按钮可在两种模式下工作,但编码器仅在最后声明的模式下工作。 (因此在此脚本顺序中,模式 1 blekeyboard 中的编码器和按钮均有效,而模式 2 中只有按钮有效。)
我做错了什么,我能做什么? 欢迎任何有关问题或整体脚本的建议。
先感谢您。
#include <Arduino.h>
#include <BleKeyboard.h>
BleKeyboard bleKeyboard;
#define ESP32
#include <encoder.h>
#include <Control_Surface.h>
#include <MIDI_Interfaces/BluetoothMIDI_Interface.hpp>
BluetoothMIDI_Interface midi;
const int usermodebutton1 = 2;
const int usermodebutton2 = 0;
int usermode = 0;
// ---------------------- mode 2 MIDI Input Elements ------------------------ //
using namespace MIDI_Notes;
NoteButton csButton1 = {
2,
note(C, 4),
};
CCRotaryEncoder csEnc1 = {
{26, 25}, // pins
MCU::V_POT_1, // MIDI address (CC number + optional channel)
1, // optional multiplier if the control isn't fast enough
};
// -------------------------- mode 1 blekeyboard --------------------------- //
int kbutton1 = 2;
int kbutton1State;
int keyInterval = 400000;
Encoder kencoder1(25, 26);
int encInterval = 5000;
TickType_t currentTime;
TickType_t previousTime;
long enc1_oldPos = -999;
// ============================================================================= //
void setup()
{
pinMode(usermodebutton1, INPUT_PULLUP);
pinMode(usermodebutton2, INPUT_PULLUP);
Serial.begin(115200);
Serial.println("");
Serial.println("select mode:");
// ----------------------------------------------------------------------------- //
while (true)
{
if (digitalRead(usermodebutton1) == LOW)
{
usermode = 1;
Serial.println("mode 1 selected");
break;
}
if (digitalRead(usermodebutton2) == LOW)
{
usermode = 2;
Serial.println("mode 2 selected");
break;
}
delay(1000);
}
// ----------------------------------------------------------------------------- //
if (usermode == 1)
{
Serial.println("setup mode 1");
Serial.println("Starting BLE work...");
bleKeyboard.begin();
pinMode(kbutton1, INPUT_PULLUP);
previousTime = 0;
}
if (usermode == 2)
{
Serial.println("setup mode 2");
Serial.println("Control Surface BLE starting...");
RelativeCCSender::setMode(relativeCCmode::TWOS_COMPLEMENT);
Control_Surface.begin(); // Initialize Control Surface
}
}
// ============================================================================= //
void loop()
{
while (usermode == 1)
{
while (bleKeyboard.isConnected())
{
// mode 1 encoders
long enc1_newPos = kencoder1.read();
currentTime = esp_timer_get_time();
if (enc1_newPos < enc1_oldPos && currentTime - previousTime > encInterval)
{
enc1_oldPos = enc1_newPos;
previousTime = currentTime;
// bleKeyboard.write(KEY_MEDIA_VOLUME_DOWN);
Serial.print("enc1: ");
Serial.println(enc1_newPos);
}
if (enc1_newPos > enc1_oldPos && currentTime - previousTime > encInterval)
{
enc1_oldPos = enc1_newPos;
previousTime = currentTime;
// bleKeyboard.write(KEY_MEDIA_VOLUME_UP);
Serial.print("enc1: ");
Serial.println(enc1_newPos);
}
// mode 1 keys
kbutton1State = digitalRead(kbutton1);
if (kbutton1State == LOW && currentTime - previousTime > keyInterval)
{
previousTime = currentTime;
Serial.println("button 1 pressed");
bleKeyboard.print("1");
}
}
}
while (usermode == 2)
{
Control_Surface.loop(); // Refresh all elements
}
}
首先,您的代码需要进行一般整理。 不要在#include 或#define 部分之后实例化对象。
避免这样做:
#include <BleKeyboard.h>
BleKeyboard bleKeyboard;
#include <MIDI_Interfaces/BluetoothMIDI_Interface.hpp>
BluetoothMIDI_Interface midi;
我通常将我的代码组织为:
// Include libraries
#include <lib1.h>
#include <lib2.h>
...
// Macros
#define SOMETHING_FUNNY value // see the Macro name in capitals?
#define SOMETHING_USEFUL anothervalue
...
/*
* Variables Section.
* Also, I usually categorize my variables section by type: floats, integers, chars, etc. If I ever use booleans I pack them in a section called 'flags'. Also, if a boolean is used inside an interrupt it should be volatile
*/
Type var_name1 = initial_value; // the initaliztion is optional
AnotherType var_name2;
...
// Object instantiation
ClassName object1;
AnotherClassName object2 = new AnotherClassName(constructor_parameters);
...
//Setup Function
void setup(){
// Serial Port initialization goes first
Serial.begin(baudrate);
// Initialization routines --> use functions!
}
void loop(){
// Check for states of your FSM and call the respective function
}
// Functions definitions
output type myFunction1(args){
// Routine
}
...
其次,您的代码对我大喊“有限状态机”,这基本上是您正在实现的,但不是以传统方式实现的。 请阅读 Nick Gammon 关于 FSM 的精彩教程。 这样,您将根据用户的选择或硬件输入枚举您的状态并触发操作或事件,而不会阻塞代码流。
现在,我假设您已经从两个库中读取了 .cpp 文件并检查了它们之间是否没有冲突? 另外,您使用的是哪个encoder.h
库? 看起来像 Paul Stoffregen 的图书馆,是吗? 我问是因为他的库在很大程度上基于中断,并且它是用一些 ASM 块编码的,这些块可能没有针对 ESP32 进行优化,但请不要引用我的话。 正如 enhzflep 所说:
我怀疑冲突中断有问题。
我对此完全同意。 如果您正在使用该库,则有一个宏可以挽救您的生命:
#define ENCODER_DO_NOT_USE_INTERRUPTS
在这个例子中使用来自图书馆的 repo
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.