You dont have javascript enabled! Please enable it!

Caso práctico: Bucle cerrado: Arduino Due+TMC2209+AS5600

Caso práctico: Bucle cerrado: Arduino Due+TMC2209+AS5600 — hero

Objetivo y caso de uso

Qué construirás: Un sistema de control de motor paso a paso utilizando Arduino Due, TMC2209 y AS5600 para lograr un posicionamiento preciso en bucle cerrado.

Para qué sirve

  • Control de motores paso a paso en aplicaciones robóticas para movimientos precisos.
  • Automatización de procesos industriales donde se requiere un posicionamiento exacto.
  • Desarrollo de impresoras 3D que necesitan un control de posición de alta precisión.
  • Uso en sistemas de control de cámaras para seguimiento automático.

Resultado esperado

  • Latencia de respuesta del sistema inferior a 10 ms en el control del motor.
  • Precisión de posicionamiento de ±0.1 grados en el motor paso a paso.
  • Capacidad de manejar hasta 1000 pulsos por segundo sin pérdida de pasos.
  • Consumo de energía optimizado, manteniendo el driver TMC2209 en modo standby cuando no está en uso.

Público objetivo: Ingenieros y desarrolladores de sistemas embebidos; Nivel: Avanzado

Arquitectura/flujo: Arduino Due controla el TMC2209, que a su vez gestiona el motor paso a paso, mientras que el AS5600 proporciona la retroalimentación de posición y el HM-10 BLE permite la comunicación inalámbrica.

Nivel: Avanzado

Prerrequisitos

Sistema operativo y versiones probadas

  • Linux:
  • Ubuntu 22.04.4 LTS (x86_64)
  • Windows:
  • Windows 11 Pro 23H2 (x64)
  • macOS:
  • macOS 14 Sonoma (Apple Silicon o Intel)

Nota: Las instrucciones de compilación y flasheo se muestran para Linux y Windows; en macOS son equivalentes a Linux con Homebrew/Paths ajustados.

Toolchain exacta

  • Arduino CLI 0.35.3
  • Núcleo de placas (core) Arduino SAM (para Arduino Due): arduino:sam 1.6.12
  • Librerías Arduino:
  • TMCStepper 0.7.3
  • DueTimer 1.7.2
  • Compilador ARM (incluido en el core arduino:sam)
  • Software auxiliar (opcional para validación):
  • Python 3.10.x con screen/minicom (Linux) o PuTTY (Windows) para consola serie
  • App BLE en smartphone (nRF Connect, LightBlue u otra consola BLE)

Materiales

  • Dispositivo exacto del proyecto:
  • Arduino Due + TMC2209 stepper drivers + AS5600 encoders + HM-10 BLE
  • Componentes específicos:
  • 1x Arduino Due (SAM3X8E, 3.3 V)
  • 1x Driver TMC2209 en módulo (ej. BigTreeTech TMC2209 v3.x) con R_SENSE ≈ 0.110 Ω
  • 1x Motor paso a paso NEMA17 (200 pasos/rev) adecuado para TMC2209
  • 1x Sensor magnético AS5600 (I2C, 12-bit), con imán diametral emparejado
  • 1x Módulo BLE HM-10 (breakout con regulador y nivel lógico 3.3 V)
  • Fuente de alimentación para motor: 12–24 V DC (capacidad según motor; típico 24 V/3 A)
  • Alimentación para lógica: la propia del Arduino Due vía USB; compartir GND con la fuente de 24 V
  • Resistencias 1 kΩ (2 unidades) para UART de TMC2209 (half-duplex en PDN_UART)
  • Resistencias de pull-up I2C (opcional si tu módulo AS5600 ya las incluye): 4.7 kΩ a 3.3 V
  • Cables Dupont, protoboard (si aplica), y fijación mecánica del imán AS5600 al eje del motor

Notas:
– El Arduino Due opera a 3.3 V lógicos. Evita conectar señales de 5 V a sus pines.
– HM-10: usa un módulo que funcione de forma fiable a 3.3 V lógicos. Muchos breakouts aceptan 3.3–6 V en VCC y manejan logic-level a 3.3 V.

Preparación y conexión

Principios de la conexión

  • El TMC2209 se usará:
  • En modo STEP/DIR para el movimiento
  • Con comunicación UART para configuración (half-duplex en PDN_UART)
  • El AS5600 proporciona la posición angular absoluta por I2C (0x36). Implementaremos multiturno por software.
  • El HM-10 BLE crea una consola serie inalámbrica para enviar comandos de destino de posición y parámetros PID desde el móvil.
  • El Arduino Due:
  • Serial (USB) para log y depuración
  • Serial1 (pines 18/19) para HM-10
  • Serial2 (pines 16/17) para UART del TMC2209
  • I2C (SDA: 20, SCL: 21) para AS5600
  • Pines digitales para STEP/DIR/EN del TMC2209

Tabla de mapeo de pines y alimentación

Módulo/SeñalArduino Due pin/puertoMódulo externoNotas
STEP (TMC2209)D2STEP del TMC2209Pulsos de paso (activo flanco)
DIR (TMC2209)D3DIR del TMC2209Sentido de giro
EN (TMC2209)D4EN del TMC2209Activo en LOW para habilitar el driver
UART TX (TMC2209)TX2 (D16)PDN_UART del TMC2209 (via 1k)Half-duplex: ver esquema de resistencias abajo
UART RX (TMC2209)RX2 (D17)PDN_UART del TMC2209 (via 1k)Half-duplex: mismo nodo PDN_UART
Motor coilsA1 A2 B1 B2Conecta según datasheet del motor
VM (Driver)+12–24 VAlimentación potencia motor
GND (Driver)GNDGND comúnGND común con Arduino Due
AS5600 VCC3.3 VVCC del AS56003.3 V recomendado
AS5600 GNDGNDGND del AS5600
AS5600 SDASDA (D20)SDA del AS5600I2C 0x36; pull-ups a 3.3 V si el módulo no las tiene
AS5600 SCLSCL (D21)SCL del AS5600
HM-10 VCC3.3 VVCC del HM-10Usar módulo compatible 3.3 V
HM-10 GNDGNDGND del HM-10
HM-10 TXDRX1 (D19)TXD del HM-109600 8N1 por defecto
HM-10 RXDTX1 (D18)RXD del HM-10
USB (log)Programming Port USBPara subir firmware y ver logs serie (Serial)

Conexión UART TMC2209 (half-duplex):
– Conecta PDN_UART del TMC2209 a:
– Arduino Due TX2 a través de una resistencia de 1 kΩ
– Arduino Due RX2 a través de otra resistencia de 1 kΩ
– Si el módulo expone pin PDN/CFG, úsalo para UART. Consulta la hoja del módulo específico (algunos traen jumpers para activar UART).

Ajustes TMC2209:
– Microstepping objetivo: 1/16 microsteps (interpolación a 256 interna activa)
– Corriente RMS inicial: 800 mA (ajusta a tu motor térmicamente seguro)
– Modo stealthChop habilitado para suavidad a baja velocidad

Mecánica del AS5600:
– Monta el imán diametral en el eje del motor, centrado y a ~1–3 mm del chip según datasheet. Una desalineación reduce linealidad.

Código completo (Arduino Due, C++)

A continuación, un sketch integral que:
– Configura TMC2209 por UART
– Lee el AS5600 por I2C y genera conteo multiturno
– Implementa un control de posición en bucle cerrado con PID
– Genera STEP/DIR con limitación de velocidad y aceleración
– Expone una interfaz BLE (HM-10) para comandos GOTO, ZERO, KP/KI/KD, STATUS
– Emite logs por USB (Serial)

Bloques clave:
– ISR de control a 1 kHz
– ISR de generación de pasos a 40 kHz (tick 25 µs)
– Conversión ángulo AS5600 -> pasos (con multiturno)
– Parser de comandos BLE

// Proyecto: closed-loop-stepper-positioning con Arduino Due + TMC2209 + AS5600 + HM-10
// Toolchain: Arduino CLI 0.35.3, core arduino:sam 1.6.12
// Librerías: TMCStepper 0.7.3, DueTimer 1.7.2

#include <Arduino.h>
#include <Wire.h>
#include <TMCStepper.h>
#include <DueTimer.h>

// --------------------------- Configuración de pines ---------------------------
#define STEP_PIN        2
#define DIR_PIN         3
#define EN_PIN          4

// UART para TMC2209
HardwareSerial& TMC_UART = Serial2;   // TX2(D16), RX2(D17)

// UART para HM-10 BLE
HardwareSerial& BLE = Serial1;        // TX1(D18), RX1(D19)

// I2C AS5600
#define AS5600_ADDR    0x36
#define AS5600_RAW_ANGLE_H 0x0C
#define AS5600_RAW_ANGLE_L 0x0D

// ---------------------- Configuración eléctrica TMC2209 ----------------------
#define R_SENSE         0.110f
#define DRIVER_ADDRESS  0b00  // Ajustar si usas múltiples drivers
TMC2209Stepper driver(&TMC_UART, R_SENSE, DRIVER_ADDRESS);

// Microstepping
const uint16_t MICROSTEPS = 16;          // 1/16
const uint16_t FULL_STEPS_PER_REV = 200; // motor 1.8°
const uint32_t STEPS_PER_REV = FULL_STEPS_PER_REV * MICROSTEPS; // 3200

// -------------------- Control, cinemática y límites -------------------------
volatile int32_t target_pos_steps = 0;    // Objetivo en micro-pasos
volatile float   cmd_vel_steps_s = 0.0f;  // Velocidad comandada por el controlador [steps/s]
volatile float   max_vel_steps_s = 12000.0f;   // Límite velocidad
volatile float   max_acc_steps_s2 = 40000.0f;  // Límite aceleración

// PID de posición (error = target - measured)
volatile float Kp = 2.0f;
volatile float Ki = 0.0f;
volatile float Kd = 0.02f;
volatile float integ = 0.0f;
volatile float prev_err = 0.0f;

// Medición encoder multiturno
volatile uint16_t last_raw_angle = 0;
volatile int32_t turns = 0;            // conteo de vueltas (multiturno)
volatile int32_t zero_offset_counts = 0; // puesta a cero
const float steps_per_encoder_count = (float)STEPS_PER_REV / 4096.0f;

// Estado de paso
volatile float phase_accum = 0.0f;     // acumulador de fase para emitir pasos
volatile bool step_high = false;       // estado del pulso STEP
volatile int8_t motion_dir = 1;        // +1 fwd, -1 rev

// Telemetría
volatile int32_t measured_pos_steps = 0;  // posición medida [steps]
volatile int32_t commanded_pos_steps = 0; // posición comandada (integración de pasos emitidos)

// Buffers BLE
char ble_buf[96];
size_t ble_idx = 0;

// Timers
// controlTimer: 1 kHz, stepTimer: 40 kHz (25 us)
DueTimer controlTimer = DueTimer(3);
DueTimer stepTimer    = DueTimer(4);

// ---------------------- Utilidades de I2C para AS5600 -----------------------
uint16_t readAS5600RawAngle() {
  Wire.beginTransmission(AS5600_ADDR);
  Wire.write(AS5600_RAW_ANGLE_H);
  if (Wire.endTransmission(false) != 0) {
    return last_raw_angle; // si falla, devuelve último valor
  }
  Wire.requestFrom(AS5600_ADDR, 2u);
  if (Wire.available() < 2) {
    return last_raw_angle;
  }
  uint8_t high = Wire.read();
  uint8_t low  = Wire.read();
  uint16_t angle = ((high & 0x0F) << 8) | low; // 12 bits: [11:8] en high[3:0], [7:0] en low
  return angle;
}

// ---------------------- Inicialización del TMC2209 --------------------------
void initTMC2209() {
  pinMode(EN_PIN, OUTPUT);
  digitalWrite(EN_PIN, HIGH); // deshabilitado inicialmente (EN activo en LOW)

  TMC_UART.begin(115200);
  delay(50);

  driver.begin();              // Carga parámetros por defecto
  driver.toff(5);              // driver enable (sgnificant >0)
  driver.rms_current(800);     // mA RMS (ajusta según motor)
  driver.microsteps(MICROSTEPS);
  driver.pdn_disable(true);    // PDN/UART como UART, no power-down
  driver.I_scale_analog(false);
  driver.en_spreadCycle(false); // usar stealthChop
  driver.pwm_autoscale(true);   // calibración automática
  driver.TCOOLTHRS(0xFFFFF);    // umbral alto para stealthChop
  driver.semin(5); driver.semax(2); driver.sedn(0b01); // CoolStep básico

  digitalWrite(EN_PIN, LOW);   // habilitar driver
}

// ----------------------- ISR del control (1 kHz) -----------------------------
void controlISR() {
  // 1) Leer encoder y construir multiturno
  uint16_t angle = readAS5600RawAngle();
  int16_t delta = (int16_t)angle - (int16_t)last_raw_angle;

  // Detectar cruces (wrap) en ±2048 (la mitad de 4096)
  if (delta > 2048) {
    turns -= 1; // pasó por 0 hacia atrás
  } else if (delta < -2048) {
    turns += 1; // pasó por 0 hacia delante
  }
  last_raw_angle = angle;

  int32_t multi_counts = turns * 4096 + (int32_t)angle - zero_offset_counts;
  int32_t pos_steps = (int32_t)lroundf(multi_counts * steps_per_encoder_count);
  measured_pos_steps = pos_steps;

  // 2) Calcular error de posición
  int32_t err = target_pos_steps - measured_pos_steps;

  // 3) PID
  const float dt = 0.001f; // 1 ms
  float f_err = (float)err;
  float deriv = (f_err - prev_err) / dt;
  integ += f_err * dt;

  // anti wind-up sencillo: clamp integral
  const float integ_limit = max_vel_steps_s * 0.5f;
  if (integ > integ_limit) integ = integ_limit;
  if (integ < -integ_limit) integ = -integ_limit;

  float vel_cmd = Kp * f_err + Ki * integ + Kd * deriv;

  // 4) Acel/vel limitación (rampa)
  // Limitar aceleración incremental por periodo de control
  float dv_max = max_acc_steps_s2 * dt;
  float dv = vel_cmd - cmd_vel_steps_s;
  if (dv > dv_max) dv = dv_max;
  if (dv < -dv_max) dv = -dv_max;
  cmd_vel_steps_s += dv;

  // Limitar velocidad máxima
  if (cmd_vel_steps_s > max_vel_steps_s) cmd_vel_steps_s = max_vel_steps_s;
  if (cmd_vel_steps_s < -max_vel_steps_s) cmd_vel_steps_s = -max_vel_steps_s;

  // Configurar dirección deseada (se usa en generador de pasos)
  motion_dir = (cmd_vel_steps_s >= 0.0f) ? +1 : -1;
}

// ------------------- ISR del generador de pasos (25 us) ----------------------
void stepISR() {
  static bool need_low_after_high = false;

  if (need_low_after_high) {
    digitalWrite(STEP_PIN, LOW);
    need_low_after_high = false;
    // Actualiza posición comandada tras el flanco de bajada
    commanded_pos_steps += motion_dir;
    return;
  }

  // Incrementa el acumulador con |vel|*dt (dt = 25e-6 s)
  float inc = fabsf(cmd_vel_steps_s) * 0.000025f; // steps per tick
  phase_accum += inc;

  if (phase_accum >= 1.0f) {
    // Preparar pulso: fijar DIR primero
    digitalWrite(DIR_PIN, (motion_dir > 0) ? HIGH : LOW);
    // Emitir flanco de subida STEP
    digitalWrite(STEP_PIN, HIGH);
    need_low_after_high = true;
    phase_accum -= 1.0f;
  }
}

// ------------------------- Parser de comandos BLE ----------------------------
// Comandos:
// - GOTO <steps>
// - ZERO
// - KP <val>, KI <val>, KD <val>
// - VMAX <steps_s>, AMAX <steps_s2>
// - STATUS
void handleCommand(const char* line) {
  if (strncmp(line, "GOTO", 4) == 0) {
    long val = atol(line + 4);
    noInterrupts();
    target_pos_steps = (int32_t)val;
    interrupts();
    BLE.println(F("OK GOTO"));
  } else if (strncmp(line, "ZERO", 4) == 0) {
    noInterrupts();
    zero_offset_counts = turns * 4096 + (int32_t)last_raw_angle;
    target_pos_steps = 0;
    commanded_pos_steps = 0;
    interrupts();
    BLE.println(F("OK ZERO"));
  } else if (strncmp(line, "KP ", 3) == 0) {
    float v = atof(line + 3);
    noInterrupts(); Kp = v; interrupts();
    BLE.println(F("OK KP"));
  } else if (strncmp(line, "KI ", 3) == 0) {
    float v = atof(line + 3);
    noInterrupts(); Ki = v; integ = 0; interrupts();
    BLE.println(F("OK KI"));
  } else if (strncmp(line, "KD ", 3) == 0) {
    float v = atof(line + 3);
    noInterrupts(); Kd = v; interrupts();
    BLE.println(F("OK KD"));
  } else if (strncmp(line, "VMAX ", 5) == 0) {
    float v = atof(line + 5);
    noInterrupts(); max_vel_steps_s = v; interrupts();
    BLE.println(F("OK VMAX"));
  } else if (strncmp(line, "AMAX ", 5) == 0) {
    float v = atof(line + 5);
    noInterrupts(); max_acc_steps_s2 = v; interrupts();
    BLE.println(F("OK AMAX"));
  } else if (strncmp(line, "STATUS", 6) == 0) {
    noInterrupts();
    long t = target_pos_steps;
    long m = measured_pos_steps;
    long c = commanded_pos_steps;
    float v = cmd_vel_steps_s;
    float kp = Kp, ki = Ki, kd = Kd;
    interrupts();
    BLE.print(F("T=")); BLE.print(t);
    BLE.print(F(" M=")); BLE.print(m);
    BLE.print(F(" C=")); BLE.print(c);
    BLE.print(F(" V=")); BLE.print(v, 1);
    BLE.print(F(" KP=")); BLE.print(kp, 3);
    BLE.print(F(" KI=")); BLE.print(ki, 3);
    BLE.print(F(" KD=")); BLE.print(kd, 3);
    BLE.println();
  } else {
    BLE.println(F("ERR CMD"));
  }
}

void pollBLE() {
  while (BLE.available()) {
    char ch = BLE.read();
    if (ch == '\r' || ch == '\n') {
      if (ble_idx > 0) {
        ble_buf[ble_idx] = '\0';
        handleCommand(ble_buf);
        ble_idx = 0;
      }
    } else {
      if (ble_idx < sizeof(ble_buf) - 1) {
        ble_buf[ble_idx++] = ch;
      }
    }
  }
}

// ------------------------------- setup/loop ----------------------------------
void setup() {
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  digitalWrite(STEP_PIN, LOW);
  digitalWrite(DIR_PIN, LOW);

  Serial.begin(115200); // USB (Programming Port)
  while (!Serial) { ; }
  Serial.println(F("Init: Arduino Due closed-loop stepper with TMC2209 + AS5600 + HM-10"));

  BLE.begin(9600);      // HM-10 default
  Wire.begin();         // I2C

  // Inicializar TMC2209
  initTMC2209();

  // Inicializar AS5600 base
  last_raw_angle = readAS5600RawAngle();
  turns = 0;
  zero_offset_counts = 0;

  // Timers
  controlTimer.attachInterrupt(controlISR).setFrequency(1000).start(); // 1 kHz
  stepTimer.attachInterrupt(stepISR).setFrequency(40000).start();      // 40 kHz (25 us)

  Serial.println(F("Timers started. Send BLE commands: GOTO, ZERO, KP/KI/KD, VMAX/AMAX, STATUS"));
}

uint32_t lastLog = 0;

void loop() {
  // Consola BLE
  pollBLE();

  // Log periódico por USB
  uint32_t now = millis();
  if (now - lastLog > 500) {
    noInterrupts();
    long t = target_pos_steps;
    long m = measured_pos_steps;
    long c = commanded_pos_steps;
    float v = cmd_vel_steps_s;
    interrupts();
    Serial.print(F("[INFO] T=")); Serial.print(t);
    Serial.print(F(" M=")); Serial.print(m);
    Serial.print(F(" C=")); Serial.print(c);
    Serial.print(F(" V=")); Serial.print(v, 1);
    Serial.println();
    lastLog = now;
  }
}

Explicación breve de partes clave:
– initTMC2209 configura el driver para 1/16 microstepping, corriente RMS, stealthChop y UART activo en PDN.
– controlISR (1 kHz) ejecuta el PID de posición sobre la medición de AS5600; limita velocidad y aceleración para suavidad.
– stepISR (40 kHz) implementa un generador de pulsos con acumulador de fase: emite un pulso STEP cuando la “energía” acumulada supera 1 micro-paso.
– La multiturn del AS5600 detecta cruces por 0/4095 y ajusta un contador de vueltas; el comando ZERO re-referencia la posición a 0 pasos.
– La interfaz BLE acepta comandos de texto sencillos (por ejemplo: “GOTO 6400” para dos vueltas si 3200 steps/rev).

Compilación, flasheo y ejecución

A continuación, pasos reproducibles con Arduino CLI 0.35.3 usando Arduino Due (Programming Port).

Instalación de Arduino CLI y core arduino:sam

Linux (Ubuntu 22.04):

# 1) Instalar Arduino CLI 0.35.3 en $HOME/bin
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=$HOME/bin sh -s -- v0.35.3
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

# 2) Verificar versión
arduino-cli version
# Debe mostrar: arduino-cli Version: 0.35.3

# 3) Inicializar configuración
arduino-cli config init

# 4) Actualizar índice de cores y librerías
arduino-cli core update-index

# 5) Instalar el core Arduino SAM (Due)
arduino-cli core install arduino:sam@1.6.12

# 6) Instalar librerías necesarias
arduino-cli lib install "TMCStepper@0.7.3"
arduino-cli lib install "DueTimer@1.7.2"

Windows 11 (PowerShell):
– Descarga binario de Arduino CLI 0.35.3 para Windows desde GitHub Releases, agrega su carpeta al PATH del usuario.
– En PowerShell:

arduino-cli version
arduino-cli core update-index
arduino-cli core install arduino:sam@1.6.12
arduino-cli lib install "TMCStepper@0.7.3"
arduino-cli lib install "DueTimer@1.7.2"

Nota: En Windows, instala los drivers Arduino (incluidos con IDE o CLI) para el “Arduino Due (Programming Port)”. El puerto aparecerá como COMx.

Compilación y subida

1) Conecta el Arduino Due por el Programming Port (no el Native USB Port).
2) Guarda el sketch anterior como carpeta/proyecto, por ejemplo: closed_loop_due/closed_loop_due.ino
3) Identifica el puerto:
– Linux:

arduino-cli board list
# Ejemplo de salida:
# Port         Type              Board Name                 FQBN
# /dev/ttyACM0 Serial Port (USB) Arduino Due (Programming)  arduino:sam:arduino_due_x_dbg
  • Windows:
arduino-cli board list
# Buscar COMx correspondiente al "Arduino Due (Programming Port)"

4) Compila:

arduino-cli compile --fqbn arduino:sam:arduino_due_x_dbg closed_loop_due

5) Sube el firmware:

# Linux: ajusta el puerto si es distinto
arduino-cli upload -p /dev/ttyACM0 --fqbn arduino:sam:arduino_due_x_dbg --verify closed_loop_due

# Windows (PowerShell), ajusta COMx
arduino-cli upload -p COM5 --fqbn arduino:sam:arduino_due_x_dbg --verify closed_loop_due

6) Abre la consola serie para logs (USB):

# Linux
screen /dev/ttyACM0 115200
# o
minicom -D /dev/ttyACM0 -b 115200

En Windows, usa PuTTY/Serial a 115200 baudios en el COMx del Programming Port.

Validación paso a paso

Objetivo: demostrar “closed-loop-stepper-positioning” con el AS5600 como sensor de posición y el TMC2209 como actuador, con comandos BLE y telemetría por USB.

1) Revisión eléctrica de seguridad
– Verifica que EN del TMC2209 esté inicialmente en HIGH (driver deshabilitado) antes de dar alimentación de motor.
– Asegúrate de GND común entre fuente del motor, driver y Arduino Due.
– Alimenta el TMC2209 con 12–24 V, sin motor inicialmente, para comprobar que no hay sobrecorriente.
– Conecta el motor después de la verificación de alimentación.

2) Puesta en marcha del software
– Conecta el Programming Port del Due, sube el firmware (ver comandos).
– Abre el monitor serie a 115200 baudios. Debes ver:
– “Init: Arduino Due closed-loop stepper …”
– “Timers started. Send BLE commands: …”
– Si no ves mensajes, revisa que usas el Programming Port y que el puerto serie es correcto.

3) Prueba del encoder AS5600
– Sin cerrar el lazo, ejecuta comandos BLE para ver STATUS.
– Desde el móvil, con la app BLE:
– Empareja con HM-10 (nombre por defecto “HMSoft” o similar).
– Abre la UART BLE y envía “STATUS”.
– Debes recibir algo como: “T=0 M=0 C=0 V=0.0 KP=2.000 KI=0.000 KD=0.020”
– Gira el eje manualmente: el campo M (medida) debe cambiar; si cambia al revés de lo esperado, luego invertirás DIR en el cableado o en software.

4) Cierre de lazo básico con ZERO y GOTO
– Envía “ZERO”: pondrá el origen en la posición actual y fijará T=0.
– Envía “GOTO 3200”: objetivo 1 vuelta (microstepping 1/16 => 3200 µpasos).
– Observa:
– El motor debe acelerar, moverse y detenerse cerca del objetivo.
– En Serial (USB), verás logs de T, M, C, V. M debe converger a T con error pequeño.

5) Ajuste PID (si es necesario)
– Si hay sobreoscilación (overshoot) o vibración:
– Reduce Kp o aumenta Kd ligeramente. Ejemplo:
– “KD 0.05”
– “KP 1.5”
– Si hay error permanente:
– Introduce una pequeña Ki. Ejemplo: “KI 0.005”
– Verifica el comportamiento repitiendo GOTO a varios objetivos: 0, 1600, 3200, -1600, etc.

6) Verificación de límites VMAX y AMAX
– Envía “VMAX 8000” para bajar velocidad máx si el motor salta pasos.
– Envía “AMAX 20000” si notas golpes al arrancar; valores bajos suavizan el arranque/parada.
– Comprueba estabilidad frente a cambios de objetivo consecutivos.

7) Evaluación de seguimiento
– Compara M (medido) y C (comandado). En un buen ajuste, ambos serán cercanos y convergerán al objetivo T.
– Un desfase sostenido indica desajuste de PID o saturación (VMAX/AMAX demasiado bajos).

8) Comando sostenido y multiturno
– Prueba GOTO 12800 (≈4 vueltas) y regresa a 0.
– Asegura que el multiturno no presenta saltos (M crece/ decrece continuamente).

9) Comprobación BLE frente a USB
– Confirma que los comandos por BLE afectan al comportamiento y se reflejan en el log USB.

10) Prueba de carga
– Si es posible, aplica una ligera carga resistiva al eje y verifica que el lazo corrige el error y sostiene la posición.

Troubleshooting

1) El Due no aparece en la lista de puertos o la subida falla
– Causa: cable USB inadecuado (solo carga), drivers no instalados o puerto incorrecto.
– Solución:
– Usa un cable USB de datos y el Programming Port.
– En Linux: agrega tu usuario al grupo dialout: sudo usermod -a -G dialout $USER y reabre sesión.
– Verifica con arduino-cli board list y ajusta el puerto en upload.

2) El motor vibra o no se mueve al enviar GOTO
– Causa: fase de motor mal cableada (A/B invertidas) o microstepping/dir invertido.
– Solución:
– Intercambia una bobina (A1/A2) o B1/B2 para corregir vibración.
– Invierte el sentido DIR en software (cambia HIGH/LOW) o invierte el cable DIR.

3) El encoder mide al revés del movimiento
– Causa: convención de sentido opuesta entre AS5600 y pasos.
– Solución:
– Cambia el sentido DIR en software o multiplica measured_pos_steps por -1 en el cálculo, o invierte el imán 180°.

4) Pérdida de pasos a alta velocidad
– Causa: VMAX/AMAX excesivos, corriente insuficiente o tensión de alimentación baja.
– Solución:
– Reduce VMAX/AMAX (comandos VMAX/AMAX).
– Aumenta rms_current en TMC (recompila con mayor driver.rms_current dentro de límite térmico).
– Sube VM a 24 V si tu hardware lo permite.

5) TMC2209 no responde por UART (config no se aplica)
– Causa: cableado UART half-duplex incorrecto o PDN no configurado como UART.
– Solución:
– Verifica resistencias de 1 kΩ desde TX2 y RX2 al pin PDN_UART del TMC2209.
– Asegura driver.pdn_disable(true) y velocidad 115200 en TMC_UART.
– Comprueba jumpers del módulo (algunos requieren puentear para UART).

6) Lectura del AS5600 salta o es ruidosa
– Causa: imán descentrado, distancia inadecuada o cable I2C largo sin pull-ups adecuadas.
– Solución:
– Centra mejor el imán, ajusta la distancia a 1–3 mm.
– Añade pull-ups de 4.7 kΩ a 3.3 V en SDA/SCL si el módulo no las trae.
– Filtra con media móvil o un pequeño filtro derivativo (aumenta Kd, reduce Kp).

7) HM-10 no conecta o no recibe comandos
– Causa: módulo BLE a baudios distintos o sin alimentación correcta.
– Solución:
– Asegura BLE.begin(9600) y que tu HM-10 esté a 9600 (de fábrica).
– Verifica VCC 3.3 V y conexión TXD→RX1, RXD→TX1.
– Reinicia el módulo y vuelve a parear.

8) El lazo oscila o tarda demasiado en asentar
– Causa: PID mal ajustado.
– Solución:
– Empieza con Ki = 0, aumenta Kp hasta un ligero overshoot, añade Kd para amortiguar.
– Introduce Ki pequeño para eliminar error de régimen permanente.
– Reajusta VMAX/AMAX para no saturar el actuador.

Mejoras/variantes

  • Estrategia de control
  • Reemplazar PID por control por perfil trapezoidal/cinco segmentos y lazo de seguimiento de velocidad + lazo de posición (cascada).
  • Añadir feedforward de velocidad/acceleración basado en la cinemática planeada.

  • Telemetría avanzada

  • Transmitir por BLE un paquete periódico JSON con {T, M, C, V, err} y visualizarlo en una app móvil o en un dashboard.

  • Gestión de fallos

  • Añadir detección de pérdida de seguimiento (|T-M| > umbral por tiempo) y estrategia de reintento o alarma.
  • Monitorizar sobrecorriente/temperatura del driver con pines DIAG del TMC2209.

  • Multieje

  • Extender a dos ejes con Serial3 para el segundo TMC2209 y un segundo AS5600 en dirección I2C alternativa (usar versiones de AS5600 con ADDR o multiplexor I2C).

  • Autotuning

  • Implementar un procedimiento de sintonía automática: escalón pequeño, medir respuesta, estimar parámetros de planta y derivar Kp, Ki, Kd (método Ziegler-Nichols o IMC).

  • Sin librería de encoder

  • Si deseas robustez total frente a dependencias, ya se usa lectura I2C directa; puedes añadir calibración del AS5600 (offset) escribiendo registros del chip.

Checklist de verificación

  • [ ] Instalada Arduino CLI 0.35.3 y core arduino:sam 1.6.12
  • [ ] Librerías TMCStepper 0.7.3 y DueTimer 1.7.2 instaladas
  • [ ] Conexión eléctrica revisada: GND común, VM 12–24 V, motor conectado correctamente
  • [ ] PDN_UART cableado con dos resistencias de 1 kΩ a TX2 y RX2
  • [ ] AS5600 conectado a 3.3 V, SDA (D20), SCL (D21) y pull-ups si faltan
  • [ ] HM-10 conectado a Serial1 (TX1/RX1), alimentado a 3.3 V, BLE funcional
  • [ ] Firmware compilado con FQBN arduino:sam:arduino_due_x_dbg y subido sin errores
  • [ ] Log USB visible a 115200 baudios con mensajes de inicio y estado
  • [ ] Comando BLE “ZERO” responde “OK ZERO”
  • [ ] Comando BLE “GOTO 3200” mueve 1 vuelta y asienta cerca del objetivo
  • [ ] Ajuste PID realizado (sin oscilaciones, error de régimen pequeño)
  • [ ] VMAX y AMAX adecuados (sin pérdidas de pasos ni golpes)
  • [ ] Multiturno correcto (varias vueltas en ambos sentidos sin saltos)

Apéndice: configuración opcional del HM-10 mediante AT

Si deseas renombrar el HM-10 o fijar su velocidad, temporalmente conéctalo a un adaptador USB-UART a 9600 baudios y envía:

AT            // debe responder OK
AT+NAMECLStepper   // renombra el periférico
AT+BAUD4      // 9600 (por defecto); BAUD8 sería 115200 si lo cambias
AT+RESET

Asegúrate de mantener BLE.begin(9600) si usas 9600 baudios.

Notas finales sobre coherencia del hardware

  • El tutorial está estrictamente alineado con el modelo: Arduino Due + TMC2209 stepper drivers + AS5600 encoders + HM-10 BLE. Todo el cableado, código y comandos se han ajustado a esta combinación.
  • El uso del core arduino:sam 1.6.12 y la FQBN arduino:sam:arduino_due_x_dbg asegura compatibilidad con el Programming Port del Arduino Due en Arduino CLI 0.35.3.

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.

Quiz rápido

Pregunta 1: ¿Cuál es la versión probada de Ubuntu mencionada en el artículo?




Pregunta 2: ¿Qué tipo de controlador se menciona como parte del dispositivo del proyecto?




Pregunta 3: ¿Cuál es la versión del Arduino CLI utilizada en el artículo?




Pregunta 4: ¿Qué tipo de sensor se utiliza en el proyecto?




Pregunta 5: ¿Cuál es el voltaje de operación del Arduino Due?




Pregunta 6: ¿Qué librería se menciona para el manejo de temporizadores?




Pregunta 7: ¿Qué tipo de motor se menciona en el artículo?




Pregunta 8: ¿Cuál es la capacidad típica de la fuente de alimentación para el motor?




Pregunta 9: ¿Qué software auxiliar se menciona como opcional para validación?




Pregunta 10: ¿Qué es R_SENSE en el contexto del controlador TMC2209?




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