标题:
K60_CCD直立小车源码(二等奖程序)
[打印本页]
作者:
zoulichuan
时间:
2018-5-10 21:07
标题:
K60_CCD直立小车源码(二等奖程序)
k60 ccd二等奖程序
本程序配套4按键直立一体板
按键功能:
E0: 参数加
E1: 参数减
E2: 切换显示及功能
E3: 回到最初显示及功能
调试直立
A、修改直立静态偏移量: calcultion.c s32 GRAVITY_OFFSET=485;//230 MPU6550为平衡时Z轴角度,放大10倍
B、main.c里 run()函数中: 修改 PWMout=MotorSpeedOut(AAngPWM,MotorSpeedPWM,MotorTurnPWM);//电机输出
为: PWMout=MotorSpeedOut(AAngPWM,0,0);//关闭速度环和转向环分量,直立后再加上两个分量
系统连线说明 :
0.png
(18.88 KB, 下载次数: 69)
下载附件
2018-5-12 06:06 上传
0.png
(11.31 KB, 下载次数: 73)
下载附件
2018-5-12 06:06 上传
单片机源程序如下:
#include "include.h"
#include "calculation.h"
#include"VisualScope.h"
#include "CCD.h"
#include "LQ12864.h"
#include "MPU6050.h"
int16 angletmp,angle_g,angle_w; //16位
int16 angle6550; //MPU6550计算
extern byte F6x8[][6];
extern s16 g_nLeftMotorPulseSigma,g_nRightMotorPulseSigma;
extern float GYROSCOPE_ANGLE_RATIO;
s32 TurnPosition;//实际位置
s32 TurnPositionOld; //上一次位置
int dline; //左右边界差
float ANGLE_CONTROL_P=240;//* 260 //直立P 260
float ANGLE_CONTROL_D=30;//1.5;//* 4.8 //直立D 5.8
int16 xgout=1000; //MPU6050六轴参数 x轴角速度
int16 ygout=1000;
int16 zgout=1000;
int16 xaout=-1000; //x轴加速度
int16 yaout=-1000;
int16 zaout=-1000;
uint8 PWMDEADL = 0; //死区电压左路电机
uint8 PWMDEADR = 0; //死区电压右路电机
uint16 MAXTURNPWM= 200; //电机转向最大PWM值
#define SAVEADRESS (0X1C)
extern s32 GRAVITY_OFFSET;
uint8 disen; //允许上传CCD图像
uint16 A_P,A_D,V_P,V_I,T_P,T_D; //从FLASH中读出的参数
uint32 G_RATIO;
uint8 flashreadbuf[6];
u16 SpeedKP = 24;//4.4;//* //速度P 放大10倍
u16 SpeedKI = 6;//* //速度D 放大10倍
u16 TurnP1 = 80; //直道前进时舵机PD值,放大10倍
u16 TurnD1 = 2;
//u16 TurnP2 = 34;//70; //弯道时舵机转角比例系数 放大10倍
//u16 TurnD2 = 140;//30; //弯道时舵机转角积分系数 放大100倍
//
//u16 TurnP3 = 40; //大弯时转角比例
//u16 TurnD3 = 110; //大弯时转角积分
//
//u16 TurnP4 = 48; //大弯时转角比例
//u16 TurnD4 = 90; //大弯时转角积分
u16 TurnP; //* 94 //方向P
u16 TurnD; //* 8.4 //方向D
u16 turnsetmax; //转向最大PWM值
u16 turnpwmmax;
u8 disccd[128][4];
u8 paraadjflag; //参数修改组切换
extern int leftline, rightline; //左右边界值
extern int leftlineold,rightlineold; //左右边界上一次值
extern int yuzhizhi;//动态阈值
extern signed int sumlspeed,sumrspeed;
s16 SetSpeed= -250;
s16 AmSpeed;//* //目标速度 用于外部 设置速度时在这里设置
s16 g_Speedgoal=0;//用于内部 自加速使用
//时间标志位
extern u8 TIME0flag_5ms,TIME0flag_10ms,TIME0flag_20ms;
extern u8 TIME1flag_100ms,flag_1ms ;
extern u8 TIME1flag_1s ; //PT1口1s定时标志位
extern s16 whitelength;//91; //具体看CCD图像,赛道宽度
s32 ATimeCount=700;//100ms进入标志 由20个5ms构成,速度PID时使用
s32 TimeCount=0 ;//1ms中断标志
//角度传感器
s32 GYROSCOPE_OFFSET,GYROSCOPE_turn_OFFSET;//陀螺仪静止时的零点
s32 AD_ACC_Z;//加速度计的Z轴
s32 AD_GYRO;//平衡陀螺仪
s32 AD_GYRO_turn;//转向陀螺仪
s32 AAngPWM=0,LastAAngPWM=0,AAngPeriodCount=0,MotorAAngPWM=0 ;
//速度变量
float g_SpeedControlOutNew,g_SpeedControlOutOld ;
s16 SpeedPeriodCount=0;
s32 MotorSpeedPWM=0 ;
s32 PWMout ;
int start_flag=0,stop_jiasu=0;
//CCD变量
int ccd_count=0;
uint8_t Pixel[128];
int ccd_flag=0;
s16 TurnPeriodCount=0 ;
s32 MotorTurnPWM=0 ;
s16 TurnPWMOUT=0 ;
s16 LastTurnPWMOUT=0;
u16 discnt;
u8 workflag;
void run();//直立主函数
void qibu();//起步不能一下把速度加上去,速度要慢慢加
void GPIO_Init();
void dispage1();
void dispage2();
void dispage3();
void disdata1();
void disdata2();
void disdata3();
void disccdval();
extern void Pause(void);
extern void LCD_CLS(void);
void main()
{ int16 ii;
discnt=0;
paraadjflag=0;
workflag=0;
AmSpeed = SetSpeed;
turnsetmax = 650;
s32 xgtemp,ygtemp;
DisableInterrupts; //禁止总中断
uart_init (UART0,115200);//初始化UART0,输出脚PTA15,输入脚PTA14
//AngleAcceleration_init() ;//AD初始化
FTM1_QUAD_Iint();//正交解码测速 A相---PTA8 B相---PTA9
FTM2_QUAD_Iint();//正交解码测速 A相---PTA10 B相---PTA11
oled_init();//oled初始化
CCD_init (); //CCD初始化
GPIO_Init(); //程序运行灯
pit_init_ms(PIT0, 1); //初始化PIT0,定时时间为: 1ms
pit_init_ms(PIT1, 100);//初始化PIT1,定时时间为: 100ms
FTM_init() ; //PWM初始化
delayms(100);
MPU6050_Init(); //MPU6050初始化 , PD8 , PD9
delayms(300);
xgtemp=0;
ygtemp=0;
TurnP=TurnP1;
TurnD=TurnD1;
for(ii=0;ii<100;ii++)
{
xgtemp += MPU6050_GetDoubleData(MPU6050_GYRO_XOUT);//读X轴角速度,直立
Pause();
ygtemp += MPU6050_GetDoubleData(MPU6050_GYRO_YOUT);//读Y轴角速度,转向
Pause();
}
GYROSCOPE_OFFSET = xgtemp/100; //静态X轴角速度值,直立,理论上为0,但实际可能不为0
GYROSCOPE_turn_OFFSET = ygtemp/100; //静态Y轴角速度值,转向,理论上为0,但实际可能不为0
EnableInterrupts;//开总中断
uart_irq_EN(UART0);
uart_putchar(UART0,'O');
uart_putchar(UART0,'K');
A_P = ANGLE_CONTROL_P;
A_D = ANGLE_CONTROL_D*10;
V_P = SpeedKP;
V_I = SpeedKI;
T_P = TurnP;
T_D = TurnD;
G_RATIO = GYROSCOPE_ANGLE_RATIO*100;
LCD_CLS();
dispage1(); //正常显示
while(1)
{
if(workflag==0) //正常状态
{ if(gpio_get(PORTE,3)==0) //状态切换
{ delayms(4);
if(gpio_get(PORTE,3)==0)
{
workflag=1;
LCD_CLS(); //清屏
dispage2();
while(gpio_get(PORTE,3)==0); //等待按键松开
}
}
discnt++;
if(discnt>=100)
{ discnt=0;
disdata1();
delayms(2);
}
delayms(1);
}
else if(workflag==1) //显示和上传CCD图像
{ if(ccd_flag==1)//采完一副图像
{
ccd_flag=0;
tuxiang(); //红树伟业上位机
discnt++;
if(discnt>=100)
{ discnt=0;
disdata2(); //显示图像
disccdval();
delayms(1);
}
}
if(gpio_get(PORTE,3)==0) //状态切换
{ delayms(4);
if(gpio_get(PORTE,3)==0)
{
workflag=2;
LCD_CLS(); //清屏
dispage3();
while(gpio_get(PORTE,3)==0); //等待按键松开
}
}
if(gpio_get(PORTE,2)==0) //回正常状态
{ delayms(4);
if(gpio_get(PORTE,2)==0)
{
workflag=0;
LCD_CLS(); //清屏
dispage1();
while(gpio_get(PORTE,5)==0); //等待按键松开
}
}
}
else if(workflag==2) //调节参数
{ if(gpio_get(PORTE,3)==0) //修改参数变换
{ delayms(4);
if(gpio_get(PORTE,3)==0)
{
paraadjflag++;
if(paraadjflag==5) paraadjflag=0; // 切换。如果有更多的参数组,自行修改
if(paraadjflag==0)
{ LCD_P6x8Str(0,1,"Speed Para: <--");
LCD_P6x8Str(0,3,"Turn Para: ");
LCD_P6x8Str(0,5,"Speed Set: ");
}
else if(paraadjflag==1)
{ LCD_P6x8Str(0,1,"Speed Para: -->");
LCD_P6x8Str(0,3,"Turn Para: ");
LCD_P6x8Str(0,5,"Speed Set: ");
}
else if(paraadjflag==2)
{ LCD_P6x8Str(0,1,"Speed Para: ");
LCD_P6x8Str(0,3,"Turn Para: <--");
LCD_P6x8Str(0,5,"Speed Set: ");
}
else if(paraadjflag==3)
{ LCD_P6x8Str(0,1,"Speed Para: ");
LCD_P6x8Str(0,3,"Turn Para: -->");
LCD_P6x8Str(0,5,"Speed Set: ");
}
else if(paraadjflag==4)
{ LCD_P6x8Str(0,1,"Speed Para: ");
LCD_P6x8Str(0,3,"Turn Para: ");
LCD_P6x8Str(0,5,"Speed Set: <--");
}
while(gpio_get(PORTE,3)==0); //等待按键松开
}
}
if(gpio_get(PORTE,2)==0) //回正常状态
{ delayms(4);
if(gpio_get(PORTE,2)==0)
{
workflag=0;
LCD_CLS(); //清屏
dispage1();
while(gpio_get(PORTE,2)==0); //等待按键松开
}
}
if(gpio_get(PORTE,0)==0) //参数调节
{ delayms(4);
if(gpio_get(PORTE,0)==0)
{ if(paraadjflag==0) //速度KP 加减
{ SpeedKP++;
Dis_num(24,2,SpeedKP);
}
else if(paraadjflag==1)
{ SpeedKI++;
Dis_num(90,2,SpeedKI);
}
else if(paraadjflag==2)
{ turnsetmax=turnsetmax+5;
Dis_num(24,4,turnsetmax);
}
else if(paraadjflag==3)
{ TurnD++;
Dis_num(90,4,TurnD);
}
else if(paraadjflag==4) //速度
{ SetSpeed = SetSpeed - 5;
AmSpeed = SetSpeed;
Dis_num(24,6,SetSpeed);
}
while(gpio_get(PORTE,0)==0); //等待按键松开
}
}
if(gpio_get(PORTE,1)==0) //参数调节
{ delayms(4);
if(gpio_get(PORTE,1)==0)
{
if(paraadjflag==0) //速度KP 加减
{ SpeedKP--;
Dis_num(24,2,SpeedKP);
}
else if(paraadjflag==1)
{ SpeedKI--;
Dis_num(90,2,SpeedKI);
}
else if(paraadjflag==2)
{ turnsetmax=turnsetmax-5;
Dis_num(24,4,turnsetmax);
}
else if(paraadjflag==3)
{ TurnD--;
Dis_num(90,4,TurnD);
}
else if(paraadjflag==4) //速度
{ SetSpeed = SetSpeed + 5;
Dis_num(24,6,SetSpeed);
AmSpeed = SetSpeed;
}
while(gpio_get(PORTE,1)==0); //等待按键松开
}
}
delayms(5);
}
}
}
void GPIO_Init()
{
gpio_init (PORTA, 17, GPO, 1u); //初始化PTE0为高电平输出---LED0
gpio_set (PORTA, 19, 0); //设置PTE0为高电平输出,LED0灭
gpio_init (PORTE,0,GPI,0); //按键输入
gpio_init (PORTE,1,GPI,0); //按键输入
gpio_init (PORTE,2,GPI,0); //按键输入
gpio_init (PORTE,3,GPI,0); //按键输入
}
void run()//直立函数 在isr.c中的1ms中断中调用 PIT0_IRQHandler
{
TimeCount++ ;
SpeedPeriodCount++;
TurnPeriodCount ++ ;
AAngPeriodCount ++ ;
if(AAngPeriodCount>=4) AAngPeriodCount=4;
MotorTurnPWM = TurnPWMOut(TurnPWMOUT,LastTurnPWMOUT,TurnPeriodCount) ;
MotorSpeedPWM = SpeedPWMOut(g_SpeedControlOutNew ,g_SpeedControlOutOld,SpeedPeriodCount);
MotorAAngPWM = AAangPWMOut(AAngPWM ,LastAAngPWM ,AAngPeriodCount);
Checkcarstate();//开启停止判断
if(TimeCount>=5)//读速度 5ms
{
TimeCount=0;
GetMotorPulse();//读速度脉冲
}
else if(TimeCount == 1)//读取MPU6050
{
xaout=MPU6050_GetDoubleData(MPU6050_ACCEL_XOUT);//读X轴加速度
yaout=MPU6050_GetDoubleData(MPU6050_ACCEL_YOUT);//读X轴加速度
zaout=MPU6050_GetDoubleData(MPU6050_ACCEL_ZOUT);//读X轴加速度
xgout=MPU6050_GetDoubleData(MPU6050_GYRO_XOUT);//读X轴角速度,直立角速度
ygout=MPU6050_GetDoubleData(MPU6050_GYRO_YOUT);//读Y轴角速度,转向角速度
angle6550=MPU6050_Get_Angle(xaout,yaout,zaout,0);
}
else if(TimeCount == 2)//5ms 直立滤波,控制
{
AAngPeriodCount = 0;
AngleCalculate();//计算加速值和角度值
LastAAngPWM = AAngPWM ;
AAngPWM = AngleControl() ; //计算平衡电机速度
PWMout=MotorSpeedOut(AAngPWM,MotorSpeedPWM,MotorTurnPWM);//电机输出
//PWMout=MotorSpeedOut(0,0,MotorTurnPWM);
//PWMout=MotorSpeedOut(AAngPWM,MotorSpeedPWM,0);//电机输出 刚开始用的时候可以把MotorSpeedPWM和MotorTurnPWM都设为0
//PWMout=MotorSpeedOut(AAngPWM,0,0);//电机输出 刚开始用的时候可以把MotorSpeedPWM和MotorTurnPWM都设为0
//先调直立,再加速度MotorSpeedPWM,最后加方向MotorTurnPWM
}
else if(TimeCount == 3)//5ms 速度PI调节
{
ATimeCount ++ ;
if(ATimeCount >= 20)//20*5=100ms进行一次速度PID调节
{
ATimeCount=0;
SpeedPID() ;
SpeedPeriodCount = 0 ;
qibu();//起步 不可以一下就把速度加上,要缓慢加
}
}
else if(TimeCount == 4)// CCD图像采集与处理
{
ccd_count++;
if(ccd_count>=4)//20ms进一次
{
ccd_count=0;
ccd_flag=1;//发送图像到上位机标志
ImageCapture(Pixel) ;//将捕捉到的图像放在Pixel数组中
//process();//图像处理函数
FindLine();
dline = rightline - leftline;
if((dline>64)||(dline<12)) //十字路或桥上
{ //TurnP = TurnP1;
//TurnD = TurnD1;
turnpwmmax=turnsetmax;
}
else if((dline>(whitelength+16))||(dline<(whitelength-16))) //丢线
{ turnpwmmax=turnsetmax+50;
//TurnD = TurnD4;
}
else if((dline>(whitelength+9))||(dline<(whitelength-9))) //60度弯道
{ //TurnP = TurnP4;
//TurnD = TurnD4;
turnpwmmax=turnsetmax+30;
}
else if((dline>(whitelength+4))||(dline<(whitelength-4))) //50度弯道
{ //TurnP = TurnP3;
//TurnD = TurnD3;
turnpwmmax=turnsetmax+20;
}
else if((dline>(whitelength+2))||(dline<(whitelength-2))) //亚直道
{ //TurnP = TurnP2;
//TurnD = TurnD2;
turnpwmmax=turnsetmax;
}
else //直道
{ //TurnP = TurnP1;
//TurnD = TurnD1;
turnpwmmax=turnsetmax;
}
LastTurnPWMOUT = TurnPWMOUT ;
TurnPWM() ;
TurnPeriodCount = 0 ;
}
}
if(TIME1flag_1s == 1)//程序运行灯
{
TIME1flag_1s = 0 ;
PTA17_OUT = ~PTA17_OUT ;
}
}
void qibu()//这一部分认真看一下,也可以根据自己的想法改一下
{
if(AmSpeed!=0)//在目标速度不为0时才运行
{
start_flag++;
if(start_flag<30)//静止2S才出发 可根据规则修改
{ g_Speedgoal=0;
//SpeedKI=0;
}
else if(start_flag>=30)
{
if(g_Speedgoal>AmSpeed&&stop_jiasu==0)//然后逐渐加速
{
g_Speedgoal-=15; // 30 //单次加速值,值大加速能力强,比赛前可设两组值,一组快速加速,用于应对起步时是长
//直道的情况,另一组为慢加速,用于应对起步时就是弯道的情况
}
else if(g_Speedgoal<=AmSpeed&&stop_jiasu==0) //内部速度高于设置速度,停止大幅度加速,进行小幅度调整加速
{
g_Speedgoal=AmSpeed;
stop_jiasu=1;
}
start_flag=3000; //终止静止2s计数
//SpeedKI=0;
if(stop_jiasu==1) //车模之后的目标速度调整主要在此函数中
{
if(g_Speedgoal>AmSpeed)//然后逐渐加速
{
g_Speedgoal-=15;//
}
else if(g_Speedgoal<=AmSpeed)
{
g_Speedgoal=AmSpeed;
}
}
}
}
}
void dispage1()
{ Dis_num(0,0,GRAVITY_OFFSET); //设定值,垂直时加速度AD
Dis_num(42,0,GYROSCOPE_OFFSET);//陀螺仪零偏 自检平均值
LCD_P6x8Str(0,1,"Ap:");
Dis_num(20,1,A_P);//加计零偏 定值
LCD_P6x8Str(60,1,"Ad:");
Dis_num(80,1,A_D);
LCD_P6x8Str(0,2,"Vp:");
Dis_num(20,2,V_P);
LCD_P6x8Str(60,2,"Vd:");
Dis_num(80,2,V_I);
LCD_P6x8Str(0,3,"Tp:");
Dis_num(20,3,T_P);
LCD_P6x8Str(60,3,"Td:");
Dis_num(80,3,T_D);
LCD_P6x8Str(0,4,"A S C");
LCD_P6x8Str(0,5,"Spd");
LCD_P6x8Str(1,7,"LMB:");
LCD_P6x8Str(64,7,"RMB:");
}
void disdata1()
{ Dis_num(6,4,angletmp);
Dis_num(48,4,-AmSpeed);
Dis_num(90,4,TurnPosition);
A_P = ANGLE_CONTROL_P;
A_D = ANGLE_CONTROL_D*10;
V_P = SpeedKP;
V_I = SpeedKI;
T_P = TurnP;
T_D = TurnD;
Dis_num(20,1,A_P);//加计零偏 定值
//Dis_num(80,1,A_D);
Dis_num(80,1,TurnPWMOUT);
Dis_num(20,2,V_P);
Dis_num(80,2,V_I);
Dis_num(20,3,T_P);
Dis_num(80,3,T_D);
delayms(50);
Dis_num(10,6,leftlineold); //赛道左边界
Dis_num(94,6,rightlineold); //赛道右边界
Dis_num(52,6,dline); //赛道右-左
Dis_num(28,7,sumlspeed);
Dis_num(96,7,sumrspeed);
Dis_num(20,5,AmSpeed);
Dis_num(80,5,turnsetmax);
}
void dispage2()
{ LCD_P6x8Str(0,0,"CCD DATA UP&DIS");
LCD_P6x8Str(0,1,"L: R:");
Dis_num(20,1,leftlineold); //赛道左边界
Dis_num(94,1,rightlineold); //赛道右边界
}
void disdata2()
{ Dis_num(20,1,leftlineold); //赛道左边界
Dis_num(94,1,rightlineold); //赛道右边界
}
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
K60_CCD直立.rar
(13.35 MB, 下载次数: 55)
2018-5-10 21:07 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
admin
时间:
2018-5-12 06:08
好资料,51黑有你更精彩!!!
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1