You dont have javascript enabled! Please enable it!

Caso práctico: probador de servos con Arduino UNO

Caso práctico: probador de servos con Arduino UNO — hero

Objetivo y caso de uso

Qué construirás: Un probador de calibración de servos independiente y multimodo que permite a los usuarios hacer un barrido manual, centrar automáticamente (1500µs) y probar los límites físicos de los servos estándar de hobby.

Por qué es importante / Casos de uso

  • Configuración de vehículos RC: Centrar perfectamente los servos de dirección y aceleración antes de colocar los brazos mecánicos (horns) del servo para garantizar una geometría de dirección simétrica.
  • Ensamblaje de brazos robóticos: Identificar los valores exactos en microsegundos de PWM (por ejemplo, de 500µs a 2500µs) para los límites físicos de las articulaciones y evitar así atascos mecánicos bruscos y que el motor se queme en tu código.
  • Diagnóstico de hardware: Probar rápidamente servos recuperados o sospechosos en busca de puntos muertos, engranajes desgastados o vibración excesiva (jitter) sin necesidad de escribir o flashear un script de prueba personalizado.
  • Prototipado rápido: Establecer una herramienta de banco permanente para accionar manualmente los enlaces y probar mecanismos durante la fase de diseño mecánico.

Resultado esperado

  • Una interfaz de control de hardware confiable que utiliza un potenciómetro leído por ADC para realizar ajustes de ángulo manuales suaves y de baja latencia.
  • Una entrada de botón con eliminación de rebotes (debounce) por software que alterna de manera fluida la máquina de estados del microcontrolador entre tres modos operativos: Control manual, Centro (90°) y Barrido automático (Auto Sweep).

Audiencia: Aficionados al hardware, desarrolladores de robótica y constructores de RC; Nivel: Intermedio

Arquitectura/flujo: Entradas de usuario (Potenciómetro y botón) → Microcontrolador (Lectura ADC y lógica de debounce) → Salida de señal PWM de 50Hz → Accionamiento del servomotor

Nota educativa de validación

Antes de publicar este caso, el contenido pasó la puerta automática de validación de Prometeo con estado PASS. El validador comprobó los bloques de código, la estructura del artículo, los comandos copiables y la coherencia con el catálogo de dispositivos soportados.

Evidencia de validación publicada

  • Resultado automático: PASS.
  • Estructura parseada: 3 apartados, 3 tablas y 2 bloques de código detectados antes de publicar.
  • Código comprobado: 1 Arduino/arduino-cli compile, 1 Bash/copy-paste checks.
  • Catálogo soportado: el texto se contrastó contra los perfiles de dispositivo validables de Prometeo y los stacks no soportados bloquean la publicación.
  • Hallazgos del informe: sin hallazgos bloqueantes.

Esta validación confirma compatibilidad sintáctica y de herramientas para el material publicado, pero no sustituye la prueba física sobre tu hardware, cableado y entorno exactos.

Nota educativa de seguridad

Este prototipo está diseñado estrictamente para uso de laboratorio educativo y calibración de banco de pequeños servos de hobby sin carga.
* Límites de energía: No intente alimentar servos de alto torque (por ejemplo, MG995, MG996R) o brazos robóticos multiservo directamente desde el pin de 5V del Arduino UNO. Hacerlo excederá los límites térmicos y de corriente del regulador de voltaje integrado, lo que podría destruir la placa Arduino o el puerto USB de su computadora.
* Peligros mecánicos: Incluso los servos pequeños pueden presentar un peligro de pellizco si están unidos a enlaces mecánicos rígidos. Realice siempre las pruebas de calibración iniciales con el brazo del servo (horn) desmontado o completamente libre de obstrucciones mecánicas.
* Idoneidad: Este dispositivo no es adecuado, ni está destinado a ser utilizado en sistemas de control críticos, aplicaciones RC aeroespaciales o cualquier entorno donde una falla pueda resultar en daños a la propiedad o lesiones.

Diagrama de bloques conceptual

Vista de alto nivel: qué entra, qué procesa cada bloque y qué sale del sistema.

Arquitectura funcional

Entradas de usuario (Potenciómetro y botón)

Microcontrolador (Lectura ADC y lógica de…

Salida de señal PWM de 50Hz

Accionamiento del servomotor

Flujo conceptual de señales y responsabilidades entre bloques del dispositivo.

Ruta de validación

Sketch

arduino-cli compile

Upload

Prueba funcional

Resumen conceptual de las herramientas usadas para comprobar el material publicado.

Requisitos previos

Para completar con éxito este tutorial, debe tener:
* Una comprensión básica de cómo utilizar una terminal o símbolo del sistema.
* Arduino CLI instalado en su estación de trabajo.
* Familiaridad con el prototipado básico en protoboard (comprender la continuidad a lo largo de los rieles de alimentación y las tiras de terminales).
* Comprensión de los conceptos básicos de la modulación por ancho de pulsos (PWM), específicamente el período estándar de 20 milisegundos y el ciclo de trabajo de 1–2 milisegundos utilizado por los servos estándar de hobby.

Materiales

Para este prototipo, necesitará exactamente los siguientes componentes:
* Arduino UNO R3 (ATmega328P): La placa del microcontrolador principal.
* Micro Servo SG90: Un servomotor estándar de hobby de 9 gramos.
* Potenciómetro de 10 kΩ: Un potenciómetro rotativo estándar (preferiblemente de variación lineal).
* Botón pulsador: Un interruptor táctil momentáneo estándar.
* Protoboard y cables puente (jumper wires): Para realizar conexiones sin soldadura.
* Cable USB Tipo A a Tipo B: Para conectar el Arduino UNO R3 a su computadora.

Configuración/Conexión

La configuración del hardware está diseñada para ser mínima, utilizando la resistencia pull-up interna del Arduino para el botón pulsador para reducir la cantidad de componentes externos.

Guía de cableado de componentes:

ComponentePin / TerminalConexión Arduino UNO R3Notas
Servo SG90Cable Marrón / NegroGNDConexión a tierra.
Servo SG90Cable Rojo5VConexión de alimentación (Solo para pruebas sin carga).
Servo SG90Cable Naranja / AmarilloPin Digital 9Señal de control PWM.
PotenciómetroTerminal Izquierdo (Pin 1)5VVoltaje de referencia para la lectura analógica.
PotenciómetroTerminal Central (Wiper)Pin Analógico A0Salida de voltaje variable (0-5V).
PotenciómetroTerminal Derecho (Pin 3)GNDReferencia a tierra.
Botón pulsadorTerminal 1Pin Digital 2Señal de entrada.
Botón pulsadorTerminal 2GNDCierra el circuito a tierra cuando se presiona.

Nota sobre el botón pulsador: Conectamos el botón directamente entre el Pin Digital 2 y Tierra. En el software, configuraremos el Pin 2 con INPUT_PULLUP. Esto mantiene el pin en un nivel lógico ALTO (5V) internamente. Cuando se presiona el botón, conecta el pin a tierra, llevando el nivel lógico a BAJO.

Nota sobre la alimentación del servo: El SG90 es un servo pequeño. Cuando está completamente sin carga (sin enlaces mecánicos conectados), puede obtener energía de forma segura del pin de 5V del Arduino UNO, que es suministrada por la conexión USB. Si conecta una carga mecánica al servo, consumirá más corriente y puede provocar que el Arduino se reinicie.

Código validado

El proyecto requiere dos archivos. El primero es el sketch principal de Arduino que contiene la lógica. El segundo es un script de shell simple para automatizar el proceso de compilación y carga utilizando Arduino CLI.

Sketch principal: servo_tester.ino

Cree un directorio llamado servo_tester y guarde el siguiente código dentro de él como servo_tester.ino.

Vista pública parcial del archivo validado. El código completo se muestra a miembros y en PDF/Print.

/*
 * Project: Servo Calibration Tester
 * Target: Arduino UNO R3 (ATmega328P)
 * Description: A multi-mode servo testing tool. Uses a potentiometer for manual
 * control and a pushbutton to cycle between Manual, Center, and Sweep modes.
 */

#include <Servo.h>

// Pin Definitions
const int SERVO_PIN = 9;
const int POT_PIN = A0;
const int BUTTON_PIN = 2;

// Servo Object
Servo testServo;

// State Machine Variables
enum TesterMode {
  MODE_MANUAL = 0,
  MODE_CENTER = 1,
  MODE_SWEEP  = 2
};

TesterMode currentMode = MODE_MANUAL;

// Button Debouncing Variables
int buttonState = HIGH;             // Current reading from the input pin
int lastButtonState = HIGH;         // Previous reading from the input pin
unsigned long lastDebounceTime = 0; // The last time the output pin was toggled
const unsigned long debounceDelay = 50;   // Debounce time in milliseconds

// Servo Sweep Variables
int sweepAngle = 0;
int sweepDirection = 1;
unsigned long lastSweepUpdate = 0;
const unsigned long sweepInterval = 15; // Milliseconds between sweep steps

// Telemetry Variables
unsigned long lastTelemetryTime = 0;
const unsigned long telemetryInterval = 500; // Update Serial every 500ms

void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  while (!Serial) {
    ; // Wait for serial port to connect
  }

  Serial.println("Initializing Servo Calibration Tester...");

  // Configure Pins
  pinMode(POT_PIN, INPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP); // Use internal pull-up resistor

  // Attach Servo
  // Using standard min/max pulse widths (1000us to 2000us)
  // Some SG90 servos respond better to 500us to 2400us, adjust if necessary.
  testServo.attach(SERVO_PIN, 1000, 2000);

  // Set initial position
  testServo.write(90);
  Serial.println("System Ready. Mode: MANUAL");
}

void loop() {
  handleButton();
  updateServo();
  sendTelemetry();
}

void handleButton() {
  int reading = digitalRead(BUTTON_PIN);

  // Check if the button state has changed
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }
// ... continúa para miembros en el código completo validado ...

🔒 Parte del código validado es premium. Con el pase de 7 días o la suscripción mensual podrás consultar el archivo completo validado.

/*
 * Project: Servo Calibration Tester
 * Target: Arduino UNO R3 (ATmega328P)
 * Description: A multi-mode servo testing tool. Uses a potentiometer for manual
 * control and a pushbutton to cycle between Manual, Center, and Sweep modes.
 */

#include <Servo.h>

// Pin Definitions
const int SERVO_PIN = 9;
const int POT_PIN = A0;
const int BUTTON_PIN = 2;

// Servo Object
Servo testServo;

// State Machine Variables
enum TesterMode {
  MODE_MANUAL = 0,
  MODE_CENTER = 1,
  MODE_SWEEP  = 2
};

TesterMode currentMode = MODE_MANUAL;

// Button Debouncing Variables
int buttonState = HIGH;             // Current reading from the input pin
int lastButtonState = HIGH;         // Previous reading from the input pin
unsigned long lastDebounceTime = 0; // The last time the output pin was toggled
const unsigned long debounceDelay = 50;   // Debounce time in milliseconds

// Servo Sweep Variables
int sweepAngle = 0;
int sweepDirection = 1;
unsigned long lastSweepUpdate = 0;
const unsigned long sweepInterval = 15; // Milliseconds between sweep steps

// Telemetry Variables
unsigned long lastTelemetryTime = 0;
const unsigned long telemetryInterval = 500; // Update Serial every 500ms

void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  while (!Serial) {
    ; // Wait for serial port to connect
  }

  Serial.println("Initializing Servo Calibration Tester...");

  // Configure Pins
  pinMode(POT_PIN, INPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP); // Use internal pull-up resistor

  // Attach Servo
  // Using standard min/max pulse widths (1000us to 2000us)
  // Some SG90 servos respond better to 500us to 2400us, adjust if necessary.
  testServo.attach(SERVO_PIN, 1000, 2000);

  // Set initial position
  testServo.write(90);
  Serial.println("System Ready. Mode: MANUAL");
}

void loop() {
  handleButton();
  updateServo();
  sendTelemetry();
}

void handleButton() {
  int reading = digitalRead(BUTTON_PIN);

  // Check if the button state has changed
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }

  // If the state has been stable longer than the debounce delay
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // If the button state has physically changed
    if (reading != buttonState) {
      buttonState = reading;

      // Only toggle mode if the new button state is LOW (pressed)
      if (buttonState == LOW) {
        cycleMode();
      }
    }
  }
  lastButtonState = reading;
}

void cycleMode() {
  if (currentMode == MODE_MANUAL) {
    currentMode = MODE_CENTER;
    Serial.println(">>> Mode Switched: CENTER (90 deg) <<<");
  } else if (currentMode == MODE_CENTER) {
    currentMode = MODE_SWEEP;
    Serial.println(">>> Mode Switched: AUTO-SWEEP <<<");
  } else {
    currentMode = MODE_MANUAL;
    Serial.println(">>> Mode Switched: MANUAL <<<");
  }
}

void updateServo() {
  switch (currentMode) {
    case MODE_MANUAL:
      {
        int potValue = analogRead(POT_PIN);
        // Map 10-bit ADC (0-1023) to Servo Angle (0-180)
        int targetAngle = map(potValue, 0, 1023, 0, 180);
        testServo.write(targetAngle);
      }
      break;

    case MODE_CENTER:
      {
        testServo.write(90);
      }
      break;

    case MODE_SWEEP:
      {
        if (millis() - lastSweepUpdate > sweepInterval) {
          lastSweepUpdate = millis();
          sweepAngle += sweepDirection;

          if (sweepAngle >= 180) {
            sweepAngle = 180;
            sweepDirection = -1;
          } else if (sweepAngle <= 0) {
            sweepAngle = 0;
            sweepDirection = 1;
          }
          testServo.write(sweepAngle);
        }
      }
      break;
  }
}

void sendTelemetry() {
  if (millis() - lastTelemetryTime > telemetryInterval) {
    lastTelemetryTime = millis();

    int currentAngle = testServo.read();
    int currentMicroseconds = testServo.readMicroseconds();

    Serial.print("Mode: ");
    switch (currentMode) {
      case MODE_MANUAL: Serial.print("MANUAL\t"); break;
      case MODE_CENTER: Serial.print("CENTER\t"); break;
      case MODE_SWEEP:  Serial.print("SWEEP \t"); break;
    }

    Serial.print(" | Angle: ");
    Serial.print(currentAngle);
    Serial.print(" deg | Pulse: ");
    Serial.print(currentMicroseconds);
    Serial.println(" us");
  }
}

Script de compilación: build.sh

Guarde este archivo en el directorio principal de servo_tester (o ajuste la ruta según corresponda). Hágalo ejecutable con chmod +x build.sh. Reemplace <PORT> con su puerto serie real (por ejemplo, /dev/ttyACM0 en Linux, COM3 en Windows).

#!/bin/bash

PORT="/dev/ttyACM0" # CHANGE THIS TO YOUR ACTUAL PORT
FQBN="arduino:avr:uno"
SKETCH_DIR="servo_tester"

echo "Updating Arduino core index..."
arduino-cli core update-index

echo "Installing AVR core if not present..."
arduino-cli core install arduino:avr

echo "Compiling sketch..."
arduino-cli compile --fqbn $FQBN $SKETCH_DIR

if [ $? -eq 0 ]; then
    echo "Compilation successful. Uploading to $PORT..."
    arduino-cli upload --fqbn $FQBN --port $PORT $SKETCH_DIR
    echo "Upload complete. Open your serial monitor at 115200 baud."
else
    echo "Compilation failed. Aborting upload."
    exit 1
fi

Comandos de compilación/flasheo/ejecución

Para compilar y cargar el firmware manualmente (si decide no usar el script de shell proporcionado), siga este flujo de trabajo estandarizado utilizando Arduino CLI.

Referencia de comandos

AcciónComando
Actualizar índicearduino-cli core update-index
Instalar Corearduino-cli core install arduino:avr
Compilararduino-cli compile --fqbn arduino:avr:uno servo_tester
Cargararduino-cli upload --fqbn arduino:avr:uno --port <PORT> servo_tester
Monitorizararduino-cli monitor --port <PORT> --config baudrate=115200

Flujo de trabajo

  1. Identifique su puerto: Conecte su Arduino UNO R3 a su computadora. Ejecute arduino-cli board list para encontrar el identificador del puerto (por ejemplo, /dev/ttyUSB0, /dev/ttyACM0 o COM3).
  2. Prepare el entorno: Ejecute los comandos de actualización e instalación del core para asegurarse de que su sistema tenga la última cadena de herramientas (toolchain) para ATmega328P.
  3. Compile el código: Ejecute el comando de compilación apuntando al directorio servo_tester. Verifique que no se devuelvan errores de sintaxis.
  4. Flashee el dispositivo: Ejecute el comando de carga (upload), reemplazando <PORT> con el puerto identificado en el paso 1.
  5. Monitorice la salida: Inicie el comando del monitor serie para observar la secuencia de arranque y la telemetría.

Validación paso a paso

Una vez que el código esté cargado y el monitor serie esté abierto, realice las siguientes comprobaciones agrupadas para validar el sistema.

  • Punto de control 1: Encendido e inicialización

    • Acción: Reinicie el Arduino.
    • Observación esperada: El monitor serie muestra «Initializing Servo Calibration Tester…» seguido de «System Ready. Mode: MANUAL». El servo debería moverse a una posición inicial de 90 grados.
    • Condición de éxito: La telemetría comienza a imprimirse cada 500ms mostrando «Mode: MANUAL».
  • Punto de control 2: Modo de barrido manual

    • Acción: Mientras está en modo MANUAL, gire el potenciómetro desde el extremo izquierdo hasta el extremo derecho.
    • Observación esperada: El brazo del servo gira suavemente junto con el movimiento del potenciómetro.
    • Condición de éxito: El monitor serie informa de ángulos que cambian suavemente de ~0° a ~180° y anchos de pulso que cambian de ~1000 µs a ~2000 µs.
  • Punto de control 3: Cambio de modo y centrado

    • Acción: Presione el botón pulsador una vez.
    • Observación esperada: El monitor serie muestra «>>> Mode Switched: CENTER (90 deg) <<<«. El servo se mueve inmediatamente a su punto central mecánico y se bloquea allí.
    • Condición de éxito: Girar el potenciómetro ahora no tiene efecto en el servo. La telemetría muestra exactamente 90 grados y 1500 µs.
  • Punto de control 4: Modo de barrido automático

    • Acción: Presione el botón pulsador por segunda vez.
    • Observación esperada: El monitor serie muestra «>>> Mode Switched: AUTO-SWEEP <<<«. El servo comienza a oscilar hacia adelante y hacia atrás automáticamente.
    • Condición de éxito: La telemetría muestra el ángulo incrementándose a 180, invirtiéndose, decrementándose a 0 y repitiéndose.
  • Punto de control 5: Volver al modo manual

    • Acción: Presione el botón pulsador por tercera vez.
    • Observación esperada: El sistema vuelve al modo MANUAL.
    • Condición de éxito: El servo se ajusta inmediatamente al ángulo dictado actualmente por la posición física del contacto (wiper) del potenciómetro.

Solución de problemas

SíntomaCausa probableSolución
El servo vibra erráticamente (jitters)Fuente de alimentación inestable o mala conexión a tierra.Asegúrese de que todos los pines de tierra (Arduino, Potenciómetro, Servo) estén conectados a un riel común. Revise los cables puente.
El Arduino se reinicia cuando el servo se mueveEl servo consume demasiada corriente (caída de voltaje / brownout).El servo está bajo carga mecánica. Desconecte la carga o alimente el servo desde una fuente externa de 5V (compartiendo las tierras).
Se ignora la pulsación del botón / disparos doblesEl retardo antirrebote (debounce delay) es demasiado corto o el cableado está suelto.Aumente debounceDelay en el código a 100ms. Verifique que el botón esté firmemente asentado en la protoboard.
El servo solo gira 90 grados en totalDesajuste en el mapeo del ancho de pulso PWM.Cambie testServo.attach(SERVO_PIN, 1000, 2000) a testServo.attach(SERVO_PIN, 500, 2400) para que coincida con los límites específicos de su SG90.
Error de compilación: «Servo.h: No such file»Falta la biblioteca estándar.Ejecute arduino-cli lib install Servo para asegurarse de que la biblioteca estándar esté disponible para el compilador.

Mejoras

Una vez que el prototipo base esté funcionando, considere estas mejoras agrupadas:

Actualizaciones de hardware
* Fuente de alimentación externa: Agregue una fuente de alimentación dedicada de 5V y 2A (como un UBEC o una fuente de banco) a los rieles de alimentación de la protoboard para probar servos de engranajes metálicos de servicio pesado y alto torque sin provocar caídas de voltaje (brownout) en el Arduino.
* Pantalla OLED: Agregue una pantalla OLED I2C de 0.96″ para mostrar el ángulo actual y el ancho de pulso directamente en el dispositivo, eliminando la necesidad de una computadora conectada y un monitor serie.

Mejoras de software
* Ajuste personalizado del ancho de pulso: Agregue un cuarto modo que utilice el potenciómetro para ajustar finamente los límites mínimo y máximo en microsegundos, permitiéndole mapear los puntos finales físicos exactos de servos de marcas genéricas.
* Modo de prueba de velocidad: Implemente un modo que ordene saltos instantáneos de 0° a 180° y mida el tiempo de la respuesta física, ayudando a verificar las especificaciones de velocidad del servo.

Lista de verificación

  • [ ] Arduino CLI está instalado y el core AVR está actualizado.
  • [ ] Los componentes están cableados de acuerdo con la tabla de Configuración (verificando la tierra común).
  • [ ] El botón pulsador está cableado correctamente para utilizar la resistencia pull-up interna.
  • [ ] servo_tester.ino se ha guardado en el directorio correcto.
  • [ ] El sketch se compila correctamente utilizando arduino-cli compile.
  • [ ] El firmware se carga correctamente en el puerto serie adecuado.
  • [ ] El monitor serie muestra la secuencia de inicialización a 115200 baudios.
  • [ ] El servo responde suavemente al potenciómetro en modo MANUAL.
  • [ ] El botón pulsador alterna con éxito a través de los tres modos operativos.

Encuentra este producto y/o libros sobre este tema en Amazon

Ir a Amazon

Como afiliado de Amazon, gano con las compras que cumplan los requisitos. Si compras a través de este enlace, ayudas a mantener este proyecto.

Carlos Núñez Zorrilla
Carlos Núñez Zorrilla
Electronics & Computer Engineer

Ingeniero Superior en Electrónica de Telecomunicaciones e Ingeniero en Informática (titulaciones oficiales en España).

Sígueme:
Scroll al inicio