Upload on Nano ESP32 won't complete

Uploading sketches on the Arduino Nano ESP32 has always been different for me compared to doing so on other Arduino boards. It's super slow but in the past, after the compiling, the board would disconnect and reconnect after uploading is done - and it would work.

Now every time the sketch is uploaded the board won't reconnect automatically, needing me to reset the board, causing the code to not run at all. The LED blinks in an RGB pattern.

I had similar issues and in the past I could solve them by pressing the reset button twice, and it would couple of times before having to repeat the process. It also involved reopening Arduino IDE, unplugging and plugging everything.

Now pressing reset twice doesn't help anymore and somehow pressing once now gives me this phasing green blink. The same issue persists here where it would disconnect before finishing up the upload. I read that it is a boot loader mode, so I tried to reset the boot loader and download the firmware again. I short B1 and GND as given the instruction and the firmware downloading worked, but it didn't fix anything...

This is the code that I was planning to upload


//  Importing external libraries
#include <ESP32Servo.h>
#include <Encoder.h>

//  Declare pinout
const int p1_encoderPinA = D2;
const int p1_encoderPinB = D3;
const int p1_servoRPin = D4;
const int p1_servoLPin = D5;
const int receiverPin_A0 = A0;

const int signalPuffer = -5;  //  Increase puffer if servo twitches at end positions
const int averageFactor = 2;  //  Increase factor for more stable inputs, but slower computation

const int p1_minConstrainValue = 1000 - signalPuffer;
const int p1_maxConstrainValue = 1500 - signalPuffer;
const int p1_minServoSpeed = 55;  //  lowest == 0
const int p1_maxServoSpeed = 125; //  highest == 180
const int stopServoValue = 90;

const int p1_maxEncoderPosition = 40; //  Change according to how far P1 is allowed to roll

//  Variables for interruptISR && encoder
unsigned long p1_lastIncReadTime = micros();
unsigned long p1_lastDecReadTime = micros();
volatile int p1_encoderPosition = 0;
int p1_encoderTargetPosition = 0;

//  Create encoder
Encoder p1_encoder(p1_encoderPinA, p1_encoderPinB);

//  Create servos
Servo p1_servoR;
Servo p1_servoL;

void setup() {
  //  Setup role for each pin
  pinMode(receiverPin_A0, INPUT_PULLUP);
  pinMode(p1_encoderPinA, INPUT_PULLUP);
  pinMode(p1_encoderPinB, INPUT_PULLUP);
  pinMode(p1_servoRPin, OUTPUT);
  pinMode(p1_servoLPin, OUTPUT);

  //  Configure servos
  p1_servoR.attach(p1_servoRPin);
  p1_servoL.attach(p1_servoLPin);

  //  Enable external interrupt
  attachInterrupt(digitalPinToInterrupt(p1_encoderPinA), p1_encoderISR, CHANGE);
  attachInterrupt(digitalPinToInterrupt(p1_encoderPinB), p1_encoderISR, CHANGE);

  Serial.begin(9600);
}

void loop() {
  //  Gather <averageFactor> amount of samples and return median value
  int A0_averageReceiverValue = 0;
  for (int i = 0; i < averageFactor; i++) {
    A0_averageReceiverValue += pulseIn(receiverPin_A0, HIGH);
  }
  A0_averageReceiverValue /= averageFactor;

  //  Create segments that correspond to distinct <p1_encoderTargetPosition> to reference goal
  int p1_mappedReceiverValue = constrain(A0_averageReceiverValue, p1_minConstrainValue, p1_maxConstrainValue);
  float p1_fluctuationConstant = (p1_maxConstrainValue - p1_minConstrainValue) / p1_maxEncoderPosition;
  if (p1_mappedReceiverValue > p1_minConstrainValue) {
    for (int i = 1; i != p1_maxEncoderPosition; i++) {
      float maxFluctuationConverter = p1_minConstrainValue + i * p1_fluctuationConstant;
      float minFluctuationConverter = maxFluctuationConverter - p1_fluctuationConstant;
      if (p1_mappedReceiverValue <= maxFluctuationConverter && p1_mappedReceiverValue > minFluctuationConverter) {
        p1_encoderTargetPosition = i;
      } else if (p1_mappedReceiverValue > maxFluctuationConverter) {
        p1_encoderTargetPosition = p1_maxEncoderPosition - 1;
      }
    }
  }

  //  Future failsafe redundancy; measure current spike to detect resistance and reset encoderPosition
  //  Rotate servo according to relation between <p1_encoderPosition> and <p1_encoderTargetPosition>
  //  Failsafe feature so that <p1_encoderPosition> doesn't breach boundary
  if (p1_encoderPosition >= 0 && p1_encoderPosition <= p1_maxEncoderPosition) {
    if (p1_encoderPosition < p1_encoderTargetPosition) {
      //  Reverse following if roational direction is reversed
      p1_servoR.write(p1_minServoSpeed);
      p1_servoL.write(p1_maxServoSpeed);
    } else if (p1_encoderPosition > p1_encoderTargetPosition) {
      //  Reverse following if roational direction is reversed
      p1_servoR.write(p1_maxServoSpeed);
      p1_servoL.write(p1_minServoSpeed);
    } else {
      Serial.println("+-+-+Target position reached+-+-+");
    }
  } else {
    //  Failsafe feature so that <p1_encoderPosition> doesn't breach boundary
    Serial.println("***WARNING, OUT OF BOUNDARY***");
    if (p1_encoderPosition > p1_maxEncoderPosition) {
        int overstep = p1_maxEncoderPosition - p1_encoderPosition;
        p1_encoderPosition += overstep;
    } else {
        int overstep = p1_encoderPosition;
        p1_encoderPosition -= overstep;
    }
  }

  Serial.print("Stabilized A0 signal: ");
  Serial.println(A0_averageReceiverValue);
  Serial.print("P1 Encoder target position: ");
  Serial.println(p1_encoderTargetPosition);
  Serial.print(">>> P1 Encoder position: ");
  Serial.println(p1_encoderPosition);
}

void p1_encoderISR() {
  static uint8_t old_AB = 3;
  static int8_t encval = 0;
  static const int8_t enc_states[]  = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};

  old_AB <<=2;

  if (digitalRead(p1_encoderPinA)) old_AB |= 0x02;
  if (digitalRead(p1_encoderPinB)) old_AB |= 0x01;
  
  encval += enc_states[( old_AB & 0x0f )];

  if(encval > 3) {
    int changevalue = 1;
    p1_lastIncReadTime = micros();
    p1_encoderPosition = p1_encoderPosition + changevalue;
    encval = 0;
  }
  else if(encval < -3) {
    int changevalue = -1;
    p1_lastDecReadTime = micros();
    p1_encoderPosition = p1_encoderPosition + changevalue;
    encval = 0;
  }
}

I really can't think of ways to fix this issue now. It's possible to upload the same code to my Arduino Nano so I think the issues's with the ESP32.

Can anyone who has experience help?

Thank you for your time

Hello @alexaccountrelatedemails; what core are you using and what version? (You can check the Boards Manager tab).

EDIT: Also, can you post a log of the bootloader upload (the one following this procedure)?

I'm using Arduino ESP32 Boards by Arduino, version 2.0.17
Sorry, not sure what you mean by the core? I could upload the core file in the Arduino15 folder

Here is the log of the bootloader upload:

Sketch uses 293221 bytes (9%) of program storage space. Maximum is 3145728 bytes.
Global variables use 31584 bytes (9%) of dynamic memory, leaving 296096 bytes for local variables. Maximum is 327680 bytes.
esptool.py v4.5.1
Serial port /dev/cu.usbmodem1401
Connecting...
Chip is ESP32-S3 (revision v0.2)
Features: WiFi, BLE
Crystal is 40MHz
MAC: 3c:84:27:c3:1e:3c
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Flash will be erased from 0x00000000 to 0x00003fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Flash will be erased from 0x0000e000 to 0x0000ffff...
Flash will be erased from 0x00f70000 to 0x00fb9fff...
Flash will be erased from 0x00010000 to 0x00057fff...
Compressed 15104 bytes to 10429...
Writing at 0x00000000... (100 %)
Wrote 15104 bytes (10429 compressed) at 0x00000000 in 0.2 seconds (effective 621.8 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 158...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (158 compressed) at 0x00008000 in 0.0 seconds (effective 765.1 kbit/s)...
Hash of data verified.
Compressed 8192 bytes to 47...
Writing at 0x0000e000... (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 1055.9 kbit/s)...
Hash of data verified.
Compressed 302800 bytes to 175756...
Writing at 0x00f70000... (9 %)
Writing at 0x00f7b368... (18 %)
Writing at 0x00f84251... (27 %)
Writing at 0x00f89a70... (36 %)
Writing at 0x00f8ef06... (45 %)
Writing at 0x00f94545... (54 %)
Writing at 0x00f99991... (63 %)
Writing at 0x00fa1308... (72 %)
Writing at 0x00faa2cf... (81 %)
Writing at 0x00fb0040... (90 %)
Writing at 0x00fb594c... (100 %)
Wrote 302800 bytes (175756 compressed) at 0x00f70000 in 2.0 seconds (effective 1182.6 kbit/s)...
Hash of data verified.
Compressed 293584 bytes to 168903...
Writing at 0x00010000... (9 %)
Writing at 0x0001bdd5... (18 %)
Writing at 0x000245ce... (27 %)
Writing at 0x00029c69... (36 %)
Writing at 0x0002f258... (45 %)
Writing at 0x0003452c... (54 %)
Writing at 0x00039b9d... (63 %)
Writing at 0x000421c2... (72 %)
Writing at 0x0004a9a9... (81 %)
Writing at 0x00050085... (90 %)
Writing at 0x00055bef... (100 %)
Wrote 293584 bytes (168903 compressed) at 0x00010000 in 2.0 seconds (effective 1167.1 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

Thanks. The log is perfect, so I don't understand what is happening on your board... To help me troubleshoot, can you please try the following procedure?

  • enter ROM bootloader via B1+GND (dim LED)
  • from the IDE do a Burn bootloader (not "Upload using programmer")
  • disconnect and reconnect the board => it should stay in the "dim LED" mode
  • in the IDE, from the examples open a Blink sketch
  • from the IDE do an Upload using programmer (make sure to select Esptool in the programmer) => the log should be the same as above
  • disconnect and reconnect the board

This will completely erase the Flash and restore the default programming on your board. At the end, the yellow LED should be blinking and it should be possible to simply "Upload" any other sketch; double pressing the reset button should land you in the "green fade".

Let me know anything that goes wrong or is different from what I described.

It worked - kind of... so I burned the bootloader, here is the log:

esptool.py v4.5.1
Serial port /dev/cu.usbmodem1401
Connecting...
Chip is ESP32-S3 (revision v0.2)
Features: WiFi, BLE
Crystal is 40MHz
MAC: 3c:84:27:c3:1e:3c
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 3.5s
Hard resetting via RTS pin...

Then I opened a blink sketch from the basic tab in example sketches, uploaded using a programmer on esp32 and the log was indeed the same as before. The dim rgb light turned off and the yellow led above D13 started blinking. Same happens after disconnecting and connecting the board again.

Now I uploaded my sketch, and it worked, but unfortunately only once.

The issue was the same as to before completely erasing the flash. After the uploading was done, the board disconnected and wouldn't reconnect, starting the rgb blinking without an end. After the complete flash wipe where it worked, it disconnected and reconnected like I was used to a week ago...

I was curious as to why so I wanted to do the whole procedure again, but while burning the bootloader, it showed me this error:

esptool.py v4.5.1
Serial port /dev/cu.usbmodem3C8427C31E3C2

A fatal error occurred: Could not open /dev/cu.usbmodem3C8427C31E3C2, the port doesn't exist
Failed chip erase: uploading error: exit status 2

Well yeah... do you have an idea how to continue from here? Also, thank you very much for the support. I hope we'll get to the root of this...

Thank you for the feedback, this is extremely interesting. I have a hunch, but I still cannot reproduce it here. :slightly_frowning_face:

If you don't do the B1+GND & RESET dance properly, you may sometimes end up in a state where you see the "dim led" but the CPU is still not in ROM bootloader - and you see the error you mentioned; it depends on the Flash contents. Simply try again, as the procedure is repeatable.

You successfully flashed Blink (via esptool), then your sketch (via DFU). As I want to be super clear on the details after you upload the sketch, I have some more questions to test your patience: :slightly_smiling_face:

  • Do you see the R-G-B fade (once!) at the end of the (second) upload?
  • Do you have any confirmation your sketch is running?
  • If it is running and you try to do another DFU upload, does the upload in itself work or does the IDE show an error?
  • What happens on the board after this upload? (It should by itself do the RGB fade once then start the new program). Let me know if you ever have to press RESET or power cycle the board at any time.

One other thing - can you try uploading only the Blink sample several times, changing the delays so that you know it is always updating? Anything different?

I'll keep digging! :hammer_and_wrench:

I think I tried 4 or 5 times where it failed - closed my IDE and tried again and then it decided to work (burning bootloader)... After the whole procedure, after uploading the blink sketch, now my sketch wouldn't upload even once. But this time I selected pin numbering by GPIO pins (legacy)? This could also be potential issue?

Now every time I close the IDE and open it up again the burning of the bootloader works...

Also sometimes I get this weird log:

Sketch uses 293221 bytes (9%) of program storage space. Maximum is 3145728 bytes.
Global variables use 31584 bytes (9%) of dynamic memory, leaving 296096 bytes for local variables. Maximum is 327680 bytes.
esptool.py v4.5.1
Serial port /dev/cu.usbmodem11401
Connecting....
Chip is ESP32-S3 (revision v0.2)
Features: WiFi, BLE
Crystal is 40MHz
MAC: 3c:84:27:c3:1e:3c
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Flash will be erased from 0x00000000 to 0x00003fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Flash will be erased from 0x0000e000 to 0x0000ffff...
Flash will be erased from 0x00f70000 to 0x00fb9fff...
Flash will be erased from 0x00010000 to 0x00057fff...
Compressed 15104 bytes to 10429...
Writing at 0x00000000... (100 %)

A fatal error occurred: Invalid head of packet (0x45): Possible serial noise or corruption.

So after the upload of my sketch I do see the RGB fade but not just once, as it loops forever. Usually my confirmation on the fact that is running is based on whether or not I get print outputs on the serial monitor. The upload itself on the IDE sometimes either seems to be successful, as it notifies me as "Done uploading", or it uploads for a while then throw this error at me:

Port monitor error: command 'open' failed: no such file or directory. Could not connect to /dev/cu.usbmodem3C8427C31E3C2 serial port.

(I assume it's because IDE (correctly) assumes I disconnected it)

However the Arduino, with both outcomes, wouldn't reconnect and I'd have to press the reset button for it to connect again - and then when I go to the serial monitor tab, my code wouldn't run.

Actually I tested it again and again... after wiping the flash everything does seem to work fine. I could upload the blink sketch as often as I wanted and changed the delays - and it would work.

Also uploading my own sketch works - what won't work is using the pin numbering by GPIO pin (legancy) at the pin numbering, so that really must be the issue.

Every time I tried to upload using this setting I would 'put some error' on my board and it wouldn't reconnect - and flash wiping does help.

This is also most likely why you weren't able to reproduce the error.

But then this bugs me because it used to work fine with the GPIO pin numbering - I tested my code just last week so I didn't think too much about that... I changed from standard arduino pins to GPIO because of a previous issue as the pin numbering on arduino lead to eg. assigning the interruptISR to another pin than intended...

I hope you can work with these new infos

1 Like

3 posts were split to a new topic: Re: Upload on Nano ESP32 won't complete

@alexaccountrelatedemails Thanks. I do have a proper fix for that interrupt issue, but haven't yet released the update because I wanted to understand this as well - turns out they're related! Will do some experiments with pin numbering as well and let you know.

1 Like

Ok what a surprise, tripped over both stones - and didn't know you were the developer for the software! Thank you, please keep me posted, as the project is kind of time-bounded. But no pressure!

And also, is there a reason why generally the Nano ESP32 compiling and uploading takes longer? Have seen someone of the forum asking about the same, but he couldn't get to the ends of that

There is a lot going on in any ESP32 code. Have a look at how many files are compiled. Even if they were compiled before, part of the verify process still needs to dig through all these files which takes time.

If you enable verbose output during compilation, you will see those files mentioned.

I See, thank you, makes sense

Still no luck with the blink sketch and "By GPIO" - it works every time. But your sketch looks like it might trip on one of the issues I am about to fix, so I would like you to test with the next version, it will probably come out early next week.

Just realized that I haven't asked you to downgrade to 2.0.13 (you can do that from the Boards Manager!) and test with that version. Sorry for not giving you the option earlier :man_facepalming: , but your feedback was very useful!

@alexaccountrelatedemails A new version of the Nano ESP32 core has been released in the Arduino ESP32 Boards package, and includes several fixes over 2.0.17.

Can you give the latest version a try and let us know if this issue is fixed as well? (After upgrading the core, please do update the bootloader on the board one last time :slightly_smiling_face:)

Thanks!

@lburelli Ok so I've tried different things and generally I can say that the problem still persists and my code doesn't work.

I've updated to the new version of the ESP32 core, the 2.0.18-20240930.arduino3. After burning the bootloader on the board I was able to upload successfully with both the standard Arduino Pin Numbering as well as the legacy GPIO numbering. However, the serial monitor wasn't responding, not printing anything, letting alone receiving signal from the transmitter. I had no clue what the issue could be, so I assumed it was perhaps due to this;

//  Declare pinout
const int p1_encoderPinA = 2;
const int p1_encoderPinB = 3;
const int p1_servoRPin = 6;
const int p1_servoLPin = 5;
const int receiverPin_A0 = A0;

So I uploaded the code with this change:

//  Declare pinout
const int p1_encoderPinA = D2;
const int p1_encoderPinB = D3;
const int p1_servoRPin = D6;
const int p1_servoLPin = D5;
const int receiverPin_A0 = A0;

And then the old issue would occur. It would disconnect without connecting again (Before adding the D prefix to fix potential misnumbering it would reconnect after disconnecting for the upload).

But still - that is quite strange because the misnumbering wouldn't really affect A0, which is my pin assigned to receive signals using pulseIn(), not even an external interrupt.

Thanks for the feedback. Since I'd like to make baby steps, can you confirm if you have any issue with a Blink sketch on the latest core?
Feel free to add a Serial.begin(9600) and a few Serial.print() here and there to test the serial monitor, and also try any combination of pin numbering. Updates should be repeatable and smooth.

I prefer to make sure that works fine before moving to debug your sketch - otherwise we might miss the forest for the trees :slight_smile:

@lburelli The Blink sketch works just as intended. Both using legacy GPIO pin numbering and default Arduino pin numbering.

I assigned random pins and it worked again for both pin numbering systems. Even adding the D prefix... which seemed weird to me. So I tried my code again...

And it didn't work :sweat_smile: Now I really can't think of anything. It is probably related to my code... This is what I tried uploading (didn't change from the start):

//  Importing external libraries
#include <ESP32Servo.h>
#include <Encoder.h>

//  Declare pinout
const int p1_encoderPinA = D2;
const int p1_encoderPinB = D3;
const int p1_servoRPin = D4;
const int p1_servoLPin = D5;
const int receiverPin_A0 = A0;

const int signalPuffer = -5;  //  Increase puffer if servo twitches at end positions
const int averageFactor = 2;  //  Increase factor for more stable inputs, but slower computation

const int p1_minConstrainValue = 1000 - signalPuffer;
const int p1_maxConstrainValue = 1500 - signalPuffer;
const int p1_minServoSpeed = 55;  //  lowest == 0
const int p1_maxServoSpeed = 125; //  highest == 180
const int stopServoValue = 90;

const int p1_maxEncoderPosition = 40; //  Change according to how far P1 is allowed to roll

//  Variables for interruptISR && encoder
unsigned long p1_lastIncReadTime = micros();
unsigned long p1_lastDecReadTime = micros();
volatile int p1_encoderPosition = 0;
int p1_encoderTargetPosition = 0;

//  Create encoder
Encoder p1_encoder(p1_encoderPinA, p1_encoderPinB);

//  Create servos
Servo p1_servoR;
Servo p1_servoL;

void setup() {
  //  Setup role for each pin
  pinMode(receiverPin_A0, INPUT_PULLUP);
  pinMode(p1_encoderPinA, INPUT_PULLUP);
  pinMode(p1_encoderPinB, INPUT_PULLUP);
  pinMode(p1_servoRPin, OUTPUT);
  pinMode(p1_servoLPin, OUTPUT);

  //  Configure servos
  p1_servoR.attach(p1_servoRPin);
  p1_servoL.attach(p1_servoLPin);

  //  Enable external interrupt
  attachInterrupt(digitalPinToInterrupt(p1_encoderPinA), p1_encoderISR, CHANGE);
  attachInterrupt(digitalPinToInterrupt(p1_encoderPinB), p1_encoderISR, CHANGE);

  Serial.begin(9600);
}

void loop() {
  //  Gather <averageFactor> amount of samples and return median value
  int A0_averageReceiverValue = 0;
  for (int i = 0; i < averageFactor; i++) {
    A0_averageReceiverValue += pulseIn(receiverPin_A0, HIGH);
  }
  A0_averageReceiverValue /= averageFactor;

  //  Create segments that correspond to distinct <p1_encoderTargetPosition> to reference goal
  int p1_mappedReceiverValue = constrain(A0_averageReceiverValue, p1_minConstrainValue, p1_maxConstrainValue);
  float p1_fluctuationConstant = (p1_maxConstrainValue - p1_minConstrainValue) / p1_maxEncoderPosition;
  if (p1_mappedReceiverValue > p1_minConstrainValue) {
    for (int i = 1; i != p1_maxEncoderPosition; i++) {
      float maxFluctuationConverter = p1_minConstrainValue + i * p1_fluctuationConstant;
      float minFluctuationConverter = maxFluctuationConverter - p1_fluctuationConstant;
      if (p1_mappedReceiverValue <= maxFluctuationConverter && p1_mappedReceiverValue > minFluctuationConverter) {
        p1_encoderTargetPosition = i;
      } else if (p1_mappedReceiverValue > maxFluctuationConverter) {
        p1_encoderTargetPosition = p1_maxEncoderPosition - 1;
      }
    }
  }

  //  Future failsafe redundancy; measure current spike to detect resistance and reset encoderPosition
  //  Rotate servo according to relation between <p1_encoderPosition> and <p1_encoderTargetPosition>
  //  Failsafe feature so that <p1_encoderPosition> doesn't breach boundary
  if (p1_encoderPosition >= 0 && p1_encoderPosition <= p1_maxEncoderPosition) {
    if (p1_encoderPosition < p1_encoderTargetPosition) {
      //  Reverse following if roational direction is reversed
      p1_servoR.write(p1_minServoSpeed);
      p1_servoL.write(p1_maxServoSpeed);
    } else if (p1_encoderPosition > p1_encoderTargetPosition) {
      //  Reverse following if roational direction is reversed
      p1_servoR.write(p1_maxServoSpeed);
      p1_servoL.write(p1_minServoSpeed);
    } else {
      Serial.println("+-+-+Target position reached+-+-+");
    }
  } else {
    //  Failsafe feature so that <p1_encoderPosition> doesn't breach boundary
    Serial.println("***WARNING, OUT OF BOUNDARY***");
    if (p1_encoderPosition > p1_maxEncoderPosition) {
        int overstep = p1_maxEncoderPosition - p1_encoderPosition;
        p1_encoderPosition += overstep;
    } else {
        int overstep = p1_encoderPosition;
        p1_encoderPosition -= overstep;
    }
  }

  Serial.print("Stabilized A0 signal: ");
  Serial.println(A0_averageReceiverValue);
  Serial.print("P1 Encoder target position: ");
  Serial.println(p1_encoderTargetPosition);
  Serial.print(">>> P1 Encoder position: ");
  Serial.println(p1_encoderPosition);
}

void p1_encoderISR() {
  static uint8_t old_AB = 3;
  static int8_t encval = 0;
  static const int8_t enc_states[]  = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};

  old_AB <<=2;

  if (digitalRead(p1_encoderPinA)) old_AB |= 0x02;
  if (digitalRead(p1_encoderPinB)) old_AB |= 0x01;
  
  encval += enc_states[( old_AB & 0x0f )];

  if(encval > 3) {
    int changevalue = 1;
    p1_lastIncReadTime = micros();
    p1_encoderPosition = p1_encoderPosition + changevalue;
    encval = 0;
  }
  else if(encval < -3) {
    int changevalue = -1;
    p1_lastDecReadTime = micros();
    p1_encoderPosition = p1_encoderPosition + changevalue;
    encval = 0;
  }
}

Hello @alexaccountrelatedemails, thanks for the clarifications! Tried your sketch and it crashed, but the fix was easy on my side: since you are using low-level libraries, make sure you are using the "by GPIO number" option with that sketch.

@lburelli I did use by GPIO numbering. Tried both in fact, several times. 9 out of 10 tries my Arduino ESP32 won't reconnect and that one time it works (accidentally works idk) I don't get any signal from the transmitter, nor any simple Serial prints. I talked about it in post #16