Medir RPM ESP-32

¿Viste que el problema era el tiempo de antirrebote?
Te lo dije en #12, cabeza dura. :grin:

Lo de los rebotes te lo expliqué en el post anterior, no es que con el ESP haya más rebotes, es que (y acá si está bien empleado) es más sensible a esos rebotes.

Si tuvieras un osciloscopio verías que con ambos micros hay rebotes (porque los genera el optoacoplador independiente de lo que tenga conectado), pero el arduino a 5V es un poco más inmune ya que mientras los rebotes no superen los 3V, no los ve. Seguramente un Pro Mini en versión 3.3V tiene los mismos problemas o más que el ESP ya que el nivel alto es a partir de los 1.98V (0.6×3.3V) y sería aún más sensible.

Hacé una cosa, según la máxima velocidad (RPM) que pienses medir, calculá cada cuanto llegarían los pulsos, y ajustá el valor de tiempoDeRebote 1 o 2 mseg por debajo así te asegurás no perder pulsos y eliminar prácticamente cualquier rebote.
Incluso podrías usar micros() en lugar de millis() para tener un mejor ajuste.

Saludos

Si gatul, tenias razón el problema era el tiempo de antirrebote que era muy largo y no contaba los pulsos como debería ser.

Muchas gracias a todos por sus consejos que fueron de mucha ayuda, el problema ya quedo solucionado.

Saludos ruilviana, surbyte, gatul y gracias otra vez.

¡Excelente!

Saludos

Estoy muy sorprendido por el posible origen de los rebotes?

Si había demasiado rebote, lo note cuando primero quise hacer la prueba de contar ranuras. Apenas colocaba el encoder en el sensor y había realizado 11 cuentas de ranuras con solo colocarlo.

Puedes poner fotos que ayuden a entender.

Claro surbyte, te adjunto foto del problema que tenia cuando quería contar las ranuras del encoder:

Esos 16 números son los rebotes que tiene el ESP32 al introducir el encoder. Si le das rotación al motor existe todavía mas rebotes .

Esto se corrige colocando un tiempo de rebote en la interrupción para poder contar de manera correcta

Dime como esta armado tu optoacoplador.
Es esto nada mas.
imagen
Acabo de descubir que pones 5V en el lado de colector del opto, es asi o solo un esquema que encontraste y esta a 3.3V del propio ESP32?

Voy a repetir tu experiencia a ver que ocurre.

Ese diagrama es así, funciona conectando los 5V a los positivos del opto acoplador como viene indicado. Ese diagrama sirve si lo quieres alimentar con 5v ya sea con fuente externa o los 5V del ESP.

También funciona de esta manera si quieres usar los 3.3V del esp32, solo cambia la resistencia de 220 por 100 Ohms:

Funciona bien, lo único que no me gusta es la señal por que tiene ruido y llega dar lecturas de ±3 rpm y algunas veces ±5 rpm.

Jamás he visto ruido en una señal de optoacoplador, por eso te hago la pregunta. Si tienes ruido es porque falta filtrado. Agrega un electrolitico en bornes del terminal 3.3V y GND
Algo no esta bien pero el opto no puede generar rebotes. EL opto no es mecánico, como un switch que SI REBOTA.
Porque no miras la alimentación en un canal en simultáneo con la salida del opto?

¡Es un "ruido" óptico!

Hay 3 zonas: luz, penumbra y sombra, por eso hay lo que vulgarmente llamamos rebotes, por la maldita penumbra.

Y por eso los optoacopladores tipo rendija más caros tienen rendijas (valga la redundancia) que llegan hasta el grosor de un cabello y además tienen máscaras, para tratar de reducir la penumbra al mínimo.

Saludos

Ok @gatul lo tomo en cuenta, pero voy a hacer mis comprobaciones porque no lo puedo creer, me huele mas a un error sistemático, algo como que debería protegerse el ambiente (encerrar la lectura entre encoder y opto) para no tener contaminación ambiental en ese caso. He usado encoders y nunca tuve este problema pero no digo que no exista, solo que me sorprende no haberme topado con el.

hola surbyte y gatul, he observado en el serial plotter los picos que existen en la señal, hice un pequeño cambio al diagrama colocando un capacitor de 100 nF para disminuir esos picos:

Estos fueron los resultados:

La prueba la realice dejando cierto tiempo el encoder girando en el sensor con el capacitor y después lo retire, como se muestra en la figura con capacitor solo arroja picos hacia un lado.

Estoy realizando otro código para poder disminuir esos picos, la idea es tomar 5 muestras y promediarlo:

volatile int contador = 0; 
volatile int rpm= 0;
float rpmPromedio = 0;

int sensor = 16;

volatile unsigned long tiempoDeInterrupcionAnterior = 0;
#define tiempoDeRebote 12 

void IRAM_ATTR interrupcion(); // es para que la funcion se guarde en la memoria ram y no en la flash

void setup() {
  pinMode(sensor,INPUT);
  Serial.begin(115200);
  attachInterrupt(sensor,interrupcion,FALLING);
  //attachInterrupt(digitalPinToInterrupt(23),interrupcion,RISING);
}

  void loop(){
  contador=0;
  delay(1000);
  noInterrupts();
  
  for(int i=0;i<5;i++){  
    rpm= contador*3;
    delay(2);
    }
    
    rpmPromedio= rpm/5.0;
    interrupts();
    Serial.println(rpmPromedio);
    }

void  interrupcion(){
  if(millis() - tiempoDeInterrupcionAnterior > tiempoDeRebote){

   contador=contador+1;
   ///Serial.println(contador);
    
    tiempoDeInterrupcionAnterior = millis();
  }                                                            
}

fueron malos resultados por que no leyo nada solo me dio esto:

Estoy leyendo de filtros poder hacer un promedio para esa disminución que comentaba anteriormente.

saludos.

Y si... Por eso los encoders ópticos industriales vienen dentro de un receptáculo estanco, no es solo para aislarlos del polvo y demás, también de la contaminación lumínica.

Si pero ademas el uso del capacitor ya provocó cambios. Veremos como evoluciona el tema.

hola gatul, me di cuenta que el aire del ventilador o el movimiento de la mesa causaba ruido. No sabia que los encoders ópticos eran muy delicados.

Estuve probando este código para disminuir los pico de la señal utilizando un filtro de promedio móvil exponencial:

Código:

volatile int contador = 0; 
int sensor = 23;

//Filtro promedio movil exponencial
int rpmFiltrado = 0;
volatile int rpm = 0;
#define alpha 0.5


volatile unsigned long tiempoDeInterrupcionAnterior = 0;
#define tiempoDeRebote 12 

void IRAM_ATTR interrupcion(); // es para que la funcion se guarde en la memoria ram y no en la flash

void setup() {
  pinMode(sensor,INPUT);
  Serial.begin(115200);
  attachInterrupt(sensor,interrupcion,FALLING);
  //attachInterrupt(digitalPinToInterrupt(23),interrupcion,RISING);

}

  void loop(){
  contador=0;
  delay(1000);
  noInterrupts(); //Desconectamos la interrupción para que no actué en esta parte del programa

  rpm=contador*3;

  /*Estas condicionales sirven para estabilizar lo mas rapido 
  posible las rpm por que al principio existe un poco de retardo*/
  
  if(rpm == 0){
    rpmFiltrado = 0;
  }

  else if(rpm>0 && rpm<90){
    rpmFiltrado = rpm;
  }

  else{
    rpmFiltrado = (alpha*rpm) + ((1-alpha)*rpmFiltrado);
  }
  
  interrupts(); //Reiniciamos la interrupción
  Serial.print(rpm);
  Serial.print(" ");
  Serial.println(rpmFiltrado);
}

void  interrupcion(){
  if(millis() - tiempoDeInterrupcionAnterior > tiempoDeRebote){

   contador=contador+1;
   ///Serial.println(contador);
    
    tiempoDeInterrupcionAnterior = millis();
  }                                                            
}

Imagen de la señal en el Serial Plotter:

Aplicando zoom en la grafica anterior:

Se puede observar en la grafica que existe una disminución de los picos con el filtro. El único inconveniente es que hay un pequeño retardo al principio de dos o tres segundos como se puede apreciar en la curva de la señal.

Tengo una duda con el filtro, esta bien ese filtro o existen otros filtros para mejorar la señal?

Saludos.

No me refería a tanto como el aire de un ventilador... De hecho no debería influir en la parte óptica.

Probablemente lo delicado sea la parte mecánica y está influyendo en lo que "ve" el sensor.

Saludos