2020-12-26

   日期:2020-12-27     浏览:93    评论:0    
核心提示:为参加今年的工训大赛,本人自学32和openmv,虽不深不才但学有所获,虽结果不尽人意,但能思其所以,再之csdn教会了我很多,也想发表一下自己的芝麻设计,希望能给读者带来一些思考和灵感,水平有限希望理解,备注:侵立删!以下是openmv的巡线和识别一体化程序设计:# 基于openmv与stm32串口通信的巡线+识别 - By:水下管道机器人智能控制设计者付智辉#1 - 周四 12月 17 2020import sensor, image, time, mathfrom pyb import

为参加今年的工训大赛,本人自学32和openmv,虽不深不才但学有所获,虽结果不尽人意,但能思其所以,再之csdn教会了我很多,也想发表一下自己的芝麻设计,希望能给读者带来一些思考和灵感,水平有限希望理解,备注:侵立删!
以下是openmv的巡线和识别一体化程序设计:

# 基于openmv与stm32串口通信的巡线+识别 - By:水下管道机器人智能控制设计者付智辉
#1 - 周四 12月 17 2020


import sensor, image, time, math
from pyb import UART
sensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_framesize(sensor.QQVGA)
#       _____________________________________________________________________________
#规定串行通信组合为
#turn_right=bytearray([0xb2,0xb3,0xb1,0x0d,0x0a])
#turn_left=bytearray([0xb2,0xb3,0xb2,0x0d,0x0a])
#find_red=bytearray([0xb2,0xb3,0xb3,0x0d,0x0a])
#find_green=bytearray([0xb2,0xb3,0xb4,0x0d,0x0a])
#find_black=bytearray([0xb2,0xb3,0xb5,0x0d,0x0a])
#find_blue=bytearray([0xb2,0xb3,0xb6,0x0d,0x0a])
#find_circle=bytearray([0xb2,0xb3,0xb7,0x0d,0x0a])
#find_rectangle=bytearray([0xb2,0xb3,0xb8,0x0d,0x0a])
#
#_____________________________________________________________________________

uart = UART(3,115200)
uart.init(115200,bits=8,parity=None,stop=1)

turn_right=bytearray([0xb2,0xb3,0xb1,0x0d,0x0a])
turn_left=bytearray([0xb2,0xb3,0xb2,0x0d,0x0a])
find_red=bytearray([0xb2,0xb3,0xb3,0x0d,0x0a])
find_green=bytearray([0xb2,0xb3,0xb4,0x0d,0x0a])
find_black=bytearray([0xb2,0xb3,0xb5,0x0d,0x0a])
find_blue=bytearray([0xb2,0xb3,0xb6,0x0d,0x0a])
find_circle=bytearray([0xb2,0xb3,0xb7,0x0d,0x0a])
find_rectangle=bytearray([0xb2,0xb3,0xb8,0x0d,0x0a])

white_threshold_01 = ((95, 100, -18, 3, -8, 4));  #白色阈值
black_threshold_01 = ((0, 15, -24, -1, -18, 6));  #黑色阈值
red_threshold_01 = ((35, 100, 41, 77, 24, 59));#红色阈值
green_threshold_01 = ((50, 100, -80, -20, 8, 20));#绿色阈值
blue_threshold_01 = ((20, 100, -18, 18, -80, -30));#蓝色阈值


#设置是否使用img.binary()函数进行图像分割


BINARY_VISIBLE = True 
#           _________________________________________________________________________________

def find_max(blobs):    #定义寻找色块面积最大的函数
    max_size=0
    for blob in blobs:
        if blob.pixels() > max_size:
            max_blob=blob
            max_size = blob.pixels()
    return max_blob
sensor.skip_frames(time = 2000)
clock = time.clock()
while(True):
    THRESHOLD = (190, 255)
    sensor.set_auto_whitebal(False)#关闭白平衡
    clock.tick()
    img = sensor.snapshot().binary([THRESHOLD]) if BINARY_VISIBLE else sensor.snapshot()
    img.draw_rectangle(130, 85, 30, 35, color = (0, 0, 0), thickness = 2, fill = True)
    line = img.get_regression([(255,255) if BINARY_VISIBLE else THRESHOLD])
    if (line):
        img.draw_line(line.line(), color = 127)
        theta = int(line.theta())
        x = int ( (line.x1()+line.x2())/2)
        print("find line")
        if line.magnitude() >= 1:
            print(theta,x) #x的中值大概是60
            if theta>100:
               print("turn_right!")
               uart.write(turn_right)
            elif theta<80:
               print("turn_left!")
               uart.write(turn_left)
            else:
               print("go straight!")
               sensor.reset()
               sensor.set_pixformat(sensor.RGB565)
               sensor.set_framesize(sensor.QQVGA)
               sensor.skip_frames(time = 2000)
               sensor.set_auto_gain(False)
               clock = time.clock()
               clock.tick() # Track elapsed milliseconds between snapshots().
               img = sensor.snapshot() # Take a picture and return the image.
               #  pixels_threshold=100, area_threshold=100
               blobs = img.find_blobs([red_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10);
               blobs1 = img.find_blobs([green_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10);
               blobs2 = img.find_blobs([blue_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10);
               blobs3 = img.find_blobs([black_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10);
               cx=0;cy=0;cx1=0;cy1=0;cx2=0;cy2=0;
               if blobs:
                   #如果找到了red
                   max_b = find_max(blobs);
                   # Draw a rect around the blob.
                   img.draw_rectangle(max_b[0:4]) # rect
                   #用矩形标记出目标颜色区域
                   img.draw_cross(max_b[5], max_b[6]) # cx, cy
                   img.draw_cross(160, 120) # 在中心点画标记
                   #在目标颜色区域的中心画十字形标记
                   cx=max_b[5];
                   cy=max_b[6];
                   img.draw_line((160,120,cx,cy), color=(127));
                   #img.draw_string(160,120, "(%d, %d)"%(160,120), color=(127));
                   img.draw_string(cx, cy, "(%d, %d)"%(cx,cy), color=(127));
                   print("找到红色!")
                   uart.write(find_red)
                   sensor.reset() #初始化设置
                   sensor.set_pixformat(sensor.RGB565)
                   sensor.set_framesize(sensor.QQVGA)#设置为彩色设置清晰度sensor.set_framesize(sensor.SVGA)
                   sensor.skip_frames(time = 2000) #跳过前2000ms的图像
                   sensor.set_auto_gain(False) # must be turned off for color tracking
                   sensor.set_auto_whitebal(False) # must be turned off for color tracking
                   clock = time.clock() #创建一个clock便于计算FPS,看看到底卡不卡
                   sensor.set_auto_gain(False) # 关闭自动自动增益。默认开启的。
                   sensor.set_auto_whitebal(False) #关闭白平衡。在颜色识别中,一定要关闭白平衡。
                   clock.tick()
                   img = sensor.snapshot().lens_corr(1.8) #拍摄一张照片,lens_corr函数用于非鱼眼畸变矫正,默认设置参数为1.8,
                   for blob in img.find_blobs([black_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10):
                       #openmv自带的寻找色块函数。img.find_blobs([red_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10);
                       #pixels_threshold是像素阈值,面积小于这个值的色块就忽略blobs4 = img.find_blobs([thresholds], pixels_threshold=100, area_threshold=100, merge=True, margin=10);

                       #roi是感兴趣区域,只在这个区域内寻找色块   if blobs4:
                       #are_threshold是面积阈值,如果色块被框起来的面积小于这个值,会被过滤掉
                           print('该形状占空比为',blob.density())
                            #density函数可以自动返回色块面积/外接矩形面积这个值
                           if blob.density()>0.805:#理论上矩形和他的外接矩形应该是完全重合
                           #但是测试时候发现总会有偏差,多次试验取的这个值。下面圆形和三角形亦然
                               print("检测为长方形  ",end='')
                               uart.write(find_rectangle)

                           elif blob.density()>0.65:
                               print("检测为圆  ",end='')
                               uart.write(find_circle)

                           else: 
                               print("no dectedtion")
                               elif blobs2:
                       #如果找到了blue
                       max_b = find_max(blobs2);
                       # Draw a rect around the blob.
                       img.draw_rectangle(max_b[0:4]) 
                       img.draw_cross(max_b[5], max_b[6]) 
                       img.draw_cross(160, 120) 
                       cx2=max_b[5];
                       cy2=max_b[6];
                       img.draw_line((160,120,cx2,cy2), color=(127));
                       #img.draw_string(160,120, "(%d, %d)"%(160,120), color=(127));
                       img.draw_string(cx2, cy2, "(%d, %d)"%(cx2,cy2), color=(127));
                       print("找到蓝色!")
                       uart.write(find_blue)
                       sensor.reset() 
                       sensor.set_pixformat(sensor.RGB565)
                       sensor.set_framesize(sensor.QQVGA)
                       sensor.skip_frames(time = 2000) 
                       sensor.set_auto_gain(False)
                       sensor.set_auto_whitebal(False) 
                       clock = time.clock() 
                       sensor.set_auto_gain(False) 
                       sensor.set_auto_whitebal(False) 
                       clock.tick()
                       img = sensor.snapshot().lens_corr(1.8) 
                       for blob in img.find_blobs([black_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10):

                               print('该形状占空比为',blob.density())

                               if blob.density()>0.805:

                                   print("检测为长方形  ",end='')
                                   uart.write(find_rectangle)

                               elif blob.density()>0.65:
                                   print("检测为圆  ",end='')
                                   uart.write(find_circle)

                                   print('圆形半径',(blob.w()+blob.h())/4)
                               else: 
                                   print("no dectedtion")
                                   elif blobs3:
                               #如果找到了black
                               max_b = find_max(blobs3);
                               # Draw a rect around the blob.
                               img.draw_rectangle(max_b[0:4]) 
                               img.draw_cross(max_b[5], max_b[6]) 
                               img.draw_cross(160, 120)
                               
                               cx2=max_b[5];
                               cy2=max_b[6];
                               img.draw_line((160,120,cx2,cy2), color=(127));
                               #img.draw_string(160,120, "(%d, %d)"%(160,120), color=(127));
                               img.draw_string(cx2, cy2, "(%d, %d)"%(cx2,cy2), color=(127));
                               print("找到黑色!")

                               sensor.reset() 
                               sensor.set_pixformat(sensor.RGB565)
                               sensor.set_framesize(sensor.QQVGA)
                               sensor.skip_frames(time = 2000) 
                               sensor.set_auto_gain(False)
                               sensor.set_auto_whitebal(False) 
                               clock = time.clock() 
                               sensor.set_auto_gain(False) 
                               sensor.set_auto_whitebal(False) 
                               clock.tick()
                               img = sensor.snapshot().lens_corr(1.8) 
                               for blob in img.find_blobs([black_threshold_01], pixels_threshold=100, area_threshold=100, merge=True, margin=10):

                                       print('该形状占空比为',blob.density())

                                       if blob.density()>0.805:

                                           print("检测为长方形  ",end='')
                                           uart.write(find_rectangle)

                                       elif blob.density()>0.65:
                                           print("检测为圆  ",end='')
                                           uart.write(find_circle)

                                       else:
                                           print("no dectedtion")
               else:
                               print("没找到!")


               print(clock.fps())
               sensor.reset() #初始化设置
               sensor.set_pixformat(sensor.GRAYSCALE)
               sensor.set_framesize(sensor.QQVGA)
               sensor.set_auto_whitebal(False)#关闭白平衡
               sensor.set_auto_gain(True)

    else:
        print("not line!")

以下是stm32串口通信服务程序:

#include "sys.h"
#include "usart.h"	  
#include "led.h"
#include "delay.h"


#include "stdio.h"
#include "motor.h"
// 	 
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//ucos 使用	  
#endif
 
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
_sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0x40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 

 
 
#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	  
u8 t;
	u8 len;	
	u16 times=0; 
 u8 date[4];
void uart_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
  
	//USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX	  GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式

  USART_Init(USART1, &USART_InitStructure); //初始化串口1
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1 

}

void USART1_IRQHandler(void)                	//串口1中断服务程序
	{
	u8 Res;
#if SYSTEM_SUPPORT_OS 	
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		{
		Res =USART_ReceiveData(USART1);	//读取接收到的数据
		if((USART_RX_STA&0x8000)==0)//接收未完成
			{
			if(USART_RX_STA&0x4000)//接收到了0x0d
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
				}
			else //还没收到0x0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
					USART_RX_BUF[USART_RX_STA&0x3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		
			
     if(USART_RX_STA&0x8000)
		{					   
			MOTOR_FORWARD_OFF();
			len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度
			
			for(t=0;t<len;t++)
			{
				date[t]=USART_RX_BUF[t];
				
			}

			if(date[2]==0xb1)//需右转//
			{	
				MOTOR_FORWARD_OFF();
			MOTOR_RIGHT_ON();
delay_ms(50000);
MOTOR_RIGHT_OFF();
		}
			else if(date[2]==0xb2)//需左转//
				{	
					MOTOR_FORWARD_OFF();
		MOTOR_LEFT_ON();
delay_ms(50000);
MOTOR_LEFT_OFF();
		}
				
		  else if(date[2]==0xb3)//找到红色//
				{	
		LEDR1_ON;
					delay_ms(50000);
	 LEDR1_OFF;	
		}
				
				else if(date[2]==0xb6)//找到蓝色//
				{	
		LEDB1_ON;
					delay_ms(50000);
	 LEDB1_OFF;	
		}
				else if(date[2]==0xb7)//找到圆//
				{	
		LEDR2_ON;
					delay_ms(50000);
	 LEDR2_OFF;	
		}
				else if(date[2]==0xb8)//找到方//
				{	
		LEDG2_ON;
					delay_ms(50000);
	 LEDG2_OFF;	
		}
		USART_RX_STA=0;//消除中断标志位
}
		
		
	} 
		
		
	
#if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
	OSIntExit();  											 
#endif
} 
#endif

关于船体转弯是通过触碰开关引发单片机外部中端,进入中断程序,引起左右电机转动转弯,时间可调,如何归位管道,通过openmv的直线识别,如以上程序,船体上升下浅可通过针筒排水进水改变船体重量实现。


最后感谢符同学和王同学的辛苦付出,为青春干杯,走好正确的路,自己的世界才是真正光明的,才能真正谈自己有世界。20.12.26

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服