#include <stdlib.h>
#include <util/delay.h>
#include "inherit.h"
#include "pid.h"
#include "output.h"
#include "main.h"
#include "ad.h"
#include "filter.h"
/*********************************************
*函数名: void inherit(void) 遗传进化PID参数
*说明:
1、调用函数:
found(unsigned int *colony,unsigned int *health)
evaluating_unit(unsigned int unit)
roulette(unsigned int *health,unsigned int health_sum)
variation(unsigned int baby)
evaluating(unsigned int *health,unsigned *mini_p)
2、变量说明:
colony[] 个体生存空间
health[] 个体适应值
health_sum 适应值总合
dad,mum 父本,母本
baby1,baby2 子代1,子代2
mini,mini_id 最小适应值,最小适应值的id
epoch 遗传代数
temp,i 一般用
time_pid 全局变量,PID调节的时间标志
3、常量说明:
col_MAX // 群体空间大小
var_p //变异概率:65对应的变异概率约等于0.001,650为0.01
epoch_MAX //进化代数
*入口:
*出口:
*********************************************/
#define col_MAX 50
#define var_p 650
#define epoch_MAX 200
void inherit(void)
{
unsigned int colony[col_MAX]={
62267,15148,39769,31849,58411,49944,29915,58375 ,53831
,29144,40332,51900,60411,48378,11552,26588,61306,60089
,26887,58565, 3794,23125,53291, 646, 9102,13288,13023
,39570,17838,13029, 1001,48941,29169,61066,30539,27436
,55457,34416,13280,44049,54926, 1287,44647,24869,54512
,32952,46495,28107,19963,12429
};
unsigned int health[col_MAX]; // 对应colony[] ,每个个体的适应值,
unsigned int health_sum; //适应值总合
unsigned int dad,mum,baby1,baby2;
unsigned int mini,mini_id;
unsigned int temp;
unsigned char i,epoch;
mini=found(&colony[0],&health[0]); //评估初始个体,并作适应值缩放
for(epoch=0;epoch<epoch_MAX;epoch++) //开始进化
{
i=roulette(&health[0],health_sum);
dad=colony[i];
i=roulette(&health[0],health_sum);
mum=colony[i];
baby1=dad&0xff;
baby1|=mum&0xff00;
baby2=mum&0xff;
baby2|=dad&0xff00;
baby1=variation(baby1); //变异
baby2=variation(baby2);
temp=evaluating_unit(baby1);
if(temp>mini)
{
mini_id=evaluating(&health[0]); //取得最差个体的适应值,及其id
colony[mini_id]=baby1;
health[mini_id]=temp-mini;
}
temp=evaluating_unit(baby2);
if(temp>mini)
{
mini_id=evaluating(&health[0]); //取得最差个体的适应值,及其id
colony[mini_id]=baby2;
health[mini_id]=temp-mini;
}
}
while(1); //结束进化
}
/*********************************************
*函数名:unsigned int evaluating_unit(unsigned int unit) //评估个体适应值
*说明:
1、调用函数:
unsigned int ad(void) //AD采集
unsigned int filter_8pj(unsigned int temp) //滤波
unsigned int filter_yj(unsigned int new_data) //滤波
void redressal(unsigned int k_dip); //对基因进行解码
int pid(int nonce,int aim); //增量PID调整
void output(unsigned char pwm); //系统输出
2、变量说明:
unit //个体基因
ad_value //采集的电压值
max //最大超调量
test_pwm //无调制时的输出值
uk //PID增量
temp,i //一般用
3、常量说明:
ev_N //PID调整次数,采集每次调整的绝对误差,并累加
aim_value //期望电压值,350对应3.50伏
*入口: evaluating_unit(unsigned int unit) //传递个体基因
*出口: return (ret) //返回适应值
*********************************************/
#define ev_N 25
#define aim_value 350
unsigned int evaluating_unit(unsigned int unit)
{
unsigned int ret=0,temp=0,ad_value=0,max=0;
unsigned char i=0;
unsigned char test_pwm=100;
int uk=0;
redressal(unit); //根据个体,修改PID三个参数
output(test_pwm);
for(i=0;i<120;i++)
{
_delay_ms(10);
}
for(i=0;i<28;i++)
{
ad_value=ad();
ad_value=filter_8pj(ad_value);
ad_value=filter_yj(ad_value);
ad_value=ad_value*20/41;
}
i=0;
while(i<ev_N) //PID调整
{
if((1==time_pid))
{
time_pid=0;
if(ad_value>aim_value)
{
temp=ad_value-aim_value;
if(temp>max)
{
max=temp;
}
}
else temp=aim_value-ad_value;
ret+=temp;
uk=pid(ad_value,aim_value);
if((test_pwm+uk)>255)
{
output(255);
}
else output(test_pwm+=uk);
i++;
}
else
{
ad_value=ad(); //采集电压
ad_value=filter_8pj(ad_value); //递推平均滤波
ad_value=filter_yj(ad_value); //一阶自调整滤波
ad_value=ad_value*20/41; //转换成实际电压(比实际值放大了100倍)
}
}
output(test_pwm);
ret=65500/(ret/ev_N+max);
return (ret);
}
/*********************************************
*函数名:unsigned int found(unsigned int *colony,unsigned int *health) //计算初始群体适应值,并找出最小值
*说明:
1、调用函数:
unsigned char evaluating(unsigned int *health) //评估个体适应值函数
2、变量说明:
mini //最小适应值
3、常量说明:
无
*入口:unsigned int found(unsigned int *colony,unsigned int *health) //传递群体及群体适应值数组指针
*出口:return (mini) //返回最小适应值
*********************************************/
unsigned int found(unsigned int *colony,unsigned int *health)
{
unsigned char i;
unsigned int mini=0xff;
for(i=0;i<col_MAX;i++)
{
*(health+i)=evaluating_unit(*(colony+i));
if(*(health+i)<mini)
{
mini=*(health+i);
}
}
for(i=0;i<col_MAX;i++) //适应值缩放
{
*(health+i)-=mini;
}
return (mini);
}
/*********************************************
*函数名:unsigned char roulette(unsigned int *health,unsigned int health_sum) //轮盘赌转
*说明:
1、调用函数:
rand() //产生0~0XFFFF随机值(最大随机值在stdlib.h中修改)
2、变量说明:
i,temp //一般用
3、常量说明:
col_MAX // 群体空间大小
*入口:unsigned char roulette(unsigned int *health,unsigned int health_sum) //传递适应值数组指针及适应值总合
*出口:return (i) //返回被选中的id(数组下标)
*********************************************/
unsigned char roulette(unsigned int *health,unsigned int health_sum)
{
unsigned char i;
unsigned int temp=0;
i=(unsigned char)(rand()/7282); //0~50随机选择起点
for(;i<col_MAX;i++)
{
temp+=*(health+i); //累加适应值
if (temp>1200)
{
return (i);
}
if( temp<1200 && col_MAX-1==i ) //实现首尾相接
{
i=0;
}
}
return i;
}
/*********************************************
*函数名:unsigned char evaluating(unsigned int *health) //取得最小适应值的个体id(数组下标)
*说明:
1、调用函数:
无
2、变量说明:
id //最小适应值的个体id(数组下标)
mini //当前最小值
3、常量说明:
无
*入口:unsigned char evaluating(unsigned int *health) //传递适应值数组指针
*出口:return (id) //返回最小适应值的个体id(数组下标)
*********************************************/
unsigned char evaluating(unsigned int *health)
{
unsigned char i,id;
unsigned int mini=0xffff;
for(i=0;i<col_MAX;i++)
{
if(*(health+i)<mini)
{
mini=*(health+i);
id=i;
}
}
return id;
}
/*********************************************
*函数名:unsigned int variation(unsigned int baby) //对基因进行变异
*说明:
1、调用函数:
无
2、变量说明:
i 循环用
3、常量说明:
var_p //变异概率:65对应的变异概率约等于0.001,650为0.01
*入口:unsigned int variation(unsigned int baby) //传递个体基因
*出口:return (baby) //返回变异后的基因
*********************************************/
unsigned int variation(unsigned int baby)
{
unsigned char i;
for(i=0;i<16;i++)
{
if(rand()<var_p)
{
if(0==(baby&(1<<i)))
{
baby|=(1<<i);
}
else baby&=~(1<<i);
}
}
return baby;
}