標(biāo)題:
Atmega16+mpu6050平衡小車源碼 卡爾曼濾波
[打印本頁(yè)]
作者:
swkdnf
時(shí)間:
2017-12-12 20:18
標(biāo)題:
Atmega16+mpu6050平衡小車源碼 卡爾曼濾波
代碼測(cè)試通過,卡爾曼濾波
Anyway2.0_新驅(qū)動(dòng)_客戶例程->default->Anyway_main.hex 此文件為燒寫代碼
0.png
(12.13 KB, 下載次數(shù): 78)
下載附件
2017-12-13 02:02 上傳
單片機(jī)源程序如下:
//方能儀器平衡車程序V2.0***************************
//Landforcer 方能儀器版權(quán)所有
/*使用到的單片機(jī)模塊有:
1、一路定時(shí)器中斷用于給定卡爾曼濾波周期,大約10ms
2、七路AD,其中ADC0用于檢測(cè)轉(zhuǎn)向電位器輸出(備用擴(kuò)展,小車有接口),
ADC1用于檢測(cè)左輪電機(jī)的電流(備用),
ADC2連接外部滑動(dòng)變阻器RK0,用于調(diào)整小車的平衡角度,也就是調(diào)零,ADC3連接
RK1用于調(diào)節(jié)角度的比例系數(shù),ADC4連接RK2用于調(diào)節(jié)角度的微分系數(shù),ADC5連接
RK3用于調(diào)節(jié)位置的比例系數(shù),ADC6連接RK4用于調(diào)節(jié)位置的微分系數(shù),ADC7用于檢測(cè)
右輪電機(jī)的電流(備用)
3、兩路外部中斷,用于檢測(cè)編碼器的輸出脈沖數(shù),進(jìn)而測(cè)得車速
4、兩路PWM輸出,PWM驅(qū)動(dòng)直流伺服電機(jī)
5、一般IO口,通過發(fā)送高低電平控制電機(jī)的正反轉(zhuǎn),
6、iic接口用于讀取MPU6050六軸傳感器的數(shù)據(jù)
使用到的外部硬件模塊有:MPU6050六軸傳感器
電機(jī)驅(qū)動(dòng)模塊,車輪檢測(cè)編碼器模塊和主控板*/
//*************************AnyWay調(diào)試說明**********************//
/*RK0為小車的平衡角度調(diào)節(jié),也就是零點(diǎn)調(diào)節(jié),
RK1為角度比例系數(shù),順時(shí)針變小,逆時(shí)針變大,系數(shù)越大車子越有力,但是系數(shù)太大會(huì)導(dǎo)致抖動(dòng)造成自激,建議大小為2.0V
RK2為角度微分系數(shù),順時(shí)針變小,逆時(shí)針變大,系數(shù)越大車子反應(yīng)越靈敏,能一定程度上消除RK1導(dǎo)致的自激,但是不能太大,建議為3.6V
RK3為位置微分系數(shù),順時(shí)針變小,逆7時(shí)針變大,系數(shù)越大車子越穩(wěn)定,但是太大會(huì)導(dǎo)致自激,建議為0.6V
RK4為位置比例系數(shù),順時(shí)針變小,逆時(shí)針變大,系數(shù)越大車子回到原點(diǎn)的速度越快,但是太大也會(huì)導(dǎo)致自激,建議為1.0V
*/
#include<avr/io.h>
#include<avr/interrupt.h>
//#include<avr/signal.h>
#include "Anyway_uart.h"
#include "Anyway_Kalman.h"
#include "Anyway_mup6050.h"
#include"Anyway_twi.h"
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
/////////////////變量定義區(qū)
extern float angle, angle_dot;
volatile unsigned int AD_data;
volatile float PWM;
volatile unsigned char flager,reger;
volatile int speed_output_RH,speed_output_LH,NUMBER;
volatile int speed_real_LH,speed_real_RH;
volatile float gyro,acc,adc_v,angle_t;
volatile int Kp_angle,Kd_angle,Kd_position;
volatile float Kp_position;
volatile float position,position_dot;
volatile float position_dot_filter;
volatile int Turn_Need,Speed_Need;
unsigned char cdis[14]={0,}; //讀緩存區(qū)
unsigned int aaa,ggg;
#define xtal 16 //以MHz為單位,不同的系統(tǒng)時(shí)鐘要修改。
void delay_1ms(void)
{
unsigned int i;
for(i=0;i<(unsigned int)(xtal*143-2);i++);
}
void delay_nms(unsigned int num)
{
unsigned int i;
for(i=0;i<num;i++)
delay_1ms();
}
///////////////////中斷初始化
void T1_initial(void)
{
TCCR1A|=(1<<COM1A1)|(1<<WGM10)|(1<<COM1B1); //T1:8位快速PWM模式、匹配時(shí)清0,TOP時(shí)置位
TCCR1B|=(1<<WGM12)|(1<<CS11); //PWM:8分頻:16M/8/256=8KHz;
}
//-------------------------------------------------------
//定時(shí)器2初始化
void T2_initial(void) //T2:計(jì)數(shù)至OCR2時(shí)產(chǎn)生中斷
{
OCR2=0x30;//0X5E; //T2:10ms時(shí)產(chǎn)生中斷;
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); //外部中斷使能
}
///////////////////////ad轉(zhuǎn)換
int mega16_ad(uchar Ch1)
{
uint addata;
ADMUX = 0x00 | Ch1;//這個(gè)地方注意設(shè)置,外部基準(zhǔn)源
ADCSRA|=(1<<ADEN)|(1<<ADSC)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);;
while(!(ADCSRA & (1 << ADIF)));
addata=ADCL;
addata=addata+ADCH*256;
// AD_data-=512;
ADCSRA &= ~(1 << ADIF);
ADCSRA &= ~(1 << ADEN);
return addata;
}
void AD_calculate(void)
{aaa=cdis[2]*256+cdis[3]+32768;
//acc=(mega16_ad(0)-mega16_ad(2))*3.286/800;
acc=(32768-aaa*1.0)/16384;//+(512-mega16_ad(2))*0.004;;
if(acc>1) ///這個(gè)地方必須限幅,不然會(huì)出問題
acc=1;
else if(acc<-1)
acc=-1;
acc=57.3*acc;
//gyro=-(mega16_ad(1)-380)*4.9;
ggg=cdis[10]*256+cdis[11]+32768;
gyro=(32768-ggg*1.0)/131;
angle_t=mega16_ad(7)/5.3;
//Kalman_Filter(acc,gyro);
angle=0.95*(angle)+0.05*acc;
angle_dot=gyro;
}
////////////////////////////////PWM發(fā)送
void PWM_output (int PWM_LH,int PWM_RH)
{
if (PWM_LH<0)
{
PORTB|=1<<7;
PWM_LH*=-1;
}
else
{
PORTB&=~(1<<7);
}
if (PWM_LH>252)
{
PWM_LH=252;
}
if (PWM_RH<0)
{
PORTB|=1<<6;
PWM_RH*=-1;
}
else
{
PORTB&=~(1<<6);
}
if (PWM_RH>252)
{
PWM_RH=252;
}
OCR1AH=0;
OCR1AL=PWM_LH; //OC1A輸出;
OCR1BH=0;
OCR1BL=PWM_RH; //OC1B輸出;
}
///////////////////////////////////PWM 計(jì)算
void PWM_calculate(void)
{
// PORTB|=(1<<6);
/* if (0x10==(PINB&1<<4) ) //前進(jìn)
{
Speed_Need=-4;
}
else if (0x20==(PINB&1<<5) ) //后退
{
Speed_Need=4;
}
else //不動(dòng)
{
Speed_Need=0;
}
*/
//position_dot=(speed_real_LH-speed_real_RH)*0.5; ///B
// position_dot=(-speed_real_LH-speed_real_RH)*0.5;///D
// position_dot=(speed_real_LH+speed_real_RH)*0.5; ///A
position_dot=(-speed_real_LH+speed_real_RH)*0.5; ///C
position_dot_filter*=0.85; //車輪速度濾波
position_dot_filter+=position_dot*0.15;
position+=position_dot_filter;
position+=Speed_Need;
position+=Turn_Need;
if (position<-768) //防止位置誤差過大導(dǎo)致的不穩(wěn)定
{
position=-768;
}
else if (position>768)
{
position=768;
}
PWM =-Kp_angle*angle-Kd_angle*angle_dot/*+Kp_position*position*/+Kd_position*(position_dot_filter-Speed_Need);
speed_output_RH = PWM+Turn_Need;
speed_output_LH = PWM-Turn_Need;
PWM_output (speed_output_LH,speed_output_RH);
}
////////////////////////////////////主程序
int main()
{//uchar a;
DDRB=0B11000000;
// PORTB=0;
DDRB &= ~(1<<0 | 1<<1|1<<2|1<<3|1<<4|1<<5);
PORTB |= 1<<0 | 1<<1|1<<2|1<<3|1<<4|1<<5;
DDRA=0;
PORTA=0;
DDRD=0B11110010;//這個(gè)地方不能加PIN,不然會(huì)出問題
DDRC |=((1<<PC0)|(1<<PC1));
PORTC|=((1<<PC0)|(1<<PC1));
TWBR=0x0a; //I2C 初始化,400kbps
TWSR|=(1<<TWPS0);
T1_initial();
T2_initial();
USART_Init();
// PIND=0X00;
// PORTD=0X00;
// PORTD|=~(1<<6);
// SFIOR|=1<<PUD;
INT_initial();
sei();
MPU_Init();
Kp_angle=mega16_ad(3)/10.0;
Kd_angle=mega16_ad(4)/250.0;
Kp_position=mega16_ad(5)/500.0;
Kd_position=mega16_ad(6)/5.0;
angle_t=mega16_ad(7)/5.3;
while(1)
{
if(flager==1)
{MPU_6050_Read(cdis);
AD_calculate();
/*flager=0;
AD_calculate();
PWM_calculate();
MPU_6050_Read(cdis);
speed_real_LH=0;//速度計(jì)數(shù)清零
speed_real_RH=0;
}*/
/*
Putc(0xfd);
Putc(0);
Putc(angle*2+120);
*/
Putc(0xff);
Putc(angle+128); //紅
Putc(angle_t+10);//綠
Putc(acc+128); //藍(lán)
}
}
return 0;
}
ISR(TIMER2_COMP_vect)//定時(shí)器2中斷服務(wù)函數(shù)
{
flager=1;
NUMBER++;
//MPU_6050_Read(cdis);
//AD_calculate();
}
ISR(INT0_vect)
{
if (0==(PINB&1<<0))
……………………
…………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
所有資料51hei提供下載:
Anyway2.0_新驅(qū)動(dòng)_客戶例程.zip
(96.57 KB, 下載次數(shù): 35)
2017-12-12 20:17 上傳
點(diǎn)擊文件名下載附件
程序
下載積分: 黑幣 -5
作者:
z741342386
時(shí)間:
2019-10-13 15:12
感謝上傳代碼
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1