How to communicate boolean values between programs from Arduino and Console - c++

I am looking to communicate boolean values to and from two programs on arduino and windows console. I am working in C++ and using Visual Studio on the computer end and the standard arduino version of C++ on the arduino. All searches I have tried led me to using a windows form and a button on UI. I want this to all be done automatically and have both programs wait until the other has iterated. I've tried some Serial Port samples but none of them have worked so far for one reason or another.
This is the console code I have:
#include "stdafx.h"
#include <stdio.h>
#include <Windows.h>
#include <iostream>
using namespace std;
const int PIXEL_X = 1153;
const int PIXEL_Y = 636;
const int RED = 0;
const int BLUE = 50;
const int GREEN = 200;
const int TOLERANCE = 30;
int main(void) {
COLORREF color;
HDC hDC;
do {// Get the device context for the screen
Sleep(50);
hDC = GetDC(NULL);
// Retrieve the color at that position
color = GetPixel(hDC, PIXEL_X, PIXEL_Y);
// Release the device context again
ReleaseDC(GetDesktopWindow(), hDC);
printf("%i %i %i", GetRValue(color), GetGValue(color), GetBValue(color));
int flag = 0;
if (fabs(GetRValue(color) - RED) > TOLERANCE) {
flag += 1;
}
if (fabs(GetGValue(color) - GREEN) > TOLERANCE) {
flag += 1;
}
if (fabs(GetBValue(color) - BLUE) > TOLERANCE) {
flag += 1;
}
if (flag >= 2) {
return 0;
}
//TODO 1: Send Serial data to continue and wait for return statement
} while (true);
return 0;
}
EDIT: This is my arduino code
#include <Servo.h>
Servo myServo;
Servo myServo2;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
myServo.attach(2);
myServo2.attach(3);
}
void A_button() {
myServo.write(125);
delay(1000);
myServo.write(97);
delay(250);
}
void L_button() {
myServo2.write(72);
delay(1000);
myServo2.write(90);
delay(250);
}
void loop() {
for(int i=0; i < 16; i++) {
A_button();
Serial.print("1 ");
delay(1500);
}
delay(3000);
// TODO 2: send Serial data
L_button();
Serial.print("0 ");
}
EDIT: Thank you for the response. I want the console application code to wait until the arduino code goes to TODO 2, then the console application runs until TODO 1 and checks if the RGB values are in their tolerances. If the RGB values are within the tolrance, then I want the arduino code to continue iterating until the TODO 2 again and repeat. I don't have any C++ code for the serial communication because none of the examples I've tried have compiled, and I can't use a windows form as I understand it.
I want to have the code wait at the TODO, but I have absolutely no idea how to do this and would appreciate any help. I will elaborate if any needs me to.
Thank you in advance.

Related

Arduino serial monitor lagging and cant get it to work

I wrote this program to check some things m but for me it is not working
` #define outputA 7
#define outputB 3
int counter = 0;
int aState;
int aLastState;
int StateAreTheSamePrinted = 0;
int StatePrinted = 0;
void setup() {
// put your setup code here, to run once:
pinMode(outputA, INPUT);
pinMode(3, INPUT);
Serial.begin(115200);
aLastState = digitalRead(outputA);
Serial.print("Arduino started");
}
void loop() {
// put your main code here, to run repeatedly:
aState = digitalRead(outputA);
if(StatePrinted == 0)
{
Serial.print(aState);
StatePrinted = 1;
}
if(aState == aLastState && StateAreTheSamePrinted == 0)
{
Serial.print("States are the same");
StateAreTheSamePrinted = 1;
}
if(aState != aLastState)
{
if(aState == 1){
Serial.print("A is high \n");
}
else
{
Serial.print("A is low \n");
}
StateAreTheSamePrinted = 0;
StatePrinted = 0;
}
aLastState = aState;
}
It always prints once arduino started, 1 (state of input), and states are the same, when I wire 5v from arduino into port 7, sometimes it react once, sometimes n ot, after few minutes it start priting output like 50-100 lines of messages and stops and lags again. Does anyone got into this problem?
`
I was expecting that after giving power into arduino 7 port it would print A is high or A is low and toggle between them
Sounds like you need to "debounce" after the state changes. When you hook 5v into the pin, it might not make a stable connection right away so it changes state very quickly a few times. A simple fix is to put a ~10ms delay after it detects a state change.

ESP32 Bluetooth connection status

I am running into some problems finding a solution when it comes to performing some form of Bluetooth connection check for my project that will allow me to have a connection status light.
My project consists of creating a Bluetooth speaker that has Led Strips controlled over Bluetooth serial (an app will be made to handle this) and audio stream over Bluetooth from a single ESP32.
I have found plenty of examples and had success with performing an spp callback event, however, of course this only works if I connect to the Bluetooth serial side of things through my 'Serial Bluetooth Terminal' app on my phone. If I just go into my phone Bluetooth list and connect to the audio side of things, nothing is registered, which isn't very useful for a Bluetooth speaker!
Basically I really need some help finding a way of registering that a device has connected to the Bluetooth audio so that I can have some form of indication light to tell the user that they are successfully connected to the speaker to play music.
Below is my code:
#include <btAudio.h> //<-------this is the library that I am using to handle Bluetooth audio to an external I2s DAC
#include "BluetoothSerial.h"
#include <FastLED.h>
TaskHandle_t Task1;
//POWER/BT-LIGHT-SETUP----------------------------------------
int powerPinR = 4;
int powerPinG = 16;
int powerPinB = 17;
bool BTisConnected;
//FAST-LED-STUFF----------------------------------------------
CRGB leds[NUM_STRIPS][NUM_LEDS];
CRGB leds_temp[NUM_STRIPS][NUM_LEDS/2];
//BLUETOOTH-SETUP---------------------------------------------
btAudio audio = btAudio("");
BluetoothSerial SerialBT;
//CONNECTION-CHECK--------------------------------------------
void callback(esp_spp_cb_event_t event, esp_spp_cb_param_t*param){
if(event == ESP_SPP_SRV_OPEN_EVT){
Serial.println("Client Connected");
BTisConnected = true;
}
else {
BTisConnected = false;
}
}
//------------------------------------------------------------
void setup() {
//CORE-1-INITIALISE
xTaskCreatePinnedToCore(
codeForTask1, /* Task function. */
"Task_1", /* name of task. */
1000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
0); /* Core */
//POWER/BLUETOOTH-CONNECTION-LIGHT-SETUP
pinMode(powerPinR, OUTPUT);
pinMode(powerPinG, OUTPUT);
pinMode(powerPinB, OUTPUT);
digitalWrite (powerPinR, HIGH);
digitalWrite (powerPinG, HIGH);
digitalWrite (powerPinB, HIGH);
//COOLDOWN-DELAY
delay(3000);
//AUDIO-INITIALISE
audio.begin();
int bck = 26;
int ws = 27;
int dout = 25;
audio.I2S(bck, dout, ws);
//LED-STRIP-SETUP-&-CLEAR-ALL
FastLED.addLeds<WS2812B,STRIP1PIN,GRB>(leds[0], NUM_LEDS);
FastLED.addLeds<WS2812B,STRIP2PIN,GRB>(leds[1], NUM_LEDS);
FastLED.clear();
FastLED.show();
//SERIAL-INITIALISE-&-CLIENT-CONNECTION-CHECK
Serial.begin(115200);
SerialBT.begin("Pilot"); //<-----BLUETOOTH NAME
SerialBT.register_callback(callback); //<-- SerialBT connection check works perfectly, but nothing for audio connection! :(
}
//CORE-0-VOID-LOOP--------------------------------------------
void codeForTask1( void * parameter )
{
for (;;) {
manageData();
delay(10);
}
}
//CORE-1-VOID-LOOP--------------------------------------------
void loop() {
BTconnectionCheck();
playScene();
}
//MANAGE-INCOMING-BLUETOOTH-SERIAL-DATA-----------------------------------------------
void manageData() {
//READ FROM SERIAL AND PARSE OUT ** READ FROM SERIAL AND PARSE OUT ** READ FROM SERIAL AND PARSE OUT **
char rawData[100] = "";
char keyword[] = "Mydata=";
if (SerialBT.available() > 0) {//new data in
size_t byteCount = SerialBT.readBytesUntil('\n', rawData, sizeof(rawData) - 1); //read in data to buffer
rawData[byteCount] = NULL;//put an end character on the data
const char delimiter[] = ",";
char parsedStrings[5][8]; //first number = how many bits of data - 2nd number = max size of eeach data
int dataCount = 0;
int dataPosition = 0;
char *token = strtok(&rawData[dataPosition], delimiter);//look for first piece of data after keyword until comma
if (token != NULL && strlen(token) < sizeof(parsedStrings[0])) {
strncpy(parsedStrings[0], token, sizeof(parsedStrings[0]));
dataCount++;
} else {
Serial.println("token to big");
strcpy(parsedStrings[0], NULL);
}
for (int i = 1; i < 5; i++) {
token = strtok(NULL, delimiter);
if (token != NULL && strlen(token) < sizeof(parsedStrings[i])) {
strncpy(parsedStrings[i], token, sizeof(parsedStrings[i]));
dataCount++;
} else {
Serial.println("token to big");
strcpy(parsedStrings[i], NULL);
}
}
if (dataCount == 5) {
scene = atoi (parsedStrings[0]);
hue = atoi(parsedStrings[1]);
saturation = atoi(parsedStrings[2]);
brightness = atoi(parsedStrings[3]);
eventInterval = atol (parsedStrings[4]);
}
}
}
//BLUETOOTH-CONNECTION-CHECK---------------------------------------------------------
void BTconnectionCheck(){
SerialBT.register_callback(callback);
if (BTisConnected == true){
bluetoothConnected();
}
else {
bluetoothSearch();
}
}
void bluetoothSearch(){
digitalWrite (powerPinR, LOW);
digitalWrite (powerPinG, LOW);
digitalWrite (powerPinB, HIGH);
}
void bluetoothConnected(){
digitalWrite (powerPinR, HIGH);
digitalWrite (powerPinG, LOW);
digitalWrite (powerPinB, HIGH);
}
I have cut lots of the code to do with the LEDs out but its still quite long, If it would help to have a more condensed version then I will chop it down further. Or if it helps to have the full code then I can also post it.
Any help would be greatly appreciated as I am well and truly stuck with this one and its a pretty important part of the project.
Thanks in advance!

Rotary encoder strange behaviour

I have problem with results (on serial monitor) of rotary encoder.
I am using Arduino UNO and RotaryEncoder library.
When I am running example code serial monitor show proper values when rotating with any speed.
I want to use encoder to change volume in Df-player.
Problem starts when I want to use this code together with more complicated one - Mp3 player.
It actually works only when I am rotating encoder very very slowly
#include <SPI.h>
#include <MFRC522.h>
#include <Arduino.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <RotaryEncoder.h>
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 10 // Configurable, see typical pin layout above
#define PIN_IN1 2
#define PIN_IN2 3
#define ROTARYSTEPS 1
#define ROTARYMIN 0
#define ROTARYMAX 30
const int playPauseButton = 4;
const int shuffleButton = 5;
boolean isPlaying = false;
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
SoftwareSerial mySoftwareSerial(5, 6); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);
// Setup a RotaryEncoder with 2 steps per latch for the 2 signal input pins:
RotaryEncoder encoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::TWO03);
// Last known rotary position.
int lastPos = -1;
//*****************************************************************************************//
void setup() {
Serial.begin(9600); // Initialize serial communications with the PC, COMMENT OUT IF IT FAILS TO PLAY WHEN DISCONNECTED FROM PC
mySoftwareSerial.begin(9600);
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
while (! Serial);
encoder.setPosition(5 / ROTARYSTEPS); // start with the value of 5.
pinMode(playPauseButton, INPUT_PULLUP);
pinMode(shuffleButton, INPUT_PULLUP);
Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3.
Serial.println(F("Unable to begin:"));
Serial.println(F("1.Please recheck the connection!"));
Serial.println(F("2.Please insert the SD card!"));
}
Serial.println(F("DFPlayer Mini online. Place card on reader to play a spesific song"));
//myDFPlayer.volume(15); //Set volume value. From 0 to 30
//volumeLevel = map(analogRead(volumePot), 0, 1023, 0, 30); //scale the pot value and volume level
myDFPlayer.volume(5);
//prevVolume = volumeLevel;
//----Set different EQ----
myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
// myDFPlayer.EQ(DFPLAYER_EQ_POP);
// myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
// myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);
// myDFPlayer.EQ(DFPLAYER_EQ_CLASSIC);
// myDFPlayer.EQ(DFPLAYER_EQ_BASS);
}
//*****************************************************************************************//
void loop() {
encoder.tick();
// get the current physical position and calc the logical position
int newPos = encoder.getPosition() * ROTARYSTEPS;
if (newPos < ROTARYMIN) {
encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
newPos = ROTARYMIN;
} else if (newPos > ROTARYMAX) {
encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
newPos = ROTARYMAX;
} // if
if (lastPos != newPos) {
Serial.println(newPos);
myDFPlayer.volume(newPos);
lastPos = newPos;
} // if
// Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
MFRC522::MIFARE_Key key;
for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;
//some variables we need
byte block;
byte len;
MFRC522::StatusCode status;
if (digitalRead(playPauseButton) == LOW) {
if (isPlaying) {
myDFPlayer.pause();
isPlaying = false;
Serial.println("Paused..");
}
else {
isPlaying = true;
myDFPlayer.start();
Serial.println("Playing..");
}
delay(500);
}
if (digitalRead(shuffleButton) == LOW) {
myDFPlayer.randomAll();
Serial.println("Shuffle Play");
isPlaying = true;
delay(1000);
}
//-------------------------------------------
// Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
if ( mfrc522.PICC_IsNewCardPresent()) {
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) {
return;
}
Serial.println(F("**Card Detected:**"));
//-------------------------------------------
mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); //dump some details about the card
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid)); //uncomment this to see all blocks in hex
//-------------------------------------------
Serial.print(F("Number: "));
//---------------------------------------- GET NUMBER AND PLAY THE SONG
byte buffer2[18];
block = 1;
len = 18;
status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid)); //line 834
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Authentication failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
status = mfrc522.MIFARE_Read(block, buffer2, &len);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("Reading failed: "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
//PRINT NUMBER
String number = "";
for (uint8_t i = 0; i < 16; i++)
{
number += (char)buffer2[i];
}
number.trim();
Serial.print(number);
//PLAY SONG
myDFPlayer.play(number.toInt());
isPlaying = true;
//----------------------------------------
Serial.println(F("\n**End Reading**\n"));
delay(1000); //change value if you want to read cards faster
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
}
Any ideas what is wrong?
You have a delay(1000) in your main loop, and since your RotaryEncoder object seems to need a tick() function, i am assuming that it is not interrupt driven. This means that it will check only once per second if it has moved to the next step.
If a rotary encoder is stepped twice, and the middle step is missed by the MCU, the latter has no way of knowing which way round the encoder has turned.
So in this case you can only turn it one step per second.
What you need is, either:
a free running main loop, which goes round at least 100 times per second. (less nice)
a rotary encoder driver that is interrupt driven. (very nice)
I don't know if such a library exists, because i tend not to use arduino libs, but it is a very good exercise to write your own using GPIO interrupts.

blinking led on teensy3.2 with arm programming

I am a newbie in arm programming. I am using teensy 3.2 which has MK20DX256 microcontroller chip and the led is connected to PTC5 of MC.
I have written this code to blink the LED.
The project builds without error but HEX file does not blink led. I am using teensy loader to program the board with HEX file.
Here is my code:
#include "MK20D7.h"
void delay(unsigned int);
int main(void) {
SystemCoreClockUpdate(); /* Get Core Clock Frequency */
SysTick_Config(SystemCoreClock/1000); /* Generate interrupt each 1 ms */
PORTC->PCR[5]= 256; //declared as GPIO
PTC->PDDR=0x00000010;
while(1){
PTC->PDOR=0x00000010;
delay(500);
PTC->PDOR=0x00000000;
delay(500);
}
void delay(unsigned int ms){
unsigned int i,j;
for(i=0;i<ms;i++)
for(j=0;j<20000;j++);
}
}
Please help me in finding what is wrong with this code
Try this first see if the led comes on and stays on
# include "MK20D7.h"
int main(void)
{
PORTC->PCR[5]= 256; //declared as GPIO
PTC->PDDR=0x00000010;
PTC->PDOR=0x00000010;
//PTC->PDOR=0x00000000;
while(1) continue;
}
If not then you need to disassemble, see below.
Then try this
# include "MK20D7.h"
int main(void)
{
PORTC->PCR[5]= 256; //declared as GPIO
PTC->PDDR=0x00000010;
//PTC->PDOR=0x00000010;
PTC->PDOR=0x00000000;
while(1) continue;
}
and see if it goes/stays off
Then try this
# include "MK20D7.h"
void delay(unsigned int );
int main(void)
{
PORTC->PCR[5]= 256; //declared as GPIO
PTC->PDDR=0x00000010;
while(1)
{
PTC->PDOR=0x00000010;
delay();
PTC->PDOR=0x00000000;
delay();
}
}
void delay(void)
{
volatile unsigned int j;
for(j=0;j<20000;j++);
}
Assuming you have the right header file and the binary is built and linked properly, etc. Ideally you want to disassemble the binary, examine vector table to insure its placement and proper contents. Examine the code after the main label and compare it to the documentation for the few registers used.
PSOR and PCOR are easier to use
PTC->PSOR=1<<5;
delay();
PTC->PCOR=1<<5;
delay();

How to make encoder work with two libraries?

First I'd like to say I'm very new to c++, that's why I'm using the Arduino core and libraries on ESP32, and I would like to apologize for the dumpster fire you're about to see below.
Simply making a custom keyboard with buttons and encoders. When booted, select one of two modes: blekeyboard or ble midi control surface.
The button works in both modes but the encoder only works in whichever mode is declared last. (so in this script order, both the encoder and button in mode 1 blekeyboard works, while only the button works in mode 2.)
What did I do wrong and what can I do? Any suggestions regarding the problem or the overall script is welcome.
Thank you in advance.
#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
}
}
First of all, your code needs general tidying up. Do not instantiate an object after the #include or #define section.
Avoid doing this:
#include <BleKeyboard.h>
BleKeyboard bleKeyboard;
#include <MIDI_Interfaces/BluetoothMIDI_Interface.hpp>
BluetoothMIDI_Interface midi;
I generally organise my code as:
// 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
}
...
Second, your code shouts to me 'Finite-States Machines', which is basically what you are implementing but not in a conventional way. Please read Nick Gammon's amazing tutorial on FSMs. This way, you will enumerate your states and trigger actions or events depending on the user's selection or hardware inputs without blocking the flow of the code.
Now, I assume that you have read both the .cpp files from your two libraries and checked if there are no conflicts between them? Also, which encoder.h library are you using? It looks like Paul Stoffregen's library, is it? I ask because his library is heavily based on interrupts and it was coded with some ASM blocks that might be not optimized for the ESP32, but please don't quote me on that. As enhzflep said:
I'd suspect there to be a problem with clashing interrupts.
and I could not agree more on that. If you are using that library, there is a Macro that could save your life:
#define ENCODER_DO_NOT_USE_INTERRUPTS
used in this example from the library's repo