标题:
智能车竞赛入门巡线代码分析-基于OV7620与STM32
[打印本页]
作者:
火鸟雪中飞
时间:
2021-7-18 20:41
标题:
智能车竞赛入门巡线代码分析-基于OV7620与STM32
本帖最后由 火鸟雪中飞 于 2021-7-30 20:50 编辑
经典的智能车入门基础代码(ov7620)
工程:IAR
单片机:stmf10x
使用人群:单片机初学者 智能车入门 智能车竞赛参与者
注意:体会智能车制作的软件入门思想 化为己用
下面是主函数
包括四个主要内容:
DataAnalyse(1) ----> 将图像二值化 单片机最后处理的就是黑点和白点
mygetLmr() --------> 横向扫描找出两条黑线的中点 即赛道的中线
SmoothMid() ------> 中线滤波 使其更平滑
Steer_control()
SpeedControl(420)-->偏差传递 舵机与电机PID控制
int main(void)
{
Init();
delay_ms(300);
while(1)
{
if(DataReadyFlag)
{
EXTI->IMR &=~(1<<5); //屏蔽中断
EXTI->IMR &=~(1<<6); //屏蔽中断
EXTI->PR |=(1<<5); //清楚悬挂标记位;
EXTI->PR |=(1<<6); //清楚悬挂标记位;
DataReadyFlag=0; //将标志位清零
DataAnalyse(1); //处理图像,滤波,二值化
mygetLmr(); //找到中线
SmoothMid() ; //平滑中线
Steer_control(); //控制舵机
SpeedControl(420);
// send_pic();
EXTI->IMR &=~(1<<5); //屏蔽中断
EXTI->IMR &=~(1<<6); //屏蔽中断
EXTI->IMR |=(1<<5); //开中断
}
}
}
复制代码
以下为中线处理函数
主要的思想就是单行点数查找 确定两侧黑白交接点位置 取两侧点中间值
但扫描方式有所不同
采用先向左找第一个点 再向右找第二个点 并扫描数行 形成中线
void mygetLmr()
{
u8 i=0;
u8 j=0;
u8 pLeft,pRight ;
u8 bFoundLeft = 0;
u8 bFoundRight = 0;
/// unsigned char TripLen = 4;
char bLeftEnd=0;
char bRightEnd=0;
char bMidEnd=0;
BlackLineData[R-1]=LastFieldMid1;
for (i=R-2;i>3&&bMidEnd!=1;i--)
{
//清零,以备下一行使用
bFoundLeft=0;
bFoundRight=0;
//向左扫描 找到左边界,没有找到黑线,左边界值设为1
for (pLeft=BlackLineData[i+1];pLeft>2;pLeft--)
{
if (*(Data+i*C+pLeft)==Black)
{
bFoundLeft=1;
Left[i]=pLeft;
pLeft=1;
}
}
if(bFoundLeft!=1) //若没有找到黑线,左边界值设为1
Left[i]=1;
//检测是否到了尽头
//向右扫描,找到右边界,若没有找到黑线,有边界值设为C-1
for (pRight=BlackLineData[i+1];pRight<C-2;pRight++)
{
if (*(Data+i*C+pRight)==Black)
{
bFoundRight=1;
Right[i]=pRight;
pRight=C;
}
}
if (bFoundRight!=1)//若没有找到黑线,有边界值设为C-1
Right[i]=C-1;
//求左右边界的中点,求得中线值
BlackLineData[i]=((Left[i]+Right[i]))/2;
if ((BlackLineData[i]>C-4)||BlackLineData[i]<4)
bMidEnd=1;
}
LastFieldMid1= BlackLineData[ R-5];
LastFieldMid2=BlackLineData[ R-6];
}
复制代码
进行平滑滤波原理较为简单 数组值循环平均即可 自行百度原理
void SmoothMid()
{
u8 i;
for (i=R-3;i>2;i--)
{
if (Abs8(BlackLineData[i]-BlackLineData[i-1])>5&& Abs8(BlackLineData[i]-BlackLineData[i+1])>5 )
BlackLineData[i]=(BlackLineData[i-1]+BlackLineData[i+1] )/2;
}
}
复制代码
对于控制部分只是简单的实现PID让车动起来,对于真正参加比赛还需要学弟学妹们自己努力调试
void Steer_control(void)
{
u8 kp,kd,ki;
s16 steererr = 0;
Err=(BlackLineData[7]+BlackLineData[8]+BlackLineData[9]+BlackLineData[10]+BlackLineData[11])/5-45;
//简单PID编写
kp=2; //P控制
kd=0; //D控制
ki=0; //I控制
steererr = kp*Err;
Steerangle = STRM-steererr;
////舵机限位,很重要,此代码不能删除
if(Steerangle<=STRL) Steerangle=STRL;
if(Steerangle>=STRR) Steerangle=STRR;
//设置PWM占空比,控制舵机
SpeedControl(Steerangle);
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1