Esto ocurrió hace un tiempo, en una galaxia no muy distante, donde muchos hombres han ido anteriormente.
Con un colega habíamos diseñado un circuito de encendido para un instrumento portátil alimentado a pilas, bastante simple: un MOSFET cierra el circuito puenteando el pulsador de encendido cuando el microcontrolador inicializa y configura el pin, como puede verse en el diagrama a continuación.
Para encender el instrumento, el usuario presiona el pulsador; el microcontrolador recibe alimentación, ejecuta su secuencia de inicialización y setea POW_CTRL en estado alto, habilitando el MOSFET, que lo mantiene alimentado luego que el usuario suelta el pulsador. Para apagarlo, el usuario presiona el pulsador nuevamente (estando encendido…), esto es leído por el programa en el pin SW_OFF, inhabilitando al MOSFET e ingresando en un loop de inactividad. Cuando el usuario suelta el pulsador, la tensión en ON_PWR comienza a descender, y el microcontrolador finalmente se apaga cuando los capacitores se descargan lo suficiente.
Esto funcionó perfectamente en el laboratorio y en las primeras unidades producidas para el cliente. Un tiempo más tarde, sin embargo, en otro lote de producción, una o dos de las nuevas unidades no se apagaban; el programa se reiniciaba siendo imposible el apagado.
Dado que yo había sido el perpetrador del hardware, fui elegido por unanimidad para hacerme cargo de resolver el misterio y encontrar la razón lógica detrás de este comportamiento esotérico. Munido de todas las unidades “con falla” y un par de unidades “funcionales”, comencé la inspección osciloscópica del circuito en cuestión.
Las unidades “funcionales” mostraban una esperada exponencial decreciente, correspondiente al descenso monotónico de la tensión de alimentación; aunque algunas porciones de la curva acusaban cambios en la pendiente.
Las unidades “con falla” mostraban cambios de pendiente más pronunciados, con una extraña tendencia a quedar horizontales momentos antes de que el microcontrolador decidiera reiniciarse. El trazo celeste corresponde a la tensión de alimentación en ON_PWR, antes de ingresar a un LDO, mientras que el trazo naranja es la tensión en POW_CTRL, con un resistor adicional conectado al positivo de las pilas (a través de ese resistor en el circuito esquemático que parece ir a ningún lado, esto es parte de un circuito más complejo pero generalmente dejado sin conectar o puesto a masa) para poder observar cuando el microcontrolador dejaba sus pines en alta impedancia (al resetearse). (Créanme que sólo lo tuve conectado el tiempo suficiente para tomar las capturas)
Finalmente, una de estas unidades “con falla” fue lo suficientemente gentil como para permitir al osciloscopio que me mostrara un pequeño incremento en la tensión de alimentación; sí, ese puntito celeste dentro del círculo rojo, justo antes del flanco ascendente del trazo anaranjado (el reset del micro). Por supuesto que esto puede ser simplemente ruido, pero se veía como si la tensión de alimentación ascendiera justo un instante antes del momento del reset. Sí, nadie había presionado el botón, y si estás pensando en echarle la culpa al LDO, a los fines prácticos llevaba visto lo suficiente esos chips como para considerarlos como un cable para todas las tensiones inferiores a la de regulación.
Mi teoría es que, una vez que el MOSFET dejaba de conducir y la alimentación del microcontrolador disminuía al descargarse el capacitor principal, los circuitos internos del microcontrolador (periféricos) se iban apagando y tomando cada vez menos corriente. Esa corriente es mayormente entregada por el capacitor electrolítico principal, y lo que yo estaba observando era su dQ/dC mientras su dQ estaba siendo diezmada por di siendo drenada con el transcurso de dt; a eso le restamos la caída di x ESR (Equivalent Series Resistance, resistencia interna serie equivalente que para este propósito sirve como paragüas para un probablemente amplio grupo de sutiles detalles químicos). Eso explicaría los cambios de pendiente…
Aparentemente, en algunas unidades esas diferencias de corriente cuando los periféricos se iban apagando cooperaban con las alinealidades de la ESR del capacitor para alterar el comportamiento monotónico de la alimentación (y tal vez verse como un aumento en la tensión), situación que dispararía el BOR (Brown-Out Reset) y el circuito interno de reset, reiniciando al microcontrolador, y habilitando al MOSFET nuevamente.
Afortunadamente, debido a la funcionalidad de apagado nos era posible observar si el botón estaba presionado o no. La condición de pulsador presionado es típica del encendido, mientras que una condición de pulsador abierto estaría indicando uno de esos despreciables y compulsivos resets ocasionados por el BOR, situación que podemos reconocer por programa e ignorar muy elegantemente, desviando el flujo de programa a un loop que espere a ver si la tensión de alimentación desaparece de una vez por todas, o el usuario realmente presiona el pulsador (porque a veces, sólo a veces, los pulsadores presentan rebotes en sus contactos; pero creo que eso ya es bien sabido, ¿no?).