直立平衡车包括,直立还,速度环,和CCD循迹设计。
定时器产生中断,第1毫秒进行加速剂陀螺仪AD采样,第2毫秒进行角度融合,PWM控制输出,第3毫秒进行直立速度融合,第4ms进行CCD循迹方向控制。
/***************************************
Copyright:Electronic innovation laboratory
Author:niub
Date:2016-12-21
Version:V1.2
Description: the software of Freescale Carle photoelectric vertical design
****************************************/
#include "includes.h"
#include "math.h"
#include "HAL_GPIO.h"
#define STATIC_ADC_RESULT_X 0
#define STATIC_ADC_RESULT_Y 0
void init_gpio(void);
void init_offset();
void bianmaqi(void);
void SpeedControl(void);
void SpeedControlOutput(void);
void DirectionControl();
void DirectionControlOutput();
void MotorOutput() ;
extern uint8 IntegrationTime ;
extern void StartIntegration(void);
/*********************************************************************************/
void delay(void);
int16 adc_get_ave(ADCx, uint8, uint16);
int16 adc_result_to_velocity(int16);
float pwm1,pwm2;
float P;
float d;
/*********************CCD的参数定义********************************/
uint8 AtemP ;
uint8 Pixel[128];
uint8 send_data_cnt = 0;
uint8 *pixel_pt;
volatile uint8 k;
uint8 TIME0flag_5ms;
uint8 TIME0flag_10ms;
uint8 TIME0flag_15ms;
uint8 TIME0flag_20ms;
uint8 TIME1flag_20ms;
uint8 TIME1flag_1ms;
extern uint8 TimerFlag20ms;
/******************************************************/
int count2=0;
void main(void)
{
sysinit ();
init_gpio();
LPLD_ADC_Init(ADC0, MODE_10, CONV_SING);
void LCD_Init(void);
delay();
LPLD_PIT_Init(PIT0, 1000, pit_isr0);
LPLD_FTM0_PWM_Init(10000);
LPLD_FTM1_PWM_Init(100);
LPLD_FTM1_PWM_Open(0,0);
LPLD_FTM0_PWM_Open(0,0);
LPLD_FTM0_PWM_Open(1,0);
LPLD_FTM0_PWM_Open(2,0);
LPLD_FTM0_PWM_Open(3,0);
FTM1_QUAD_Iint();
FTM2_QUAD_Iint();
CCD_init1();
pixel_pt = Pixel;
for(k=0; k<128+10; k++)
{
*pixel_pt++ = 0;
}
while(1)
{
/**************************CCD程序**发送给上位机***************************************************************/
if(TIME1flag_20ms == 1)
{
TIME1flag_20ms = 0 ;
ImageCapture(Pixel);
CalculateIntegrationTime();
if(++send_data_cnt >= 5)
{
send_data_cnt = 0;
SendImageData(Pixel);
}
/**********
计算黑线位置
**********/
CCD_handle();
Delay_us(100000);
LCD_clear();
Delay_us(100000);
LCD_write_english_string(24,0,"LANDZO");
LCD_write_english_string(24,1,"tangwenkai");
printf("mid_line[2]=%d
",mid_line[2]);
printf("mid_line[3]=%d
",mid_line[3]);
printf("Left=%d
",Left_point);
printf("Right=%d
",Right_point);
}
}
}
/*******************************************进入中断处理程序***********************************************/
void pit_isr0()
{
static int event_count;
g_nSpeedControlPeriod ++;
SpeedControlOutput();
g_nDirectionControlPeriod ++;
DirectionControlOutput();
/***************************************线性CCD自适应曝光******************************/
static unsigned char TimerCnt20ms = 0;
static unsigned char TimerCnt10ms =0;
uint8 integration_piont;
TIME1flag_1ms = 1 ;
TimerCnt20ms++;
TimerCnt10ms++;
count2++;
integration_piont = 20- IntegrationTime;
if(integration_piont >= 2) {
if(integration_piont == TimerCnt20ms)
StartIntegration();
}
if(TimerCnt20ms >= 20) {
TimerCnt20ms = 0;
TIME1flag_20ms = 1;
}
if(event_count >= 5)
{
event_count = 0 ;
bianmaqi();
}
else if(event_count == 1)
{
Adc0_Result=adc_get_ave(ADC0, 10, 20);
Adc1_Result=adc_get_ave(ADC0, 9, 20);
Adc2_Result=LPLD_ADC_SE_Get(ADC0, 12);
}
else if(event_count == 2)
{
}
else if(event_count == 3 )
{
}
else if(event_count == 4)
{
}
event_count ++;
}
/*******************************电机输出函数*********************************************************/
void MotorOutput(void)
{
g_fLeftMotorOut = pwm1- g_fSpeedControlOut+ g_fDirectionControlOut ;
g_fRightMotorOut = pwm1- g_fSpeedControlOut- g_fDirectionControlOut;
if(g_fLeftMotorOut>6000)g_fLeftMotorOut=6000;
if(g_fLeftMotorOut<-6000)g_fLeftMotorOut=-6000;
if(g_fRightMotorOut>6000) g_fRightMotorOut=6000;
if(g_fRightMotorOut<-6000) g_fRightMotorOut=-6000;
if(g_fLeftMotorOut>=0)
{
LPLD_FTM0_PWM_ChangeDuty(0,(int)(g_fLeftMotorOut));
LPLD_FTM0_PWM_ChangeDuty(1,0);
}
else if(g_fLeftMotorOut<0)
{
LPLD_FTM0_PWM_ChangeDuty(1,(int)(-g_fLeftMotorOut));
LPLD_FTM0_PWM_ChangeDuty(0,0);
}
if(g_fRightMotorOut>=0)
{
LPLD_FTM0_PWM_ChangeDuty(2,(int)(g_fRightMotorOut));
LPLD_FTM0_PWM_ChangeDuty(3,0);
}
else if(g_fRightMotorOut<0)
{
LPLD_FTM0_PWM_ChangeDuty(3,(int)(-g_fRightMotorOut));
LPLD_FTM0_PWM_ChangeDuty(2,0);
}
}
void init_gpio()
{
LPLD_GPIO_Init(PTD, 15, DIR_OUTPUT, OUTPUT_L, IRQC_DIS);
LPLD_GPIO_Init(PTC, 0, DIR_OUTPUT, OUTPUT_H, IRQC_DIS);
LPLD_GPIO_Init(PTA, 17, DIR_OUTPUT, OUTPUT_H, IRQC_DIS);
LPLD_GPIO_Init(PTE, 26, DIR_OUTPUT, OUTPUT_H, IRQC_DIS);
}
void delay()
{
unsigned int i, n;
for(i=0;i<10000;i++)
{
for(n=0;n<800;n++)
{
asm("nop");
}
}
}
int16 adc_get_ave(ADCx adc, uint8 channel, uint16 cnt)
{
uint32 tmp=0;
uint8 i;
for(i=cnt; i>0; i--)
{
tmp += LPLD_ADC_SE_Get(adc, channel);
}
tmp /= cnt;
return (int16)tmp;
}
//part of CCD design
#include “includes.h”
/********************“CCD定义*****************************************/
int Mid_line_average;
float CCD_center =64;
unsigned char Mid_line=64; //CCD提取中线
unsigned char Left_Flag,Right_Flag;
unsigned char left_flag[3]={0,0,0};
unsigned char right_flag[3]={0,0,0};
unsigned char mid_line[4] = { 0,0,0,0};
unsigned char PRE_left_point[4]={0,0,0,0};
unsigned char PRE_right_point[4]={0,0,0,0};
//unsigned char pre_Mid_line;
//unsigned int Mid_line_sum;
unsigned char farlength=0;//定义白 {MOD}区域的宽度,初始时为零
unsigned char Right_point;
unsigned char Left_point;
unsigned char Left_num = 74;//这两个值可以看情况而定
unsigned char Right_num = 54;
unsigned char pre_Right_point;
unsigned char pre_Left_point;
unsigned int Threshold_Value;
//赛道判别
unsigned char startline_Flag=0;
unsigned int stop_Flag=0;
unsigned char white=0;
unsigned char black=0;
int Average=0;
unsigned int MIN_pixel,MAX_pixel;
unsigned char pixel3_pt[128]; // 取阀值转换用
unsigned char pixel_pt2[128];
unsigned int Flag_Threshold = 0; //取阀值
unsigned char data_pixel[128];
/* 128个像素点的平均AD值 */
unsigned char PixelAverageValue;
/* 128个像素点的平均电压值的10倍 */
unsigned char PixelAverageVoltage;
uint8 CCDCompleteFlag=0;
/***************************************************************
* 蓝宙电子工作室
*
* 函数名称:CCD_init
* 功能说明:CCD初始化
* 参数说明:
* 函数返回:无
* 修改时间:2012-10-20
* 备 注:
***************************************************************/
void CCD_init1(void)
{
LPLD_GPIO_Init(PTE, 0, DIR_OUTPUT, OUTPUT_H, IRQC_DIS); //gpio_init (PORTE , 4, GPO,HIGH);
LPLD_GPIO_Init(PTE, 2, DIR_OUTPUT, OUTPUT_H, IRQC_DIS); //gpio_init (PORTE , 5, GPO,HIGH);
LPLD_ADC_Init(ADC1, MODE_8, CONV_SING);//ADC1采集数据初始化。。。// adc_init(ADC1, AD6b) ;
}
/***************************************************************
* 蓝宙电子工作室
*
* 函数名称:StartIntegration
* 功能说明:CCD启动程序
* 参数说明:
* 函数返回:无
* 修改时间:2012-10-20
* 备 注:
***************************************************************/
void StartIntegration(void) {
unsigned char i;
SI_SetVal(); /* SI = 1 */
SamplingDelay();
CLK_SetVal(); /* CLK = 1 */
SamplingDelay();
SI_ClrVal(); /* SI = 0 */
SamplingDelay();
CLK_ClrVal(); /* CLK = 0 */
for(i=0; i<127; i++) {
SamplingDelay();
SamplingDelay();
CLK_SetVal(); /* CLK = 1 */
SamplingDelay();
SamplingDelay();
CLK_ClrVal(); /* CLK = 0 */
}
SamplingDelay();
SamplingDelay();
CLK_SetVal(); /* CLK = 1 */
SamplingDelay();
SamplingDelay();
CLK_ClrVal(); /* CLK = 0 */
}
/***************************************************************
* 蓝宙电子工作室
*
* 函数名称:ImageCapture
* 功能说明:CCD采样程序
* 参数说明:* ImageData 采样数组
* 函数返回:无
* 修改时间:2012-10-20
* 备 注:
*ImageData = ad_once(ADC1, AD6a, ADC_8bit);
***************************************************************/
void ImageCapture(unsigned char * ImageData) {
unsigned char i;
extern uint8 AtemP ;
SI_SetVal(); /* SI = 1 */
SamplingDelay();
CLK_SetVal(); /* CLK = 1 */
SamplingDelay();
SI_ClrVal(); /* SI = 0 */
SamplingDelay();
`这里写代码片`for(i = 0; i < 250; i++) { //更改250,让CCD的图像看上去比较平滑,
SamplingDelay() ; //200ns //把该值改大或者改小达到自己满意的结果。
}
*ImageData = LPLD_ADC_SE_Get(ADC1 , 5); //取得PTE1引脚的AD值。。//ad_once(ADC1, AD6b, ADC_8bit);
ImageData ++ ;
CLK_ClrVal(); /* CLK = 0 */
for(i=0; i<127; i++) {
SamplingDelay();
SamplingDelay();
CLK_SetVal(); /* CLK = 1 */
SamplingDelay();
SamplingDelay();
*ImageData =LPLD_ADC_SE_Get(ADC1,5);// ad_once(ADC1, AD6b, ADC_8bit);
ImageData ++ ;
CLK_ClrVal(); /* CLK = 0 */
}
SamplingDelay();
SamplingDelay();
CLK_SetVal(); /* CLK = 1 */
SamplingDelay();
SamplingDelay();
CLK_ClrVal(); /* CLK = 0 */
}
/***************************************************************
* 蓝宙电子工作室
*
* 函数名称:CalculateIntegrationTime
* 功能说明:计算曝光时间
* 参数说明:
* 函数返回:无
* 修改时间:2012-10-20
* 备 注:
***************************************************************/
/* 曝光时间,单位ms */
uint8 IntegrationTime = 10;
/* 128个像素点的平均电压值的10倍 */
uint8 PixelAverageVoltage;
/* 设定目标平均电压值,实际电压的10倍 */
int16 TargetPixelAverageVoltage = 25;
/* 设定目标平均电压值与实际值的偏差,实际电压的10倍 */
int16 PixelAverageVoltageError = 0;
/* 设定目标平均电压值允许的偏差,实际电压的10倍 */
int16 TargetPixelAverageVoltageAllowError = 2;
void CalculateIntegrationTime(void) {
/* 计算128个像素点的平均AD值 */
PixelAverageValue = PixelAverage(128,Pixel);
/* 计算128个像素点的平均电压值,实际值的10倍 */
PixelAverageVoltage = (unsigned char)((int)PixelAverageValue * 25 / 194);
PixelAverageVoltageError = TargetPixelAverageVoltage - PixelAverageVoltage;
if(PixelAverageVoltageError < -TargetPixelAverageVoltageAllowError)
{
PixelAverageVoltageError = 0- PixelAverageVoltageError ;
PixelAverageVoltageError /= 2;
if(PixelAverageVoltageError > 10 )
PixelAverageVoltageError = 10 ;
IntegrationTime -= PixelAverageVoltageError;
}
if(PixelAverageVoltageError > TargetPixelAverageVoltageAllowError)
{
PixelAverageVoltageError /= 2;
if(PixelAverageVoltageError > 10 )
PixelAverageVoltageError = 10 ;
IntegrationTime += PixelAverageVoltageError;
}
if(IntegrationTime <= 1)
IntegrationTime = 1;
if(IntegrationTime >= 100)
IntegrationTime = 100;
}