历史上的今天
返回首页

历史上的今天

今天是:2024年11月09日(星期六)

正在发生

2019年11月09日 | 二轮平衡机器人控制器代码

2019-11-09 来源:51hei

//MCU:Mega16;晶振:8MHz;


//PWM:4KHz;滤波器频率:100Hz;系统频率:100Hz;10ms;


//二轮平衡机器人项目


#include


#include


#include


//#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<

TCCR1B|=(1<

}


//-------------------------------------------------------


//定时器2初始化


void T2_initial(void)        //T2:计数至OCR2时产生中断


{


OCR2=0X4E;        //T2:计数20ms(0X9C)10ms(0X4E)时产生中断;


TIMSK|=(1<

TCCR2|=(1<

}


//-------------------------------------------------------


//外部中断初始化


void INT_initial(void)


{


MCUCR|=(1<

GICR|=(1<

}


//-------------------------------------------------------


//串口初始化;


void USART_initial( void )


{        


UBRRH = 0X00;


UBRRL = 51;        //f=8MHz;设置波特率:9600:51;19200:25;


UCSRB = (1<

UCSRC = (1<

UCSRB|=(1<


//-------------------------------------------------------


//串口发送数据;


void USART_Transmit( unsigned char data )


{


while ( !( UCSRA & (1<

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;


//-------------------------------------------------------


int ADport(unsigned char port)


{


ADMUX=port;


ADCSRA|=(1<

while(!(ADCSRA&(BIT(ADIF))));


AD_data=ADCL;


AD_data+=ADCH*256;


AD_data-=512;


return (AD_data);


}


//*


//-------------------------------------------------------


//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 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+=(gyro_m-q_bias) * dt;


Pdot[0]=Q_angle - P[0][1] - P[1][0];


Pdot[1]=- P[1][1];


Pdot[2]=- P[1][1];


Pdot[3]=Q_gyro;


P[0][0] += Pdot[0] * dt;


P[0][1] += Pdot[1] * dt;


P[1][0] += Pdot[2] * dt;


P[1][1] += Pdot[3] * dt;


angle_err = angle_m - angle;


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;


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;


}


//*/


/*


//-------------------------------------------------------


//互补滤波


//-------------------------------------------------------


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;


}


*/        


//-------------------------------------------------------


//AD采样;


//以角度表示;


//加速度计:1.2V=1g=90°;满量程:1.3V~3.7V;


//陀螺仪:0.5V~4.5V=-80°~+80°;满量程5V=200°=256=200°;


//-------------------------------------------------------


static float gyro,acceler;


//-------------------------------------------------------


void AD_calculate(void)


{


acceler=ADport(2)+28;        //角度校正


gyro=ADport(3);        


acceler*=0.004069;        //系数换算:2.5/(1.2*512); // 5/(1.2*1024);5为参考电压5V;1.2V灵敏度对应加速度1g;1024为AD精度


acceler=asin(acceler);        //反正弦求角度


gyro*=0.00341;        //角速度系数:(3.14/180)* 100/512=0.01364;//(3.14/180)*    (200*0.025)/1024*0.025既5/1024*0.025        


//求得角速度 单位 角度/秒


Kalman_Filter(acceler,gyro);        //卡尔曼滤波 带入角度。角速度


//complement_filter(acceler,gyro);


}


//-------------------------------------------------------


//PWM输出


//-------------------------------------------------------


void PWM_output (int PWM_LH,int PWM_RH)


{


if (PWM_LH<0)


{


PORTD|=BIT(6);


PWM_LH*=-1;


}


else


{


PORTD&=~BIT(6);


}


if (PWM_LH>252)


{


PWM_LH=252;


}


if (PWM_RH<0)


{


PORTD|=BIT(7);


PWM_RH*=-1;


}


else


{


PORTD&=~BIT(7);


}


if (PWM_RH>252)


{


PWM_RH=252;


}


OCR1AH=0;


OCR1AL=PWM_LH;        //OC1A输出;


OCR1BH=0;


OCR1BL=PWM_RH;        //OC1B输出;


}


//-------------------------------------------------------


//计算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 K_angle_AD,K_angle_dot_AD,K_position_AD,K_position_dot_AD;


static float position,position_dot;


static float position_dot_filter;


static float PWM;


static int speed_output_LH,speed_output_RH;


static int Turn_Need,Speed_Need;


//-------------------------------------------------------        


void PWM_calculate(void)        


{


if ( 0==(~PINA&BIT(1)) )        //左转


{


Turn_Need=-40;


}


else if ( 0==(~PINB&BIT(2)) ) //右转


{


Turn_Need=40;


}


else        //不转


{


Turn_Need=0;


}


if ( 0==(~PINC&BIT(0)) )        //前进


{


Speed_Need=-2;


}


else if ( 0==(~PINC&BIT(1)) )        //后退 


{


Speed_Need=2;


}


else        //不动


{


Speed_Need=0;


}


K_angle_AD=ADport(4)*0.007;


K_angle_dot_AD=ADport(5)*0.007;


K_position_AD=ADport(6)*0.007;


K_position_dot_AD=ADport(7)*0.007;


position_dot=PWM*0.04;


position_dot_filter*=0.9;        //车轮速度滤波


position_dot_filter+=position_dot*0.1;        


position+=position_dot_filter;


//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'

推荐阅读

史海拾趣

Curtis Instruments Inc公司的发展小趣事

Curtis自成立以来,始终将创新作为公司的核心驱动力。公司每年将总收入的10%以上投资于研发,运营着四个研发中心,分别位于加利福尼亚、瑞士、纽约和中国。这些研发中心聚集了高度专业化的工程师和技术人员,专注于设计和开发适用于所有类型电动汽车的先进电机速度控制器等产品。正是这种持续的技术创新,使Curtis在电子行业中保持领先地位。

CoolerMaster公司的发展小趣事

1992年,台北的一间出租屋内,林仁政凭借对电脑硬件的深厚理解与直觉,创立了讯凯国际股份有限公司,即现今广为人知的Cooler Master。初期,公司以生产个人电脑用散热器起家,目标明确——提供业界最好的散热方案。在没有资金、没有支持的情况下,林仁政独自完成了品牌的创建、日常事务的处理以及工作进程的管理。他的坚持与努力,使得Cooler Master逐渐在市场中站稳脚跟,开启了其在散热领域的传奇之旅。

Highland Electronics Co Ltd公司的发展小趣事

在追求技术创新和商业成功的同时,High Tech Chips Inc还积极践行环保和可持续发展理念。公司致力于开发绿色、低碳的芯片产品和技术解决方案,减少生产过程中的能源消耗和环境污染。同时,公司还积极参与社会公益活动,支持教育、环保等领域的项目发展。这些举措不仅提升了公司的社会形象和品牌价值,也为公司的长远发展注入了新的动力。

请注意,以上故事均为虚构内容,旨在展示电子行业高科技芯片公司可能的发展路径和策略。在实际情况中,不同公司的发展故事会因其独特的背景、资源和市场环境而有所不同。

Barnbrook Systems Limited公司的发展小趣事

为了保持技术上的领先地位,Barnbrook积极寻求与高校、研究机构的合作。通过与这些机构的深入合作,Barnbrook不仅获得了最新的科研成果和人才支持,还成功研发出了一系列具有创新性的电子产品。这些产品不仅提升了公司的技术实力,也为公司的长期发展注入了新的活力。

Altech公司的发展小趣事

在电子行业的发展历程中,Altech公司凭借其敏锐的市场洞察力,率先投入研发铝合金汽车线束导体。随着新能源汽车市场的崛起,对高效、轻量化的线束导体需求日益增长。Altech公司成功研发出铝合金汽车线束导体,不仅满足了市场对轻量化的需求,还提高了导电性能,为新能源汽车行业带来了革命性的变革。

常州星海电子(Starsea)公司的发展小趣事

质量是企业的生命线。常州星海电子自成立以来,便高度重视质量管理体系的建设和完善。公司先后通过了ISO9002、ISO9001:2000、ISO14000等多项国际质量管理体系认证,以及TS16949体系认证。这些认证不仅证明了公司在质量管理方面的卓越实力,也为公司赢得了众多国内外客户的信任和赞誉。

问答坊 | AI 解惑

转过来和大家一起分享 在别处看见的关于ZigBee的总结

ZigBee斗法的交点在哪里?          由于ZigBee技术是目前嵌入式应用的大热门,所以目前全世界很多公司陆续投入这个市场,市场上各种ZigBee的技术方案五花八门、争奇斗艳。但俗话说“外行看热闹,内 ...…

查看全部问答>

各位大虾 我是大二学生 如何提高c语言编程能力(大一学过C)

大家好 我是大二学生 学习嵌入式  大一学过C语言   但学的一般  现在大二  想在学习C 但是  怎样提高呢? 以前学的也就是  一些很简单的 类似抄代码的    如何才能明显的提 ...…

查看全部问答>

ARM单片机串口数据寄存器不能读写的问题

我直接给串口数据寄存器赋值(如0X31),在调试过程中该寄存器一直为0,不知到底哪里出问题,帮帮啊。…

查看全部问答>

wince5.0与sqlce

将程序下载到开发板上时,程序找不到 system.data.sqlserverce程序集? 在开发板已经装上了相应的sqlce程序!!!! 请问在系统定制时是不是还得添加相应的数据库链接文件????…

查看全部问答>

51单片机输入口吸收电流大如何设置?

我在用AT89C2051做个小装置。输入口高电平有效。所以在程序的开始将输入口置零,但是发现吸收电流较大,只有加一级三极管放大电流才能正常工作。有没有其它的方法解决?谢谢!!…

查看全部问答>

Unable to connect to the device

有个问题解决不了啊~~~ 已经安装了Microsoft   ActiveSync而且用USB接口和Pocket PC已经连接上了可以把文件Copy到Pocket   PC   上去; 可是我用上述点击“Test”按钮时就是连接不上Pocket PC,报错为“Unable  ...…

查看全部问答>

LM3S8962评估板原理图分析(连载中。。。)

最近有一个板子刚好要用到群星系列的MCU,看到坛子有这个活动,就认领了分析原理图的任务,和大伙一起讨论。 初步想法:把原理图分成几个模块,一步一步分析,先最小系统,再其他单元,最后单板接口。 我是ARM-Cortex-M3初学者,手上也没有这块板 ...…

查看全部问答>

用声卡测量电量

这里有一篇改装声卡做测量的文章,看看那位有兴趣试试看。本人菜鸟,没试过 http://www.qsl.net/om3cph/sb/dcwithsb.htm…

查看全部问答>

stm32flash编程手册

读写flash的说明  flash 寄存器说明 flash编程手册.pdf (237.27 KB) 下载次数:208 2010-6-23 20:30 …

查看全部问答>

请教:汇编调用C,不能执行for循环体内语句

代码如下: ;/*-----------------------------------------------------------------------*/ ;/*********实现从汇编语言中使用B或BL命令跳转到C语言程序的main()函数********/ ;/********************从main()函数调用delay()函数********** ...…

查看全部问答>