Flappy Bird

Flappy Bird
Flappy Bird

#include

#include

#include

#include

#include

/********函数变量声明********/

#define PR_Box printf("■")

#define PR_Gold printf("★")

#define PR_Ag printf("☆")

#define PR_FBird printf("Ю")

#define PR_DBird printf("Ф")

#define PR_Land printf("┳┳┯")

#define PR_Bg_TL printf("╔")

#define PR_Bg_TR printf("╗")

#define PR_Bg_DL printf("╚")

#define PR_Bg_DR printf("╝")

#define PR_Bg_X printf("═")

#define PR_Bg_Y printf("║")

#define PR_Blank printf(" ");

int Grade = 1, C_Gold = 0, C_Ag = 0, Score = 0, Delay_time = 1000,Max_blank=9,Distance=18; //Grade 游戏等级

//Score 分数

//Max_blank 上下两个烟囱之间的最大距离

//Distance 左右两个烟囱之间的距离

struct Birds//小鸟的结构体

{

int x, y;//小鸟的位置

int condition;//此变量未用

};

Birds *Bird = (Birds*)malloc(sizeof(Birds));//给小鸟指针分配空间

struct Bg//烟囱的结构体--循环双向链表

{

int x, y;//上烟囱的左下角砖块的坐标

int l_blank;//上相两个烟囱之间的距离

int reward[9];

Bg *pri;//前指针-指向前一个结点

Bg *next;//后指针-指向后一个结点

};

Bg *Bg1 = new Bg[sizeof(Bg)];//将一个烟囱结点设置成全局变量

void Position(int x, int y)//将光标移动到X,Y坐标处

{

COORD pos = { x - 1, y - 1 };

HANDLE Out = GetStdHandle(STD_OUTPUT_HANDLE);

SetConsoleCursorPosition(Out, pos);

}

void CreatBird()//创建小鸟

{

Bird->x=41;//小鸟的坐标

Bird->y=10;

Bird->condition =0;

}

void CreatBg()//创建数据结构为循环双向链表的烟囱

{

Bg *Bg2 = (Bg*)malloc(sizeof(Bg));

Bg1->x=90;Bg1->y =8;

Bg2->x=Bg1->x+Distance;Bg2->y =9;

Bg1->l_blank =Max_blank-Grade;

Bg2->l_blank =Max_blank-Grade;

Bg1->next=Bg2;

Bg1->pri=Bg2;

Bg2->next=Bg1;

Bg2->pri=Bg1;

}

void InsertBg(Bg *p)//创建一个结点插入到传入结点之前。循环双向链表的插入{int temp;

Bg *Bgs = (Bg*)malloc(sizeof(Bg));

Bgs->x=p->pri->x+Distance;

Bgs->l_blank =Max_blank-Grade;

srand((int)time(0));//将系统时间作为产生随机数的种子

temp=rand();//产生随机数

if(temp%2==0)//当随机数%==2时,烟囱口向下移动

{ if((temp%4+p->pri->y+Max_blank-Grade)<21)//检测是否存在向下移动的可行性Bgs->y=p->pri->y+temp%4;//若有则向下移动temp%4个单位

else

Bgs->y=p->pri->y;//若无,则不动

}

else//反之亦然

{

if((p->pri->y-temp%4)>2)

Bgs->y=p->pri->y-temp%4;

else

Bgs->y=p->pri->y;

}

Bgs->pri=p->pri;//循环链表指向

Bgs->next =p;

p->pri->next=Bgs;

p->pri =Bgs;

}

void Check_Bg(Bg *q)//检查是否有烟囱超出屏幕,若有超出,则移动到屏幕右侧。{ Bg *p=q;int i=0,temp;

while(++i<=5)//注意烟囱只有5个,时来回循环移动的

{ if(p->x>-4)//若有烟囱超出

p=p->next;

else

{ srand((int)time(0));

temp=rand();

if(temp%2==0)//++

{ if((temp%4+p->y+Max_blank-Grade)<21)

p->y=p->y+temp%4;

else

p->y=p->y;

p->x=p->pri->x+Distance;//将烟囱移动到前一结点的右侧+Distance的单位

p->l_blank=Max_blank-Grade;//计算上下两个烟囱的距离

}

else//反之亦然

{

if((p->y-temp%4)>2)

p->y=p->y-temp%4;

else

p->y=p->y;

p->x=p->pri->x+Distance;

p->l_blank=Max_blank-Grade;

}

}

}

}

void Loop_Bg(Bg *q)//烟囱单向循环移动

{

Bg *p=q;int i=0;

while(++i<=5)

{p->x=p->x-1;

p=p->next ;

if(Bird->x==p->x)//每经过一个烟囱,加一分

{Score+=1;

if(Score%4==0&&Grade<4)//烟囱

Grade++;

}

}

}

void Prt_Bg(Bg *q)//画烟囱----较冗余的代码

{ Bg *p=q;int i=0,k,j;

while(++i<=5)

{ if(p->x>0&&p->x<=78)

{ for(k=2;ky;k++)//画出上烟囱上半部分

{ Position(p->x+1,k);

PR_Box;PR_Box;PR_Blank;//输出两个格子,输出空格,清除原来余影

}

Position(p->x,p->y);//画出上烟囱下半部分

PR_Box;PR_Box;PR_Box;PR_Blank;//输出三个格子,输出空格,清除原来余影Position(p->x,p->y+p->l_blank);//画出下烟囱上半部分

PR_Box;PR_Box;PR_Box;PR_Blank;//输出三个格子,输出空格,清除原来余影k=k+p->l_blank+1;

for(k;k<=22;k++)//画出下烟囱下半部分

{Position(p->x+1,k);

PR_Box;PR_Box;PR_Blank;//输出两个格子,输出空格,清除原来余影

}

Position(p->x,23);//输出地下的线

for(k=1;k

PR_Land;

}

p=p->next;

if(p->x==0)

{ for(j=2;jy;j++)

{ Position(p->x+1,j);

PR_Blank;PR_Blank;

}

Position(p->x+1,p->y);

PR_Blank;PR_Blank;PR_Blank;

Position(p->x+1,p->y+Max_blank-Grade);

PR_Blank;PR_Blank;PR_Blank;

j=j+Max_blank-Grade+1;

for(j;j<=22;j++)

{Position(p->x+1,j);

PR_Blank;PR_Blank;

}

}

}

}

void PrtBg()//画上下两条线

{ int i;

Position(1,1);PR_Bg_TL;

Position(79,1);PR_Bg_TR;

Position(1,24);PR_Bg_DL;

Position(79,24);PR_Bg_DR;

for(i=3;i<=78;i+=2)

{ Position(i,1);PR_Bg_X;

Position(i,24);PR_Bg_X;

}

/*for(i=2;i<=23;i++)

{ Position(1,i);PR_Bg_Y;printf("%d",i-1);

Position(79,i);PR_Bg_Y;

}*/

}

void PrtBird()//画鸟

{ Position(Bird->x,Bird->y-1);//清除原来屏幕上面的鸟

PR_Blank;

Position(Bird->x,Bird->y);//画新鸟

PR_FBird;

Position(38,2);

printf("Score:%d",Score);//输出得分

}

int CheckYN(Bg *q)//检查是否撞壁

{ Bg *p=q;int i=0;

while(++i<=5)

{ if(Bird->y>23)//鸟是否落地

return 0;

if(Bird->x==p->x&&Bird->y<=p->y)//是否撞到上烟囱左侧

return 0;

if((Bird->x==p->x||Bird->x==p->x+1||Bird->x==p->x+2)&&Bird->y==p->y)//是否撞到上烟囱下侧

return 0;

if(Bird->x==p->x&&Bird->y>p->y+p->l_blank)//是否撞到下烟囱左侧

return 0;

if((Bird->x==p->x||Bird->x==p->x+1||Bird->x==p->x+2)&&Bird->y==p->y+p->l_blank)//是否撞到上烟囱上侧

return 0;

p=p->next;

}

return 1;

}

void Prtfirst()

{

printf("══════════════════════════════════════\n");

printf(" ■■ ■■\n");

printf(" ■■ ■■\n");

printf(" ■■ ■■ C语言版Flappy Bird\n");

printf(" ■■ ■■ 瞎搞人:yyposs\n");

printf(" ■■ ■■ 瞎搞日期:2014.2\n");

printf(" ■■ ■■ 耗时:4小时\n");

printf(" ■■■ ■■ 游戏说明:\n");

printf(" ■■ 1-按上箭头使鸟起飞\n");

printf(" ■■ 2-等级越高,难度越大!\n");

printf(" Ю ■■■\n");

printf("\n");

printf(" ■■■ 欢迎各路大神与我探讨C、C++、VB、PHP、C#\n");

printf(" ■■\n");

printf(" ■■\n");

printf(" ■■ ■■■ 【无版权,随意修改】\n");

printf(" ■■ ■■\n");

printf(" ■■ Ф ■■\n");

printf(" ■■ ■■\n");

printf(" ■■ ■■\n");

printf(" ■■ ■■\n");

printf(" ■■ ■■\n");

printf(" ┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳\n"); system("pause");

Position(1,1);

int i=0;

while(i++<40*25)

PR_Blank;

}

void main()

{int i=0;char ch;

Prtfirst();//开始屏幕

PrtBg();//画上下两边的框框

CreatBg();//创建循环双向链表烟囱

InsertBg(Bg1);//给循环双向链表中插入一个烟囱结点

InsertBg(Bg1);//给循环双向链表中插入一个烟囱结点

InsertBg(Bg1);//给循环双向链表中插入一个烟囱结点

CreatBird();//创造小鸟

while(1)

{

if(!CheckYN(Bg1))//检查鸟是否碰壁

break;//若碰壁,则退出

Check_Bg(Bg1);//检查是否有烟囱X坐标<0

Prt_Bg(Bg1);//画背景烟囱

PrtBird();//画小鸟

Loop_Bg(Bg1);//背景烟囱单项循环

Bird->y=Bird->y+1;

if(GetAsyncKeyState(VK_UP))//检测是否有按键

{ Position(Bird->x,Bird->y-1);

PR_Blank;//在屏幕上清除原小鸟

Bird->y=Bird->y-4;//鸟的位置上升4个长度

}

while(i++<500);

{ Sleep(100);

}

i=0;

}

Position(38,10);

printf("You Lost!");

Position(1,25);

system("pause");

}

// 1 2 3 4 5 6 7 8 10 15 20 25 30 35 38

//══════════════════════════════════════

//1 ■■ ■■

//2 ■■ ■■

//3 ■■ ■■

//4 ■■ ■■

//5 ■■ ■■

//6 ■■ ■■

//7 ■■■ ■■

//8 ■■

//9 ■■

//10 Ю ■■■

//11

//12 ■■■

//13 ■■

//14 ■■

//15 ■■ ■■■

//16 ■■ ■■

//17 ■■ Ф ■■

//18 ■■ ■■

//19 ■■ ■■

//20 ■■ ■■

//21 ■■ ■■

//22┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳┳┯┳//══════════════════════════════════════

基于模糊控制的速度跟踪控制问题(C语言以及MATLAB仿真实现)

基于模糊控制的速度控制 ——地面智能移动车辆速度控制系统问题描述 利用模糊控制的方法解决速度跟踪问题,即已知期望速度(desire speed),控制油门(throttle output)和刹车(brake output)来跟踪该速度。已知输入:车速和发动机转速(值可观测)。欲控制刹车和油门电压(同一时刻只有一个量起作用)。 算法思想 模糊控制器是一语言控制器,使得操作人员易于使用自然语言进行人机对话。模糊控制器是一种容易控制、掌握的较理想的非线性控制器,具有较佳的适应性及强健性(Robustness)、较佳的容错性(Fault Tolerance)。利用控制法则来描述系统变量间的关系。不用数值而用语言式的模糊变量来描述系统,模糊控制器不必对被控制对象建立完整的数学模式。 Figure 1模糊控制器的结构图 模糊控制的优点: (1)模糊控制是一种基于规则的控制,它直接采用语言型控制规则,出发点是现场操作人员的控制经验或相关专家的知识,在设计中不需要建立被控对象的精确的数学模型,因而使得控制机理和策略易于接受与理解,设计简单,便于应用。 (2)由工业过程的定性认识出发,比较容易建立语言控制规则,因而模糊控制对那些数学模型难以获取,动态特性不易掌握或变化非常显著的对象非常适用。 (3)基于模型的控制算法及系统设计方法,由于出发点和性能指标的不同,容易导致较大差异;但一个系统语言控制规则却具有相对的独立性,利用这些控制规律间的模糊连接,容易找到折中的选择,使控制效果优于常规控制器。 (4)模糊控制是基于启发性的知识及语言决策规则设计的,这有利于模拟人工控制的过程和方法,增强控制系统的适应能力,使之具有一定的智能水平。 简化系统设计的复杂性,特别适用于非线性、时变、模型不完全的系统上。 模糊控制的缺点

PWM调速的C语言程序编写

PWM调速的C语言程序编写 关于PWM的原理在上一篇文章中已经说的很详细了,现在就细说一下pwm C语言程序的编写。 C语言中PWM的编写有这么几种方法;一、用普通的I/O口输出的PWM ,二、使用定时计数器编写,三、就是使用片内PWM了。 1 先说使用普通的I\O口编写PWM程序了。 使用I/O口输出PWM波形你必须首先明白PWM他的实质是:调制占空比,占空比就是波形中高电平的长度与整个波长的比值。我们写C语言的目的是写PWM波形的一个周期。在这个周期内高低电平的比值是可以改变的。这也就符合了PWM的原意脉宽调制。即高电平的宽度的调制。当然了PWM他也可用于改变频率,我们这里只先说他改变脉宽。 一旦我们的C语言程序写完那么他产生的PWM波形的频率就一定了。(也可写频率变化的PWM,难度有点大)一般我们控制使用1K到10K的PWM波进行控制。当然了你也可在要求不是很高的地方使用频率更低的PWM波。比如在飞思卡尔智能车比赛中我们学校使用的PWM波频率只有600HZ. 我们要改变一个PWM波周期内的高电平的宽度显然需要将一个PWM波的周期分成单片机可以控制的N个小的周期,N的

取值越大你的调速等级越高,但产生的PWM频率就越低。我们下面以实现100级调速为例编写PWM程序。 先写出程序再慢慢给大家分析 void pwm (uchar x,uint y) //X 为占空比 Y为函数使用时间 { uint i,j,a,b; for(i=y;i>0;i--) //定时外函数 { for(j=7;j>0;j--) //定时内函数 { for(a=y;a>0;a--) //PWM波高电平宽度 { PORTA=0X01; }

最新五种编程方式实现流水灯的单片机c程序讲课教案

五种编程方式实现流水灯的单片机C程序 //功能:采用顺序结构实现的流水灯控制程序 /*此方式中采用的是字操作(也称为总线操作)*/ #include void delay(unsigned char i); //延时函数声明 void main() //主函数 { while(1) { P1 = 0xfe; //点亮第1个发光二极管,0.000389s delay(200); //延时 P1 = 0xfd; //点亮第2个发光二极管,0.155403s,0.1558 delay(200); //延时 P1 = 0xfb; //点亮第3个发光二极管 delay(200); //延时 P1 = 0xf7; //点亮第4个发光二极管 delay(200); //延时 P1 = 0xef; //点亮第5个发光二极管 delay(200); //延时 P1 = 0xdf; //点亮第6个发光二极管 delay(200); //延时 P1 = 0xbf; //点亮第7个发光二极管 delay(200); //延时 P1 = 0x7f; //点亮第8个发光二极管 delay(200); //延时 } } //函数名:delay //函数功能:实现软件延时 //形式参数:unsigned char i; // i控制空循环的外循环次数,共循环i*255次 //返回值:无 void delay(unsigned char i) //延时函数,无符号字符型变量i为形式参数{ unsigned char j, k; //定义无符号字符型变量j和k for(k = 0; k < i; k++) //双重for循环语句实现软件延时 for(j = 0; j < 255; j++); } //功能:采用循环结构实现的流水灯控制程序 //此方式中采用的移位,按位取反等操作是位操作 #include //包含头文件REG51.H void delay(unsigned char i); //延时函数声明 void main() //主函数

PID控制算法的C语言实现完整版精编版

P I D控制算法的C语言 实现完整版 文件编码(008-TTIG-UTITD-GKBTT-PUUTI-WYTUI-8256)

P I D控制算法的C语言实现一P I D算法原理最近两天在考虑一般控制算法的C语言实现问题,发现网络上尚没有一套完整的比较体系的讲解。于是总结了几天,整理一套思路分享给大家。 在工业应用中PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法,如果能够熟练掌握PID算法的设计与实现过程,对于一般的研发人员来讲,应该是足够应对一般研发问题了,而难能可贵的是,在我所接触的控制算法当中,PID控制算法又是最简单,最能体现反馈思想的控制算法,可谓经典中的经典。经典的未必是复杂的,经典的东西常常是简单的,而且是最简单的,想想牛顿的力学三大定律吧,想想爱因斯坦的质能方程吧,何等的简单!简单的不是原始的,简单的也不是落后的,简单到了美的程度。先看看PID算法的一般形式: PID的流程简单到了不能再简单的程度,通过误差信号控制被控量,而控制器本身就是比例、积分、微分三个环节的加和。这里我们规定(在t 时刻): 1.输入量为rin(t); 2.输出量为rout(t); 3.偏差量为err(t)=rin(t)-rout(t); pid的控制规律为

理解一下这个公式,主要从下面几个问题着手,为了便于理解,把控制环境具体一下: 1.规定这个流程是用来为直流电机调速的; 2.输入量rin(t)为电机转速预定值; 3.输出量rout(t)为电机转速实际值; 4.执行器为直流电机; 5.传感器为光电码盘,假设码盘为10线; 6.直流电机采用PWM调速转速用单位转/min表示; 不难看出以下结论: 1.输入量rin(t)为电机转速预定值(转/min); 2. 输出量rout(t)为电机转速实际值(转/min); 3.偏差量为预定值和实际值之差(转/min); 那么以下几个问题需要弄清楚: 1.通过PID环节之后的U(t)是什么值呢 2.控制执行器(直流电机)转动转速应该为电压值(也就是PWM占空比)。

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

用单片机控制直流电动机的正反转、加减速的程序如何用C语言写 参考一下这个例子吧。 #include #define uchar unsigned char #define uint unsigned int sbit PW1=P2^0 ; sbit PW2=P2^1 ; //控制电机的两个输入 sbit accelerate=P2^2 ; //调速按键 sbit stop=P2^3 ; //停止按键 sbit left=P2^4 ; //左转按键 sbit right=P2^5 ; //右转按键 #define right_turn PW1=0;PW2=1 //顺时针转动 #define left_turn PW1=1;PW2=0 //逆向转动 #define end_turn PW1=1;PW2=1 //停转 uint t0=25000,t1=25000; //初始时占空比为50% uint a=25000; // 设置定时器装载初值 25ms 设定频率为20Hz uchar flag=1; //此标志用于选择不同的装载初值 uchardflag; //左右转标志 uchar count; //用来标志速度档位 void keyscan(); //键盘扫描 void delay(uchar z); void time_init(); //定时器的初始化 void adjust_speed(); //通过调整占空比来调整速度 //**********************************// void main() { time_init(); //定时器的初始化 while(1) { keyscan(); //不断扫描键盘程序,以便及时作出相应的响应 } }

PID控制算法的C语言实现

PID控制算法的C语言实现一PID算法原理 最近两天在考虑一般控制算法的C语言实现问题,发现网络上尚没有一套完整的比较体系的讲解。于是总结了几天,整理一套思路分享给大家。 在工业应用中PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法,如果能够熟练掌握PID算法的设计与实现过程,对于一般的研发人员来讲,应该是足够应对一般研发问题了,而难能可贵的是,在我所接触的控制算法当中,PID控制算法又是最简单,最能体现反馈思想的控制算法,可谓经典中的经典。经典的未必是复杂的,经典的东西常常是简单的,而且是最简单的,想想牛顿的力学三大定律吧,想想爱因斯坦的质能方程吧,何等的简单!简单的不是原始的,简单的也不是落后的,简单到了美的程度。先看看PID算法的一般形式: PID的流程简单到了不能再简单的程度,通过误差信号控制被控量,而控制器本身就是比例、积分、微分三个环节的加和。这里我们规定(在t时刻): 1.输入量为rin(t); 2.输出量为rout(t); 3.偏差量为err(t)=rin(t)-rout(t); pid的控制规律为

理解一下这个公式,主要从下面几个问题着手,为了便于理解,把控制环境具体一下: 1.规定这个流程是用来为直流电机调速的; 2.输入量rin(t)为电机转速预定值; 3.输出量rout(t)为电机转速实际值; 4.执行器为直流电机; 5.传感器为光电码盘,假设码盘为10线; 6.直流电机采用PWM调速转速用单位转/min表示; 不难看出以下结论: 1.输入量rin(t)为电机转速预定值(转/min); 2. 输出量rout(t)为电机转速实际值(转/min); 3.偏差量为预定值和实际值之差(转/min); 那么以下几个问题需要弄清楚: 1.通过PID环节之后的U(t)是什么值呢 2.控制执行器(直流电机)转动转速应该为电压值(也就是PWM占空比)。 3.那么U(t)与PWM之间存在怎样的联系呢

用C语言编写程序实现通过按键使LED灯周期闪烁

用C语言编写程序实现通过按键使LED灯周期闪烁(2010-02-24 21:12:44)标签: 循环闪烁周期led灯按键杂谈 一、设计题目 二、程序功能: 开机复位后,LED0到LED7全部点亮,所有LEDPort持续2S后熄灭,然后等待按键,按0键LED7以 0.8S周期闪烁,按1键LEDPort以1S周期闪烁。 三、总体设计思想 用中断方式实现定时器的定时,然后通过键盘中断程序实现通过对按键的操作来实现相应的周期闪烁。 在我编写的实验程序中我用到了定时器中断和外部中断。程序共分为两个模块,一个为定时器模块,一个为键盘中断程序模块,在主函数中,首先实现所有LEDPort点亮,然后通过中断方式实现定时2S,在定时器num==20时,设定全局变量为标志位flag=1,然后再主函数中设定条件,通过标志位的变化实现所有LEDPort持续2S后熄灭。然后进入循环,等待按键,在按键中断服务程序中使用switch语句实现通过改变num1的值来实现LED7的闪烁周期。设定标志位b=0,在主函数中使用if语句通过判断b的值来改变LED7的亮灭情况,同时相应的b值会取反。 四、程序具体实现 实验要求开机复位后,LED0到LED7全部点亮2S后熄灭。在主函数中使用LEDPort=0x00;这条语句实现所有灯都亮,使用中断方式实现定时器定时2S,因为实验要求20ms溢出,所以设定num=100,在定时器中断服务程序中使用if语句判断条件,当num加到100,也就是说2S时间到时,执行flag=1;语句(先设定全局变量flag=0)。然后在主函数中使用while语句规定只有在flag=0时才执行所有LEDPort点亮的操作。2S时间到后,所有灯熄灭。然后进入while循环,

PID控制算法的C语言实现 完整版

P I D控制算法的C语言实现完整版 集团标准化工作小组 [Q8QX9QT-X8QQB8Q8-NQ8QJ8-M8QMN]

PID控制算法的C语言实现一 PID算法原理 最近两天在考虑一般控制算法的C语言实现问题,发现网络上尚没有一套完整的比较体系的讲解。于是总结了几天,整理一套思路分享给大家。 在工业应用中PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法,如果能够熟练掌握PID算法的设计与实现过程,对于一般的研发人员来讲,应该是足够应对一般研发问题了,而难能可贵的是,在我所接触的控制算法当中,PID控制算法又是最简单,最能体现反馈思想的控制算法,可谓经典中的经典。经典的未必是复杂的,经典的东西常常是简单的,而且是最简单的,想想牛顿的力学三大定律吧,想想爱因斯坦的质能方程吧,何等的简单!简单的不是原始的,简单的也不是落后的,简单到了美的程度。先看看PID算法的一般形式: PID的流程简单到了不能再简单的程度,通过误差信号控制被控量,而控制器本身就是比例、积分、微分三个环节的加和。这里我们规定(在t时刻): 1.输入量为rin(t); 2.输出量为rout(t); 3.偏差量为err(t)=rin(t)-rout(t); pid的控制规律为 理解一下这个公式,主要从下面几个问题着手,为了便于理解,把控制环境具体一下:

1.规定这个流程是用来为直流电机调速的; 2.输入量rin(t)为电机转速预定值; 3.输出量rout(t)为电机转速实际值; 4.执行器为直流电机; 5.传感器为光电码盘,假设码盘为10线; 6.直流电机采用PWM调速转速用单位转/min表示; 不难看出以下结论: 1.输入量rin(t)为电机转速预定值(转/min); 2. 输出量rout(t)为电机转速实际值(转/min); 3.偏差量为预定值和实际值之差(转/min); 那么以下几个问题需要弄清楚: 1.通过PID环节之后的U(t)是什么值呢 2.控制执行器(直流电机)转动转速应该为电压值(也就是PWM占空比)。 3.那么U(t)与PWM之间存在怎样的联系呢 (见附录1)这篇文章上给出了一种方法,即,每个电压对应一个转速,电压和转速之间呈现线性关系。但是我考虑这种方法的前提是把直流电机的特性理解为线性了,而实际情况下,直流电机的特性绝对不是线性的,或者说在局部上是趋于线性的,这就是为什么说PID调速有个范围的问题。具体看一下(见附录2)这篇文章就可以了解了。所以在正式进行调速设计之前,需要现有开环系统,测试电机和转速之间的特性曲线(或者查阅电机的资料说明),然后再进行闭环参数整定。这篇先写到这,下一篇说明连续系统的离散化问题。并根据离散化后的特点讲述位置型PID和增量型PID的用法和C语言实现过程。

温度控制的PID算法 及C程序实现

温度控制与PID算法 温度控制与PID算法j较为复杂,下面结合实际浅显易懂的阐述一下PID控制理论,将温度控制及PID算法作一个简单的描述。 1.温度控制的框图 这是一个典型的闭环控制系统,用于控制加热温区的温度(PV)保持在恒定的温度设定值(SV)。系统通过温度采集单元反馈回来的实时温度信号(PV)获取偏差值(EV),偏差值经过PID调节器运算输出,控制发热管的发热功率,以克服偏差,促使偏差趋近于零。例如,当某一时刻炉内过PCB板较多,带走的热量较多时,即导致温区温度下降,这时,通过反馈的调节作用,将使温度迅速回升。其调节过程如下: 温度控制的功率输出采用脉宽调制的方法。固态继电器SSR的输出端为脉宽可调的电压U OUT 。当SSR的触发角触发时,电源电压U AN通过SSR的输出端加到发热管的两端;当SSR的触发角没有触发信号时,SSR关断。因此,发热管两端的平均电压为U d=(t/T)* U AN=K* U AN 其中K=t/T,为一个周期T中,SSR触发导通的比率,称为负载电压系数或是占空比,K 的变化率在0-1之间。一般是周期T固定不便,调节t, 当t在0-T的范围内变化时,发热管的电压即在0-U AN之间变化,这种调节方法称为定频调宽法。下面将要描述的PID 调节器的算式在这里的实质即是运算求出一个实时变化的,能够保证加热温区在外界干扰的情况下仍能保持温度在一个较小的范围内变化的合理的负载电压系数K。

2.温度控制的两个阶段 温度控制系统是一个惯性较大的系统,也就是说,当给温区开始加热之后,并不能立即观察得到温区温度的明显上升;同样的,当关闭加热之后,温区的温度仍然有一定程度的上升。另外,热电偶对温度的检测,与实际的温区温度相比较,也存在一定的滞后效应。这给温度的控制带来了困难。因此,如果在温度检测值(PV)到达设定值时才关断输出,可能因温度的滞后效应而长时间超出设定值,需要较长时间才能回到设定值;如果在温度检测值(PV)未到设定值时即关断输出,则可能因关断较早而导致温度难以达到设定值。为了合理地处理系统响应速度(即加热速度)与系统稳定性之间地矛盾,我们把温度控制分为两个阶段。 (1)PID调节前阶段

PID控制算法的C语言实现(完整版)

PID控制算法的C语言实现一 PID算法原理 最近两天在考虑一般控制算法的C语言实现问题,发现网络上尚没有一套完整的比较体系的讲解。于是总结了几天,整理一套思路分享给大家。 在工业应用中PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法,如果能够熟练掌握PID算法的设计与实现过程,对于一般的研发人员来讲,应该是足够应对一般研发问题了,而难能可贵的是,在我所接触的控制算法当中,PID控制算法又是最简单,最能体现反馈思想的控制算法,可谓经典中的经典。经典的未必是复杂的,经典的东西常常是简单的,而且是最简单的,想想牛顿的力学三大定律吧,想想爱因斯坦的质能方程吧,何等的简单!简单的不是原始的,简单的也不是落后的,简单到了美的程度。先看看PID算法的一般形式: PID的流程简单到了不能再简单的程度,通过误差信号控制被控量,而控制器本身就是比例、积分、微分三个环节的加和。这里我们规定(在t时刻): 1.输入量为rin(t); 2.输出量为rout(t); 3.偏差量为err(t)=rin(t)-rout(t); pid的控制规律为 理解一下这个公式,主要从下面几个问题着手,为了便于理解,把控制环境具体一下: 1.规定这个流程是用来为直流电机调速的;

2.输入量rin(t)为电机转速预定值; 3.输出量rout(t)为电机转速实际值; 4.执行器为直流电机; 5.传感器为光电码盘,假设码盘为10线; 6.直流电机采用PWM调速转速用单位转/min表示; 不难看出以下结论: 1.输入量rin(t)为电机转速预定值(转/min); 2. 输出量rout(t)为电机转速实际值(转/min); 3.偏差量为预定值和实际值之差(转/min); 那么以下几个问题需要弄清楚: 1.通过PID环节之后的U(t)是什么值呢? 2.控制执行器(直流电机)转动转速应该为电压值(也就是PWM占空比)。 3.那么U(t)与PWM之间存在怎样的联系呢? https://www.360docs.net/doc/8a13007705.html,/user1/3407/archives/2006/33541.html(见附录1)这篇文章上给出了一种方法,即,每个电压对应一个转速,电压和转速之间呈现线性关系。但是我考虑这种方法的前提是把直流电机的特性理解为线性了,而实际情况下,直流电机的特性绝对不是线性的,或者说在局部上是趋于线性的,这就是为什么说PID调速有个范围的问题。具体看一下 https://www.360docs.net/doc/8a13007705.html,/component/article90249.htm(见附录2)这篇文章就可以了解了。所以在正式进行调速设计之前,需要现有开环系统,测试电机和转速之间的特性曲线(或者查阅电机的资料说明),然后再进行闭环参数整定。这篇先写到这,下一篇说明连续系统的离散化问题。并根据离散化后的特点讲述位置型PID和增量型PID的用法和C语言实现过程。

模糊逻辑系统的C语言实现方法

模糊逻辑系统的C语言实现方法 贺维,江汉红,王海峰,张朝亮 (武汉海军工程大学湖北武汉 430033) 摘要:本文首先介绍了三种专门用于模糊逻辑控制系统设计的软件系统。详细地介绍了利用软件进行模糊逻辑控制系统设计的基本原理以及模糊控制器的软件程序设计方法。实验表明,模糊逻辑系统的C语言实现方法是完全可行的,并且能够大大减少工作量。 关键词:模糊逻辑C语言 C Language Realize Method of Fuzzy Logic System HE-wei JIANG Han-hong WANG Hai-feng ZHANG Chao-liang (Naval University of Engineering, Wuhan 430033, China) Abstract: This paper presents three special software systems for the the design of hardware circuit of Fuzzy Logic control system. The paper introduced the composing and working principle in detail . The way of designing and programming of Fuzzy Logic control system is also presented in detail in the paper. In the end the results of experiment shows that C Language realize method is completely viable,and can reduce lots of workload. Key words: Fuzzy Control C Language 1.引言 对于模糊控制的实现是模糊控制在实际应用中的一个重要环节。由于Matlab软件工具提供了强大的数学工具,一般模糊控制仿真在MATLAB/Simulink/Fuzzy Logic Toolbox下进行的。但是往往在实际应用之中,Matlab的程序就不能完成提供强大的功能了。在本文的无刷直流电机的DSP控制实验中,Matlab的程序与DSP的应用程序并不兼容,因而我们需要设计的智能控制器就变得有些复杂了,因而我们需要一种能快速解决模糊控制器的设计及应用的方法。文章中提出了以下三种有效的设计方案。 2.Matlab工具 对于实际模糊控制系统,由于在高级语言中模糊控制程序的实现比较复杂,因此引入模糊控制存在一定的困难,程序代码的过于复杂也会严重影响模糊控制系统的开发周期。而Matlab系统及其工具箱中提供了一些能够独立完成某些Matlab 功能的C/C++库函数,这些库函数可以直接应用到C/C++平台中,脱离系统完成Matlab某些功能,极大的方便了实际应用。Matlab Fuzzy Logic 工具箱的独立C 代码就是一个这样的C语言库[1]。 独立的C代码模糊推理引擎函数库fis.c位于Matlab目录下的toolbox\fuzzy\fuzzy目录中,它包含了在C语言环境下调用Matlab Fuzzy Logic 工具箱建立的模糊推理系统的数据文件(*.fis)进行模糊逻辑推理的一系列C函数,其基本原理是利用C代码实现Matlab中的模糊推理系统(FIS)功能。该目录下还有一个C代码程序fismain.c,它实际上是利用fis.c库函数来实现模糊推理系统的一个实例。 正确地熟悉了fis.c库函数中的函数定义,在应用程序中正确调用,即可实现模糊推理系统功能。例如,从Matlab的模糊推理系统文件(*.fis)读入系统数据,可用下面的语句:fisMatrix=returnFismatrix(fis_file,&fis_row_n,&fis_col_n);建

C语言实现串行通信接口程序

摘要本文说明了异步串行通信(RS-232)的工作方式,探讨了查询和中断两种软件接口利弊,并给出两种方式的C语言源程序。 的I/O通道之一,以最简单方式组成的串行双工线路只需两条信号线和一条公共地线,因此串行通信既有线路简单的优点同时也有它的缺点,即通信速率无法同并行通信相比,实际上EIA RS-232C在标准条件下的最大通信速率仅为20Kb/S。尽管如此,大多数外设都提供了串行口接口,尤其在工业现场RS-232C的应用更为常见。IBM PC及兼容机系列都有RS-232的适配器,操作系统也提供了编程接口,系统接口分为DOS功能调用和BIOS功能调用两种:DOS INT 21H的03h和04h号功能调用为异步串行通信的接收和发送功能;而BIOS INT 14H有4组功能调用为串行通信服务,但DOS和BIOS功能调用都需握手信号,需数根信号线连接或彼此间互相短接,最为不便的是两者均为查询方式,不提供中断功能,难以实现高效率的通信程序,为此本文采用直接访问串行口硬件端口地址的方式,用C语言编写了串行通信查询和中断两种方式的接口程序。 1.串行口工作原理 微机串行通信采用EIA RS-232C标准,为单向不平衡传输方式,信号电平标准±12V,负逻辑,即逻辑1(MARKING)表示为信号电平-12V,逻辑0(SPACING)表示为信号电平+12V,最大传送距离15米,最大传送速率19.6K波特,其传送序列如图1,平时线路保持为1,传送数据开始时,先送起始位(0),然后传8(或7,6,5)个数据位(0,1),接着可传1位奇偶校验位,最后为1~2个停止位(1),由此可见,传送一个ASCII字符(7位),加上同步信号最少需9位数据位。 @@T8S12300.GIF;图1@@ 串行通信的工作相当复杂,一般采用专用芯片来协调处理串行数据的发送接收,称为通用异步发送/接收器(UART),以节省CPU的时间,提高程序运行效率,IBM PC系列采用8250 UART来处理串行通信。 在BIOS数据区中的头8个字节为4个UART的端口首地址,但DOS只支持2个串行口:COM1(基地址0040:0000H)和COM2(基地址0040:0002H)。8250 UART共有10个可编程的单字节寄存器,占用7个端口地址,复用地址通过读/写操作和线路控制寄存器的第7位来区分。这10个寄存器的具体功能如下:COM1(COM2) 寄存器 端口地址功能DLAB状态 3F8H(2F8H) 发送寄存器(写) 0 3F8H(2F8H) 接收寄存器(读) 0 3F8H(2F8H) 波特率因子低字节1 3F9H(2F9H) 波特率因子高字节1 3F9H(2F9H) 中断允许寄存器0 3FAH(2FAH) 中断标志寄存器 3FBH(2FBH) 线路控制寄存器 3FCH(2FCH) MODEM控制寄存器 3FDH(2FDH) 线路状态寄存器 3FEH(2FEH) MODEM状态寄存器 注:DLAB为线路控制寄存器第七位在编写串行通信程序时,若采用低级方式,只需访问UART的这10个寄存器即可,相对于直接控制通信的各个参量是方便

PID控制算法的C语言实现系列

PID控制算法的C语言实现系列

PID控制算法的C语言实现一PID算法原理 2011年11月07日星期一 12:30 P.M. 最近两天在考虑一般控制算法的C语言实现问题,发现网络上尚没有一套完整的比较体系的讲解。于是总结了几天,整理一套思路分享给大家。 在工业应用中PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法,如果能够熟练掌握PID算法的设计与实现过程,对于一般的研发人员来讲,应该是足够应对一般研发问题了,而难能可贵的是,在我所接触的控制算法当中,PID控制算法又是最简单,最能体现反馈思想的控制算法,可谓经典中的经典。经典的未必是复杂的,经典的东西常常是简单的,而且是最简单的,想想牛顿的力学三大定律吧,想想爱因斯坦的质能方程吧,何等的简单!简单的不是原始的,简单的也不是落后的,简单到了美的程度。先看看PID算法的一般形式: PID的流程简单到了不能再简单的程度,通过误差信号控制被控量,而控制器本身就是比例、积分、微分三个环节的加和。这里我们规定(在t时刻): 1.输入量为rin(t); 2.输出量为rout(t); 3.偏差量为err(t)=rin(t)-rout(t); pid的控制规律为 理解一下这个公式,主要从下面几个问题着手,为了便于理解,把控制环境具体一下:

1.规定这个流程是用来为直流电机调速的; 2.输入量rin(t)为电机转速预定值; 3.输出量rout(t)为电机转速实际值; 4.执行器为直流电机; 5.传感器为光电码盘,假设码盘为10线; 6.直流电机采用PWM调速转速用单位转/min 表示; 不难看出以下结论: 1.输入量rin(t)为电机转速预定值(转/min); 2. 输出量rout(t)为电机转速实际值(转/min); 3.偏差量为预定值和实际值之差(转/min); 那么以下几个问题需要弄清楚: 1.通过PID环节之后的U(t)是什么值呢? 2.控制执行器(直流电机)转动转速应该为电压值(也就是PWM占空比)。 3.那么U(t)与PWM之间存在怎样的联系呢? https://www.360docs.net/doc/8a13007705.html,/user1/3407/archives/2006/33541.html这篇文章上给出了一种方法,即,每个电压对应一个转速,电压和转速之间呈现线性关系。但是我考虑这种方法的前提是吧直流电机的特性理解为线性了,而实际情况下,直流电机的特性绝对不是线性的,或者说在局部上是趋于线性的,这就是为什么说PID调速有个范围的问题。具体看一下 https://www.360docs.net/doc/8a13007705.html,/component/article90249.htm这篇文章就可以了解了。所以在正式进行调速设计之前,需要现有开环系统,测试电机和转速之间的特性曲线(或者查阅电机的资料说明),然后再进行闭环参数整定。这篇先写到这,下一篇说明连续系统的离散化问题。并根据离散化后的特点讲述位置型PID和增量型PID的用法和C语言实现过程。

相关文档
最新文档