之前准备电赛的时候,找滚球的程序很费劲,找了很久终于找到一个不收费的了
板球系统网上的标配是:
stm32f4+ov2640或7725或7760+液晶彩屏(方便调试),具体的我就不在赘述了,网上帖子很多,这里单纯的分享资源,希望方便有需要的人,
系统基于原子的探索者f4+ov2640,软件二值化.
单片机源程序如下:
- #include "sys.h"
- #include "delay.h"
- #include "usart.h"
- #include "led.h"
- #include "key.h"
- #include "lcd.h"
- #include "usmart.h"
- #include "usart2.h"
- #include "timer.h"
- #include "ov2640.h"
- #include "dcmi.h"
- #include "string.h"
- #include "pwm.h"
- u16 rgb_buf[144][176];
- u16 gray,Have=0,SY=0,time=0;
- extern u8 flag;
- u16 hang=0,time1=0;
- u8 X_MAX,Y_MAX=0; //小球的坐标信息
- u8 X_MAX_LSAT, X_MIN_LSAT, Y_MAX_LSAT, Y_MIN_LSAT=0; //上一次小球坐标位置信息
- u8 X,Y=0; //小球的质心信息
- u8 X_MIN,Y_MIN=180;
- unsigned char ax,ay;
- int PWM_X,PWM_Y=0;
- float Err_X,Err_Y=0;
- float Err_X_LAST,Err_Y_LAST=0;
- float Aim_X,Aim_Y=0;
- float Kp,Ki,Kd=0;
- //ALIENTEK 探索者STM32F407开发板 实验35
- //摄像头 实验 -库函数版本
- //技术支持:www.openedv.com
- //淘宝店铺:http://eboard.taobao.com
- //广州市星翼电子科技有限公司
- //作者:正点原子 @ALIENTEK
- //JPEG尺寸支持列表
- const u16 jpeg_img_size_tbl[][2]=
- {
- 176,144, //QCIF
- 160,120, //QQVGA
- 352,288, //CIF
- 320,240, //QVGA
- 640,480, //VGA
- 800,600, //SVGA
- 1024,768, //XGA
- 1280,1024, //SXGA
- 1600,1200, //UXGA
- };
- void TIM3_Int_Init(u16 arr,u16 psc);
- u16 getcolor2(u16 tx,u16 ty) //从LCD读点,转化为灰度值
- {
- u16 i,tempcolor,R,G,B,avr;
- tempcolor=LCD_ReadPoint(tx,ty);
- R = (int) ((tempcolor>>11) * 255.0 / 31.0 + 0.5);
- G = (int) ((tempcolor>>5&0x3f) * 255.0 / 63.0 + 0.5);
- B = (int) ((tempcolor&0x1f) * 255.0 / 31.0 + 0.5);
- avr=(R * 19595 + G * 38469 + B * 7472) >> 16;
- return avr;
- }
- void search(void)
- {
- unsigned char tx,ty,avr[162][134];
- ax=0;
- ay=0;
- for(tx=8;tx<162;tx+=3){
- for(ty=10;ty<134;ty+=3){
- if(getcolor2(tx,ty)==255) //当前点为白色
- {
- if(getcolor2(tx-1,ty-1)==255 &&getcolor2(tx+1,ty+1)==255 &&getcolor2(tx-1,ty+1)==255 && getcolor2(tx+1,ty-1)==255 ){
- ax=tx/176.0*58;
- ay=ty/144.0*48;
- }
- }
- }
- }
- // if(ax==0&&ay==0){
- // ax=29;
- // ay=25;
- // }
- }
- //t最佳阈值,w0背景比例,u0背景均值,w1前景比例,u1前景均值,u整幅图像的均值
- u16 GetThreshValue(void)
- {
- int pixelNum[256];//图像直方图 共256点
- u16 i,j,color;
- int n, n1, n2;
- int total;//total为总和
- double m1, m2, sum, csum, fmax, sb;//sb类间房差,fmax存储最大方差值
- int k, t, q;
- int threshValue =1;// 阈值
- for(i=0; i<144; i+=3){
- for(j=0; j<176; j+=3){
- color=getcolor2(i,j);//返回各个点的颜色
- pixelNum[color]++;//相应直方图+1
- }
- }
- //直方图平滑化
- for(k=0; k<=255; k++){
- total =0;
- for(t =-2; t <=2; t++){//附近两个灰度做平滑化
- q = k + t;
- if(q <0)//越界处理
- q =0;
- if(q >255)
- q =255;
- total = total + pixelNum[q];//total为总和,累计值
- }
- //平滑化,左边两个+中间1个+右边两个
- pixelNum[k]=(int)((float)total /5.0+0.5);
- }
- //求阈值
- sum = csum =0.0;
- n =0;
- //求总的图像的点数和质量矩
- for(k =0; k <=255; k++){
- //x*f(x)每个灰度的值*其点数(归一化后为概率)
- sum +=(double)k *(double)pixelNum[k];
- n += pixelNum[k];//n总点数,归一化后为累积概率
- }
- fmax =-1.0;//sb不可能为负
- n1 =0;
- for(k =0; k <255; k++){//计算一次分割后的sb
- n1 += pixelNum[k];//n1为在当前阈值遍前景图像的总数
- if(n1 ==0){continue;}//没有分出前后景
- n2 = n - n1;//n2为背景图像的点数
- //n2=0为全后景图
- if(n2 ==0){break;}
- csum +=(double)k * pixelNum[k];//前景的灰度值*点数 的总和
- m1 = csum / n1;//m1前景的平均灰度
- m2 =(sum - csum)/ n2;//m2背景的平均灰度
- sb =(double)n1 *(double)n2 *(m1 - m2)*(m1 - m2);//sb类间方差
- if(sb > fmax){//此次类方差>前一次类方差
- fmax = sb;//取最大值
- threshValue = k;//返回阈值
- }
- }
- return threshValue;
- }
- void senddata(void)
- {
- USART_SendData(USART2,(ax&0x3f));
- while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);
- USART_SendData(USART2,(ay|0xc0));
- while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);
- }
- int main(void)
- {
- u16 i,j;
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
- delay_init(168); //初始化延时函数
- uart_init(115200); //初始化串口波特率为115200
- usart2_init(42,9600); //初始化串口2波特率为115200
- //LED_Init(); //初始化LED
- LCD_Init(); //LCD初始化
- //KEY_Init(); //按键初始化
- TIM3_Int_Init(10000-1,8400-1);//10Khz计数,1秒钟中断一次
-
- //TIM14_PWM_Init(10000-1,168-1); //重装载值10000,所以PWM频率为 150hz. //舵机预留
- //TIM11_PWM_Init(10000-1,336-1); //重装载值10000,所以PWM频率为 150hz.
-
- //usmart_dev.init(84); //初始化USMART
- OV2640_Init();
- OV2640_OutSize_Set(176,144);
-
- // OV2640_Light_Mode(0); //白平衡设置 自动
- // OV2640_Auto_Exposure(0); //自动曝光
- // OV2640_Color_Saturation(2); //色度设置
- // OV2640_Brightness(0); //亮度设置
- OV2640_Contrast(4); //对比度设置
- // OV2640_Special_Effects(2); //黑白化
- OV2640_RGB565_Mode(); //RGB565模式
- My_DCMI_Init(); //DCMI配置
- DCMI_DMA_Init((u32)rgb_buf,sizeof(rgb_buf)/4,DMA_MemoryDataSize_HalfWord,DMA_MemoryInc_Enable);//DCMI DMA配置
- DCMI_Start(); //启动传输
- while(1)
- {
- LCD_SetCursor(0,0);
- LCD_WriteRAM_Prepare(); //开始写入GRAM
- for(i=0;i<150;i++){
- for(j=0;j<176;j++){
- if(j==175){
- LCD_SetCursor(0,i+1);
- LCD_WriteRAM_Prepare(); //开始写入GRAM
- }
- gray=((rgb_buf[i][j]>>11)*19595+((rgb_buf[i][j]>>5)&0x3f)*38469 +(rgb_buf[i][j]&0x1f)*7472)>>16;
- //gray=((rgb_buf[i][j]>>5)&0x3f)* 255.0 / 63.0 + 0.5;
- if(gray >23){
- // if(i>8&&i<136&&j<160&&j>16){
- // if(i>X_MAX) X_MAX=i;
- // if(i<X_MIN) X_MIN=i;
- // if(j>Y_MAX) Y_MAX=j;
- // if(j<Y_MIN) Y_MIN=j;
- // }
- LCD->LCD_RAM=WHITE;
- }
- else{
- LCD->LCD_RAM=BLACK;
- }
- }
- }
- // X_MAX_LSAT = X_MAX; //更新pid的real坐标信息 清除掉本次坐标用于再次遍历最大值 最小值
- // X_MIN_LSAT = X_MIN;
- // Y_MAX_LSAT = Y_MAX;
- // Y_MIN_LSAT = Y_MIN;
- //
- // X_MAX=0;
- // X_MIN=180;
- // Y_MAX=0;
- // Y_MIN=180;
- //
- // X=(X_MAX_LSAT+X_MIN_LSAT)/2;
- // Y=(Y_MAX_LSAT+Y_MIN_LSAT)/2;
-
- // TIM_SetCompare1(TIM14,9340); //修改比较值,修改占空比
- // TIM_SetCompare1(TIM11,9300); //修改比较值,修改占空比
- search();
- LCD_ShowxNum(30,210,ax,3,16,0);
- LCD_ShowxNum(30,230,ay,3,16,0);
- if(Have==1){
- senddata();
- if( ((ax==29||ax==28||ax==30)&&(ay==7||ay==8||ay==9)) || ((ax==11||ax==12||ax==13)&&(ay==7||ay==8||ay==9)) || ((ax==30||ax==31||ax==29)&&(ay==26||ay==27)) )
- SY=1;
- else{
- SY=0;
- }
- }
- else{
- time1=0;
- }
- LCD_ShowxNum(80,210,time,3,16,0);//显示当前时间
- LCD_ShowxNum(80,230,time1,3,16,0);//区域2停留的时间
- }
- }
- void TIM3_IRQHandler(void)
- {
- if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
- {
- if(Have==1){
- time++;
- if(time>60)
- time=0;
- }
- if(SY==1){
- time1++;
- }
- if(SY==0)
- time1=0;
- Kp=3.4;
- Kd=80.9;
- Aim_X=72;
- Aim_Y=88;
-
- Err_X=X-Aim_X;
- Err_Y=Y-Aim_Y;
-
- PWM_X=9340+(Err_X*Kp+(Err_X-Err_X_LAST)*Kd);
- PWM_Y=9300+(Err_Y*Kp+(Err_Y-Err_Y_LAST)*Kd);
-
- if(PWM_Y>9370)PWM_Y=9370;
- if(PWM_Y<9230)PWM_Y=9230;
-
- if(PWM_X>9410)PWM_X=9410;
- if(PWM_X<9270)PWM_X=9270;
-
- Err_X_LAST=Err_X;
- Err_Y_LAST=Err_Y;
-
- TIM_SetCompare1(TIM14,PWM_X); //修改比较值,修改占空比
- TIM_SetCompare1(TIM11,PWM_Y); //修改比较值,修改占空比
- }
- TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
- }
复制代码
所有资料51hei提供下载:
实验板球系统.7z
(375.89 KB, 下载次数: 56)
|