|
基于STM32温控系统的设计 5 C3 y# _; D) i: G2 l. ~
; v" b; h% S, i; U; p) u; e! J- ^3 |一、系统功能描述 利用STM32系列芯片,作为本温控系统的主控芯片。同过RS232通信协议实现下位机与计算机的通信,通过XTR105和PT100铂热电阻组合转化为稳定的模拟信号量,然后通过AD7705将模拟量转变为数字量输入主控芯片,这样主控芯片通过计算就可以得到当前温度的值。然后,主控芯片经过PID算法,计算出需要输出电流大小,写到MAX538芯片中,该芯片将数字量转化为模拟量输入XTR110,从而得到稳定的电流输出。
4 d8 c% f% ]9 W) S' X
/ |8 i h7 o2 i" |
1 p1 w% _$ b) P: v: v二、硬件电路设计 Q4 U" {8 ~1 W
1、硬件电路设计包括PT100铂电阻的信号调理电路、AD7705的使用、MAX538的使用、XTR110的使用。其中AD、DA的使用按照芯片说明书, 连接电路,并配置主控芯片即可。这里仅仅阐述测温的信号调理电路。 # J) q- B+ a9 G2 f
根据TI提供的芯片的使用信息,这里实际的测温范围为0-500度,计算出上述电路中的电阻。 2 P5 D% m1 j" L: Z6 o
2、USB转串口电路设计 8 G6 Y s1 Y4 J) L- ^) |; g9 ?
选用该芯片的好处:开发电路成熟,开发速度快,尤其是有配套驱动,基本不需在开发对应的驱动程序。
8 L8 a, }& l( E& k
' h5 g" |+ q! L! Y' @8 K. l三、软件层的设计
4 @+ C5 C H a0 Y! ?7 X# f1、 上位机软件开发 需求分析:上位机需要先设置串口通讯的基本参数,然后打开串口,设置温控的参数,设置完成后点击开始温控,最后接受下位机发出来的串口信息。 ' B1 z! @/ u Z X9 K
2、 下位机软件开发 需求分析:下位机需要完成与上位机的通讯,同时当开始温控时还要完成温控功能。下位机采用uC/OSII嵌入式实时操作系统,建立两个任务。
( K. X0 m$ d* d2 _7 ^" I1 B& o( q G串口通讯任务通过任务解析模块对上位机发出来的指令进行解析,启动温控任务。温控任务将测量出来的温度通过Message的方式把内部的数据发送给串口通讯任务。串口通讯任务在将这些任务发送给上位机。 任务解析模块需要处理的事件有,串口参数设置、温控任务启动、温控任务结束。 + ]* \- m' z# z5 t% c5 a
3、 PID温度控制算法 Kp可以说是PID算法中必不可少的一个量。没有它控制就不可能实现。它的作用是根据当前量与设定量的差值按照一定比例放大后得到控制量。 - //pid.h
( g( f; f% C4 c {/ J3 Q - #ifndef __PID__( P) ~) h* F# |9 f B# l
- #define __PID__
. b/ y' q5 X4 J1 g! Z - /*PID = Uk +KP*[E(k)-E(k-1)]+KI*E(k)+KD*[E(k)-2E(k-1)+E(k-2)];(增量型PID算式)
复制代码函数入口: RK(设定值),CK(实际值),KP,KI,KD 函数出口: U(K)*/ - typedef struct PIDValue- S4 B. I1 w4 ^' `: ?
- {
, ~+ E Y. b' @' R9 ~7 {! q - int8 KP;
: a: p" y: k1 R, \1 P - int8 KI;
" @8 g1 a/ d) X S% i( ]+ e8 | - int8 KD;
6 j' l1 E: U& P8 L2 } - int8 F;! L4 h$ r% b$ @1 Z% V3 t6 [+ d; _0 W
- int8 BITMOV;
5 p5 W9 W' d0 B0 y0 b - int EK[3];
& S6 f: w$ {# x- n - 0 s5 S2 h8 {- n3 ~) B8 n) e
- int UK;+ o6 X2 d. Y' L6 B+ F
- int RK;" {9 z3 \% G1 i Z6 u
- int CK;
2 c* ~+ _( H$ U% Y1 _ - int UK_REAL;& e9 }' A2 P3 Z& b
- - |( ]% P) w( }
- }pid_str;
8 ?0 A5 `+ j2 s9 x O - //PIDValueStr PID;$ ~' Q# |( j7 R/ t8 {* g" Z
- void pid_exe(pid_str*PID) ;4 Y; c* c; K4 C% d9 Q
- #endif
$ }5 ~: Z& T6 ~ - + [& J4 T3 F/ i
- //pid.c i i6 t% L2 o& X
- /*PID = PID->UK_REAL +PID->KP*[E(k)-E(k-1)]+PID->KI*E(k)+PID->KD*[E(k)-2E(k-1)+E(k-2)];(增量型PID算式)
- o" K7 K- b2 o+ G* M, X. ^2 T - 函数入口:PID->RK(设定值),PID->CK(实际值),PID->KP,PID->KI,PID->KD: k. ` B: k8 m1 V+ K$ f
- 函数出口: U(K)*/
. t# d3 z2 ^3 d$ d4 Q1 X' ^$ R - #include"defines.h"* M9 p) q- h& F7 t( U8 \, t
- #include"pid.h"
1 K L& w% J, f5 O [ - #define MAXOUT 0xff5 Y( H, m* k" Z4 o' Z- M; b0 H* J
- //#define MAXGAP 1009 H3 P- i) _+ F4 h
-
2 N# i, ~1 Z4 k# w - void pid_exe(pid_str*PID)' Z- _. C7 j5 X2 P3 U, ]% y
- {2 R& q8 w8 S- T2 |
- PID->EK[2]=PID->EK[1];, ^& V7 \0 H+ D: F$ u& l
- PID->EK[1]=PID->EK[0];
6 K) F2 M3 G" K: i4 @6 x - PID->EK[0]=PID->RK-PID->CK;
/ ~8 t. Y6 }8 X6 x0 B5 ~ - PID->UK_REAL=PID->UK_REAL- ~5 a3 e' h, G' f- f8 F
- +PID->KP*(PID->EK[0]-PID->EK[1])//微分一次后积分即原数2 t6 L) z! o* f* D% H
- +(float)PID->KI*PID->EK[0]/PID->F//直接积分
% m+ @6 \- e, }2 _4 V - +(float)PID->KD*(PID->EK[0]-2*PID->EK[1]+PID->EK[2])*PID->F;//二阶微分后积分即一阶微分6 m: l" v# u7 x( W1 s' p1 R
- if((PID->UK_REAL>>PID->BITMOV)>=MAXOUT)
; t- E* R+ D$ @+ c$ P7 |/ i: Z0 W) R - {
: B9 Q% P0 B% B- Q - PID->UK=MAXOUT;
* x8 E8 }' B' M' _$ I - }elseif(PID->UK_REAL>>PID->BITMOV<=-MAXOUT) _: h" ^$ h1 G( H. H' A
- {
1 m4 _7 w) W4 }$ Y. e - PID->UK=-MAXOUT;
: d- R- B9 l2 w+ q1 M8 r( ` - }else/ x/ w7 ?4 X: U; k
- {: P+ h/ k; _& \& ^
- PID->UK=PID->UK_REAL>>PID->BITMOV;4 P) a P( Y# h9 b. t7 E
- }
& T+ v* d8 M. ^ -
$ u+ k5 }/ W' P/ T$ x/ k - }
复制代码这里我写的代码用到的是增量型的PID(即UK_REAL +PID->KP*[E(k)-E(k-1)]+PID->KI*E(k)+PID->KD*[E(k)-2E(k-1)+E(k-2)];这句话所对应的是pid控制量在之前pid控制量的基础上增加的值,相当于求了一次导)。最终输出的结果将每一次运算的值累加输出就行了。
9 ~+ X7 k, z" u k* r |