ESP32 Error Rebooting TACOMETRO RPM

Hola tengo el siguiente error el cual recibo por el monitor de serie
ya que el compilador de arduino no me da error es propio del esp23

alguien tiene idea de como solventarlo es un código de un tacómetro que estoy diseñando el cual compara la diferencia de tiempo entre dos pulsos el error me daba aunque no mande pulsos por el pin 23 (pin que se medirá para el calculo de RPM), cambie algunos valores iniciales a 1 para que no divida entre 0. Anterior mente me daba este error:

Guru Meditation Error: Core  1 panic'ed (IntegerDivideByZero). Exception was unhandled.

Core  1 register dump:
PC      : 0x400d114a  PS      : 0x00060830  A0      : 0x800d1c60  A1      : 0x3ffb2800  
A2      : 0x3ffc1354  A3      : 0x00000000  A4      : 0x00000014  A5      : 0x00000004  
A6      : 0x3ffb8874  A7      : 0x80000001  A8      : 0x00000000  A9      : 0x3ffb27e0  
A10     : 0x3ffc1354  A11     : 0x00000000  A12     : 0x0000000a  A13     : 0x00000003  
A14     : 0x00000001  A15     : 0x00000000  SAR     : 0x00000009  EXCCAUSE: 0x00000006  
EXCVADDR: 0x00000000  LBEG    : 0x40085e98  LEND    : 0x40085ea3  LCOUNT  : 0x00000000  


Backtrace:0x400d1147:0x3ffb28000x400d1c5d:0x3ffb2820 




ELF file SHA256: 0000000000000000

Rebooting...
ets Jul 29 2019 12:21:46

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1184
load:0x40078000,len:13160
load:0x40080400,len:3036
entry 0x400805e4

Cambiando lo ya dicho me da este Error al mandar pulso por el pin 23 :


assert failed: taskSelectHighestPriorityTaskSMP tasks.c:3446 (xTaskScheduled == pdTRUE)

Backtrace:0x40084340:0x3ffbd3a00x3ffbd45d:0x3ffbd480  |<-CORRUPTED
ELF file SHA256: 0000000000000000

Rebooting...
ets Jul 29 2019 12:21:46

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1184
load:0x40078000,len:13160
load:0x40080400,len:3036
entry 0x400805e4

En fin este es mi código espero me puedan ayudar:

bool auxPulso = 0;
//definen la cantidad de pulsos por vuelta y el tiempo que le corresponde
unsigned int pulsosvuelta = 1;
unsigned long int tiempo = 60000/pulsosvuelta;
unsigned long int anterior = 1;
unsigned long int RPM = 1;
unsigned long int RPMavrg = 1;
unsigned long int contador = 1;
unsigned long int RPMtotal = 1;


void pulsos() {
detachInterrupt(23);
delay(100);
if(auxPulso == 0)
{
anterior = millis(); 
auxPulso = 1;
 }
 else
   {
RPM = round((millis() - anterior)/tiempo);
RPMtotal = RPM + RPMtotal;
contador ++;
anterior = millis();
}
 {
  attachInterrupt(23, pulsos,RISING);
 }
}


void setup() {
Serial.begin(115200);
pinMode(23, INPUT_PULLUP);
attachInterrupt(23, pulsos, RISING); 
  Serial.flush(); 
}

void loop() {
delay(1000);
RPMavrg = round(RPMtotal/contador);
Serial.println(RPMavrg);
}

No puedes usar delay() dentro de una rutina de interrupción.
No se puede atender la interrupción del timer que maneja delay(), como resultado se cuelga el programa.

millis(), hmmm...
Creo que tal como la usas funciona pero a futuro ten presente que millis() no se actualiza hasta que no se salga de la rutina de interrupción.

La variable anterior debes declararla volatile porque se modifica dentro de la interrupción. O sea

volatile unsigned long anterior = 1;

Te recomiendo una mirada a
http://www.gammon.com.au/interrupts

Ok, ya no da error peor mide en 0 supongo que es por lo que dices al entrar en una interrupción ya no cambia millis por ende la diferencia de tiempo es 0

Cambie esta parte de esta manera y el error persiste :c
Lo que hice fue separar esto para que en una interrupción haga un punto y en la otra lo mida.

bool auxPulso = 0;
//definen la cantidad de pulsos por vuelta y el tiempo que le corresponde
unsigned int pulsosvuelta = 1;
unsigned long int tiempo = 60000/pulsosvuelta;
volatile long int anterior = 1;
unsigned long int RPM = 1;
unsigned long int RPMavrg = 1;
unsigned long int contador = 1;
unsigned long int RPMtotal = 1;


void pulsos() {
detachInterrupt(23);
if(auxPulso == 0)
{
anterior = millis(); 
auxPulso = 1;
Serial.println("paso 1");
 }
 else
   {
RPM = round((millis() - anterior)/tiempo);
RPMtotal = RPM + RPMtotal;
contador ++;
auxPulso = 0;
Serial.println("paso 2");
}
 {
  attachInterrupt(23, pulsos,RISING);
 }
}


void setup() {
Serial.begin(115200);
pinMode(23, INPUT_PULLUP);
attachInterrupt(23, pulsos, RISING); 
  Serial.flush(); 
}

void loop() {
delay(1000);
RPMavrg = round(RPMtotal/contador);
Serial.println(RPMavrg);
}

Empiezo a dudar que sea un error de rebote o ruido del sensor IR que estoy usando ya que que tengo risisng al pasar solo debería de hacer un pulso pero hace dos en este caso al pasar mi dedo por este marca pasa por paso 1 y paso 2 en el mismo lo que no me hace sentido es que probé este antes con otro codigo mas sencillo que realice y no me daba este error

No porque tu guardas el contenido de millis() en interrupciones diferentes, entonces si se actualiza.
Lo que no puedes hacer es por ejemplo comparar su valor al entrar a la interrupción y antes de salir, ahí si daría 0 porque no se actualiza mientras esté atendiendo tu interrupción.

¿No será que estás tratando de medir una frecuencia de más de 1KHz?
Ahí si la diferencia sería 0 .

Prueba con micros() en lugar de millis(), recuerda que debes dividir por 60.000.000 en lugar de 60.000

¿No leíste lo que te linkeé, no?
No puedes usar print() dentro de una ISR.

1 Like

Ok lo pruebo

Perdón pensé q solo en las internas como en temporizadores procedo a repararlo

Porque dentro de la interrupción vuelves a cargar la interrupción

  attachInterrupt(23, pulsos,RISING);

Eso se hace en el setup()
En el loop, se apaga la interrupción, se hacen las cuentas si corresponde y se vuelve a activar.
Quítala del final de

void pulsos() 

Moderador:
Porque tienes dos hilos con el mismo tema? Mismo código, etc.
Tienes una primer advertencia, la próxima de este tipo sanción x 1 dia x doble posteo.

SI utilizo el dettach no es necesario volver a poner attach entonces?
o quito ambos mejor.

Si usas deatach claro que debes volver a usarlo o no habrá mas interrupciones. Pero no lo usas en tu código.
Habitualmente se pone deatach antes de esto

detachInterrupt(23);
RPMavrg = round(RPMtotal/contador);
Serial.println(RPMavrg);
attachInterrupt(23, pulsos, RISING); 

Justo así lo tengo :c

el problema que detecto es que ya una ves poniendo en micros aun no tengo un valor en rpm me marca 0

Asi va el código actual bro pero sin resultados aun ´probé y si aumenta el contador pero no tengo valores en RPM y por ende tampoco en los cálculos que lo incluyan.

bool auxPulso = 0;
//definen la cantidad de pulsos por vuelta y el tiempo que le corresponde
unsigned int pulsosvuelta = 1;
unsigned long int tiempo = 60000000 /pulsosvuelta;
volatile long int anterior;
unsigned long RPM;
unsigned long RPMavrg;
volatile unsigned long contador;
volatile unsigned long RPMtotal;


void pulsos() {
detachInterrupt(23);
if 
if(auxPulso == 0)
{
anterior = micros(); 
auxPulso = 1;
 }
 else
   {
RPM = (micros() - anterior)/tiempo;
RPMtotal = RPM + RPMtotal;
contador ++;
anterior = micros(); 
}
{
  attachInterrupt(23, pulsos,RISING);
 }
}


void setup() {
Serial.begin(115200);
pinMode(23, INPUT_PULLUP);
attachInterrupt(23, pulsos, RISING); 
  Serial.flush(); 
}

void loop() {
delay(1000);

if (contador >= 1 )
{
RPMavrg = round(RPMtotal/contador);
Serial.print(RPMavrg);
Serial.print("      contador");
Serial.print(contador);
Serial.print("RPM");
Serial.print(RPM);
Serial.println("RPMtotal");
Serial.println(RPMtotal);
contador = 0;
RPMtotal = 0;
}
}

Como vas a poner detach dentro de la ISR? Va en el loop.

void pulsos() {
detachInterrupt(23);     // <=== ACA NO
if                       // <=== y esto? Se un poco mas prolijo! Si posteas cosas al menos pruébalas sino estas respondiendo en el aire.
if(auxPulso == 0)
{
anterior = micros(); 
auxPulso = 1;
 }
 else
   {
RPM = (micros() - anterior)/tiempo;
RPMtotal = RPM + RPMtotal;
contador ++;
anterior = micros(); 
}
{
  attachInterrupt(23, pulsos,RISING); // <=== ACA NO
 }
}

Mira lee este tutorial, y observa como se hacen las cosas.

Consejo:
Otra cosa. No se si te has dado cuenta que te respondemos con códigos ordenados y que tienen sangría. Intenta usar el autoformato y trabajar con mas orden.

Bueno el código quedo asi al final por si alguien ocupa un medidor de revoluciones que se obtenga por la diferencia de tiempo entre pulsos sin tener que hacer uso de temporizadores para poderse utilizar en múltiples plataformas sin tener q modificar el codigo:

// RPM MEDICION
 bool auxPulso = 0;
 //definen la cantidad de pulsos por vuelta y el tiempo que le corresponde
 unsigned int pulsosvuelta = 1;
 unsigned long int tiempo = 60000/pulsosvuelta;
 volatile long int anterior;
 unsigned long int RPM;
 unsigned long RPMavrg;
 volatile unsigned long contador;
 volatile unsigned long RPMtotal;

void pulsos(){ 
if(auxPulso == 0)
{
anterior = millis(); 
auxPulso = 1;
 }
 else
   {
RPM = tiempo/(millis() - anterior);
RPMtotal = RPM + RPMtotal;
contador ++;
anterior = millis(); 
}
}


void setup() {
  Serial.begin(9600);
pinMode(2, INPUT_PULLUP);
attachInterrupt(0, pulsos, RISING); 
  Serial.flush(); 

}

void loop() {
  if(contador >= 1)
  {
  delay(1500);
RPMavrg = RPMtotal/contador;
contador = 0;
RPMtotal = 0;
Serial.print("RPM: ");
Serial.println(RPMavrg);
}
}

Tu código tiene algunos errores o cosas de mas.

    anterior = millis();

lo pones asi no importa que ocurra, si auxpulso = 0 o si no lo es. Si es el caso entonces colocalo fuera de los condicionales.
Además como hablas de millis() anterior podria llegar a tomar el mismo valor que millis() en cuyo caso la resta daría 0 y todo número dividido por 0 te da un error en el microcontrolador.

    RPM = tiempo / (millis() - anterior);

tienes que preguntar que anterior != millis()
No creo que con un delay(1500) las cuentas de RPM te den correctamente en RPM.
El delay() debe ser de 1000mseg
Salvo x ese contador que actua como promedio. Algo raro.
Busca en el foro ejemplos de medicion de RPM.
Se cuentas pulsos dentro de una ventana de 100 o 1000 mseg y como te dije luego de hacerlo se detienen las interrupciones y luego se vuelven a activar. En el proceso de presentacion ocurrren cuentas que generar errores.
Ahora dichos errores los enmascaras usando promedio, pero te aseguro que si un motor gira normal, sus RPM son constantes o muy estables.

1 Like

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