2. 测量OTA下载能耗基线

任务目标

在标准Wi-Fi条件下,使用功耗分析仪测量IoT终端下载1MB固件所消耗的能量,记录峰值电流、平均电流、下载耗时与总能耗,建立OTA下载能耗基线数据,为后续优化提供对比基准。

测量环境与设备

  • 被测设备:ESP32-S3开发板(Wi-Fi 802.11 b/g/n模式)
  • 功耗分析仪:Nordic Power Profiler Kit 2(PPK2),或同等支持电流采样率≥100kSPS的设备
  • 固件服务器:本地HTTP服务器(如Python http.server),确保Wi-Fi信号强度在-45~-55 dBm范围内
  • 固件文件:1MB随机数据文件(firmware.bin),放置于服务器根目录

测量原理

功耗分析仪串联在设备供电回路中,以固定采样率(本案例设为100kSPS)连续记录电流与电压。通过积分电流×电压×时间得到总能耗。测量分为两个阶段:空闲基线(Wi-Fi连接保持但不传输数据,持续5秒)和下载阶段(从HTTP服务器拉取1MB固件)。两阶段能耗差值即为OTA下载净增量能耗。

关键完整代码

// main.c - ESP32-S3 OTA下载能耗测量固件
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "esp_http_client.h"
#include "nvs_flash.h"
#include "driver/gpio.h"

#define FW_URL "http://192.168.1.100:8000/firmware.bin"
#define FW_SIZE (1024 * 1024)  // 1MB
#define GPIO_TRIGGER GPIO_NUM_4   // 测量触发引脚,接功耗分析仪数字输入

static void wifi_init(void) {
    nvs_flash_init();
    esp_netif_init();
    esp_event_loop_create_default();
    esp_netif_create_default_wifi_sta();
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);
    wifi_config_t wc = {.sta = {.ssid = "TEST_AP", .password = "12345678"}};
    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_set_config(WIFI_IF_STA, &wc);
    esp_wifi_start();
    esp_wifi_connect();
    vTaskDelay(pdMS_TO_TICKS(3000));  // 等待DHCP获取IP
}

static void http_download(void) {
    esp_http_client_config_t cfg = {
        .url = FW_URL,
        .method = HTTP_METHOD_GET,
        .timeout_ms = 30000,
    };
    esp_http_client_handle_t client = esp_http_client_init(&cfg);
    esp_http_client_open(client, 0);
    int len = esp_http_client_fetch_headers(client);
    int total = 0;
    char buf[1024];
    
    gpio_set_level(GPIO_TRIGGER, 1);  // 拉高触发引脚,标记下载开始
    while (total < FW_SIZE) {
        int r = esp_http_client_read(client, buf, sizeof(buf));
        if (r <= 0) break;
        total += r;
    }
    gpio_set_level(GPIO_TRIGGER, 0);  // 下载完成,拉低触发引脚
    esp_http_client_close(client);
    esp_http_client_cleanup(client);
    printf("Downloaded: %d bytes\n", total);
}

void app_main(void) {
    gpio_config_t io = {.pin_bit_mask = 1ULL << GPIO_TRIGGER,
                        .mode = GPIO_MODE_OUTPUT};
    gpio_config(&io);
    gpio_set_level(GPIO_TRIGGER, 0);
    
    wifi_init();
    vTaskDelay(pdMS_TO_TICKS(2000));  // 等待Wi-Fi稳定
    
    // 阶段1:空闲基线(5秒),功耗分析仪记录
    printf("Idle phase start\n");
    vTaskDelay(pdMS_TO_TICKS(5000));
    printf("Idle phase end\n");
    
    // 阶段2:下载1MB固件
    printf("Download phase start\n");
    http_download();
    printf("Download phase end\n");
    
    vTaskDelay(pdMS_TO_TICKS(1000));  // 等待数据落盘
}

测量步骤

  1. 硬件连接:将PPK2的VOUT接入ESP32-S3的3.3V供电端,GPIO4接PPK2的数字输入通道(用于事件标记)
  2. 启动服务器:在PC上执行 python3 -m http.server 8000,确保firmware.bin位于当前目录
  3. 配置PPK2:采样率设为100kSPS,量程选择合适档位(建议100mA或1A),开启数字输入记录
  4. 烧录并运行:idf.py flash monitor,观察串口输出"Idle phase start/end"与"Download phase start/end"
  5. 数据导出:在PPK2软件中标记两个阶段的时间区间,导出CSV数据

数据处理与基线计算

# analyze.py - 计算能耗基线
import csv
import sys

def calc_energy(csv_path, start_s, end_s):
    """计算指定时间段的能耗(单位:mWh)"""
    energy = 0.0
    peak_current = 0.0
    count = 0
    with open(csv_path) as f:
        reader = csv.DictReader(f)
        for row in reader:
            t = float(row['time_s'])
            if start_s <= t <= end_s:
                v = float(row['voltage_V'])
                i = float(row['current_A'])
                dt = 1.0 / 100000  # 100kSPS
                energy += v * i * dt / 3600 * 1000  # 转为mWh
                peak_current = max(peak_current, i)
                count += 1
    return energy, peak_current, count / 100000  # 返回能耗、峰值电流、时长

# 使用示例(根据PPK2导出的实际时间戳填写)
# idle_energy, idle_peak, idle_time = calc_energy('dump.csv', 5.0, 10.0)
# dl_energy, dl_peak, dl_time = calc_energy('dump.csv', 10.2, 15.8)
# print(f"下载净能耗: {dl_energy - idle_energy:.3f} mWh")

验证方法与通过标准

  • 功能验证:串口输出"Downloaded: 1048576 bytes",确认1MB固件完整下载
  • 数据有效性:PPK2记录中GPIO4信号在下载阶段为高电平,且下载阶段时长与串口时间戳误差<0.5s
  • 基线合理性:下载阶段平均电流应明显高于空闲阶段(通常3~10倍),总能耗在10~50mWh范围内(视Wi-Fi环境与设备功耗等级而定)
  • 可重复性:连续测量3次,能耗值偏差不超过±15%

常见问题

  • 下载失败:检查服务器IP与端口,确认ESP32能ping通服务器
  • 电流超量程:PPK2量程调至1A档,或降低采样率至50kSPS
  • GPIO信号毛刺:在GPIO4与GND之间并联100nF电容滤波