Codificador de rueda utilizando un sensor IR

5

Hice un codificador rotatorio utilizando un sensor IR y una rueda con radios impresos en blanco y negro. Todo parece funcionar pero me pregunto si hay una mejor manera de codificar esto. La señal IR se ve idealmente como una onda cuadrada y la tengo buscando el borde ascendente de cada onda. Luego calcule el tiempo entre los flancos ascendentes para calcular las RPM de la rueda.

int wheelPin = 11; // I/O pin for encoder
int count = 0; // number of encoder ticks 
bool rising = false; // bool for rising edge of encoder signal
double dt; // time between rising edges
long dtStore[2]; // FIFO array holding current and previous rising edge times
float rpm;

void setup(){
  Serial.begin(57600);
}

void loop() {
  int wheelVal = analogRead(wheelPin); // get encoder val

/* check to see if we are at a low spot in the wave.  Set rising (bool) so we know to expect a rising edge */

if (wheelVal < 200) {
  rising = true;
}

/* Check for a rising edge.  Rising is true and a wheelVal above 200 (determined experimentally)*/

if (rising && wheelVal > 200) {
   dtStore[0]=dtStore[1]; // move the current time to the previous time spot
   count++;
   dtStore[1] = millis(); // record the current time of the rising edge
   dt = dtStore[1]-dtStore[0]; // calculate dt between the last and current rising edge time
   rpm = (0.0625)/dt*1000*60; // RPM calculation
   rising = false; // reset flag
 } 
Serial.println(rpm);
}
    
pregunta JDD

4 respuestas

5

Hay dos cosas que debes hacer.

En primer lugar, implementar un poco de histéresis. Actualmente, parece que estás usando 200 como el umbral tanto en la dirección ascendente como descendente. Lo que siempre obtendrá con sensores analógicos es un poco de ruido. Esto significa que, incluso durante un flanco ascendente, es posible que a veces se vea un borde descendente pequeño. ¡Incluso podría verlo cruzar su umbral hacia arriba, luego hacia abajo y luego hacia arriba otra vez!

  • La línea verde muestra lo que esperas que esté produciendo tu sensor.
  • La línea roja muestra lo que probablemente está produciendo. En realidad, probablemente sea mucho peor que esto.
  • La línea morada es lo que quieres
  • La línea negra es lo que podrías estar obteniendo

Entonces, cuando la señal está aumentando, use 200 como su umbral. Y cuando la señal está cayendo, usa algo como 150 como umbral.

En segundo lugar, puedes usar los bordes ascendentes y descendentes para calcular tu velocidad. De esa manera puedes tener el doble de la tasa de actualización.

    
respondido por el Rocketmagnet
2

En cuanto a una "mejor manera de codificar esto", puedes usar el Comparador analógico que está en el chip Atmega. Funciona comparando los voltajes que están presentes en dos pines específicos del microcontrolador: AIN0 y AIN1. Agregue un potenciómetro que establezca un umbral para la transición en AIN1, luego conecte su sensor a AIN0. Cuando el voltaje del sensor está por encima del voltaje establecido por el potenciómetro, el comparador analógico puede configurarse para aumentar una interrupción; usted agrega su lógica a la rutina de servicio para esta interrupción.

Otra forma de codificar esto podría ser mediante el uso de la funcionalidad de interrupción externa en Atmega: obtienes una interrupción en el flanco ascendente o descendente de algún pin específico del microcontrolador, pero deberías hacer un acondicionamiento de señal usando un opamp separado para poder Para establecer el umbral y la histéresis.

Tendrías que recurrir a la programación de un "nivel AVR" C para hacer todo esto en lugar de la jerga de Arduino.

Editar Aún puedes hacer eso desde el entorno de Arduino, este es un sniplet sobre el uso del comparador analógico en arduino, solo usa las definiciones de avr-libc directamente dentro del código arduino:

void setup(){
  pinMode(7,INPUT);
  Serial.begin(9600);
  ACSR = B01011010; // comparator interrupt enabled and tripped on falling edge.
}

void loop(){
}

ISR(ANALOG_COMP_vect) {
  Serial.println("Interrupt Executed!")
}
    
respondido por el miceuz
2

Estoy haciendo algo bastante similar en este momento. Pero con dos diferencias:

  • Tengo un disparador schmitt (74HCT14) entre la fuente de señal y el controlador
  • No mido el tiempo entre dos bordes, pero cuento los bordes durante una cierta cantidad de tiempo y calculo las RPM a partir de la división del número de bordes y el tiempo

Me parece que generar una interrupción de frecuencia constante (como 1Hz) y contar pulsos es más fácil y más robusto que medir un tiempo en el rango de ms.

Pero quizás este enfoque no se aplique a su diseño.

    
respondido por el wollud1969
1

Además de la histéresis para las transiciones de nivel de señal analógica, es posible que desee utilizar un algoritmo de rebote una vez digitalizado. Establece que los temporizadores de rebote sean un valor pequeño en relación con la tasa de cambio esperada a la velocidad de rotación máxima.

Por ejemplo, Para 4 radios, el máximo de 120 rpm espera una salida de onda cuadrada de 8 Hz. Con un período de 125 ms, puede pagar temporizadores de rebote de, por ejemplo, 10 ms en cada transición. La idea es mantener 10ms "pequeños" en relación con sus tiempos de espera de 62.5ms. P.ej. una transición L-H podría forzar una salida 1 durante 10 ms, una transición H-L podría forzar una salida 0 durante 10 ms, etc.

    
respondido por el shuckc

Lea otras preguntas en las etiquetas