index.html (8411B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1" /> 6 <title>Diagnóstico de batería de litio desde software</title> 7 <link rel="icon" type="image/png" href="/favicon.png" /> 8 <link rel="stylesheet" type="text/css" href="../article.css" /> 9 </head> 10 <body> 11 <header> 12 <p class="title">Diagnóstico de batería de litio desde software</p> 13 <p class="date">8 de diciembre de 2022 • fjbalon</p> 14 </header> 15 <p>La siguiente sección del cuaderno de bitácora detalla la investigación que he llevado a cabo para determinar el estado de salud de la batería de litio de mi ordenador portátil, la cual mantiene desde hace algo de tiempo un comportamiento extraño. Primero de todo, he querido omitir pruebas eléctricas directamente sobre el hardware, para detallar los pasos sobre el software y el sistema operativo que he seguido para determinar el diagnóstico.</p> 16 <p>La única información realmente útil para el lector es, entonces, que utilizo el sistema operativo GNU/Linux (con el kernel <emb>6.0.11-arch1-1</emb>) en su distribución archlinux.</p> 17 <p>Para leer el porcentaje de batería utilizada uso ACPI (<emb>acpi 1.7</emb>), concretamente los valores que se encuentran en <emb>/sys/class/power_supply/BAT0/</emb> (siendo <emb>BAT0</emb> la interfaz de batería de mi equipo).</p> 18 <p>Concretamente, el fragmento del código que obtiene el valor de batería es:</p> 19 <pre><code>int perc; 20 char path[PATH_MAX]; 21 22 if (esnprintf(path, sizeof(path), "/sys/class/power_supply/BAT0/capacity", bat) < 0) { 23 return NULL; 24 } 25 26 if (pscanf(path, "%d", &perc) != 1) { 27 return NULL; 28 } 29 30 return bprintf("%d", perc);</code></pre> 31 <p>Que recibe el valor del fichero <emb>capacity</emb>. Llegados a este punto, es necesario aclarar los distintos ficheros del directorio <emb>/sys/class/power_supply/BAT0/</emb> (que se resumen en el fichero <emb>uevent</emb>):</p> 32 <pre><code>POWER_SUPPLY_NAME=BAT0 33 POWER_SUPPLY_TYPE=Battery 34 POWER_SUPPLY_STATUS=Discharging 35 POWER_SUPPLY_PRESENT=1 36 POWER_SUPPLY_TECHNOLOGY=Li-ion 37 POWER_SUPPLY_CYCLE_COUNT=0 38 POWER_SUPPLY_VOLTAGE_MIN_DESIGN=11400000 39 POWER_SUPPLY_VOLTAGE_NOW=11759000 40 POWER_SUPPLY_CURRENT_NOW=1089000 41 POWER_SUPPLY_CHARGE_FULL_DESIGN=4100000 42 POWER_SUPPLY_CHARGE_FULL=900000 43 POWER_SUPPLY_CHARGE_NOW=675000 44 POWER_SUPPLY_CAPACITY=75 45 POWER_SUPPLY_CAPACITY_LEVEL=Normal 46 POWER_SUPPLY_MODEL_NAME=standard 47 POWER_SUPPLY_MANUFACTURER=OEM 48 POWER_SUPPLY_SERIAL_NUMBER=00001</code></pre> 49 <p>Para un mayor detalle, es posible que desee ver cómo se define la clase del dispositivo power-supply en <a href="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/include/linux/power_supply.h?h=v6.0.11">include/linux/power_supply.h</a>. Sin embargo en esta entrada iré al grano.</p> 50 <p>Por lo que todos los valores <emb>charge_*</emb> (<emb>charge_full_design</emb>, <emb>charge_full</emb> y <emb>charge_now</emb>) se mide en microamperios/hora (µAh), mientras que <emb>current_now</emb> se mide en microamperios (µA).</p> 51 <pre><code>POWER_SUPPLY_CHARGE_FULL_DESIGN=4100000 52 POWER_SUPPLY_CHARGE_FULL=900000 53 POWER_SUPPLY_CHARGE_NOW=675000</code></pre> 54 <p>Cuando era nueva, la batería afirma haber tenido una capacidad de carga completa de 4,10Ah (<emb>charge_full_design</emb>), pero desde entonces se ha degradado dando lugar a una capacidad de carga completa actual de 0,9Ah. Actualmente, le quedan 0,675Ah de carga. Que realizando un simple cálculo de porcentaje:</p> 55 <math xmlns="http://www.w3.org/1998/Math/MathML" alttext="100\frac{0,675}{0,9}=75" display="block"> 56 <mrow> 57 <mrow> 58 <mn>100</mn> 59 <mo></mo> 60 <mfrac> 61 <mrow> 62 <mn>0</mn> 63 <mo>,</mo> 64 <mn>675</mn> 65 </mrow> 66 <mrow> 67 <mn>0</mn> 68 <mo>,</mo> 69 <mn>9</mn> 70 </mrow> 71 </mfrac> 72 </mrow> 73 <mo>=</mo> 74 <mn>75</mn> 75 </mrow> 76 </math> 77 <p>Da como valor el porcentaje de batería restante, que también se obtiene de <emb>capacity</emb>:</p> 78 <pre><code>cat /sys/class/power_supply/BAT0/capacity 79 75</code></pre> 80 <p>Por otro lado, el voltaje mínimo de diseño (nunca debería descargarse por debajo de este voltaje) se mide en microvoltios (µV):</p> 81 <pre><code>POWER_SUPPLY_VOLTAGE_MIN_DESIGN=11400000 82 POWER_SUPPLY_VOLTAGE_NOW=11759000</code></pre> 83 <p>Siendo <emb>voltage_min_design</emb> 11400000µV, sea 11,4V. El voltaje actual según la medida en este momento es de 11,759V. La batería en este momento proporciona 1,089A de corriente:</p> 84 <pre><code>POWER_SUPPLY_CURRENT_NOW=1089000</code></pre> 85 <p>Como una simple estimación, con la corriente que está tomando de la batería en este momento:</p> 86 <math xmlns="http://www.w3.org/1998/Math/MathML" alttext="\frac{0,675Ah}{1,089A}=0.62h=37m" display="block"> 87 <mrow> 88 <mfrac> 89 <mrow> 90 <mn>0</mn> 91 <mo>,</mo> 92 <mrow> 93 <mn>675</mn> 94 <mo></mo> 95 <mi>A</mi> 96 <mo></mo> 97 <mi>h</mi> 98 </mrow> 99 </mrow> 100 <mrow> 101 <mn>1</mn> 102 <mo>,</mo> 103 <mrow> 104 <mn>089</mn> 105 <mo></mo> 106 <mi>A</mi> 107 </mrow> 108 </mrow> 109 </mfrac> 110 <mo>=</mo> 111 <mrow> 112 <mn>0.62</mn> 113 <mo></mo> 114 <mi>h</mi> 115 </mrow> 116 <mo>=</mo> 117 <mrow> 118 <mn>37</mn> 119 <mo></mo> 120 <mi>m</mi> 121 </mrow> 122 </mrow> 123 </math> 124 <p>Le quedan unos 37 minutos de energía.</p> 125 <p>Sin embargo y como es evidente, no se puede diagnosticar por los valores concretos de un momento t en el tiempo, sin tener más valores estadísticos. Por lo que para ello, he implementado monitorización a través de un servidor Zabbix que gestione todos estos campos (concretamente para obtener una vez por minuto). Los <emb>UserParameters</emb> de Zabbix usados por el agente son:</p> 126 <pre><code>UserParameter=ChargeNow,cat /sys/class/power_supply/BAT0/charge_now 127 UserParameter=ChargeFull,cat /sys/class/power_supply/BAT0/charge_full 128 UserParameter=ChargeFullDesign,cat /sys/class/power_supply/BAT0/charge_full_design 129 UserParameter=VoltageMin,cat /sys/class/power_supply/BAT0/voltage_min_design 130 UserParameter=VoltageNow,cat /sys/class/power_supply/BAT0/voltage_now 131 UserParameter=CurrentNow,cat /sys/class/power_supply/BAT0/current_now 132 UserParameter=Capacity,cat /sys/class/power_supply/BAT0/capacity 133 UserParameter=Status,if [ "$(cat /sys/class/power_supply/BAT0/status)" = "Charging" ]; then echo 1; else echo 0; fi</code></pre> 134 <p>De tal forma, monitorizamos los valores de la batería, como el amperaje degradado y la corriente la corriente a través del tiempo:</p> 135 <img class="color-invertible" style="width: 100%;" src="resources/graph-charge.png" /> 136 <p>Por otro lado, comprobamos la capacidad porcentual (y bruta). Esto nos muestra valores interesantes, como que la batería tarda en desgastarse prácticamente lo mismo que al rellenarse, sin embargo, al llegar al umbral de 8% de capacidad, ésta se vacía a una velocidad mucho más lenta hasta el 0%, lo que constituye un primer indicador del funcionamiento extraño de la batería:</p> 137 <img class="color-invertible" style="width: 100%;" src="resources/graph-perc.png" /> 138 <p>Otro de los indicadores más extraños proviene al apagar el equipo durante unas horas. Éste al encenderse de nuevo, marca una batería que no se corresponde con el valor de apagado. En el ejemplo registrado, se observa como la batería se encontraba aproximadamente marcando un 10% de capacidad, pero tras 1,45h sin interacción de ningún tipo (lógicamente no estuvo conectado a la red eléctrica en este tiempo) vuelve a marcar un valor entre el 60-70% de capacidad:</p> 139 <img class="color-invertible" style="width: 100%;" src="resources/graph-poweroff.png" /> 140 <p>Como sabemos, el valor mínimo establecido por diseño que indica la batería es de 11.4V. Sin embargo y tal como se ve, sólo excede el mínimo cuando está conectado a AC:</p> 141 <img class="color-invertible" style="width: 100%;" src="resources/graph-voltage.png" /> 142 <p>Por lo tanto y con toda la información recopilada, concretamente la pronunciada degradación de la batería (diferencia entre <emb>charge_full_design</emb> y <emb>charge_full</emb>) y la evidencia de que baja regularmente del voltaje mínimo establecido por diseño (<emb>voltage_min_design</emb>) sugiere que la batería probablemente esté en un estado crítico, y que podría fallar en cualquier momento.</p> 143 </body> 144 </html>