DEV Community

Cover image for Building a Multi-Year Battery Life IoT Data Logger: A Deep Dive into Ultra-Low-Power Design

Building a Multi-Year Battery Life IoT Data Logger: A Deep Dive into Ultra-Low-Power Design

Introduction

Ever wondered how industrial IoT devices achieve multi-year battery life while transmitting data over cellular networks? In this article, I'll walk you through a real-world implementation of an ultra-low-power industrial data logger that monitors diesel fuel levels remotely and achieves an impressive 3-11 year battery life.

We'll be using the EC-M12-BC-C6-C-A, a battery-powered device with an STM32L0 series microcontroller and a SIM7070 LTE modem – a common setup in industrial monitoring applications.

The Challenge

Remote monitoring systems face a critical tradeoff: you need frequent data updates for real-time insights, but each transmission cycle drains your battery. Cellular modems are particularly power-hungry, with peak currents reaching 840mA during network initialisation.

The goal? Design a system that can:

  • Read analog sensor data accurately
  • Transmit to cloud dashboard via 4G/LTE-M
  • Operate for years on primary lithium batteries
  • Handle harsh industrial environments

System Architecture

[4-20mA Fuel Sensor] → [STM32L0 MCU] → [SIM7070 Modem] → [4G Network] → [ThingsBoard Dashboard]
Enter fullscreen mode Exit fullscreen mode

Hardware Components

  • MCU: STM32L0
  • Cellular: SIM7070 NB-IoT/LTE-M modem
  • Power: 2× ER34615H lithium batteries (19,000mAh each)
  • Sensor: 4-20mA diesel fuel tank level sensor

The Power Consumption Breakdown

Here's where it gets interesting. The system operates in three distinct stages:

Stage 1: Modem Initialization (60 seconds)

  • Average Current: 17.71mA
  • Peak Current: 840mA (during network registration)
  • Energy: 3.93 J

This is the power-hungry phase. The SIM7070 needs to:

  1. Power up the RF circuitry
  2. Search for cellular networks
  3. Register with the tower
  4. Establish GPRS/LTE connection

Key Design Decision: A 1000µF tantalum capacitor placed near the modem acts as a local energy reservoir, smoothing out the 30-40ms current spikes that can exceed 300mA.

Stage 2: Sensor Read + Data Transmission (7.5 seconds)

  • Average Current: 11.24mA
  • Energy: 0.31 J

During this phase:

  1. Read 4-20mA sensor (fuel level)
  2. Read battery voltage
  3. Publish telemetry to ThingsBoard via MQTT
  4. Disable all peripherals

Stage 3: Deep Sleep (15 minutes)

Average Current: 1.05µA
Energy: 0.0035 J

This is where the magic happens. The STM32L0 enters shutdown mode:

All peripherals powered down
Only RTC remains active
Occasional 2-3mA spikes for RTC maintenance (negligible impact)

The Math Behind Battery Life

With 38,000mAh capacity, here's the battery life estimation:

Average Current Formula:

I_avg = (I_sleep × T_sleep + I_active × T_active) / (T_sleep + T_active)

Results:

Current Usage Data EC-M12-BC-C6-C-A

The 4× increase in sleep time gives you a 3.4× improvement in battery life. This demonstrates the power of duty cycling in embedded systems.

Software Implementation Highlights

Low-Power Mode Configuration

// STM32L0 shutdown mode configuration
#include <STM32LowPower.h>
void setup() {
  Serial.begin(9600);
  LowPower.begin();                   //Initiate low power mode
}
void loop() {
  Serial.println("Entering low power mode...");

  SPI.end();
  delay(1000);
  Wire2.end();
  delay(1000);


  digitalWrite(BOOST_EN, LOW);
  delay(1000);

  // === Fully cut power to GSM ===
  digitalWrite(GSM_POWER, HIGH);  // Depending on your wiring,   HIGH disables modem regulator
  delay(2000);

LowPower.shutdown(900000);
}

Enter fullscreen mode Exit fullscreen mode

Efficient MQTT Publishing

The system uses MQTT over LTE for minimal protocol overhead:

void publishTelemetry() {
 int16_t adc0, adc1, adc2, adc3;

  adc1 = ads1.readADC_SingleEnded(1) * mA_Factor;
  adc2 = ads1.readADC_SingleEnded(2);


  float voltage2 = adc2 * 0.125 / 1000.0 / VOLTAGE_DIVIDER_RATIO;

  Serial.print("AIN1: "); Serial.print(adc0); Serial.println("  ");
  Serial.print("AIN2: "); Serial.print(adc1); Serial.println("  ");
  Serial.print("Voltage: "); Serial.print(voltage2); Serial.println("  ");


  float fuel_percent = (adc1 - 4.0) * 100.0 / 16.0;
  fuel_percent = constrain(fuel_percent, 0, 100);

  // Fuel height
  float fuel_level_mm = (fuel_percent / 100.0) * 1000;

  // Fault detection
  bool fuel_sensor_fault = false;
  if (adc1 < 3.6 || adc1 > 22.0) {
    fuel_sensor_fault = true;
  }

  StaticJsonDocument<200> doc;
  doc["fuel_level_percent"] = fuel_percent;
  doc["fuel_level_mm"]      = fuel_level_mm;
  doc["battery_voltage"]    = voltage2;
  doc["fuel_sensor_fault"]  = fuel_sensor_fault;

  String jsonStr;
  serializeJson(doc, jsonStr);

  mqtt.publish("v1/devices/me/telemetry", jsonStr.c_str());
  Serial.print("Published: ");
  Serial.println(jsonStr);

}

Enter fullscreen mode Exit fullscreen mode

Sensor Fault Detection

The system monitors for open/short circuits in the 4-20mA loop:

  • < 3.8mA: Sensor fault (open circuit)
  • > 20.5mA: Sensor fault (short circuit)
  • 4-20mA: Normal operation

Real-World Considerations

  1. Cellular Signal Strength
    Poor signal = higher power consumption. The modem will retry connections and transmit at higher power levels, significantly reducing battery life.

  2. Sensor Current Impact
    The 4-20mA sensor itself consumes power proportional to the measured value. A full tank (20mA) drains more power than an empty tank (4mA).

  3. Temperature Effects
    Lithium batteries lose capacity in extreme cold. Consider temperature-compensated battery life calculations for outdoor installations.

  4. Network Protocol Choice
    NB-IoT and LTE-M are specifically designed for IoT applications with lower power consumption than standard LTE. Choose wisely based on your region's network availability.

Lessons Learned

  1. Duty cycling is king: The difference between 15-minute and 1-hour intervals is massive (3.36 vs 11.4 years).

  2. Modem initialization dominates: Even though it's only 1 minute per cycle, it consumes 85% of the total energy per transmission.

  3. Hardware matters: The STM32L0's 1.05µA shutdown current makes multi-year operation possible. A standard MCU would drain batteries in months.

Future Improvements

  • Implement adaptive transmission intervals based on fuel level change rate
  • Implement predictive maintenance alerts based on battery voltage trends

Conclusion

Building ultra-low-power IoT devices requires careful consideration of every milliamp-hour. By combining:

  • Efficient duty cycling
  • Ultra-low-power MCU sleep modes
  • Optimized cellular communication
  • Smart peripheral management

We achieved a system that can monitor remote industrial assets for over 3 years on battery power alone, with the potential to extend that to 11+ years with less frequent updates.

The complete source code and detailed setup instructions are available on GitHub.

Check the product (EC-M12-BC-C6-C-A) documentation.

Top comments (0)