【STM32CubeMX】位置式PID调节控制输出电压(超详解)

2023-11-16

  本文将借助STM32CubeMX来配置ADC、DMA、DAC、USART,并利用PID位置式算法实现对输出电压进行AD采集通过PID算法调节DAC,获取到我们想要的电压值。
讲解的主要知识:

  1. 何为PID以及为何需要PID
  2. STM32CubeMX创建
  3. STM32源代码

1、何为PID以及为何需要PID

  以下是PID控制的整体框图,过程描述为:设定一个输出目标,反馈系统传回输出值,如与目标不一致,则存在一个误差,PID根据此误差调整输入值,直至输出达到设定值。

  疑问:那我们为什么需要PID呢?比如我想要利用DAC输出一个1.65V电压,直接输出不就可以了吗?

  这里必须要先说下我们的目标,因为我们所有的控制无非就是想输出能够达到我们的设定,即如果我们设定了一个目标电压值,那么我们想要一个什么样的电压值变化呢?

  比如设定目标电压值为1.65V,目标无非是希望其能够快速而且没有抖动的达到1.65V。

  那这样大家应该就明白,如果只是使用DAC输出一个数字信号,外界出现的误差(例如导线、噪声等原因)都可能影响到最终输出的数值,因此我们需要利用PID调节最终读取到我们想要的值。

在这里插入图片描述
Eg:要求输出1.65V,控制输出1.65V,其实得到的是1.6V,如果控制输出1.68V,那么可能可以得到1.65V,其实就是缩减目标与实际之间的误差。


2、STM32CubeMX配置:

2.1 所用工具:

  • 芯片:STM32F103RCT6
  • IDE:MDK-Keil软件
  • STM32F1xxHAL库

2.2 知识概括:

  • STM32CubeMX创建ADC、DMA、DAC、USART例程
  • Keil软件程序编写

2.3 工程创建

1、芯片选择
  芯片:STM32F103RCT6(根据自己的板子来进行选择)

在这里插入图片描述
2、设置RCC
  设置高速外部时钟HSE 选择外部时钟源

在这里插入图片描述
3、设置ADC引脚
  ADC1通道0即PA0,开启连续转换模式,转换周期:55.5Cycles

在这里插入图片描述
在这里插入图片描述

4、ADC利用DMA传输
  设置DMA传输模式:循环传输(有数据就传输),同时设置高优先级

在这里插入图片描述
5、开启DAC输出
在这里插入图片描述
6、开启USART1
  设置异步通信,波特率115200Bits/s

在这里插入图片描述

7、配置时钟
  F1系列芯片系统时钟为72MHzs

在这里插入图片描述
8、项目创建最后步骤

  • 设置项目名称
  • 设置存储路径
  • 选择所用IDE

在这里插入图片描述

9、输出文件

  • ②处:复制所用文件的.c和.h
  • ③处:每个功能生产独立的.c和.h文件
    在这里插入图片描述

10、创建工程文件
  点击GENERATE CODE 创建工程

11、配置下载工具
  这里我们需要勾选上下载后直接运行

在这里插入图片描述


3、STM32源代码:

  首先编写pid.c与pid.h文件代码,这里编写的是pid位置式算法。
(1)pid.h

#ifndef __PID_H__
#define __PID_H__
#include "main.h"

typedef struct
{
    float SetVoltage;	  	//定义设定值
    float ActualVoltage;	//定义实际值
    float err;			    //定义偏差值
    float err_last;		  	//定义上一个偏差值
    float Kp,Ki,Kd;		  	//定义比例、积分、微分系数
    float result;		    //pid计算结果
    float voltage;		  	//定义电压值(控制执行器的变量)0-5v右转 5-10v左转
    float integral;		  	//定义积分值
}pid_p; 

void PID_init( void);
float PID_realize( float v, float v_r);

#endif

(2)pid.c

#include "pid.h"
#include "stdio.h"

pid_p pid;

//pid位置式
void PID_init()
{
    printf("PID_init begin \n");
    pid.SetVoltage= 0.0;		  	// 设定的预期电压值
    pid.ActualVoltage= 0.0;			// adc实际电压值
    pid.err= 0.0;				    // 当前次实际与理想的偏差
    pid.err_last=0.0;			    // 上一次的偏差
    pid.voltage= 0.0;			    // 控制电压值
    pid.integral= 0.0;			  	// 积分值
    pid.Kp= 0.2;				    // 比例系数
    pid.Ki= 0.15;				    // 积分系数
    pid.Kd= 0.2;				    // 微分系数
    printf("PID_init end \n");
}

float PID_realize( float v, float v_r)
{
    pid.SetVoltage = v;			// 固定电压值传入
    pid.ActualVoltage = v_r;	// 实际电压传入 = ADC_Value * 3.3f/ 4096
    pid.err = pid.SetVoltage - pid.ActualVoltage;	//计算偏差
    pid.integral += pid.err;						//积分求和
    pid.result = pid.Kp * pid.err + pid.Ki * pid.integral + pid.Kd * ( pid.err - pid.err_last);//位置式公式
    pid.err_last = pid.err;				//留住上一次误差
    return pid.result;
}

(3)在main.c加上:

/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "pid.h"
/* USER CODE END Includes */
/* USER CODE BEGIN PD */
#define ADC_Channel_MAX 2
/* USER CODE END PD */
/* USER CODE BEGIN PV */
uint16_t ADC_DMA_Value[ADC_Channel_MAX];  // DMA得到ADC的值
uint16_t ADC_Value = 0;
uint16_t DAC_Value = 100;
/* USER CODE END PV */
/* USER CODE BEGIN 0 */
/**
  * 函数功能: 重定向c库函数printf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
 
/**
  * 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明:无
  */
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}
/* USER CODE END 0 */

(4)在ADC初始化之后加上AD校准函数:

  /* USER CODE BEGIN 2 */
  HAL_ADCEx_Calibration_Start(&hadc1);  // f1系列需要ADC校准,f4不需要
  HAL_ADC_Start_DMA(&hadc1,(uint32_t *)&ADC_DMA_Value,ADC_Channel_MAX); // 启动ADC的DMA转换
  PID_init();
  /* USER CODE END 2 */

(5)while中加上:

      HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, DAC_Value); // 设置DAC数值
	  HAL_DAC_Start(&hdac,DAC_CHANNEL_1);   // 开启DAC输出
	  ADC_Value = ADC_DMA_Value[0];
	  printf("%0.2f\r\n", ADC_Value*3.3/4096);
	  // 这里设置输出1.65V
	  DAC_Value = DAC_Value + PID_realize(2048, ADC_Value);
	  HAL_Delay(100);

(6)用一根杜邦线连接PA0(ADC1_IN0)与PA4(DAC),然后串口连接电脑(我这里利用USB转TLL连接电脑,RX接PA9(USART1_TX),TX接PA10(USART1_RX))

(7)之后就可以完成正常读取,刚打开串口时:
在这里插入图片描述
(8)PID调节稳定后(DAC输出1.65V):
在这里插入图片描述
程序下载地址:https://download.csdn.net/download/weixin_44270218/13981014

总结:

  以上就是利用PID调节控制获取我想要设定的电压值。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【STM32CubeMX】位置式PID调节控制输出电压(超详解) 的相关文章

  • 在NLP上,CNN、RNN、MLP三者相比各有何优劣

    本文为知乎温颖就如下问题的回答 已授权CSDN转载 若想要实现某个具体的任务 如做关系抽取 实体识别 情感分类等 在不考虑实现的难度的情况下 如何从理论 经验 直觉上去选择最有希望的模型 前段时间做过用不同的神经网络模型做文本分类 情感分析
  • Linux(vi基本用法)

    在Linux下 可以键入vimtutor命令 有一个包含实操的vim教程 1 VI的三种命令模式 1 Command 命令 模式 用于输入命令 2 Insert 插入 模式 用于插入文本 3 Visual 可视 模式 用于视化的的高亮并选定

随机推荐

  • 报错:flask: TypeError: ‘function‘ object is not iterable

    错误 TypeError function object is not iterable Type错误 表示 函数 对象不是可迭代的 这是我在学习flask时在html模板中 进行for循环遍历闪现消息时缺少 导致遍历对象为一个函数 报错代
  • tomcat虚拟目录和虚拟主机等相关配置

    一 WEB 服务器 1 什么是WEB 服务器 就是一台电脑 安装了一个服务器软件 2 为什么需要安装 WEB 服务器 思考问题 从一台计算机的 IE 浏览器如何去访问另一台计算机中的文件 2 1 两台计算机是如何实现通讯的 IP地址 计算机
  • mesa 教程

    只有这个是靠谱的 Compiling and Installing The Mesa 3D Graphics Library latest documentation
  • yolov4训练自己的数据模型

    看了下yolov4的作者给的操作说明 链接如下 https github com AlexeyAB darknet how to compile on linux using make 有兴趣的可以去看看 总结起来 跟yolov3的操作方式
  • SpringCloud 商城系统搭建之Hystrix(基于Feign)

    前提 1 Feign在整合到Spring Cloud时已经自带了hystrix模块 所以pom xml中不需要额外引入feign依赖 2 本文是基于SpringCloud 商城系统搭建之eureka 一 基于Feign使用熔断器 按照下面步
  • H.264概述

    我的百科 我的贡献 草稿箱 百度首页 登录 新闻 网页 贴吧 知道 MP3 图片 视频 百科 帮助设置 添加到搜藏 返回百度百科首页 编辑词条 H 264
  • STM32控制L298n(从零开始)

    一 L298N模块简介 L298N是一款驱动模块 单片机通过向IN1 IN2 IN3 IN4输入PWM波从而控制OUT1 OUT2 ENA与ENB为使能引脚 使能引脚两根排针一定要短接 12v为模块供电 5v为单片机供电 二 L298N的逻
  • 什么是CentOS

    什么是CentOS CentOS是Community ENTerprise Operating System的简称 我们有很多人叫它社区企业操作系统 不管你怎么叫它 它都是linux的一个发行版本 CentOS并不是全新的linux发行版
  • MySQL密码忘记了怎么办?

    MySQL密码忘记了怎么办 本文就介绍了如何用canvas案例画出哆啦A梦的基础内容 提示 以下是本篇文章正文内容 下面案例可供参考 一 1 打开cmd命令符 先关闭正在运行的数据库 输入如下命令 二 打开mysql exe和mysqld
  • VUE的核心特性:响应式

  • 【Pytorch Lighting】第 6 章:深度生成模型

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • openEuler和linux什么关系,华为openEuler和鸿蒙(HarmonyOS)不是同一个操作系统

    华为推出了新操作系统 定名为openEuler 当前已提供20 03版本下载 有人不解的问 它跟鸿蒙 HarmonyOS 是不是同一个操作系统 或者有什么关系 华为openEuler和鸿蒙 HarmonyOS 100 不是同一个操作系统 并
  • string类型数组java_Java string类和数组的相关函数总结

    一 string类 1 字符串查找 1 str indexOf substr 返回substr首次在str里出现的索引 str 任意字符串对象 substr 要搜索的字符串 2 str lastIndexOf substr 返回substr
  • 洛谷P1011 [NOIP1998 提高组] 车站题解

    斐波那契数列 题目描述 火车从始发站 称为第1站 开出 在始发站上车的人数为a 然后到达第2站 在第2站有人上 下车 但上 下车的人数相同 因此在第2站开出时 即在到达第3站之前 车上的人数保持为a人 从第3站起 包括第3站 上 下车的人数
  • 拒绝摆烂!C语言练习打卡第四天

    博客主页 小王又困了 系列专栏 每日一练 人之为学 不日近则日退 感谢大家点赞 收藏 评论 目录 一 选择题 1 第一题 2 第二题 3 第三题 二 编程题 1 第一题 2 第二题 前言 在前面我们学习完C语言的所以知识 当然练习巩固也不能
  • 万维网(www)

    万维网 www 是互联网中使用最广泛的一种应用 是一个超大规模线上信息储藏所 以链接的形式为用户提供信息检索服务 万维网的核心作用 使得信息在网上自由传输 万维网提供分布式的信息检索服务 箭头代表以链接的形式跳转到其他页面 这种方式使得一个
  • 【Maven】单元测试、统计、覆盖率相关插件使用介绍

    maven surefire plugin maven surefire plugin是maven执行单元测试的插件 不显性配置也可以直接使用 这个插件的surefire test命令会默认绑定maven执行的test阶段 执行结束后 默认
  • Mysql数据库的环境搭建【详细】

    作者简介 大学机械本科 野生程序猿 学过C语言 玩过前端 还鼓捣过嵌入式 设计也会一点点 不过如今痴迷于网络爬虫 因此现深耕Python 数据库 seienium JS逆向 安卓逆向等等 目前为全职爬虫工程师 学习的过程喜欢记录 目前已经写
  • ASM插桩:学完ASM Tree api,再也不用怕hook了

    背景 对于ASM插桩来说 可能很多人都不陌生了 但是大多数可能都停留在core api上 对于现在市面上的一些插桩库 其实很多都用tree api进行编写了 因为tree api的简单与明了的特性 也越来越成为许多开源库的选择 ASM有两套
  • 【STM32CubeMX】位置式PID调节控制输出电压(超详解)

    本文将借助STM32CubeMX来配置ADC DMA DAC USART 并利用PID位置式算法实现对输出电压进行AD采集通过PID算法调节DAC 获取到我们想要的电压值 讲解的主要知识 何为PID以及为何需要PID STM32CubeMX