//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'
上一篇:AVR单片机经典使用经验
下一篇:ATMEGA16L实现时间和温度的循环显示程序分享
推荐阅读
史海拾趣
1966年,Baumer Electric Ag完成了从个体企业向股份公司的转型。同年,公司推出了测量开关和控制开关,这一创新产品为公司的成功发展奠定了坚实基础。股份制改革为公司带来了更多的资金和资源支持,加速了产品研发和市场推广的进程。
Compostar Technology Co Ltd公司自成立以来,一直致力于电子技术的研发与创新。在早期,公司凭借一款具有高效能耗比的电源管理芯片,成功打入了市场。随着技术的不断进步,公司逐渐将业务扩展到通信、智能家居和可穿戴设备等多个领域。公司不断投入研发资金,吸引了一批优秀的科研人才,成功研发出多款具有竞争力的产品,逐渐在电子行业中树立了良好的口碑。
在市场竞争日益激烈的情况下,AVA电子意识到单打独斗已经难以应对市场的挑战。于是,公司开始寻求与上下游企业的合作,通过产业链整合实现协同发展。AVA电子与供应商建立了长期稳定的合作关系,确保了原材料的稳定供应和质量保障;同时,公司还与多家销售渠道商建立了战略合作关系,共同开拓市场。这种产业链整合的模式不仅降低了公司的运营成本,也提高了公司的市场竞争力。
在市场竞争日益激烈的今天,Dau Semiconductor Inc公司深知只有不断创新和升级技术,才能保持市场竞争力。因此,公司不断加大对研发的投入,引进先进的设备和人才,探索新的技术方向。近年来,公司成功研发出了多款具有创新性的半导体芯片产品,如基于人工智能技术的智能芯片、基于物联网技术的低功耗传感器芯片等。这些产品的推出,不仅为公司带来了更多的商业机会,也为行业的发展注入了新的活力。
EPC公司成立于2007年,由三位拥有六十年先进功率管理技术经验的资深工程师共同创立。公司的创始人们认识到,随着技术的不断发展,传统的硅功率技术已接近其性能极限。他们决定专注于氮化镓技术的研究与开发,这是一种新型的半导体材料,具有比硅更高的电子迁移率和更低的电阻。经过数年的研究和试验,EPC公司成功开发出了基于氮化镓的高效功率半导体器件,这一突破性的技术为公司的未来发展奠定了坚实的基础。
近年来,智能化和物联网技术的快速发展为电子行业带来了前所未有的机遇。CUI技术作为实现电子设备智能化和互联互通的关键环节之一,得到了广泛的应用。一些企业针对智能化和物联网的需求,开发出具有特殊功能的CUI材料,如柔性CUI、透明CUI等,为电子产品的创新提供了有力支持。
请注意,以上故事仅为概述性质,并非针对特定公司的实际发展历程。每个公司的具体情况可能因市场环境、技术实力、管理策略等因素而有所不同。如果需要了解特定公司的具体发展故事,建议查阅相关公司的官方网站、新闻报道或行业分析报告。
作者:孙天泽,华清远见嵌入式学院金牌讲师。 从1991年诞生的那天起,Linux内核就在全世界的黑客们精心呵护下不断发展壮大。很多Linux Fans想为Linux内核做贡献,但或许是包括技术在内的等等原因,你的Ideas不一定会被内核容纳。对于操作系统来 ...… 查看全部问答∨ |
|
有个工控设备,其中内置一台个人电脑(PC全内置主板),需要配备显示器和键盘。 因为安装空间太小,容纳不了普通CRT或笔记本LCD显示器。况且,该设备的用户界面很简单,只需要控制串口通讯以及操作一个简单的ACCESS数据库,使用带触摸的2.5~3.5寸 ...… 查看全部问答∨ |
前几日使用维纶触摸屏MT6100I系列产品,大约7天后发现故障: 基本症状如下: 黑屏与维纶手型标志交替闪动. 咨询厂家说: 没有遇到此类情况. 把屏返回厂家说,测试了几天,没有发现故障. 大约7天后,另外一个工地,同样的屏出现了同样的故障.即黑屏与维纶手 ...… 查看全部问答∨ |
INOUT引脚: 1.FPGA IO在做输入时,可以用作高阻态,这就是所说的高阻输入; 2.FPGA IO在做输出时,则可以直接用来输入输出。 芯片外部引脚很多都使用inout类型的,为的是节省管腿。就是一个端口同时做输入和输出。 inout在具体实现上一般用 ...… 查看全部问答∨ |
如题,官方评估板的例程带了RLos, 我用UDPTCPdbg工具调试,在局域网里传送文件,工具上显示速率只有几十K,想弄个裸奔的程序再试试,有没有弄过的指点下。先谢谢了!… 查看全部问答∨ |
OFFSET current:失调电流、BIAS current:偏置电流 选择运放的时候,看见这两个参数,他们的区别是什么呢?搞不懂啊, 实际运用中用的到吗? … 查看全部问答∨ |
在请问一下,我定义一个 srtuct a { unsigned char a1; unsigned char a2; unsigned char a3; unsigned char a4; }aa; 现在我想把一个数组,比如unsigned char b[4]={0,1,2,3}; 分别赋给结构体里的a1,a2,a3,a4有没有方便的办 ...… 查看全部问答∨ |