这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » Let'sdo2026第3期】基于边缘AI的电机状态检测--成果帖

共1条 1/1 1 跳转至页

Let'sdo2026第3期】基于边缘AI的电机状态检测--成果帖

菜鸟
2026-11-05 19:30:34     打赏

实现功能

利用AI边缘检测,实现对电机停止,低速,高速和异常四个状态的分类,通过本地部署,反应很快。


系统框图

image.png

 

通过按键改变电机状态,加速度传感器将电机抖动数据传给MCU,MCU上部署的AI模型对数据进行分析,并将电机运行状态进行分类。

 

电路原理图

 image.png

4f8de64212c776c8b52618873d120497.jpg

这张图展示了整个项目的硬件连接

 

启动

 将代码烧录,并将各模块按照原理图连接,将串口连接上位机,打开电源后整个设备就能正常启动了。按下板子上的用户按键来改变电机状态,通过串口查看检测到的状态。

 

主要参数情况

 

加速度传感器采集到的数据也都非常准确,各个运行状态的数据通过串口打印分析一下,也都有明显的差别。

 image.png

训练过程中的数据也都不错,软件上写的准确率100%

image.png

 测试了一会,感觉识别成功率还是很高的,尤其是对异常的检测,之前没在数据中的异常抖动也被分入异常这一类。

 屏幕截图 2026-11-05 165616.png

软件调试

 前面帖子中对遇到的问题大部分都解决了,在软件调试中没有遇到太大的困难,软件部分也是在前面代码的基础上修改,模块驱动代码没动,主要调整了一下主函数逻辑,新增了对异常情况的报警。


项目主要代码

 

/**
  ******************************************************************************
  * file           : main.c
  * brief          : Main program body
  *                  Calls target system initialization then loop in main.
  ******************************************************************************
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32c5xx_hal_gpio.h"
#include <stdint.h>
#include <stdio.h>
#include "LIS3DHTR.h"
#include "MOTO.h"
#include "NanoEdgeAI.h"
#include <stdbool.h>
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
float input_signal[NEAI_INPUT_SIGNAL_LENGTH * NEAI_INPUT_AXIS_NUMBER]; // Buffer of input values
float probabilities[NEAI_NUMBER_OF_CLASSES]; // Buffer of class probabilities
uint16_t wait = 0;
uint16_t key_num = 0;
#define MAX_FIFO_SAMPLES 32
int16_t fifo_acc[MAX_FIFO_SAMPLES * 3];
uint16_t signal_index = 0;
/* Private functions prototype -----------------------------------------------*/
void HAL_TIM_UpdateCallback(hal_tim_handle_t *htim)
{
    if (htim == mx_tim7_gethandle()) {
        MOTO_RUN(wait);
    }
}
int __io_putchar(int ch)
{
  uint8_t byte = (uint8_t)ch;
  HAL_UART_Transmit(mx_usart2_uart_gethandle(), &byte, 1, 1000);
  return ch;
}
uint16_t KEY_GET(uint16_t key_num)
{
  if(HAL_GPIO_ReadPin(HAL_GPIOC, HAL_GPIO_PIN_13) == HAL_GPIO_PIN_SET)
  {
    HAL_Delay(20);
    while(HAL_GPIO_ReadPin(HAL_GPIOC, HAL_GPIO_PIN_13) == HAL_GPIO_PIN_SET);
    HAL_Delay(20);
    key_num ++;
  }
  if(key_num > 2)
    {
      key_num = 0;
    }
  return key_num;
}
/**
  * brief:  The application entry point.
  * retval: none but we specify int to comply with C99 standard
  */
int main(void)
{
  /** System Init: this code placed in targets folder initializes your system.
    * It calls the initialization (and sets the initial configuration) of the peripherals.
    * You can use STM32CubeMX to generate and call this code or not in this project.
    * It also contains the HAL initialization and the initial clock configuration.
    */
  if (mx_system_init() != SYSTEM_OK)
  {
    return (-1);
  }
  else
  {
    /*
      * You can start your application code here
      */
    HAL_TIM_Start_IT(mx_tim7_gethandle());
    LIS3DHTR_Init();
    enum neai_state error_code = neai_classification_init();
    if (error_code != NEAI_OK) {
      printf("AI MODEL INIT FAILED\r\n");
      /* Check the returned error code (cf NanoEdgeAI.h). */
    }
    else {
      printf("AI MODEL INIT SUCCESS\r\n");
    }
    int id_class = 0;
    uint32_t last_time = HAL_GetTick();
    uint16_t key_num = 0;
    uint16_t key_num_last = 5;
    uint16_t class_count[4] = {0};
    uint16_t count = 0;
    
    while (1) {
      int16_t acc[3] = {0};
      key_num = KEY_GET(key_num);
      if ( key_num_last != key_num)
      {
          key_num_last = key_num;
          HAL_TIM_Stop_IT(mx_tim7_gethandle());
          HAL_TIM_SetCounter(mx_tim7_gethandle(), 0);
          if (key_num == 1)
          {
              
              HAL_TIM_SetPeriod(mx_tim7_gethandle(), 0x7CF);   // 1 kHz
              HAL_TIM_Start_IT(mx_tim7_gethandle());
          }
          else if (key_num == 2)
          {
              HAL_TIM_SetPeriod(mx_tim7_gethandle(), 0x4E1F);  // 100 Hz
              HAL_TIM_Start_IT(mx_tim7_gethandle());
          }
          else if(key_num == 0)
          {
            HAL_TIM_Stop_IT(mx_tim7_gethandle());
          }
      }
      int samples_read = LIS3DHTR_Read_FIFO_Data(fifo_acc);
      if(samples_read > 0) 
      {
      for (int i = 0; i < samples_read; i++) 
        {
          input_signal[signal_index * 3 + 0] = (float)fifo_acc[i * 3 + 0]; // X
          input_signal[signal_index * 3 + 1] = (float)fifo_acc[i * 3 + 1]; // Y
          input_signal[signal_index * 3 + 2] = (float)fifo_acc[i * 3 + 2]; // Z
          signal_index++;
          if(signal_index >= NEAI_INPUT_SIGNAL_LENGTH)
          {
            signal_index = 0;
            
            
             neai_classification(input_signal, probabilities, &id_class);
            
             switch (id_class) {
                case 0:
                    printf("STOP\r\n");
                    HAL_GPIO_WritePin(HAL_GPIOC, HAL_GPIO_PIN_11, HAL_GPIO_PIN_RESET);
                    break;
                case 1:
                    printf("LOW\r\n");
                    HAL_GPIO_WritePin(HAL_GPIOC, HAL_GPIO_PIN_11, HAL_GPIO_PIN_RESET);
                    break;
                case 2:
                    printf("FAST\r\n");
                    HAL_GPIO_WritePin(HAL_GPIOC, HAL_GPIO_PIN_11, HAL_GPIO_PIN_RESET);      
                    break;
                case 3:
                    printf("ABNORMAL\r\n");
                    HAL_GPIO_WritePin(HAL_GPIOC, HAL_GPIO_PIN_11, HAL_GPIO_PIN_SET);
                    break;
                default:
                    printf("Unknown class\r\n");
                    break;
             }
            }
         }
    }
    }
  }
} /* end main */


新的体会

 这次做下来,最大的感受是边缘AI确实很适合做电机状态检测这类任务。数据在本地采集、本地推理,响应很快,实际体验比预想的要流畅。

训练时准确率显示100%,一开始还有点担心是不是过拟合,但后面测试时发现,即使是一些没有参与训练的新异常抖动,模型也能正确识别,说明它学到的不是简单的背数据,而是确实抓住了不同状态之间的特征差异。

软件部分相对顺利,主要是在原有框架上继续完善。驱动层基本不用动,重点放在主循环里把数据采集、AI推理和状态输出串起来。加了一个异常报警后,整个系统看起来也更完整了。

整体来说,这个项目把传感器数据采集、AI模型部署和嵌入式控制结合得比较紧,做完之后对边缘AI在电机监测上的应用有了更直观的认识。




共1条 1/1 1 跳转至页

回复

匿名不能发帖!请先 [ 登陆 注册 ]