fly_v1

Dependencies:   BufferedSerial SoftPWM mbed send

Fork of withbufferserial_nrftst by aurora moon

main.cpp

Committer:
wanzq
Date:
2017-12-24
Revision:
6:6e0f02edb404
Parent:
5:683542d82dd7

File content as of revision 6:6e0f02edb404:

#include "mbed.h"
#include "nRF24L01P.h"
#include "SoftPWM.h"
#include"JY901.h"

#define TRANSFER_SIZE   12
#define fail_max   10 //最大重连次数

#define maxroll 10
#define maxpitch 10
#define maxyaw 10//遥控器调节的最大值

#define maxp_z 0.5
#define maxpi0 0.3
#define maxpi1 0.25
#define maxpi2 0.2//参数设定需满足 0.33*maxp_z+maxpi1+maxpi2<0.5 ;maxp_z+0.5*maxpi2+maxpi0<0.5
#define p_z_max 0.3f
#define p_z_min -0.2
#define I0_INIT 0.0f
#define I1_INIT 0.0f

SoftPWM PWM1(PA_2);
PwmOut PWM2(PA_3),PWM3(PA_6),PWM4(PA_7),PWM5(PB_0),PWM6(PB_1);//六路PWM输出接口 
//PS:PA_2 mbed不支持PWM输出 与USART3的串口时钟初始化冲突 只能采用软件pwm,其原有库有一定的问题,应用此方法后不应该采用中断处理时间较长的中断)
JY901 _JY901(PA_9,PA_10);//JY901 接口 (波特率为115200,在bufferserial库中更改!)
nRF24L01P my_nrf24l01p(PB_15, PB_14, PB_13, PC_1, PC_2, PC_0);//nrf模块,nrf可能会由于电压波动断电,需要软件重启

int state=0;//状态标志
int pid_flag=0;//pid标志位
int fail_num=0;//nrf通讯失败计数
float target_roll[3]={0,0,-30},p_z=p_z_min,target_roll_attach[3]={0,0,0},p_z_attach=0;//目标
float err_old[3]={0,0,0};//记录前一个的误差值
float I[3]={I0_INIT,I1_INIT,0};//积分值
float kp1=0.004,ki1=8e-5,kd1=0.08,
      kp2=-0.002,ki2=0,kd2=-0.12,
      kp0=0.005,ki0=1e-4,kd0=0.10;//pid参数设置
char rxData[TRANSFER_SIZE];

void _pid_flag(){pid_flag=1;}//定时控制pid

void pid_control(){
    _JY901.receiveData();
    float roll[3],P1,P2,P3,P4,P5,P6;
    _JY901.getAttitude(roll[0], roll[1], roll[2]);
    if(roll[0]>180) roll[0]-=360;
    if(roll[1]>180) roll[1]-=360;
    if(roll[2]>180) roll[2]-=360;//更新数据
    
    
    target_roll_attach[2] = (float)(((int)rxData[1]*256+(int)rxData[2])-32768);
    if(state!=3) p_z_attach =65536.0f-(float)((int)rxData[3]*256+(int)rxData[4]);
    target_roll_attach[1] = (float)(((int)rxData[5]*256+(int)rxData[6])-32768);
    target_roll_attach[0] = (float)(((int)rxData[7]*256+(int)rxData[8])-32768);
    
    target_roll[0]=maxroll*target_roll_attach[0]/32767.0f;
    target_roll[1]=maxpitch*target_roll_attach[1]/32767.0f;
    target_roll[2]=maxyaw*target_roll_attach[2]/32767.0f;
    if(state!=3) p_z=p_z_min+(p_z_attach/65532.0f)*(p_z_max-p_z_min);
    else  p_z+=p_z_attach*1.5e-8;
    
  /*  if (target_roll[0]>maxroll)target_roll[0]=maxroll;
    if (target_roll[0]<-maxroll)target_roll[0]=-maxroll;
    if (target_roll[1]>maxpitch)target_roll[1]=maxpitch;
    if (target_roll[1]<-maxpitch)target_roll[1]=-maxpitch;
    if (target_roll[2]>maxyaw)target_roll[2]=maxyaw;
    if (target_roll[2]<-maxyaw)target_roll[2]=-maxyaw;*/
    if (p_z>maxp_z) p_z=maxp_z;
    if (p_z<-maxp_z) p_z=-maxp_z;//动力限幅
    
    P1=0.5;P2=0.5;P3=0.5;P4=0.5;P5=0.5;P6=0.5;
    float err[3];
    float pi1,pi2,pi0;
    err[0]=target_roll[0]-roll[0];  
    err[1]=target_roll[1]-roll[1];
    err[2]=target_roll[2]-roll[2];
    
    I[0]+=err[0];
    I[1]+=err[1]; 
    I[2]+=err[2];
    
    if(I[0]>0.2/ki0) I[0]=0.2/ki0;
    if(I[1]>0.2/ki1) I[1]=0.2/ki1;
    if(I[2]>0.2/ki2) I[2]=0.2/ki2;
    if(I[0]<-0.2/ki0) I[0]=-0.2/ki0;
    if(I[1]<-0.2/ki1) I[1]=-0.2/ki1;
    if(I[2]<-0.2/ki2) I[2]=-0.2/ki2;//积分项限幅防止长时间积分无法回调
    
    pi0=err[0]*kp0+ki0*I[0]+kd0*(err[0]-err_old[0]);
    pi1=err[1]*kp1+ki1*I[1]+kd1*(err[1]-err_old[1]);
    pi2=err[2]*kp2+ki2*I[2]+kd2*(err[2]-err_old[2]);//计算pid
    
    err_old[1]=err[1];
    err_old[2]=err[2];
    err_old[0]=err[0];
    
    if(pi1>maxpi1) pi1=maxpi1;//pid限幅
    if(pi1<-maxpi1) pi1=-maxpi1;
    if(pi0>maxpi0) pi0=maxpi0;
    if(pi0<-maxpi0) pi0=-maxpi0;
    if(pi2>maxpi2) pi2=maxpi2;
    if(pi2<-maxpi2) pi2=-maxpi2;
     
    P3+=(p_z/3-pi1-pi2);
    P6+=(p_z/3+pi1+pi2);
    P1+=(p_z+pi0-0.5*pi2);
    P2+=(p_z+pi0+0.5*pi2);
    P4+=(p_z+-pi0+0.5*pi2);
    P5+=(p_z+-pi0-0.5*pi2);//计算电机pwm占空比
    
    PWM3=P3;PWM6=P6;
    if(P1<=0.01) PWM1=0.01;else PWM1=P1;
    PWM2=P2;
    PWM4=P4;PWM5=P5;//更新pwm占空比
}

void nrf_restart()
{
    my_nrf24l01p.powerUp();  
    my_nrf24l01p.setTransferSize(TRANSFER_SIZE);
    my_nrf24l01p.setReceiveMode();
    my_nrf24l01p.enable();      
}//nrf重启动

int get_command()
{
   switch (rxData[0]){
       case 0x50:
        return 1;
   
       case 0x52:
        return 2;
   
       case 0x53:
        return 3;  
    }     
    return 0;
}

void state_config()
{
    switch(state)
    {
        case 0://待机状态等待启动命令
        if (get_command()==1) {p_z=p_z_min;p_z_attach=0;state=1;}
        break;
        
        case 1://启动状态,等待缓降(0x53)或急停命令(0x52)
        int u_flag=get_command();
        if (u_flag==3) {state=3;break;}
        
        if (u_flag==2) {state=2;break;}
        
        break;
        
        case 2://急停状态,急停后进入待机状态
            PWM3=0;PWM6=0;PWM4=0;PWM5=0;PWM1=0;PWM2=0;
            state=0;
            target_roll[0]=0;
            target_roll[1]=0;
            target_roll[2]=0;
            target_roll_attach[0]=0;
            target_roll_attach[1]=0;
            target_roll_attach[2]=0;
            I[0]=I0_INIT;
            I[1]=I1_INIT;I[2]=0;
     //       p_z_attach=-2e5;
        break;
        
        case 3://缓降状态,等待急停命令,缓降更改目标为0,匀减速降落。
            if (get_command()==2) state=2;     
            target_roll[0]=0;
            target_roll[1]=0;
            target_roll[2]=0;
            target_roll_attach[0]=0;
            target_roll_attach[1]=0;
            target_roll_attach[2]=0;
            p_z_attach=-2e5;
        break;
    }
}
void pwm_init(){
    //PWM1.period_us(100);
    PWM2.period_ms(1);
    PWM3.period_ms(1);
    PWM4.period_ms(1);    
    PWM5.period_ms(1);
    PWM6.period_ms(1);
    PWM1=0.0;PWM2=0.0;PWM3=0.0;PWM4=0.0;PWM5=0.0;PWM6=0.0;
}

int main() {
    pwm_init(); 
    nrf_restart();
    Ticker time;
    time.attach(&_pid_flag,0.01);
    while(1){
        if(my_nrf24l01p.readable()) {
            my_nrf24l01p.read(NRF24L01P_PIPE_P0,rxData,sizeof(rxData));
            state_config();
            }
            else {
                if (fail_num==fail_max) {nrf_restart();fail_num=0;} 
                else fail_num++;
                }//接收遥控器指令,一定次数没收到指令自动重新启动nrf模块
        switch(state)
        {
            case 0:
            break;
            case 1:
                if (pid_flag) {pid_control();pid_flag=0;}
            break;
            case 3:
                if (pid_flag) {pid_control();pid_flag=0;}
            break;
        }
     }  
}