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

【嵌入式电机控制#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.xdnf.cn/news/15741.html

相关文章:

  • 【Linux系统】进程控制
  • 从0开始学习R语言--Day51--PH检验
  • OpenCV 官翻 1 -介绍、安装、功能概览、核心操作
  • 云计算与 DevOps(开发与运维)
  • sqli-labs靶场通关笔记:第32-33关 宽字节注入
  • Java 中的继承与多态
  • 基于GEE与哨兵2号的土地覆盖分类方法及实现
  • Vue Swiper组件
  • n8n教程分享,从Github读取.md文档内容
  • MySQL(145)如何升级MySQL版本?
  • 【爬虫】04 - 高级数据存储
  • Fortran实战:快速解析气象NC数据
  • OpenCV 官翻8 - 其他算法
  • 牛客-倒置字符串
  • SQL Server和PostgreSQL填充因子
  • debian的pulseaudio删掉也没事
  • SIMATIC WinCC Unified 使用 KPI 优化流程
  • Nacos配置管理
  • 【Unity3D实例-功能-移动】角色移动-通过WSAD(Rigidbody方式)
  • Kafka、RabbitMQ 与 RocketMQ 高可靠消息保障方案对比分析
  • TinyMCE 富文本编辑器在 vue2 中的使用 @tinymce/tinymce-vue
  • MySQL——约束类型
  • Vue 3 中封装并使用 IndexedDB 的完整教程(含泛型、模块化、通用 CRUD)
  • 网络爬虫概念初解
  • 【Unity】YooAsset问题记录
  • 如何在HTML5页面中嵌入视频
  • Git基础
  • 【每日算法】专题十五_BFS 解决 FloodFill 算法
  • 电脑windows系统深度维护指南
  • 微软原版系统下载的几个好用网站