控制方法的c语言实现

版权所有:王帅严谨任何盗版或出于商业目的的恶意传播正常转载请注明版权第一章数学模型被控系统的数学模型是描述系统内在物理量之间关系的数学表达式。

系统的数学模型体现了输入量、输出量之间的内在关系,将输入量与输出量通过物理关系连接起来。

认清被控系统的数学模型,是设计控制系统的基础。

从另外一层意义上讲,对于本领域被控对象数学模型认识的深入程度,直接决定了工程师在该领域所能取得的成就。

认识系统的数学模型是进行控制系统设计的基础。

1.1 时域与复域时域,是以时间做基本变量的范围,描述数学函数或物理信号对时间的关系。

时域是真实世界,是惟一实际存在的域。

我们的经历都是在时域中发展和验证的,我们习惯于事件按时间的先后顺序地发生。

而评估数字产品的性能时,通常在时域中进行分析,因为产品的性能最终就是在时域中测量的。

正是因为时序是真实世界的反映,在用编程语言描述系统模型或控制系统时,首先需要分析出系统的时域模型。

复域,是指时域的微分方程通过拉普拉斯变坏得到的变量在复数范围内的域。

得到复域数学模型(传递函数)的目的在于分析系统的稳定性,常用的分析方法包括根轨迹和频域分析法。

分析系统的稳定性是设计稳定系统的基础,读者务求深入了解。

图1-1所示为系统分析设计的一般步骤。

实际系统是真实世界的客观存在,进行系统设计时,首先要根据实际系统,分析出系统的时域模型,然后通过拉普拉斯变换得到系统的传递函数,利用控制系统分析方法,分析系统的稳定性,并根据设计要求设计系统校正环节,然后将校正环节转换为时域系统,利用模拟量或者数字控制技术离散化各个环节,并实现基本的设计,然后根据实际系统控制状态完善控制方式,最终完成整个系统的设计。

以上便完成了整个控制系统的设计流程。

本书将分不同章节分别从模型、分析、设计、实现四个方面进行讲解,以期达到使读者融会贯通的目的。

本章是从模型的角度出发,分析并说明由实际系统向时域模型的抽象,并进一步生成传递函数的方法。

以下能容为本节需要的基本数学知识,如果读者对微分、积分、拉普拉斯变化、拉普拉斯反变换能够充分了解,本节可略去不看。

图1-1 控制系统设计环图1.2 基本数学工具1.2.1 微分方程与差分方程凡是表示未知函数、未知函数的导数与自变量之间关系的方程,都称之为微分方程。

微分方程用来描述实际系统被关注特性随时间演变的过程,它可以描述系统的动态过程。

微分方程进行离散化变形成了差分方程,而差分方程的时间上的连续发生便会形成微分方程。

为什么要建立微分方程与差分方程,因为人们对于变化非常关注,人们往往希望从目前已知的东西上加上合理的预测而得到未来的变化。

也就是说如果我们可以知道“变化值= 现在值– 过去值”,那么我们就希望能够得到“未来值=现在值+ 变化值”。

而微分方程的形式dm/dt与差分方程的形式(MN+1−MN)/(TN+1−TN)恰恰反映了系统的变化的特性。

下面示例1-1说明了系统微分方程的建立过程。

如图1-2所示,电路由电阻R、电感L、电容C组成,写出以U(t)为输入,U(t)为输出的微分方程。

LCU(t)U0(t)图1-2 示例1-1电路图基尔霍夫定律指出回路的电压和为0,那么我们可以知道u(t)=L didt +(1C)∫i(t)dt+Ri(t),其中我们又知道u0(t)=1c∫i(t)dt,消去中间变量即可得到电压输入输出的微分方程。

LC(d2u0(t))dt2+RC(du0(t))dt+u(t)=u(t)由公式不难看出,微分方程体现了给定电压u(t)与u(t)随时间t的变化关系,是系统的一种动态的体现。

对于控制系统而言,控制的过程是动态的过程,控制中所说的平衡也是一种动态的平衡,那么建立系统的动态模型就是完成控制系统设计的重要前提。

下面我们把上述微分方程转换为差分方程的形式。

首先需要明确,二次微分是对一次微分求微分,明白这点后,差分方程也就容易写出了。

LC ((u 0t (n +1)−u 0t (n ))/(t (n +1)−t (n ))−(u 0t (n )−u 0t (n −1))/(t (n )−t (n −1)))(t (n +1)−t (n ))+RC (u 0t (n +1)−u 0t (n ))(t (n +1)−t (n ))+u 0t (n +1)=ut (n +1)我们不难看出,差分方程能够将微分方程离散化,离散化的系统可以很容易用C 语言表示出来,从而容易用C 语言描述出相应的模型,进而为设计控制系统提供模型仿真依据。

所以说,微分方程转化为差分方程,最终实现系统的离散化,是理论设计向实际应用转化的必要步骤。

1.2.2 拉普拉斯变换与传递函数通过上一小节,我们可以知道,系统可以使用多阶微分的形式表示出来,但是问题在于,如果对系统进行分析,微分方程的求解相当麻烦,尤其对于复杂的系统而言,分析多阶微分方程是相当困难的,那么有没有一种方法,能够将复杂的微积分运算转化到简单的四则运算呢,拉普拉斯变换就是提供了这样一种方案,将时间域上的系统转化到复域上来,并在复域上进行分析设计,进行控制设计时,将复域控制系统通过拉普拉斯反变换的方式转化到时间域,进而可以离散化实现控制过程。

定义:时间函数f (t ),当t ⩾0使有定义,且广义积分∫0+∞f (t )e −st dt 在s 的某一区域内收敛,则由此积分确定的参数为s 的函数F (s )=∫0+∞f (t )e −st dt 叫做函数f (t )的拉普拉斯变换。

零初始条件下,系统输出量的拉普拉斯变换与输入量的拉普拉斯变化之比就称为线性定常系统的传递函数。

1.3 典型环节的微分方程、传递函数及C语言实现方法无论多么复杂的系统,总是可以由简单的子系统构成,分析典型环节的特点,其目的是为了通过典型环节的特点分析更为复杂的系统,实际工程应用中,真正完全通过理论的方式建立模型是非常困难的,实际的模型建立过程是一个复杂的过程,需要通过假设、验证、参数实验给定等多种手段分析完善模型内容,利用实验获取模型的方法又称作系统辨识技术,在下一节中将重点讲解。

假设的过程,其实就是根据系统特点,综合典型环节的过程。

将不同的环节通过四则运算给予不同的参数进行运算,从而接近真实的模型。

从这个角度上讲,透彻理解典型环节的特点,无论对于理论分析系统,还是对于实际建立系统模型都具有重要的意义。

这里的典型环节包括比例、积分、微分、惯性、震荡、滞后六个子环节。

下面进行单独讲解。

1.3.1 比例环节比例环节是自然界普遍存在的一个环节,几乎所有的系统必定存在比例环节。

比例环节的特点在于输入输出量成正比例关系,没有失真与延时。

其微分方程可表示为:c (t )=Kr (t )。

其传递函数可表示为:G (s )=C (s )R (s )=K 。

对于比例环节而言,C 语言实现相对比较简单。

下面进行C 语言实现过程的说明。

float ProElement (float K, float GiveValue ){float result;result = K*GiveValue;return result;以上代码用C 语言实现了比例环节的处理。

使用时直接定义一全局变量,例如float ResultValue; 然后直接调用该函数即可,例如 ResultValue = ProElement (0.1, 10);返回的ResultValue = 1.0。

1.3.2 惯性环节惯性环节是自然界普遍存在的另一个环节,其存在的广泛性不亚于比例环节,任何系统,只有时间精度足够高,都必然存在一定的惯性性能。

惯性环节的特点是对变化的输入量,输出量不能立刻复现,或多或少的存在一定的延时,在延时的时间内,输出量会逐渐接近输入的给定值。

其微分方程可表示为:T dc (t )(dt )+c (t )=r (t )。

其中T 为惯性时间常数,T 越大,惯性越大,当延时时间约为3-4倍的T 时,输出接近输入给定值。

其传递函数可表示为:G(s)=1Ts+1。

下面讲解用C语言实现惯性环节的过程。

这里注意系统的输出为c(t),输入为r(t)。

首先将微分方程转化为差分方程的形式:T c(t)−c(t−1)t−(t−1)+c(t)=r(t),化简该公式可表示为:c(t)=r(t)+Tc(t−1)T+1。

上述公式表明,当前时刻输出量c(t)与上一时刻输出量c(t-1)相关。

利用该原理,可使用C语言通过迭代函数实现。

首先定于全局变量,存放上一时刻输出量的值float ResultValueBack。

初值设定为0,然后可通过下面函数实现迭代过程。

float InertialElement(float T,float GiveValue){float result;result= (T*ResultValueBack+GiveValue)/(1+T);ResultValueBack=result;return result;1.3.3 积分环节积分环节是设计校正系统是常用的一个环节,经典的PID算法就分别用到了比例、积分、微分三个环节。

积分环节的显著特点是,输出量与输入量的积分成正比例关系,当输入量消失后,输出量具有记忆功能,能够储存部分能量。

其微分方程可表示为:c(t)=∫r(d)dt。

其传递函数可表示为:G(s)=1s。

对于离散系统而言,积分过程实质上是系统输入量的累加和,用C语言实现积分过程可表示为:定义全局变量ResultValuefloat IntegralElement(float GiveValue){float result;ResultValue=ResultValue+GiveValue;result=ResultValue;return result;1.3.4 震荡环节震荡环节相对而言较为复杂,日常所见系统中,震荡环节体现的相对也少一些,比如RC震荡电路,单摆等系统输入震荡系统,该系统的特点在于,系统中存在两个独立储能元件,并可以进行能量交换,从而形成震荡。

其微分方程表示为:T2d2c(t)dt2+2℘Tdc(t)dt+c(t)=r(t),其传递函数表示为:G(s)=1T2s2+2℘Ts+1。

其中T为时间常数,℘为阻尼系数。

上述公式表示成差分方程的形式为:T2[c(t)−2c(t−1)+c(t−2)]+2℘T[c(t)−c(t−1)]+c(t)=r(t),整理化简得到如下公式:c(t)=r(t)+(2T2+2℘T)c(t−1)−T2c(t−2)T2+2℘T+1,由上述公式可知输出量c(t)与输入量r(t),以及前两次的输出量存在关系。

类似惯性环节的C语言实现方式,我们使用迭代函数实现该环节。

定义全局float型变量ResultValueBackOne,ResultValueBackTwo。

合集下载

c语言开发逆变器控制算法

c语言开发逆变器控制算法

C语言开发逆变器控制算法1. 什么是逆变器控制算法逆变器是一种将直流电能转换为交流电能的设备,广泛应用于太阳能发电、风能发电等可再生能源领域。

逆变器控制算法是指在逆变器中运行的软件程序,用于实现对逆变器的控制和调节。

2. 逆变器控制算法的基本原理逆变器控制算法的基本原理是通过对输入直流电压进行采样和测量,根据预设的控制策略调节输出交流电压和频率,以实现对输出功率的精确控制。

具体来说,逆变器控制算法通常包括以下几个步骤:2.1 直流输入采样与测量首先,需要对输入直流电压进行采样和测量。

这可以通过使用模数转换器(ADC)将模拟信号转换为数字信号来实现。

采样频率和精度会影响到后续步骤中对电压值的准确度和稳定性。

2.2 控制策略选择与参数设置接下来,根据具体需求选择合适的控制策略,并设置相应的参数。

常见的控制策略包括恒功率控制、最大功率点跟踪(MPPT)控制等。

2.3 逆变器输出调节根据采样到的直流电压值和设定的控制策略,通过调整逆变器的输出电压和频率来实现对输出功率的精确调节。

这通常涉及到使用脉宽调制(PWM)技术来将直流电压转换为交流电压。

2.4 反馈与闭环控制为了保证逆变器输出的稳定性和可靠性,通常需要引入反馈机制和闭环控制。

通过对输出电压、频率等进行实时监测,并根据实际情况对控制算法进行调整,以实现更精确的控制。

3. C语言开发逆变器控制算法C语言是一种广泛应用于嵌入式系统开发的编程语言,也是开发逆变器控制算法常用的工具之一。

以下是一个简单示例代码,演示了如何使用C语言开发一个基本的逆变器控制算法:#include <stdio.h>// 定义输入直流电压float inputVoltage = 24.0;// 定义控制策略参数float targetPower = 1000.0;float outputVoltage = 220.0;float outputFrequency = 50.0;// 主函数int main() {// 逆变器控制算法实现float inputPower = inputVoltage * targetPower / outputVoltage;float modulationIndex = inputPower / (outputFrequency * outputVoltage);// 输出结果printf("Input Power: %.2f\n", inputPower);printf("Modulation Index: %.2f\n", modulationIndex);return 0;}在这个示例代码中,我们首先定义了输入直流电压、目标输出功率、输出电压和输出频率等参数。

PID的C语言实现

PID的C语言实现

位置式PID的C语言实现第一步:定义PID变量结构体,代码如下:struct _pid{float SetSpeed; //定义设定值float ActualSpeed; //定义实际值float err; //定义偏差值float err_last; //定义上一个偏差值float Kp,Ki,Kd; //定义比例、积分、微分系数float voltage; //定义电压值(控制执行器的变量)float integral; //定义积分值}pid;控制算法中所需要用到的参数在一个结构体中统一定义,方便后面的使用。

第二部:初始化变量,代码如下:void PID_init(){printf("PID_init begin \n");pid.SetSpeed=0.0;pid.ActualSpeed=0.0;pid.err=0.0;pid.err_last=0.0;pid.voltage=0.0;pid.integral=0.0;pid.Kp=0.2;pid.Ki=0.015;pid.Kd=0.2;printf("PID_init end \n");}统一初始化变量,尤其是Kp,Ki,Kd三个参数,调试过程当中,对于要求的控制效果,可以通过调节这三个量直接进行调节。

第三步:编写控制算法,代码如下:float PID_realize(float speed){pid.SetSpeed=speed;pid.err=pid.SetSpeed-pid.ActualSpeed;pid.integral+=pid.err;pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);pid.err_last=pid.err;pid.ActualSpeed=pid.voltage*1.0;return pid.ActualSpeed;}注意:这里用了最基本的算法实现形式,没有考虑死区问题,没有设定上下限,只是对公式的一种直接的实现,后面的介绍当中还会逐渐的对此改进。

C语言实现控制电机加减速正反转(飞思卡尔C代码)

C语言实现控制电机加减速正反转(飞思卡尔C代码)

C语言实现控制电机加减速正反转(飞思卡尔C代码)用单片机控制直流电动机的正反转、加减速的程序如何用C语言写参考一下这个例子吧。

#include#defineucharunignedchar#defineuintunignedintbitPW1=P2^0;bitPW2=P2^1;//控制电机的两个输入bitaccelerate=P2^2;//调速按键bittop=P2^3;//停止按键bitleft=P2^4;//左转按键bitright=P2^5;//右转按键#defineright_turnPW1=0;PW2=1//顺时针转动#defineleft_turnPW1=1;PW2=0//逆向转动#defineend_turnPW1=1;PW2=1//停转uintt0=25000,t1=25000;//初始时占空比为50%uinta=25000;//设置定时器装载初值25m设定频率为20Hzucharflag=1;//此标志用于选择不同的装载初值uchardflag;//左右转标志ucharcount;//用来标志速度档位voidkeycan();//键盘扫描voiddelay(ucharz);voidadjut_peed();//通过调整占空比来调整速度//某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某//voidmain(){keycan();//不断扫描键盘程序,以便及时作出相应的响应}}if(flag){flag=0;end_turn;a=t0;//t0的大小决定着低电平延续时间TH0=(65536-a)/256;TL0=(65536-a)%6;//重装载初值}ele{flag=1;//这个标志起到交替输出高低电平的作用if(dflag==0){right_turn;//右转}ele{left_turn;//左转}a=t1;//t1的大小决定着高电平延续时间TH0=(65536-a)/256;TL0=(65536-a)%6;//重装载初值}}TMOD=0某01;//工作方式寄存器软件起动定时器定时器功能方式1定时器0TH0=(65536-a)/256;TL0=(65536-a)%6;//装载初值ET0=1;//开启定时器中断使能EA=1;//开启总中断TR0=0;}//某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某//voiddelay(ucharz)//在12M下延时z毫秒{ uint某,y;for(某=z;某>0;某--)for(y=110;y>0;y--);}//某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某//voidkeycan(){if(top==0){TR0=0;//关闭定时器0即可停止转动end_turn;} if(left==0){TR0=1;dflag=1;//转向标志置位则左转}if(right==0){TR0=1;dflag=0;//转向标志复位则右转}if(accelerate==0){delay(5);//延时消抖if(accelerate==0){ while(accelerate==0);//等待松手count++;if(count==1){t0=20000;t1=30000;//占空比为百分之60}if(count==2){t0=15000;t1=35000;//占空比为百分之70}if(count==3){t0=10000;t1=40000;//占空比为百分之80}if(count==4){t0=5000;t1=45000;//占空比为百分之90}if(count==5){count=0;}}}}功能特点:1)总线速度高达40MHz,CAN总线:3个1Mbp的CAN总线,兼容CAN2.0A/B;2)128KB程序Flah和8KBDataFlah,用于实现程序和数据存储,均带有错误校正码(ECC);3)可配置A/D:16通道模数转换器;可选8位10位和12位精度,3μ的转换时间4)内嵌MSCAN模块用于CAN节点应用,内嵌支持LIN协议的增强型SIC模块和SPI模块;5)4通道16位计数器,CRG时钟和复位发生器:锁相环、看门狗、实时中断;增强型捕捉定时器;6)出色的低功耗特性,带有中断唤醒功能的10,实现唤醒休眠系统的功能;7)通道PWM:8位8通道或16位4通道PWM,易于实现电机控制。

c语言实现单片机控制步进电机加减速源程序

c语言实现单片机控制步进电机加减速源程序

C 语言实现单片机控制步进电机加减速源程序1. 引言在现代工业控制系统中,步进电机作为一种常见的执行元件,广泛应用于各种自动化设备中。

而作为一种常见的嵌入式软件开发语言,C 语言在单片机控制步进电机的加减速过程中具有重要的作用。

本文将从单片机控制步进电机的加减速原理入手,结合 C 语言的编程技巧,介绍如何实现单片机控制步进电机的加减速源程序。

2. 单片机控制步进电机的加减速原理步进电机是一种能够精确控制角度的电机,它通过控制每个步骤的脉冲数来实现旋转。

在单片机控制步进电机的加减速过程中,需要考虑步进电机的加速阶段、匀速阶段和减速阶段。

在加速阶段,需要逐渐增加脉冲的频率,使步进电机的转速逐渐增加;在匀速阶段,需要保持恒定的脉冲频率,使步进电机以匀速旋转;在减速阶段,需要逐渐减小脉冲的频率,使步进电机的转速逐渐减小。

这一过程需要通过单片机的定时器和输出控制来实现。

3. C 语言实现步进电机加减速的源程序在 C 语言中,可以通过操作单片机的 GPIO 来控制步进电机的旋转。

在编写源程序时,需要使用单片机的定时器模块来生成脉冲信号,以控制步进电机的旋转角度和速度。

以下是一个简单的 C 语言源程序,用于实现步进电机的加减速控制:```c#include <reg52.h>void main() {// 初始化定时器// 设置脉冲频率,控制步进电机的加减速过程// 控制步进电机的方向// 控制步进电机的启停}```4. 总结与回顾通过本文的介绍,我们了解了单片机控制步进电机的加减速原理和 C 语言实现步进电机加减速源程序的基本思路。

掌握这些知识之后,我们可以更灵活地应用在实际的嵌入式系统开发中。

在实际项目中,我们还可以根据具体的步进电机型号和控制要求,进一步优化 C 语言源程序,实现更加精准和稳定的步进电机控制。

希望本文能为读者在单片机控制步进电机方面的学习和应用提供一定的帮助。

5. 个人观点与理解在我看来,掌握 C 语言实现单片机控制步进电机加减速源程序的技术是非常重要的。

c语言电流环控制参数设置

c语言电流环控制参数设置

c语言电流环控制参数设置电流环控制是现代工业中常见的一种控制方式,它通过对电流进行监测和调节,实现对电流的精确控制。

在C语言中,我们可以通过设置一些参数来实现电流环控制的精确调节。

本文将介绍一些常见的电流环控制参数设置方法。

首先,我们需要了解一些基本的电流环控制参数。

在电流环控制中,最常见的参数是比例增益(Kp)、积分时间(Ti)和微分时间(Td)。

比例增益决定了控制器对电流误差的响应速度,积分时间决定了控制器对电流误差的积累程度,微分时间决定了控制器对电流误差变化率的响应程度。

这些参数的设置将直接影响到电流环控制的性能。

其次,我们需要根据具体的电流环控制系统来确定参数的合理取值范围。

不同的电流环控制系统具有不同的特性和要求,因此参数的设置也会有所不同。

一般来说,比例增益的取值范围为0到无穷大,积分时间的取值范围为0到无穷大,微分时间的取值范围为0到无穷大。

在实际应用中,我们可以根据系统的响应速度、稳定性和抗干扰能力等要求来确定参数的具体取值。

接下来,我们可以通过试验和调试来确定最佳的参数取值。

在实际应用中,我们可以通过改变参数的取值来观察系统的响应情况,并根据实际需求进行调整。

一般来说,我们可以先将比例增益设置为一个较小的值,然后逐渐增大,直到系统的响应速度满足要求。

然后,我们可以逐渐增大积分时间,直到系统的稳定性满足要求。

最后,我们可以逐渐增大微分时间,直到系统的抗干扰能力满足要求。

通过不断地试验和调试,我们可以找到最佳的参数取值,从而实现电流环控制的精确调节。

最后,我们需要注意一些常见的问题和注意事项。

在进行电流环控制参数设置时,我们需要注意系统的稳定性和抗干扰能力。

如果参数设置不当,可能会导致系统的不稳定或者对干扰信号过于敏感。

此外,我们还需要注意参数的单位和量纲。

在C语言中,我们需要将参数的单位和量纲进行统一,以确保计算的准确性。

总之,C语言电流环控制参数设置是实现电流精确调节的重要步骤。

温度控制的PID算法的C语言程序

温度控制的PID算法的C语言程序

我的题目是:基于PID算法的温度控制系统89C51单片机,通过键盘输入预设值,与DS18B20测得的实际值做比较,然后驱动制冷或加热电路。

用keil C语言来实现PID的控制。

最佳答案//PID算法温控C语言2008-08-17 18:58#include<reg51.h>#include<intrins.h>#include<math.h>#include<string.h>struct PID {unsigned int SetPoint; // 设定目标 Desired Valueunsigned int Proportion; // 比例常数 Proportional Constunsigned int Integral; // 积分常数 Integral Constunsigned int Derivative; // 微分常数 Derivative Constunsigned int LastError; // Error[-1]unsigned int PrevError; // Error[-2]unsigned int SumError; // Sums of Errors};struct PID spid; // PID Control Structureunsigned int rout; // PID Response (Output)unsigned int rin; // PID Feedback (Input)sbit data1=P1^0;sbit clk=P1^1;sbit plus=P2^0;sbit subs=P2^1;sbit stop=P2^2;sbit output=P3^4;sbit DQ=P3^3;unsigned char flag,flag_1=0;unsigned char high_time,low_time,count=0;//占空比调节参数unsigned char set_temper=35;unsigned char temper;unsigned char i;unsigned char j=0;unsigned int s;/*********************************************************** 延时子程序,延时时间以12M晶振为准,延时时间为30us×time***********************************************************/ void delay(unsigned char time){unsigned char m,n;for(n=0;n<time;n++)for(m=0;m<2;m++){}}/*********************************************************** 写一位数据子程序***********************************************************/ void write_bit(unsigned char bitval){EA=0;DQ=0; /*拉低DQ以开始一个写时序*/if(bitval==1){_nop_();DQ=1; /*如要写1,则将总线置高*/}delay(5); /*延时90us供DA18B20采样*/DQ=1; /*释放DQ总线*/_nop_();_nop_();EA=1;}/*********************************************************** 写一字节数据子程序***********************************************************/ void write_byte(unsigned char val){unsigned char i;unsigned char temp;EA=0; /*关中断*/TR0=0;for(i=0;i<8;i++) /*写一字节数据,一次写一位*/{temp=val>>i; /*移位操作,将本次要写的位移到最低位*/temp=temp&1;write_bit(temp); /*向总线写该位*/}delay(7); /*延时120us后*/// TR0=1;EA=1; /*开中断*/}/*********************************************************** 读一位数据子程序***********************************************************/ unsigned char read_bit(){unsigned char i,value_bit;EA=0;DQ=0; /*拉低DQ,开始读时序*/_nop_();_nop_();DQ=1; /*释放总线*/for(i=0;i<2;i++){}value_bit=DQ;EA=1;return(value_bit);}/*********************************************************** 读一字节数据子程序***********************************************************/ unsigned char read_byte(){unsigned char i,value=0;EA=0;for(i=0;i<8;i++){if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/ value|=0x01<<i;delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/}EA=1;return(value);}/***********************************************************复位子程序***********************************************************/ unsigned char reset(){unsigned char presence;EA=0;DQ=0; /*拉低DQ总线开始复位*/delay(30); /*保持低电平480us*/DQ=1; /*释放总线*/delay(3);presence=DQ; /*获取应答信号*/delay(28); /*延时以完成整个时序*/EA=1;return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/ }/***********************************************************获取温度子程序***********************************************************/void get_temper(){unsigned char i,j;do{i=reset(); /*复位*/}while(i!=0); /*1为无反馈信号*/ i=0xcc; /*发送设备定位命令*/ write_byte(i);i=0x44; /*发送开始转换命令*/ write_byte(i);delay(180); /*延时*/do{i=reset(); /*复位*/}while(i!=0);i=0xcc; /*设备定位*/write_byte(i);i=0xbe; /*读出缓冲区内容*/write_byte(i);j=read_byte();i=read_byte();i=(i<<4)&0x7f;s=(unsigned int)(j&0x0f);s=(s*100)/16;j=j>>4;temper=i|j; /*获取的温度放在temper中*/}/*================================================================= ===================================Initialize PID Structure=================================================================== ==================================*/void PIDInit (struct PID *pp){memset ( pp,0,sizeof(struct PID));}/*================================================================= ===================================PID计算部分=================================================================== ==================================*/unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ){unsigned int dError,Error;Error = pp->SetPoint - NextPoint; // 偏差pp->SumError += Error; // 积分dError = pp->LastError - pp->PrevError; // 当前微分pp->PrevError = pp->LastError;pp->LastError = Error;return (pp->Proportion * Error//比例+ pp->Integral * pp->SumError //积分项+ pp->Derivative * dError); // 微分项}/***********************************************************温度比较处理子程序***********************************************************/ compare_temper(){unsigned char i;if(set_temper>temper){if(set_temper-temper>1){high_time=100;low_time=0;}else{for(i=0;i<10;i++){ get_temper();rin = s; // Read Inputrout = PIDCalc ( &spid,rin ); // Perform PID Interation}if (high_time<=100)high_time=(unsigned char)(rout/800); elsehigh_time=100;low_time= (100-high_time);}}else if(set_temper<=temper){if(temper-set_temper>0){high_time=0;low_time=100;}else{for(i=0;i<10;i++){ get_temper();rin = s; // Read Inputrout = PIDCalc ( &spid,rin ); // Perform PID Interation }if (high_time<100)high_time=(unsigned char)(rout/10000);elsehigh_time=0;low_time= (100-high_time);}}// else// {}}/***************************************************** T0中断服务子程序,用于控制电平的翻转 ,40us*100=4ms周期******************************************************/ void serve_T0() interrupt 1 using 1{if(++count<=(high_time))output=1;else if(count<=100){output=0;}elsecount=0;TH0=0x2f;TL0=0xe0;}/***************************************************** 串行口中断服务程序,用于上位机通讯******************************************************/void serve_sio() interrupt 4 using 2 {/* EA=0;RI=0;i=SBUF;if(i==2){while(RI==0){}RI=0;set_temper=SBUF;SBUF=0x02;while(TI==0){}TI=0;}else if(i==3){TI=0;SBUF=temper;while(TI==0){}TI=0;}EA=1; */}void disp_1(unsigned char disp_num1[6]) {unsigned char n,a,m;for(n=0;n<6;n++){// k=disp_num1[n];for(a=0;a<8;a++){clk=0;m=(disp_num1[n]&1);disp_num1[n]=disp_num1[n]>>1;if(m==1)data1=1;elsedata1=0;_nop_();clk=1;_nop_();}}}/***************************************************** 显示子程序功能:将占空比温度转化为单个字符,显示占空比和测得到的温度******************************************************/ void display(){unsigned char codenumber[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};unsigned char disp_num[6];unsigned int k,k1;k=high_time;k=k%1000;k1=k/100;if(k1==0)disp_num[0]=0;elsedisp_num[0]=0x60;k=k%100;disp_num[1]=number[k/10];disp_num[2]=number[k%10];k=temper;k=k%100;disp_num[3]=number[k/10];disp_num[4]=number[k%10]+1;disp_num[5]=number[s/10];disp_1(disp_num);}/*********************************************************** 主程序***********************************************************/ main(){unsigned char z;unsigned char a,b,flag_2=1,count1=0;unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2};TMOD=0x21;TH0=0x2f;TL0=0x40;SCON=0x50;PCON=0x00;TH1=0xfd;TL1=0xfd;PS=1;EA=1;EX1=0;ET0=1;ES=1;TR0=1;TR1=1;high_time=50;low_time=50;PIDInit ( &spid ); // Initialize Structure spid.Proportion = 10; // Set PID Coefficients spid.Integral = 8;spid.Derivative =6;spid.SetPoint = 100; // Set PID Setpoint while(1){if(plus==0){EA=0;for(a=0;a<5;a++)for(b=0;b<102;b++){} if(plus==0){set_temper++;flag=0;}}else if(subs==0) {for(a=0;a<5;a++)for(b=0;a<102;b++){} if(subs==0){set_temper--;flag=0;}}else if(stop==0) {for(a=0;a<5;a++)for(b=0;b<102;b++){} if(stop==0){flag=0;break;}EA=1;}get_temper();b=temper;if(flag_2==1)a=b;if((abs(a-b))>5) temper=a;elsetemper=b;a=temper;flag_2=0;if(++count1>30) {display();count1=0;}compare_temper(); }TR0=0;z=1;while(1){EA=0;if(stop==0){for(a=0;a<5;a++)for(b=0;b<102;b++){} if(stop==0)disp_1(phil);// break;}EA=1;}}//DS18b20 子程序#include <REG52.H>sbit DQ=P2^1; //定义端口typedef unsigned char byte;typedef unsigned int word;//延时void delay(word useconds){for(;useconds>0;useconds--);}//复位byte ow_reset(void){byte presence;DQ=0; //DQ低电平delay(29); //480us DQ=1; //DQ高电平delay(3); //等待presence=DQ; //presence信号delay(25);return(presence);} //0允许,1禁止//从1-wire 总线上读取一个字节byte read_byte(viod){byte i;byte value=0;for (i=8;i>0;i--){value>>=1;DQ=0;DQ=1;delay(1);if(DQ)value|=0x80;delay(6);}return(value);}//向1-wire总线上写一个字节void write_byte(char val){byte i;for (i=8;i>0;i--) //一次写一个字节{DQ=0;DQ=val&0x01;delay(5);DQ=1;val=val/2;}delay(5);}//读取温度char Read_Temperature(void) {union{byte c[2];int x;}temp;ow_reset();write_byte(0xcc);write_byte(0xBE);temp.c[1]=read_byte(); temp.c[0]=read_byte();ow_reset();write_byte(0xCC);write_byte(0x44);return temp.x/2;}参考资料:你把这两个程序组合就可以了图1 模拟PID 控制系统原理图PID 控制器的控制规律可以描述为:(1)比例(P)控制能迅速反应误差,从而减小稳态误差。

C语言机器人控制机器人运动和传感器的控制

C语言机器人控制机器人运动和传感器的控制C语言是一种广泛应用于嵌入式系统和机器人控制方面的编程语言。

在机器人控制中,C语言被广泛使用来实现对机器人运动和传感器的控制。

本文将介绍C语言在机器人控制方面的应用和相关技术。

一、机器人运动控制1. 运动控制概述机器人的运动控制是指通过编程控制机器人执行各种动作和移动。

在C语言中,可以通过对机器人的关节进行控制来实现运动控制。

通过控制机器人的关节角度或速度,可以实现机器人的运动,如平移、旋转、抬臂等。

2. 控制机器人关节角度在C语言中,可以利用舵机或直流电机来控制机器人的关节角度。

通过设定合适的目标角度,可以控制机器人的位置和姿态。

下面是一个简单实例,介绍了如何使用C语言控制舵机的角度:```c#include <stdio.h>#include <stdlib.h>#include <wiringPi.h>#define PIN 18int main(){if (wiringPiSetupGpio() == -1){printf("wiringPi setup failed!\n"); return 1;}pinMode(PIN, PWM_OUTPUT); pwmSetMode(PWM_MODE_MS); pwmSetClock(192);pwmSetRange(2000);while (1){pwmWrite(PIN, 100);delay(1000);pwmWrite(PIN, 500);delay(1000);}return 0;}```上述代码通过使用wiringPi库来实现对GPIO的控制。

通过设定PWM的占空比,可以控制舵机的角度,从而实现机器人的运动控制。

3. 控制机器人关节速度除了控制机器人的关节角度,还可以控制关节的速度来实现运动控制。

在C语言中,可以使用PID控制算法来控制机器人关节的速度,从而实现平稳的机器人运动。

PID算法的C语言实现

PID算法的C语言实现PID(Proportional-Integral-Derivative)算法是一种常用的控制算法,被广泛应用于自动控制系统中。

它是通过计算系统当前的误差,来调整控制器的输出值,从而使得系统的输出与期望输出之间达到期望的关系。

以下是一个简单的PID算法的C语言实现示例:```c#include <stdio.h>//PID控制器参数float Kp = 1.0; // 比例系数float Ki = 0.5; // 积分系数float Kd = 0.2; // 微分系数//预设值float setpoint = 100.0;//PID控制器输出限制float outMin = 0.0;float outMax = 255.0;//PID控制器变量float integral = 0.0;float lastError = 0.0;//PID控制器计算函数//计算误差float error = setpoint - input;//计算比例项float proportional = Kp * error;//计算积分项integral += Ki * error;//计算微分项float derivative = Kd * (error - lastError);//保存上一次的误差lastError = error;//计算PID输出float output = proportional + integral + derivative; //限制输出值在指定范围内if (output > outMax)output = outMax;} else if (output < outMin)output = outMin;}return output;int maifloat processVariable = 0.0; // 进程变量,即被控制物理系统的输出值//模拟控制循环for (int i = 0; i < 100; i++)//获取控制器输出值//模拟物理系统processVariable += (output * 0.1);printf("Iteration: %d\tOutput: %.2f\tProcessVariable: %.2f\n", i, output, processVariable);}return 0;```上述代码中,首先定义了PID控制器的参数(比例系数Kp、积分系数Ki和微分系数Kd)、预设值(setpoint)以及PID控制器的输出限制(outMin和outMax)。

c语言定时控制代码

c语言定时控制代码
在C语言中,可以使用``库中的`sleep()`函数来暂停程序的执行一段时间。

下面是一个简单的示例代码,演示如何使用`sleep()`函数实现定时控制:
```c
include <>
include <>
int main() {
// 输出提示信息
printf("开始倒计时...\n");
// 倒计时10秒
for (int i = 10; i >= 0; i--) {
// 输出当前时间
printf("%d\n", i);
// 暂停1秒
sleep(1);
}
// 倒计时结束,输出提示信息
printf("倒计时结束!\n");
return 0;
}
```
在上面的代码中,我们使用了`sleep()`函数来实现每秒钟输出一次当前时间,并且每次输出后暂停1秒钟。

通过循环控制,实现了倒计时10秒的功能。

当倒计时结束后,程序会输出提示信息。

C语言飞行控制代码设计

C语言飞行控制代码设计一、引言飞行控制是飞机飞行过程中最核心的部分之一,其关系到飞行的稳定性和安全性。

而C语言是一种高效且广泛应用于嵌入式系统开发的编程语言。

本文将介绍基于C语言的飞行控制代码设计,着重讨论飞行控制的功能需求和代码设计方法。

二、功能需求1. 飞行模式选择飞行控制代码应该能够支持多种飞行模式的选择,例如手动模式、自动模式、自动驾驶模式等。

通过定义枚举类型或宏常量的方式,实现对不同飞行模式的控制和切换。

2. 姿态控制飞行控制代码需要实现对飞机的姿态进行控制。

姿态控制包括飞行器的横滚角、俯仰角和偏航角的控制。

可以使用PID控制算法或其他控制方法来实现姿态控制。

3. 高度控制飞行控制代码应该能够实现对飞机的高度进行控制。

高度控制包括飞行器的爬升率和目标飞行高度的控制。

可以使用高度保持控制方法或其他合适的算法来实现高度控制。

4. 航向控制飞行控制代码需要实现对飞机的航向进行控制。

航向控制包括对飞行器的飞行方向和航线进行控制。

可以使用航向保持控制方法或其他合适的算法来实现航向控制。

5. 自动导航飞行控制代码可以根据导航系统提供的导航信息,自动进行导航飞行。

当飞机工作在自动驾驶模式下时,飞行控制代码应该能够根据导航信息进行自动飞行、导航和着陆控制。

三、代码设计方法1. 模块化设计飞行控制代码应该按照功能需求进行模块化设计。

可以将不同的功能模块划分为不同的函数或文件,提高代码的复用性和可维护性。

例如,可以将姿态控制功能作为一个独立的函数,并在主程序中调用。

2. 数据结构设计为了方便管理和传递数据,飞行控制代码应该设计合适的数据结构。

可以使用结构体或类来表示飞行器的状态和控制参数。

通过定义全局变量或将数据结构作为函数参数传递,实现数据的共享与传递。

3. 状态机设计飞行控制代码可以使用状态机的思想进行设计。

通过定义不同的状态和状态转移条件,实现对不同飞行模式和控制状态的切换和控制。

状态机设计有助于代码的可读性和灵活性。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档