3. 部署正弦波预测模型

任务目标

本案例将训练好的正弦波预测模型(TensorFlow Lite Micro格式)部署到MCU上,实现基于历史输入样本的实时正弦波预测,并通过串口输出预测结果。核心目标是验证TFLite Micro推理链路在嵌入式平台上的完整可用性。

环境与依赖

  • 硬件:STM32F746G-DISCO开发板(或任意Cortex-M4F以上、≥320KB RAM的MCU)
  • 工具链:GNU Arm Embedded Toolchain 10.3+,CMake 3.16+
  • 依赖库:TensorFlow Lite Micro(从tensorflow/tflite-micro官方仓库获取,版本≥2023.09)
  • 模型文件:sine_model.tflite(已量化,输入/输出均为float32,输入维度[1,1],输出维度[1,1])

模型与输入说明

模型实现函数近似:y = sin(x),输入为归一化到[-π, π]的相位值,输出为[-1, 1]的预测值。模型已通过TensorFlow训练并转换为TFLite格式,经xxd转换为C数组嵌入工程。

关键完整代码

// main.cc - TFLite Micro 正弦波预测部署
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/micro/micro_mutable_op_resolver.h"
#include "tensorflow/lite/micro/system_setup.h"
#include "tensorflow/lite/schema/schema_generated.h"
#include "sine_model_data.h"  // 由xxd生成的模型数组

// 全局推理环境
constexpr int kTensorArenaSize = 2 * 1024;  // 2KB张量内存池
uint8_t tensor_arena[kTensorArenaSize];

// 串口输出(STM32 HAL示例,其他平台替换为对应UART发送)
extern "C" void print_float(float val) {
  char buf[32];
  snprintf(buf, sizeof(buf), "%.4f\r\n", val);
  HAL_UART_Transmit(&huart1, (uint8_t*)buf, strlen(buf), 100);
}

int main() {
  tflite::InitializeTarget();
  
  // 加载模型
  const tflite::Model* model = tflite::GetModel(sine_model_data);
  if (model->version() != TFLITE_SCHEMA_VERSION) return -1;

  // 注册算子(仅FULLY_CONNECTED)
  static tflite::MicroMutableOpResolver<1> resolver;
  resolver.AddFullyConnected();

  // 构建解释器
  static tflite::MicroInterpreter interpreter(model, resolver, tensor_arena, 
                                               kTensorArenaSize);
  if (interpreter.AllocateTensors() != kTfLiteOk) return -2;

  // 获取输入/输出张量
  TfLiteTensor* input = interpreter.input(0);
  TfLiteTensor* output = interpreter.output(0);

  // 实时预测循环:相位从0递增到2π
  float phase = 0.0f;
  const float step = 0.1f;
  
  while (true) {
    // 设置输入(归一化到[-π, π])
    input->data.f[0] = phase - 3.14159f;
    
    // 执行推理
    if (interpreter.Invoke() != kTfLiteOk) return -3;
    
    // 输出预测值
    print_float(output->data.f[0]);
    
    // 更新相位
    phase += step;
    if (phase > 6.28318f) phase = 0.0f;
    
    // 简单延时(约100ms)
    HAL_Delay(100);
  }
}

构建与烧录

# 1. 获取TFLite Micro源码并添加本文件
git clone https://github.com/tensorflow/tflite-micro.git
cd tflite-micro
# 将main.cc放入tensorflow/lite/micro/examples/sine_deploy/
# 将sine_model_data.h放入同目录

# 2. 生成模型头文件(若尚未生成)
xxd -i sine_model.tflite > sine_model_data.h
# 编辑头文件,将数组名改为sine_model_data

# 3. 使用CMake交叉编译(以STM32F746G-DISCO为例)
make -f tensorflow/lite/micro/tools/make/Makefile \
  TARGET=stm32f746g \
  OPTIMIZED_KERNEL_DIR=cmsis_nn \
  BUILD_TYPE=release \
  sine_deploy

# 4. 烧录生成的bin文件到开发板
# 使用STM32CubeProgrammer或OpenOCD

验证方法与判定标准

  1. 串口输出检查:以115200波特率打开串口,应持续收到数值输出,格式为xxxx(4位小数)。
  2. 数值正确性:采集10个连续输出值,与sin(phase-π)的理论值对比,最大误差应<0.05(量化模型精度范围)。
  3. 周期性验证:输出值应呈现正弦波形周期变化,周期约为2π/0.1×0.1s ≈ 6.28s。
  4. 稳定性:持续运行5分钟无死机、无输出中断。

常见问题

  • 张量内存不足:若AllocateTensors()返回错误,将kTensorArenaSize增大至4KB或8KB。
  • 算子不支持:若模型含其他算子(如激活函数),需在resolver中对应添加,例如resolver.AddRelu()。
  • 输出恒为0:检查输入归一化是否正确,模型训练时的输入范围必须与部署时一致。