{"id":791,"date":"2026-11-10T10:35:04","date_gmt":"2026-11-10T10:35:04","guid":{"rendered":"https:\/\/build-mode-ak.com\/esp32-self-balancing-robot-2\/"},"modified":"2026-11-11T16:02:59","modified_gmt":"2026-11-11T16:02:59","slug":"esp32-self-balancing-robot","status":"publish","type":"post","link":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/","title":{"rendered":"Robot autoequilibrado con ESP32: tres lazos de control"},"content":{"rendered":"<section class=\"sws-page-title alignfull wp-block-sws-theme-page-title\">\n\t<div class=\"sws-page-title__inner\">\n\t\t\n\t\t\t\t\t<nav class=\"sws-page-title__nav\" aria-label=\"Migas de pan\">\n\t\t\t\t<ol class=\"sws-page-title__trail\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<li class=\"sws-page-title__crumb\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<a class=\"sws-page-title__link\" href=\"https:\/\/build-mode-ak.com\/es\/\">Inicio<\/a>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/ol>\n\t\t\t<\/nav>\n\t\t\t<\/div><!-- .sws-page-title__inner -->\n\n\t\t\t<div class=\"sws-page-title__shapes\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t<span class=\"sws-page-title__shape sws-page-title__shape--accent\">\n\t\t\t\t\t<svg class=\"sws-page-title__icon\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M7 32h10l4-10 6 20 6-20 6 20 6-20 4 10h8\"\/>\n<\/svg>\t\t\t\t<\/span>\n\t\t\t\t\t\t\t<span class=\"sws-page-title__shape sws-page-title__shape--secondary\">\n\t\t\t\t\t<svg class=\"sws-page-title__icon\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M8 32h17M25 15v34M39 15v34M39 32h17\"\/>\n<\/svg>\t\t\t\t<\/span>\n\t\t\t\t\t\t\t<span class=\"sws-page-title__shape sws-page-title__shape--tertiary\">\n\t\t\t\t\t<svg class=\"sws-page-title__icon\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\">\n  <path d=\"M7 32h50M46 16v32\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/>\n  <path d=\"M21.5 18.5c-.7-.4-1.5.1-1.5 1v25c0 .9.8 1.4 1.5 1l21.7-12.4c.8-.5.8-1.7 0-2.2z\" fill=\"currentColor\"\/>\n<\/svg>\t\t\t\t<\/span>\n\t\t\t\t\t\t\t<span class=\"sws-page-title__shape sws-page-title__shape--accent\">\n\t\t\t\t\t<svg class=\"sws-page-title__icon\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M7 40h9C16 18 24 18 24 40C24 18 32 18 32 40C32 18 40 18 40 40C40 18 48 18 48 40h9\"\/>\n<\/svg>\t\t\t\t<\/span>\n\t\t\t\t\t<\/div>\n\t<\/section>\n\n\n\n<p class=\"wp-block-paragraph\">Este robot acaba de saltar de una b\u00e1scula de ba\u00f1o y sigue de pie. Cinco d\u00edas antes ni siquiera pod\u00eda quedarse en un sitio. En ese tiempo su hardware no cambi\u00f3 en nada: el mismo chasis, los mismos motores, el mismo sensor. Solo cambi\u00f3 el programa. Un lazo de control se convirti\u00f3 en dos, luego en tres, y cada lazo nuevo resolv\u00eda lo que el anterior no sab\u00eda hacer.<\/p>\n\n\n\n<figure class=\"wp-block-video alignwide is-style-loop\"><video height=\"720\" style=\"aspect-ratio: 1280 \/ 720;\" width=\"1280\" controls loop muted poster=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c1-jump-poster.jpg\" preload=\"none\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c1-jump.mp4\" playsinline><\/video><button type=\"button\" class=\"sws-video-loop__toggle\" aria-label=\"Pausar el v\u00eddeo\" data-label-pause=\"Pausar el v\u00eddeo\" data-label-play=\"Reproducir el v\u00eddeo\" hidden><svg class=\"sws-video-loop__icon sws-video-loop__icon--pause\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M19 14h8v36h-8zM37 14h8v36h-8z\" fill=\"currentColor\"\/>\n<\/svg><svg class=\"sws-video-loop__icon sws-video-loop__icon--play\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M22 14l28 18-28 18z\" fill=\"currentColor\"\/>\n<\/svg><\/button><figcaption class=\"wp-element-caption\">El primero de los dos saltos desde la b\u00e1scula de ba\u00f1o, el 8 de noviembre: sube por la tabla, salta por el borde, aterriza de golpe y sigue manteniendo el equilibrio.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Es un robot autoequilibrado de dos ruedas: un chasis de tres pisos impreso en 3D sobre dos motorreductores de CC, una placa ESP32 y un sensor de movimiento. Lo construimos para comparar distintas formas de mantener un robot erguido con el mismo hardware, empezando por la cl\u00e1sica, el PID. Este art\u00edculo recorre los diez d\u00edas que van de la primera prueba al salto, en el orden en que ocurrieron: qu\u00e9 lleva dentro, c\u00f3mo sabe el robot d\u00f3nde es arriba, los tres lazos uno a uno y lo que nos ense\u00f1\u00f3 conducirlo por Wi-Fi. Las cifras salen de los propios registros del robot.<\/p>\n\n\n\n<figure class=\"wp-block-image alignwide size-large\"><a href=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1600\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover.jpg\" alt=\"El robot de pie sobre la cama de una impresora 3D Creality negra: un chasis naranja de tres pisos con una bater\u00eda de celdas 18650 arriba, una peque\u00f1a pantalla encendida y cableado en el medio, dos drivers de motor con disipadores negros abajo y dos ruedas negras con llantas azules.\" class=\"wp-image-734\" srcset=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover.jpg 2560w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover-300x188.jpg 300w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover-1024x640.jpg 1024w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover-768x480.jpg 768w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover-1536x960.jpg 1536w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover-2048x1280.jpg 2048w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover-1920x1200.jpg 1920w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/a><figcaption class=\"wp-element-caption\">El robot sobre la impresora que imprimi\u00f3 su chasis.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">El robot<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">El chasis est\u00e1 formado por tres pisos impresos, apilados uno sobre otro, cada uno una pieza aparte. Lo dibujamos en Fusion 360 junto con las piezas compradas, as\u00ed que los motores y los drivers ya ten\u00edan su sitio antes de imprimir nada.<\/p>\n\n\n\n<figure class=\"wp-block-video alignwide is-style-loop\"><video height=\"720\" style=\"aspect-ratio: 1280 \/ 720;\" width=\"1280\" controls loop muted poster=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c2-fusion-poster.jpg\" preload=\"none\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c2-fusion.mp4\" playsinline><\/video><button type=\"button\" class=\"sws-video-loop__toggle\" aria-label=\"Pausar el v\u00eddeo\" data-label-pause=\"Pausar el v\u00eddeo\" data-label-play=\"Reproducir el v\u00eddeo\" hidden><svg class=\"sws-video-loop__icon sws-video-loop__icon--pause\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M19 14h8v36h-8zM37 14h8v36h-8z\" fill=\"currentColor\"\/>\n<\/svg><svg class=\"sws-video-loop__icon sws-video-loop__icon--play\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M22 14l28 18-28 18z\" fill=\"currentColor\"\/>\n<\/svg><\/button><figcaption class=\"wp-element-caption\">El modelo de Fusion 360 se despieza: tres pisos impresos, dos drivers de motor, dos motores y el m\u00f3dulo de 5&nbsp;V. El soporte negro sostiene el robot en el banco de trabajo y no forma parte de \u00e9l.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">De abajo hacia arriba: los motores cuelgan bajo el piso inferior, en los soportes de su kit. El primer piso lleva los dos drivers de motor, con los disipadores hacia abajo. El segundo piso es el cerebro: la placa ESP32 con su peque\u00f1a pantalla sobre una placa perforada, el sensor de movimiento y un buzzer. El piso de arriba lleva una bater\u00eda de tres celdas con su placa de protecci\u00f3n, un interruptor y un m\u00f3dulo reductor de 5&nbsp;V. El cuerpo mide 164&nbsp;\u00d7&nbsp;128&nbsp;\u00d7&nbsp;60&nbsp;mm, 235&nbsp;mm de ancho con las ruedas, y el robot entero pesa 1025&nbsp;g.<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table class=\"has-fixed-layout\"><thead><tr><th>Pieza<\/th><th>Qu\u00e9 usamos<\/th><th>Su funci\u00f3n<\/th><\/tr><\/thead><tbody><tr><td>Controlador<\/td><td><a href=\"https:\/\/build-mode-ak.com\/es\/lilygo-ttgo-t-display\/\">LILYGO TTGO T-Display<\/a>: ESP32, dos n\u00facleos a 240&nbsp;MHz, pantalla de 1,14\u2033<\/td><td>Un n\u00facleo ejecuta el lazo de control y el otro, el Wi-Fi; la pantalla muestra las ganancias<\/td><\/tr><tr><td>Sensor de movimiento<\/td><td>MPU-6500 en una placa MPU-9250\/6500\/9255, I\u00b2C a 400&nbsp;kHz<\/td><td>Giroscopio y aceler\u00f3metro, 500 muestras por segundo<\/td><\/tr><tr><td>Drivers de motor<\/td><td>2&nbsp;\u00d7&nbsp;m\u00f3dulo BTS7960 (HW-039, IBT-2)<\/td><td>Un puente H por motor, PWM a 8&nbsp;kHz<\/td><\/tr><tr><td>Motores<\/td><td>2&nbsp;\u00d7&nbsp;JGB37-520, 12&nbsp;V, 333&nbsp;rpm, reductora met\u00e1lica de engranajes rectos, encoder de efecto Hall<\/td><td>1320 pulsos del encoder por vuelta de rueda, 0,16&nbsp;mm de recorrido por pulso<\/td><\/tr><tr><td>Ruedas<\/td><td>67&nbsp;mm, del kit de los motores<\/td><td>Unos 210&nbsp;mm de recorrido por vuelta<\/td><\/tr><tr><td>Bater\u00eda<\/td><td>Bater\u00eda 3S de celdas 18650, 11,1&nbsp;V, 12,6&nbsp;V a plena carga, con BMS e interruptor<\/td><td>Alimenta directamente los motores; el interruptor lo corta todo<\/td><\/tr><tr><td>Alimentaci\u00f3n de 5&nbsp;V<\/td><td>M\u00f3dulo reductor LM2596<\/td><td>Alimenta la placa desde la bater\u00eda<\/td><\/tr><tr><td>Buzzer<\/td><td>Buzzer activo<\/td><td>Tres pitidos cuando el robot se arma<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<figure class=\"wp-block-image alignwide size-large\"><a href=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-02-wiring.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1600\" height=\"840\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-02-wiring.jpg\" alt=\"Diagrama de bloques en un panel oscuro junto al robot en su soporte: la bater\u00eda de 12 V alimenta el LM2596, que da 5 V para el ESP32; un divisor permite al ESP32 leer la bater\u00eda por el ADC; el MPU-6500 se comunica con \u00e9l por I2C; el ESP32 env\u00eda PWM a 8 kHz a dos drivers BTS7960, que mueven dos motores; los encoders devuelven cu\u00e1nto han avanzado las ruedas.\" class=\"wp-image-735\" srcset=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-02-wiring.jpg 1600w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-02-wiring-300x158.jpg 300w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-02-wiring-1024x538.jpg 1024w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-02-wiring-768x403.jpg 768w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-02-wiring-1536x806.jpg 1536w\" sizes=\"auto, (max-width: 1600px) 100vw, 1600px\" \/><\/a><figcaption class=\"wp-element-caption\">C\u00f3mo est\u00e1 conectado, en un fotograma de nuestro v\u00eddeo. La bater\u00eda va directamente a los motores, el convertidor alimenta la placa, y la flecha que vuelve desde los encoders es de lo que trata todo este montaje.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Dos detalles de la transmisi\u00f3n marcaron todo lo que vino despu\u00e9s. El primero es el retardo. El sensor entrega una muestra nueva cada 2&nbsp;ms, y la orden que resulta de ella llega a los drivers en menos de un milisegundo, pero una rueda necesita alrededor de una d\u00e9cima de segundo para responder a un cambio de orden. El segundo es la reductora: tiene holgura, as\u00ed que tras cada cambio de sentido el motor gira un instante antes de que lo haga la rueda.<\/p>\n\n\n\n<figure class=\"wp-block-gallery alignwide has-nested-images columns-4 is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-03-drivers.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"1500\" data-id=\"736\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-03-drivers.jpg\" alt=\"Dos placas azules de driver BTS7960, una junto a otra, rotuladas HW-039 e IBT_2, cada una con una bornera verde de cuatro tornillos, un condensador de 330 \u00b5F y dos chips de potencia.\" class=\"wp-image-736\" srcset=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-03-drivers.jpg 1200w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-03-drivers-240x300.jpg 240w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-03-drivers-819x1024.jpg 819w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-03-drivers-768x960.jpg 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-04-imu.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"1500\" data-id=\"737\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-04-imu.jpg\" alt=\"Dos placas azules de sensor MPU-9250\/6500\/9255, una boca arriba con el chip y las flechas de los ejes X e Y, la otra boca abajo, cada una con diez pines rotulados: VCC, GND, SCL, SDA, EDA, ECL, AD0, INT, NCS, FSYNC.\" class=\"wp-image-737\" srcset=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-04-imu.jpg 1200w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-04-imu-240x300.jpg 240w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-04-imu-819x1024.jpg 819w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-04-imu-768x960.jpg 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-05-motor.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"1500\" data-id=\"738\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-05-motor.jpg\" alt=\"Un motorreductor JGB37-520 plateado sobre un soporte negro en forma de L, con un neum\u00e1tico negro con dibujo sobre una llanta azul montado en el eje, y seis cables de colores que salen por detr\u00e1s.\" class=\"wp-image-738\" srcset=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-05-motor.jpg 1200w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-05-motor-240x300.jpg 240w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-05-motor-819x1024.jpg 819w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-05-motor-768x960.jpg 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-06-encoder.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"1500\" data-id=\"739\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-06-encoder.jpg\" alt=\"Primer plano de la placa redonda negra del encoder en la parte trasera de un motor: un disco magn\u00e9tico en el eje, en el centro, dos sensores Hall en su borde, un conector blanco de seis pines y los r\u00f3tulos M1, GND y LED1.\" class=\"wp-image-739\" srcset=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-06-encoder.jpg 1200w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-06-encoder-240x300.jpg 240w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-06-encoder-819x1024.jpg 819w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-06-encoder-768x960.jpg 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/figure>\n<figcaption class=\"blocks-gallery-caption wp-element-caption\">Las piezas antes del montaje: los dos drivers de motor, la placa del sensor de movimiento por delante y por detr\u00e1s, un motor con su rueda y su soporte, y el encoder en la parte trasera del motor.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Y los dos motores no son gemelos. En una grabaci\u00f3n a ras de suelo, una misma orden de PWM hizo oscilar la rueda lejana 18&nbsp;mm y la cercana 8&nbsp;mm. La orden era id\u00e9ntica; por qu\u00e9 la respuesta no lo es, no lo hemos determinado. Si no se corrige, la diferencia hace que el robot gire despacio sobre s\u00ed mismo mientras se equilibra, y de eso se encarga una peque\u00f1a correcci\u00f3n de rumbo, descrita en el apartado sobre la conducci\u00f3n.<\/p>\n\n\n\n<figure class=\"wp-block-gallery alignwide has-nested-images columns-2 is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-07-middle-floor.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1600\" height=\"900\" data-id=\"740\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-07-middle-floor.jpg\" alt=\"El robot sujeto sobre una mesa, visto desde arriba y por delante: la bater\u00eda bajo una brida en el piso de arriba, la T-Display con la pantalla encendida sobre una placa perforada en el segundo piso, el buzzer a su lado y cables dupont de colores que bajan hasta los drivers.\" class=\"wp-image-740\" srcset=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-07-middle-floor.jpg 1600w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-07-middle-floor-300x169.jpg 300w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-07-middle-floor-1024x576.jpg 1024w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-07-middle-floor-768x432.jpg 768w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-07-middle-floor-1536x864.jpg 1536w\" sizes=\"auto, (max-width: 1600px) 100vw, 1600px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-08-underside.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1600\" height=\"900\" data-id=\"741\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-08-underside.jpg\" alt=\"El robot tumbado de lado en una mano, mostrando la parte inferior: los dos motores plateados montados en l\u00ednea, extremo con extremo, bajo el piso inferior, una placa de encoder con un LED verde en el extremo interior de cada uno y una rueda en cada extremo exterior.\" class=\"wp-image-741\" srcset=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-08-underside.jpg 1600w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-08-underside-300x169.jpg 300w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-08-underside-1024x576.jpg 1024w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-08-underside-768x432.jpg 768w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-08-underside-1536x864.jpg 1536w\" sizes=\"auto, (max-width: 1600px) 100vw, 1600px\" \/><\/a><\/figure>\n<figcaption class=\"blocks-gallery-caption wp-element-caption\">El robot terminado: el cerebro en el segundo piso y, debajo, los motores con sus encoders.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">D\u00f3nde es arriba<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Todo lo que hace un robot que se mantiene en equilibrio depende de un n\u00famero: su inclinaci\u00f3n. El MPU-6500 ofrece dos maneras de obtenerla, y ninguna funciona por s\u00ed sola.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">El giroscopio mide a qu\u00e9 velocidad gira el cuerpo. Suma sus lecturas cada 2&nbsp;ms y obtienes un \u00e1ngulo suave y r\u00e1pido, pero que deriva: sin corregir el desfase propio del giroscopio medimos unos 15\u00b0 por minuto. El aceler\u00f3metro sabe d\u00f3nde est\u00e1 la gravedad, as\u00ed que su \u00e1ngulo no puede derivar, pero tambi\u00e9n nota cada sacudida. Con los motores en marcha, su \u00e1ngulo saltaba de un lado a otro en un rango de 18,7\u00b0.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Un filtro complementario toma la mitad buena de cada uno. En cada paso, el giroscopio hace avanzar el \u00e1ngulo, y luego el \u00e1ngulo se acerca a la lectura del aceler\u00f3metro en una parte diminuta de la diferencia, una mil\u00e9sima. Dicho de otro modo: 99,9&nbsp;% giroscopio, 0,1&nbsp;% aceler\u00f3metro, lo que equivale a una constante de tiempo de dos segundos. En el banco de pruebas, el \u00e1ngulo filtrado se mantuvo dentro de un margen de seis cent\u00e9simas de grado.<\/p>\n\n\n\n<figure class=\"wp-block-image alignwide size-large\"><a href=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-09-filter.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1600\" height=\"840\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-09-filter.jpg\" alt=\"Panel de nuestro v\u00eddeo junto al robot en su soporte. Arriba: el \u00e1ngulo obtenido solo con el giroscopio durante 39 segundos, una l\u00ednea recta que cae a unos \u221215\u00b0 por minuto. En medio: el \u00e1ngulo del aceler\u00f3metro, una banda ruidosa de 18,7\u00b0 de ancho. Abajo: las dos f\u00f3rmulas del filtro, \u03c4 = 2 s, y el rango filtrado de 0,06\u00b0.\" class=\"wp-image-742\" srcset=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-09-filter.jpg 1600w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-09-filter-300x158.jpg 300w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-09-filter-1024x538.jpg 1024w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-09-filter-768x403.jpg 768w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-09-filter-1536x806.jpg 1536w\" sizes=\"auto, (max-width: 1600px) 100vw, 1600px\" \/><\/a><figcaption class=\"wp-element-caption\">El giroscopio por s\u00ed solo deriva, el aceler\u00f3metro por s\u00ed solo tiembla, y el filtro mantiene el \u00e1ngulo dentro de 0,06\u00b0.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">En el firmware todo se reduce a unas pocas l\u00edneas. La placa del sensor va montada de canto y ladeada 1,4\u00b0, as\u00ed que antes que nada el c\u00f3digo separa la velocidad de cabeceo, que necesita el filtro, de la velocidad de gui\u00f1ada, que m\u00e1s adelante usa el c\u00f3digo de giro:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Leaning forward, the forward axis dips below the horizontal:\n\/\/ its reading is -sin(theta).\natt.thetaAcc = atan2f(-(float)s.accel&#91;1], (float)s.accel&#91;0])\n               * DEG_PER_RAD;\n\n\/\/ The board is rolled by 1.4 deg: take pitch and yaw rates apart.\nconst float gx = s.gyro&#91;0] \/ GYRO_LSB_PER_DPS - att.gyroBiasDps&#91;0];\nconst float gz = s.gyro&#91;2] \/ GYRO_LSB_PER_DPS - att.gyroBiasDps&#91;2];\natt.omegaPitch = gz * rollCos - gx * rollSin;\natt.omegaYaw = gx * rollCos + gz * rollSin;\n\n\/\/ Complementary filter: the gyroscope carries the angle from\n\/\/ sample to sample, the accelerometer pulls it back to gravity.\n\/\/ FILTER_K = dt \/ (tau + dt) = 0.002 \/ 2.002, about 0.1 %.\natt.theta = wrapDeg(att.theta + att.omegaPitch * IMU_DT);\natt.theta = wrapDeg(att.theta\n                    + FILTER_K * wrapDeg(att.thetaAcc - att.theta));<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">El paso va al ritmo del propio reloj del sensor. Un temporizador por hardware despierta la tarea de control justo antes de cada muestra esperada, la tarea la lee y ejecuta todo el controlador, y la pantalla y el registro del ensayo esperan su turno con menor prioridad. El Wi-Fi vive en el otro n\u00facleo. El esquema viene de nuestro anterior <a href=\"https:\/\/build-mode-ak.com\/es\/videos\/esp32-propeller-balancer\/\">balanc\u00edn de h\u00e9lice<\/a>, construido con la misma placa y el mismo sensor.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Primer lazo: el \u00e1ngulo<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">El primer experimento usa un solo lazo que vigila \u00fanicamente el \u00e1ngulo. Es un controlador PID que se ejecuta 500 veces por segundo, una vez por cada muestra del sensor, y su salida es la potencia para los dos motores, en porcentaje:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>P<\/strong>, el t\u00e9rmino proporcional: kp = 30, as\u00ed que un grado de error pide el 30&nbsp;% de la potencia m\u00e1xima.<\/li>\n\n\n\n<li><strong>I<\/strong>, el t\u00e9rmino integral: ki = 30 acumula el error a lo largo del tiempo y sigue empujando mientras este dure.<\/li>\n\n\n\n<li><strong>D<\/strong>, el t\u00e9rmino derivativo: kd = 0,3 calma el balanceo. Toma la velocidad directamente del giroscopio en lugar de derivar un \u00e1ngulo ruidoso.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">La consigna no es exactamente cero. El centro de masas no queda perfectamente sobre el eje, as\u00ed que el robot se equilibra en \u03b8_ref = 0,3\u00b0.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>float pidStep(float theta, float omegaPitch, float thetaRef,\n              const Params &amp;p, float dt, float *raw) {\n    const float error = theta - thetaRef;\n    const float summed = integral + p.ki * error * dt;\n    integral = constrain(summed, -p.uMax, p.uMax);\n    const float u = p.kp * error + integral + p.kd * omegaPitch;\n    *raw = u;\n    return constrain(u, -p.uMax, p.uMax);\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">El primer ensayo en el suelo fall\u00f3 de una forma que el banco de pruebas no habr\u00eda podido mostrar. En el aire se hab\u00edan superado todas las comprobaciones: las ruedas giraban, los encoders contaban, el sensor le\u00eda la inclinaci\u00f3n. En el suelo, las ruedas se alejaban de la inclinaci\u00f3n en lugar de meterse debajo de ella, y el robot se cay\u00f3. El \u00e1ngulo estaba bien; lo que estaba invertido era el \u00abadelante\u00bb de los motores y de los encoders. Tras invertir ambos en la configuraci\u00f3n, el robot se puso de pie, y con estas ganancias m\u00e1s tarde aguant\u00f3 m\u00e1s de dos minutos con una desviaci\u00f3n est\u00e1ndar de su \u00e1ngulo de 0,2\u00b0.<\/p>\n\n\n\n<figure class=\"wp-block-video alignwide is-style-loop\"><video height=\"720\" style=\"aspect-ratio: 1280 \/ 720;\" width=\"1280\" controls loop muted poster=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c3-one-loop-poster.jpg\" preload=\"none\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c3-one-loop.mp4\" playsinline><\/video><button type=\"button\" class=\"sws-video-loop__toggle\" aria-label=\"Pausar el v\u00eddeo\" data-label-pause=\"Pausar el v\u00eddeo\" data-label-play=\"Reproducir el v\u00eddeo\" hidden><svg class=\"sws-video-loop__icon sws-video-loop__icon--pause\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M19 14h8v36h-8zM37 14h8v36h-8z\" fill=\"currentColor\"\/>\n<\/svg><svg class=\"sws-video-loop__icon sws-video-loop__icon--play\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M22 14l28 18-28 18z\" fill=\"currentColor\"\/>\n<\/svg><\/button><figcaption class=\"wp-element-caption\">Un lazo, 3 de noviembre. Un empuj\u00f3n, y el robot se aleja rodando con el cuerpo todav\u00eda erguido; luego se queda donde se ha detenido.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Aqu\u00ed es donde un solo lazo llega a su l\u00edmite. Durante ese empuj\u00f3n el cuerpo nunca se inclin\u00f3 m\u00e1s de medio grado, y el robot rod\u00f3 27&nbsp;cm y se qued\u00f3 ah\u00ed. Para un lazo de \u00e1ngulo eso es un \u00e9xito, porque el \u00e1ngulo est\u00e1 bien. No distingue entre estar quieto y rodar a velocidad constante: en nuestro suelo, mantener una velocidad v cuesta alrededor del 4,5&nbsp;% de la potencia m\u00e1s un 78&nbsp;% por cada metro por segundo, y la integral simplemente conserva la potencia que le haya dejado el empuj\u00f3n. Cualquier velocidad le parece equilibrio.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Segundo lazo: la velocidad<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">El segundo lazo vigila las ruedas. Se ejecuta 100 veces por segundo, lee los dos encoders y compara la velocidad del robot con la que deber\u00eda tener, por ahora cero. No toca los motores en absoluto: su salida es el \u00e1ngulo que debe mantener el primer lazo. \u00bfVa rodando hacia adelante? Que se incline un poco hacia atr\u00e1s, y el lazo de \u00e1ngulo, al perseguir el nuevo \u00e1ngulo, frena el robot. Es un controlador PI, con una integral limitada a los mismos pocos grados que la salida:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>float pidSpeed(float vRef, float v, const Params &amp;p, float dt,\n               bool hold) {\n    const float error = vRef - v;\n    const float summed = hold ? speedIntegral\n                              : speedIntegral + p.kvi * error * dt;\n    speedIntegral = constrain(summed, -p.thetaMax, p.thetaMax);\n    return constrain(p.kv * error + speedIntegral,\n                     -p.thetaMax, p.thetaMax);\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">El primer intento temblaba cinco veces por segundo. Su ganancia sali\u00f3 de un modelo que supon\u00eda un lazo de \u00e1ngulo tres veces m\u00e1s d\u00e9bil que el real: kv = 10 se calcul\u00f3 para kp = 10, y el robot funciona con kp = 30. El modelo tambi\u00e9n ignoraba la d\u00e9cima de segundo que tardan las ruedas en responder. La soluci\u00f3n no fue una ganancia menor, sino una medici\u00f3n m\u00e1s tranquila: ahora la velocidad se promedia en 200&nbsp;ms en lugar de 40&nbsp;ms, y da la casualidad de que un promedio de 200&nbsp;ms anula por completo una oscilaci\u00f3n de 5&nbsp;Hz.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Luego el robot se escapaba poco a poco. Con un lazo de velocidad puramente proporcional, kvi = 0, ocho de cada diez ensayos terminaron a m\u00e1s de 10&nbsp;cm de donde hab\u00edan empezado. Una integral peque\u00f1a, kvi = 1, lo arregl\u00f3: en los once ensayos siguientes ninguno se desplaz\u00f3 m\u00e1s de 2,7&nbsp;cm.<\/p>\n\n\n\n<figure class=\"wp-block-image alignwide size-large\"><a href=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-10-speed-integral.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1600\" height=\"900\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-10-speed-integral.jpg\" alt=\"Panel de nuestro v\u00eddeo junto al robot sobre un suelo de madera: el lazo de velocidad, PI a 100 Hz, encima del lazo de \u00e1ngulo, PID a 500 Hz. Dos gr\u00e1ficas de la posici\u00f3n durante 36 segundos: con kvi 0 la mayor\u00eda de los ensayos se alejan, 8 de 10 m\u00e1s all\u00e1 de 10 cm; con kvi 1 todas las curvas quedan planas, 0 de 11, como m\u00e1ximo 2,7 cm.\" class=\"wp-image-743\" srcset=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-10-speed-integral.jpg 1600w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-10-speed-integral-300x169.jpg 300w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-10-speed-integral-1024x576.jpg 1024w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-10-speed-integral-768x432.jpg 768w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-10-speed-integral-1536x864.jpg 1536w\" sizes=\"auto, (max-width: 1600px) 100vw, 1600px\" \/><\/a><figcaption class=\"wp-element-caption\">Sin la integral de la velocidad, el robot se escapa poco a poco; con ella, se queda en su sitio.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Y entonces hizo algo que nadie le hab\u00eda pedido: tras un empuj\u00f3n, volv\u00eda.<\/p>\n\n\n\n<figure class=\"wp-block-video alignwide is-style-loop\"><video height=\"720\" style=\"aspect-ratio: 1280 \/ 720;\" width=\"1280\" controls loop muted poster=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c4-two-loops-poster.jpg\" preload=\"none\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c4-two-loops.mp4\" playsinline><\/video><button type=\"button\" class=\"sws-video-loop__toggle\" aria-label=\"Pausar el v\u00eddeo\" data-label-pause=\"Pausar el v\u00eddeo\" data-label-play=\"Reproducir el v\u00eddeo\" hidden><svg class=\"sws-video-loop__icon sws-video-loop__icon--pause\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M19 14h8v36h-8zM37 14h8v36h-8z\" fill=\"currentColor\"\/>\n<\/svg><svg class=\"sws-video-loop__icon sws-video-loop__icon--play\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M22 14l28 18-28 18z\" fill=\"currentColor\"\/>\n<\/svg><\/button><figcaption class=\"wp-element-caption\">Dos lazos, 5 de noviembre. Tras un empuj\u00f3n, el robot rueda 37,8&nbsp;cm, se detiene y vuelve, hasta quedar a 2&nbsp;cm de donde estaba. Todav\u00eda no hay lazo de posici\u00f3n.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">La raz\u00f3n est\u00e1 en la integral. La integral de la velocidad es simplemente la distancia recorrida, as\u00ed que, para mantener a velocidad cero un robot desplazado, la integral de la velocidad acaba sosteniendo una peque\u00f1a inclinaci\u00f3n, de alrededor de un grado por cada metro de distancia al punto de partida. Es un resorte d\u00e9bil y oculto que tira del robot hacia casa. Y d\u00e9bil es la palabra: el robot vuelve a una franja de unos 30&nbsp;cm de ancho y no a un punto, y en esta toma dos de sus puntos de reposo quedaron a 34&nbsp;cm uno del otro. Suponemos que dentro de la franja la inclinaci\u00f3n es demasiado peque\u00f1a para vencer la holgura de la reductora, pero es una suposici\u00f3n, no una medici\u00f3n. La toma de arriba se hizo con kv = 5; la etapa se cerr\u00f3 con kv = 7.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Tercer lazo: la posici\u00f3n<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">El tercer lazo recuerda d\u00f3nde empez\u00f3 el robot, y marcamos ese punto con un barquito impreso. Veinte veces por segundo, el lazo mide la distancia hasta casa y le pide al lazo de velocidad una velocidad de vuelta. Su ganancia es kx = 1,5, as\u00ed que a diez cent\u00edmetros de casa pedir\u00eda 15&nbsp;cm\/s, pero nunca pide m\u00e1s de 10&nbsp;cm\/s. La posici\u00f3n fija la velocidad, la velocidad fija el \u00e1ngulo y el \u00e1ngulo fija los motores.<\/p>\n\n\n\n<figure class=\"wp-block-video alignwide is-style-loop\"><video height=\"720\" style=\"aspect-ratio: 1280 \/ 720;\" width=\"1280\" controls loop muted poster=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c5-dog-poster.jpg\" preload=\"none\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c5-dog.mp4\" playsinline><\/video><button type=\"button\" class=\"sws-video-loop__toggle\" aria-label=\"Pausar el v\u00eddeo\" data-label-pause=\"Pausar el v\u00eddeo\" data-label-play=\"Reproducir el v\u00eddeo\" hidden><svg class=\"sws-video-loop__icon sws-video-loop__icon--pause\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M19 14h8v36h-8zM37 14h8v36h-8z\" fill=\"currentColor\"\/>\n<\/svg><svg class=\"sws-video-loop__icon sws-video-loop__icon--play\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M22 14l28 18-28 18z\" fill=\"currentColor\"\/>\n<\/svg><\/button><figcaption class=\"wp-element-caption\">Llega control de calidad a inspeccionar el punto de referencia. El robot sigue de pie y el barquito queda aprobado.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">La distancia sale de los encoders, corregida teniendo en cuenta la inclinaci\u00f3n: cuando el cuerpo se inclina, las ruedas avanzan por debajo de \u00e9l aunque el robot en su conjunto no se mueva. Esta es la cascada tal como se ejecuta dentro del paso de 500&nbsp;Hz, un poco abreviada: se ha omitido la rama que permite al PC conducir el robot.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Every step runs at 500 Hz: position every 25th, speed every 5th.\nif (positionPhase == 0) {\n    vRefNow = pidPosition(xHold + params.xRef, xNow, params);\n}\npositionPhase = (positionPhase + 1) % POSITION_EVERY;\n\nif (speedPhase == 0) {\n    \/\/ Hold the speed integral while a hand carries the robot away.\n    const bool limited = fabsf(vRefNow) &gt;= params.vMax;\n    const bool carried = (vRefNow &gt; 0) ? (vNow &lt; -AWAY_M_S)\n                                       : (vNow &gt; AWAY_M_S);\n    thetaOffset = pidSpeed(vRefNow, vNow, params,\n                           SPEED_EVERY * IMU_DT, limited &amp;&amp; carried);\n}\nspeedPhase = (speedPhase + 1) % SPEED_EVERY;\n\nthetaRefNow = params.thetaRef + thetaOffset;\npercent = pidStep(a.theta, a.omegaPitch, thetaRefNow, params,\n                  IMU_DT, &amp;uCtl);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">La l\u00ednea \u00abcarried\u00bb (\u00abllevado\u00bb) tiene su historia. En la primera versi\u00f3n, el robot volv\u00eda tras un empuj\u00f3n a velocidades de entre 20 y 46&nbsp;cm\/s y se pasaba de su sitio de 10 a 24&nbsp;cm. La integral de la velocidad se hab\u00eda ido cargando mientras empujaba la mano, y recordaba la mano. Congelar la integral siempre que el lazo de posici\u00f3n ped\u00eda la velocidad m\u00e1xima redujo el sobrepaso a unos 5&nbsp;cm, pero entonces los empujones grandes terminaban de 12 a 27&nbsp;cm antes de llegar a casa. La regla con la que nos quedamos la congela solo mientras el lazo pide la velocidad m\u00e1xima de vuelta y el robot sigue alej\u00e1ndose de casa a m\u00e1s de 1&nbsp;cm\/s, es decir, mientras una mano lo lleva. A partir de ah\u00ed, tras empujones de 68 y 80&nbsp;cm, el robot volvi\u00f3 a menos de 3&nbsp;cm, sin sobrepaso.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">El propio kx se eligi\u00f3 moviendo el punto objetivo por Wi-Fi y observando c\u00f3mo lo segu\u00eda el robot, con 36 desplazamientos para cada valor:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table class=\"has-fixed-layout\"><thead><tr><th>kx<\/th><th>1<\/th><th>1,5<\/th><th>2<\/th><\/tr><\/thead><tbody><tr><td>Tiempo hasta quedar a menos de 3&nbsp;cm, mediana<\/td><td>8,1&nbsp;s<\/td><td>4,8&nbsp;s<\/td><td>4,6&nbsp;s<\/td><\/tr><tr><td>Mayor sobrepaso<\/td><td>2,6&nbsp;cm<\/td><td>3,0&nbsp;cm<\/td><td>5,1&nbsp;cm<\/td><\/tr><tr><td>Paradas por el camino<\/td><td>37<\/td><td>5<\/td><td>18<\/td><\/tr><\/tbody><\/table><figcaption class=\"wp-element-caption\">Con 1, el robot volv\u00eda a casa despacio y a tirones; con 2, se pasaba; 1,5 queda en medio. Una parada es una detenci\u00f3n de entre medio segundo y dos segundos en el camino a casa: la fricci\u00f3n retiene al robot hasta que la integral de la velocidad acumula inclinaci\u00f3n suficiente para volver a moverlo.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-video alignwide is-style-loop\"><video height=\"720\" style=\"aspect-ratio: 1280 \/ 720;\" width=\"1280\" controls loop muted poster=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c6-three-loops-poster.jpg\" preload=\"none\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c6-three-loops.mp4\" playsinline><\/video><button type=\"button\" class=\"sws-video-loop__toggle\" aria-label=\"Pausar el v\u00eddeo\" data-label-pause=\"Pausar el v\u00eddeo\" data-label-play=\"Reproducir el v\u00eddeo\" hidden><svg class=\"sws-video-loop__icon sws-video-loop__icon--pause\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M19 14h8v36h-8zM37 14h8v36h-8z\" fill=\"currentColor\"\/>\n<\/svg><svg class=\"sws-video-loop__icon sws-video-loop__icon--play\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M22 14l28 18-28 18z\" fill=\"currentColor\"\/>\n<\/svg><\/button><figcaption class=\"wp-element-caption\">Tres lazos, 7 de noviembre. Tras un empuj\u00f3n que lo aleja 40,6&nbsp;cm, el robot vuelve a menos de 3&nbsp;cm del barquito en 6,1 segundos.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">No vuelve exactamente al barquito. Se detiene dos o tres cent\u00edmetros antes o despu\u00e9s de \u00e9l, retenido por la misma fricci\u00f3n que permit\u00eda al robot de dos lazos detenerse en cualquier punto de su franja. Deshacer un empuj\u00f3n de 50&nbsp;cm en el sentido contrario le llev\u00f3 8,6 segundos. Si pones las tres etapas una al lado de otra, el progreso salta a la vista:<\/p>\n\n\n\n<figure class=\"wp-block-video alignwide is-style-loop\"><video height=\"720\" style=\"aspect-ratio: 1280 \/ 720;\" width=\"1280\" controls loop muted poster=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c7-triptych-poster.jpg\" preload=\"none\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c7-triptych.mp4\" playsinline><\/video><button type=\"button\" class=\"sws-video-loop__toggle\" aria-label=\"Pausar el v\u00eddeo\" data-label-pause=\"Pausar el v\u00eddeo\" data-label-play=\"Reproducir el v\u00eddeo\" hidden><svg class=\"sws-video-loop__icon sws-video-loop__icon--pause\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M19 14h8v36h-8zM37 14h8v36h-8z\" fill=\"currentColor\"\/>\n<\/svg><svg class=\"sws-video-loop__icon sws-video-loop__icon--play\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M22 14l28 18-28 18z\" fill=\"currentColor\"\/>\n<\/svg><\/button><figcaption class=\"wp-element-caption\">El mismo tipo de empuj\u00f3n con uno, dos y tres lazos.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table class=\"has-fixed-layout\"><thead><tr><th>Lazos<\/th><th>Qu\u00e9 vigila<\/th><th>Tras un empuj\u00f3n<\/th><\/tr><\/thead><tbody><tr><td>1<\/td><td>\u00c1ngulo, 500&nbsp;Hz<\/td><td>Se aleja rodando 27&nbsp;cm y se queda ah\u00ed<\/td><\/tr><tr><td>2<\/td><td>\u00c1ngulo y velocidad, 100&nbsp;Hz<\/td><td>Vuelve a una franja de unos 30&nbsp;cm de ancho<\/td><\/tr><tr><td>3<\/td><td>\u00c1ngulo, velocidad y posici\u00f3n, 20&nbsp;Hz<\/td><td>Vuelve a menos de 3&nbsp;cm de su sitio<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Conducirlo por Wi-Fi<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Una vez que el robot sabe mantenerse en un punto, conducirlo es cuesti\u00f3n de mover ese punto. El ESP32 se conecta a la red Wi-Fi de casa, y un peque\u00f1o puente en Python en el PC sirve una p\u00e1gina web con flechas: teclado, mando o un mando en pantalla. El puente reenv\u00eda la orden m\u00e1s reciente al robot por UDP veinte veces por segundo, y el robot responde al instante a cada orden con su telemetr\u00eda: \u00e1ngulo, velocidad, posici\u00f3n, rumbo, potencia, voltaje de la bater\u00eda e intensidad de la se\u00f1al. Mientras se mantiene pulsado un control, una velocidad de marcha con rampa suave sustituye a la salida del lazo de posici\u00f3n; al soltarlo, el lazo de posici\u00f3n mantiene el punto donde se ha detenido el robot.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Para girar hizo falta un lazo m\u00e1s, fuera de la cascada. Un lazo de rumbo compara la diferencia entre los encoders de las dos ruedas con una consigna que se mueve a la velocidad de giro pedida, y luego suma su correcci\u00f3n a una rueda y la resta de la otra. El mismo lazo impide que el robot gire por s\u00ed solo a causa de unos motores desiguales. La regla es que el equilibrio va primero: el giro solo recibe la potencia que le sobra al lazo de \u00e1ngulo.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Balance first: the turn gets what is left of the limit, so the\n\/\/ mean of the two wheels stays the angle loop's command.\nstatic void driveApart(float percent, float turn, float limit) {\n    drivePercent = percent;\n    const float room = max(limit - fabsf(percent), 0.0f);\n    uTurnNow = constrain(turn, -room, room);\n    motorDrive(Wheel::Left, percent - uTurnNow);\n    motorDrive(Wheel::Right, percent + uTurnNow);\n}<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-video alignwide is-style-loop\"><video height=\"720\" style=\"aspect-ratio: 1280 \/ 720;\" width=\"1280\" controls loop muted poster=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c8-spin-poster.jpg\" preload=\"none\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-c8-spin.mp4\" playsinline><\/video><button type=\"button\" class=\"sws-video-loop__toggle\" aria-label=\"Pausar el v\u00eddeo\" data-label-pause=\"Pausar el v\u00eddeo\" data-label-play=\"Reproducir el v\u00eddeo\" hidden><svg class=\"sws-video-loop__icon sws-video-loop__icon--pause\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M19 14h8v36h-8zM37 14h8v36h-8z\" fill=\"currentColor\"\/>\n<\/svg><svg class=\"sws-video-loop__icon sws-video-loop__icon--play\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M22 14l28 18-28 18z\" fill=\"currentColor\"\/>\n<\/svg><\/button><figcaption class=\"wp-element-caption\">Gira sobre s\u00ed mismo desde la p\u00e1gina web sin dejar de mantener el equilibrio.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Los l\u00edmites de trabajo son 0,35&nbsp;m\/s y 75\u00b0 por segundo. El \u00faltimo ensayo del 8 de noviembre dur\u00f3 150 segundos: 28 metros de conducci\u00f3n con picos de hasta 0,57&nbsp;m\/s, dos saltos desde la b\u00e1scula y ninguna ca\u00edda. En el primer aterrizaje el cuerpo se inclin\u00f3 por un instante hasta +7\u00b0, y el robot sigui\u00f3 de pie.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">No todos los saltos salieron tan bien. Ese mismo d\u00eda, m\u00e1s temprano, un aterrizaje desde una peque\u00f1a rampa inclin\u00f3 el robot 9\u00b0 hacia adelante. Para no caerse, sali\u00f3 disparado a cerca de un metro por segundo y fue directo contra la cama. Para que el robot se incline hacia atr\u00e1s y frene, las ruedas primero tienen que adelantarse al cuerpo, y la orden de potencia ya estaba en su l\u00edmite del 85&nbsp;%: a esa velocidad no quedaba margen para llevarlas hasta ah\u00ed. Desde entonces el l\u00edmite se ha subido al 100&nbsp;%, algo que todav\u00eda no hemos probado en el suelo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Qu\u00e9 evita que se haga da\u00f1o<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Solo arranca cuando se le pide.<\/strong> Al pulsar un bot\u00f3n se arma con tres pitidos, y se activa cuando su inclinaci\u00f3n se mantiene a menos de 5\u00b0 de la vertical durante 0,2&nbsp;s.<\/li>\n\n\n\n<li><strong>Se rinde a los 25\u00b0.<\/strong> M\u00e1s all\u00e1 de esa inclinaci\u00f3n ya no puede recuperarse, as\u00ed que los motores se apagan en lugar de hacer girar las ruedas contra el suelo.<\/li>\n\n\n\n<li><strong>Un watchdog propio.<\/strong> Un temporizador por hardware aparte desactiva la l\u00ednea de habilitaci\u00f3n (enable) de los drivers si no ha llegado ninguna muestra del sensor en 10&nbsp;ms. Un bus I\u00b2C colgado puede bloquear la tarea de control durante cerca de un segundo, y un robot que va a ciegas durante un segundo es un robot empotrado en la pared.<\/li>\n\n\n\n<li><strong>Comprobaciones de bater\u00eda y sensor.<\/strong> Se detiene si la bater\u00eda est\u00e1 baja o si falla el sensor. Si se pierde el enlace Wi-Fi, solo se detiene la conducci\u00f3n: el robot se queda quieto y sigue en equilibrio.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Mira el montaje completo<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">El v\u00eddeo cuenta la misma historia en ocho minutos y medio, con los registros dibujados sobre las im\u00e1genes. El reproductor se carga desde YouTube solo cuando lo pulsas.<\/p>\n\n\n<div class=\"sws-video-player sws-video-player--related wp-block-sws-theme-video-player\">\n\t<div class=\"sws-video-player__list\">\n\t\t\t\t\t\t\t\t<div class=\"sws-video-player__item sws-video-player__item--long\">\n\t\t\t\t<div class=\"sws-video-player__stage\"\n\t\t\t\t\tdata-embed=\"https:\/\/www.youtube-nocookie.com\/embed\/nDDhm-58iK8?autoplay=1&#038;playsinline=1&#038;rel=0&#038;hl=es-ES\"\n\t\t\t\t\tdata-title=\"Constru\u00ed un robot autoequilibrado: tres lazos de control\">\n\t\t\t\t\t<a class=\"sws-video-player__poster\" href=\"https:\/\/www.youtube.com\/watch?v=nDDhm-58iK8\">\n\t\t\t\t\t\t<img decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/self-balancing-robot-poster-1024x576.jpg\" class=\"sws-video-player__image\" alt=\"\" loading=\"lazy\" sizes=\"auto, (min-width: 1180px) 1116px, 100vw\" srcset=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/self-balancing-robot-poster-1024x576.jpg 1024w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/self-balancing-robot-poster-300x169.jpg 300w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/self-balancing-robot-poster-768x432.jpg 768w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/self-balancing-robot-poster.jpg 1280w\" \/>\t\t\t\t\t\t<span class=\"sws-video-player__play\"><svg class=\"sws-video-player__play-icon\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <path d=\"M22 14l28 18-28 18z\" fill=\"currentColor\"\/>\n<\/svg><\/span>\n\t\t\t\t\t\t<span class=\"screen-reader-text\">\n\t\t\t\t\t\t\tReproducir el v\u00eddeo: Constru\u00ed un robot autoequilibrado: tres lazos de control\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"sws-video-player__length\" aria-hidden=\"true\">8:40<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t<\/div>\n\n\t\t\t\t\t\t\t\t\t<p class=\"sws-video-player__title\">\n\t\t\t\t\t\t<a class=\"sws-video-player__title-link\" href=\"https:\/\/build-mode-ak.com\/es\/videos\/self-balancing-robot\/\">Constru\u00ed un robot autoequilibrado: tres lazos de control<\/a>\n\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t\t<ul class=\"sws-video-player__links\">\n\t\t\t\t\t<li class=\"sws-video-player__links-item\">\n\t\t\t\t\t\t<a class=\"sws-video-player__link\" href=\"https:\/\/www.youtube.com\/watch?v=nDDhm-58iK8\" target=\"_blank\" rel=\"noopener\">\n\t\t\t\t\t\t\t<svg class=\"sws-video-player__link-icon\" aria-hidden=\"true\" focusable=\"false\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 64 64\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n  <rect x=\"4\" y=\"13\" width=\"56\" height=\"38\" rx=\"11\"\/>\n  <path d=\"M27 22l16 10-16 10z\" fill=\"currentColor\" stroke=\"none\"\/>\n<\/svg>\t\t\t\t\t\t\tVer en YouTube\t\t\t\t\t\t<\/a>\n\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t\t<\/ul>\n\t\t\t<\/div>\n\t\t\t<\/div>\n\n\t<p class=\"sws-video-player__notice\">\n\t\tAl pulsar reproducir, el v\u00eddeo se carga desde YouTube.\t\t\t\t\t<a class=\"sws-video-player__notice-link\" href=\"https:\/\/build-mode-ak.com\/es\/privacy-policy\/\">Pol\u00edtica de privacidad<\/a>\n\t\t\t<\/p>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Pr\u00f3ximos pasos<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Diez d\u00edas, tres lazos, un robot que se mantiene de pie. La cascada PID funciona, pero es una pila de piezas ajustadas a mano, y cada pieza se a\u00f1adi\u00f3 para resolver lo que la anterior no sab\u00eda hacer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Lo pr\u00f3ximo que queremos es sustituir los tres lazos por un \u00fanico controlador LQR, que calcula sus ganancias a partir de un modelo del robot, en lugar de que una persona las ajuste una a una. Despu\u00e9s queremos probar una peque\u00f1a red neuronal que se ejecute en el propio ESP32. El robot ya registra sus ensayos, en parte para que una red as\u00ed tenga de qu\u00e9 aprender. Todav\u00eda no existe ninguno de los dos. Cuando existan, se enfrentar\u00e1n a los mismos empujones que aqu\u00ed recibi\u00f3 el PID, y publicaremos las cifras.<\/p>\n\n\n\n<figure class=\"wp-block-image alignwide size-large\"><a href=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-11-rose.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1600\" src=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-11-rose.jpg\" alt=\"El robot de pie sobre un suelo de madera junto a un rosal de flores rosas en una maceta de color rosa intenso, con la pantalla encendida y unos LED verdes que brillan bajo los motores.\" class=\"wp-image-744\" srcset=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-11-rose.jpg 2560w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-11-rose-300x188.jpg 300w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-11-rose-1024x640.jpg 1024w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-11-rose-768x480.jpg 768w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-11-rose-1536x960.jpg 1536w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-11-rose-2048x1280.jpg 2048w, https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-11-rose-1920x1200.jpg 1920w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/a><figcaption class=\"wp-element-caption\">Entre experimentos.<\/figcaption><\/figure>\n\n\n<div class=\"sws-spacer sws-spacer--medium wp-block-sws-theme-spacer\" aria-hidden=\"true\"><\/div>\n\n","protected":false},"excerpt":{"rendered":"<p>Diez d\u00edas, un robot, tres lazos de control. C\u00f3mo nuestro robot autoequilibrado con ESP32 y motores con escobillas aprendi\u00f3 a mantenerse de pie, a volver tras un empuj\u00f3n, a quedarse en su sitio y a dejarse conducir por Wi-Fi, con las cifras de sus registros y el firmware que lo hizo funcionar.<\/p>\n","protected":false},"author":1,"featured_media":734,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[5],"tags":[72],"topic":[58,80,86,91],"class_list":["post-791","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-sin-categorizar","tag-esp32-es","topic-esp32-es","topic-impresion-3d","topic-motores","topic-sensores"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Robot autoequilibrado con ESP32: tres lazos de control - Build Mode<\/title>\n<meta name=\"description\" content=\"Robot autoequilibrado con ESP32 y motores con escobillas: filtro complementario, tres lazos PID en cascada, fragmentos del firmware y cifras registradas.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Robot autoequilibrado con ESP32: tres lazos de control - Build Mode\" \/>\n<meta property=\"og:description\" content=\"Robot autoequilibrado con ESP32 y motores con escobillas: filtro complementario, tres lazos PID en cascada, fragmentos del firmware y cifras registradas.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/\" \/>\n<meta property=\"og:site_name\" content=\"Build Mode\" \/>\n<meta property=\"article:published_time\" content=\"2026-11-10T10:35:04+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-11-11T16:02:59+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1600\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"q_admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"q_admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"19 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/esp32-self-balancing-robot\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/esp32-self-balancing-robot\\\/\"},\"author\":{\"name\":\"q_admin\",\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/#\\\/schema\\\/person\\\/776a2342163ad07c23ce7dac33d9cc8b\"},\"headline\":\"Robot autoequilibrado con ESP32: tres lazos de control\",\"datePublished\":\"2026-11-10T10:35:04+00:00\",\"dateModified\":\"2026-11-11T16:02:59+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/esp32-self-balancing-robot\\\/\"},\"wordCount\":3408,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/esp32-self-balancing-robot\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/build-mode-ak.com\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/esp32-self-balancing-robot-01-cover.jpg\",\"keywords\":[\"ESP32\"],\"articleSection\":[\"Sin categorizar\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/esp32-self-balancing-robot\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/esp32-self-balancing-robot\\\/\",\"url\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/esp32-self-balancing-robot\\\/\",\"name\":\"Robot autoequilibrado con ESP32: tres lazos de control - Build Mode\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/esp32-self-balancing-robot\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/esp32-self-balancing-robot\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/build-mode-ak.com\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/esp32-self-balancing-robot-01-cover.jpg\",\"datePublished\":\"2026-11-10T10:35:04+00:00\",\"dateModified\":\"2026-11-11T16:02:59+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/#\\\/schema\\\/person\\\/776a2342163ad07c23ce7dac33d9cc8b\"},\"description\":\"Robot autoequilibrado con ESP32 y motores con escobillas: filtro complementario, tres lazos PID en cascada, fragmentos del firmware y cifras registradas.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/esp32-self-balancing-robot\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/esp32-self-balancing-robot\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/esp32-self-balancing-robot\\\/#primaryimage\",\"url\":\"https:\\\/\\\/build-mode-ak.com\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/esp32-self-balancing-robot-01-cover.jpg\",\"contentUrl\":\"https:\\\/\\\/build-mode-ak.com\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/esp32-self-balancing-robot-01-cover.jpg\",\"width\":2560,\"height\":1600,\"caption\":\"The robot standing on the bed of a black Creality 3D printer: an orange three-floor frame with a pack of 18650 cells on top, a small lit screen and wiring in the middle, two motor drivers with black heatsinks below, and two black wheels with blue rims.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/esp32-self-balancing-robot\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Inicio\",\"item\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Robot autoequilibrado con ESP32: tres lazos de control\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/#website\",\"url\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/\",\"name\":\"Build Mode\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/#\\\/schema\\\/person\\\/776a2342163ad07c23ce7dac33d9cc8b\",\"name\":\"q_admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9b27ab13255ffada0f0f8683c7d2916b3c1c81aa48c6c0d5668f58421dc498bc?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9b27ab13255ffada0f0f8683c7d2916b3c1c81aa48c6c0d5668f58421dc498bc?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9b27ab13255ffada0f0f8683c7d2916b3c1c81aa48c6c0d5668f58421dc498bc?s=96&d=mm&r=g\",\"caption\":\"q_admin\"},\"sameAs\":[\"https:\\\/\\\/build-mode-ak.com\"],\"url\":\"https:\\\/\\\/build-mode-ak.com\\\/es\\\/author\\\/q_admin\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Robot autoequilibrado con ESP32: tres lazos de control - Build Mode","description":"Robot autoequilibrado con ESP32 y motores con escobillas: filtro complementario, tres lazos PID en cascada, fragmentos del firmware y cifras registradas.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/","og_locale":"es_ES","og_type":"article","og_title":"Robot autoequilibrado con ESP32: tres lazos de control - Build Mode","og_description":"Robot autoequilibrado con ESP32 y motores con escobillas: filtro complementario, tres lazos PID en cascada, fragmentos del firmware y cifras registradas.","og_url":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/","og_site_name":"Build Mode","article_published_time":"2026-11-10T10:35:04+00:00","article_modified_time":"2026-11-11T16:02:59+00:00","og_image":[{"width":2560,"height":1600,"url":"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover.jpg","type":"image\/jpeg"}],"author":"q_admin","twitter_card":"summary_large_image","twitter_misc":{"Escrito por":"q_admin","Tiempo de lectura":"19 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/#article","isPartOf":{"@id":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/"},"author":{"name":"q_admin","@id":"https:\/\/build-mode-ak.com\/es\/#\/schema\/person\/776a2342163ad07c23ce7dac33d9cc8b"},"headline":"Robot autoequilibrado con ESP32: tres lazos de control","datePublished":"2026-11-10T10:35:04+00:00","dateModified":"2026-11-11T16:02:59+00:00","mainEntityOfPage":{"@id":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/"},"wordCount":3408,"commentCount":0,"image":{"@id":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/#primaryimage"},"thumbnailUrl":"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover.jpg","keywords":["ESP32"],"articleSection":["Sin categorizar"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/","url":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/","name":"Robot autoequilibrado con ESP32: tres lazos de control - Build Mode","isPartOf":{"@id":"https:\/\/build-mode-ak.com\/es\/#website"},"primaryImageOfPage":{"@id":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/#primaryimage"},"image":{"@id":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/#primaryimage"},"thumbnailUrl":"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover.jpg","datePublished":"2026-11-10T10:35:04+00:00","dateModified":"2026-11-11T16:02:59+00:00","author":{"@id":"https:\/\/build-mode-ak.com\/es\/#\/schema\/person\/776a2342163ad07c23ce7dac33d9cc8b"},"description":"Robot autoequilibrado con ESP32 y motores con escobillas: filtro complementario, tres lazos PID en cascada, fragmentos del firmware y cifras registradas.","breadcrumb":{"@id":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/#primaryimage","url":"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover.jpg","contentUrl":"https:\/\/build-mode-ak.com\/wp-content\/uploads\/2026\/11\/esp32-self-balancing-robot-01-cover.jpg","width":2560,"height":1600,"caption":"The robot standing on the bed of a black Creality 3D printer: an orange three-floor frame with a pack of 18650 cells on top, a small lit screen and wiring in the middle, two motor drivers with black heatsinks below, and two black wheels with blue rims."},{"@type":"BreadcrumbList","@id":"https:\/\/build-mode-ak.com\/es\/esp32-self-balancing-robot\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Inicio","item":"https:\/\/build-mode-ak.com\/es\/"},{"@type":"ListItem","position":2,"name":"Robot autoequilibrado con ESP32: tres lazos de control"}]},{"@type":"WebSite","@id":"https:\/\/build-mode-ak.com\/es\/#website","url":"https:\/\/build-mode-ak.com\/es\/","name":"Build Mode","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/build-mode-ak.com\/es\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Person","@id":"https:\/\/build-mode-ak.com\/es\/#\/schema\/person\/776a2342163ad07c23ce7dac33d9cc8b","name":"q_admin","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/secure.gravatar.com\/avatar\/9b27ab13255ffada0f0f8683c7d2916b3c1c81aa48c6c0d5668f58421dc498bc?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/9b27ab13255ffada0f0f8683c7d2916b3c1c81aa48c6c0d5668f58421dc498bc?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9b27ab13255ffada0f0f8683c7d2916b3c1c81aa48c6c0d5668f58421dc498bc?s=96&d=mm&r=g","caption":"q_admin"},"sameAs":["https:\/\/build-mode-ak.com"],"url":"https:\/\/build-mode-ak.com\/es\/author\/q_admin\/"}]}},"_links":{"self":[{"href":"https:\/\/build-mode-ak.com\/es\/wp-json\/wp\/v2\/posts\/791","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/build-mode-ak.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/build-mode-ak.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/build-mode-ak.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/build-mode-ak.com\/es\/wp-json\/wp\/v2\/comments?post=791"}],"version-history":[{"count":1,"href":"https:\/\/build-mode-ak.com\/es\/wp-json\/wp\/v2\/posts\/791\/revisions"}],"predecessor-version":[{"id":793,"href":"https:\/\/build-mode-ak.com\/es\/wp-json\/wp\/v2\/posts\/791\/revisions\/793"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/build-mode-ak.com\/es\/wp-json\/wp\/v2\/media\/734"}],"wp:attachment":[{"href":"https:\/\/build-mode-ak.com\/es\/wp-json\/wp\/v2\/media?parent=791"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/build-mode-ak.com\/es\/wp-json\/wp\/v2\/categories?post=791"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/build-mode-ak.com\/es\/wp-json\/wp\/v2\/tags?post=791"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/build-mode-ak.com\/es\/wp-json\/wp\/v2\/topic?post=791"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}