En este tutorial muestro como usar el encoder FC-03 o encoder FZ0888 (Módulo sensor de velocidad de infrarrojos con el comparador LM393) o optointerruptor. Lo he implementado en las 4 ruedas del robot Andromina OFF ROAD para calcular la velocidad de giro de estas. Se ha elegido este encoder por que es el más económico que hay en el mercado. Este tutorial muestra las dos mejores soluciones para conectar el encoder FC-03 a Arduino UNO o MEGA sin tener problemas. El encoder se muestra a continuación:
![]() |
Encoder FC-03 |
![]() |
Foto del montaje del motor del robot, del encoder y del disco dentado. |
El funcionamiento básico de este sensor es el siguiente; Si se hace pasar cualquier cosa entre la ranura del sensor, este crea un pulso digital en el pin D0. Este pulso va de 0V a 5V y es una señal digital TTL. Luego con Arduino podemos leer este pulso.
A continuación describimos las diferentes partes del encoder:
![]() |
Principales partes del encoder |
Pines de conexión del módulo de velocidad (encoder FC-03):
VCC: Alimentación del módulo de 3,3V a 12V.
GND: Tierra.
D0: Señal digital de los pulsos de salida.
A0: Señal analógica de los pulsos de salida. Señal de salida en tiempo real. (normalmente no se usa).
Principales características técnicas:
Dimensiones: 32 x 14 x 7mm
La ranura de lectura del sensor tiene un ancho de 5mm.
Dos salidas, una Digital y otra Analógica.
LED indicador de alimentación.
LED indicador de los pulsos de salida del pin D0.
2-Pulsos malos: Con este encoder he tenido también problemas a la hora de leer los pulsos digitales que genera el comparador LM-393. Arduino UNO o MEGA lee más pulsos de los que se generan realmente. Lee del orden de 4 veces más pulsos de los que se generan realmente. He buscado información sobre este problema en internet y he encontrado poca. Por lo que he podido aprender, es que este sensor es muy sensible a las interferencias que se puede introducir en los pines VCC y GND. Si alimentamos el sensor desde el propio Arduino a 3,3V o 5V, El regulador de tensión del propio Arduino pueden introducir corrientes parásitas en el sensor. Produciendo que este no funcione correctamente.
Usando un osciloscopio conectado entre los pin D0 y GND y analizado los pulsos que se generan en el encoder. Ver las fotos siguientes:
Si miramos el pulso generado parece que es un pulso cuadrado correcto, pero si se amplia mucho el inicio del pulso se puede ver que el pulso no es cuadrado. Tal y como puede verse en la foto siguiente, la señal digital cuadrada TTL que genera el encoder FC-03 tiene rebotes al inicio del pulso.
Usando un osciloscopio conectado entre los pin D0 y GND y analizado los pulsos que se generan en el encoder. Ver las fotos siguientes:
![]() |
Señal del pulso digital del pin A0. |
![]() |
Señal del pulso analógico del pin D0. |
![]() |
Rebote inicial de la señal visto con un osciloscopio. |
![]() |
Rebote final de la señal visto con un osciloscopio. |
La solución mejor que propongo para solventar este problema es la siguiente.
4-Solución 1 ; En la figura siguiente se muestra el esquema básico que he realizado en esta solución. El truco consiste en colocar un condensador de polièster metalizado (o cerámico) entre el pin D0 y el pin GND. Yo he probado con varios condensador diferente. El que me ha dado mejor resultado es el condensador (562J 250v). Este condensador casi no deforma el pulso digital generado por el comparador LM393.
Esta solución es la que mejor que se puede adoptar. Ya que la he ensayado con diferentes placas de Arduino y nunca ha fallado. Yo he probado con Arduino UNO, MEGA y DUE.
Esta solución es la que mejor que se puede adoptar. Ya que la he ensayado con diferentes placas de Arduino y nunca ha fallado. Yo he probado con Arduino UNO, MEGA y DUE.
![]() |
Esquema de conexión del encoder con un condensador. |
También he probado con un condensador de 100nF (104), el cual también me ha dado buen resultado. Este condensador deforma más la señal del pulso digital, al ser de mayor capacidad, pero funciona correctamente. En las dos fotos siguientes muestro el condensador soldado a los dos pines del módulo de velocidad. En esta posición el condensador queda perfectamente integrado y no molesta para nada.
![]() |
Vista del condensador soldado a los dos pines |
![]() |
Vista frontal de módulo y el condensador soldado |
En la fotografía siguiente se aprecia la rampa de subida de un pulso del encoder con el condensador ya soldado. Podemos ver que los rebotes han desaparecido por completo.
![]() |
Inicio del pulso con los rebotes eliminados |
En la fotografía siguiente se aprecia la rampa de bajada de un pulso del encoder con el condensador ya soldado. Podemos ver que los rebotes han desaparecido, pero aún se aprecia unos pequeños escalones en la señal. Estas pequeñas oscilaciones no son captadas por el Arduino. El cual reconoce el pulso correctamente.
![]() |
Final del pulso con los rebotes eliminados |
5-Diseño : Este encoder se a implementado en el robot Andromina OFF ROAD. Para medir la velocidad del robot, podemos poner solo dos encoders en dos ruedas o poner 4 encoders en las 4 ruedas.
A continuación se enseña el esquema básico de la conexión de los 4 encoders FC-03 al Arduino MEGA para un robot 4x4. Este esquema no se puede implementar en el Arduino UNO ya que solo tiene 2 pines con interrupciones. El Arduino MEGA tiene 6 pines con interrupciones, que son ; 2, 3, 18, 19, 20 y 21.
En la foto siguiente se puede apreciar todas las piezas que conforman el conjunto motriz; la rueda, el disco dentado, el encoder, el motor del robot y el soporte del motor. He diseñado un disco dentado que se acopla a la llanta de la rueda. Este disco lo he diseñado con 20 dientes. Con este número de dientes el encoder tiene una óptima presición. También he diseñado un nuevo soporte de motor para poder atornillar el encoder al motor.
Vista del chasis del robot Andromina OFF ROAD. |
![]() |
Esquema del robot con los conexión de los 4 encoders. |
![]() |
Vista de todas las piezas que conforman el motor del robot. |
![]() |
Vista de como queda el encoder montado en el motor. |
Para que el encoder FC-03 funcione correctamente con Arduino UNO Original. Se tiene que alimentar el pin VCC del encoder con un voltaje de 3,3v, desde el pin de 3,3V del Arduino. De esta manera el encoder da una señal de pulsos sin interferencias. No se necesita colocar ningún condensador. Ver el esquema de conexión siguiente:
![]() |
Esquema de conexión del encoder alimentado a 3,3V. |
Si el pin VCC del encoder FC-03 se alimenta con una tensión de 5 Voltios se generan corrientes parásitas (rebotes) en la señal digital de pulsos y Arduino no lee bien los pulsos del encoder. Leyendo más pulsos de los que realmente se generan.
A continuación se muestran las diferentes señales que salen de los dos pines del módulo.
A continuación se muestran las diferentes señales que salen de los dos pines del módulo.
![]() |
Señal analógica de los pulsos de la salida del pin A0. |
![]() |
Señal digital de los pulsos de la salida del pin D0. |
![]() |
Señal digital de los pulsos de la salida del pin D0 con un condensador (104) |
Esta solució es correcta si no queremos poner un condensador. Pero estamos enviado a Arduino señales buenas y señales malas. lo que provoca más interrupciones de las realmente necessaris.
/// Variables //////////////////////////////////////////////////////////////////////////////////////////////////////////////
int encoder_pin = 2; //Pin 2, donde se conecta el encoder
unsigned int rpm = 0; // Revoluciones por minuto calculadas.
float velocity = 0; //Velocidad en [Km/h]
volatile byte pulses = 0; // Número de pulsos leidos por el Arduino en un segundo
unsigned long timeold = 0; // Tiempo
unsigned int pulsesperturn = 20; // Número de muescas que tiene el disco del encoder.
const int wheel_diameter = 64; // Diámetro de la rueda pequeña[mm]
static volatile unsigned long debounce = 0; // Tiempo del rebote.
//// Configuración del Arduino /////////////////////////////////////////////////////////
void setup(){
Serial.begin(9600); // Configuración del puerto serie
pinMode(encoder_pin, INPUT); // Configuración del pin nº2
attachInterrupt(0, counter, RISING); // Configuración de la interrupción 0, donde esta conectado.
pulses = 0;
rpm = 0;
timeold = 0;
Serial.print("Seconds ");
Serial.print("RPM ");
Serial.print("Pulses ");
Serial.println("Velocity[Km/h]");}
//// Programa principal ///////////////////////////////////////////////////////////////////////
void loop(){
if (millis() - timeold >= 1000){ // Se actualiza cada segundo
noInterrupts(); //Don't process interrupts during calculations // Desconectamos la interrupción para que no actué en esta parte del programa.
rpm = (60 * 1000 / pulsesperturn )/ (millis() - timeold)* pulses; // Calculamos las revoluciones por minuto
velocity = rpm * 3.1416 * wheel_diameter * 60 / 1000000; // Cálculo de la velocidad en [Km/h]
timeold = millis(); // Almacenamos el tiempo actual.
Serial.print(millis()/1000); Serial.print(" ");// Se envia al puerto serie el valor de tiempo, de las rpm y los pulsos.
Serial.print(rpm,DEC); Serial.print(" ");
Serial.print(pulses,DEC); Serial.print(" ");
Serial.println(velocity,2);
pulses = 0; // Inicializamos los pulsos.
interrupts(); // Restart the interrupt processing // Reiniciamos la interrupción
}
}
////Fin de programa principal //////////////////////////////////////////////////////////////////////////////////
///////////////////////////Función que cuenta los pulsos buenos ///////////////////////////////////////////
void counter(){
if( digitalRead (encoder_pin) && (micros()-debounce > 500) && digitalRead (encoder_pin) ) {
// Vuelve a comprobar que el encoder envia una señal buena y luego comprueba que el tiempo es superior a 1000 microsegundos y vuelve a comprobar que la señal es correcta.
debounce = micros(); // Almacena el tiempo para comprobar que no contamos el rebote que hay en la señal.
pulses++;} // Suma el pulso bueno que entra.
else ; }
Hola como puedo agregar 2 driver VNH2SP30 para los 4 sensores para manejar 4 motores DC,
ResponderEliminarmi email jfn.digital@gmail.com gracias
hola que tal,,,disculpa y para agregar 2 fc03 que agrego al programa de arduino , es decir necesito 2 sensores en el mismo programa,,,gracias y saludos
ResponderEliminarTienes que definir otra interrupción. Por ejemplo si usas la placa Arduino UNO tienes que definir la interrupción en el pin 3. Si usas otra placa tienes que ver en este enlace;
Eliminarhttps://www.arduino.cc/en/Reference/AttachInterrupt
Hola, definí ya dos interrupciones, y conecté un encoder al pin 2 y el otro al 3 de la placa arduinoUNO pero sólo me da los valores de uno, no de ambos, ¿Qué puedo hacer?
EliminarEste comentario ha sido eliminado por el autor.
ResponderEliminarMe resultó muy útil el post, gracias!
ResponderEliminarHola buenos días Lautarox. Si has hecho un proyecto con este tipo de encoder. Podríamos compartir la información. Yo puedo publicar una entrada en mi blog sobre lo que has hecho.
EliminarEste comentario ha sido eliminado por el autor.
ResponderEliminaruna pregunta... las tierras de alimentacion del motor, las tienes en común con la tierra del arduino?
ResponderEliminarNo las tierras de los motores las tengo conectadas a la placa que controla los motores. La los pines de control de los motores. La tierra del encoder esta conectada a la tierra del Arduino. Luego las tierras de las dos placas están conectadas a la fuente de alimentación.
EliminarTengo un encoder FC-03 y un Logo Siemens 230 RC a 220V ac,puedo conectar la salida DO del encoder para simular un contador?o necesito algo adicional para poder conectar??Saludos
ResponderEliminarHola Diego. Por lo que veo en las especificaciones técnicas del Logo Siemens 230 RC a 220V la alimentación es de 114 o 230V. No puedes conectar el FC-03 por que necesita una alimentación de como máximo 12V. Necesita un Logo versión de 12 V.
Eliminarhola amigo muchas gracias por el tutorial, tengo una duda como se le podria poner contador de kilometros?? saludos
ResponderEliminarPara poner un contador de kilómetros se debe de introducir una nueva fórmula que te vaya sumando los kilómetros o metros realizados. Por ejemplo debes de introducir una formula que te calculé la media de velocidad en un segundo o en 5 segundos. Calculamos la media de la velocidad y luego cada segundo o cada cinco segundo vamos calculando y sumando los metros realizados.
Eliminarigual por lo visto se puede sacar la distancia con el la medida de la rueda wheel_diameter y por cada pulso de 20 equivaldría a 201.061888 mm utilizando el perímetro igual eso podrias usar y ir sumándolo, la otra opción podría ser calculando la media de la velocidad, saludos espero poder aportar algo de ayuda
EliminarSi, és una solución mejor contando los pulsos y cada 20 pulsos es una vuelta de la rueda.
EliminarGracias, soy nuevo en este asunto, la verdad no entiendo como podria leer los 20 pulsos, lo unico que se me viene hacef es usaf un if(pulses==20) de ahi no se que mas hacer
Eliminarimpresionante el nivel del post!, es excelente, mis felicitaciones!
ResponderEliminarMuchas gracias Susana.
EliminarHola, estoy tratando de leer la señal del sensor utilizando un Arduino DUE, pero no me funciona, la tarjeta no es capaz de leer los pulsos, es obligatorio el condensador para este caso? Gracias
ResponderEliminarHola. Yo he usado las placas de Arduino UNO y MEGA originales con el programa del apartado 7 de arriba y funcionaba. Con la placa DUE debería de funcionar también.
EliminarHola. Las interrupciones del Arduino DUE tienen una nomenclatura diferente. Ya que a todos los pines se les puede implementar una interrupción. Puedes probar de cambiar esta linea de la configuración de la interrupción;
EliminarattachInterrupt(2, counter, FALLING); // Para Arduino DUE
Vale, lo voy a intentar, Gracias!
Eliminarhola Andrés. Si no funciona prueva cambiando a;
EliminarattachInterrupt(2, counter, RISING);
hola, me podrias explicar los pulsos que genera, para saber cual es la velocidad del motor?. Me refiero a cuantos pulsos corresponde a una RPM, como se puede calcular eso.
ResponderEliminarEspero tu ayuda porfavor!
Primero tienes que contar el número de muescas "ranuras" que tiene el disco del tu encoder. Por ejemplo; en mi ejemplo tiene 20 muescas = 20 pulsos.
EliminarLuego necesitas saber que reducción tiene tu moto reductor, si es que la tiene. Hay motores que no tienen engranajes y están directamente conectados a la rueda.
hola, el codigo me da un error de compilacion, counter no esta declarado
ResponderEliminarHasta cuantas RPM logra sensar el arduino uno?
ResponderEliminarerror de compilacion " counter " no declarado
ResponderEliminarNecesitas la librería
EliminarMuy útil tu post. Excelente que comentes después de cada línea de código. Me ayudo bastante, gracias.
ResponderEliminarHallo. Que buen tutorial, tendrás referencias sobre el funcionamiento del módulo? Como datasheets, algun libro que hable sobre el modulo o algo por el estilo. Gracias.
ResponderEliminarHola muy buen post, Excelente info. Me podrías compartir el archivo STL de la rueda dentada que se adosa a la rueda del auto y sirve para la lectura del encoder.
ResponderEliminarDesde ya muchas gracias
Mi correo es ricardoiribarren@uprosanluis.edu.ar
puedes subir un codigo de sensor IR con arduino y lcd para poder calcular la velocidad y la aceleracion que deben tener 4 o 6 sensores IR
ResponderEliminarEstimado.
ResponderEliminarAprecio mucho y te agradezco haber compartido tu experiencia con este sensor resulta muy útil para los que no tenemos osciloscopio y en estos temas a veces sufrimos problemas que no advertimos y nos amargan la vida por andar a ciegas.
Me atrevo a agregar un comentario referente a una experiencia personal.
Cuando se trabaja con placas experimentales y estos cables con terminales hembras o machos para insertar en las mismas, Antes de conectarlos verifiquen que tengan continuidad porque algunos vienen cortados y les puedo asegurar al menos en mi caso que con algunos circuitos he estado muchos días buscando por que no funcionan o funcionan mal revisando todo menos LA CONTINUIDAD de esos cables que era el verdadero problema de las fallas.
Cordiales saludos.
The Golden Nugget - titanium teeth k9 - Tioga Sports
ResponderEliminarGolden Nugget - titanium teeth titanium flashlight k9 - Tioga Sports · Golden Nugget - titanium teeth titanium block k9 - Tioga Sports · titanium apple watch band Golden Nugget - everquest: titanium edition titanium teeth k9 - titanium granite Tioga Sports
Hola cómo podría hacer q aparezcan los datos en una pantalla LCD 16*2 con i2C
ResponderEliminaroyeeee como que ocpuamos hacer un proyecto universitario que debemos aprovar y no le entendemos a tu codigo todo pedorro :) bendiciones
ResponderEliminar