Unwanted PinMode change during loop function

Hello,
I am having some difficulties while making this program run correctly.
I have an NodeMCU ESP32s V1.1 module (NodeMCU ESP32 pinout) and there are some pins which do not keep their configuration. They work fine during the set up() but as soon as the program enters the loop function and executes a part of the code that reads the touch sensors then the pins change their behaviour.
This pins are GPIO33 and GPIO32 which are used to read some reed switches.
GPIO25 and GPIO26 have the same functionality but they work fine all the time. All this pins are configured as INPUT_PULLUP.
The same happens with the inbuilt blue LED (GPIO2), I set it as OUTPUT. It works fine during the set up but as soon as the code exectutes the loop the LED does not light up (only a very dim light can be seen as if there was a pull up resistor active)
I have tested the functionality of all these three pins inside the set up() and they work fine. If I comment the lines of code wich read the touch sensors then everythig works fine. (The blue LED and GPIO32 and 33)
The only solution I found was to code the configuration of these pins inside the loop function, so that with every iteration the pin gets configured again.
I used GPIO16 with a resistor and and an LED to replace the inbuilt LED and works fine all the time. (That is why you wont see GPIO2 used in the program)

Does anyone have any idea if some of the functions used, millis() or touchRead() can cause some issues?

Here is the code:

#include <dummy.h>

//DEFINICIONES de pines

#define PWM_Corre 23    
#define in2_Corre 22    
#define in1_Corre 21    
#define standby 19      
#define in1_Gira 18     
#define in2_Gira 5      
#define PWM_Gira 17
#define botonAbre 27    
#define botonCierra 14  
#define botonGiraCW 12  
#define botonGiraCCW 13 
#define encoderC1 36    
#define encoderC2 39    
#define encoderG1 34    
#define encoderG2 35    
#define finalCorreA 25      //Reed switch works fine
#define finalCorreC 26      //Reed switch works fine
#define finalGiraCW 33     //Reed switch that fails
#define finalGiraCCW 32  //Reed switch that fails
#define sensTouch 40    
#define ledRojo 16      //Red LED

//DEFINICIONES PARA EL MOVIMIENTO DE LOS MOTORES
#define motorCorre 2              
#define motorGira 1               
#define abre 1                    
#define cierra -1                
#define CW 1                      
#define CCW -1                  
#define velMaximaCorre 255        
#define velMaximaGira 120         
#define velAproxCorre 200         
#define velAproxGira 80           
#define posAproxApertura 200      
#define posAproxCierre 500        
#define posAproxCW 200            
#define posAproxCCW 500         

//DECLARACION DE VARIABLES GLOBALES

volatile int posicion=0, angulo=0;      
byte comandoActivo=0;                   
int posicionAnterior=0, comandoActivoAnterior=0, anguloAnterior=0, limiteApertura=0, limiteCierre=1500, limiteCW=600, limiteCCW=0;
long int tAnterior=0;                   
byte fc1, fc2, fg1, fg2, fc1A, fc2A, fg1A, fg2A;

//MANEJO DE INTERRUPCIONES
//ENCODER 1
void ISR_C1_RISING(void){
  if(digitalRead(encoderC2)==0)posicion++;
  else posicion--;
  attachInterrupt(encoderC1, ISR_C1_FALLING, FALLING);
}

void ISR_C1_FALLING(void){
  if(digitalRead(encoderC2)==0)posicion--;
  else posicion++;
  attachInterrupt(encoderC1, ISR_C1_RISING, RISING);
}

void ISR_C2_RISING(void){
  if(digitalRead(encoderC1)==0)posicion--;
  else posicion++;
  attachInterrupt(encoderC2, ISR_C2_FALLING, FALLING);
}

void ISR_C2_FALLING(void){
  if(digitalRead(encoderC1)==0)posicion++;
  else posicion--;
  attachInterrupt(encoderC2, ISR_C2_RISING, RISING);
}

//ENCODER 2
void ISR_G1_RISING(void){
  if(digitalRead(encoderG2)==0)angulo++;
  else angulo--;
  attachInterrupt(encoderG1, ISR_G1_FALLING, FALLING);
}

void ISR_G1_FALLING(void){
  if(digitalRead(encoderG2)==0)angulo--;
  else angulo++;
  attachInterrupt(encoderG1, ISR_G1_RISING, RISING);
}

void ISR_G2_RISING(void){
  if(digitalRead(encoderG1)==0)angulo--;
  else angulo++;
  attachInterrupt(encoderG2, ISR_G2_FALLING, FALLING);
}

void ISR_G2_FALLING(void){
  if(digitalRead(encoderG1)==0)angulo++;
  else angulo--;
  attachInterrupt(encoderG2, ISR_G2_RISING, RISING);
}


//SETUP - CODIGO QUE SE EJECUTA SOLO UNA VEZ

void setup() {
Serial.begin(115200);               
pinMode(PWM_Corre, OUTPUT);         //Output pins config
pinMode(in2_Corre, OUTPUT);
pinMode(in1_Corre, OUTPUT);
pinMode(standby, OUTPUT);
pinMode(in1_Gira, OUTPUT);
pinMode(in2_Gira, OUTPUT);
pinMode(PWM_Gira, OUTPUT);
pinMode(ledRojo, OUTPUT);
pinMode(botonAbre, INPUT);          //Touch pins config
pinMode(botonCierra, INPUT);
pinMode(botonGiraCW, INPUT);
pinMode(botonGiraCCW, INPUT);
pinMode(encoderC1, INPUT_PULLUP);   //Input pins config
pinMode(encoderC2, INPUT_PULLUP);
pinMode(encoderG1, INPUT_PULLUP);
pinMode(encoderG2, INPUT_PULLUP);
pinMode(finalCorreA, INPUT_PULLUP);
pinMode(finalCorreC, INPUT_PULLUP);
pinMode(finalGiraCW, INPUT_PULLUP);
pinMode(finalGiraCCW, INPUT_PULLUP);

//Initial encoder state reading to assingn falling or rising adeges
if(digitalRead(encoderC1)==0)attachInterrupt(encoderC1, ISR_C1_RISING, RISING);
else attachInterrupt(encoderC1, ISR_C1_FALLING, FALLING);                           
if(digitalRead(encoderC2)==0)attachInterrupt(encoderC2, ISR_C2_RISING, RISING);     
else attachInterrupt(encoderC2, ISR_C2_FALLING, FALLING);                       

if(digitalRead(encoderG1)==0)attachInterrupt(encoderG1, ISR_G1_RISING, RISING);
else attachInterrupt(encoderG1, ISR_G1_FALLING, FALLING);                           
if(digitalRead(encoderG2)==0)attachInterrupt(encoderG2, ISR_G2_RISING, RISING);
else attachInterrupt(encoderG2, ISR_G2_FALLING, FALLING);                       

//Initial reed switches state reading.
fc1=digitalRead(finalCorreA); 
fc1A=fc1;
fc2=digitalRead(finalCorreC);
fc2A=fc2; 
fg1=digitalRead(finalGiraCW);
fg1A=fg1;
fg2=digitalRead(finalGiraCCW);
fg2A=fg2;

digitalWrite(ledRojo, HIGH);  //Red LED test
delay(1000);
digitalWrite(ledRojo, LOW);
}

//PROGRAMA PRINCIPAL BUCLE INFINITO
void loop() {

//Touch sensors reading
if(comandoActivo==1 && touchRead(botonAbre)<sensTouch && millis()-tAnterior>300){comandoActivo=0; tAnterior=millis();}    //If the command was already activ it turns it off (0).
if(touchRead(botonAbre)<sensTouch && millis()-tAnterior>300){comandoActivo=1; tAnterior=millis();}                     //If the command Si no estaba activo lo selecciona.

if(comandoActivo==2 && touchRead(botonCierra)<sensTouch && millis()-tAnterior>300){comandoActivo=0; tAnterior=millis();}
if(touchRead(botonCierra)<sensTouch && millis()-tAnterior>300){comandoActivo=2; tAnterior=millis();}

if(comandoActivo==3 && touchRead(botonGiraCW)<sensTouch && millis()-tAnterior>300){comandoActivo=0; tAnterior=millis();}
if(touchRead(botonGiraCW)<sensTouch && millis()-tAnterior>300){comandoActivo=3; tAnterior=millis();}

if(comandoActivo==4 && touchRead(botonGiraCCW)<sensTouch && millis()-tAnterior>300){comandoActivo=0; tAnterior=millis();}
if(touchRead(botonGiraCCW)<sensTouch && millis()-tAnterior>300){comandoActivo=4; tAnterior=millis();}

//End of touch sensors reading - If commented the program works fine

fg1=digitalRead(finalGiraCW);            //Read reed switches
fg2=digitalRead(finalGiraCCW);
fc1=digitalRead(finalCorreA);
fc2=digitalRead(finalCorreC);

//To test if the reed switches work fine this part of the code will be deleted or better implemented
if(fg1!=fg1A){digitalWrite(ledRojo, HIGH); delay(500); digitalWrite(ledRojo, LOW);}
if(fg2!=fg2A){digitalWrite(ledRojo, HIGH); delay(500); digitalWrite(ledRojo, LOW);}
if(fc1!=fc1A){digitalWrite(ledRojo, HIGH); delay(500); digitalWrite(ledRojo, LOW);}
if(fc2!=fc2A){digitalWrite(ledRojo, HIGH); delay(500); digitalWrite(ledRojo, LOW);}

switch (comandoActivo){
  case 0:                           //Parada
  digitalWrite(standby, LOW);       //Pongo el driver en standby
  digitalWrite(in1_Gira, LOW);      //Pongo todas las salidas en 0 (mas que nada por consumo electrico)
  digitalWrite(in2_Gira, LOW);
  digitalWrite(in1_Corre, LOW);
  digitalWrite(in2_Corre, LOW);
  analogWrite(PWM_Gira, 0);         
  analogWrite(PWM_Corre, 0);
  break;
  
  case 1:                   
  comandoActivo=mover_motor(motorCorre, abre, velMaximaCorre, velAproxCorre, posAproxApertura, limiteApertura); 
 
  
  break;

  case 2:                   //Cierra cortinas (corre)
  comandoActivo=mover_motor(motorCorre, cierra, velMaximaCorre, velAproxCorre, posAproxCierre, limiteCierre);
  break;
  
  case 3:                   
  comandoActivo=mover_motor(motorGira, CW, velMaximaGira, velAproxGira, posAproxCW, limiteCW);
  break;
  
  case 4:                   
  comandoActivo=mover_motor(motorGira, CCW, velMaximaGira, velAproxGira, posAproxCCW, limiteCCW);
  break;
  
  default:
  comandoActivo=0;
  break;
}


//Muestra datos por puerto serie
if(posicion!=posicionAnterior || angulo!=anguloAnterior || comandoActivo!=comandoActivoAnterior || fg1!=fg1A || fg2!=fg2A || fc1!=fc1A || fc2!=fc2A){
Serial.print("G: ");
Serial.print(fg1);
fg1A=fg1;
Serial.print(fg2);
fg2A=fg2;
Serial.print(" - C: ");
Serial.print(fc1);
fc1A=fc1;
Serial.print(fc2);
fc2A=fc2;
Serial.print(" - Posicion Gira: ");
Serial.print(angulo);
anguloAnterior=angulo;
Serial.print(" - Posicion Corre: ");
Serial.print(posicion);
posicionAnterior=posicion;  
Serial.print(" - Comando activo: ");
Serial.println(comandoActivo);
comandoActivoAnterior=comandoActivo;
}


}//Fin del loop ppal.

//FUNCIONES

byte mover_motor(byte numeroMotor, int sentido, int velMaxima, int velAproximacion, int posAprox, int limite){

/* Descripcion: Funcion que controla el movimiento de los motores

Valor que devuelve: Numero que representa el comando activo de los motores (0-parada / 1-apertura / 2-cierre / 3-giro CW / 4-giro CCW 
*/


//Programacion de motor y sentido de giro
if (numeroMotor==2 && sentido>0){digitalWrite(in1_Corre, HIGH); digitalWrite(in2_Corre, LOW);}   //Motor 2 sentido de giro +
if (numeroMotor==2 && sentido<0){digitalWrite(in1_Corre, LOW); digitalWrite(in2_Corre, HIGH);}   //Motor 2 sentido de giro -
if (numeroMotor==1 && sentido>0){digitalWrite(in1_Gira, HIGH); digitalWrite(in2_Gira, LOW);}     //Motor 1 sentido de giro +
if (numeroMotor==1 && sentido<0){digitalWrite(in1_Gira, LOW); digitalWrite(in2_Gira, HIGH);}     //Motor 1 sentido de giro -

//Seleccion de velocidad en funcion de la posicion (velocidad maxima o de aproximacion)
if(numeroMotor==2 && sentido>0 && posicion<=posAprox)analogWrite(PWM_Corre, velAproximacion);    //Si al abrir se llego al punto de aproximacion, usar la velocidad de aproximacion
if(numeroMotor==2 && sentido>0 && posicion>posAprox)analogWrite(PWM_Corre, velMaxima);           //Si al abrir no se alcanzo el punto de aproximacion, usar la velocidad maxima
if(numeroMotor==2 && sentido<0 && posicion>=posAprox)analogWrite(PWM_Corre, velAproximacion);    //Si al cerrar se llego al punto de aproximacion, usar la velocidad de aproximacion
if(numeroMotor==2 && sentido<0 && posicion<posAprox)analogWrite(PWM_Corre, velMaxima);           //Si al cerrar no se alcanzo el punto de aproximacion, usar la velocidad maxima
if(numeroMotor==1 && sentido>0 && angulo<=posAprox)analogWrite(PWM_Gira, velAproximacion);       //Si al girar CW se llego al punto de aproximacion, usar la velocidad de aproximacion
if(numeroMotor==1 && sentido>0 && angulo>posAprox)analogWrite(PWM_Gira, velMaxima);              //Si al girar CW no se alcanzo el punto de aproximacion, usar la velocidad maxima
if(numeroMotor==1 && sentido<0 && angulo>=posAprox)analogWrite(PWM_Gira, velAproximacion);       //Si al girar CCW se llego al punto de aproximacion, usar la velocidad de aproximacion
if(numeroMotor==1 && sentido<0 && angulo<posAprox)analogWrite(PWM_Gira, velMaxima);              //Si al girar CCW no se alcanzo el punto de aproximacion, usar la velocidad maxima

//Apagado del driver al activarse los finales de carrera
if(numeroMotor==2 && sentido>0 && finalCorreA==0){digitalWrite(standby, LOW), digitalWrite(in1_Corre, LOW), digitalWrite(in2_Corre, LOW); return 0;}    //Si se alcanza el final de carrera al abrir se apaga el motor y la funcion devuelve 0
if(numeroMotor==2 && sentido<0 && finalCorreC==0){digitalWrite(standby, LOW); digitalWrite(in1_Corre, LOW), digitalWrite(in2_Corre, LOW); return 0;}    //Si se alcanza el final de carrera al cerrar se apaga el motor y la funcion devuelve 0
if(numeroMotor==1 && sentido>0 && finalGiraCW==0){digitalWrite(standby, LOW); digitalWrite(in1_Gira, LOW); digitalWrite(in2_Gira, LOW); return 0;}      //Si se alcanza el final de carrera al girar CW se apaga el motor y la funcion devuelve 0
if(numeroMotor==1 && sentido<0 && finalGiraCCW==0){digitalWrite(standby, LOW); digitalWrite(in1_Gira, LOW); digitalWrite(in2_Gira, LOW); return 0;}     //Si se alcanza el final de carrera al girar CCW se apaga el motor y la funcion devuelve 0

digitalWrite(standby, HIGH);    //Habilito los motores
return comandoActivo;           //Devuelvo el valor del comando activo.

It seems likely that some process on the NodeMCU is resetting those pins.

So, consider using different pins, following this guide: ESP32 Pinout Reference: Which GPIO pins should you use? | Random Nerd Tutorials

Some are input only, which is what you want for switches.

I have taken into account all pin limitations according to the module I use which is this one:

NodeMCU ESP32 pinout

The input only pins are allready in use for the encoders.
For now I'd rather stick with the actual solution, which I don't like too much (configure the pins constantly on the loop). Otherwise I'll have to make PCB V2.0
Maybe there is a different approach or I can disable certain processes...I don't know...

I can disable certain processes

What have you done to investigate that? Surely people have had this problem before. I have used those pins on other ESP32 boards without issues.

I've read a thread (https://github.com/espressif/esp-idf/issues/285) but I don't undertand much as it is not Arduino code. Besides, the guy couldn't even configure the pins, I can, but they don't keep the configuration after calling millis() or touchRead().
I am going to change the code..maybe eliminate the millis() function and then the touchRead just to try something.....

Lots of useful information in that thread, and it is indeed "Arduino code". Plain old C, actually.

Test the following from that thread, changing OUTPUT to INPUT and enabling pullups if needed.

#define GPIO_BIT_MASK  ((1ULL<<GPIO_NUM_32) | (1ULL<<GPIO_NUM_33)) 
	gpio_config_t io_conf;
	io_conf.intr_type = GPIO_INTR_DISABLE;
	io_conf.mode = GPIO_MODE_OUTPUT;
	io_conf.pin_bit_mask = GPIO_BIT_MASK;
	io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
	io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
	gpio_config(&io_conf);

If something changes it back, you will have to stop that process, or use another ESP32 module that does not have this problem.

It could work. Maybe this is a more "permanent" way. Right now I won't be able to try. I am going on hollidays in a couple of hours. But i'll try as son as I arrive home.
What bothers me is that it works perfectly but then it loses the config. That is why I was asking if anyone knew of a process, pheripheral or something that could cause this issue.
Thanks a lot jremington for your time.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.