---
title: "Error 4202 en un Neato, “batería descargada”: el día en que mi aspiradora decidió que estaba muerta"
description: "Error 4202 en un Neato D8, D9, D10 o D800: la batería no está necesariamente muerta. Cómo hice hablar al chip bq40z50 del pack con un ESP32 de dos euros, lo que dijo, el giro del día siguiente y el nuevo intento."
date: 2026-08-29
updated: 2026-09-01
image: images/neato/pack-pads-da-cl.jpg
tags: [neato, error 4202, reparación, batería, bq40z50, esp32, smbus, obsolescencia, derecho a reparar, diy]
lang: es
slug: erreur-4202-neato-obsolescence
---

# Error 4202 en un Neato, «batería descargada»: el día en que mi aspiradora decidió que estaba muerta

## Un D800 sin nube, una batería declarada «a sustituir» y tres cables en un ESP32 de dos euros para preguntarle qué le pasa en realidad

<div class="tldr" markdown="1">
**En dos minutos, si tu Neato parpadea en rojo con el error 4202**

- **El síntoma**: luz roja, error 4202, «batería descargada», el robot se niega a cargar o a arrancar. En los D8, D9, D10 y D800, la aplicación (mientras existió) añadía que el *contador de cargas* de la batería estaba superado.
- **Lo que significa**: no necesariamente que la batería esté muerta. Contiene un chip que habla con el robot; es **lo que ese chip cuenta** lo que dispara el error. Cambiar las celdas (las «pilas» de dentro) no cambia lo que cuenta.
- **Lo que encontramos** al hacerlo hablar con un microcontrolador de dos euros: ninguna avería, ninguna protección activada, un contador en **1547 ciclos** y un «no me cargues» que no era más que su modo de reposo.
- **Lo que hicimos**: guardar una copia de su memoria y poner el contador a cero. El robot volvió a funcionar… un día. **Actualización del 1 de septiembre**: la causa real estaba en otra parte: una celda recuperada más débil que disparaba la protección de sobretensión en cada carga (240 veces en tres días). Tensión de carga bajada, medidor en modo aprendizaje, en observación (ver [Dónde estamos](#ou-on-en-est)).
- **Epílogo**: las celdas originales «muertas», pasadas por el probador de capacidad, todavía dan de 1819 a 1916 mAh de los 2500 nominales. Tampoco tenían nada que reprocharse.
- **Antes de comprar una batería**: lee [Cómo reproducirlo](#pour-reproduire). Hacen falta un soldador, tres cables, un ESP32 y una tarde. Nada de programador del fabricante a 150 €, nada de contraseñas que romper.

*Este artículo pretende ser legible sin saber nada de electrónica: cada término técnico se explica la primera vez que aparece, y un glosario los recapitula al final. Los recuadros «Para ir al fondo» se despliegan para quienes quieran los registros, las direcciones y los bytes.*
</div>

![La placa electrónica del pack Neato, con la funda abierta: los pads C+ y C− en el centro y, a la derecha, los dos pequeños pads marcados DA y CL, con los cables amarillos ya soldados](../images/neato/pack-pads-da-cl.jpg)

*La placa del pack, una vez abierta la funda. Los dos pequeños pads marcados «DA» y «CL», a la derecha, son todo lo que necesitamos. Los grandes del centro, C+ y C−, son los que no se tocan.*

## Una nube apagada, y luego un botón que muere

Mi robot aspirador es un Neato D800. Un buen robot: un LIDAR giratorio (un pequeño radar láser que gira en la parte superior y mide las distancias a las paredes), un mapa de la casa, líneas prohibidas que se trazan en la aplicación, 600 € en su día. En 2023, Neato Robotics cerró. Vorwerk, la empresa matriz, mantuvo los servidores encendidos durante un tiempo —la «nube», es decir, los ordenadores remotos sin los cuales la aplicación, los mapas y la programación no funcionan— y luego anunció [el 6 de octubre de 2025](https://support.neatorobotics.com/support/solutions/articles/204000073686-announcement-6th-oct-2025) ([copia local](../assets/neato/refs/neato-announcement-2025-10-06.md)) que esa nube se apagaba. « *Your Neato robot will continue to function manually. Simply press the button once to launch a full house run.* » Un robot de 600 € degradado a aspiradora de un solo botón, por comunicado.

Y luego, unos meses más tarde, el propio botón dejó de responder. Luz roja, **error 4202**, «batería descargada». La aplicación, en sus últimos estertores, precisaba que el contador de cargas de la batería estaba superado y que había que sustituirla. Batería original: 90 €, cuando se encuentra. Compatible: de 30 a 50 €, con el riesgo, bien documentado en los foros, de que el robot la rechace.

Este artículo cuenta cómo pasamos de «robot muerto, batería muerta» a una batería que explica por sí misma lo que le pasa, sin comprar nada, con tres cables y un microcontrolador que cuesta lo que un café. Cuenta también una falsa esperanza, porque es lo que ocurre cuando se investiga de verdad. Se detiene en lo que esta investigación me habría costado hace tres años, antes de que una IA pudiera leerse un manual de 250 páginas por mí, y en el notable chip que gobierna esta batería. Y explica por qué esta historia me deja un regusto amargo sobre la manera en que fabricamos los objetos.

## Primer reflejo: las celdas

Una batería de robot es una carcasa que contiene varias **celdas** —acumuladores de litio en formato 18650 (18 mm de diámetro, 65 mm de largo, el aspecto de una pila AA grande)— conectadas en serie y gestionadas por una pequeña placa electrónica. Una batería «descargada» que ya no se recarga son, clásicamente, celdas muertas. Así que hice lo que hace cualquier manitas: abrí el pack, desoldé las cuatro celdas, soldé en su lugar cuatro celdas recuperadas —desparejadas, lo que tendrá su importancia más adelante— y lo cerré.

Resultado: **error 4202, igual que antes.**

Y sin embargo, multímetro en mano (el aparato que mide la tensión, es decir, la «presión» eléctrica, en voltios), todo era perfecto. 4,1 V en cada celda, que es una celda de litio llena; 16,4 V en los bornes del pack; 16,4 V *en el conector de salida*, lo que significa que el circuito de protección —el interruptor electrónico capaz de aislar las celdas en caso de peligro— dejaba pasar la corriente. El termistor (una resistencia cuyo valor cambia con la temperatura, que el robot lee para vigilar la batería) marcaba 6 kΩ, un valor normal para una habitación templada. El robot tenía entre manos una batería cargada al 95 % y en buen estado, y mostraba «batería descargada».

Es el momento en que uno comprende que el problema no es la batería. Es **lo que la batería dice de sí misma**.

<details markdown="1">
<summary>Para ir al fondo: medir sin quemarse</summary>

El pack es de 14,4 V nominales (cuatro celdas en serie, «4S»), 16,8 V cargado. No es una tensión peligrosa para la piel, pero un **cortocircuito** —unir directamente el más y el menos— en unas 18650 deja pasar decenas de amperios: suficiente para soldar unas pinzas, fundir una funda o incendiar una celda. Reglas simples: ni pulsera ni anillo, una sola herramienta metálica a la vez, y se mide en los **pads B+ / B−** (lado celdas) o **C+ / C−** (lado conector) sin unirlos nunca. El termistor (una NTC de 10 kΩ a 25 °C: su resistencia *baja* cuando hace calor) se lee entre el cable de temperatura y el menos.

Si la tensión es buena del lado de las celdas pero nula en el conector, es que el circuito de protección ha cortado: ahí sí es el chip el que ha decidido, y estamos de lleno en el tema de este artículo.
</details>

## La batería tiene cerebro

Los packs de los Neato de última generación (D8, D9, D10, D800) son «baterías inteligentes» (*smart batteries*): junto a las celdas, la pequeña placa lleva un **medidor de carga** (*gas gauge*), un chip —un circuito integrado, una minúscula lámina de silicio que contiene un ordenador especializado— de Texas Instruments, el **bq40z50-R2**. Es él quien mide la corriente, suma lo que entra y lo que sale, deduce el estado de carga, corta en caso de sobretensión o sobrecalentamiento, y es él quien *habla con el robot* a través de un **bus serie**: dos cables por los que circulan mensajes digitales, uno para los datos y otro para el reloj que marca el ritmo de la conversación. El protocolo (el idioma que se habla en esos cables) se llama **SMBus**, primo industrial del I²C que conocen todos los aficionados a Arduino. Un cable azul adicional en el conector del pack lleva esa conversación hasta el robot.

El robot no mide la tensión de la batería. Le *pregunta* al medidor: «¿a cuánto estás cargada?», «¿qué corriente de carga quieres?», «¿qué tensión?», «¿cuántos ciclos llevas?». Y obedece a lo que responde. Si el medidor dice «0 %» o «no me cargues», el robot muestra «batería descargada», sea cual sea la realidad eléctrica a tres centímetros de ahí.

Esta arquitectura no es absurda: un medidor dentro del pack conoce el historial de las celdas, gestiona su equilibrado (mantener las cuatro celdas al mismo nivel de carga, sin lo cual la más débil se desgasta primero) y protege eficazmente contra la fuga térmica (la reacción en cadena que hace arder una celda de litio maltratada). Pero tiene una consecuencia: **sustituir las celdas no pone el medidor a cero.** El contador de ciclos, la capacidad aprendida, los indicadores de error (*flags*: casillas de «sí/no» que el chip marca cuando detecta un problema): todo eso vive en la memoria del chip, no en las celdas. Se cambia el corazón, el cerebro conserva sus recuerdos.

En los foros, la pista suele terminar aquí. Los chips de los packs D3–D7 son de un fabricante oscuro y están bloqueados; para los bq40z50 «hace falta un EV2400 y bqStudio» —el adaptador oficial de Texas Instruments, 150 €, y su software para Windows— y nadie sabe realmente qué datos comprueba el robot. Fin de la historia, compra una batería.

<details markdown="1">
<summary>Para ir al fondo: SMBus, SBS y lo que «smart battery» quiere decir</summary>

El *Smart Battery System* (SBS) es una norma de los años noventa, nacida para los ordenadores portátiles. Una batería SBS es un periférico en la **dirección** SMBus `0x0B` —en un bus compartido, cada chip tiene un número para saber con quién se habla; la notación `0x…` significa que el número está escrito en hexadecimal, en base 16, la costumbre de los informáticos— que responde a un centenar de **comandos** estandarizados, cada uno designado por un número: `0x09` tensión, `0x0A` corriente, `0x0D` estado de carga relativo (RSOC, el «porcentaje de batería»), `0x10` capacidad a plena carga, `0x17` contador de ciclos, `0x14` / `0x15` corriente y tensión de carga *solicitadas*… Lo que devuelve un comando se llama **registro**: una pequeña casilla de memoria legible desde fuera. Un cargador «inteligente» lee esos dos últimos registros y suministra exactamente lo que se le pide. A cero, no suministra nada.

El bq40z50 añade por encima un comando comodín, `ManufacturerBlockAccess` (`0x44`), a través del cual se leen los registros de estado internos (estado de seguridad, fallos permanentes, estado de los transistores) y, con acceso suficiente, **toda la memoria flash de configuración** —la memoria que sobrevive al apagado, como una memoria USB—, 8 KB de direcciones `0x4000` a `0x5FFF`, donde viven el contador de ciclos, la capacidad nominal, los umbrales de protección y medio centenar de opciones.

Existen tres niveles de acceso: *Sealed* (sellado, solo lectura de los registros estándar), *Unsealed* (desbloqueado con una clave de 32 bits) y *Full Access* (todo, incluida la escritura en la flash, tras una segunda clave). TI recomienda sellar antes de salir de fábrica.
</details>

## Tres cables y un ESP32 de dos euros

Solo que el bq40z50 es un chip documentado públicamente. Texas Instruments publica su *Technical Reference Manual*, el manual de referencia: 250 páginas que describen cada registro, cada comando, cada dirección de memoria ([copia local del PDF](../assets/neato/refs/bq40z50-r2-trm-sluubk0b.pdf), 1,6 MB). Y el SMBus lo sabe hablar cualquier **microcontrolador** —un ordenador completo en un chip, unos pocos euros, el que se encuentra en una placa Arduino— en cuanto tiene dos pines I²C.

Tengo un cajón lleno de ESP32-C3 «Super Mini»: una placa del tamaño de un sello, dos euros la unidad, que se conecta por USB y se programa como un Arduino.

![La cara inferior de un ESP32-C3 Super Mini: de arriba abajo los pines 5V, G, 3.3, 4, 3, 2, 1, 0; usamos G, 4 y 5](../images/neato/esp32c3-supermini-pinout.jpg)

En la placa del pack, dos **pads de prueba** —puntos de contacto dejados a propósito por el fabricante para conectar sus aparatos de control al final de la cadena de montaje— llevan serigrafiadas las marcas **DA** y **CL**: *data* y *clock*, los dos cables del SMBus. Un cable en DA, otro en CL, otro en el menos de las celdas, y al otro lado los pines GPIO 4, GPIO 5 (GPIO: los pines de entrada-salida numerados de un microcontrolador) y GND (la masa, el «cero voltios» común) del ESP32. Ningún componente que añadir, ninguna alimentación que suministrar: el medidor se alimenta de sus celdas y el ESP32 de su USB.

![Esquema de cableado: GPIO 4 del ESP32-C3 al pad DA, GPIO 5 a CL, GND al menos de las celdas; C+ a 16,4 V no se toca nunca](../images/neato/cablage-esp32c3-bq40z50.svg)

En cuanto al software, doscientas líneas en Arduino, escritas con una IA (Claude) que se leyó el manual por mí: se leen los registros estándar (tensión, corriente, estado de carga, contador de ciclos, tensiones por celda), luego los registros de estado internos —estado de seguridad, fallos permanentes, estado de los transistores de carga y descarga— y después se copia la memoria flash. **No se escribe nada sin una orden explícita.** Escuchamos.

<details markdown="1">
<summary>Para ir al fondo: el cableado, los pull-ups y el código</summary>

| Pack (placa BMS) | ESP32-C3 Super Mini |
|---|---|
| Pad **DA** (SMBus data) | GPIO 4 (SDA) |
| Pad **CL** (SMBus clock) | GPIO 5 (SCL) |
| Cable negro (− de las celdas, pad B−) | G (GND) |

El SMBus necesita resistencias de polarización (*pull-up*: tiran suavemente de cada línea hacia 3,3 V cuando nadie habla, sin lo cual la señal flota) en ambas líneas. Las resistencias internas del ESP32 (≈ 45 kΩ) bastaron aquí a 100 kHz sobre diez centímetros de cable; si el chip no responde al escaneo I²C, añade dos de 4,7 kΩ entre cada línea y los 3,3 V del ESP32. El medidor tolera 3,3 V en sus líneas de bus; **nunca** se conectan los 3,3 V ni los 5 V del ESP32 al pack.

El sketch —así llama Arduino a un programa— ([`bq40z50-reader.cpp`](../assets/neato/bq40z50-reader.cpp), [`platformio.ini`](../assets/neato/platformio.ini)) corre en bucle: cada diez segundos, una lectura completa por el **puerto serie** (el canal de texto entre la placa y el ordenador, que se lee en un «monitor serie») a 115200 baudios (la velocidad del enlace). Solo escribe en el medidor con tres letras tecleadas en el monitor: `r` (reinicio del chip), `c` (contador de ciclos a cero), `C` (contador restaurado a su valor original). Todo lo demás es lectura.
</details>

## Lo que dijo el chip

Primera lectura, en el monitor serie:

```
Voltage            : 16386 mV
RSOC               : 97 %
RemainingCapacity  : 2343 mAh
FullChargeCapacity : 2437 mAh
DesignCapacity     : 2500 mAh
CycleCount         : 1547
ChargingCurrent    : 0 mA
ChargingVoltage    : 0 mV
Cellules           : 4094 / 4097 / 4100 / 4095 mV
ManufacturerName   : BLUEWAY-
DeviceName         : bq40z50-
ManufactureDate    : 2022-01-09
OperationStatus    : PRES DSG CHG SEC0  -> sécurité : FULL ACCESS
SafetyStatus       : (aucun flag)
PFStatus           : (aucun flag)
```

Para leer este informe: mV y mA son milivoltios y miliamperios (milésimas de voltio y de amperio); los mAh, miliamperios-hora, miden una cantidad de energía almacenada —2437 mAh es lo necesario para suministrar 2,4 A durante una hora—; RSOC es el porcentaje de batería que se muestra; *FullChargeCapacity* es lo que el medidor cree poder almacenar hoy, *DesignCapacity* lo que el pack almacenaba nuevo.

Tres cosas saltan a la vista.

**El medidor está en plena forma.** Ningún fallo de seguridad, ningún fallo permanente, transistores de carga y descarga conduciendo (los **transistores**, o FET, son los interruptores electrónicos con los que el medidor autoriza o corta la carga y la descarga), estado de carga estimado en el 97 %, coherente con los 4,1 V por celda. No está «descargada», y lo sabe.

**Ni siquiera está bloqueado.** El nivel de seguridad es *FULL ACCESS*: el modo más permisivo del chip, el que TI recomienda abandonar antes de salir de fábrica. Sin contraseña que romper, sin clave que adivinar. Toda la memoria es legible y escribible. El fabricante del pack entregó la casa con las llaves puestas en la puerta.

**Y sin embargo le dice al robot que no la cargue.** `ChargingCurrent = 0 mA`, `ChargingVoltage = 0 mV`. Son los dos registros que un cargador inteligente lee para saber qué hacer. A cero, significan: «no envíes corriente».

Y el contador: **1547 ciclos**. Un ciclo, para un medidor, es una descarga acumulada equivalente a una batería entera: dos medias descargas hacen un ciclo. Para una batería fabricada en enero de 2022, es un ciclo al día durante cuatro años, plausible para un robot que pasa a diario. Es también el número que la aplicación me había reprochado.

<details markdown="1">
<summary>Para ir al fondo: leer los indicadores de estado</summary>

`OperationStatus` (comando `0x44` + `0x0054`) es una palabra de 32 **bits** —treinta y dos casillas que valen 0 o 1, cada una un indicador—. Los que cuentan aquí: `PRES` (el robot está detectado), `DSG` y `CHG` (transistores de descarga y carga conduciendo), `SEC1:SEC0` (nivel de seguridad: `01` = Full Access, `10` = Unsealed, `11` = Sealed), `PF` (fallo permanente: el pack se ha autocondenado), `XCHG` / `XDSG` (carga / descarga prohibidas), `SLEEP` (recuerda este). `SafetyStatus` (`0x0051`) enumera las protecciones activas —sobretensión, subtensión, sobrecorriente, temperatura—; `PFStatus` (`0x0053`), los fallos permanentes, los que ningún reinicio borra: celda abierta, fusible fundido, desequilibrio irrecuperable. Todo estaba a cero.
</details>

## Diecisiete mil líneas de manual, y una falsa esperanza

La pregunta pasa a ser: *por qué* el medidor rechaza la carga. El manual de TI enumera con precisión los casos en que `ChargingVoltage()` cae a cero: transistor de carga cortado por una protección, temperatura fuera de rango, fallo permanente, pack declarado «retirado», sobretensión del cargador detectada. Los comprobamos todos, registro a registro. Ninguno estaba activo. Temperatura 26 °C, región de temperatura «recomendada», región de tensión «alta», todo en verde.

Exploramos también una pista seductora: el bq40z50 tiene una función de *degradación por contador de ciclos*, que reduce voluntariamente la tensión y la corriente de carga a medida que el pack envejece: una obsolescencia programada en sentido literal, activable con un bit de configuración. Leímos ese bit en la memoria flash. **Estaba a cero.** Neato no la había activado. La tabla de carga decía 4,2 V por celda y 1,5 A en todos los rangos de temperatura. Sobre el papel, el medidor debía anunciar 16,8 V y 1500 mA. Anunciaba 0 y 0.

Antes de ir más lejos, hicimos lo que siempre hay que hacer antes de tocar una memoria que no se podrá volver a comprar: **una copia de seguridad completa.** 8 KB, 256 bloques de 32 bytes (un byte son ocho bits, la unidad mínima de memoria), leídos uno a uno y guardados en un archivo ([aquí está](../assets/neato/refs/bq40z50-df-backup-neato-blueway-20260829.txt), por si el tuyo es el mismo pack). Si una escritura sale mal, se puede restaurar todo.

Luego probamos la cosa más tonta del mundo. El manual documenta un comando `0x0041 : Reset` —reinicio del chip: su memoria RAM (la memoria de trabajo, que se borra en cada reinicio) se reconstruye desde la flash, no se escribe nada—. El equivalente de «¿has probado a apagarlo y volverlo a encender?». Una letra `r` enviada por el monitor serie, tres segundos de espera:

```
>>> Envoi MAC 0x0041 Reset
ChargingCurrent    : 1500 mA
ChargingVoltage    : 16800 mV
RSOC               : 97 %
FET DSG ON, FET CHG ON, PF inactif
```

Victoria, creímos. Pack montado de nuevo, robot en su base: se acabó el error, carga, anuncia que está listo. Escribí una primera versión de este artículo esa misma noche, con una conclusión triunfal sobre el contador de ciclos del que «el robot nunca se había preocupado».

**A la mañana siguiente, luz roja, error 4202.**

## El síntoma que desaparece cuando se le mira

Pack conectado de nuevo al ESP32. `ChargingCurrent : 0 mA`, otra vez. Reinicio: 1500 mA. Y ahí, en lugar de cantar victoria, lo dejamos correr y miramos el reloj.

A los 3 segundos: 1500 mA. A los 20 segundos: 1500 mA. A los 31 segundos: **0 mA**, y en la misma lectura un indicador que no estaba diez segundos antes: `SLEEP`. Dos intentos, dos lecturas completas comparadas línea a línea: entre los 20 y los 31 segundos, lo *único* que cambia es ese indicador.

El medidor **se duerme**. En cuanto casi no circula corriente (menos de 10 mA, umbral fijado en su configuración), pasa a reposo para ahorrar sus celdas, y en ese estado anuncia «corriente de carga: 0». El reinicio no reparaba nada: lo *despertaba* treinta segundos. En el banco de trabajo, con un ESP32 que no consume nada, se volvía a dormir enseguida. En el robot, que tira unos cientos de miliamperios, está despierto y anuncia 1500 mA. El «no me cargues» nunca fue el problema. Era un espejismo de laboratorio.

![El laboratorio del día siguiente: en un sofá, el pack Neato bajo cinta kapton amarilla, unido por tres cables a un ESP32-C3, conectado a su vez por USB a un portátil cuya pantalla muestra las lecturas del medidor](../images/neato/labo-canape-esp32-pack.jpg)

*El laboratorio de la mañana siguiente: un sofá, el pack bajo kapton (la cinta adhesiva amarilla que aísla y resiste el calor), el ESP32 al extremo de tres cables y un terminal que compara las lecturas a diez segundos de intervalo.*

Es una lección que ya conocía y que aun así tuve que reaprender: cuando un síntoma desaparece *en el momento en que se le observa*, probablemente es la observación la que lo ha hecho desaparecer. Hay que mirar lo que vuelve, no lo que se va.

<details markdown="1">
<summary>Para ir al fondo: la configuración de reposo, y una documentación imprecisa</summary>

En la flash, `DA Configuration` (`0x4A7D`) vale `0x001F`: cuatro celdas, **NR = 1** (pack declarado no extraíble), **IN_SYSTEM_SLEEP = 1** y **SLEEP = 1**. `Sleep Current` (`0x48A3`) = 10 mA, `Bus Timeout` = 5 s. El TRM (§ 4.12, tabla de condiciones de `ChargingVoltage() = 0`) solo prevé la puesta a cero en reposo si `FET Options[SLEEPCHG] = 0`; aquí `FET Options` (`0x4887`) vale `0x7D`, así que SLEEPCHG = 1, y de hecho el transistor de carga sigue conduciendo en reposo. La puesta a cero de `ChargingCurrent()` / `ChargingVoltage()` se produce de todos modos. El comportamiento real tiene la última palabra sobre la documentación: una razón más para medir.

Esta configuración es la de fábrica, no se ha movido: el robot siempre ha vivido con un medidor que se duerme a la menor pausa. El Neato lo despierta simplemente consumiendo.
</details>

## El contador

Quedaba el sospechoso inicial, el que la aplicación había nombrado: **1547 ciclos**. Al medidor le da igual: la degradación por ciclos está desactivada, lo comprobamos. Pero el robot lee ese número (`CycleCount`, comando `0x17`), y un software embebido (un **firmware**: el programa grabado en el robot) que muestra «contador de cargas superado» tiene por fuerza un umbral en alguna parte.

El contador es un simple valor de dos bytes en la flash, en la dirección `0x4340`. En Full Access, se escribe como se ha leído: un comando de bloque, la dirección, dos bytes. Escribimos cero.

```
>>> CycleCount SBS avant = 1547 ; écriture DF 0x4340 = 0
>>> relecture 0x4340 : 00 00  (OK)
>>> CycleCount SBS après écriture = 0
```

Inmediato, sin reinicio, sin ningún indicador de seguridad activado. Una batería nueva, a ojos de quien solo mira ese número.

<details markdown="1">
<summary>Para ir al fondo: escribir en la data-flash</summary>

TRM § 14.1.67: una escritura en flash es un *SMBus block write* (el envío de un paquete de bytes de una vez) sobre el comando `0x44`, cuyo bloque es la dirección de inicio (en *little-endian*: primero el byte de menor peso) seguida de 1 a 32 bytes de datos. Para `CycleCount = 0`: `0x44`, longitud 4, `0x40 0x43 0x00 0x00`. A continuación se relee el bloque (block write de la dirección sola, luego block read de `0x44`, que devuelve la dirección y 32 bytes) para verificar. El valor SBS `0x17` siguió sin reinicio. El comando `C` del sketch restaura `0x0B 0x06` (1547) si se quiere volver atrás.

Lo que **no** tocamos, y por qué: `Qmax` (la capacidad química de las celdas tal como el medidor la ha aprendido, `0x4306…0x430E`, cinco veces 2650 mAh) y la tabla de resistencias internas datan de las celdas originales; `Design Capacity` (`0x48E5`) vale 2500 mAh; el estado de salud que anuncia el medidor (`FullChargeCapacity / DesignCapacity`) oscila por tanto entre el 73 % y el 92 % según la hora. Se podría hacer trampa bajando `Design Capacity`, o forzar `Qmax`. Preferimos dejar que el medidor reaprenda honestamente sobre ciclos completos; ver más abajo. El mapa completo de la flash, decodificado, está [aquí](../assets/neato/refs/bq40z50-df-map-neato.md).
</details>

## El giro {#rebondissement}

1 de septiembre por la noche: luz roja. Error 4202. El robot había aguantado un día.

Tercera vez que se repite el guion: se toca el pack, se vuelve a conectar, el robot arranca, y al día siguiente se para. Reiniciar el medidor había «funcionado» una noche; poner el contador a cero, un día y unos ciclos. Mirado de cerca, esas dos «victorias» tienen algo en común que no es la corrección: cada vez **se desconectó y se volvió a conectar el pack**. El robot se reinicia, olvida su estado «batería descargada», vuelve a intentarlo… y tropieza con la misma causa, que no habíamos encontrado.

Esta vez, antes de cualquier reinicio, el pack fue al ESP32 tal cual. Contador de ciclos: sigue en 0. Ninguna protección activa, ningún fallo permanente, medidor en plena forma: la misma lectura tranquilizadora de la primera noche. Solo que habíamos aprendido a desconfiar de las lecturas tranquilizadoras, y fuimos a leer una zona de la flash que nunca habíamos decodificado: los **datos de vida** (*Lifetimes*), el diario que el medidor lleva sobre sí mismo desde que salió de fábrica: tensiones extremas vistas por cada celda, cuántas veces ha saltado cada protección y en qué ciclo fue la última.

Comparada con la copia del 29 de agosto, decía esto:

```
                              29 ago       1 sep
COV (sobretensión de celda)   6            246   (+240 en tres días)
Vmáx de por vida, celda 4     4213 mV      4293 mV   (umbral COV: 4225)
Terminaciones de carga válidas 21813       21813 (ninguna desde el cambio de celdas)
Celdas en reposo              —            3986 / 3986 / 3995 / 3939 mV
```

Doscientos cuarenta disparos de la protección de **sobretensión** en tres días, todos en la celda 4, y ni una sola carga llevada hasta el final. El pack original había visto seis en cuatro años.

La explicación cabe en una imagen. Cuatro celdas en serie son cuatro cubos que se llenan por la misma manguera: si uno es más pequeño, rebosa el primero. La celda 4 de mi juego de celdas recuperadas tiene menos capacidad que las otras tres: en reposo es la más baja (3,94 V frente a 3,99) y en carga es la primera en cruzar los 4,225 V. El medidor hace entonces su trabajo: corta el transistor de carga, espera a que la celda baje a 4,1 V, vuelve a abrir, vuelve a cortar un segundo después. Doscientas cuarenta veces. El cargador del robot, por su parte, ve una carga que nunca termina; al cabo de un rato su firmware saca la única conclusión que conoce: «batería descargada», 4202.

El contador de ciclos no tenía nada que ver, o no del todo. Para el pack original nunca lo sabremos: cambié dos cosas a la vez. Sus datos de vida, eso sí, muestran 67 subtensiones, la última en el ciclo 1547; la celda de 41 mΩ hundiéndose en plena aspiración es una explicación al menos tan buena como el contador. El código 4202 es un cajón de sastre.

**El nuevo intento.** La solución limpia es pasar las cuatro celdas recuperadas por el probador, como las originales, y montar un pack con las cuatro celdas mejor emparejadas de las ocho. Mientras tanto, el medidor permite un parche sin soldador, siempre por los tres cables, y eso es lo que hicimos esa misma noche:

- **tensión de carga bajada de 4200 a 4100 mV por celda**: el pack se detiene en 16,4 V en lugar de 16,8; la celda 4 se queda por debajo del umbral de sobretensión, a cambio de un 10 % de autonomía;
- **capacidad de referencia reducida a 2100 mAh** (se había quedado en 2500, la del pack nuevo), capacidad química de las celdas alineada con ella;
- **medidor puesto de nuevo en modo aprendizaje**: sus valores aprendidos (capacidad química, tabla de resistencias) databan de las celdas de 2022; un bit le dice que lo reaprenda todo en los próximos ciclos.

Reinicio: el medidor anuncia 16 400 mV y 1500 mA, una capacidad a plena carga estimada de 1792 mAh, ningún fallo. Pack cerrado, robot en su base. Esta vez no cantamos victoria: esperamos unos días y volveremos a abrir el diario del medidor. Si el contador de sobretensiones sigue en 246, era eso.

<details markdown="1">
<summary>Para ir al fondo: los datos de vida, y lo que escribimos</summary>

La zona *Lifetimes* ocupa la flash de `0x4380` a `0x43F7` (TRM cap. 18): tensiones mín/máx de cada celda (`0x4380`), luego para cada protección un contador de eventos y el contador de ciclos en el último evento —COV en `0x43A0`/`0x43A2`, CUV en `0x43A4`/`0x43A6`, etc.—, después las terminaciones de carga válidas (`0x43D0`), las actualizaciones de Qmax/Ra (`0x43D4`…), el tiempo de funcionamiento. El umbral COV está en `0x494E` (4225 mV aquí, retardo 1 s, recuperación 4100 mV en `0x4959`).

Escrituras del 1 de septiembre, todas releídas después: tensión de carga por celda en las cinco regiones de temperatura del algoritmo de carga (`0x4A19`, `0x4A21`, `0x4A29`, `0x4A31`, `0x4A39`: 4200 → 4100); *Design Capacity* `0x48E5` = 2100 mAh y `0x48E7` = 3024 cWh; *Qmax* celdas 1–4 y pack `0x4306`–`0x430E` = 2100; *Qmax Cycle Count* `0x4310` = 0; *Update Status* `0x4312` = 0x04 (Impedance Track activo, «aún no aprendido»: el medidor rehará Qmax y luego la tabla Ra en los próximos ciclos, TRM 15.13.8.2 y 6.4.6); después reinicio `0x0041`. Comprobado antes de escribir: las banderas de «carga completa» (FC/TC) se activan aquí por terminación de carga válida (corriente por debajo de 130 mA, celda a menos de 75 mV de la tensión de carga), no por un umbral fijo de 4200 mV; bajar la tensión no las rompe. Margen en la celda 4: unos treinta milivoltios por debajo del umbral; el sketch tiene un comando para bajar a 4050 si no basta. Comandos: `v`/`w`/`V` (tensión 4100 / 4050 / 4200), `d`/`D` (capacidad y aprendizaje / valores de fábrica).
</details>

## Dónde estamos {#ou-on-en-est}

<div class="status" markdown="1">
**Estado a 1 de septiembre de 2026: en observación.** El error 4202 volvió el 1 de septiembre tras un día de funcionamiento; la causa real es una celda recuperada más débil que disparaba la protección de sobretensión en cada carga, 240 veces en tres días (ver [El giro](#rebondissement)). Parche aplicado esa misma noche por los tres cables: tensión de carga 4100 mV por celda, capacidad de referencia 2100 mAh, medidor en reaprendizaje. El robot está en su base; veredicto en unos días, al reabrir el diario del medidor: si el contador de sobretensiones no se ha movido, era eso. Sigue sin comprarse ninguna pieza.
</div>

Y luego está el epílogo que no vi venir. Las cuatro celdas *originales*, las que había desoldado al principio porque «la batería estaba muerta», andaban por el banco de trabajo. Por descargo de conciencia, las medí: **3,6 V cada una.** Ninguna está por debajo del umbral en el que una celda de litio se condena. Así que las pasé por el probador de capacidad: un Liitokala Lii-500, un cargador-analizador de unos treinta euros, en modo «NOR TEST»; carga la celda a tope, la descarga después a corriente constante contando los miliamperios-hora que salen, y vuelve a cargarla. Es la única forma honesta de saber lo que vale una celda: vaciarla con el cronómetro en marcha.

Veredicto, sobre celdas dadas por **2500 mAh** cuando eran nuevas:

| Celda | Capacidad medida | Porcentaje del nominal |
|---|---|---|
| A | 1916 mAh | 77 % |
| B | 1912 mAh | 76 % |
| C | 1855 mAh | 74 % |
| D | 1819 mAh | 73 % |

El probador da también la **resistencia interna** de cada celda: la «fricción» eléctrica de la química, en miliohmios (mΩ). Cuanto más alta, más se hunde la tensión cuando el robot tira corriente, y más se calienta la celda en lugar de entregar. Tres celdas oscilan entre **16 y 19 mΩ**, un buen valor para unas 18650 de esa edad. La cuarta está en **41 mΩ**: más del doble. Es el eslabón débil del pack, la que se desploma primero en plena aspiración, arrastra a las demás hacia el umbral de corte y por tanto acorta la autonomía mucho más de lo que sus 1819 mAh dejarían suponer.

Pero ninguna está muerta. Tras algo así como 1547 ciclos, estas celdas todavía entregan tres cuartas partes de su capacidad original: una pérdida normal, la que se espera de un litio que llega al final de su vida anunciada. En la práctica, la autonomía habría pasado de la hora y media larga a poco más de una hora. Una aspiradora algo menos resistente, no una aspiradora muerta.

Ahí es donde la historia cobra sentido. El pack que desencadenó todo esto no estaba averiado: estaba **gastado un 25 %**, y algo —un contador, o más probablemente su celda de 41 mΩ hundiéndose en plena aspiración— decidió que se había acabado. El cambio de celdas que hice por primer reflejo probablemente no era necesario, y hecho con celdas recuperadas nunca medidas, añadió un problema (ver [El giro](#rebondissement)); al menos me deja cuatro celdas originales en funcionamiento, medidas y documentadas, listas para servir de recambio el día en que las recuperadas fallen.

## Lo que me habría costado hace tres años

Seamos honestos sobre el escalón que subí sin verlo.

Hace tres años, esta historia se habría detenido en el párrafo «Primer reflejo: las celdas». Celdas cambiadas, error todavía ahí, multímetro tajante: la batería está bien. ¿Y después? Después, un **callejón sin salida**. Habría buscado en los foros, encontrado los mismos hilos que todo el mundo —«hace falta un EV2400 y bqStudio», «el chip está bloqueado», «compra una batería»— y habría comprado, o guardado el robot en un armario a la espera de un valor que nunca llega.

Porque el resto del proceso, que aquí cabe en unos pocos párrafos, representa un trabajo que yo no habría podido aportar en tardes de aficionado. Pongámoslo sobre la mesa:

1. **Identificar el chip** y encontrar su manual: fácil.
2. **Leer el manual**: 250 páginas, 17 000 líneas de inglés técnico denso, escritas para ingenieros de baterías que ya dominan el vocabulario. No se trata de hojearlo: hay que encontrar *las* tres tablas que dicen cuándo la corriente de carga cae a cero, el procedimiento de escritura en la flash, el mapa de las 400 direcciones de configuración, el significado de cada bit de una decena de registros de estado.
3. **Aprender el SMBus** a nivel de protocolo (el *block read*, el *block write*, el comando `0x44` y su eco, el autoincremento de dirección) y escribir un programa que lo hable sin errores.
4. **Interpretar** una lectura de cuarenta indicadores y 8 KB de bytes en bruto, cruzándolos con el manual.
5. **Diseñar los experimentos**: el reinicio y luego —tras la falsa esperanza— la idea de comparar dos lecturas completas a diez segundos de intervalo para aislar *la* línea que cambia.
6. **Escribir** en la flash sin romper nada.

Para un desarrollador competente que no es ingeniero de baterías, son varias semanas de tardes, con un riesgo real de abandono en el punto 2, que es exactamente donde se detienen los hilos de los foros. No es que sea *difícil* en el sentido intelectual; es que es *largo*, y nada garantiza, de entrada, que esas semanas lleven a alguna parte.

Con Claude, los puntos 2 a 6 llevaron dos tardes y una mañana. La IA absorbió el manual en unos segundos, escribió el sketch de una pasada, decodificó los registros a medida que llegaban, propuso el reinicio y luego —cuando el reinicio mintió— propuso repetirlo grabándolo todo, y encontró el indicador `SLEEP` en la comparación. Lo que yo conservaba: el soldador, el multímetro, las fotos, las decisiones («no tocamos Qmax, dejamos que aprenda») y, sobre todo, la duda: fue la prueba de una noche en el robot de verdad la que desmintió la victoria, no una lectura más.

Dos matices, para no convertirlo en un cuento. Primero, la IA cofirmó la falsa esperanza: tenía la misma conclusión errónea que yo la primera noche, porque teníamos los mismos datos incompletos. Lee rápido, pero no mide por mí. Segundo, encontró un error en el propio manual (el reposo que pone la corriente a cero cuando la documentación dice lo contrario) únicamente porque *medimos* lo contrario; sin el ESP32 conectado, habría defendido la documentación.

Pero el desplazamiento es real, y me parece importante para la reparación en general: **un saber que estaba encerrado en un manual de 250 páginas, y por tanto reservado a los profesionales, se vuelve accesible a alguien que sabe sostener un soldador y formular una pregunta.** Los fabricantes cuentan, sin decirlo, con que nadie leerá el manual. Esa hipótesis acaba de caer.

## Enfoque: el bq40z50, el chip que gestiona tu batería

Ya que hemos pasado dos días con él, presentémoslo. El bq40z50-R2 es lo que Texas Instruments llama un *battery pack manager*: un único chip, del tamaño de una uña (encapsulado QFN de 32 pines, con los contactos bajo el encapsulado), que hace todo lo que un pack de litio de 1 a 4 celdas en serie necesita. Se encuentra en buena parte de las baterías de portátiles de los últimos diez años, en herramientas eléctricas, robots, drones, baterías médicas.

### Lo que hace

- **Medir**: mide la corriente a través de una resistencia de medida (un *shunt*, unos pocos miliohmios) y la tensión de cada celda, y deduce el estado de carga con un algoritmo propio, *Impedance Track*: en lugar de limitarse a contar lo que entra y sale (lo que deriva con el tiempo), **aprende** la capacidad química real de las celdas (Qmax) y su resistencia interna en cada ciclo, y corrige permanentemente. Es lo que da los porcentajes precisos de los portátiles recientes.
- **Proteger**: integra el *AFE* (*analog front-end*: la parte analógica que vigila tensiones y corrientes en tiempo real, con independencia del software) y gobierna directamente los transistores de carga y descarga. Sobretensión y subtensión por celda, sobrecorriente en carga y en descarga, cortocircuito, sobrecalentamiento y baja temperatura, cada una con sus umbrales, sus retardos y sus condiciones de vuelta a la normalidad.
- **Condenarse**: una segunda familia de protecciones, los *fallos permanentes* (PF), corta definitivamente el pack —si hace falta, fundiendo un **fusible químico** irreversible— en caso de celda abierta, desequilibrio incorregible, transistor quemado o demasiadas sobretensiones repetidas.
- **Equilibrar**: durante la carga, descarga ligeramente las celdas adelantadas para que todas lleguen llenas a la vez.
- **Recordar**: contador de ciclos, temperaturas y tensiones extremas vistas a lo largo de su vida (*lifetime data*), y una **caja negra** que registra los últimos eventos de seguridad antes de un fallo permanente: material para hacer la autopsia de un pack muerto.
- **Hablar**: SMBus, todo el estándar SBS, más los comandos del fabricante. Y **autenticarse**: un mecanismo criptográfico (SHA-1 con una clave secreta) permite al aparato verificar que el pack es original. Es lo que bloquea las baterías compatibles en algunos aparatos.

### Sus puntos fuertes

- **Completo y documentado.** Todo está en un solo encapsulado, y el manual lo describe todo: es lo que ha hecho posible esta investigación. Muchos chips de la competencia están documentados bajo acuerdo de confidencialidad, o no lo están en absoluto.
- **Preciso.** Impedance Track sigue siendo la referencia en medición de carga para el gran público; el error de estimación baja al 1 % en un pack bien configurado.
- **Seguro por construcción.** El AFE protege incluso si el software se cuelga; los fallos permanentes no se negocian.
- **Ubicuo.** Decenas de millones de unidades en packs de portátiles: abundan las placas, los archivos de configuración y las experiencias compartidas.
- **Abrible.** El software oficial bqStudio y el adaptador EV2400 existen, pero, como hemos visto, un microcontrolador de dos euros basta para leer, y a menudo para escribir.

### Sus puntos débiles

- **Complejo de configurar.** Más de 400 parámetros en flash. Hacer funcionar correctamente Impedance Track exige una «imagen de referencia» (*golden image*) construida en laboratorio: identificación de la química de las celdas, calibración, ciclo de aprendizaje completo. Un pack DIY mal configurado mide mal, y el *aprendizaje* que hemos elegido lleva varios ciclos.
- **La seguridad depende del fabricante del pack.** TI proporciona las cerraduras; es el ensamblador quien decide cerrarlas. El pack Neato se entregó en Full Access. Una batería de portátil de marca, en cambio, casi siempre está sellada, y sin las claves solo se leen los registros estándar.
- **La seguridad, a la inversa, puede ser un muro.** La autenticación SHA-1 y el sellado son precisamente lo que hace irreparables algunos packs: un fallo permanente en un pack sellado es basura, sea cual sea el estado de las celdas.
- **No más de 4 celdas en serie.** Para una bicicleta eléctrica (de 10 a 13 celdas en serie) hace falta su hermano mayor, el bq40z80 (hasta 7 en serie), u otra arquitectura.
- **Difícil de cablear uno mismo.** El encapsulado QFN se suelda en horno o con aire caliente, no con soldador; las placas de desarrollo de TI cuestan un centenar de euros. En la práctica, el DIY pasa por placas recuperadas.

### Lo que se puede hacer con él, fuera del Neato

- **Diagnosticar una batería de portátil antes de tirarla.** Un pack Dell, HP o Lenovo «muerto» contiene muy a menudo un bq40z50 (o un primo: bq30z55, bq40z80) y seis celdas de las que tres están bien. El ESP32 y el sketch de este artículo leen el estado de salud, el contador, los fallos, y dicen si son las celdas o el chip. En un pack sellado se lee menos, pero se lee.
- **Rearmar un pack tras un cambio de celdas.** Exactamente este artículo: contador, eventualmente fallo permanente (`PFStatus` se pone a cero por comando, en Full Access o con la clave), y luego ciclo de aprendizaje.
- **Construir una «batería inteligente» para tus propios proyectos.** Una placa BMS recuperada con su bq40z50, cuatro celdas 18650 nuevas, y se obtiene un pack de 14,4 V que se autoprotege, se equilibra y anuncia su porcentaje: para un robot DIY, una radio de campo, un SAI de respaldo para un servidor doméstico, una lámpara de obra.
- **Vigilar una batería a distancia.** El ESP32 tiene Wi-Fi: el mismo sketch puede publicar tensión, corriente, temperatura y estado de carga por MQTT (un protocolo de mensajes ligero, el estándar de la domótica) hacia Home Assistant o una base de datos. Un pack que avisa antes de fallar.
- **Aprender.** El bq40z50 es un curso completo de gestión de baterías de litio, con un manual gratuito y un chip que se encuentra en la basura. Todo lo que hace el BMS de un coche eléctrico, él lo hace en pequeño, y se deja mirar mientras lo hace.

Una reserva: todo esto supone un pack **abierto** (no sellado) o del que se tienen las claves. Los fabricantes de portátiles sellan; los fabricantes de packs para robots, herramientas y juguetes, a menudo, se olvidan. Compruébalo antes de lanzarte: es la primera lectura, y no cuesta nada.

## Lo que esto cuenta

No creo que nadie, en Neato ni en su proveedor de baterías, *decidiera* que este robot moriría en 2026. Creo algo peor: nadie decidió que *viviría*.

Observemos las capas.

**La nube.** El robot fue diseñado para no hacer nada sin un servidor. Cuando el servidor se apaga, solo queda el botón. En los D3 a D7, una comunidad consiguió conectar un ESP32 al puerto serie de la placa base y devolver a los robots su autonomía ([vacuula/fang](https://github.com/vacuula/fang), [OpenNeato](https://github.com/renjfk/OpenNeato)). En los D8 a D10, ese puerto está *bloqueado con contraseña*. Una generación más tarde, la puerta se cerró con llave. No por la seguridad del usuario: por nada, al parecer, salvo para que no la toque.

**La batería autenticada.** El robot verifica la identidad del pack. Los foros están llenos de D5 bloqueados tras insertarles una batería compatible. El fabricante lo llama seguridad; también es, muy concretamente, un peaje sobre la pieza de desgaste número uno.

**El contador.** 1547 ciclos, y una aplicación que dice «a sustituir». No porque la batería esté fuera de uso —el propio medidor la daba cargada al 97 %, y las celdas originales, medidas desde entonces, todavía entregan del 73 al 77 % de su capacidad de fábrica—, sino porque un número ha cruzado un umbral que nadie te muestra. El robot fue puesto fuera de servicio por un cuarto de autonomía de menos.

**Y la ausencia de camino.** Un chip perfectamente documentado, dejado en acceso total, cuyo contador se pone a cero con un comando. Ningún camino, en el producto, lleva a ese comando. El diagnóstico entregado al usuario es «batería descargada», que es falso, y la solución propuesta es «comprar», que es cara.

La obsolescencia, aquí, no es una bomba de relojería programada por un ingeniero cínico. Es una suma de no-decisiones: nadie presupuestó la función «reiniciar la batería», nadie escribió el mensaje de error honesto, nadie dejó un puerto abierto. Cada elección se justifica por separado. Su suma fabrica un residuo de 600 € con una batería cargada dentro.

La buena noticia es que las mismas no-decisiones dejan grietas. El chip no se bloqueó. El fabricante del pack dejó sus pads de prueba. TI publica su manual. Y un microcontrolador de dos euros, más una IA que acepta leer 17 000 líneas de documentación sin quejarse, bastan para colarse por ellas.

A partir del 18 de febrero de 2027, el artículo 11 del [reglamento europeo sobre baterías](https://eur-lex.europa.eu/eli/reg/2023/1542/oj) ([extracto local](../assets/neato/refs/eu-regulation-2023-1542-article-11.md)) exigirá que las baterías portátiles de los aparatos sean « *readily removable and replaceable by the end-user* ». Es un avance. Pero esta historia muestra que «sustituible» no basta: mi batería *era* sustituible, y precisamente la sustitución era lo que me vendían como única salida. Lo que habría que exigir es que los objetos **digan la verdad sobre su estado**, y que dejen un camino para corregirlo. Un botón «reiniciar la batería» en una aplicación cuesta una tarde de desarrollo. El silencio, en cambio, cuesta una batería a cada cliente.

## Cómo reproducirlo {#pour-reproduire}

**Material**: un ESP32-C3 Super Mini (o cualquier ESP32/Arduino con I²C), tres cables, un soldador y, eventualmente, dos resistencias de 4,7 kΩ. El pack debe estar abierto a la altura de su placa electrónica: la funda va pegada, un cúter la raja sin forzar.

**Seguridad**: las celdas permanecen conectadas durante toda la operación. **Ninguna herramienta metálica cerca de los pads C+ y C−**, que llevan 16 V y varias decenas de amperios de cortocircuito posible. Ni pulsera, ni anillo. Los pads DA y CL, en cambio, están a 3,3 V y no corren ningún riesgo.

![La otra cara de la placa del pack: los pads de prueba T1, T3, T6, T7 y HEAT, el cable rojo del más y el cable negro del menos](../images/neato/pack-bplus-bminus.jpg)

*La otra cara de la placa: no se toca, pero muestra que el fabricante previó muchos más puntos de prueba que los dos que nos interesan.*

**Cableado**:

| Pack (placa BMS) | ESP32-C3 |
|---|---|
| Pad **DA** | GPIO 4 (SDA) |
| Pad **CL** | GPIO 5 (SCL) |
| Cable negro (− celdas) | G (GND) |

**Software**: [`bq40z50-reader.cpp`](../assets/neato/bq40z50-reader.cpp) y [`platformio.ini`](../assets/neato/platformio.ini) (PlatformIO es la herramienta que compila y sube el programa; entorno Arduino, destino `esp32-c3-devkitm-1`). Monitor serie a 115200 baudios. Los registros esenciales, en la dirección SMBus `0x0B`:

| Registro | Contenido |
|---|---|
| `0x09` / `0x0A` | tensión / corriente del pack |
| `0x0D` | estado de carga (RSOC, %) |
| `0x10` / `0x18` | capacidad a plena carga / capacidad nominal |
| `0x14` / `0x15` | corriente / tensión de carga solicitadas (0 en reposo: normal) |
| `0x17` | contador de ciclos |
| `0x3C`–`0x3F` | tensiones de las celdas 4 a 1 |
| `0x44` + `0x0054` | OperationStatus (seguridad, FET, PF, SLEEP) |
| `0x44` + `0x0053` | PFStatus (fallos permanentes) |
| `0x00` ← `0x0041` | reinicio del medidor |
| `0x44` ← `0x40 0x43` + 2 bytes | escritura del contador de ciclos (flash `0x4340`) |
| `0x44` ← `0x80 0x43` … `0xE0 0x43` | lectura de los datos de vida (flash `0x4380`–`0x43FF`): contadores COV/CUV, terminaciones de carga |
| `0x44` ← `0x19 0x4A` + 2 bytes (×5) | tensión de carga por celda (flash `0x4A19`…`0x4A39`) |

**En orden**: (1) conectar, leer, comprobar que `DeviceType` responde `0x4500` y que el nivel de seguridad es Full Access —si no, harán falta las claves del fabricante, y este artículo no las tiene—; (2) guardar la flash (el sketch lo hace al arrancar) y poner el archivo a buen recaudo; (3) leer `PFStatus` y `SafetyStatus` —un fallo permanente es otra historia—; (4) leer los datos de vida (`0x4380`…) y compararlos con la copia tras unos días en el robot: un contador COV o CUV que sube señala a una celda, no a un contador; (5) solo entonces, teclear `c`, y esperar varios días antes de concluir.

Tres reglas, si te pones a ello: leer primero, guardarlo todo después, escribir solo al final. Un medidor en *Full Access* se deja reparar tan fácilmente como destruir.

## Preguntas frecuentes

### ¿Qué significa el error 4202 en un Neato?

Es el error «batería descargada» de los D8, D9, D10 y D800. La aplicación (cuando funcionaba) precisaba que el contador de cargas de la batería estaba superado y que había que sustituirla. Aparece incluso con celdas en perfecto estado: lo que lo dispara es lo que el chip del pack le cuenta al robot; en particular, según lo que hemos observado, un contador de ciclos demasiado alto.

### ¿Cambiar las celdas del pack resuelve el error 4202?

No por sí solo. El contador de ciclos y el estado de salud viven en el chip bq40z50 del pack, no en las celdas. Tras el cambio de celdas, el error persistía en mi caso con celdas a 4,1 V.

### ¿Hace falta un EV2300/EV2400 y bqStudio para hablar con el medidor?

No. Un ESP32 (o un Arduino) con dos pines I²C, tres cables y el manual de TI bastan: el chip está documentado y, en los packs Neato que he visto, se deja en Full Access, sin contraseña. bqStudio es más cómodo, no necesario.

### ¿Una batería compatible del mercado resuelve el problema?

A veces, y a veces el robot la rechaza: los foros documentan D5 bloqueados tras insertar un pack compatible. Antes de comprar, cuesta una tarde comprobar que la batería original no ha superado simplemente un umbral de ciclos.

### ¿Es peligroso?

Las líneas DA y CL están a 3,3 V y no entrañan riesgo. El peligro está en otra parte: los pads C+/C− y B+/B− a 16 V, capaces de decenas de amperios en cortocircuito. Una sola herramienta metálica a la vez, nada de joyas, y no se toca nada más que DA, CL y el menos.

### ¿Por qué el medidor anuncia 0 mA de corriente de carga?

Porque duerme. En cuanto la corriente baja de 10 mA durante una treintena de segundos, entra en reposo y pone ChargingCurrent y ChargingVoltage a cero. En el robot, que consume permanentemente, se mantiene despierto. No es una avería, y un reinicio no «repara» nada: lo despierta treinta segundos.

### ¿Funciona en un D3, D4, D5, D6 o D7?

Los packs de esas generaciones usan un chip diferente, bloqueado, y las investigaciones de la comunidad no han dado fruto. En cambio, su puerto serie está abierto, y vacuula/fang u OpenNeato devuelven a esos robots su autonomía sin la nube.

### ¿Se puede reutilizar el chip bq40z50 de una batería vieja en otro proyecto?

Sí, si el pack no está sellado o si se tienen sus claves. Una placa BMS recuperada con sus celdas sustituidas hace una batería inteligente de 1S a 4S para un robot, una radio o un SAI DIY; un ESP32 conectado a ella puede publicar su estado por MQTT hacia la domótica. Ver la sección «Enfoque: el bq40z50».

### ¿Qué hizo exactamente la IA, y qué hizo el humano?

Claude leyó el manual de 250 páginas, escribió el programa de lectura, decodificó los registros, propuso el reinicio y luego el experimento de comparación que reveló el modo de reposo, y redactó este artículo conmigo. Yo soldé, medí, fotografié, decidí no tocar Qmax y dejé que el robot pasara una noche en su base, lo que desmintió la primera conclusión, la suya tanto como la mía.

### ¿Está reparado el robot?

Todavía no con certeza. Poner el contador a cero (30 de agosto) le dio un día, y luego el error 4202 volvió: la causa real era una celda recuperada más débil que disparaba la protección de sobretensión en cada carga. Corrección aplicada el 1 de septiembre (tensión de carga de 4100 mV por celda, reaprendizaje del medidor), en observación. Sigue sin comprarse ninguna pieza. Ver [Dónde estamos](#ou-on-en-est).

## Pequeño glosario

- **Celda**: el acumulador elemental, aquí en formato 18650 (18 mm × 65 mm). Un pack ensambla varias.
- **BMS** (*battery management system*): la placa electrónica del pack, que protege, equilibra y mide las celdas. Aquí está construida en torno al bq40z50.
- **Medidor de carga (gas gauge)**: el chip que cuenta lo que entra y sale de la batería y deduce el estado de carga.
- **Chip / circuito integrado**: un ordenador o un circuito completo grabado en unos milímetros de silicio.
- **Microcontrolador**: un pequeño ordenador completo en un chip, programable; el ESP32-C3 lo es.
- **Bus serie / SMBus / I²C**: dos cables (datos y reloj) por los que los chips intercambian mensajes digitales; SMBus es la variante que usan las baterías.
- **Dirección, registro, comando**: el número de un chip en el bus, una casilla de memoria que se puede leer, el número que la designa. `0x…`: número escrito en hexadecimal.
- **Bit, byte**: la casilla elemental (0 o 1) y el grupo de ocho; un **indicador** (*flag*) es un bit que señala un estado.
- **Firmware**: el programa grabado en un aparato. **Flash**: la memoria que sobrevive al apagado; **memoria RAM**: la de trabajo, borrada al reiniciar.
- **Ciclo**: una descarga acumulada equivalente al 90 % de la capacidad (umbral ajustable). El contador se limita a sumar.
- **RSOC**: estado de carga relativo, el «porcentaje de batería»; **FCC**: capacidad a plena carga, tal como la estima el medidor; **Qmax**: capacidad química aprendida de las celdas; **mAh**: miliamperio-hora, unidad de cantidad de energía almacenada.
- **Resistencia interna**: la «fricción» eléctrica de una celda, en miliohmios (mΩ). Cuanto más alta, más cae la tensión bajo carga y más se calienta la celda; sube con la edad y delata a una celda cansada antes de que su capacidad se desplome.
- **FET / transistor**: interruptor electrónico con el que el medidor autoriza o corta la carga y la descarga.
- **Pull-up**: resistencia que mantiene una línea del bus a 3,3 V cuando nadie habla.
- **PF (Permanent Failure)**: un fallo que el medidor juzga irrecuperable; se condena y nada lo borra. No había ninguno.
- **COV / CUV (Cell Over-/Under-Voltage)**: protecciones de sobretensión y subtensión por celda. El medidor corta la carga (COV) o la descarga (CUV), reanuda cuando la tensión vuelve al rango y cuenta cada disparo en sus datos de vida.
- **Impedance Track**: el algoritmo de TI que aprende la capacidad y la resistencia de las celdas para medir con precisión.
- **Full Access / Unsealed / Sealed**: los tres niveles de acceso al chip, del más abierto al más cerrado.

---

## Referencias y copias locales

Para que este artículo siga siendo útil cuando los enlaces hayan desaparecido, los documentos citados se alojan aquí, con su fuente original.

- **TI bq40z50-R2 Technical Reference Manual**, SLUUBK0B (junio de 2017, rev. octubre de 2018) — [fuente](https://www.ti.com/lit/pdf/sluubk0) · [copia local (PDF, 1,6 MB)](../assets/neato/refs/bq40z50-r2-trm-sluubk0b.pdf).
- **Mapa de la data-flash del pack Neato, decodificado** — [bq40z50-df-map-neato.md](../assets/neato/refs/bq40z50-df-map-neato.md) · **copia de seguridad en bruto** del 29 de agosto de 2026 — [bq40z50-df-backup-neato-blueway-20260829.txt](../assets/neato/refs/bq40z50-df-backup-neato-blueway-20260829.txt).
- **El sketch y su configuración** — [bq40z50-reader.cpp](../assets/neato/bq40z50-reader.cpp) · [platformio.ini](../assets/neato/platformio.ini).
- **Neato Robotics, «Announcement – 6th Oct 2025»** (fin de los servicios en la nube) — [fuente](https://support.neatorobotics.com/support/solutions/articles/204000073686-announcement-6th-oct-2025) · [copia en texto](../assets/neato/refs/neato-announcement-2025-10-06.md).
- **Reglamento (UE) 2023/1542 sobre baterías**, artículo 11 (aplicable a partir del 18 de febrero de 2027) — [fuente EUR-Lex](https://eur-lex.europa.eu/eli/reg/2023/1542/oj) · [extracto local](../assets/neato/refs/eu-regulation-2023-1542-article-11.md).
- **vacuula/fang** (firmware ESP32 que libera los Neato D3–D7 de la nube) — [fuente](https://github.com/vacuula/fang) · [README del 30 de agosto de 2026](../assets/neato/refs/vacuula-fang-README-20260830.md).
- **renjfk/OpenNeato** — [fuente](https://github.com/renjfk/OpenNeato) · [README del 30 de agosto de 2026](../assets/neato/refs/renjfk-OpenNeato-README-20260830.md).
- **Hilo de laptopu.ro sobre los chips de los packs Neato** (acceso Full Access mediante bqStudio) — [fuente](https://www.laptopu.ro/community/laptop-battery-chip-reset-and-repair/robot-neato-battery-nlba-reads-it-but-can-not-recognize-chip/) (sin copia: el sitio rechaza el archivado).

*Fotos y mediciones: mías. Lectura del manual, código y redacción: con Claude. Este artículo también está disponible en [Markdown en bruto](erreur-4202-neato-obsolescence.md).*
