搜索
bottom↓
回复: 0

各位莫友,帮我看下我的pwm为什么一直是高电平

[复制链接]

出0入0汤圆

发表于 2013-3-24 17:23:43 | 显示全部楼层 |阅读模式
各位莫友,帮我看下我的pwm为什么一直是高电平,而且控制车轮转动的4个管脚都输出高电平。。。。蛋疼中。。。。
谢谢各位捧场!!!


//MCU:Mega16;晶振:8MHz;
//PWM:4KHz;滤波器频率:100Hz;系统频率:100Hz;10ms;
#include <iom16v.h>
#include <macros.h>
#include <math.h>

//#define checkbit(var,bit)     (var&(0x01<<(bit)))     /*定义查询位函数*/
//#define setbit(var,bit)     (var|=(0x01<<(bit)))     /*定义置位函数*/
//#define clrbit(var,bit)     (var&=(~(0x01<<(bit)))) /*定义清零位函数*/


//-------------------------------------------------------
//输出端口初始化
void PORT_initial(void)
{
        DDRA=0B00000000;
        PINA=0X00;
        PORTA=0X00;
       
        DDRB=0B00000000;
        PINB=0X00;
        PORTB=0X00;
       
        DDRC=0B00010000;
        PINC=0X00;
        PORTC=0X00;
       
        DDRD=0B11110010;
        PIND=0X00;
        PORTD=0X00;
}


//-------------------------------------------------------
//定时器1初始化
void T1_initial(void)                                       
{
        TCCR1A|=(1<<COM1A1)|(1<<WGM10)|(1<<COM1B1);                                //T1:8位快速PWM模式、匹配时清0,TOP时置位
        TCCR1B|=(1<<WGM12)|(1<<CS11);                        //PWM:8分频:8M/8/256=4KHz;
}


//-------------------------------------------------------
//定时器2初始化
void T2_initial(void)                        //T2:计数至OCR2时产生中断
{
        OCR2=0X4E;                        //T2:计数20ms(0X9C)10ms(0X4E)时产生中断;
        TIMSK|=(1<<OCIE2);
        TCCR2|=(1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20);                        //CTC模式,1024分频
}


//-------------------------------------------------------
//外部中断初始化
void INT_initial(void)
{
        MCUCR|=(1<<ISC01)|(1<<ISC00)|(1<<ISC11)|(1<<ISC10);                        //INT0、INT1上升沿有效
        GICR|=(1<<INT0)|(1<<INT1);                        //外部中断使能
}


//-------------------------------------------------------
//串口初始化;
void USART_initial( void )
{       
        UBRRH = 0X00;
        UBRRL = 51;                //f=8MHz;设置波特率:9600:51;19200:25;
        UCSRB = (1<<RXEN)|(1<<TXEN);                //接收器与发送器使能;
        UCSRC = (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);                //设置帧格式: 8 个数据位, 1 个停止位;
       
        UCSRB|=(1<<RXCIE);                //USART接收中断使能
}


//-------------------------------------------------------
//串口发送数据;
void USART_Transmit( unsigned char data )
{
        while ( !( UCSRA & (1<<UDRE)));                //等待发送缓冲器为空;
        UDR = data;                //将数据放入缓冲器,发送数据;
}


//-------------------------------------------------------
//串口接收数据中断,确定数据输出的状态;
#pragma interrupt_handler USART_Receive_Int:12
static char USART_State;
void USART_Receive_Int(void)
{
        USART_State=UDR;//USART_Receive();
}


//-------------------------------------------------------
//在轮处已经把轮的信号一个正一个反,使得方向统一
//计算LH侧轮速:INT0中断;
//-------------------------------------------------------
static int speed_real_LH;
//-------------------------------------------------------
#pragma interrupt_handler SPEEDLHINT_fun:2
void SPEEDLHINT_fun(void)
{
        if (0==(PINB&BIT(0)))
        {
                speed_real_LH-=1;
        }
        else
        {
                speed_real_LH+=1;
        }
}


//-------------------------------------------------------
//计算RH侧轮速,:INT1中断;
//同时将轮速信号统一成前进方向了;
//-------------------------------------------------------
static int speed_real_RH;
//-------------------------------------------------------
#pragma interrupt_handler SPEEDRHINT_fun:3
void SPEEDRHINT_fun(void)
{
        if (0==(PINB&BIT(1)))
        {
                speed_real_RH+=1;
        }
        else
        {
                speed_real_RH-=1;
        }
}


//-------------------------------------------------------
//ADport采样:10位,采样基准电压Aref
//-------------------------------------------------------
static int AD_data;
float adc_v;
//-------------------------------------------------------
int ADport(unsigned char port)
{
        ADMUX=port;
        ADMUX &=0x3f;//外部基准源
        ADCSRA|=(1<<ADEN)|(1<<ADSC)|(1<<ADPS1)|(1<<ADPS0);                        //采样频率为8分频;
        while(!(ADCSRA&(BIT(ADIF))));
        AD_data=ADC;//读结果
       
        adc_v=(unsigned long)AD_data*3365/1024;
        return (adc_v);
}


//*
//-------------------------------------------------------
//Kalman滤波,8MHz的处理时间约1.8ms;
//-------------------------------------------------------
static float angle, angle_dot;                 //外部需要引用的变量
//-------------------------------------------------------
static const float Q_angle=0.001, Q_gyro=0.003, R_angle=0.5, dt=0.01;
//注意:dt的取值为kalman滤波器采样时间;
static float P[2][2] = {
                                                        { 1, 0 },
                                                        { 0, 1 }
                                                };
       
static float Pdot[4] ={0,0,0,0};

static const char C_0 = 1;
static float acc2;
static float q_bias, angle_err, PCt_0, PCt_1, E, K_0, K_1, t_0, t_1;
//-------------------------------------------------------
void Kalman_Filter(float angle_m,float gyro_m)                        //gyro_m:gyro_measure
{
        /*        ////、、、、、、、、、、、、、、、、、在这写angle对不对?给出angle的初始值       
        acc2=ADport(2);
        acc2=acc2-1650;
        acc2=acc2/800.0;
        if(acc2>1)
                acc2=1;
        else if(acc2<-1)
                acc2=-1;
        acc2=180/3.1415*asin(acc2);
        angle=acc2;
        */
       
       
        angle+=(gyro_m-q_bias) * dt;//先验估计       
        Pdot[0]=Q_angle - P[0][1] - P[1][0];// Pk-' 先验估计误差协方差的微分
        Pdot[1]=- P[1][1];
        Pdot[2]=- P[1][1];
        Pdot[3]=Q_gyro;
       
        P[0][0] += Pdot[0] * dt;// Pk- 先验估计误差协方差微分的积分 = 先验估计误差协方差
        P[0][1] += Pdot[1] * dt;
        P[1][0] += Pdot[2] * dt;
        P[1][1] += Pdot[3] * dt;
       
       
        angle_err = angle_m - angle;//zk-先验估计
       
       
        PCt_0 = C_0 * P[0][0];
        PCt_1 = C_0 * P[1][0];
       
        E = R_angle + C_0 * PCt_0;
       
        K_0 = PCt_0 / E;//Kk
        K_1 = PCt_1 / E;
       
        t_0 = PCt_0;
        t_1 = C_0 * P[0][1];

        P[0][0] -= K_0 * t_0;//后验估计误差协方差
        P[0][1] -= K_0 * t_1;
        P[1][0] -= K_1 * t_0;
        P[1][1] -= K_1 * t_1;
       
       
        angle        += K_0 * angle_err;//后验估计
        q_bias        += K_1 * angle_err;//后验估计

        angle_dot = gyro_m-q_bias;//输出值(后验估计)的微分 = 角速度/////////////////ci此处得到angle_dot
        /////////////////////////这样的angle对不对?
/////如果不要我加的那一块angle语句,那么这里得到的angle是什么?是由最初值迭代过去的?可是没看到迭代过程啊。
}

//*/

/*
//-------------------------------------------------------
//互补滤波
//-------------------------------------------------------
static float angle,angle_dot;                 //外部需要引用的变量
//-------------------------------------------------------       
static float bias_cf;
static const float dt=0.01;
//-------------------------------------------------------
void complement_filter(float angle_m_cf,float gyro_m_cf)
{
        bias_cf*=0.998;                        //陀螺仪零飘低通滤波;500次均值;
        bias_cf+=gyro_m_cf*0.002;
        angle_dot=gyro_m_cf-bias_cf;
        angle=(angle+angle_dot*dt)*0.90+angle_m_cf*0.05;       
        //加速度低通滤波;20次均值;按100次每秒计算,低通5Hz;
}
*/       




//-------------------------------------------------------
//////////////////////这块要有比较大的改动!!//////////////////////////////////////
//用rad表示角度
//k这个加速度计:800mv/g。满量程:1.5g*0.8=1.2v。0g的情况下为1.65v。
//k陀螺仪的参数:0角速度时1.35v。-300deg/sec~300deg/sec。每deg/sec=0.67mv。即满量程是:这个什么情况!
//应该都仅仅用到一个方向,7361的X,陀螺仪的x。



//AD采样;
//以角度表示;
//加速度计:1.2V=1g=90°;满量程:1.3V~3.7V;
//陀螺仪:0.5V~4.5V=-80°~+80°;满量程5V=200°=256=200°;
//-------------------------------------------------------
static float gyro,acceler,w;
//-------------------------------------------------------
void AD_calculate(void)
{


        acceler=ADport(2);                //AD的加速度计原始数据        //角度校正
        gyro=ADport(3);                //AD得陀螺仪原始数据

        acceler=acceler-1650;
        acceler=acceler/800.0;//*100 求出多少g
        if(acceler>1)
                acceler=1;
        else if(acceler<-1)
                acceler=-1;
        acceler=180/3.1415*asin(acceler);        //asin得出来的是rad还是reg??应该是rad、这。。。

        w=(gyro-1178)/0.67;//1169     ?????????这是何如????应该是减去多少?反正这里得到的是reg。
        gyro=w;
        Kalman_Filter(acceler,gyro);
        /*
        acceler*=0.0061035;                //系数换算:2.5/(1.2*512);///%%%2.5/(0.8*512)************改了此
        acceler=asin(acceler);
        gyro*=0.00341;                        //角速度系数:(3.14/180)* 100/512=0.003407;?       
       
        */
        //complement_filter(acceler,gyro);
}
       


//-------------------------------------------------------
//PWM输出和控制前后转动
//-------------------------------------------------------
void PWM_output (int PWM_LH,int PWM_RH)
{
        if (PWM_LH<0)
        {
                /////////////////////////////这个思想对不对?当1、2都置一时不就是两端都输出1,电机不转吧?
                PORTC &=~(1<<1);//反转,反箭头
                PORTC |=(1<<2);///////至一,转向箭头方向,于是箭头方向就是反方向由
                PWM_LH*=-1;///////////////////////////////哦这个是不是让一段一直保持为1,当此时置一使得不前后转,然后这边给个方向信号。
        }
        else
        {
                PORTC &=~(1<<2);//正转,箭头
                PORTC |=(1<<1);
        }
       
        if (PWM_LH>252)
        {
                PWM_LH=252;
        }
        if (PWM_LH<-252)
        {
                PWM_LH=-252;
        }
       
        /////////////////////////////
        if (PWM_RH<0)
        {
                PORTC &=~(1<<3);//反转,反箭头
                PORTC |=(1<<4);///////至一,转向箭头方向,于是箭头方向就是反方向由
                PWM_RH*=-1;
        }
        else
        {
                PORTC &=~(1<<4);//正转,箭头
                PORTC |=(1<<3);
        }
       
        if (PWM_RH>252)
        {
                PWM_RH=252;
        }
        if (PWM_RH<-252)
        {
                PWM_RH=-252;
        }
               
        OCR1AH=0;
        OCR1AL=PWM_LH;                        //OC1A输出;
       
        OCR1BH=0;
        OCR1BL=PWM_RH;                        //OC1B输出;
       
}



//////////////////////////////此处zl用的是4个电位计做为四个系数,此处我采用feng的做法直接设系数
//-------------------------------------------------------
//计算PWM输出值
//车辆直径:76mm; 12*64pulse/rev; 1m=3216pulses;
//-------------------------------------------------------       
//static int speed_diff,speed_diff_all,speed_diff_adjust;
//static float K_speed_P,K_speed_I;
static float K_voltage,K_angle,K_angle_dot,K_position,K_position_dot;
static float position,position_dot;
static float K_angle_AD=400,K_angle_dot_AD=10,K_position_AD=5.5,K_position_dot_AD=300;
static float position_dot_filter;
static float PWM;
static int speed_output_LH,speed_output_RH;
static int Turn_Need,Speed_Need;
/*此处是feng的思路,我要把两者结合,把4个实体电位计换成具体值
volatile double ut,angle_ek,speed,speed_filter=0,position=0;
volatile int Kp_angle=400;
volatile int Kd_angle=10;
volatile int Kp_speed=300;
volatile double Ki_speed=5.5;
volatile double Kd_speed=0;??????????
*///-------------------------------------------------------       
void PWM_calculate(void)       
{
        if ( 1==(~PINB&BIT(6)) )        //左转。。。。此处的按键的逻辑错了貌似。
        {
                Turn_Need=-40;
        }
        else if ( 1==(~PINB&BIT(7)) )         //右转
        {
                Turn_Need=40;
        }
        else        //不转
        {
                Turn_Need=0;
        }
       
        if ( 1==(~PINB&BIT(4)) )        //前进
        {
                Speed_Need=-2;
        }
        else if ( 1==(~PINB&BIT(5)) )        //后退
        {
                Speed_Need=2;
        }
        else        //不动
        {
                Speed_Need=0;
        }
       


        position_dot=(speed_real_LH+speed_real_RH)*0.5;
        /////这两条是不是反了?
        position_dot_filter*=0.85;                //车轮速度滤波
        position_dot_filter+=position_dot*0.15;        /////////////////////////position_dot_filter
       
        position+=position_dot_filter;///////////////////////////position
        //position+=position_dot;        //这一条还要不要?这怎么不要了,这个
        position+=Speed_Need;
       
        if (position<-768)                //防止位置误差过大导致的不稳定
        {
                position=-768;
        }
        else if  (position>768)
        {
                position=768;
        }
       
        PWM = K_angle*angle *K_angle_AD + K_angle_dot*angle_dot *K_angle_dot_AD +
                                        K_position*position *K_position_AD + K_position_dot*position_dot_filter *K_position_dot_AD;
       
       
        speed_output_RH = PWM - Turn_Need;
        speed_output_LH = - PWM - Turn_Need ;
       
        /*
        speed_diff=speed_real_RH-speed_real_LH;                        //左右轮速差PI控制;
        speed_diff_all+=speed_diff;
        speed_diff_adjust=(K_speed_P*speed_diff+K_speed_I*speed_diff_all)/2;
        */
               
        PWM_output (speed_output_LH,speed_output_RH);       
}

//-------------------------------------------------------
//定时器2中断处理
//-------------------------------------------------------
static unsigned char temp;
//-------------------------------------------------------
#pragma interrupt_handler T2INT_fun:4
void T2INT_fun(void)                                               
{
        AD_calculate();
       
        PWM_calculate();
       
        if(temp>=4)                        //10ms即中断;每秒计算:100/4=25次;
        {               
        //////////////////////////此处是干嘛呢????
                if (USART_State==0X30)                //ASCII码:0X30代表字符'0'
                {
                        USART_Transmit(angle*57.3+128);
                        USART_Transmit(angle_dot*57.3+128);
                        USART_Transmit(128);       
                }
                else if(USART_State==0X31)                //ASCII码:0X30代表字符'1'
                {
                        USART_Transmit(speed_output_LH+128);
                        USART_Transmit(speed_output_RH+128);                       
                        USART_Transmit(128);
                }
                else if(USART_State==0X32)                //ASCII码:0X30代表字符'2'
                {
                        USART_Transmit(speed_real_LH+128);
                        USART_Transmit(speed_real_RH+128);
                        USART_Transmit(128);
                }
                else if(USART_State==0X33)                //ASCII码:0X30代表字符'3'
                {
                        USART_Transmit(K_angle+128);
                        USART_Transmit(K_angle_dot+128);
                        USART_Transmit(K_position_dot+128);
                }                               
                temp=0;                               
        }
        speed_real_LH=0;
        speed_real_RH=0;       
        temp+=1;       
}



//-------------------------------------------------------
int i,j;
//-------------------------------------------------------
void main(void)
{
        PORT_initial();
        T2_initial();
        INT_initial();
        USART_initial ();
       
        SEI();
        ///////////////c此处和那4个参数一样就是系数而已,换算不换算其实无所谓。保留、/////////////////////////////////
        K_position=1;///0.8 * 0.209;                //换算系数:(256/10) * (2*pi/(64*12))=0.20944;//256/10:电压换算至PWM,256对应10V;
        K_angle=1;///34 * 25.6;                //换算系数:256/10 =25.6;
        K_position_dot=1;///1.09 * 20.9;                //换算系数:(256/10) * (25*2*pi/(64*12))=20.944;
        K_angle_dot=1;////2 * 25.6;                //换算系数:256/10 =25.6;


        for (i=1;i<=500;i++)                //延时启动PWM,等待卡尔曼滤波器稳定
        {
                for (j=1;j<=300;j++);;
               
        }
        T1_initial();
               
        while(1)
        {
                ;
        }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-28 18:19

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表