Sensor de temperatura: Consumo y autonomía con ATTINY13

Desde hace tiempo tengo entre manos el proyecto de un sensor de temperatura autónomo basado en un ESP8266 y un sensor DS18B20. La experiencia utilizando deepsleep con el watchdog del ESP8266 y los circuitos anteriores no había sido muy buena. Registrando la temperatura cada hora con una batería LiPo de 3600mAh conseguía una autonomía de 17 días, y con tres pilas recargables de NiMH de 2400mAh en serie tan solo llegaba a una semana, por lo que decidí modificar el circuito a esto:

El nuevo circuito incluye un ATTINY13 que se encarga de controlar la alimentación del NodeMCU usando un MOSFET-N como interruptor en la línea de tierra. El circuito consta de:

  • ESP8266 (NodeMCU)
  • ATTINY13
  • MOSFET-N IRL2203N con un pulldown de 10kΩ
  • Condensador de 220μF
  • DS18B20 con pullup de 4k7Ω
  • 3x Pila AA HR6 NiMH de 1,2v y 2400mAh

Para cargar las pilas estoy utilizando el circuito basado en el TP4056 de los diseños anteriores. Aunque el voltaje nominal de las pilas en total es de 3,6 vóltios con este circuito las cargo hasta 4,2 vóltios, realmente un poco menos. Estoy conectandolas directamente a 3.3v para evitar el consumo de regulador de tensión y del CP2102, y parece que el ESP8266 aguanta bien las tensiones superiores a 3.3 vóltios.

Con este nuevo circuito el sensor lleva funcionando más de tres semanas, registrando la temperatura alrededor de cada 40 minutos, y el voltaje en las pilas solo ha caido 0,14 vóltios (el ADC del ESP8266 no está calibrado, por eso el voltaje empieza en 3.5 en vez de ~4.2).

El código cargado en el ATTINY13 es el siguiente:

#include <avr/interrupt.h>
#include <avr/sleep.h>
// Pin 4 for MOSFET
int mosfet = 4;
int watchdog_counter = 0;
ISR(WDT_vect) {
  watchdog_counter++;
}
void setup() {
  ADCSRA &= ~(1 << ADEN);
  // prescale timer so we can measure temperature
  WDTCR |= (1<<WDP3 )|(0<<WDP2 )|(0<<WDP1)|(1<<WDP0); // 8s
  // Enable watchdog timer interrupts
  WDTCR |= (1<<WDTIE);
  WDTCR |= (0<<WDE);
  sei(); // Enable global interrupts
  // Use the Power Down sleep mode
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}
// the loop routine runs over and over again forever:
void loop() {
  sleep_mode();
  if(watchdog_counter > 225) { // 225 * 8 = 1800s = 30 min
    watchdog_counter = 0;
      pinMode(mosfet, OUTPUT);
      digitalWrite(mosfet, HIGH);   // switch the MOSFET
      delay(5000);               // wait for five a second
      digitalWrite(mosfet, LOW);
  }
}

El código activa el watchdog y el deepsleep del ATTINY13, y comprueba cada 8 segundos (que es el máximo que puede “dormir”) si han pasado 30 minutos desde la última medida. Si es así activa el MOSFET durante 5 segundos, tiempo suficiente para que el NodeMCU se encienda, conecte, mida la temperatura y la envíe al servidor. Como el NodeMCU tiene el mismo sketch que la versión anterior al acabar el proceso pasa a reposo. Como resultado el sensor ha pasado a consumir ~0,1μA en reposo, y añadiendo tan solo ~240μA a los periodos de actividad (y estoy muy contento con el resultado).

El resto de versiones, la documentación de los componetes y los esquemas pueden encontrarse en el repositorio en Github.