当前位置: 首页 > news >正文

【嵌入式电机控制#16】电流环(三):过采样提高采集精度看门狗监测总线电压

一、香农采样定律

        为不失真的复现信号的变化,采样频率至少应大于等于连续信号最高频率分量的二倍

        采样定律只能确定采样周期的上限(采样频率的下限),实际采样周期的选择受多方面影响。

        一般情况下:

        1. 对于响应快波动大、易受干扰(压力、流量)的过程,应该选较高的采样频率

        2. 对于过程响应慢,滞后大(温度、化学成分等)选取较低采样频率

        当过程的纯滞后时间较长时,选取采样周期为纯滞后时间的1/4到1/8

        

        STM32的ADC分辨率为12bit,假设PWM脉冲频率为20KHz,则理论上讲采样频率达到40Khz就能正确采集波形。

二、代码改进

        注意看写的注释,不然干看代码是看不懂的

        (1)adc.h修改配置     

                       VoltageResolution = ADC(Hex) * 3.3 / 2^n *1000 mV

        根据香农采样定律,采样频率选取的最小值应该为PWM的两倍

        再由过采样理论, 实际采样率 > 两倍PWM频率 *  4^2 

        所以采样频率能够拉到14bit,公式中应该改为除以2^14也就是16384

#define VOLT_RESOLUTION     ((float)((VOLT_REF/(float)(16384))*(float)1000))
#define VOLTBUS_RESOLUTION  ((float)( 3.3f/(float)4096) * (42.4f+2.0f) / 2.0f)

       (2)adc.c 采样DMA                

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)  
{uint16_t ConvCnt = 0;int32_t ADConv = 0 ; 
//定义采样次数计数器,定义采样结果寄存器(注意,这次移到中断里成动态量了)
//这里注意防止采样次数AverCnt溢出HAL_ADC_Stop_DMA(hadc);
//先停止DMA,目的是不干扰时序SetChannelAsRank1(hadc,ADC_VOLT_CHANNEL);
//设置电压采样优先,为电压提供专属的数据采集时机,为电流保留了数据处理的机会
//此时DMA只采集电压,电流DMA被维护HAL_ADC_Start(hadc);
//ADC重新开启,此时正式开始采集电压,与此同时处理电流for(ConvCnt = 0; ConvCnt < (ADC_BUFFER ); ConvCnt++){ADConv += ((int32_t)ADC_ConvValueHex[ConvCnt]);}
//进行电流采集量累加,一共1024次ADConv >>= ADC_Base;
//进行取平均,注意这里只移动了8位,也就是256,故意少除以2^2,为12bit->14bit的过采样处理AverSum += ADConv;
//进行采样结果累加AverCnt++;
//采样次数自增 HAL_ADC_Stop(hadc);
//停止ADC,并把ADC权限留给电流,电压后续在窗口看门狗中进行总线电压监测SetChannelAsRank1(hadc,ADC_CURRENT_CHANNEL);HAL_ADC_Start_DMA(hadc,(uint32_t*)ADC_ConvValueHex,ADC_BUFFER);
//这句话不仅有重新开始DMA的含义,也有重启ADC的意思
}

        (3) 定时器中断采样数据进一步处理

void HAL_SYSTICK_Callback(void)
{__IO int32_t ADC_Resul= 0;__IO float Volt_Result = 0;__IO float ADC_CurrentValue;//定义ADC结果寄存器,电流采样电压结果寄存器,最终实际电流值寄存器if((uwTick % 50) == 0){ADC_Resul = AverSum/AverCnt ;
//每一次中断,进行动态窗口滤波,窗口长度根据此前DMA次数调整OffsetCnt_Flag++;if(OffsetCnt_Flag >= 16){//经过实际测试,17次进入定时器中断时,电流波形才稳定//那么我们就把前一次的值当作零漂if(OffsetCnt_Flag == 16){OffSetHex = ADC_Resul;}//标准的状态机写法,以固定的32代表电流采样进入正常状态,每次进来都会被赋为32//那么我们如果需要在控制日志中导出电流数据,就可以在这个大判断后print它的flagOffsetCnt_Flag = 32;//adc结果减去偏差才是真正的采样值ADC_Resul -= OffSetHex;}
//计算进入单片机的电压模拟量Volt_Result = ( (float)( (float)(ADC_Resul) * VOLT_RESOLUTION) );
//计算电机端实际的电流ADC_CurrentValue = (float)( (Volt_Result / GAIN) / SAMPLING_RES);
//对动态窗口的计数值、累加值清零AverCnt = 0;AverSum = 0;printf("Volt: %.1f mV -- Curr: %d mA\n",Volt_Result,(int32_t(ADC_CurrentValue+10));}
}

          (4) 窗口看门狗实现总线电压监测

        这段代码实现了一个逻辑:如果电压异常被WD连续检测出六次,则强制关闭电机,然后关闭定时器PWM输出。

void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
{//给一个计数值i,并定义为静态量//注意这种用法,下一次触发看门狗时,i的值还保留,效果类似全局静态static uint8_t i = 0;i++;//这里直接自增了 ,说明一切从i==1开始if(ADC_VoltBus > VOLT_LIMIT_MIN  && ADC_VoltBus < VOLT_LIMIT_MAX)//如果总线电压大于最小供电,并小于最大电压限制i = 0 ;else if(i>=6){SHUTDOWN_MOTOR();//禁用驱动HAL_TIM_PWM_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);HAL_TIMEx_PWMN_Stop(&htimx_BDCMOTOR,TIM_CHANNEL_1);//关闭输出PWM_Duty = 0;//这里可以直接做PID清理
//    ADC_VoltBus = (float)ADC_VoltBus * VOLTBUS_RESOLUTION;//如果需要在控制日志中查看危险电压到底是多少,可以算一下ADCprintf("Bus Voltage is out of range!!\n");//汇报控制日志printf("Please Reset the Target!\n");//死循环,等待用户resetwhile(1);}
}

(5)以上三个中断的优先级配置建议

        为了安全起见,看门狗的中断优先级必须是三个中最高的。这样单片机才能在安全环境下稳定工作。

        其次,ADC采样速率要求较快,并且是定时器数据处理的基础,所以我们安排次高优先级。

        最后,当ADC数据处理完毕后,再将数据送给数据处理中断,所以它安排最低。

        总结:

                最高:窗口看门狗中断

                适中:ADC的DMA中断

                最低:数据处理的定时器中断

http://www.dtcms.com/a/287485.html

相关文章:

  • Nginx 实战 :使用logrotate实现日志轮转与保留策略!
  • 【数据结构】二叉树初阶详解(一):树与二叉树基础 + 堆结构全解析
  • 2025 Data Whale x PyTorch 安装学习笔记(Windows 版)
  • Kotlin方差
  • 403 Forbidden:无权限访问请求的资源如何处理
  • Apache Kafka 学习笔记
  • FreeRTOS—列表和列表项
  • Kafka、RabbitMQ 与 RocketMQ 高可靠消息保障方案对比分析
  • 阿里云服务器 CentOS 7 安装 MySQL 8.4 超详细指南
  • UniApp 优化实践:使用常量统一管理本地存储 Key,提升可维护性
  • 【无标题】重点阅读——如何在信息层面区分和表征卷曲维度,解析黑洞内部的维度区分机制
  • 基于 Google Earth Engine 的 DEM 鞍部自动提取
  • 基于Python的毕业设计选题管理系统设计与实现
  • 【CAN通信】AUTOSAR架构下TC3xx芯片是如何将一帧CAN报文发送出去的
  • NX二次开发常用函数坐标转化UF_MTX4_csys_to_csys和UF_MTX4_vec3_multipl
  • Linux基础命令(第二期)
  • 地图定位与导航
  • Go-Redis × RediSearch 全流程实践
  • Node.js:Stream、模块系统
  • KANO模型分类,以扫地机功能为例子
  • 实验-华为综合
  • 论文略读: RASA: RANK-SHARING LOW-RANK ADAPTATION
  • 《Linux系统配置实战:NTP时间同步与SSH免密登录全流程指南》​​
  • 【洛谷】询问学号、寄包柜、移动零、颜色分类(vector相关算法题p1)
  • LVS(Linux virual server)基础概念详解
  • 网络通信原理:分层协作与协议解析
  • Matplotlib 30分钟精通
  • 免费收听广播
  • C++类和对象(一)基础内容讲解
  • 使用uvx运行和安装Python应用程序