STM32CubeMX实战教学(1):基于STM32的PID温控系统设计(直流)

这篇具有很好参考价值的文章主要介绍了STM32CubeMX实战教学(1):基于STM32的PID温控系统设计(直流)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        在工业生产和科学实验中,温度常常是一个关键的因素,这时就要用到温控系统,在本文中将会基于STM32设计一个温控系统

        Github:SuiXinSc/STM32 (github.com)

        程序放在Q_qun:659512171

目录

一,基础知识:

二,程序设计:

三,STM32CubeMX配置:

四,Keil编程:

1,测试:

(1)串口:

(2)ADC,PWM: 

2,实际工程: 

(1)电路设计:

(2)温度曲线拟合:

(3)PID控温:

(4)人机交互: 

五,效果:


一,基础知识:

        因为是温控系统,所以需要用一个温敏电阻(或热电偶)来检测实时温度(或者温度传感器,精度更高),而温敏电阻和热电偶都需要一个ADC来检测电压值计算温度,我在前面的一篇文章中讲过ADC+DMA读取电压         传送门

        PID简介: PID,就是“比例(proportional)、积分(integral)、微分(derivative)”,是一种很常见的控制算法,目的是让被控制的量保持稳定。P,I,D是三种不同的调节作用,可以分开用(P,I,D)也可以组合使用(PI,PD,PID)

        P:P像一个弹簧,当目标与现有的差距越大时,P的力度就越大,就可以使现有值更快相目标值靠近;如果差距不大,P的力度也就较小,使现有值缓慢的向目标值逼近。P的系数KP越大,调节速度越快,但是越不容易稳住。有了P的作用,会使实际值在目标值附近抖动

        D:D就像刹车,使被控制的物理量不再抖动,D的系数KD越大,物理量的波动越稳,但是调节速度越慢

        似乎只需要PD两个就可以实现控制了,那么I 是干什么的?

        I:I 的作用是修正误差,举个例子,当烧水时外界很冷,热水热量散逸速度等于P的加热速度,温度就上不去了,D又寻思着温度没啥变化,它也不用干活,温度就一直上不去,这时就需要I 这个值来修正了。I 是一个积分量,只要误差存在,就会不断积分,最后反映在修正力度上。I的系数KI越大,积分修正效果越明显。

        所以可以得出,P、I、D分别对应的是“现在,过去,未来”,PID算法结合了这三者,实现精准的调控,常听到的PID调参调的其实就是P、I、D的系数,使得更加精确

        另外,还需要明白如何实现温控,既然是温控,就需要有加热器(有时候还需要冷却器),要想实现高精度控制就需要控制功率,这里根据电源类型又可以分为两种:直流和交流

        直流:直流调功比较简单,使用PWM脉宽调制再加一个驱动电路(三极管)即可,如果想要得到电压调节(即直流调压)的效果,只需在后面串接一个电感。但是有一点要注意,直流控制功率不能使用可控硅,因为可控硅有一个保持电流,只要流过的电流不低于这个值就不会断开(类似于自锁开关)。

        交流:交流调功相对而言就比较复杂了,通常而言,交流控制电路需要一个过零检测来提供过零信号,并且常常使用双向可控硅,根据控制方式又可将其分为两类:相位控制和零位控制。

           相位控制:使用相位控制的可控硅电力控制器叫做调压器通过改变每个正弦波正半波和负半波的导通角来控制电压的大小,进而调节输出电压和功率大小。它的优点是控制精度高,输出时电表不会抖动,但缺点是当负载容量较大时,会产生谐波污染电网。适用于定阻抗负载,变阻抗负载,感性负载,灯管等。

            零位控制:也叫周波控制,使用零位控制的可控硅电力控制器叫做调功器,其原理是将交流电分为多个周期(比如每1800°为一个周期),在一个周期内负载与电源接通几个周波再断开几个周波,通过控制接通周波与断开周波之比控制功率。应用简单且不会产生谐波干扰,但是控制精度有所降低,输出时电表会抖动。多用于电热丝等定阻抗负载。

        在这一篇里只做直流调功,以后会专门出一篇讲解交流控制。

        当然,既然是温控,肯定少不了执行器,这里使用PWM脉宽调制,也就是调节PWM信号的占空比来调节功率,如何调节PWM占空比和频率在之前的博文里讲过        传送门

二,程序设计:

        设计思路如下:使用ADC模块读取温敏电阻输出的电压值,计算出温度,然后使用PID算法计算PWM占空比。

三,STM32CubeMX配置:

        打开STM32CubeMX,选择MCU,新建工程,配置RCC和调试

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

         开启ADC和PWM,配置ADC的DMA

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

PWM里面的几个值我在之前的博文里都讲过,这里不再重复        传送门 

        为了方便调试,这里把串口打开

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

        配置时钟树

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

        配置工程 

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

 然后点击右上角的GENERATE CODE生成文件,点击Open Project打开工程。

四,Keil编程:

1,测试:

(1)串口:

        打开工程,先编译一次,没有报错,打开usart.c,编写串口重定向stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

/* USER CODE BEGIN 1 */
//发送的重定向,重定向以后可以使用printf等函数
int fputc(int ch, FILE *f)
{
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
    return ch;
}
 
//接收的重定向,重定向以后可以使用scanf等函数
int fgetc(FILE *f)
{		
	int ch;
	HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 1000);	
	return (ch);
}
/* USER CODE END 1 */

如果使用printf函数需要使用微库(Micro LIB),可在魔术棒里打开

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

(2)ADC,PWM: 

        然后再打开main.c,编写测试程序

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机


  /* USER CODE BEGIN 2 */
  uint32_t adc = 0;
  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
  HAL_ADC_Start_DMA(&hadc1,&adc,1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    HAL_ADC_Start_DMA(&hadc1,&adc,1);
    printf("%d\r\n",adc);
    HAL_Delay(500);
  }
  /* USER CODE END 3 */

然后编译,下载,连接好串口调试助手,观察现象

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

可以看到,ADC已经正常读取了(这时还没有接入温敏电阻) ,然后更改程序,测试PWM脉宽调制stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

  /* USER CODE BEGIN 2 */
  uint32_t adc = 0;
  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
  HAL_ADC_Start_DMA(&hadc1,&adc,1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    HAL_ADC_Start_DMA(&hadc1,&adc,1);
    printf("%d\r\n",adc);
    __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,adc/41);
    HAL_Delay(500);
  }
  /* USER CODE END 3 */

 在PA0上接一个LED,改变PA1的电压,可以看到LED的亮度跟随电压的变化而变化,这里将adc的值除以41是因为adc的最大值为4095,但由于我们设置的PWM自动重装值为100,当脉冲长度设为100时,已经是100%占空比了,所以需要除以一个41

2,实际工程: 

(1)电路设计:

测试结束,接下来需要先将外围电路设计好

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

这里面R1是温敏电阻的分压电阻,当Rt的阻值改变时,PA1的电压也会改变,R1根据使用的温敏电阻参数选择, 一般选取与温敏电阻常温阻值接近的电阻(当时选错了电阻,用的是100k的温敏电阻和47k的定值电阻)

(2)温度曲线拟合:

        温敏电阻的阻值变化不是线性的,其电阻与温度的关系可近似于二次函数的一部分,所以需要先连接好电路,使用测试程序测得在不同温度下的ADC值(一定要有两个近似于极端值的值,不然拟合出来的结果使用时可能会出错),列表记录多组数据(不少于3组),然后找一个网站拟合曲线得到函数解析式(以ADC值为x,温度为F(x) ),以后会出一篇文章讲讲最小二乘拟合函数

        使用这种方法不需要将ADC变换为阻值再对照出温度,直接用ADC的值就可以计算出温度

         计算出解析式后,放到程序中,测试输出

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机 可以看到,拟合精度还是比较高的

(3)PID控温:

        创建两个文件,control.c 和control.h 用于编写控制函数(不创建在main.c中写也可以,取决于个人喜好),编写PID控制程序

control.c:

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

#include "control.h"
#include "tim.h"

#define KP 3.0           // 比例系数
#define KI 0.1           // 积分系数
#define KD 0.03          // 微分系数
 
double PWM = 0.0;        //控制信号

double integral = 0.0;   // 积分项,历史误差
double derivative = 0.0; // 微分项,变化趋势

double Error = 0.0;      //当前误差
double LastError = 0.0;  //上次误差

void PID_Control(double Now,double Set){
  /*PID算法*/
  Error = Set - Now;
  integral += Error;
  derivative = Error - LastError;
  PWM = KP * Error + KI * integral + KD * derivative;// 
  LastError = Error;
  /*约束占空比的值*/
  if(PWM > 100){
    PWM = 100;
  }else if(PWM < 0){
    PWM = 0;
  }
  /*更新占空比*/
  __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,PWM);
}

 control.h:

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

#ifndef __CONTROL_H_
#define __CONTROL_H_

#include "main.h"
#include "math.h"

void PID_Control(double Now,double Set);

#endif

 然后在主程序中包括 control.h,应用PID_Control函数

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "control.h"
/* USER CODE END Includes */
  /* USER CODE BEGIN 2 */
  uint32_t adc = 0;
  int temp;
  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
  HAL_ADC_Start_DMA(&hadc1,&adc,1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    HAL_ADC_Start_DMA(&hadc1,&adc,1);
    temp = 0.0000031352*adc*adc+0.000414*adc+8.715;
    printf("%d\r\n",temp);
    PID_Control(temp,20);
    HAL_Delay(500);
  }
  /* USER CODE END 3 */

连接好外围电路,编译,下载,运行,可以发现温度已经稳定到设定温度了,下一步就是写一个程序来更改设定温度(也就是人机交互),这里直接在Keil中定义几个GPIO,使用按键更改,通过串口返回当前设定值

(4)人机交互: 

gpio.c:

void MX_GPIO_Init(void)
{
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  
  GPIO_InitTypeDef GPIO_Initstruct;
  
  GPIO_Initstruct.Pin = GPIO_PIN_12|GPIO_PIN_13;
  GPIO_Initstruct.Mode = GPIO_MODE_INPUT;
  GPIO_Initstruct.Pull = GPIO_PULLUP;
  GPIO_Initstruct.Speed = GPIO_SPEED_LOW;
  
  HAL_GPIO_Init(GPIOB,&GPIO_Initstruct);
}

main.c:

  /* USER CODE BEGIN 2 */
  uint32_t adc = 0;
  double set_temp,temp;
  HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
  HAL_ADC_Start_DMA(&hadc1,&adc,1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    /*查询按键是否按下*/
    if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12) == 0){
      HAL_Delay(10);
      if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12) == 0){
        set_temp += 1;
        while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12) == 0);
      }
    }else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13) == 0){
      HAL_Delay(10);
      if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13) == 0){
        set_temp -= 1;
        while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13) == 0);
      }
    }
    /*约束温度设定值*/
    if(set_temp > 50){
      set_temp = 50;
    }else if(set_temp < 0){
      set_temp = 0;
    }
    /*读取ADC,串口返回数据,PID控制*/
    HAL_ADC_Start_DMA(&hadc1,&adc,1);
    temp = 0.0000031352*adc*adc+0.000414*adc+8.715;
    printf("Set temputer: %d\r\n",(int)set_temp);
    printf("Now temputer: %d\r\n",(int)temp);
    printf("\r");
    PID_Control(temp,set_temp);
    HAL_Delay(80);
  }
  /* USER CODE END 3 */

五,效果:

stm32 pid温控电路,STM32,# STM32CubeMX开发,# STM32实战,stm32,嵌入式硬件,单片机

都看到这里了点点关注和赞再走吧

交流Q_qun:659512171文章来源地址https://www.toymoban.com/news/detail-815245.html

到了这里,关于STM32CubeMX实战教学(1):基于STM32的PID温控系统设计(直流)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32CubeMX 直流电机串级PID位置速度控制、HAL库、cubemx、PID、串级PID、位置控制、速度控制、双环控制

    提示:本文章的串级PID位置速度控制,是在前两篇文章速度控制,位置控制的基础上实现的,这一章节中不需要额外的cubemx的配置,只需要写简单的代码即可,复杂的地方在于串级pid的调试过程。 pid是我们在学习单片机中首先要学会的控制算法,而串级pid又是在单pid的基础上

    2024年02月14日
    浏览(51)
  • [CubeMX项目]基于STM32的平衡小车(硬件设计)

    一直以来我都想在本科毕业前完成一个电机相关的实验,之前看了网上比较火热的自平衡莱洛三角形项目后,决心先做一个类似的小项目。因此,我通过学习大量前辈的项目案例,完成了该项目。 本项目的特点是:在需要通信的部分,全部采用STM32自带的硬件接口,使用自己

    2024年02月03日
    浏览(44)
  • 搭建STM32F407的Freertos系统(基于STM32CubeMX)

           本人长期开发Linux、Windows上应用软件,一直以来MCU开发有所接触,但较少(最近项目需要,小公司么,都得会,被逼的),好在有STM32CubeMX这样工具,貌似就是我想要的工具。         本次demo目标立下:         1. 搭建或移植FreeRTOS到STM32上,毕竟对于长期在Linux环境

    2024年02月10日
    浏览(61)
  • STM32基于HAL库和STM32CubeMX的实时操作系统FreeRtOS开发

    1、FreeRTOS RTOS是一类操作系统,µC/OS,FreeRTOS,RTX,RT-Thread 等这些都是RTOS 类的操作系统 FreeRTOS 是众多RTOS 类操作系统中的一种,FreeRTOS 十分的小巧,可以在资源有限的微控制器中运行,FreeRTOS 也不仅仅局限于在微控制器中使用。就单从文件数量上来看FreeRTOS 要比µC/OS 少得多

    2024年02月21日
    浏览(60)
  • stm32毕设 stm32 wifi远程温控风扇系统

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月19日
    浏览(49)
  • STM32学习-基于STM32F1具有控制菜单的温控小风扇

    本文仅作个人学习记录,非教程,内容不完整,仅供参考,请勿用于商业用途。 使用ADC读取环境温度,根据环境温度设置PWM占空比,从而控制FAN转速。控制菜单功能:1.设置特定转速,2.切换为手动模式任意控制FAN转速。 整个系统并不复杂:MCU负责运行代码并输出信号;NTC是

    2024年02月06日
    浏览(239)
  • 单相逆变电路实战!(基于STM32F103C8T6的单相逆变电路,PID控制输出额定电压)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 我建了一个群,分享我个人做项目的经历和资源,纯个人爱好,一切免费,看自己空闲时间答疑,有想法的可以加QQ群280730348 本篇文章是对单相逆变电路进行实战演练的一次项目,主要实现功能为: 直

    2023年04月08日
    浏览(71)
  • PID温控实验平台搭建(四)——PID温控系统实验代码讲解

    (一)PID基础知识介绍 (二)PID进阶知识介绍及源码分享 (三)从零开始搭建STM32温控实验平台 (四)PID温控系统代码讲解 (五)最终实验现象与总结 文章目录 前言 一、主程序功能描述 二、部分代码讲解 1、PID程序 2、PWM输出 3、DS18B20传感器代码 4、OLED显示 总结 最近,我

    2023年04月17日
    浏览(35)
  • 单片机毕业设计 stm32智能温控风扇设计与实现 - 嵌入式 物联网

    Hi,大家好,学长今天向大家介绍一个 单片机项目 基于stm32的智能温控风扇设计与实现 大家可用于 课程设计 或 毕业设计 随着科技的日新月异,智能家居逐渐走入普通家庭,风扇作为基本的家用电器也将成为智能家居的一部分。这里介绍的是以STM32单片机为控制单元并结合嵌

    2024年02月09日
    浏览(90)
  • 单片机毕设 stm32 wifi远程温控风扇系统

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月19日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包