← Índice del curso

Microcontroladores · Tema 40

Consumo energético y modos de bajo consumo

Un microcontrolador activo gasta unos 10 mA; dormido, unas millonésimas de amperio. Esa diferencia de mil o diez mil veces es la que permite que un sensor funcione años con dos pilas. Ahorrar energía no es optimizar el código: es dormir casi todo el tiempo, despertar solo para lo imprescindible y no dejar nada encendido por descuido.

01 · Punto de partida

Por qué importa la energía

En un proyecto conectado a la pared, el consumo es un detalle. En uno que funciona con batería (un sensor en el campo, un registrador de datos, una llave inteligente, un dispositivo portátil) es el requisito principal. La pregunta pasa a ser «¿cuánto dura?», y la respuesta depende de una sola cuenta: la capacidad de la batería dividida por la corriente media.

Con 2500 mAh (dos pilas AA), un circuito que gasta 45 mA como un Arduino Uno encendido dura unas 44 horas. Uno que gasta 17 µA dura más de 13 años. Es la misma batería y casi el mismo microcontrolador: lo que cambia es el programa y el circuito alrededor. Ese factor de 2000 es el territorio de este tema.

La idea general es la del ciclo de trabajo: el microcontrolador despierta, hace su trabajo en unas decenas de milisegundos y vuelve a dormir. Si está activo 0,04 % del tiempo, ese 0,04 % pesa tanto como la corriente de sueño de todo el resto, y hay que cuidar las dos.

02 · Orígenes del consumo

De dónde sale el consumo

Un circuito CMOS gasta energía sobre todo cuando conmuta: cada vez que un transistor cambia de estado carga y descarga una pequeña capacidad. La potencia dinámica es P ≈ C · V² · f: crece con la frecuencia (más conmutaciones por segundo) y con el cuadrado de la tensión. Además hay una parte estática: corrientes de fuga, el oscilador, las referencias internas, que no dependen de lo que haga el programa.

De ahí salen tres palancas:

  • Bajar la frecuencia reduce la corriente activa casi en proporción. Pero la tarea tarda más: la energía por tarea no baja (la parte dinámica por ciclo es la misma), salvo por la parte fija.
  • Bajar la tensión reduce la energía por ciclo con el cuadrado: pasar de 5 V a 3,3 V la deja en el 44 %. El ATmega328P admite 1,8 V a 5,5 V, pero la frecuencia máxima depende de la tensión (4 MHz desde 1,8 V; 10 MHz desde 2,7 V; 20 MHz desde 4,5 V).
  • Dormir. Detener los relojes del microcontrolador elimina casi toda la parte dinámica. Es lo más efectivo: factores de 1000 o más.
Órdenes de magnitud del ATmega328P (el chip solo; valores típicos que conviene verificar en el datasheet).
EstadoCondicionesCorriente aproximada
Activo16 MHz, 5 V9 a 12 mA
Activo8 MHz, 3,3 V3 a 4 mA
Activo1 MHz, 1,8 V0,2 a 0,3 mA
IdleCPU detenida, periféricos activosUn cuarto a un tercio de la activa
Power-saveTimer2 con cristal de 32 kHzAlrededor de 1 µA
Power-downWatchdog apagadoDécimas de µA
Power-downWatchdog activo4 a 6 µA
Placa Arduino Uno enteraCualquier estado40 a 50 mA

La última fila es una advertencia. La placa Uno gasta decenas de miliamperios aunque el chip duerma, porque el regulador de tensión, el LED de alimentación, el chip que traduce a USB y los pull-ups consumen por su cuenta. Una placa de desarrollo no sirve para medir el ahorro de un diseño: para ver los microamperios hay que sacar el chip de esa placa, usar una variante sin regulador ni LED (como la Pro Mini) o armar el circuito mínimo en una placa de prueba.

03 · Tipos de sueño

Los modos de sueño del ATmega328P

Perfil de corriente de un nodo de bajo consumo La corriente en función del tiempo es casi nula, en el nivel de microamperios, durante el sueño, con un pulso breve y alto en cada despertar. El período entre pulsos es de 60 segundos. El dibujo no está a escala. activo 8 mA durante 25 ms sueño: 5 µA durante 59,975 s T = 60 sT = 60 s (no está a escala: el pulso real es 1600 veces más alto que el nivel de sueño y 2400 veces más breve que el período) Itiempo

El ATmega328P dispone de seis modos de sueño, que se eligen con los bits SM2:0 del registro SMCR. Cuanto más profundo el modo, más relojes se detienen, menos consume y menos cosas pueden despertar al microcontrolador:

Modos de sueño (SMCR, bit SE habilita el sueño).
ModoSM2:0Qué sigue funcionandoQué lo despierta
Idle000Todos los periféricos; se detiene solo la CPUCualquier interrupción
ADC Noise Reduction001ADC, interrupciones externas, TWI (dirección), Timer2 asíncrono, watchdogFin del ADC, interrupciones externas, TWI, Timer2, watchdog, EEPROM
Power-down010Interrupciones externas, TWI (dirección), watchdogINT0/INT1 (por nivel), cambio de pin, TWI (dirección), watchdog
Power-save011Lo anterior y el Timer2 asíncronoLo anterior y el Timer2
Standby110Como Power-down pero con el oscilador de cristal en marchaComo Power-down; despierta en pocos ciclos
Extended Standby111Como Power-save con el oscilador en marchaComo Power-save

La regla de elección es simple: el modo más profundo que conserve lo que necesitás. Si lo único que querés es esperar un pulsador, alcanza Power-down; si querés llevar la hora, Power-save con el Timer2 y un cristal de 32,768 kHz; si hace falta recibir bytes de la UART o seguir con un temporizador, solo Idle. La segunda herramienta del laboratorio recomienda el modo según la fuente de despertar.

La profundidad también afecta al tiempo de despertar. En Idle el reloj sigue en marcha y la ejecución continúa en pocos ciclos. En Power-down se detiene el oscilador principal y, al despertar, hay que esperar a que arranque y se estabilice: del orden de milisegundos con un oscilador interno, y más con un cristal (según los fusibles del arranque, tema 12). Para respuestas rápidas se usa Standby.

04 · Mecánica del sueño

Dormir y despertar

La biblioteca <avr/sleep.h> de avr-libc encapsula el procedimiento. Dormir es habilitar el sueño y ejecutar la instrucción SLEEP; despertar es recibir una interrupción habilitada, ejecutar su rutina y continuar justo después de SLEEP.

#include <avr/sleep.h>
#include <avr/interrupt.h>

volatile uint8_t pulsado;

ISR(INT0_vect) { pulsado = 1; }                   // la rutina puede estar casi vacía: basta con que exista

static void dormir_hasta_pulsador(void) {
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);          // modo más profundo que conserva INT0 (por nivel)
    cli();
    if (!pulsado) {                               // ¿ya ocurrió el evento?
        sleep_enable();
        sei();                                    // la instrucción siguiente a SEI se ejecuta antes de atender interrupciones
        sleep_cpu();                              // duerme aquí
        sleep_disable();
    }
    sei();
}

El orden cli() – comprobar – sei() – sleep_cpu() cierra una condición de carrera clásica. Si el evento llegara justo entre la comprobación y el SLEEP, la interrupción se atendería antes de dormir y el microcontrolador dormiría sin nada que lo despierte, quizás para siempre. La instrucción posterior a SEI se ejecuta antes de que el hardware atienda una interrupción pendiente: por eso sei(); sleep_cpu(); es seguro y las interrupciones se habilitan atómicamente con el sueño.

Cuatro advertencias:

  • Sin interrupciones habilitadas no hay despertar. Olvidar sei() o la máscara de la fuente deja al microcontrolador dormido para siempre (hasta un reinicio).
  • Una bandera pendiente despierta de inmediato. Si la interrupción ya se había disparado y su bandera sigue en 1, SLEEP vuelve al instante. Hay que borrar las banderas antes de dormir (tema 19).
  • El Timer0 se detiene en Power-down. Funciones basadas en él (millis(), delay() de Arduino) no avanzan durante el sueño. Una marca de tiempo debe corregirse con la duración del sueño.
  • La UART deja de recibir. Los bytes que lleguen mientras duerme se pierden, y el primero suele ser el que despierta.

05 · Un reloj que no cuesta casi nada

Despertar cada cierto tiempo

El caso más común es una medición periódica: dormir un minuto, medir, enviar, volver a dormir. Hay dos relojes que siguen en marcha durante el sueño profundo:

  • El watchdog (tema 13), con su propio oscilador de 128 kHz. Se puede configurar en modo de interrupción (sin reiniciar) para que despierte al microcontrolador con períodos de 16 ms a 8 s. Cuesta unos microamperios y es poco preciso (±10 % o peor, con la temperatura y la tensión).
  • El Timer2 asíncrono con un cristal de reloj de 32,768 kHz (tema 23): un reloj de tiempo real de precisión de cristal, en modo Power-save, con unos microamperios más.
#include <avr/wdt.h>

volatile uint8_t despertares;
ISR(WDT_vect) { despertares++; }                  // solo cuenta; el despertar ya ocurrió

static void wdt_8s(void) {                        // interrupción cada 8 s, sin reinicio
    cli();
    wdt_reset();
    MCUSR &= ~(1 << WDRF);                       // el flag de reinicio por watchdog bloquea la configuración
    WDTCSR |= (1 << WDCE) | (1 << WDE);          // secuencia de desbloqueo: cuatro ciclos para escribir
    WDTCSR = (1 << WDIE) | (1 << WDP3) | (1 << WDP0);   // WDIE = interrupción; WDP = 1001 → 8 s
    sei();
}

static void dormir(void) {
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    sleep_bod_disable();                          // apaga el detector de brown-out durante el sueño, si el chip lo permite
    sei();
    sleep_cpu();
    sleep_disable();
}

int main(void) {
    /* configurar pines y periféricos (sección siguiente) */
    wdt_8s();
    for (;;) {
        dormir();
        if (despertares >= 8) {                   // 8 × 8 s ≈ 64 s: «un minuto» con la tolerancia del watchdog
            despertares = 0;
            /* medir, guardar o transmitir */
        }
    }
}

Los períodos del watchdog son 16, 32, 64, 125, 250 y 500 ms y 1, 2, 4 y 8 s, según los bits WDP3:0. Para intervalos mayores se cuentan despertares: con 8 s, un minuto son 8 despertares (64 s, con un error de hasta ±10 %). Si la hora importa, el reloj de cristal en el Timer2 es la respuesta. El segundo detalle: el watchdog en modo de interrupción despierta, pero si se deja WDE también activo, un segundo vencimiento sin atender provoca un reinicio.

06 · Lo que queda encendido

Apagar lo que no se usa

Dormir no alcanza si algo queda consumiendo. Una lista de comprobación, de lo más grande a lo más chico:

  • El ADC (cientos de microamperios encendido). Se apaga con ADCSRA &= ~(1 << ADEN).
  • El comparador analógico: ACSR |= (1 << ACD).
  • El detector de brown-out (BOD): consume unas decenas de microamperios mientras está activo. Se desactiva durante el sueño con sleep_bod_disable() o con los fusibles (a costa de perder la protección contra tensiones bajas, tema 13).
  • El watchdog: si no hace falta, se apaga.
  • Los periféricos con el registro de reducción de potencia PRR (PRTWI, PRTIM2, PRTIM0, PRTIM1, PRSPI, PRUSART0, PRADC): detiene el reloj del módulo. Se usan las macros power_adc_disable(), power_spi_disable(), power_twi_disable(), power_usart0_disable() y power_timer0_disable() de <avr/power.h>. Hay que inhabilitar el periférico antes de cortar su reloj, y reconfigurarlo al volver a encenderlo.
  • Los buffers digitales de los pines analógicos (DIDR0).
  • Los pines: un pin de entrada flotante (sin conectar ni pull-up) puede quedar en un nivel intermedio y hacer conducir ambos transistores de su buffer, con un consumo apreciable. Los pines sin uso se configuran como salida en bajo, o como entrada con pull-up interno. Los pines conectados a circuitos externos requieren cuidado: un pull-up que tira contra un nivel bajo de otro dispositivo consume V/R en forma permanente (10 kΩ a 5 V son 0,5 mA, cien veces el consumo dormido).
#include <avr/power.h>

static void estado_de_ahorro(void) {
    ADCSRA &= ~(1 << ADEN);                      // ADC apagado
    ACSR   |=  (1 << ACD);                       // comparador analógico apagado
    DIDR0   =  0x3F;                              // sin buffers digitales en PC0 a PC5
    power_adc_disable();
    power_spi_disable();
    power_twi_disable();
    power_usart0_disable();
    power_timer0_disable();
    power_timer1_disable();
    power_timer2_disable();

    DDRB = 0xFF;  PORTB = 0x00;                   // pines sin uso: salida en bajo (ajustar si alguno está conectado)
    DDRC = 0xFF;  PORTC = 0x00;
    DDRD = 0xFE;  PORTD = 0x01;                   // PD0 como entrada con pull-up (RX)
}

// Encender un sensor solo mientras se lo usa: alimentarlo desde un pin (hasta ~20 mA)
#define SENSOR_ON()   (PORTD |=  (1 << PD3))
#define SENSOR_OFF()  (PORTD &= ~(1 << PD3))

El último truco es el control de alimentación de los periféricos externos: un sensor que consume 1 mA todo el tiempo domina el presupuesto de un nodo que duerme a 5 µA. Si se alimenta desde un pin del microcontrolador (para corrientes bajas) o a través de un MOSFET (para corrientes mayores), se enciende, se espera a que se estabilice, se mide y se apaga. Cuidado con los buses compartidos: un sensor I2C apagado puede seguir recibiendo corriente a través de los pull-ups de SDA y SCL.

07 · La cuenta

El presupuesto de energía

La corriente media de un dispositivo que alterna entre actividad y sueño es el promedio ponderado por el tiempo:

Imedia = ( Iactiva · tactiva + Isueño · (T − tactiva) ) / T vida = capacidad · fracción útil / Imedia

Un nodo de medición despierta una vez por minuto: está activo 25 ms con 8 mA (CPU, sensor y transmisión) y duerme el resto a 5 µA. La parte activa aporta 3,33 µA al promedio; el sueño, 5,0 µA; el total del circuito es 8,33 µA. Con dos pilas AA (2500 mAh, el 80 % utilizable), serían 27 años.

Pero la cuenta tiene un tercer término que casi siempre se olvida: la autodescarga de la batería. Una pila alcalina pierde alrededor del 3 % de su carga por año aun sin uso; sobre 2500 mAh son unos 8,6 µA equivalentes, más que el consumo del circuito. Con ese término la vida baja a 13,5 años, y la mitad del consumo total es la batería «gastándose sola». En este régimen, reducir el circuito de 8 a 4 µA casi no cambia nada; hay que cambiar de batería. Las celdas de litio primarias (litio-tionilo, litio-dióxido de manganeso) pierden alrededor del 1 % al año.

El orden en que se ataca el consumo depende de cuál término domina:

  • Domina la parte activa: medir menos seguido, acortar el trabajo (menos ciclos, sensores encendidos menos tiempo), subir la frecuencia para terminar antes, bajar la tensión.
  • Domina el sueño: buscar los consumos parásitos (regulador, LED, pull-ups, pines flotantes, sensores alimentados), bajar a Power-down, apagar BOD y watchdog.
  • Domina la autodescarga: cambiar el tipo de batería o el tamaño; ya no se gana nada ahorrando en el circuito.

Otra consecuencia es la regla de «correr para dormir» (race to sleep): como parte de la corriente activa no depende de la frecuencia (osciladores, referencias, fugas), una tarea que se completa rápido a 16 MHz gasta menos energía que la misma tarea a 1 MHz, porque pasa menos tiempo con la parte fija encendida. Por eso en un diseño de bajo consumo se suele hacer lo contrario de lo intuitivo: se sube la frecuencia, se termina rápido y se duerme. La excepción es cuando la tensión puede bajarse (la energía por ciclo cae con V²) o cuando la tarea es tan corta que el despertar domina.

08 · Verificar con instrumentos

Medir el consumo

Los cálculos son una estimación; lo que importa es lo que mide un instrumento. Hay tres enfoques:

  • Multímetro en serie (escala de µA). Sirve para la corriente de sueño estable. Hay que recordar su resistencia de entrada (una caída de 0,1 a 1 V en la escala de µA): puede hacer que el circuito se comporte distinto. Y no sirve para ráfagas de milisegundos: promedia o se pierde la mitad.
  • Resistencia en serie y osciloscopio. Una resistencia de 10 Ω a 100 Ω en la alimentación convierte la corriente en una tensión que se observa en el osciloscopio: se ve la forma de cada despertar y se mide su duración. Para sueño de microamperios hace falta un amplificador o resistencias mucho mayores.
  • Instrumentos especializados (analizadores de energía como el Nordic PPK2, el Joulescope): miden desde nanoamperios hasta amperios, con registro y energía integrada por evento. Son la herramienta cómoda para ajustar un diseño.

Método de trabajo: medir primero el sueño (aislado de cualquier otra cosa), luego el despertar, y comparar con la estimación. Si el sueño mide 100 veces lo esperado, buscar el consumo parásito retirando componentes de a uno: LED, regulador, sensores, resistencias de pull-up. Una vez medido, repetir con la batería real a distintas temperaturas: el frío reduce la capacidad.

09 · Lo que suele salir mal

Trampas y buenas prácticas

Síntomas y causas en un diseño de bajo consumo.
SíntomaCausa probable
Medido en sueño: cientos de µA o mARegulador con corriente de reposo alta (los lineales comunes gastan 5 mA en vacío), LED de alimentación, pull-up contra un nivel bajo, pin flotante, sensor alimentado
El microcontrolador no despierta nuncaFalta sei() o la máscara de la fuente, el modo de sueño no admite esa fuente (Power-down no despierta con Timer0), o el evento llegó antes del SLEEP
Despierta inmediatamente y repetidoUna bandera de interrupción sigue en 1 (hay que borrarla); un pulsador con rebotes
La hora se atrasaTimer0 detenido durante el sueño (millis() no cuenta); el watchdog impreciso
Se pierden bytes de la UARTSe recibió mientras dormía
Lecturas del ADC raras tras despertarLa primera conversión tras encender el ADC es inexacta (25 ciclos) o el sensor no se estabilizó
Se reinicia al despertarLa tensión de la batería cae por debajo del brown-out cuando se enciende la radio o el sensor: capacitor mayor, batería de menor resistencia interna

Buenas prácticas, en orden de rendimiento: 1) diseñar la arquitectura alrededor del sueño: el programa se organiza en eventos que despiertan y vuelven a dormir; 2) evitar la espera activa (_delay_ms consume la corriente activa entera, hay que dormir en su lugar); 3) alimentar sensores y radios solo cuando se usan; 4) elegir un regulador de baja corriente de reposo (o prescindir de él con una batería de litio de 3 V); 5) medir.

10 · Analogía con programación

Calcular el consumo con datos

Este programa compara cinco escenarios de consumo y vida de una batería, descompone el consumo de un nodo de medición, muestra los períodos del watchdog y los despertares necesarios para un minuto, calcula la corriente media de una tarea según frecuencia y tensión, y estima el efecto de dos consumos parásitos.

Python en tu navegador. Los bloques son editables: cambiá los valores y presioná «Ejecutar Python». La primera vez tarda unos segundos en cargar.

import math

# 1) corriente media y vida de la bateria
def vida(i_act_ma, t_act_s, i_sleep_ua, periodo_s, cap_mah=2500, util=0.8, autodescarga=0.03, extra_ua=0.0):
    carga_act = i_act_ma * 1000 * t_act_s                       # uA*s por periodo
    carga_sleep = i_sleep_ua * (periodo_s - t_act_s)
    medio = (carga_act + carga_sleep) / periodo_s + extra_ua
    i_sd = cap_mah * 1000 * autodescarga / 8760                 # uA equivalentes de autodescarga
    total = medio + i_sd
    return medio, i_sd, cap_mah * util * 1000 / total           # horas

print("escenario                                   corriente media    vida")
casos = (
    ("Uno encendida todo el tiempo (45 mA)", 45000.0, None),
    ("Uno durmiendo el chip, placa 35 mA", 35000.0, None),
    ("chip solo: 8 mA durante 25 ms cada 60 s", None, (8, 0.025, 5, 60)),
    ("igual, midiendo cada 10 minutos", None, (8, 0.025, 5, 600)),
    ("igual, con pines flotantes (+0,5 mA)", None, (8, 0.025, 5 + 500, 60)),
)
for nombre, fijo, par in casos:
    if fijo is not None:
        horas = 2500 * 0.8 * 1000 / fijo
        print(f"{nombre:42s} {fijo:9.0f} uA   {horas:7.0f} h ({horas / 24:5.1f} dias)")
    else:
        medio, sd, horas = vida(*par)
        anios = horas / 8760
        print(f"{nombre:42s} {medio + sd:9.1f} uA   {horas:7.0f} h ({anios:5.1f} anios)")

# 2) a que se debe el consumo del nodo de 60 s
medio, sd, horas = vida(8, 0.025, 5, 60)
act = 8 * 1000 * 0.025 / 60
print()
print(f"nodo de 60 s: despierto {act:.2f} uA, durmiendo {5 * (60 - 0.025) / 60:.2f} uA, autodescarga {sd:.2f} uA")

# 3) dormir por intervalos con el watchdog
print()
print("WDP3:0   periodo nominal del watchdog")
nominal = ["16 ms", "32 ms", "64 ms", "0,125 s", "0,25 s", "0,5 s", "1 s", "2 s", "4 s", "8 s"]
for codigo in range(10):
    print(f"  {codigo:04b}    {nominal[codigo]:>8s}  (16 ms x 2^{codigo} = {16 * 2 ** codigo} ms)")
despertares = math.ceil(60 / 8)
print(f"para un minuto: {despertares} despertares de 8 s = {despertares * 8} s; con el oscilador del watchdog +-10 %: de {despertares * 8 * 0.9:.0f} a {despertares * 8 * 1.1:.0f} s")

# 4) energia por tarea segun reloj y tension: I = (fija + (ref - fija) * f/16) * V/5
def corriente(f, v, ref=10.0, fija=0.5):
    return (fija + (ref - fija) * f / 16) * v / 5

def corriente_media(f, v, n=100000, periodo=1.0, i_sleep=5.0):
    t = n / (f * 1e6)
    if t > periodo:
        return None
    return (corriente(f, v) * 1000 * t + i_sleep * (periodo - t)) / periodo

print()
print("tarea de 100 000 ciclos cada 1 s, corriente de sueno 5 uA:")
print("  V     f (MHz)   activa    tiempo activo   media")
for v in (5.0, 3.3):
    for f in (1, 4, 8, 16):
        if (v < 4.5 and f > 10) or (v < 2.7 and f > 4):
            continue
        m = corriente_media(f, v)
        print(f"  {v:3.1f}   {f:5d}    {corriente(f, v):5.2f} mA   {100000 / (f * 1e6) * 1000:7.2f} ms    {m:7.2f} uA")
print(f"energia relativa por ciclo, 3,3 V frente a 5 V: {(3.3 / 5) ** 2:.2f}")

# 5) consumos parasitos
print()
for nombre, ma in (("pull-up de 10 kohm a 5 V mantenido en bajo", 5 / 10000 * 1000), ("LED de alimentacion con 1 kohm", (5 - 2) / 1000 * 1000)):
    medio, sd, horas = vida(8, 0.025, 5, 60, extra_ua=ma * 1000)
    print(f"{nombre}: {ma:.2f} mA permanentes -> vida {horas / 24:6.0f} dias")

Resultado: la placa Uno encendida da 44 horas (1,9 días) con 2500 mAh; el chip solo midiendo una vez por minuto, 16,9 µA y 13,5 años; midiendo cada 10 minutos, 16,4 años (la autodescarga ya domina). Un pin flotante o un consumo parásito de 0,5 mA lo hunde a 0,4 años, y un LED de 3 mA a 28 días. En el nodo de 60 s, el 20 % del consumo es el despertar, el 30 % el sueño y el 51 % la autodescarga. Con un watchdog de 8 s, un minuto son 8 despertares (64 s, entre 58 y 70 s por la tolerancia del oscilador). En el modelo de reloj y tensión, a 5 V la tarea de 100 000 ciclos cada segundo cuesta 113,9 µA a 1 MHz y 67,5 µA a 16 MHz (correr para dormir); a 3,3 V y 8 MHz baja a 48,3 µA.

Los números de corriente son valores típicos del orden de magnitud; los reales dependen del chip, de la temperatura y de la tensión, y deben medirse.

11 · Exploración interactiva

Batería, sueño y reloj

La primera herramienta calcula la corriente media y la vida de una batería. La segunda recomienda el modo de sueño y muestra el código. La tercera estima el costo de una tarea según la frecuencia y la tensión.

Banco de energía

1. Corriente media y vida de la batería

Ciclo de trabajo—
Corriente media—
Vida de la batería—
Reparto del consumo—

2. Elegir el modo de sueño

Modo recomendado—
Consumo orientativo—
Qué queda en marcha—

3. Una tarea según reloj y tensión

Especificación—
Corriente activa—
Energía—
Corriente media—
Comparación de relojes—

Recorrido guiado

  1. Con los valores del ejemplo (8 mA durante 25 ms cada 60 s, 5 µA dormido, 2500 mAh): 0,042 % despierto y 8,33 µA de circuito. Con la autodescarga del 3 % sube a 16,9 µA y la vida es de 13,5 años (27,4 sin autodescarga); el 51 % del consumo es la batería.
  2. Subí la corriente dormido a 45 000 µA (una placa Uno con su regulador y su LED): 44,5 horas, y la nota avisa que es un consumo parásito.
  3. Pasá a un ciclo de 1 s con 100 ms despierto: 805 µA medios y 102 días, con el 98 % del consumo en la parte despierta.
  4. En el modo de sueño, el watchdog recomienda Power-down; el Timer2 asíncrono, Power-save; la UART, solo Idle.
  5. En la tercera herramienta, a 5 V la tarea de 100 000 ciclos por segundo gasta 113,9 µA a 1 MHz, 76,8 µA a 4 MHz, 70,6 µA a 8 MHz y 67,5 µA a 16 MHz: conviene correr y dormir.
  6. Con 3,3 V y 16 MHz el programa avisa que está fuera de la especificación; con 8 MHz la corriente media baja a 48,3 µA.
Desafío: ¿cuánto dura un reloj de pared con una pila?

Un reloj usa el Timer2 con su cristal de 32 kHz en Power-save (1 µA), despierta cada segundo 1 ms para actualizar una pantalla de 0,5 mA y la pila es una CR2032 de 220 mAh. El consumo medio es 1 µA + 0,5 mA × 1 ms / 1 s = 1 µA + 0,5 µA = 1,5 µA. La vida teórica es 220 mAh × 0,8 / 1,5 µA ≈ 117 000 horas (13 años); pero la CR2032 tiene una autodescarga del 1 % anual (unos 0,25 µA) y su capacidad cae si la corriente de pico es alta, por lo que se esperan de 5 a 8 años reales. La pantalla de 0,5 mA domina el despertar: si se actualizara cada minuto en lugar de cada segundo, el consumo bajaría a 1,01 µA.

12 · Comprensión

Confusiones frecuentes

«Mi Arduino con sleep gasta 40 mA, así que sleep no funciona»

El chip duerme, pero la placa no: el regulador, el LED y el convertidor USB siguen gastando. Para medir el ahorro hay que aislar el microcontrolador.

«Bajar la frecuencia siempre ahorra energía»

Baja la potencia instantánea, pero la tarea tarda más: la energía por tarea casi no cambia y la parte fija de la corriente se paga durante más tiempo. Es mejor terminar rápido y dormir.

«delay() deja el microcontrolador en reposo»

Es una espera activa: la CPU ejecuta un bucle y consume la corriente activa completa. Dormir con una interrupción de temporizador o del watchdog gasta miles de veces menos.

«Si la corriente de sueño es de 0,1 µA, la batería durará décadas»

La autodescarga y el consumo de todo lo demás (regulador, sensores, pull-ups) suelen ser mayores que el del chip. Hay que sumar todo el circuito y también la batería.

«Puedo dormir a un microcontrolador sin pensar en cómo despierta»

Sin una interrupción habilitada y de una fuente que el modo admita, no despierta. Y un evento que llegue justo antes de la instrucción SLEEP puede perderse si no se protege con el orden cli, comprobar, sei, sleep.

13 · Práctica guiada

Predecí antes de comprobar

1. Corriente media

Un dispositivo consume 5 mA durante 100 ms cada 10 s y 10 µA el resto. ¿Cuál es la corriente media y cuánto dura una batería de 1000 mAh (80 % útil, sin autodescarga)?

Ver solución

Imedia = (5000 µA × 0,1 s + 10 µA × 9,9 s) / 10 s = (500 + 99) / 10 = 59,9 µA. Vida = 800 mAh / 59,9 µA = 13 356 h = 556 días.

2. Elegir el modo

Para cada caso, ¿qué modo conviene? (a) Despertar con un pulsador; (b) llevar la hora con un cristal de 32 kHz; (c) recibir un byte por la UART.

Ver solución

(a) Power-down con interrupción por cambio de pin o por nivel. (b) Power-save, con el Timer2 asíncrono. (c) Idle, porque la UART necesita el reloj de E/S (en Power-down se puede despertar con un cambio en RX, pero se pierde el primer byte).

3. Intervalo con el watchdog

Se quiere medir cada 5 minutos con despertares de 8 s. ¿Cuántos despertares y qué error de tiempo se espera?

Ver solución

300 / 8 = 37,5 → 38 despertares (304 s). Con la tolerancia de ±10 % del oscilador, el intervalo real varía entre unos 274 y 334 s. Si hace falta mayor precisión, se usa el Timer2 con el cristal.

4. Energía por tarea

Una tarea de un millón de ciclos consume 3,125 nJ por ciclo a 5 V (modelo de corriente proporcional). ¿Cuánta energía cuesta a 5 V y a 3,3 V?

Ver solución

A 5 V: 1 000 000 × 3,125 nJ = 3,125 mJ. A 3,3 V la energía por ciclo es (3,3 / 5)² = 0,4356 veces: 1,361 mJ, un 56 % menos. Con la tensión menor la frecuencia máxima baja a 10 MHz.

5. Un consumo parásito

Un pull-up de 4,7 kΩ a 3,3 V queda mantenido en bajo por un sensor mientras el microcontrolador duerme a 10 µA. ¿Cuánto consume y cómo se evita?

Ver solución

3,3 V / 4,7 kΩ = 0,70 mA: 70 veces el consumo dormido. Se evita usando un pull-up de valor mucho mayor (100 kΩ: 33 µA, todavía alto), activando el pull-up interno solo mientras se lee, o cortando la alimentación del sensor y de su pull-up cuando no se usa.

14 · Síntesis

Ideas para recordar

  • La vida de una batería es capacidad dividida por corriente media; un dispositivo que duerme casi todo el tiempo gasta miles de veces menos que uno siempre activo.
  • El consumo dinámico crece con la frecuencia y el cuadrado de la tensión; hay una parte fija; el ATmega328P admite 1,8 a 5,5 V, con una frecuencia máxima que depende de la tensión.
  • Los modos de sueño (Idle, ADC Noise Reduction, Power-save, Power-down) se eligen con SMCR; se usa el más profundo que conserve la fuente de despertar necesaria.
  • Se duerme con sleep_enable(); sei(); sleep_cpu();, comprobando antes el evento para evitar la condición de carrera; sin interrupción habilitada no se despierta.
  • El watchdog (16 ms a 8 s) y el Timer2 asíncrono con cristal de 32 kHz son los relojes del sueño profundo.
  • Hay que apagar el ADC, el comparador, el BOD y los periféricos con PRR; fijar los pines sin uso; y alimentar los sensores solo cuando se usan.
  • Hay que sumar la autodescarga de la batería, que suele pesar tanto como el circuito; y hay que medir, porque un solo componente parásito puede multiplicar el consumo por cien.

¿Listo para el tema 41?

Antes de avanzar, calculá la corriente media y la vida de una batería para un ciclo dado, elegí el modo de sueño para una fuente de despertar y explicá por qué convienen terminar rápido y dormir. Si podés justificar las tres respuestas, entendés cómo se diseña para la batería.

En el próximo tema vemos la estructura de un programa para microcontroladores: inicialización, bucle principal, interrupciones y módulos, es decir, cómo organizar un programa que lo hace todo sin bloquearse y con la energía bajo control.